Update tests to use plain JavaScript classes

Tests that rely on replaceState or isMounted use
updater.enqueueReplaceState and updater.isMounted instead.
This commit is contained in:
Andrew Clark 2017-03-21 18:38:15 -07:00
parent 087fe88f20
commit c76a4eaa2a
24 changed files with 663 additions and 940 deletions

View File

@ -13,10 +13,10 @@
var React = require('React');
var Child = React.createClass({
render: function() {
class Child extends React.Component {
render() {
return React.createElement('div');
},
});
}
}
module.exports = Child;

View File

@ -13,23 +13,18 @@
var React = require('React');
var ReactMockedComponentTestComponent = React.createClass({
getDefaultProps: function() {
return {bar: 'baz'};
},
class ReactMockedComponentTestComponent extends React.Component {
state = {foo: 'bar'};
getInitialState: function() {
return {foo: 'bar'};
},
hasCustomMethod: function() {
hasCustomMethod() {
return true;
},
}
render: function() {
render() {
return <span />;
},
}
});
}
ReactMockedComponentTestComponent.defaultProps = {bar: 'baz'};
module.exports = ReactMockedComponentTestComponent;

View File

@ -89,64 +89,10 @@ src/isomorphic/classic/__tests__/ReactContextValidator-test.js
* should warn (but not error) if getChildContext method is missing
* should pass parent context if getChildContext method is missing
src/isomorphic/classic/class/__tests__/ReactBind-test.js
* Holds reference to instance
* works with mixins
* warns if you try to bind to this
* does not warn if you pass an auto-bound method to setState
src/isomorphic/classic/class/__tests__/ReactBindOptout-test.js
* should work with manual binding
* should not hold reference to instance
* works with mixins that have not opted out of autobinding
* works with mixins that have opted out of autobinding
* does not warn if you try to bind to this
* does not warn if you pass an manually bound method to setState
src/isomorphic/classic/class/__tests__/ReactClass-test.js
* should throw when `render` is not specified
* should copy `displayName` onto the Constructor
* should copy prop types onto the Constructor
* should warn on invalid prop types
* should warn on invalid context types
* should throw on invalid child context types
* should warn when mispelling shouldComponentUpdate
* should warn when mispelling componentWillReceiveProps
* should throw if a reserved property is in statics
* should support statics
* should work with object getInitialState() return values
* renders based on context getInitialState
* should throw with non-object getInitialState() return values
* should work with a null getInitialState() return value
* should throw when using legacy factories
src/isomorphic/classic/class/__tests__/ReactClassMixin-test.js
* should support merging propTypes and statics
* should support chaining delegate functions
* should chain functions regardless of spec property order
* should validate prop types via mixins
* should override mixin prop types with class prop types
* should support mixins with getInitialState()
* should throw with conflicting getInitialState() methods
* should not mutate objects returned by getInitialState()
* should support statics in mixins
* should throw if mixins override each others' statics
* should throw if mixins override functions in statics
* should warn if the mixin is undefined
* should warn if the mixin is null
* should warn if an undefined mixin is included in another mixin
* should warn if a null mixin is included in another mixin
* should throw if the mixin is a React component
* should throw if the mixin is a React component class
* should have bound the mixin methods to the component
* should include the mixin keys in even if their values are falsy
* should work with a null getInitialState return value and a mixin
src/isomorphic/classic/element/__tests__/ReactElement-test.js
* uses the fallback value when in an environment without Symbol
* returns a complete element according to spec
* should warn when `key` is being accessed on createClass element
* should warn when `key` is being accessed on ES class element
* should warn when `key` is being accessed on composite element
* should warn when `key` is being accessed on a host element
* should warn when `ref` is being accessed
* allows a string to be passed as the type
@ -165,7 +111,6 @@ src/isomorphic/classic/element/__tests__/ReactElement-test.js
* merges rest arguments onto the children prop in an array
* allows static methods to be called using the type property
* identifies valid elements
* allows the use of PropTypes validators in statics
* is indistinguishable from a plain object
* should use default prop value when removing a prop
* should normalize props with default values
@ -495,8 +440,6 @@ src/renderers/__tests__/ReactCompositeComponent-test.js
* should react to state changes from callbacks
* should rewire refs when rendering to different child types
* should not cache old DOM nodes when switching constructors
* should auto bind methods and values correctly
* should not pass this to getDefaultProps
* should use default values for undefined props
* should not mutate passed-in props object
* should warn about `forceUpdate` on unmounted components
@ -718,7 +661,6 @@ src/renderers/__tests__/ReactUpdates-test.js
* does not call render after a component as been deleted
* marks top-level updates
* throws in setState if the update callback is not a function
* throws in replaceState if the update callback is not a function
* throws in forceUpdate if the update callback is not a function
* does not update one component twice in a batch (#2410)
* does not update one component twice in a batch (#6371)
@ -1299,7 +1241,6 @@ src/renderers/dom/shared/__tests__/ReactServerRendering-test.js
* allows setState in componentWillMount without using DOM
* renders components with different batching strategies
* warns with a no-op when an async setState is triggered
* warns with a no-op when an async replaceState is triggered
* warns with a no-op when an async forceUpdate is triggered
* should warn when children are mutated during render

View File

@ -38,33 +38,31 @@ describe('ReactContextValidator', () => {
// ensure that this is not required for ES6 classes with Flow.
it('should filter out context not in contextTypes', () => {
var Component = React.createClass({
contextTypes: {
foo: React.PropTypes.string,
},
render: function() {
class Component extends React.Component {
render() {
return <div />;
},
});
}
}
Component.contextTypes = {
foo: React.PropTypes.string,
};
var ComponentInFooBarContext = React.createClass({
childContextTypes: {
foo: React.PropTypes.string,
bar: React.PropTypes.number,
},
getChildContext: function() {
class ComponentInFooBarContext extends React.Component {
getChildContext() {
return {
foo: 'abc',
bar: 123,
};
},
}
render: function() {
render() {
return <Component ref="child" />;
},
});
}
}
ComponentInFooBarContext.childContextTypes = {
foo: React.PropTypes.string,
bar: React.PropTypes.number,
};
var instance = ReactTestUtils.renderIntoDocument(
<ComponentInFooBarContext />,
@ -77,47 +75,45 @@ describe('ReactContextValidator', () => {
var actualShouldComponentUpdate;
var actualComponentWillUpdate;
var Parent = React.createClass({
childContextTypes: {
foo: React.PropTypes.string.isRequired,
bar: React.PropTypes.string.isRequired,
},
getChildContext: function() {
class Parent extends React.Component {
getChildContext() {
return {
foo: this.props.foo,
bar: 'bar',
};
},
}
render: function() {
render() {
return <Component />;
},
});
}
}
Parent.childContextTypes = {
foo: React.PropTypes.string.isRequired,
bar: React.PropTypes.string.isRequired,
};
var Component = React.createClass({
contextTypes: {
foo: React.PropTypes.string,
},
componentWillReceiveProps: function(nextProps, nextContext) {
class Component extends React.Component {
componentWillReceiveProps(nextProps, nextContext) {
actualComponentWillReceiveProps = nextContext;
return true;
},
}
shouldComponentUpdate: function(nextProps, nextState, nextContext) {
shouldComponentUpdate(nextProps, nextState, nextContext) {
actualShouldComponentUpdate = nextContext;
return true;
},
}
componentWillUpdate: function(nextProps, nextState, nextContext) {
componentWillUpdate(nextProps, nextState, nextContext) {
actualComponentWillUpdate = nextContext;
},
}
render: function() {
render() {
return <div />;
},
});
}
}
Component.contextTypes = {
foo: React.PropTypes.string,
};
var container = document.createElement('div');
ReactDOM.render(<Parent foo="abc" />, container);
@ -130,37 +126,36 @@ describe('ReactContextValidator', () => {
it('should pass previous context to lifecycles', () => {
var actualComponentDidUpdate;
var Parent = React.createClass({
childContextTypes: {
foo: React.PropTypes.string.isRequired,
bar: React.PropTypes.string.isRequired,
},
getChildContext: function() {
class Parent extends React.Component {
getChildContext() {
return {
foo: this.props.foo,
bar: 'bar',
};
},
}
render: function() {
render() {
return <Component />;
},
});
}
}
Parent.childContextTypes = {
foo: React.PropTypes.string.isRequired,
bar: React.PropTypes.string.isRequired,
};
var Component = React.createClass({
contextTypes: {
foo: React.PropTypes.string,
},
componentDidUpdate: function(prevProps, prevState, prevContext) {
class Component extends React.Component {
componentDidUpdate(prevProps, prevState, prevContext) {
actualComponentDidUpdate = prevContext;
},
}
render: function() {
render() {
return <div />;
},
});
}
}
Component.contextTypes = {
foo: React.PropTypes.string,
};
var container = document.createElement('div');
ReactDOM.render(<Parent foo="abc" />, container);
@ -171,15 +166,14 @@ describe('ReactContextValidator', () => {
it('should check context types', () => {
spyOn(console, 'error');
var Component = React.createClass({
contextTypes: {
foo: React.PropTypes.string.isRequired,
},
render: function() {
class Component extends React.Component {
render() {
return <div />;
},
});
}
}
Component.contextTypes = {
foo: React.PropTypes.string.isRequired,
};
ReactTestUtils.renderIntoDocument(<Component />);
@ -191,21 +185,20 @@ describe('ReactContextValidator', () => {
' in Component (at **)',
);
var ComponentInFooStringContext = React.createClass({
childContextTypes: {
foo: React.PropTypes.string,
},
getChildContext: function() {
class ComponentInFooStringContext extends React.Component {
getChildContext() {
return {
foo: this.props.fooValue,
};
},
}
render: function() {
render() {
return <Component />;
},
});
}
}
ComponentInFooStringContext.childContextTypes = {
foo: React.PropTypes.string,
};
ReactTestUtils.renderIntoDocument(
<ComponentInFooStringContext fooValue={'bar'} />,
@ -214,21 +207,20 @@ describe('ReactContextValidator', () => {
// Previous call should not error
expectDev(console.error.calls.count()).toBe(1);
var ComponentInFooNumberContext = React.createClass({
childContextTypes: {
foo: React.PropTypes.number,
},
getChildContext: function() {
class ComponentInFooNumberContext extends React.Component {
getChildContext() {
return {
foo: this.props.fooValue,
};
},
}
render: function() {
render() {
return <Component />;
},
});
}
}
ComponentInFooNumberContext.childContextTypes = {
foo: React.PropTypes.number,
};
ReactTestUtils.renderIntoDocument(
<ComponentInFooNumberContext fooValue={123} />,
@ -247,20 +239,19 @@ describe('ReactContextValidator', () => {
it('should check child context types', () => {
spyOn(console, 'error');
var Component = React.createClass({
childContextTypes: {
foo: React.PropTypes.string.isRequired,
bar: React.PropTypes.number,
},
getChildContext: function() {
class Component extends React.Component {
getChildContext() {
return this.props.testContext;
},
}
render: function() {
render() {
return <div />;
},
});
}
}
Component.childContextTypes = {
foo: React.PropTypes.string.isRequired,
bar: React.PropTypes.number,
};
ReactTestUtils.renderIntoDocument(<Component testContext={{bar: 123}} />);
expectDev(console.error.calls.count()).toBe(1);
@ -362,16 +353,16 @@ describe('ReactContextValidator', () => {
}
var childContext;
var ChildContextConsumer = React.createClass({
contextTypes: {
bar: React.PropTypes.string.isRequired,
foo: React.PropTypes.string.isRequired,
},
render: function() {
class ChildContextConsumer extends React.Component {
render() {
childContext = this.context;
return <div />;
},
});
}
}
ChildContextConsumer.contextTypes = {
bar: React.PropTypes.string.isRequired,
foo: React.PropTypes.string.isRequired,
};
ReactTestUtils.renderIntoDocument(<ParentContextProvider />);
expect(childContext.bar).toBeUndefined();

View File

@ -34,11 +34,11 @@ describe('ReactElement', () => {
ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
// NOTE: We're explicitly not using JSX here. This is intended to test
// classic JS without JSX.
ComponentClass = React.createClass({
render: function() {
ComponentClass = class extends React.Component {
render() {
return React.createElement('div');
},
});
}
};
});
afterEach(() => {
@ -59,37 +59,7 @@ describe('ReactElement', () => {
expect(element.props).toEqual({});
});
it('should warn when `key` is being accessed on createClass element', () => {
spyOn(console, 'error');
var container = document.createElement('div');
var Child = React.createClass({
render: function() {
return <div> {this.props.key} </div>;
},
});
var Parent = React.createClass({
render: function() {
return (
<div>
<Child key="0" />
<Child key="1" />
<Child key="2" />
</div>
);
},
});
expectDev(console.error.calls.count()).toBe(0);
ReactDOM.render(<Parent />, container);
expectDev(console.error.calls.count()).toBe(1);
expectDev(console.error.calls.argsFor(0)[0]).toContain(
'Child: `key` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)',
);
});
it('should warn when `key` is being accessed on ES class element', () => {
it('should warn when `key` is being accessed on composite element', () => {
spyOn(console, 'error');
var container = document.createElement('div');
class Child extends React.Component {
@ -97,8 +67,8 @@ describe('ReactElement', () => {
return <div> {this.props.key} </div>;
}
}
var Parent = React.createClass({
render: function() {
class Parent extends React.Component {
render() {
return (
<div>
<Child key="0" />
@ -106,9 +76,9 @@ describe('ReactElement', () => {
<Child key="2" />
</div>
);
},
});
expectDev(console.error.calls.count()).toBe(0);
}
}
expect(console.error.calls.count()).toBe(0);
ReactDOM.render(<Parent />, container);
expectDev(console.error.calls.count()).toBe(1);
expectDev(console.error.calls.argsFor(0)[0]).toContain(
@ -136,21 +106,21 @@ describe('ReactElement', () => {
it('should warn when `ref` is being accessed', () => {
spyOn(console, 'error');
var container = document.createElement('div');
var Child = React.createClass({
render: function() {
class Child extends React.Component {
render() {
return <div> {this.props.ref} </div>;
},
});
var Parent = React.createClass({
render: function() {
}
}
class Parent extends React.Component {
render() {
return (
<div>
<Child ref="childElement" />
</div>
);
},
});
expectDev(console.error.calls.count()).toBe(0);
}
}
expect(console.error.calls.count()).toBe(0);
ReactDOM.render(<Parent />, container);
expectDev(console.error.calls.count()).toBe(1);
expectDev(console.error.calls.argsFor(0)[0]).toContain(
@ -257,12 +227,12 @@ describe('ReactElement', () => {
var Component = React.createFactory(ComponentClass);
var element;
var Wrapper = React.createClass({
render: function() {
class Wrapper extends React.Component {
render() {
element = Component();
return element;
},
});
}
}
var instance = ReactTestUtils.renderIntoDocument(
React.createElement(Wrapper),
@ -324,19 +294,12 @@ describe('ReactElement', () => {
it('allows static methods to be called using the type property', () => {
spyOn(console, 'error');
var StaticMethodComponentClass = React.createClass({
statics: {
someStaticMethod: function() {
return 'someReturnValue';
},
},
getInitialState: function() {
return {valueToReturn: 'hi'};
},
render: function() {
class StaticMethodComponentClass extends React.Component {
render() {
return React.createElement('div');
},
});
}
}
StaticMethodComponentClass.someStaticMethod = () => 'someReturnValue';
var element = React.createElement(StaticMethodComponentClass);
expect(element.type.someStaticMethod()).toBe('someReturnValue');
@ -346,11 +309,11 @@ describe('ReactElement', () => {
// NOTE: We're explicitly not using JSX here. This is intended to test
// classic JS without JSX.
it('identifies valid elements', () => {
var Component = React.createClass({
render: function() {
class Component extends React.Component {
render() {
return React.createElement('div');
},
});
}
}
expect(React.isValidElement(React.createElement('div'))).toEqual(true);
expect(React.isValidElement(React.createElement(Component))).toEqual(true);
@ -367,21 +330,6 @@ describe('ReactElement', () => {
expect(React.isValidElement(JSON.parse(jsonElement))).toBe(true);
});
it('allows the use of PropTypes validators in statics', () => {
// TODO: This test was added to cover a special case where we proxied
// methods. However, we don't do that any more so this test can probably
// be removed. Leaving it in classic as a safety precaution.
var Component = React.createClass({
render: () => null,
statics: {
specialType: React.PropTypes.shape({monkey: React.PropTypes.any}),
},
});
expect(typeof Component.specialType).toBe('function');
expect(typeof Component.specialType.isRequired).toBe('function');
});
// NOTE: We're explicitly not using JSX here. This is intended to test
// classic JS without JSX.
it('is indistinguishable from a plain object', () => {
@ -393,14 +341,12 @@ describe('ReactElement', () => {
// NOTE: We're explicitly not using JSX here. This is intended to test
// classic JS without JSX.
it('should use default prop value when removing a prop', () => {
var Component = React.createClass({
getDefaultProps: function() {
return {fruit: 'persimmon'};
},
render: function() {
class Component extends React.Component {
render() {
return React.createElement('span');
},
});
}
}
Component.defaultProps = {fruit: 'persimmon'};
var container = document.createElement('div');
var instance = ReactDOM.render(
@ -416,14 +362,12 @@ describe('ReactElement', () => {
// NOTE: We're explicitly not using JSX here. This is intended to test
// classic JS without JSX.
it('should normalize props with default values', () => {
var Component = React.createClass({
getDefaultProps: function() {
return {prop: 'testKey'};
},
render: function() {
class Component extends React.Component {
render() {
return React.createElement('span', null, this.props.prop);
},
});
}
}
Component.defaultProps = {prop: 'testKey'};
var instance = ReactTestUtils.renderIntoDocument(
React.createElement(Component),
@ -437,8 +381,8 @@ describe('ReactElement', () => {
});
it('throws when changing a prop (in dev) after element creation', () => {
var Outer = React.createClass({
render: function() {
class Outer extends React.Component {
render() {
var el = <div className="moo" />;
expect(function() {
@ -447,17 +391,16 @@ describe('ReactElement', () => {
expect(el.props.className).toBe('moo');
return el;
},
});
}
}
var outer = ReactTestUtils.renderIntoDocument(<Outer color="orange" />);
expect(ReactDOM.findDOMNode(outer).className).toBe('moo');
});
it('throws when adding a prop (in dev) after element creation', () => {
var container = document.createElement('div');
var Outer = React.createClass({
getDefaultProps: () => ({sound: 'meow'}),
render: function() {
class Outer extends React.Component {
render() {
var el = <div>{this.props.sound}</div>;
expect(function() {
@ -467,8 +410,9 @@ describe('ReactElement', () => {
expect(el.props.className).toBe(undefined);
return el;
},
});
}
}
Outer.defaultProps = {sound: 'meow'};
var outer = ReactDOM.render(<Outer />, container);
expect(ReactDOM.findDOMNode(outer).textContent).toBe('meow');
expect(ReactDOM.findDOMNode(outer).className).toBe('');
@ -476,11 +420,11 @@ describe('ReactElement', () => {
it('does not warn for NaN props', () => {
spyOn(console, 'error');
var Test = React.createClass({
render: function() {
class Test extends React.Component {
render() {
return <div />;
},
});
}
}
var test = ReactTestUtils.renderIntoDocument(<Test value={+undefined} />);
expect(test.props.value).toBeNaN();
expectDev(console.error.calls.count()).toBe(0);
@ -508,11 +452,11 @@ describe('ReactElement', () => {
React = require('react');
var Component = React.createClass({
render: function() {
class Component extends React.Component {
render() {
return React.createElement('div');
},
});
}
}
expect(React.isValidElement(React.createElement('div'))).toEqual(true);
expect(React.isValidElement(React.createElement(Component))).toEqual(true);
@ -544,16 +488,16 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
describe('when using jsx only', () => {
var Parent, instance;
beforeEach(() => {
Parent = React.createClass({
render: function() {
Parent = class extends React.Component {
render() {
return (
<div>
<Child ref="child" foo="foo value">children value</Child>
</div>
);
},
});
instance = ReactTestUtils.renderIntoDocument(<Parent />);
}
};
instance = ReactTestUtils.renderIntoDocument(<Parent/>);
});
it('should scry children but cannot', () => {
@ -580,14 +524,11 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
var factory, instance;
beforeEach(() => {
var childFactory = React.createFactory(Child);
var Parent = React.createClass({
render: function() {
return React.DOM.div(
{},
childFactory({ref: 'child', foo: 'foo value'}, 'children value'),
);
},
});
class Parent extends React.Component {
render() {
return React.DOM.div({}, childFactory({ ref: 'child', foo: 'foo value' }, 'children value'));
}
}
factory = React.createFactory(Parent);
instance = ReactTestUtils.renderIntoDocument(factory());
});
@ -615,18 +556,11 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
describe('when using parent that uses .createElement()', () => {
var factory, instance;
beforeEach(() => {
var Parent = React.createClass({
render: function() {
return React.DOM.div(
{},
React.createElement(
Child,
{ref: 'child', foo: 'foo value'},
'children value',
),
);
},
});
class Parent extends React.Component {
render() {
return React.DOM.div({}, React.createElement(Child, { ref: 'child', foo: 'foo value' }, 'children value'));
}
}
factory = React.createFactory(Parent);
instance = ReactTestUtils.renderIntoDocument(factory());
});

View File

@ -25,52 +25,52 @@ describe('ReactElementClone', () => {
// NOTE: We're explicitly not using JSX here. This is intended to test
// classic JS without JSX.
ComponentClass = React.createClass({
render: function() {
ComponentClass = class extends React.Component {
render() {
return React.createElement('div');
},
});
}
};
});
it('should clone a DOM component with new props', () => {
var Grandparent = React.createClass({
render: function() {
class Grandparent extends React.Component {
render() {
return <Parent child={<div className="child" />} />;
},
});
var Parent = React.createClass({
render: function() {
}
}
class Parent extends React.Component {
render() {
return (
<div className="parent">
{React.cloneElement(this.props.child, {className: 'xyz'})}
</div>
);
},
});
}
}
var component = ReactTestUtils.renderIntoDocument(<Grandparent />);
expect(ReactDOM.findDOMNode(component).childNodes[0].className).toBe('xyz');
});
it('should clone a composite component with new props', () => {
var Child = React.createClass({
render: function() {
class Child extends React.Component {
render() {
return <div className={this.props.className} />;
},
});
var Grandparent = React.createClass({
render: function() {
}
}
class Grandparent extends React.Component {
render() {
return <Parent child={<Child className="child" />} />;
},
});
var Parent = React.createClass({
render: function() {
}
}
class Parent extends React.Component {
render() {
return (
<div className="parent">
{React.cloneElement(this.props.child, {className: 'xyz'})}
</div>
);
},
});
}
}
var component = ReactTestUtils.renderIntoDocument(<Grandparent />);
expect(ReactDOM.findDOMNode(component).childNodes[0].className).toBe('xyz');
});
@ -81,43 +81,43 @@ describe('ReactElementClone', () => {
});
it('should keep the original ref if it is not overridden', () => {
var Grandparent = React.createClass({
render: function() {
class Grandparent extends React.Component {
render() {
return <Parent child={<div ref="yolo" />} />;
},
});
}
}
var Parent = React.createClass({
render: function() {
class Parent extends React.Component {
render() {
return (
<div>
{React.cloneElement(this.props.child, {className: 'xyz'})}
</div>
);
},
});
}
}
var component = ReactTestUtils.renderIntoDocument(<Grandparent />);
expect(component.refs.yolo.tagName).toBe('DIV');
});
it('should transfer the key property', () => {
var Component = React.createClass({
render: function() {
class Component extends React.Component {
render() {
return null;
},
});
}
}
var clone = React.cloneElement(<Component />, {key: 'xyz'});
expect(clone.key).toBe('xyz');
});
it('should transfer children', () => {
var Component = React.createClass({
render: function() {
class Component extends React.Component {
render() {
expect(this.props.children).toBe('xyz');
return <div />;
},
});
}
}
ReactTestUtils.renderIntoDocument(
React.cloneElement(<Component />, {children: 'xyz'}),
@ -125,12 +125,12 @@ describe('ReactElementClone', () => {
});
it('should shallow clone children', () => {
var Component = React.createClass({
render: function() {
class Component extends React.Component {
render() {
expect(this.props.children).toBe('xyz');
return <div />;
},
});
}
}
ReactTestUtils.renderIntoDocument(
React.cloneElement(<Component>xyz</Component>, {}),
@ -138,11 +138,11 @@ describe('ReactElementClone', () => {
});
it('should accept children as rest arguments', () => {
var Component = React.createClass({
render: function() {
class Component extends React.Component {
render() {
return null;
},
});
}
}
var clone = React.cloneElement(
<Component>xyz</Component>,
@ -175,41 +175,39 @@ describe('ReactElementClone', () => {
});
it('should support keys and refs', () => {
var Parent = React.createClass({
render: function() {
var clone = React.cloneElement(this.props.children, {
key: 'xyz',
ref: 'xyz',
});
class Parent extends React.Component {
render() {
var clone =
React.cloneElement(this.props.children, {key: 'xyz', ref: 'xyz'});
expect(clone.key).toBe('xyz');
expect(clone.ref).toBe('xyz');
return <div>{clone}</div>;
},
});
}
}
var Grandparent = React.createClass({
render: function() {
class Grandparent extends React.Component {
render() {
return <Parent ref="parent"><span key="abc" /></Parent>;
},
});
}
}
var component = ReactTestUtils.renderIntoDocument(<Grandparent />);
expect(component.refs.parent.refs.xyz.tagName).toBe('SPAN');
});
it('should steal the ref if a new ref is specified', () => {
var Parent = React.createClass({
render: function() {
class Parent extends React.Component {
render() {
var clone = React.cloneElement(this.props.children, {ref: 'xyz'});
return <div>{clone}</div>;
},
});
}
}
var Grandparent = React.createClass({
render: function() {
class Grandparent extends React.Component {
render() {
return <Parent ref="parent"><span ref="child" /></Parent>;
},
});
}
}
var component = ReactTestUtils.renderIntoDocument(<Grandparent />);
expect(component.refs.child).toBeUndefined();
@ -217,12 +215,12 @@ describe('ReactElementClone', () => {
});
it('should overwrite props', () => {
var Component = React.createClass({
render: function() {
class Component extends React.Component {
render() {
expect(this.props.myprop).toBe('xyz');
return <div />;
},
});
}
}
ReactTestUtils.renderIntoDocument(
React.cloneElement(<Component myprop="abc" />, {myprop: 'xyz'}),
@ -230,14 +228,12 @@ describe('ReactElementClone', () => {
});
it('should normalize props with default values', () => {
var Component = React.createClass({
getDefaultProps: function() {
return {prop: 'testKey'};
},
render: function() {
class Component extends React.Component {
render() {
return <span />;
},
});
}
}
Component.defaultProps = {prop: 'testKey'};
var instance = React.createElement(Component);
var clonedInstance = React.cloneElement(instance, {prop: undefined});
@ -289,26 +285,27 @@ describe('ReactElementClone', () => {
it('should check declared prop types after clone', () => {
spyOn(console, 'error');
var Component = React.createClass({
propTypes: {
color: React.PropTypes.string.isRequired,
},
render: function() {
class Component extends React.Component {
render() {
return React.createElement('div', null, 'My color is ' + this.color);
},
});
var Parent = React.createClass({
render: function() {
}
}
Component.propTypes = {
color: React.PropTypes.string.isRequired,
};
class Parent extends React.Component {
render() {
return React.cloneElement(this.props.child, {color: 123});
},
});
var GrandParent = React.createClass({
render: function() {
return React.createElement(Parent, {
child: React.createElement(Component, {color: 'red'}),
});
},
});
}
}
class GrandParent extends React.Component {
render() {
return React.createElement(
Parent,
{ child: React.createElement(Component, {color: 'red'}) }
);
}
}
ReactTestUtils.renderIntoDocument(React.createElement(GrandParent));
expectDev(console.error.calls.count()).toBe(1);
expectDev(console.error.calls.argsFor(0)[0]).toBe(

View File

@ -31,11 +31,11 @@ describe('ReactElementValidator', () => {
React = require('react');
ReactDOM = require('react-dom');
ReactTestUtils = require('ReactTestUtils');
ComponentClass = React.createClass({
render: function() {
ComponentClass = class extends React.Component {
render() {
return React.createElement('div');
},
});
}
};
});
it('warns for keys for arrays of elements in rest args', () => {
@ -54,21 +54,19 @@ describe('ReactElementValidator', () => {
spyOn(console, 'error');
var Component = React.createFactory(ComponentClass);
var InnerClass = React.createClass({
displayName: 'InnerClass',
render: function() {
class InnerClass extends React.Component {
render() {
return Component(null, this.props.childSet);
},
});
}
}
var InnerComponent = React.createFactory(InnerClass);
var ComponentWrapper = React.createClass({
displayName: 'ComponentWrapper',
render: function() {
return InnerComponent({childSet: [Component(), Component()]});
},
});
class ComponentWrapper extends React.Component {
render() {
return InnerComponent({childSet: [Component(), Component()] });
}
}
ReactTestUtils.renderIntoDocument(React.createElement(ComponentWrapper));
@ -83,12 +81,10 @@ describe('ReactElementValidator', () => {
it('warns for keys for arrays with no owner or parent info', () => {
spyOn(console, 'error');
var Anonymous = React.createClass({
displayName: undefined,
render: function() {
return <div />;
},
});
function Anonymous() {
return <div />;
}
Object.defineProperty(Anonymous, 'name', { value: undefined });
var divs = [<div />, <div />];
ReactTestUtils.renderIntoDocument(<Anonymous>{divs}</Anonymous>);
@ -119,23 +115,17 @@ describe('ReactElementValidator', () => {
it('warns for keys with component stack info', () => {
spyOn(console, 'error');
var Component = React.createClass({
render: function() {
return <div>{[<div />, <div />]}</div>;
},
});
function Component() {
return <div>{[<div />, <div />]}</div>;
}
var Parent = React.createClass({
render: function() {
return React.cloneElement(this.props.child);
},
});
function Parent(props) {
return React.cloneElement(props.child);
}
var GrandParent = React.createClass({
render: function() {
return <Parent child={<Component />} />;
},
});
function GrandParent() {
return <Parent child={<Component />} />;
}
ReactTestUtils.renderIntoDocument(<GrandParent />);
@ -154,16 +144,14 @@ describe('ReactElementValidator', () => {
it('does not warn for keys when passing children down', () => {
spyOn(console, 'error');
var Wrapper = React.createClass({
render: function() {
return (
<div>
{this.props.children}
<footer />
</div>
);
},
});
function Wrapper(props) {
return (
<div>
{props.children}
<footer />
</div>
);
}
ReactTestUtils.renderIntoDocument(
<Wrapper>
@ -255,19 +243,15 @@ describe('ReactElementValidator', () => {
// component, we give a small hint as to which parent instantiated that
// component as per warnings about key usage in ReactElementValidator.
spyOn(console, 'error');
var MyComp = React.createClass({
propTypes: {
color: React.PropTypes.string,
},
render: function() {
return React.createElement('div', null, 'My color is ' + this.color);
},
});
var ParentComp = React.createClass({
render: function() {
return React.createElement(MyComp, {color: 123});
},
});
function MyComp(props) {
return React.createElement('div', null, 'My color is ' + props.color);
}
MyComp.propTypes = {
color: React.PropTypes.string,
};
function ParentComp() {
return React.createElement(MyComp, {color: 123});
}
ReactTestUtils.renderIntoDocument(React.createElement(ParentComp));
expectDev(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Failed prop type: ' +
@ -325,11 +309,9 @@ describe('ReactElementValidator', () => {
it('includes the owner name when passing null, undefined, boolean, or number', () => {
spyOn(console, 'error');
var ParentComp = React.createClass({
render: function() {
return React.createElement(null);
},
});
function ParentComp() {
return React.createElement(null);
}
expect(function() {
ReactTestUtils.renderIntoDocument(React.createElement(ParentComp));
}).toThrowError(
@ -349,15 +331,13 @@ describe('ReactElementValidator', () => {
it('should check default prop values', () => {
spyOn(console, 'error');
var Component = React.createClass({
propTypes: {prop: React.PropTypes.string.isRequired},
getDefaultProps: function() {
return {prop: null};
},
render: function() {
class Component extends React.Component {
render() {
return React.createElement('span', null, this.props.prop);
},
});
}
}
Component.propTypes = {prop: React.PropTypes.string.isRequired};
Component.defaultProps = {prop: null};
ReactTestUtils.renderIntoDocument(React.createElement(Component));
@ -372,15 +352,13 @@ describe('ReactElementValidator', () => {
it('should not check the default for explicit null', () => {
spyOn(console, 'error');
var Component = React.createClass({
propTypes: {prop: React.PropTypes.string.isRequired},
getDefaultProps: function() {
return {prop: 'text'};
},
render: function() {
class Component extends React.Component {
render() {
return React.createElement('span', null, this.props.prop);
},
});
}
}
Component.propTypes = {prop: React.PropTypes.string.isRequired};
Component.defaultProps = {prop: 'text'};
ReactTestUtils.renderIntoDocument(
React.createElement(Component, {prop: null}),
@ -397,14 +375,14 @@ describe('ReactElementValidator', () => {
it('should check declared prop types', () => {
spyOn(console, 'error');
var Component = React.createClass({
propTypes: {
prop: React.PropTypes.string.isRequired,
},
render: function() {
class Component extends React.Component {
render() {
return React.createElement('span', null, this.props.prop);
},
});
}
}
Component.propTypes = {
prop: React.PropTypes.string.isRequired,
};
ReactTestUtils.renderIntoDocument(React.createElement(Component));
ReactTestUtils.renderIntoDocument(
@ -437,14 +415,15 @@ describe('ReactElementValidator', () => {
it('should warn if a PropType creator is used as a PropType', () => {
spyOn(console, 'error');
var Component = React.createClass({
propTypes: {
myProp: React.PropTypes.shape,
},
render: function() {
class Component extends React.Component {
render() {
return React.createElement('span', null, this.props.myProp.value);
},
});
}
}
Component.propTypes = {
myProp: React.PropTypes.shape,
};
ReactTestUtils.renderIntoDocument(
React.createElement(Component, {myProp: {value: 'hi'}}),
@ -462,11 +441,9 @@ describe('ReactElementValidator', () => {
it('should warn when accessing .type on an element factory', () => {
spyOn(console, 'error');
var TestComponent = React.createClass({
render: function() {
return <div />;
},
});
function TestComponent() {
return <div />;
}
var TestFactory = React.createFactory(TestComponent);
expect(TestFactory.type).toBe(TestComponent);
expectDev(console.error.calls.count()).toBe(1);
@ -481,14 +458,14 @@ describe('ReactElementValidator', () => {
it('does not warn when using DOM node as children', () => {
spyOn(console, 'error');
var DOMContainer = React.createClass({
render: function() {
class DOMContainer extends React.Component {
render() {
return <div />;
},
componentDidMount: function() {
}
componentDidMount() {
ReactDOM.findDOMNode(this).appendChild(this.props.children);
},
});
}
}
var node = document.createElement('div');
// This shouldn't cause a stack overflow or any other problems (#3883)

View File

@ -205,13 +205,10 @@ describe('ReactPropTypesProduction', function() {
it('should not have been called', function() {
var spy = jest.fn();
var Component = React.createClass({
propTypes: {num: spy},
render: function() {
return <div />;
},
});
function Component() {
return <div />;
}
Component.propTypes = {num: spy};
var instance = <Component num={5} />;
ReactTestUtils.renderIntoDocument(instance);

View File

@ -225,23 +225,28 @@ describe('ReactComponentLifeCycle', () => {
it('should correctly determine if a component is mounted', () => {
spyOn(console, 'error');
var Component = React.createClass({
componentWillMount: function() {
expect(this.isMounted()).toBeFalsy();
},
componentDidMount: function() {
expect(this.isMounted()).toBeTruthy();
},
render: function() {
expect(this.isMounted()).toBeFalsy();
return <div />;
},
});
class Component extends React.Component {
_isMounted() {
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
return this.updater.isMounted(this);
}
componentWillMount() {
expect(this._isMounted()).toBeFalsy();
}
componentDidMount() {
expect(this._isMounted()).toBeTruthy();
}
render() {
expect(this._isMounted()).toBeFalsy();
return <div/>;
}
}
var element = <Component />;
var instance = ReactTestUtils.renderIntoDocument(element);
expect(instance.isMounted()).toBeTruthy();
expect(instance._isMounted()).toBeTruthy();
expectDev(console.error.calls.count()).toBe(1);
expectDev(console.error.calls.argsFor(0)[0]).toContain(
@ -251,23 +256,28 @@ describe('ReactComponentLifeCycle', () => {
it('should correctly determine if a null component is mounted', () => {
spyOn(console, 'error');
var Component = React.createClass({
componentWillMount: function() {
expect(this.isMounted()).toBeFalsy();
},
componentDidMount: function() {
expect(this.isMounted()).toBeTruthy();
},
render: function() {
expect(this.isMounted()).toBeFalsy();
class Component extends React.Component {
_isMounted() {
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
return this.updater.isMounted(this);
}
componentWillMount() {
expect(this._isMounted()).toBeFalsy();
}
componentDidMount() {
expect(this._isMounted()).toBeTruthy();
}
render() {
expect(this._isMounted()).toBeFalsy();
return null;
},
});
}
}
var element = <Component />;
var instance = ReactTestUtils.renderIntoDocument(element);
expect(instance.isMounted()).toBeTruthy();
expect(instance._isMounted()).toBeTruthy();
expectDev(console.error.calls.count()).toBe(1);
expectDev(console.error.calls.argsFor(0)[0]).toContain(
@ -276,38 +286,38 @@ describe('ReactComponentLifeCycle', () => {
});
it('isMounted should return false when unmounted', () => {
var Component = React.createClass({
render: function() {
return <div />;
},
});
class Component extends React.Component {
render() {
return <div/>;
}
}
var container = document.createElement('div');
var instance = ReactDOM.render(<Component />, container);
expect(instance.isMounted()).toBe(true);
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
expect(instance.updater.isMounted(instance)).toBe(true);
ReactDOM.unmountComponentAtNode(container);
expect(instance.isMounted()).toBe(false);
expect(instance.updater.isMounted(instance)).toBe(false);
});
it('warns if findDOMNode is used inside render', () => {
spyOn(console, 'error');
var Component = React.createClass({
getInitialState: function() {
return {isMounted: false};
},
componentDidMount: function() {
class Component extends React.Component {
state = {isMounted: false};
componentDidMount() {
this.setState({isMounted: true});
},
render: function() {
}
render() {
if (this.state.isMounted) {
expect(ReactDOM.findDOMNode(this).tagName).toBe('DIV');
}
return <div />;
},
});
}
}
ReactTestUtils.renderIntoDocument(<Component />);
expectDev(console.error.calls.count()).toBe(1);
@ -513,30 +523,31 @@ describe('ReactComponentLifeCycle', () => {
return true;
};
};
var Outer = React.createClass({
render: function() {
class Outer extends React.Component {
componentWillMount = logger('outer componentWillMount');
componentDidMount = logger('outer componentDidMount');
componentWillReceiveProps = logger('outer componentWillReceiveProps');
shouldComponentUpdate = logger('outer shouldComponentUpdate');
componentWillUpdate = logger('outer componentWillUpdate');
componentDidUpdate = logger('outer componentDidUpdate');
componentWillUnmount = logger('outer componentWillUnmount');
render() {
return <div><Inner x={this.props.x} /></div>;
},
componentWillMount: logger('outer componentWillMount'),
componentDidMount: logger('outer componentDidMount'),
componentWillReceiveProps: logger('outer componentWillReceiveProps'),
shouldComponentUpdate: logger('outer shouldComponentUpdate'),
componentWillUpdate: logger('outer componentWillUpdate'),
componentDidUpdate: logger('outer componentDidUpdate'),
componentWillUnmount: logger('outer componentWillUnmount'),
});
var Inner = React.createClass({
render: function() {
}
}
class Inner extends React.Component {
componentWillMount = logger('inner componentWillMount');
componentDidMount = logger('inner componentDidMount');
componentWillReceiveProps = logger('inner componentWillReceiveProps');
shouldComponentUpdate = logger('inner shouldComponentUpdate');
componentWillUpdate = logger('inner componentWillUpdate');
componentDidUpdate = logger('inner componentDidUpdate');
componentWillUnmount = logger('inner componentWillUnmount');
render() {
return <span>{this.props.x}</span>;
},
componentWillMount: logger('inner componentWillMount'),
componentDidMount: logger('inner componentDidMount'),
componentWillReceiveProps: logger('inner componentWillReceiveProps'),
shouldComponentUpdate: logger('inner shouldComponentUpdate'),
componentWillUpdate: logger('inner componentWillUpdate'),
componentDidUpdate: logger('inner componentDidUpdate'),
componentWillUnmount: logger('inner componentWillUnmount'),
});
}
}
var container = document.createElement('div');
log = [];

View File

@ -41,8 +41,15 @@ describe('ReactComponentTreeHook', () => {
return addendum.replace(/\(at .+?:\d+\)/g, '(at **)');
}
var Anon = React.createClass({displayName: null, render: () => null});
var Orange = React.createClass({render: () => null});
function Anon() {
return null;
}
Object.defineProperty(Anon, 'name', {
value: null,
});
function Orange() {
return null;
}
expectDev(getAddendum()).toBe('');
expectDev(getAddendum(<div />)).toBe('\n in div (at **)');

View File

@ -166,64 +166,6 @@ describe('ReactCompositeComponent', () => {
expect(instance.getAnchor().className).toBe('');
});
it('should auto bind methods and values correctly', () => {
spyOn(console, 'error');
var ComponentClass = React.createClass({
getInitialState: function() {
return {valueToReturn: 'hi'};
},
methodToBeExplicitlyBound: function() {
return this;
},
methodAutoBound: function() {
return this;
},
render: function() {
return <div />;
},
});
var instance = <ComponentClass />;
// Next, prove that once mounted, the scope is bound correctly to the actual
// component.
var mountedInstance = ReactTestUtils.renderIntoDocument(instance);
expect(function() {
mountedInstance.methodToBeExplicitlyBound.bind(instance)();
}).not.toThrow();
expect(function() {
mountedInstance.methodAutoBound();
}).not.toThrow();
expectDev(console.error.calls.count()).toBe(1);
var explicitlyBound = mountedInstance.methodToBeExplicitlyBound.bind(
mountedInstance,
);
expectDev(console.error.calls.count()).toBe(2);
var autoBound = mountedInstance.methodAutoBound;
var context = {};
expect(explicitlyBound.call(context)).toBe(mountedInstance);
expect(autoBound.call(context)).toBe(mountedInstance);
expect(explicitlyBound.call(mountedInstance)).toBe(mountedInstance);
expect(autoBound.call(mountedInstance)).toBe(mountedInstance);
});
it('should not pass this to getDefaultProps', () => {
var Component = React.createClass({
getDefaultProps: function() {
expect(this.render).not.toBeDefined();
return {};
},
render: function() {
return <div />;
},
});
ReactTestUtils.renderIntoDocument(<Component />);
});
it('should use default values for undefined props', () => {
class Component extends React.Component {
static defaultProps = {prop: 'testKey'};
@ -1204,17 +1146,17 @@ describe('ReactCompositeComponent', () => {
});
it('should replace state', () => {
var Moo = React.createClass({
getInitialState: function() {
return {x: 1};
},
render: function() {
class Moo extends React.Component {
state = {x: 1};
render() {
return <div />;
},
});
}
}
var moo = ReactTestUtils.renderIntoDocument(<Moo />);
moo.replaceState({y: 2});
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
moo.updater.enqueueReplaceState(moo, {y: 2});
expect('x' in moo.state).toBe(false);
expect(moo.state.y).toBe(2);
});
@ -1226,21 +1168,22 @@ describe('ReactCompositeComponent', () => {
NotActuallyImmutable.prototype.amIImmutable = function() {
return true;
};
var Moo = React.createClass({
getInitialState: function() {
return new NotActuallyImmutable('first');
},
render: function() {
class Moo extends React.Component {
state = new NotActuallyImmutable('first');
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
_replaceState = update => this.updater.enqueueReplaceState(this, update);
render() {
return <div />;
},
});
}
}
var moo = ReactTestUtils.renderIntoDocument(<Moo />);
expect(moo.state.str).toBe('first');
expect(moo.state.amIImmutable()).toBe(true);
var secondState = new NotActuallyImmutable('second');
moo.replaceState(secondState);
moo._replaceState(secondState);
expect(moo.state.str).toBe('second');
expect(moo.state.amIImmutable()).toBe(true);
expect(moo.state).toBe(secondState);
@ -1254,14 +1197,14 @@ describe('ReactCompositeComponent', () => {
var fifthState = new NotActuallyImmutable('fifth');
ReactDOM.unstable_batchedUpdates(function() {
moo.setState({str: 'fourth'});
moo.replaceState(fifthState);
moo._replaceState(fifthState);
});
expect(moo.state).toBe(fifthState);
// When more than one state update is enqueued, we have the same behavior
var sixthState = new NotActuallyImmutable('sixth');
ReactDOM.unstable_batchedUpdates(function() {
moo.replaceState(sixthState);
moo._replaceState(sixthState);
moo.setState({str: 'seventh'});
});
expect(moo.state.str).toBe('seventh');

View File

@ -24,34 +24,34 @@ describe('ReactCompositeComponent-state', () => {
ReactDOM = require('react-dom');
ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
TestComponent = React.createClass({
peekAtState: function(from, state) {
state = state || this.state;
this.props.stateListener(from, state && state.color);
},
TestComponent = class extends React.Component {
constructor(props) {
super(props);
this.peekAtState('getInitialState', undefined, props);
this.state = {color: 'red'};
}
peekAtCallback: function(from) {
peekAtState = (from, state = this.state, props = this.props) => {
props.stateListener(from, state && state.color);
}
peekAtCallback = from => {
return () => this.peekAtState(from);
},
}
setFavoriteColor: function(nextColor) {
setFavoriteColor(nextColor) {
this.setState(
{color: nextColor},
this.peekAtCallback('setFavoriteColor'),
);
},
}
getInitialState: function() {
this.peekAtState('getInitialState');
return {color: 'red'};
},
render: function() {
render() {
this.peekAtState('render');
return <div>{this.state.color}</div>;
},
}
componentWillMount: function() {
componentWillMount() {
this.peekAtState('componentWillMount-start');
this.setState(function(state) {
this.peekAtState('before-setState-sunrise', state);
@ -72,25 +72,27 @@ describe('ReactCompositeComponent-state', () => {
this.peekAtState('after-setState-orange', state);
});
this.peekAtState('componentWillMount-end');
},
}
componentDidMount: function() {
componentDidMount() {
this.peekAtState('componentDidMount-start');
this.setState(
{color: 'yellow'},
this.peekAtCallback('setState-yellow'),
);
this.peekAtState('componentDidMount-end');
},
}
componentWillReceiveProps: function(newProps) {
componentWillReceiveProps(newProps) {
this.peekAtState('componentWillReceiveProps-start');
if (newProps.nextColor) {
this.setState(function(state) {
this.peekAtState('before-setState-receiveProps', state);
return {color: newProps.nextColor};
});
this.replaceState({color: undefined});
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
this.updater.enqueueReplaceState(this, {color: undefined});
this.setState(
function(state) {
this.peekAtState('before-setState-again-receiveProps', state);
@ -103,28 +105,28 @@ describe('ReactCompositeComponent-state', () => {
});
}
this.peekAtState('componentWillReceiveProps-end');
},
}
shouldComponentUpdate: function(nextProps, nextState) {
shouldComponentUpdate(nextProps, nextState) {
this.peekAtState('shouldComponentUpdate-currentState');
this.peekAtState('shouldComponentUpdate-nextState', nextState);
return true;
},
}
componentWillUpdate: function(nextProps, nextState) {
componentWillUpdate(nextProps, nextState) {
this.peekAtState('componentWillUpdate-currentState');
this.peekAtState('componentWillUpdate-nextState', nextState);
},
}
componentDidUpdate: function(prevProps, prevState) {
componentDidUpdate(prevProps, prevState) {
this.peekAtState('componentDidUpdate-currentState');
this.peekAtState('componentDidUpdate-prevState', prevState);
},
}
componentWillUnmount: function() {
componentWillUnmount() {
this.peekAtState('componentWillUnmount');
},
});
}
};
});
it('should support setting state', () => {

View File

@ -35,14 +35,14 @@ describe('ReactMultiChild', () => {
var mockUpdate = jest.fn();
var mockUnmount = jest.fn();
var MockComponent = React.createClass({
componentDidMount: mockMount,
componentDidUpdate: mockUpdate,
componentWillUnmount: mockUnmount,
render: function() {
class MockComponent extends React.Component {
componentDidMount = mockMount;
componentDidUpdate = mockUpdate;
componentWillUnmount = mockUnmount;
render() {
return <span />;
},
});
}
}
expect(mockMount.mock.calls.length).toBe(0);
expect(mockUpdate.mock.calls.length).toBe(0);
@ -67,13 +67,13 @@ describe('ReactMultiChild', () => {
var mockMount = jest.fn();
var mockUnmount = jest.fn();
var MockComponent = React.createClass({
componentDidMount: mockMount,
componentWillUnmount: mockUnmount,
render: function() {
class MockComponent extends React.Component {
componentDidMount = mockMount;
componentWillUnmount = mockUnmount;
render() {
return <span />;
},
});
}
}
expect(mockMount.mock.calls.length).toBe(0);
expect(mockUnmount.mock.calls.length).toBe(0);
@ -95,13 +95,13 @@ describe('ReactMultiChild', () => {
var mockMount = jest.fn();
var mockUnmount = jest.fn();
var MockComponent = React.createClass({
componentDidMount: mockMount,
componentWillUnmount: mockUnmount,
render: function() {
class MockComponent extends React.Component {
componentDidMount = mockMount;
componentWillUnmount = mockUnmount;
render() {
return <span />;
},
});
}
}
class WrapperComponent extends React.Component {
render() {
@ -132,13 +132,13 @@ describe('ReactMultiChild', () => {
var mockMount = jest.fn();
var mockUnmount = jest.fn();
var MockComponent = React.createClass({
componentDidMount: mockMount,
componentWillUnmount: mockUnmount,
render: function() {
class MockComponent extends React.Component {
componentDidMount = mockMount;
componentWillUnmount = mockUnmount;
render() {
return <span />;
},
});
}
}
expect(mockMount.mock.calls.length).toBe(0);
expect(mockUnmount.mock.calls.length).toBe(0);

View File

@ -64,16 +64,16 @@ describeStack('ReactPerf', () => {
}
};
LifeCycle = React.createClass({
shouldComponentUpdate: emptyFunction.thatReturnsTrue,
componentWillMount: emptyFunction,
componentDidMount: emptyFunction,
componentWillReceiveProps: emptyFunction,
componentWillUpdate: emptyFunction,
componentDidUpdate: emptyFunction,
componentWillUnmount: emptyFunction,
render: emptyFunction.thatReturnsNull,
});
LifeCycle = class extends React.Component {
shouldComponentUpdate = emptyFunction.thatReturnsTrue;
componentWillMount = emptyFunction;
componentDidMount = emptyFunction;
componentWillReceiveProps = emptyFunction;
componentWillUpdate = emptyFunction;
componentDidUpdate = emptyFunction;
componentWillUnmount = emptyFunction;
render = emptyFunction.thatReturnsNull;
};
});
afterEach(() => {

View File

@ -249,15 +249,14 @@ describe('ReactStatelessComponent', () => {
it('deduplicates ref warnings based on element or owner', () => {
spyOn(console, 'error');
// Prevent the Babel transform adding a displayName.
var createClassWithoutDisplayName = React.createClass;
// When owner uses JSX, we can use exact line location to dedupe warnings
var AnonymousParentUsingJSX = createClassWithoutDisplayName({
class AnonymousParentUsingJSX extends React.Component {
render() {
return <StatelessComponent name="A" ref={() => {}} />;
},
});
}
}
Object.defineProperty(AnonymousParentUsingJSX, 'name', {value: undefined});
const instance1 = ReactTestUtils.renderIntoDocument(
<AnonymousParentUsingJSX />,
);
@ -273,14 +272,16 @@ describe('ReactStatelessComponent', () => {
console.error.calls.reset();
// When owner doesn't use JSX, and is anonymous, we warn once per internal instance.
var AnonymousParentNotUsingJSX = createClassWithoutDisplayName({
class AnonymousParentNotUsingJSX extends React.Component {
render() {
return React.createElement(StatelessComponent, {
name: 'A',
ref: () => {},
});
},
});
}
}
Object.defineProperty(AnonymousParentNotUsingJSX, 'name', {value: undefined});
const instance2 = ReactTestUtils.renderIntoDocument(
<AnonymousParentNotUsingJSX />,
);

View File

@ -391,30 +391,23 @@ describe('ReactUpdates', () => {
},
};
var Box = React.createClass({
mixins: [UpdateLoggingMixin],
render: function() {
class Box extends React.Component {
render() {
return <div ref="boxDiv">{this.props.children}</div>;
},
});
}
}
Object.assign(Box.prototype, UpdateLoggingMixin);
var Child = React.createClass({
mixins: [UpdateLoggingMixin],
render: function() {
class Child extends React.Component {
render() {
return <span ref="span">child</span>;
},
});
}
}
Object.assign(Child.prototype, UpdateLoggingMixin);
var Switcher = React.createClass({
mixins: [UpdateLoggingMixin],
getInitialState: function() {
return {tabKey: 'hello'};
},
render: function() {
class Switcher extends React.Component {
state = {tabKey: 'hello'};
render() {
var child = this.props.children;
return (
@ -428,20 +421,20 @@ describe('ReactUpdates', () => {
</div>
</Box>
);
},
});
}
}
Object.assign(Switcher.prototype, UpdateLoggingMixin);
var App = React.createClass({
mixins: [UpdateLoggingMixin],
render: function() {
class App extends React.Component {
render() {
return (
<Switcher ref="switcher">
<Child key="hello" ref="child" />
</Switcher>
);
},
});
}
}
Object.assign(App.prototype, UpdateLoggingMixin);
var root = <App />;
root = ReactTestUtils.renderIntoDocument(root);
@ -913,52 +906,6 @@ describe('ReactUpdates', () => {
expect(console.error.calls.count()).toBe(3);
});
it('throws in replaceState if the update callback is not a function', () => {
spyOn(console, 'error');
function Foo() {
this.a = 1;
this.b = 2;
}
var A = React.createClass({
getInitialState: function() {
return {};
},
render: function() {
return <div />;
},
});
var component = ReactTestUtils.renderIntoDocument(<A />);
expect(() => component.replaceState({}, 'no')).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: no',
);
expectDev(console.error.calls.argsFor(0)[0]).toContain(
'replaceState(...): Expected the last optional `callback` argument to be ' +
'a function. Instead received: no.',
);
component = ReactTestUtils.renderIntoDocument(<A />);
expect(() => component.replaceState({}, {foo: 'bar'})).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: [object Object]',
);
expectDev(console.error.calls.argsFor(1)[0]).toContain(
'replaceState(...): Expected the last optional `callback` argument to be ' +
'a function. Instead received: [object Object].',
);
component = ReactTestUtils.renderIntoDocument(<A />);
expect(() => component.replaceState({}, new Foo())).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: [object Object]',
);
expectDev(console.error.calls.argsFor(2)[0]).toContain(
'replaceState(...): Expected the last optional `callback` argument to be ' +
'a function. Instead received: [object Object].',
);
expect(console.error.calls.count()).toBe(3);
});
it('throws in forceUpdate if the update callback is not a function', () => {
spyOn(console, 'error');

View File

@ -868,11 +868,11 @@ describe('ReactDOMComponent', () => {
container.shadyRoot = {};
return container;
};
var ShadyComponent = React.createClass({
class ShadyComponent extends React.Component {
render() {
return <polymer-component />;
},
});
}
}
var node = document.createElement('div');
ReactDOM.render(<ShadyComponent />, node);
expectDev(console.error.calls.count()).toBe(1);
@ -1350,12 +1350,12 @@ describe('ReactDOMComponent', () => {
it('gives useful context in warnings', () => {
spyOn(console, 'error');
var Row = React.createClass({
render: () => <tr />,
});
var FancyRow = React.createClass({
render: () => <Row />,
});
function Row() {
return <tr />;
}
function FancyRow() {
return <Row />;
}
class Table extends React.Component {
render() {
@ -1369,12 +1369,12 @@ describe('ReactDOMComponent', () => {
}
}
var Viz1 = React.createClass({
render: () => <table><FancyRow /></table>,
});
var App1 = React.createClass({
render: () => <Viz1 />,
});
function Viz1() {
return <table><FancyRow /></table>;
}
function App1() {
return <Viz1 />;
}
ReactTestUtils.renderIntoDocument(<App1 />);
expectDev(console.error.calls.count()).toBe(1);
expectDev(
@ -1389,12 +1389,12 @@ describe('ReactDOMComponent', () => {
: 'See Viz1 > table > FancyRow > Row > tr.',
);
var Viz2 = React.createClass({
render: () => <FancyTable><FancyRow /></FancyTable>,
});
var App2 = React.createClass({
render: () => <Viz2 />,
});
function Viz2() {
return <FancyTable><FancyRow /></FancyTable>;
}
function App2() {
return <Viz2 />;
}
ReactTestUtils.renderIntoDocument(<App2 />);
expectDev(console.error.calls.count()).toBe(2);
expectDev(

View File

@ -89,13 +89,13 @@ describe('ReactMount', () => {
var mockMount = jest.fn();
var mockUnmount = jest.fn();
var Component = React.createClass({
componentDidMount: mockMount,
componentWillUnmount: mockUnmount,
render: function() {
class Component extends React.Component {
componentDidMount = mockMount;
componentWillUnmount = mockUnmount;
render() {
return <span>{this.props.text}</span>;
},
});
}
}
expect(mockMount.mock.calls.length).toBe(0);
expect(mockUnmount.mock.calls.length).toBe(0);

View File

@ -490,32 +490,6 @@ describe('ReactDOMServer', () => {
expect(markup).toBe('<div>hello</div>');
});
it('warns with a no-op when an async replaceState is triggered', () => {
var Bar = React.createClass({
componentWillMount: function() {
this.replaceState({text: 'hello'});
setTimeout(() => {
this.replaceState({text: 'error'});
});
},
render: function() {
return <div onClick={() => {}}>{this.state.text}</div>;
},
});
spyOn(console, 'error');
ReactDOMServer.renderToString(<Bar />);
jest.runOnlyPendingTimers();
expectDev(console.error.calls.count()).toBe(1);
expectDev(console.error.calls.mostRecent().args[0]).toBe(
'Warning: replaceState(...): Can only update a mounting component. ' +
'This usually means you called replaceState() outside componentWillMount() on the server. ' +
'This is a no-op.\n\nPlease check the code for the Bar component.',
);
var markup = ReactDOMServer.renderToStaticMarkup(<Bar />);
expect(markup).toBe('<div>hello</div>');
});
it('warns with a no-op when an async forceUpdate is triggered', () => {
class Baz extends React.Component {
componentWillMount() {

View File

@ -207,9 +207,11 @@ describe('BeforeInputEventPlugin', function() {
function TestEditableReactComponent(Emulator, Scenario, ExpectedResult) {
ModuleCache = new initialize(Emulator);
var EditableDiv = React.createClass({
render: () => <div contentEditable="true" />,
});
class EditableDiv extends React.Component {
render() {
return <div contentEditable="true" />;
}
}
var rendered = ReactTestUtils.renderIntoDocument(<EditableDiv />);
var node = ModuleCache.ReactDOM.findDOMNode(rendered);

View File

@ -873,15 +873,13 @@ describe('ReactIncremental', () => {
it('can replaceState', () => {
let instance;
const Bar = React.createClass({
getInitialState() {
instance = this;
return {a: 'a'};
},
class Bar extends React.Component {
state = {a: 'a'};
render() {
instance = this;
return <div>{this.props.children}</div>;
},
});
}
}
function Foo() {
return (
@ -895,7 +893,7 @@ describe('ReactIncremental', () => {
ReactNoop.flush();
instance.setState({b: 'b'});
instance.setState({c: 'c'});
instance.replaceState({d: 'd'});
instance.updater.enqueueReplaceState(instance, {d: 'd'});
ReactNoop.flush();
expect(instance.state).toEqual({d: 'd'});
});

View File

@ -29,18 +29,23 @@ describe('ReactIncrementalReflection', () => {
const instances = [];
const Component = React.createClass({
class Component extends React.Component {
_isMounted() {
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
return this.updater.isMounted(this);
}
componentWillMount() {
instances.push(this);
ops.push('componentWillMount', this.isMounted());
},
ops.push('componentWillMount', this._isMounted());
}
componentDidMount() {
ops.push('componentDidMount', this.isMounted());
},
ops.push('componentDidMount', this._isMounted());
}
render() {
return <span />;
},
});
}
}
function Foo() {
return <Component />;
@ -53,7 +58,7 @@ describe('ReactIncrementalReflection', () => {
expect(ops).toEqual(['componentWillMount', false]);
expect(instances[0].isMounted()).toBe(false);
expect(instances[0]._isMounted()).toBe(false);
ops = [];
@ -62,7 +67,7 @@ describe('ReactIncrementalReflection', () => {
expect(ops).toEqual(['componentDidMount', true]);
expect(instances[0].isMounted()).toBe(true);
expect(instances[0]._isMounted()).toBe(true);
});
it('handles isMounted when an unmount is deferred', () => {
@ -70,18 +75,21 @@ describe('ReactIncrementalReflection', () => {
const instances = [];
const Component = React.createClass({
class Component extends React.Component {
_isMounted() {
return this.updater.isMounted(this);
}
componentWillMount() {
instances.push(this);
},
}
componentWillUnmount() {
ops.push('componentWillUnmount', this.isMounted());
},
ops.push('componentWillUnmount', this._isMounted());
}
render() {
ops.push('Component');
return <span />;
},
});
}
}
function Other() {
ops.push('Other');
@ -98,7 +106,7 @@ describe('ReactIncrementalReflection', () => {
expect(ops).toEqual(['Component']);
ops = [];
expect(instances[0].isMounted()).toBe(true);
expect(instances[0]._isMounted()).toBe(true);
ReactNoop.render(<Foo mount={false} />);
// Render part way through but don't yet commit the updates so it is not
@ -108,14 +116,14 @@ describe('ReactIncrementalReflection', () => {
expect(ops).toEqual(['Other']);
ops = [];
expect(instances[0].isMounted()).toBe(true);
expect(instances[0]._isMounted()).toBe(true);
// Finish flushing the unmount.
ReactNoop.flush();
expect(ops).toEqual(['componentWillUnmount', true]);
expect(instances[0].isMounted()).toBe(false);
expect(instances[0]._isMounted()).toBe(false);
});
it('finds no node before insertion and correct node before deletion', () => {

View File

@ -74,22 +74,20 @@ describe('ReactIncrementalUpdates', () => {
it('only drops updates with equal or lesser priority when replaceState is called', () => {
let instance;
let ops = [];
const Foo = React.createClass({
getInitialState() {
return {};
},
class Foo extends React.Component {
state = {};
componentDidMount() {
ops.push('componentDidMount');
},
}
componentDidUpdate() {
ops.push('componentDidUpdate');
},
}
render() {
ops.push('render');
instance = this;
return <div />;
},
});
}
}
ReactNoop.render(<Foo />);
ReactNoop.flush();
@ -100,7 +98,7 @@ describe('ReactIncrementalUpdates', () => {
instance.setState({a: 'a'});
instance.setState({b: 'b'});
});
instance.replaceState({c: 'c'});
instance.updater.enqueueReplaceState(instance, {c: 'c'});
instance.setState({d: 'd'});
ReactNoop.flushAnimationPri();
@ -201,19 +199,17 @@ describe('ReactIncrementalUpdates', () => {
it('can abort an update, schedule a replaceState, and resume', () => {
let instance;
let ops = [];
const Foo = React.createClass({
getInitialState() {
return {};
},
class Foo extends React.Component {
state = {};
componentDidUpdate() {
ops.push('componentDidUpdate');
},
}
render() {
ops.push('render');
instance = this;
return <span />;
},
});
}
}
ReactNoop.render(<Foo />);
ReactNoop.flush();
@ -245,7 +241,9 @@ describe('ReactIncrementalUpdates', () => {
instance.setState(createUpdate('f'));
ReactNoop.performAnimationWork(() => {
instance.setState(createUpdate('d'));
instance.replaceState(createUpdate('e'));
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
instance.updater.enqueueReplaceState(instance, createUpdate('e'));
});
instance.setState(createUpdate('g'));
@ -256,21 +254,21 @@ describe('ReactIncrementalUpdates', () => {
it('passes accumulation of previous updates to replaceState updater function', () => {
let instance;
const Foo = React.createClass({
getInitialState() {
return {};
},
class Foo extends React.Component {
state = {};
render() {
instance = this;
return <span />;
},
});
}
}
ReactNoop.render(<Foo />);
ReactNoop.flush();
instance.setState({a: 'a'});
instance.setState({b: 'b'});
instance.replaceState(previousState => ({previousState}));
// No longer a public API, but we can test that it works internally by
// reaching into the updater.
instance.updater.enqueueReplaceState(instance, previousState => ({previousState}));
ReactNoop.flush();
expect(instance.state).toEqual({previousState: {a: 'a', b: 'b'}});
});

View File

@ -90,12 +90,12 @@ describe('ReactTestUtils', () => {
it('should have shallow unmounting', () => {
var componentWillUnmount = jest.fn();
var SomeComponent = React.createClass({
render: function() {
class SomeComponent extends React.Component {
componentWillUnmount = componentWillUnmount;
render() {
return <div />;
},
componentWillUnmount,
});
}
}
var shallowRenderer = ReactTestUtils.createRenderer();
shallowRenderer.render(<SomeComponent />);