// 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
(props.name = 11)}>Hello {props.name}
; } var vnode = 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
{this.state.aaa}
; } } var vnode = 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
{this.state.aaa}
; } } var vnode = 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
{this.state.aaa.a}
; } } var vnode = 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
{this.state.aaa.a}
; } } var vnode = 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 {props.value}; } class App extends React.Component { constructor(props) { super(props); this.state = { value: "南京" }; } onChange(e) { this.setState({ value: e.target.value }); } render() { return (
); } } var s = React.render(, 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 ( ); } } // var s = React.render(, 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 ( ); } } var s = React.render(, 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 ( ); } } var s = React.render(, 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 (
xx
); } } 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" ?

{this.state.path}

: null; } } var s = React.render(, 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( , 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 (
xxx
); } } class B extends React.Component { componentDidMount() { expect(typeof this.refs.wrapper2).toBe("object"); str += "222"; } render() { return

son

; } } var s = React.render(, 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 (
{this.a == 0 ? : }
); } } var title = 0; class A extends React.Component { constructor(props) { super(props); this.state = {}; } componentDidUpdate(a) { title = 1; } render() { return {this.props.title}; } } A.defaultProps = { title: "默认值" }; var s = React.render(, 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 ( ); } } function A(props) { return {props.title}; } A.defaultProps = { title: "默认值" }; var s = React.render(, 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 {props.aaa} } ReactDOM.render({ list.push(!!a)}} aaa={111} />, div); ReactDOM.render({ 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 {props.aaa} } } } ReactDOM.render({ list2.push(!!a)}} aaa={111} />, div); ReactDOM.render({ 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 ; } 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 ? : null; } } var el = document.createElement("div"); var component; component = React.render(, el); expect(!!ReactDOM.findDOMNode(component)).toBe(true); component = React.render(, el); expect(ReactDOM.findDOMNode(component).tagName).toBe(undefined); component = React.render(, el); expect(!!ReactDOM.findDOMNode(component)).toBe(true); expect(assertions).toBe(3); }); it("虚拟DOM的_owner必须在render中加上", function() { class B extends React.Component { render() { return
{this.props.children}
; } } var b, c; class App extends React.Component { constructor(props) { super(props); this.state = { value: "南京" }; } _renderPopup(a) { return (

); } onChange(e) { this.setState({ value: e.target.value }); } render() { return (

{this._renderPopup({ ref: "xxxx", children: [(b = 333)] })} {this._renderPopup({ ref: "yyyy", children: [(c = 444)] })}
); } } var s = React.render(, div); expect(b._owner.constructor).toBe(App); expect(c._owner.constructor).toBe(App); });*/ });