123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- // import PureComponent from "src/PureComponent";
- import ReactTestUtils from "../../lib/ReactTestUtils";
- import React from '../../src/May';
- import { render, unmountComponentAtNode } from '../../src/may-dom/MayDom';
- var ReactDOM = {
- render: render,
- unmountComponentAtNode: unmountComponentAtNode
- }
- React.render = render;
- // import React from "../../dist/ReactANU";
- // var ReactDOM=React;
- // var React = require('react');//hyphenate
- // var ReactDOM = require('react-dom');
- describe("组件相关", function() {
- // this.timeout(200000);
- // before(async () => {
- // await beforeHook();
- // });
- // after(async () => {
- // await afterHook(false);
- // });
- var body = document.body,
- div;
- beforeEach(function() {
- div = document.createElement("div");
- body.appendChild(div);
- });
- afterEach(function() {
- body.removeChild(div);
- });
- it("stateless", function() {
- function HelloComponent(
- props
- //context
- ) {
- return <div onClick={() => (props.name = 11)}>Hello {props.name}</div>;
- }
- var vnode = <HelloComponent name="Sebastian" />
- React.render(vnode, div);
- expect(vnode.mayInfo.instance.mayInst.hostNode.innerHTML).toBe("Hello Sebastian");
- });
-
- it("shouldComponentUpdate什么也不返回", function() {
- var a = 1;
- class App extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- aaa: 1
- };
- }
- shouldComponentUpdate() {
- //这里相当于返回false
- }
- click() {
- this.setState(
- function(a) {
- a.aaa++;
- },
- function() {
- a++;
- }
- );
- this.setState(
- function(a) {
- a.aaa++;
- },
- function() {
- a++;
- }
- );
- }
- render() {
- return <div onClick={this.click.bind(this)}>{this.state.aaa}</div>;
- }
- }
- var vnode = <App />
- ReactDOM.render(vnode, div);
- expect(vnode.mayInfo.instance.mayInst.hostNode.innerHTML).toBe("1");
- // ReactTestUtils.Simulate.click(vnode._hostNode)
- // expect(vnode.mayInfo.instance.mayInst.hostNode.innerHTML).toBe("1");
- // expect(a).toBe(3);
- });
- it("shouldComponentUpdate返回false", function() {
- var a = 1;
- class App extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- aaa: 1
- };
- }
- shouldComponentUpdate() {
- return false;
- }
- click() {
- this.setState(
- function(a) {
- a.aaa++;
- },
- function() {
- a++;
- }
- );
- this.setState(
- function(a) {
- a.aaa++;
- },
- function() {
- a++;
- }
- );
- }
- render() {
- return <div onClick={this.click.bind(this)}>{this.state.aaa}</div>;
- }
- }
- var vnode = <App />
- ReactDOM.render(vnode, div);
- expect(vnode.mayInfo.instance.mayInst.hostNode.innerHTML).toBe("1");
- // ReactTestUtils.Simulate.click(vnode.mayInfo.hostNode)
- // expect(vnode.mayInfo.instance.mayInst.hostNode.innerHTML).toBe("1");
- // expect(a).toBe(3);
- });
- it("PureComponent", function() {
- var a = 1;
- class App extends React.PureComponent {
- constructor(props) {
- super(props);
- this.state = {
- aaa: {
- a: 7
- }
- };
- }
- click() {
- this.setState(function(state) {
- state.aaa.a = 8;
- });
- }
- render() {
- return <div onClick={this.click.bind(this)}>{this.state.aaa.a}</div>;
- }
- }
- var vnode = <App />
- ReactDOM.render(vnode, div);
- expect(vnode.mayInfo.instance.mayInst.hostNode.innerHTML).toBe("7");
- // ReactTestUtils.Simulate.click(vnode._hostNode)
- // expect(vnode._hostNode.innerHTML).toBe("7");
- });
- it("PureComponent2", function() {
- class App extends React.PureComponent {
- constructor(props) {
- super(props);
- this.state = {
- aaa: {
- a: 7
- }
- };
- }
- click() {
- var aaa = this.state.aaa;
- aaa.a = 9;
- this.setState({
- aaa: aaa,
- ccc: 222
- });
- }
- render() {
- return <div onClick={this.click.bind(this)}>{this.state.aaa.a}</div>;
- }
- }
- var vnode = <App />
- ReactDOM.render(vnode, div);
- expect(vnode.mayInfo.instance.mayInst.hostNode.innerHTML).toBe("7");
- // ReactTestUtils.Simulate.click(vnode._hostNode)
- // expect(vnode._hostNode.innerHTML).toBe("9");
- });
- it("子组件是无状态组件",() => {// async
- function Select(props) {
- return <strong>{props.value}</strong>;
- }
- class App extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- value: "南京"
- };
- }
- onChange(e) {
- this.setState({
- value: e.target.value
- });
- }
- render() {
- return (
- <div>
- <Select value={this.state.value} />
- <input ref="a" value={this.state.value} onInput={this.onChange.bind(this)} />
- </div>
- );
- }
- }
- var s = React.render(<App />, div);
- expect(s.refs.a.value).toBe("南京");//await
- // browser
- // .setValue(s.refs.a, "南京22")
- // .pause(200)
- // .$apply();
- expect(s.refs.a.value).toBe("南京");
- expect(div.getElementsByTagName("strong")[0].innerHTML).toBe("南京");
- });
- it("多选下拉框",() => {// async
- class App extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- value: ["aaa", "ccc"]
- };
- }
- onChange(e) {
- var values = [];
- var elems = e.target.getElementsByTagName("option");
- for (var i = 0, el; (el = elems[i++]); ) {
- if (el.selected) {
- if (el.getAttribute("value") != null) {
- values.push(el.getAttribute("value"));
- } else {
- values.push(el.text);
- }
- }
- }
- this.setState({
- values: values
- });
- }
- render() {
- return (
- <select value={this.state.value} multiple="true" onChange={this.onChange.bind(this)}>
- <optgroup>
- <option ref="a">aaa</option>
- <option ref="b">bbb</option>
- </optgroup>
- <optgroup>
- <option ref="c">ccc</option>
- <option ref="d">ddd</option>
- </optgroup>
- </select>
- );
- }
- }
- // var s = React.render(<App />, div);
- // // await browser.pause(100).$apply();
- // expect(s.refs.a.selected).toBe(true);
- // expect(s.refs.b.selected).toBe(false);
- // expect(s.refs.c.selected).toBe(true);
- // expect(s.refs.d.selected).toBe(false);
- // s.setState({
- // value: ["bbb", "ddd"]
- // });
- // // await browser.pause(100).$apply();
- // expect(s.refs.a.selected).toBe(false);
- // expect(s.refs.b.selected).toBe(true);
- // expect(s.refs.c.selected).toBe(false);
- // expect(s.refs.d.selected).toBe(true);
- });
- /*it("多选下拉框defaultValue", function() {
- class App extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- value: "ccc"
- };
- }
- render() {
- return (
- <select defaultValue={this.state.value}>
- <option ref="a">aaa</option>
- <option ref="b">bbb</option>
- <option ref="c">ccc</option>
- <option ref="d">ddd</option>
- </select>
- );
- }
- }
- var s = React.render(<App />, div);
-
- expect(s.refs.c.selected).toBe(true);
- });
- it("多选下拉框没有defaultValue与ReactDOM.render的回调this指向问题", function() {
- class App extends React.Component {
- constructor(props) {
- super(props);
- this.state = {};
- }
- render() {
- return (
- <select>
- <option ref="a">aaa</option>
- <option ref="b">bbb</option>
- <option ref="c">ccc</option>
- <option ref="d">ddd</option>
- </select>
- );
- }
- }
- var s = React.render(<App />, div, function() {
- expect(this.constructor.name).toBe("App");
- });
- expect(s.refs.a.selected).toBe(true);
- });
- it("一个组件由元素节点变注释节点再回元素节点,不触发componentWillUnmount", function() {
- class App extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- path: "111"
- };
- }
- change(path) {
- this.setState({
- path: path || "333"
- });
- }
- render() {
- return (
- <div>
- <span>xx</span>
- <Route path={this.state.path} />
- </div>
- );
- }
- }
- var updateCount = 0;
- var receiveCount = 0;
- var destroyCount = 0;
- class Route extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- path: props.path
- };
- }
- componentWillReceiveProps(props) {
- receiveCount++;
- console.log("receiveCount", receiveCount);
- this.setState(function(nextState, props) {
- nextState.path = props.path;
- return nextState;
- });
- }
- componentWillUpdate() {
- updateCount++;
- console.log("updateCount", updateCount);
- }
- componentWillUnmount() {
- destroyCount++;
- console.log("destroyCount", destroyCount);
- }
- render() {
- return this.state.path == "111" ? <p>{this.state.path}</p> : null;
- }
- }
- var s = React.render(<App />, div);
-
- expect(updateCount).toBe(0);
- expect(receiveCount).toBe(0);
- s.change("111");
-
- expect(updateCount).toBe(1);
- expect(receiveCount).toBe(1);
- s.change("111x");
-
- expect(updateCount).toBe(2);
- expect(receiveCount).toBe(2);
- expect(div.firstChild.childNodes[1].nodeType).toBe(8);
- expect(destroyCount).toBe(0);
- s.change("111");
-
- expect(updateCount).toBe(3);
- expect(receiveCount).toBe(3);
- expect(div.firstChild.childNodes[1].nodeType).toBe(1);
- expect(destroyCount).toBe(0);
- });
- it("select的准确匹配", function() {
- var dom = ReactDOM.render(
- <select value={222}>
- <option value={111}>aaa</option>
- <option value={"222"}>xxx</option>
- <option value={222}>bbb</option>
- <option value={333}>ccc</option>
- </select>,
- div
- );
- expect(dom.options[2].selected).toBe(true);
- });
- it("确保ref执行在componentDidMount之前", function() {
- var str = "";
- class Test extends React.Component {
- componentDidMount() {
- expect(typeof this.refs.wrapper).toBe("object");
- str += "111";
- }
- render() {
- return (
- <div ref="wrapper" id="aaa">
- xxx<B />
- </div>
- );
- }
- }
- class B extends React.Component {
- componentDidMount() {
- expect(typeof this.refs.wrapper2).toBe("object");
- str += "222";
- }
- render() {
- return <p ref="wrapper2">son</p>;
- }
- }
- var s = React.render(<Test />, div);
-
- expect(str).toBe("222111");
- expect(React.findDOMNode(s.refs.wrapper)).toBe(div.querySelector("#aaa"));
- });
- it("确保componentDidUpdate的第一个参数是prevProps", function() {
- class HasChild extends React.Component {
- constructor(props) {
- super(props);
- this.state = {};
- this.onClick = this.onClick.bind(this);
- this.a = 0;
- }
- onClick() {
- this.a = 1;
- this.forceUpdate();
- }
- render() {
- return (
- <div onClick={this.onClick} ref="componentDidUpdate">
- {this.a == 0 ? <A title="xxx" ref="a" /> : <A ddd="ddd" ref="a" />}
- </div>
- );
- }
- }
- var title = 0;
- class A extends React.Component {
- constructor(props) {
- super(props);
- this.state = {};
- }
- componentDidUpdate(a) {
- title = 1;
- }
- render() {
- return <span>{this.props.title}</span>;
- }
- }
- A.defaultProps = {
- title: "默认值"
- };
- var s = React.render(<HasChild />, div);
-
- expect(s.refs.a.props.title).toBe("xxx");
- eactTestUtils.Simulate.click(s.refs.componentDidUpdate)
-
- expect(s.refs.a.props.title).toBe("默认值");
- expect(s.refs.a.props.ddd).toBe("ddd");
- expect(title).toBe(1);
- });
- it("defaultProps的处理", function() {
- class HasChild extends React.Component {
- constructor(props) {
- super(props);
- this.state = {};
- this.onClick = this.onClick.bind(this);
- this.a = 0;
- }
- onClick() {
- this.a = 1;
- this.forceUpdate();
- }
- render() {
- return (
- <div onClick={this.onClick} ref="componentDidUpdate2">
- {this.a == 0 ? <A title="xxx" ref="a" /> : <A ddd="ddd" ref="a" />}
- </div>
- );
- }
- }
- function A(props) {
- return <span>{props.title}</span>;
- }
- A.defaultProps = {
- title: "默认值"
- };
- var s = React.render(<HasChild />, div);
-
- var span = div.getElementsByTagName("span")[0];
- expect(span.innerHTML).toBe("xxx");
- eactTestUtils.Simulate.click(s.refs.componentDidUpdate2)
-
- expect(span.innerHTML).toBe("默认值");
- });
- it("新旧两种无状态组件的ref传参", function(){
- var list = []
- function Old (props){
- return <span>{props.aaa}</span>
- }
- ReactDOM.render(<Old ref={(a)=>{ list.push(!!a)}} aaa={111} />, div);
- ReactDOM.render(<Old ref={(a)=>{ list.push(!!a)}} aaa={222} />, div);
- expect(list).toEqual([false, false, false])
- var list2 = []
- function New (props){
- return {
- componentWillMount(){
- list2.push("mount")
- },
- componentWillUpdate(){
- list2.push("update")
- },
- render(){
- return <span>{props.aaa}</span>
- }
- }
- }
- ReactDOM.render(<New ref={(a)=>{ list2.push(!!a)}} aaa={111} />, div);
- ReactDOM.render(<New ref={(a)=>{ list2.push(!!a)}} aaa={222} />, div);
- expect(list2).toEqual(["mount", true, false, "update",true])
- })
- it("componentWillUnmount钩子中调用ReactDOM.findDOMNode 应该还能找到元素", () => {
- var assertions = 0;
- class Inner extends React.Component {
- render() {
- return <span />;
- }
- componentDidMount() {
- expect(!!ReactDOM.findDOMNode(this)).toBe(true);
- assertions++;
- }
- componentWillUnmount() {
- expect(!!ReactDOM.findDOMNode(this)).toBe(true);
- assertions++;
- }
- }
- class Wrapper extends React.Component {
- render() {
- return this.props.showInner ? <Inner /> : null;
- }
- }
- var el = document.createElement("div");
- var component;
- component = React.render(<Wrapper showInner={true} />, el);
- expect(!!ReactDOM.findDOMNode(component)).toBe(true);
- component = React.render(<Wrapper showInner={false} />, el);
- expect(ReactDOM.findDOMNode(component).tagName).toBe(undefined);
- component = React.render(<Wrapper showInner={true} />, el);
- expect(!!ReactDOM.findDOMNode(component)).toBe(true);
- expect(assertions).toBe(3);
- });
- it("虚拟DOM的_owner必须在render中加上", function() {
- class B extends React.Component {
- render() {
- return <div className="xxx">{this.props.children}</div>;
- }
- }
- var b, c;
- class App extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- value: "南京"
- };
- }
- _renderPopup(a) {
- return (
- <B>
- <p {...a} />
- </B>
- );
- }
- onChange(e) {
- this.setState({
- value: e.target.value
- });
- }
- render() {
- return (
- <div>
- {this._renderPopup({ ref: "xxxx", children: [(b = <span>333</span>)] })}
- {this._renderPopup({ ref: "yyyy", children: [(c = <strong>444</strong>)] })}
- </div>
- );
- }
- }
- var s = React.render(<App />, div);
-
- expect(b._owner.constructor).toBe(App);
- expect(c._owner.constructor).toBe(App);
- });*/
- });
|