Skip to content

Commit

Permalink
Re-add tests unintentionally deleted in facebook#9209
Browse files Browse the repository at this point in the history
These tests are useful and don't test addons specifically.
I moved them to appropriate places in the codebase.
  • Loading branch information
gaearon committed Mar 20, 2017
1 parent 34e4352 commit 68c8529
Show file tree
Hide file tree
Showing 4 changed files with 470 additions and 0 deletions.
13 changes: 13 additions & 0 deletions scripts/fiber/tests-passing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,8 @@ src/renderers/__tests__/ReactComponent-test.js
* fires the callback after a component is rendered
* throws usefully when rendering badly-typed elements
* includes owner name in the error about badly-typed elements
* throws if a plain object is used as a child
* throws if a plain object even if it is in an owner

src/renderers/__tests__/ReactComponentLifeCycle-test.js
* should not reuse an instance when it has been unmounted
Expand Down Expand Up @@ -526,6 +528,8 @@ src/renderers/__tests__/ReactCompositeComponent-test.js
* should warn when mutated props are passed
* should only call componentWillUnmount once
* prepares new child before unmounting old
* respects a shallow shouldComponentUpdate implementation
* does not do a deep comparison for a shallow shouldComponentUpdate implementation

src/renderers/__tests__/ReactCompositeComponentDOMMinimalism-test.js
* should not render extra nodes for non-interpolated text
Expand Down Expand Up @@ -1151,6 +1155,15 @@ src/renderers/dom/shared/__tests__/quoteAttributeValueForBrowser-test.js
* should escape number to string
* should escape string

src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js
* should pass context when rendering subtree elsewhere
* should throw if parentComponent is invalid
* should update context if it changes due to setState
* should update context if it changes due to re-render
* should render portal with non-context-provider parent
* should get context through non-context-provider parent
* should get context through middle non-context-provider layer

src/renderers/dom/shared/__tests__/validateDOMNesting-test.js
* allows any tag with no context
* allows valid nestings
Expand Down
34 changes: 34 additions & 0 deletions src/renderers/__tests__/ReactComponent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,4 +380,38 @@ describe('ReactComponent', () => {
// One warning for each element creation
expectDev(console.error.calls.count()).toBe(1);
});

it('throws if a plain object is used as a child', () => {
var children = {
x: <span />,
y: <span />,
z: <span />,
};
var element = <div>{[children]}</div>;
var container = document.createElement('div');
expect(() => ReactDOM.render(element, container)).toThrowError(
'Objects are not valid as a React child (found: object with keys ' +
'{x, y, z}). If you meant to render a collection of children, use an ' +
'array instead.',
);
});

it('throws if a plain object even if it is in an owner', () => {
class Foo extends React.Component {
render() {
var children = {
a: <span />,
b: <span />,
c: <span />,
};
return <div>{[children]}</div>;
}
}
var container = document.createElement('div');
expect(() => ReactDOM.render(<Foo />, container)).toThrowError(
'Objects are not valid as a React child (found: object with keys ' +
'{a, b, c}). If you meant to render a collection of children, use an ' +
'array instead.\n\nCheck the render method of `Foo`.',
);
});
});
123 changes: 123 additions & 0 deletions src/renderers/__tests__/ReactCompositeComponent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ var ReactDOMServer;
var ReactCurrentOwner;
var ReactPropTypes;
var ReactTestUtils;
var shallowEqual;
var shallowCompare;

describe('ReactCompositeComponent', () => {
beforeEach(() => {
Expand All @@ -31,6 +33,12 @@ describe('ReactCompositeComponent', () => {
ReactCurrentOwner = require('react/lib/ReactCurrentOwner');
ReactPropTypes = require('ReactPropTypes');
ReactTestUtils = require('ReactTestUtils');
shallowEqual = require('fbjs/lib/shallowEqual');

shallowCompare = function(instance, nextProps, nextState) {
return !shallowEqual(instance.props, nextProps) ||
!shallowEqual(instance.state, nextState);
};

MorphingComponent = class extends React.Component {
state = {activated: false};
Expand Down Expand Up @@ -1396,4 +1404,119 @@ describe('ReactCompositeComponent', () => {
'B componentDidMount',
]);
});

it('respects a shallow shouldComponentUpdate implementation', () => {
var renderCalls = 0;
class PlasticWrap extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
color: 'green',
};
}

render() {
return <Apple color={this.state.color} ref="apple" />;
}
}

class Apple extends React.Component {
state = {
cut: false,
slices: 1,
};

shouldComponentUpdate(nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}

cut() {
this.setState({
cut: true,
slices: 10,
});
}

eatSlice() {
this.setState({
slices: this.state.slices - 1,
});
}

render() {
renderCalls++;
return <div />;
}
}

var container = document.createElement('div');
var instance = ReactDOM.render(<PlasticWrap />, container);
expect(renderCalls).toBe(1);

// Do not re-render based on props
instance.setState({color: 'green'});
expect(renderCalls).toBe(1);

// Re-render based on props
instance.setState({color: 'red'});
expect(renderCalls).toBe(2);

// Re-render base on state
instance.refs.apple.cut();
expect(renderCalls).toBe(3);

// No re-render based on state
instance.refs.apple.cut();
expect(renderCalls).toBe(3);

// Re-render based on state again
instance.refs.apple.eatSlice();
expect(renderCalls).toBe(4);
});

it('does not do a deep comparison for a shallow shouldComponentUpdate implementation', () => {
function getInitialState() {
return {
foo: [1, 2, 3],
bar: {a: 4, b: 5, c: 6},
};
}

var renderCalls = 0;
var initialSettings = getInitialState();

class Component extends React.Component {
state = initialSettings;

shouldComponentUpdate(nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}

render() {
renderCalls++;
return <div />;
}
}

var container = document.createElement('div');
var instance = ReactDOM.render(<Component />, container);
expect(renderCalls).toBe(1);

// Do not re-render if state is equal
var settings = {
foo: initialSettings.foo,
bar: initialSettings.bar,
};
instance.setState(settings);
expect(renderCalls).toBe(1);

// Re-render because one field changed
initialSettings.foo = [1, 2, 3];
instance.setState(initialSettings);
expect(renderCalls).toBe(2);

// Re-render because the object changed
instance.setState(getInitialState());
expect(renderCalls).toBe(3);
});
});
Loading

0 comments on commit 68c8529

Please sign in to comment.