UNPKG

luy

Version:

所谓类```React```框架就是**和React用法一模一样**的框架。其实当初制造这个框架的目的是为了能更好的学习React内部结构,了解其原理而制作的玩具。但是随着框架的渐渐成长,代码越来越多,我还是决定将其发展下去. ![](https://github.com/215566435/Luy/blob/master/luy%20icon2.jpg?raw=true)

367 lines (286 loc) 10.1 kB
import React from "../app/src/Luy"; import getTestDocument from "./getTestDocument"; import ReactTestUtils from "../lib/ReactTestUtils"; import ReactShallowRenderer from "../lib/ReactShallowRenderer"; //https://github.com/facebook/react/blob/master/src/isomorphic/children/__tests__/ReactChildren-test.js var ReactDOM = window.ReactDOM || React; describe("ReactComponent", function () { //context穿透更新 it("should pass context when re-rendered for static child", () => { var parentInstance = null; var childInstance = null; class Parent extends React.Component { state = { flag: false }; getChildContext() { return { foo: "bar", flag: this.state.flag }; } render() { return React.Children.only(this.props.children); } } class Middle extends React.Component { render() { return this.props.children; } } class Child extends React.Component { render() { childInstance = this; return <span>Child</span>; } } parentInstance = ReactTestUtils.renderIntoDocument( <Parent> <Middle> <Child /> </Middle> </Parent> ); expect(parentInstance.state.flag).toBe(false); expect(childInstance.context).toEqual({ foo: "bar", flag: false }); parentInstance.setState({ flag: true }); expect(parentInstance.state.flag).toBe(true); expect(childInstance.context).toEqual({ foo: "bar", flag: true }); }); //context穿透更新 it("should pass context when re-rendered for static child within a composite component", () => { class Parent extends React.Component { state = { flag: true }; getChildContext() { return { flag: this.state.flag }; } render() { return <div>{this.props.children}</div>; } } class Child extends React.Component { render() { return <div />; } } class Wrapper extends React.Component { render() { return ( <Parent ref="parent"> <Child ref="child" /> </Parent> ); } } var wrapper = ReactTestUtils.renderIntoDocument(<Wrapper />); expect(wrapper.refs.parent.state.flag).toEqual(true); expect(wrapper.refs.child.context).toEqual({ flag: true }); // We update <Parent /> while <Child /> is still a static prop relative to this update wrapper.refs.parent.setState({ flag: false }); expect(wrapper.refs.parent.state.flag).toEqual(false); expect(wrapper.refs.child.context).toEqual({ flag: false }); }); it("should pass context transitively", () => { var childInstance = null; var grandchildInstance = null; class Parent extends React.Component { getChildContext() { return { foo: "bar", depth: 0 }; } render() { return <Child />; } } class Child extends React.Component { getChildContext() { return { depth: this.context.depth + 1 }; } render() { childInstance = this; return <Grandchild />; } } class Grandchild extends React.Component { render() { grandchildInstance = this; return <div />; } } ReactTestUtils.renderIntoDocument(<Parent />); expect(childInstance.context).toEqual({ foo: "bar", depth: 0 }); expect(grandchildInstance.context).toEqual({ foo: "bar", depth: 1 }); }); it("should pass context when re-rendered", () => { var parentInstance = null; var childInstance = null; class Parent extends React.Component { state = { flag: false }; getChildContext() { return { foo: "bar", depth: 0 }; } render() { var output = <Child />; if (!this.state.flag) { output = <span>Child</span>; } return output; } } class Child extends React.Component { render() { childInstance = this; return <span>Child</span>; } } parentInstance = ReactTestUtils.renderIntoDocument(<Parent />); expect(childInstance).toBeNull(); expect(parentInstance.state.flag).toBe(false); /* ReactDOM.unstable_batchedUpdates(function() { parentInstance.setState({flag: true}); }); expect(parentInstance.state.flag).toBe(true); expect(childInstance.context).toEqual({foo: 'bar', depth: 0}); */ }); it("unmasked context propagates through updates", () => { class Leaf extends React.Component { componentWillReceiveProps(nextProps, nextContext) { expect("foo" in nextContext).toBe(true); } shouldComponentUpdate(nextProps, nextState, nextContext) { expect("foo" in nextContext).toBe(true); return true; } render() { return <span>{this.context.foo}</span>; } } class Intermediary extends React.Component { componentWillReceiveProps(nextProps, nextContext) { console.log("unmasked context propagates through updates",nextContext) expect("foo" in nextContext).toBe(false); } shouldComponentUpdate(nextProps, nextState, nextContext) { expect("foo" in nextContext).toBe(false); return true; } render() { return <Leaf />; } } class Parent extends React.Component { getChildContext() { return { foo: this.props.cntxt }; } render() { return <Intermediary />; } } var div = document.createElement("div"); ReactDOM.render(<Parent cntxt="1noise" />, div); expect(div.children[0].innerHTML).toBe("1noise"); div.children[0].innerHTML = "aliens"; div.children[0].id = "aliens"; expect(div.children[0].innerHTML).toBe("aliens"); expect(div.children[0].id).toBe("aliens"); ReactDOM.render(<Parent cntxt="bar" />, div); expect(div.children[0].innerHTML).toBe("bar"); expect(div.children[0].id).toBe("aliens"); }); it("should trigger componentWillReceiveProps for context changes", () => { var contextChanges = 0; var propChanges = 0; class GrandChild extends React.Component { componentWillReceiveProps(nextProps, nextContext) { expect("foo" in nextContext).toBe(true); if (nextProps !== this.props) { propChanges++; } if (nextContext !== this.context) { contextChanges++; } } render() { return <span className="grand-child">{this.props.children}</span>; } } class ChildWithContext extends React.Component { componentWillReceiveProps(nextProps, nextContext) { expect("foo" in nextContext).toBe(true); if (nextProps !== this.props) { propChanges++; } if (nextContext !== this.context) { contextChanges++; } } render() { return <div className="child-with">{this.props.children}</div>; } } class ChildWithoutContext extends React.Component { componentWillReceiveProps(nextProps, nextContext) { expect("foo" in nextContext).toBe(false); if (nextProps !== this.props) { propChanges++; } if (nextContext !== this.context) { contextChanges++; } } render() { return <div className="child-without">{this.props.children}</div>; } } class Parent extends React.Component { state = { foo: "abc" }; getChildContext() { return { foo: this.state.foo }; } render() { return <div className="parent">{this.props.children}</div>; } } var div = document.createElement("div"); var parentInstance = null; ReactDOM.render( <Parent ref={inst => (parentInstance = inst)}> <ChildWithoutContext> A1 <GrandChild>A2</GrandChild> </ChildWithoutContext> <ChildWithContext> B1 <GrandChild>B2</GrandChild> </ChildWithContext> </Parent>, div ); parentInstance.setState({ foo: "def" }); expect(propChanges).toBe(0); expect(contextChanges).toBe(3); // ChildWithContext, GrandChild x 2 }); })