import PropTypes from '../../lib/ReactPropTypes';
import ReactTestUtils from "../../lib/ReactTestUtils";
import React from '../../src/May';
import { render, unmountComponentAtNode, findDOMNode } from '../../src/may-dom/MayDom'
var ReactDOM = {
render: render,
unmountComponentAtNode: unmountComponentAtNode,
findDOMNode: findDOMNode
}
React.render = render;
// import React from "../../dist/ReactANU";
// var ReactDOM = React;
// https://github.com/facebook/react/blob/master/src/renderers/__tests__/EventPluginHub-test.js
describe("ReactCompositeComponentDOMMinimalism", function() {
// this.timeout(200000);
var TestComponent = class extends React.Component {
constructor(props) {
super(props);
this.peekAtState("getInitialState", undefined, props);
this.state = { color: "red" };
}
peekAtState = (from, state = this.state, props = this.props) => {
props.stateListener(from, state && state.color);
};
peekAtCallback = from => {
return () => this.peekAtState(from);
};
setFavoriteColor(nextColor) {
this.setState({ color: nextColor }, this.peekAtCallback("setFavoriteColor"));
}
render() {
this.peekAtState("render");
return
{this.state.color}
;
}
componentWillMount() {
this.peekAtState("componentWillMount-start");
this.setState(function(state) {
this.peekAtState("before-setState-sunrise", state);
});
this.setState({ color: "sunrise" }, this.peekAtCallback("setState-sunrise"));
this.setState(function(state) {
this.peekAtState("after-setState-sunrise", state);
});
this.peekAtState("componentWillMount-after-sunrise");
this.setState({ color: "orange" }, this.peekAtCallback("setState-orange"));
this.setState(function(state) {
this.peekAtState("after-setState-orange", state);
});
this.peekAtState("componentWillMount-end");
}
componentDidMount() {
this.peekAtState("componentDidMount-start");
this.setState({ color: "yellow" }, this.peekAtCallback("setState-yellow"));
this.peekAtState("componentDidMount-end");
}
componentWillReceiveProps(newProps) {
this.peekAtState("componentWillReceiveProps-start");
if (newProps.nextColor) {
this.setState(function(state) {
this.peekAtState("before-setState-receiveProps", state);
return { color: newProps.nextColor };
});
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
this.setState({ color: undefined });
this.setState(function(state) {
this.peekAtState("before-setState-again-receiveProps", state);
return { color: newProps.nextColor };
}, this.peekAtCallback("setState-receiveProps"));
this.setState(function(state) {
this.peekAtState("after-setState-receiveProps", state);
});
}
this.peekAtState("componentWillReceiveProps-end");
}
shouldComponentUpdate(nextProps, nextState) {
this.peekAtState("shouldComponentUpdate-currentState");
this.peekAtState("shouldComponentUpdate-nextState", nextState);
return true;
}
componentWillUpdate(nextProps, nextState) {
this.peekAtState("componentWillUpdate-currentState");
this.peekAtState("componentWillUpdate-nextState", nextState);
}
componentDidUpdate(prevProps, prevState) {
this.peekAtState("componentDidUpdate-currentState");
this.peekAtState("componentDidUpdate-prevState", prevState);
}
componentWillUnmount() {
this.peekAtState("componentWillUnmount");
}
};
/*it("should support setting state", () => {
var container = document.createElement("div");
document.body.appendChild(container);
var stateListener = spyOn.createSpy();
var instance = ReactDOM.render(, container, function peekAtInitialCallback() {
this.peekAtState("initial-callback");
});
ReactDOM.render(, container, instance.peekAtCallback("setProps"));
instance.setFavoriteColor("blue");
instance.forceUpdate(instance.peekAtCallback("forceUpdate"));
ReactDOM.unmountComponentAtNode(container);
let expected = [
// there is no state when getInitialState() is called
["getInitialState", null],
["componentWillMount-start", "red"],
// setState()'s only enqueue pending states.
["componentWillMount-after-sunrise", "red"],
["componentWillMount-end", "red"],
// pending state queue is processed
["before-setState-sunrise", "red"],
["after-setState-sunrise", "sunrise"],
["after-setState-orange", "orange"],
// pending state has been applied
["render", "orange"],
["componentDidMount-start", "orange"],
// setState-sunrise and setState-orange should be called here,
// after the bug in #1740
// componentDidMount() called setState({color:'yellow'}), which is async.
// The update doesn't happen until the next flush.
["componentDidMount-end", "orange"],
["shouldComponentUpdate-currentState", "orange"],
["shouldComponentUpdate-nextState", "yellow"],
["componentWillUpdate-currentState", "orange"],
["componentWillUpdate-nextState", "yellow"],
["render", "yellow"],
["componentDidUpdate-currentState", "yellow"],
["componentDidUpdate-prevState", "orange"],
["setState-sunrise", "yellow"],
["setState-orange", "yellow"],
["setState-yellow", "yellow"],
["initial-callback", "yellow"],
["componentWillReceiveProps-start", "yellow"],
// setState({color:'green'}) only enqueues a pending state.
["componentWillReceiveProps-end", "yellow"],
// pending state queue is processed
// We keep updates in the queue to support
// replaceState(prevState => newState).
["before-setState-receiveProps", "yellow"],
["before-setState-again-receiveProps", void 666],
["after-setState-receiveProps", "green"],
["shouldComponentUpdate-currentState", "yellow"],
["shouldComponentUpdate-nextState", "green"],
["componentWillUpdate-currentState", "yellow"],
["componentWillUpdate-nextState", "green"],
// setFavoriteColor('blue')
["render", "green"],
["componentDidUpdate-currentState", "green"],
["componentDidUpdate-prevState", "yellow"],
["setState-receiveProps", "green"],
["setProps", "green"],
// setFavoriteColor('blue')
["shouldComponentUpdate-currentState", "green"],
["shouldComponentUpdate-nextState", "blue"],
["componentWillUpdate-currentState", "green"],
["componentWillUpdate-nextState", "blue"],
["render", "blue"],
["componentDidUpdate-currentState", "blue"],
["componentDidUpdate-prevState", "green"],
["setFavoriteColor", "blue"],
// forceUpdate()
["componentWillUpdate-currentState", "blue"],
["componentWillUpdate-nextState", "blue"],
["render", "blue"],
["componentDidUpdate-currentState", "blue"],
["componentDidUpdate-prevState", "blue"],
["forceUpdate", "blue"],
// unmountComponent()
// state is available within `componentWillUnmount()`
["componentWillUnmount", "blue"]
];
expect(stateListener.calls.join("\n")).toEqual(expected.join("\n"));
});*/
it("should call componentDidUpdate of children first", () => {});
it("should batch unmounts", () => {
var outer;
class Inner extends React.Component {
render() {
return ;
}
componentWillUnmount() {
// This should get silently ignored (maybe with a warning), but it
// shouldn't break React.
outer.setState({ showInner: false });
}
}
class Outer extends React.Component {
state = { showInner: true };
render() {
return {this.state.showInner && }
;
}
}
var container = document.createElement("div");
outer = ReactDOM.render(, container);
expect(() => {
ReactDOM.unmountComponentAtNode(container);
}).not.toThrow();
});
it("should update state when called from child cWRP", function() {
const log = [];
class Parent extends React.Component {
state = { value: "one" };
render() {
log.push("parent render " + this.state.value);
return ;
}
}
let updated = false;
class Child extends React.Component {
componentWillReceiveProps() {
if (updated) {
return;
}
log.push("child componentWillReceiveProps " + this.props.value);
this.props.parent.setState({ value: "two" });
log.push("child componentWillReceiveProps done " + this.props.value);
updated = true;
}
render() {
log.push("child render " + this.props.value);
return {this.props.value}
;
}
}
var container = document.createElement("div");
ReactDOM.render(, container);
ReactDOM.render(, container);
expect(log).toEqual([
"parent render one",
"child render one",
"parent render one",
"child componentWillReceiveProps one",
"child componentWillReceiveProps done one",
"child render one",
"parent render two",
"child render two"
]);
});
it("should merge state when sCU returns false", function() {
const log = [];
class Test extends React.Component {
state = { a: 0 };
render() {
return null;
}
shouldComponentUpdate(nextProps, nextState) {
log.push("scu from " + Object.keys(this.state) + " to " + Object.keys(nextState));
return false;
}
}
const container = document.createElement("div");
const test = ReactDOM.render(, container);
test.setState({ b: 0 });
expect(log.length).toBe(1);
test.setState({ c: 0 });
expect(log.length).toBe(2);
expect(log).toEqual(["scu from a to a,b", "scu from a,b to a,b,c"]);
});
it("should treat assigning to this.state inside cWRP as a replaceState, with a warning", () => {
spyOn(console, "error");
let ops = [];
class Test extends React.Component {
state = { step: 1, extra: true };
componentWillReceiveProps() {
this.setState({ step: 2 }, () => {
// Tests that earlier setState callbacks are not dropped
ops.push(`callback -- step: ${this.state.step}, extra: ${!!this.state.extra}`);
});
// Treat like replaceState
this.state = { step: 3 };
}
render() {
ops.push(`render -- step: ${this.state.step}, extra: ${!!this.state.extra}`);
return null;
}
}
// Mount
const container = document.createElement("div");
ReactDOM.render(, container);
// Update
ReactDOM.render(, container);
expect(ops).toEqual(["render -- step: 1, extra: true", "render -- step: 2, extra: false", "callback -- step: 2, extra: false"]);
/*
expect(console.error.calls.count()).toEqual(1);
expect(console.error.calls.argsFor(0)[0]).toEqual(
'Warning: Test.componentWillReceiveProps(): Assigning directly to ' +
"this.state is deprecated (except inside a component's constructor). " +
'Use setState instead.',
);/**/
});
});