diff --git a/.eslintrc.js b/.eslintrc.js
index 3938a6cfe531b..ac446e7258025 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -59,6 +59,6 @@ module.exports = {
},
globals: {
- expectDev: true,
+ spyOnDev: true,
},
};
diff --git a/package.json b/package.json
index 901af480d2aba..97d5ef1906bc5 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
"core-js": "^2.2.1",
"coveralls": "^2.11.6",
"create-react-class": "^15.6.2",
+ "cross-env": "^5.1.1",
"del": "^2.0.2",
"derequire": "^2.0.3",
"escape-string-regexp": "^1.0.5",
@@ -102,7 +103,8 @@
"linc": "node ./scripts/tasks/linc.js",
"lint": "node ./scripts/tasks/eslint.js",
"postinstall": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json",
- "test": "jest",
+ "test": "cross-env NODE_ENV=development jest",
+ "test-prod": "cross-env NODE_ENV=production jest",
"flow": "node ./scripts/tasks/flow.js",
"prettier": "node ./scripts/prettier/index.js write-changed",
"prettier-all": "node ./scripts/prettier/index.js write",
diff --git a/packages/react-dom/src/__tests__/CSSPropertyOperations-test.js b/packages/react-dom/src/__tests__/CSSPropertyOperations-test.js
index 81b3efe48f76a..10190db51ef9e 100644
--- a/packages/react-dom/src/__tests__/CSSPropertyOperations-test.js
+++ b/packages/react-dom/src/__tests__/CSSPropertyOperations-test.js
@@ -91,15 +91,17 @@ describe('CSSPropertyOperations', () => {
}
}
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var root = document.createElement('div');
ReactDOM.render(, root);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
- 'Warning: Unsupported style property background-color. Did you mean backgroundColor?' +
- '\n in div (at **)' +
- '\n in Comp (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
+ 'Warning: Unsupported style property background-color. Did you mean backgroundColor?' +
+ '\n in div (at **)' +
+ '\n in Comp (at **)',
+ );
+ }
});
it('should warn when updating hyphenated style names', () => {
@@ -111,7 +113,7 @@ describe('CSSPropertyOperations', () => {
}
}
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var styles = {
'-ms-transform': 'translate3d(0, 0, 0)',
'-webkit-transform': 'translate3d(0, 0, 0)',
@@ -120,17 +122,19 @@ describe('CSSPropertyOperations', () => {
ReactDOM.render(, root);
ReactDOM.render(, root);
- expectDev(console.error.calls.count()).toBe(2);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
- 'Warning: Unsupported style property -ms-transform. Did you mean msTransform?' +
- '\n in div (at **)' +
- '\n in Comp (at **)',
- );
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toEqual(
- 'Warning: Unsupported style property -webkit-transform. Did you mean WebkitTransform?' +
- '\n in div (at **)' +
- '\n in Comp (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(2);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
+ 'Warning: Unsupported style property -ms-transform. Did you mean msTransform?' +
+ '\n in div (at **)' +
+ '\n in Comp (at **)',
+ );
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toEqual(
+ 'Warning: Unsupported style property -webkit-transform. Did you mean WebkitTransform?' +
+ '\n in div (at **)' +
+ '\n in Comp (at **)',
+ );
+ }
});
it('warns when miscapitalizing vendored style names', () => {
@@ -150,23 +154,25 @@ describe('CSSPropertyOperations', () => {
}
}
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var root = document.createElement('div');
ReactDOM.render(, root);
- // msTransform is correct already and shouldn't warn
- expectDev(console.error.calls.count()).toBe(2);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
- 'Warning: Unsupported vendor-prefixed style property oTransform. ' +
- 'Did you mean OTransform?' +
- '\n in div (at **)' +
- '\n in Comp (at **)',
- );
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toEqual(
- 'Warning: Unsupported vendor-prefixed style property webkitTransform. ' +
- 'Did you mean WebkitTransform?' +
- '\n in div (at **)' +
- '\n in Comp (at **)',
- );
+ if (__DEV__) {
+ // msTransform is correct already and shouldn't warn
+ expect(console.error.calls.count()).toBe(2);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
+ 'Warning: Unsupported vendor-prefixed style property oTransform. ' +
+ 'Did you mean OTransform?' +
+ '\n in div (at **)' +
+ '\n in Comp (at **)',
+ );
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toEqual(
+ 'Warning: Unsupported vendor-prefixed style property webkitTransform. ' +
+ 'Did you mean WebkitTransform?' +
+ '\n in div (at **)' +
+ '\n in Comp (at **)',
+ );
+ }
});
it('should warn about style having a trailing semicolon', () => {
@@ -187,22 +193,24 @@ describe('CSSPropertyOperations', () => {
}
}
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var root = document.createElement('div');
ReactDOM.render(, root);
- expectDev(console.error.calls.count()).toBe(2);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
- "Warning: Style property values shouldn't contain a semicolon. " +
- 'Try "backgroundColor: blue" instead.' +
- '\n in div (at **)' +
- '\n in Comp (at **)',
- );
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toEqual(
- "Warning: Style property values shouldn't contain a semicolon. " +
- 'Try "color: red" instead.' +
- '\n in div (at **)' +
- '\n in Comp (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(2);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
+ "Warning: Style property values shouldn't contain a semicolon. " +
+ 'Try "backgroundColor: blue" instead.' +
+ '\n in div (at **)' +
+ '\n in Comp (at **)',
+ );
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toEqual(
+ "Warning: Style property values shouldn't contain a semicolon. " +
+ 'Try "color: red" instead.' +
+ '\n in div (at **)' +
+ '\n in Comp (at **)',
+ );
+ }
});
it('should warn about style containing a NaN value', () => {
@@ -214,16 +222,18 @@ describe('CSSPropertyOperations', () => {
}
}
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var root = document.createElement('div');
ReactDOM.render(, root);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
- 'Warning: `NaN` is an invalid value for the `fontSize` css style property.' +
- '\n in div (at **)' +
- '\n in Comp (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
+ 'Warning: `NaN` is an invalid value for the `fontSize` css style property.' +
+ '\n in div (at **)' +
+ '\n in Comp (at **)',
+ );
+ }
});
it('should not warn when setting CSS custom properties', () => {
@@ -246,16 +256,18 @@ describe('CSSPropertyOperations', () => {
}
}
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var root = document.createElement('div');
ReactDOM.render(, root);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
- 'Warning: `Infinity` is an invalid value for the `fontSize` css style property.' +
- '\n in div (at **)' +
- '\n in Comp (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
+ 'Warning: `Infinity` is an invalid value for the `fontSize` css style property.' +
+ '\n in div (at **)' +
+ '\n in Comp (at **)',
+ );
+ }
});
it('should not add units to CSS custom properties', () => {
diff --git a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js
index 7f544506a5f35..343adc05318d5 100644
--- a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js
+++ b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js
@@ -151,7 +151,7 @@ describe('DOMPropertyOperations', () => {
it('should not remove attributes for special properties', () => {
var container = document.createElement('div');
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
ReactDOM.render(
,
container,
@@ -164,10 +164,12 @@ describe('DOMPropertyOperations', () => {
);
expect(container.firstChild.getAttribute('value')).toBe('foo');
expect(container.firstChild.value).toBe('foo');
- expect(console.error.calls.count()).toBe(1);
- expect(console.error.calls.argsFor(0)[0]).toContain(
- 'A component is changing a controlled input of type text to be uncontrolled',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'A component is changing a controlled input of type text to be uncontrolled',
+ );
+ }
});
});
});
diff --git a/packages/react-dom/src/__tests__/EventPluginHub-test.js b/packages/react-dom/src/__tests__/EventPluginHub-test.js
index eaf40602ab6b6..ec1f83d0ee821 100644
--- a/packages/react-dom/src/__tests__/EventPluginHub-test.js
+++ b/packages/react-dom/src/__tests__/EventPluginHub-test.js
@@ -22,7 +22,7 @@ describe('EventPluginHub', () => {
});
it('should prevent non-function listeners, at dispatch', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var node = ReactTestUtils.renderIntoDocument(
,
);
@@ -31,10 +31,12 @@ describe('EventPluginHub', () => {
}).toThrowError(
'Expected `onClick` listener to be a function, instead got a value of `string` type.',
);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Expected `onClick` listener to be a function, instead got a value of `string` type.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Expected `onClick` listener to be a function, instead got a value of `string` type.',
+ );
+ }
});
it('should not prevent null listeners, at dispatch', () => {
diff --git a/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.js b/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.js
index 647109a907b3d..cd4bff6102660 100644
--- a/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.js
+++ b/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.js
@@ -285,13 +285,15 @@ describe('ReactBrowserEventEmitter', () => {
putListener(CHILD, ON_CLICK_KEY, recordIDAndReturnFalse.bind(null, CHILD));
putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, PARENT));
putListener(GRANDPARENT, ON_CLICK_KEY, recordID.bind(null, GRANDPARENT));
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
ReactTestUtils.Simulate.click(CHILD);
expect(idCallOrder.length).toBe(3);
expect(idCallOrder[0]).toBe(CHILD);
expect(idCallOrder[1]).toBe(PARENT);
expect(idCallOrder[2]).toBe(GRANDPARENT);
- expectDev(console.error.calls.count()).toEqual(0);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toEqual(0);
+ }
});
/**
diff --git a/packages/react-dom/src/__tests__/ReactChildReconciler-test.js b/packages/react-dom/src/__tests__/ReactChildReconciler-test.js
index 09fa3d436e124..9bbf9176cf69a 100644
--- a/packages/react-dom/src/__tests__/ReactChildReconciler-test.js
+++ b/packages/react-dom/src/__tests__/ReactChildReconciler-test.js
@@ -46,7 +46,7 @@ describe('ReactChildReconciler', () => {
}
it('warns for duplicated array keys', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
render() {
@@ -56,17 +56,19 @@ describe('ReactChildReconciler', () => {
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Keys should be unique so that components maintain their identity ' +
- 'across updates. Non-unique keys may cause children to be ' +
- 'duplicated and/or omitted — the behavior is unsupported and ' +
- 'could change in a future version.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Keys should be unique so that components maintain their identity ' +
+ 'across updates. Non-unique keys may cause children to be ' +
+ 'duplicated and/or omitted — the behavior is unsupported and ' +
+ 'could change in a future version.',
+ );
+ }
});
it('warns for duplicated array keys with component stack info', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
render() {
@@ -88,24 +90,24 @@ describe('ReactChildReconciler', () => {
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(
- normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]),
- ).toContain(
- 'Encountered two children with the same key, `1`. ' +
- 'Keys should be unique so that components maintain their identity ' +
- 'across updates. Non-unique keys may cause children to be ' +
- 'duplicated and/or omitted — the behavior is unsupported and ' +
- 'could change in a future version.',
- ' in div (at **)\n' +
- ' in Component (at **)\n' +
- ' in Parent (at **)\n' +
- ' in GrandParent (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toContain(
+ 'Encountered two children with the same key, `1`. ' +
+ 'Keys should be unique so that components maintain their identity ' +
+ 'across updates. Non-unique keys may cause children to be ' +
+ 'duplicated and/or omitted — the behavior is unsupported and ' +
+ 'could change in a future version.',
+ ' in div (at **)\n' +
+ ' in Component (at **)\n' +
+ ' in Parent (at **)\n' +
+ ' in GrandParent (at **)',
+ );
+ }
});
it('warns for duplicated iterable keys', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
render() {
@@ -115,17 +117,19 @@ describe('ReactChildReconciler', () => {
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Keys should be unique so that components maintain their identity ' +
- 'across updates. Non-unique keys may cause children to be ' +
- 'duplicated and/or omitted — the behavior is unsupported and ' +
- 'could change in a future version.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Keys should be unique so that components maintain their identity ' +
+ 'across updates. Non-unique keys may cause children to be ' +
+ 'duplicated and/or omitted — the behavior is unsupported and ' +
+ 'could change in a future version.',
+ );
+ }
});
it('warns for duplicated iterable keys with component stack info', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
render() {
@@ -147,19 +151,19 @@ describe('ReactChildReconciler', () => {
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(
- normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]),
- ).toContain(
- 'Encountered two children with the same key, `1`. ' +
- 'Keys should be unique so that components maintain their identity ' +
- 'across updates. Non-unique keys may cause children to be ' +
- 'duplicated and/or omitted — the behavior is unsupported and ' +
- 'could change in a future version.',
- ' in div (at **)\n' +
- ' in Component (at **)\n' +
- ' in Parent (at **)\n' +
- ' in GrandParent (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toContain(
+ 'Encountered two children with the same key, `1`. ' +
+ 'Keys should be unique so that components maintain their identity ' +
+ 'across updates. Non-unique keys may cause children to be ' +
+ 'duplicated and/or omitted — the behavior is unsupported and ' +
+ 'could change in a future version.',
+ ' in div (at **)\n' +
+ ' in Component (at **)\n' +
+ ' in Parent (at **)\n' +
+ ' in GrandParent (at **)',
+ );
+ }
});
});
diff --git a/packages/react-dom/src/__tests__/ReactComponent-test.js b/packages/react-dom/src/__tests__/ReactComponent-test.js
index 0a63915429c2a..1f7da05821317 100644
--- a/packages/react-dom/src/__tests__/ReactComponent-test.js
+++ b/packages/react-dom/src/__tests__/ReactComponent-test.js
@@ -45,13 +45,23 @@ describe('ReactComponent', () => {
}).toThrow();
});
- it('should warn when children are mutated during render', () => {
- spyOn(console, 'error');
+ it('should throw (in dev) when children are mutated during render', () => {
+ spyOnDev(console, 'error');
function Wrapper(props) {
props.children[1] = ; // Mutation is illegal
return
{props.children}
;
}
- expect(() => {
+ if (__DEV__) {
+ expect(() => {
+ ReactTestUtils.renderIntoDocument(
+
+
+
+
+ ,
+ );
+ }).toThrowError(/Cannot assign to read only property.*/);
+ } else {
ReactTestUtils.renderIntoDocument(
@@ -59,11 +69,11 @@ describe('ReactComponent', () => {
,
);
- }).toThrowError(/Cannot assign to read only property.*/);
+ }
});
- it('should warn when children are mutated during update', () => {
- spyOn(console, 'error');
+ it('should throw (in dev) when children are mutated during update', () => {
+ spyOnDev(console, 'error');
class Wrapper extends React.Component {
componentDidMount() {
@@ -76,7 +86,17 @@ describe('ReactComponent', () => {
}
}
- expect(() => {
+ if (__DEV__) {
+ expect(() => {
+ ReactTestUtils.renderIntoDocument(
+
+
+
+
+ ,
+ );
+ }).toThrowError(/Cannot assign to read only property.*/);
+ } else {
ReactTestUtils.renderIntoDocument(
@@ -84,7 +104,7 @@ describe('ReactComponent', () => {
,
);
- }).toThrowError(/Cannot assign to read only property.*/);
+ }
});
it('should support refs on owned components', () => {
@@ -335,14 +355,16 @@ describe('ReactComponent', () => {
});
it('throws usefully when rendering badly-typed elements', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var X = undefined;
expect(() => ReactTestUtils.renderIntoDocument()).toThrowError(
'Element type is invalid: expected a string (for built-in components) ' +
- 'or a class/function (for composite components) but got: undefined. ' +
- "You likely forgot to export your component from the file it's " +
- 'defined in, or you might have mixed up default and named imports.',
+ 'or a class/function (for composite components) but got: undefined.' +
+ (__DEV__
+ ? " You likely forgot to export your component from the file it's " +
+ 'defined in, or you might have mixed up default and named imports.'
+ : ''),
);
var Y = null;
@@ -351,12 +373,14 @@ describe('ReactComponent', () => {
'or a class/function (for composite components) but got: null.',
);
- // One warning for each element creation
- expectDev(console.error.calls.count()).toBe(2);
+ if (__DEV__) {
+ // One warning for each element creation
+ expect(console.error.calls.count()).toBe(2);
+ }
});
it('includes owner name in the error about badly-typed elements', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var X = undefined;
@@ -378,14 +402,18 @@ describe('ReactComponent', () => {
expect(() => ReactTestUtils.renderIntoDocument()).toThrowError(
'Element type is invalid: expected a string (for built-in components) ' +
- 'or a class/function (for composite components) but got: undefined. ' +
- "You likely forgot to export your component from the file it's " +
- 'defined in, or you might have mixed up default and named imports.' +
- '\n\nCheck the render method of `Bar`.',
+ 'or a class/function (for composite components) but got: undefined.' +
+ (__DEV__
+ ? " You likely forgot to export your component from the file it's " +
+ 'defined in, or you might have mixed up default and named imports.' +
+ '\n\nCheck the render method of `Bar`.'
+ : ''),
);
- // One warning for each element creation
- expectDev(console.error.calls.count()).toBe(1);
+ if (__DEV__) {
+ // One warning for each element creation
+ expect(console.error.calls.count()).toBe(1);
+ }
});
it('throws if a plain object is used as a child', () => {
@@ -404,10 +432,12 @@ describe('ReactComponent', () => {
}
expect(ex).toBeDefined();
expect(normalizeCodeLocInfo(ex.message)).toBe(
- '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.' +
- '\n in div (at **)',
+ 'Objects are not valid as a React child (found: object with keys {x, y, z}).' +
+ (__DEV__
+ ? ' If you meant to render a collection of children, use ' +
+ 'an array instead.' +
+ '\n in div (at **)'
+ : ''),
);
});
@@ -431,11 +461,13 @@ describe('ReactComponent', () => {
}
expect(ex).toBeDefined();
expect(normalizeCodeLocInfo(ex.message)).toBe(
- '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' +
- ' in div (at **)\n' +
- ' in Foo (at **)',
+ 'Objects are not valid as a React child (found: object with keys {a, b, c}).' +
+ (__DEV__
+ ? ' If you meant to render a collection of children, use ' +
+ 'an array instead.\n' +
+ ' in div (at **)\n' +
+ ' in Foo (at **)'
+ : ''),
);
});
@@ -454,10 +486,12 @@ describe('ReactComponent', () => {
}
expect(ex).toBeDefined();
expect(normalizeCodeLocInfo(ex.message)).toBe(
- '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.' +
- '\n in div (at **)',
+ 'Objects are not valid as a React child (found: object with keys {x, y, z}).' +
+ (__DEV__
+ ? ' If you meant to render a collection of children, use ' +
+ 'an array instead.' +
+ '\n in div (at **)'
+ : ''),
);
});
@@ -481,11 +515,13 @@ describe('ReactComponent', () => {
}
expect(ex).toBeDefined();
expect(normalizeCodeLocInfo(ex.message)).toBe(
- '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' +
- ' in div (at **)\n' +
- ' in Foo (at **)',
+ 'Objects are not valid as a React child (found: object with keys {a, b, c}).' +
+ (__DEV__
+ ? ' If you meant to render a collection of children, use ' +
+ 'an array instead.\n' +
+ ' in div (at **)\n' +
+ ' in Foo (at **)'
+ : ''),
);
});
@@ -494,16 +530,18 @@ describe('ReactComponent', () => {
function Foo() {
return Foo;
}
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(, container);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in Foo (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in Foo (at **)',
+ );
+ }
});
it('warns on function as a return value from a class', () => {
@@ -512,16 +550,18 @@ describe('ReactComponent', () => {
return Foo;
}
}
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(, container);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in Foo (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in Foo (at **)',
+ );
+ }
});
it('warns on function as a child to host component', () => {
@@ -532,18 +572,20 @@ describe('ReactComponent', () => {
);
}
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(, container);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in span (at **)\n' +
- ' in div (at **)\n' +
- ' in Foo (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in span (at **)\n' +
+ ' in div (at **)\n' +
+ ' in Foo (at **)',
+ );
+ }
});
it('does not warn for function-as-a-child that gets resolved', () => {
@@ -553,15 +595,13 @@ describe('ReactComponent', () => {
function Foo() {
return {() => 'Hello'};
}
- spyOn(console, 'error');
var container = document.createElement('div');
ReactDOM.render(, container);
expect(container.innerHTML).toBe('Hello');
- expectDev(console.error.calls.count()).toBe(0);
});
it('deduplicates function type warnings based on component type', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Foo extends React.PureComponent {
constructor() {
super();
@@ -583,22 +623,24 @@ describe('ReactComponent', () => {
var container = document.createElement('div');
var component = ReactDOM.render(, container);
component.setState({type: 'portobello mushrooms'});
- expectDev(console.error.calls.count()).toBe(2);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in div (at **)\n' +
- ' in Foo (at **)',
- );
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
- 'Warning: Functions are not valid as a React child. This may happen if ' +
- 'you return a Component instead of from render. ' +
- 'Or maybe you meant to call this function rather than return it.\n' +
- ' in span (at **)\n' +
- ' in div (at **)\n' +
- ' in Foo (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(2);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in div (at **)\n' +
+ ' in Foo (at **)',
+ );
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
+ 'Warning: Functions are not valid as a React child. This may happen if ' +
+ 'you return a Component instead of from render. ' +
+ 'Or maybe you meant to call this function rather than return it.\n' +
+ ' in span (at **)\n' +
+ ' in div (at **)\n' +
+ ' in Foo (at **)',
+ );
+ }
});
});
});
diff --git a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
index 66eaecbcf2e57..4da75f8629121 100644
--- a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
+++ b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
@@ -198,7 +198,7 @@ describe('ReactComponentLifeCycle', () => {
});
it('should not allow update state inside of getInitialState', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class StatefulComponent extends React.Component {
constructor(props, context) {
@@ -214,21 +214,25 @@ describe('ReactComponentLifeCycle', () => {
}
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: setState(...): Can only update a mounted or ' +
- 'mounting component. This usually means you called setState() on an ' +
- 'unmounted component. This is a no-op.\n\nPlease check the code for the ' +
- 'StatefulComponent component.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toBe(
+ 'Warning: setState(...): Can only update a mounted or ' +
+ 'mounting component. This usually means you called setState() on an ' +
+ 'unmounted component. This is a no-op.\n\nPlease check the code for the ' +
+ 'StatefulComponent component.',
+ );
+ }
// Check deduplication
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ }
});
it('should correctly determine if a component is mounted', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
_isMounted() {
// No longer a public API, but we can test that it works internally by
@@ -252,14 +256,16 @@ describe('ReactComponentLifeCycle', () => {
var instance = ReactTestUtils.renderIntoDocument(element);
expect(instance._isMounted()).toBeTruthy();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Component is accessing isMounted inside its render()',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Component is accessing isMounted inside its render()',
+ );
+ }
});
it('should correctly determine if a null component is mounted', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
_isMounted() {
// No longer a public API, but we can test that it works internally by
@@ -283,10 +289,12 @@ describe('ReactComponentLifeCycle', () => {
var instance = ReactTestUtils.renderIntoDocument(element);
expect(instance._isMounted()).toBeTruthy();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Component is accessing isMounted inside its render()',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Component is accessing isMounted inside its render()',
+ );
+ }
});
it('isMounted should return false when unmounted', () => {
@@ -309,7 +317,7 @@ describe('ReactComponentLifeCycle', () => {
});
it('warns if findDOMNode is used inside render', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
state = {isMounted: false};
componentDidMount() {
@@ -324,14 +332,16 @@ describe('ReactComponentLifeCycle', () => {
}
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Component is accessing findDOMNode inside its render()',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Component is accessing findDOMNode inside its render()',
+ );
+ }
});
it('should carry through each of the phases of setup', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class LifeCycleComponent extends React.Component {
constructor(props, context) {
@@ -440,10 +450,12 @@ describe('ReactComponentLifeCycle', () => {
expect(getLifeCycleState(instance)).toBe('UNMOUNTED');
expect(instance.state).toEqual(POST_WILL_UNMOUNT_STATE);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'LifeCycleComponent is accessing isMounted inside its render() function',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'LifeCycleComponent is accessing isMounted inside its render() function',
+ );
+ }
});
it('should not throw when updating an auxiliary component', () => {
diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js
index 17b54543fdf02..5797e4b942934 100644
--- a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js
+++ b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js
@@ -122,26 +122,29 @@ describe('ReactCompositeComponent', () => {
}
}
- spyOn(console, 'warn');
+ spyOnDev(console, 'warn');
var markup = ReactDOMServer.renderToString();
// Old API based on heuristic
var container = document.createElement('div');
container.innerHTML = markup;
ReactDOM.render(, container);
- expectDev(console.warn.calls.count()).toBe(1);
- expectDev(console.warn.calls.argsFor(0)[0]).toContain(
- 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' +
- 'will stop working in React v17. Replace the ReactDOM.render() call ' +
- 'with ReactDOM.hydrate() if you want React to attach to the server HTML.',
- );
-
+ if (__DEV__) {
+ expect(console.warn.calls.count()).toBe(1);
+ expect(console.warn.calls.argsFor(0)[0]).toContain(
+ 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' +
+ 'will stop working in React v17. Replace the ReactDOM.render() call ' +
+ 'with ReactDOM.hydrate() if you want React to attach to the server HTML.',
+ );
+ console.warn.calls.reset();
+ }
// New explicit API
- console.warn.calls.reset();
container = document.createElement('div');
container.innerHTML = markup;
ReactDOM.hydrate(, container);
- expectDev(console.warn.calls.count()).toBe(0);
+ if (__DEV__) {
+ expect(console.warn.calls.count()).toBe(0);
+ }
});
it('should react to state changes from callbacks', () => {
@@ -231,7 +234,7 @@ describe('ReactCompositeComponent', () => {
});
it('should warn about `forceUpdate` on unmounted components', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
document.body.appendChild(container);
@@ -248,25 +251,31 @@ describe('ReactCompositeComponent', () => {
instance = ReactDOM.render(instance, container);
instance.forceUpdate();
- expectDev(console.error.calls.count()).toBe(0);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(0);
+ }
ReactDOM.unmountComponentAtNode(container);
instance.forceUpdate();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Can only update a mounted or mounting component. This usually means ' +
- 'you called setState, replaceState, or forceUpdate on an unmounted ' +
- 'component. This is a no-op.\n\nPlease check the code for the ' +
- 'Component component.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Can only update a mounted or mounting component. This usually means ' +
+ 'you called setState, replaceState, or forceUpdate on an unmounted ' +
+ 'component. This is a no-op.\n\nPlease check the code for the ' +
+ 'Component component.',
+ );
+ }
instance.forceUpdate();
- expectDev(console.error.calls.count()).toBe(1);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ }
});
it('should warn about `setState` on unmounted components', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
document.body.appendChild(container);
@@ -291,7 +300,9 @@ describe('ReactCompositeComponent', () => {
instance.setState({value: 1});
- expectDev(console.error.calls.count()).toBe(0);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(0);
+ }
expect(renders).toBe(2);
@@ -300,13 +311,15 @@ describe('ReactCompositeComponent', () => {
expect(renders).toBe(2);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Can only update a mounted or mounting component. This usually means ' +
- 'you called setState, replaceState, or forceUpdate on an unmounted ' +
- 'component. This is a no-op.\n\nPlease check the code for the ' +
- 'Component component.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Can only update a mounted or mounting component. This usually means ' +
+ 'you called setState, replaceState, or forceUpdate on an unmounted ' +
+ 'component. This is a no-op.\n\nPlease check the code for the ' +
+ 'Component component.',
+ );
+ }
});
it('should silently allow `setState`, not call cb on unmounting components', () => {
@@ -338,27 +351,31 @@ describe('ReactCompositeComponent', () => {
});
it('should warn when rendering a class with a render method that does not extend React.Component', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
class ClassWithRenderNotExtended {
render() {
return ;
}
}
- expectDev(console.error.calls.count()).toBe(0);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(0);
+ }
expect(() => {
ReactDOM.render(, container);
}).toThrow(TypeError);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Warning: The component appears to have a render method, ' +
- "but doesn't extend React.Component. This is likely to cause errors. " +
- 'Change ClassWithRenderNotExtended to extend React.Component instead.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Warning: The component appears to have a render method, ' +
+ "but doesn't extend React.Component. This is likely to cause errors. " +
+ 'Change ClassWithRenderNotExtended to extend React.Component instead.',
+ );
+ }
});
it('should warn about `setState` in render', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
@@ -378,17 +395,21 @@ describe('ReactCompositeComponent', () => {
}
}
- expectDev(console.error.calls.count()).toBe(0);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(0);
+ }
var instance = ReactDOM.render(, container);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Cannot update during an existing state transition (such as within ' +
- "`render` or another component's constructor). Render methods should " +
- 'be a pure function of props and state; constructor side-effects are ' +
- 'an anti-pattern, but can be moved to `componentWillMount`.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Cannot update during an existing state transition (such as within ' +
+ "`render` or another component's constructor). Render methods should " +
+ 'be a pure function of props and state; constructor side-effects are ' +
+ 'an anti-pattern, but can be moved to `componentWillMount`.',
+ );
+ }
// The setState call is queued and then executed as a second pass. This
// behavior is undefined though so we're free to change it to suit the
@@ -406,11 +427,13 @@ describe('ReactCompositeComponent', () => {
// Test deduplication
ReactDOM.unmountComponentAtNode(container);
ReactDOM.render(, container);
- expectDev(console.error.calls.count()).toBe(1);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ }
});
it('should warn about `setState` in getChildContext', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
@@ -432,19 +455,25 @@ describe('ReactCompositeComponent', () => {
}
Component.childContextTypes = {};
- expectDev(console.error.calls.count()).toBe(0);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(0);
+ }
var instance = ReactDOM.render(, container);
expect(renderPasses).toBe(2);
expect(instance.state.value).toBe(1);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: setState(...): Cannot call setState() inside getChildContext()',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toBe(
+ 'Warning: setState(...): Cannot call setState() inside getChildContext()',
+ );
+ }
// Test deduplication
ReactDOM.unmountComponentAtNode(container);
ReactDOM.render(, container);
- expectDev(console.error.calls.count()).toBe(1);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ }
});
it('should cleanup even if render() fatals', () => {
@@ -496,7 +525,7 @@ describe('ReactCompositeComponent', () => {
});
it('should warn when shouldComponentUpdate() returns undefined', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
state = {bogus: false};
@@ -513,15 +542,17 @@ describe('ReactCompositeComponent', () => {
var instance = ReactTestUtils.renderIntoDocument();
instance.setState({bogus: true});
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Component.shouldComponentUpdate(): Returned undefined instead of a ' +
- 'boolean value. Make sure to return true or false.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toBe(
+ 'Warning: Component.shouldComponentUpdate(): Returned undefined instead of a ' +
+ 'boolean value. Make sure to return true or false.',
+ );
+ }
});
it('should warn when componentDidUnmount method is defined', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
componentDidUnmount = () => {};
@@ -533,16 +564,18 @@ describe('ReactCompositeComponent', () => {
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Component has a method called ' +
- 'componentDidUnmount(). But there is no such lifecycle method. ' +
- 'Did you mean componentWillUnmount()?',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toBe(
+ 'Warning: Component has a method called ' +
+ 'componentDidUnmount(). But there is no such lifecycle method. ' +
+ 'Did you mean componentWillUnmount()?',
+ );
+ }
});
it('should warn when componentDidReceiveProps method is defined', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
componentDidReceiveProps = () => {};
@@ -554,18 +587,20 @@ describe('ReactCompositeComponent', () => {
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Component has a method called ' +
- 'componentDidReceiveProps(). But there is no such lifecycle method. ' +
- 'If you meant to update the state in response to changing props, ' +
- 'use componentWillReceiveProps(). If you meant to fetch data or ' +
- 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toBe(
+ 'Warning: Component has a method called ' +
+ 'componentDidReceiveProps(). But there is no such lifecycle method. ' +
+ 'If you meant to update the state in response to changing props, ' +
+ 'use componentWillReceiveProps(). If you meant to fetch data or ' +
+ 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().',
+ );
+ }
});
it('should warn when defaultProps was defined as an instance property', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Component extends React.Component {
constructor(props) {
@@ -580,11 +615,13 @@ describe('ReactCompositeComponent', () => {
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toBe(
- 'Warning: Setting defaultProps as an instance property on Component is not supported ' +
- 'and will be ignored. Instead, define defaultProps as a static property on Component.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toBe(
+ 'Warning: Setting defaultProps as an instance property on Component is not supported ' +
+ 'and will be ignored. Instead, define defaultProps as a static property on Component.',
+ );
+ }
});
it('should pass context to children when not owner', () => {
@@ -1056,7 +1093,7 @@ describe('ReactCompositeComponent', () => {
});
it('should disallow nested render calls', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class Inner extends React.Component {
render() {
@@ -1072,13 +1109,15 @@ describe('ReactCompositeComponent', () => {
}
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toMatch(
- 'Render methods should be a pure function of props and state; ' +
- 'triggering nested component updates from render is not allowed. If ' +
- 'necessary, trigger nested updates in componentDidUpdate.\n\nCheck the ' +
- 'render method of Outer.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toMatch(
+ 'Render methods should be a pure function of props and state; ' +
+ 'triggering nested component updates from render is not allowed. If ' +
+ 'necessary, trigger nested updates in componentDidUpdate.\n\nCheck the ' +
+ 'render method of Outer.',
+ );
+ }
});
it('only renders once if updated in componentWillReceiveProps', () => {
@@ -1353,7 +1392,7 @@ describe('ReactCompositeComponent', () => {
});
it('should warn when mutated props are passed', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
@@ -1368,15 +1407,19 @@ describe('ReactCompositeComponent', () => {
}
}
- expectDev(console.error.calls.count()).toBe(0);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(0);
+ }
ReactDOM.render(, container);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Foo(...): When calling super() in `Foo`, make sure to pass ' +
- "up the same props that your component's constructor was passed.",
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Foo(...): When calling super() in `Foo`, make sure to pass ' +
+ "up the same props that your component's constructor was passed.",
+ );
+ }
});
it('should only call componentWillUnmount once', () => {
@@ -1592,7 +1635,7 @@ describe('ReactCompositeComponent', () => {
});
it('should return a meaningful warning when constructor is returned', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class RenderTextInvalidConstructor extends React.Component {
constructor(props) {
super(props);
@@ -1608,25 +1651,29 @@ describe('ReactCompositeComponent', () => {
ReactTestUtils.renderIntoDocument();
}).toThrow();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.mostRecent().args[0]).toBe(
- 'Warning: RenderTextInvalidConstructor(...): No `render` method found on the returned component instance: ' +
- 'did you accidentally return an object from the constructor?',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.mostRecent().args[0]).toBe(
+ 'Warning: RenderTextInvalidConstructor(...): No `render` method found on the returned component instance: ' +
+ 'did you accidentally return an object from the constructor?',
+ );
+ }
});
it('should return error if render is not defined', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
class RenderTestUndefinedRender extends React.Component {}
expect(function() {
ReactTestUtils.renderIntoDocument();
}).toThrow();
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.mostRecent().args[0]).toBe(
- 'Warning: RenderTestUndefinedRender(...): No `render` method found on the returned ' +
- 'component instance: you may have forgotten to define `render`.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.mostRecent().args[0]).toBe(
+ 'Warning: RenderTestUndefinedRender(...): No `render` method found on the returned ' +
+ 'component instance: you may have forgotten to define `render`.',
+ );
+ }
});
});
diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js
index 93b4d9280e72d..131488a500e91 100644
--- a/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js
+++ b/packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js
@@ -381,7 +381,7 @@ describe('ReactCompositeComponent-state', () => {
});
it('should treat assigning to this.state inside cWRP as a replaceState, with a warning', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
let ops = [];
class Test extends React.Component {
@@ -416,20 +416,24 @@ describe('ReactCompositeComponent-state', () => {
'render -- step: 3, extra: false',
'callback -- step: 3, 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.',
- );
+ if (__DEV__) {
+ 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.',
+ );
+ }
// Check deduplication
ReactDOM.render(, container);
- expect(console.error.calls.count()).toEqual(1);
+ if (__DEV__) {
+ expect(console.error.calls.count()).toEqual(1);
+ }
});
it('should treat assigning to this.state inside cWM as a replaceState, with a warning', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
let ops = [];
class Test extends React.Component {
@@ -461,11 +465,13 @@ describe('ReactCompositeComponent-state', () => {
'render -- step: 3, extra: false',
'callback -- step: 3, extra: false',
]);
- expect(console.error.calls.count()).toEqual(1);
- expect(console.error.calls.argsFor(0)[0]).toEqual(
- 'Warning: Test.componentWillMount(): Assigning directly to ' +
- "this.state is deprecated (except inside a component's constructor). " +
- 'Use setState instead.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toEqual(1);
+ expect(console.error.calls.argsFor(0)[0]).toEqual(
+ 'Warning: Test.componentWillMount(): Assigning directly to ' +
+ "this.state is deprecated (except inside a component's constructor). " +
+ 'Use setState instead.',
+ );
+ }
});
});
diff --git a/packages/react-dom/src/__tests__/ReactDOM-test.js b/packages/react-dom/src/__tests__/ReactDOM-test.js
index 9caa898ff1c9b..dde2608bfa3bd 100644
--- a/packages/react-dom/src/__tests__/ReactDOM-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOM-test.js
@@ -109,7 +109,7 @@ describe('ReactDOM', () => {
});
it('throws in render() if the mount callback is not a function', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
function Foo() {
this.a = 1;
@@ -129,31 +129,37 @@ describe('ReactDOM', () => {
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: no',
);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'render(...): Expected the last optional `callback` argument to be ' +
- 'a function. Instead received: no.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'render(...): Expected the last optional `callback` argument to be ' +
+ 'a function. Instead received: no.',
+ );
+ }
expect(() => ReactDOM.render(, myDiv, {foo: 'bar'})).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: [object Object]',
);
- expectDev(console.error.calls.argsFor(1)[0]).toContain(
- 'render(...): Expected the last optional `callback` argument to be ' +
- 'a function. Instead received: [object Object].',
- );
+ if (__DEV__) {
+ expect(console.error.calls.argsFor(1)[0]).toContain(
+ 'render(...): Expected the last optional `callback` argument to be ' +
+ 'a function. Instead received: [object Object].',
+ );
+ }
expect(() => ReactDOM.render(, myDiv, new Foo())).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: [object Object]',
);
- expectDev(console.error.calls.argsFor(2)[0]).toContain(
- 'render(...): Expected the last optional `callback` argument to be ' +
- 'a function. Instead received: [object Object].',
- );
- expect(console.error.calls.count()).toBe(3);
+ if (__DEV__) {
+ expect(console.error.calls.argsFor(2)[0]).toContain(
+ 'render(...): Expected the last optional `callback` argument to be ' +
+ 'a function. Instead received: [object Object].',
+ );
+ expect(console.error.calls.count()).toBe(3);
+ }
});
it('throws in render() if the update callback is not a function', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
function Foo() {
this.a = 1;
@@ -174,29 +180,35 @@ describe('ReactDOM', () => {
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: no',
);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'render(...): Expected the last optional `callback` argument to be ' +
- 'a function. Instead received: no.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'render(...): Expected the last optional `callback` argument to be ' +
+ 'a function. Instead received: no.',
+ );
+ }
ReactDOM.render(, myDiv); // Re-mount
expect(() => ReactDOM.render(, myDiv, {foo: 'bar'})).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: [object Object]',
);
- expectDev(console.error.calls.argsFor(1)[0]).toContain(
- 'render(...): Expected the last optional `callback` argument to be ' +
- 'a function. Instead received: [object Object].',
- );
+ if (__DEV__) {
+ expect(console.error.calls.argsFor(1)[0]).toContain(
+ 'render(...): Expected the last optional `callback` argument to be ' +
+ 'a function. Instead received: [object Object].',
+ );
+ }
ReactDOM.render(, myDiv); // Re-mount
expect(() => ReactDOM.render(, myDiv, new Foo())).toThrowError(
'Invalid argument passed as callback. Expected a function. Instead ' +
'received: [object Object]',
);
- expectDev(console.error.calls.argsFor(2)[0]).toContain(
- 'render(...): Expected the last optional `callback` argument to be ' +
- 'a function. Instead received: [object Object].',
- );
- expect(console.error.calls.count()).toBe(3);
+ if (__DEV__) {
+ expect(console.error.calls.argsFor(2)[0]).toContain(
+ 'render(...): Expected the last optional `callback` argument to be ' +
+ 'a function. Instead received: [object Object].',
+ );
+ expect(console.error.calls.count()).toBe(3);
+ }
});
it('preserves focus', () => {
@@ -338,4 +350,26 @@ describe('ReactDOM', () => {
];
expect(actual).toEqual(expected);
});
+
+ it('should not crash with devtools installed', () => {
+ try {
+ global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
+ inject: function() {},
+ onCommitFiberRoot: function() {},
+ onCommitFiberUnmount: function() {},
+ supportsFiber: true,
+ };
+ jest.resetModules();
+ React = require('react');
+ ReactDOM = require('react-dom');
+ class Component extends React.Component {
+ render() {
+ return ;
+ }
+ }
+ ReactDOM.render(, document.createElement('container'));
+ } finally {
+ delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
+ }
+ });
});
diff --git a/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js b/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js
index 67589233e9652..fe2d647b7b292 100644
--- a/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js
@@ -46,20 +46,20 @@ describe('ReactDOM unknown attribute', () => {
});
it('changes values true, false to null, and also warns once', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
testUnknownAttributeAssignment(true, null);
testUnknownAttributeAssignment(false, null);
- expectDev(
- normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]),
- ).toMatch(
- 'Received `true` for a non-boolean attribute `unknown`.\n\n' +
- 'If you want to write it to the DOM, pass a string instead: ' +
- 'unknown="true" or unknown={value.toString()}.\n' +
- ' in div (at **)',
- );
- expectDev(console.error.calls.count()).toBe(1);
+ if (__DEV__) {
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toMatch(
+ 'Received `true` for a non-boolean attribute `unknown`.\n\n' +
+ 'If you want to write it to the DOM, pass a string instead: ' +
+ 'unknown="true" or unknown={value.toString()}.\n' +
+ ' in div (at **)',
+ );
+ expect(console.error.calls.count()).toBe(1);
+ }
});
it('removes unknown attributes that were rendered but are now missing', () => {
@@ -82,17 +82,17 @@ describe('ReactDOM unknown attribute', () => {
});
it('coerces NaN to strings and warns', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
testUnknownAttributeAssignment(NaN, 'NaN');
- expectDev(
- normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]),
- ).toMatch(
- 'Warning: Received NaN for the `unknown` attribute. ' +
- 'If this is expected, cast the value to a string.\n' +
- ' in div (at **)',
- );
- expectDev(console.error.calls.count()).toBe(1);
+ if (__DEV__) {
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toMatch(
+ 'Warning: Received NaN for the `unknown` attribute. ' +
+ 'If this is expected, cast the value to a string.\n' +
+ ' in div (at **)',
+ );
+ expect(console.error.calls.count()).toBe(1);
+ }
});
it('coerces objects to strings and warns', () => {
@@ -107,50 +107,54 @@ describe('ReactDOM unknown attribute', () => {
});
it('removes symbols and warns', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
testUnknownAttributeRemoval(Symbol('foo'));
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid value for prop `unknown` on
tag. Either remove it ' +
- 'from the element, or pass a string or number value to keep it ' +
- 'in the DOM. For details, see https://fb.me/react-attribute-behavior\n' +
- ' in div (at **)',
- );
- expectDev(console.error.calls.count()).toBe(1);
+ if (__DEV__) {
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Invalid value for prop `unknown` on
tag. Either remove it ' +
+ 'from the element, or pass a string or number value to keep it ' +
+ 'in the DOM. For details, see https://fb.me/react-attribute-behavior\n' +
+ ' in div (at **)',
+ );
+ expect(console.error.calls.count()).toBe(1);
+ }
});
it('removes functions and warns', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
testUnknownAttributeRemoval(function someFunction() {});
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid value for prop `unknown` on
tag. Either remove ' +
- 'it from the element, or pass a string or number value to ' +
- 'keep it in the DOM. For details, see ' +
- 'https://fb.me/react-attribute-behavior\n' +
- ' in div (at **)',
- );
- expectDev(console.error.calls.count()).toBe(1);
+ if (__DEV__) {
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Invalid value for prop `unknown` on
tag. Either remove ' +
+ 'it from the element, or pass a string or number value to ' +
+ 'keep it in the DOM. For details, see ' +
+ 'https://fb.me/react-attribute-behavior\n' +
+ ' in div (at **)',
+ );
+ expect(console.error.calls.count()).toBe(1);
+ }
});
it('allows camelCase unknown attributes and warns', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var el = document.createElement('div');
ReactDOM.render(, el);
expect(el.firstChild.getAttribute('helloworld')).toBe('something');
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(
- normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]),
- ).toMatch(
- 'React does not recognize the `helloWorld` prop on a DOM element. ' +
- 'If you intentionally want it to appear in the DOM as a custom ' +
- 'attribute, spell it as lowercase `helloworld` instead. ' +
- 'If you accidentally passed it from a parent component, remove ' +
- 'it from the DOM element.\n' +
- ' in div (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toMatch(
+ 'React does not recognize the `helloWorld` prop on a DOM element. ' +
+ 'If you intentionally want it to appear in the DOM as a custom ' +
+ 'attribute, spell it as lowercase `helloworld` instead. ' +
+ 'If you accidentally passed it from a parent component, remove ' +
+ 'it from the DOM element.\n' +
+ ' in div (at **)',
+ );
+ }
});
});
});
diff --git a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
index e9b1911952452..2c40743854c36 100644
--- a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
@@ -132,47 +132,55 @@ describe('ReactDOMComponent', () => {
}
ReactTestUtils.renderIntoDocument();
- expectDev(() => (style.position = 'absolute')).toThrow();
+ if (__DEV__) {
+ expect(() => (style.position = 'absolute')).toThrow();
+ }
});
it('should warn for unknown prop', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(
{}} />, container);
- expectDev(console.error.calls.count(0)).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid value for prop `foo` on
tag. Either remove it ' +
- 'from the element, or pass a string or number value to keep ' +
- 'it in the DOM. For details, see https://fb.me/react-attribute-behavior' +
- '\n in div (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count(0)).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Invalid value for prop `foo` on
tag. Either remove it ' +
+ 'from the element, or pass a string or number value to keep ' +
+ 'it in the DOM. For details, see https://fb.me/react-attribute-behavior' +
+ '\n in div (at **)',
+ );
+ }
});
it('should group multiple unknown prop warnings together', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(
{}} baz={() => {}} />, container);
- expectDev(console.error.calls.count(0)).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid values for props `foo`, `baz` on
tag. Either remove ' +
- 'them from the element, or pass a string or number value to keep ' +
- 'them in the DOM. For details, see https://fb.me/react-attribute-behavior' +
- '\n in div (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count(0)).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Invalid values for props `foo`, `baz` on
tag. Either remove ' +
+ 'them from the element, or pass a string or number value to keep ' +
+ 'them in the DOM. For details, see https://fb.me/react-attribute-behavior' +
+ '\n in div (at **)',
+ );
+ }
});
it('should warn for onDblClick prop', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(
{}} />, container);
- expectDev(console.error.calls.count(0)).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid event handler property `onDblClick`. Did you mean `onDoubleClick`?\n in div (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count(0)).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Invalid event handler property `onDblClick`. Did you mean `onDoubleClick`?\n in div (at **)',
+ );
+ }
});
it('should warn for unknown string event handlers', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(, container);
expect(container.firstChild.hasAttribute('onUnknown')).toBe(false);
@@ -183,20 +191,22 @@ describe('ReactDOMComponent', () => {
ReactDOM.render(, container);
expect(container.firstChild.hasAttribute('on-unknown')).toBe(false);
expect(container.firstChild['on-unknown']).toBe(undefined);
- expectDev(console.error.calls.count(0)).toBe(3);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Unknown event handler property `onUnknown`. It will be ignored.\n in div (at **)',
- );
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
- 'Warning: Unknown event handler property `onunknown`. It will be ignored.\n in div (at **)',
- );
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(2)[0])).toBe(
- 'Warning: Unknown event handler property `on-unknown`. It will be ignored.\n in div (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count(0)).toBe(3);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Unknown event handler property `onUnknown`. It will be ignored.\n in div (at **)',
+ );
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
+ 'Warning: Unknown event handler property `onunknown`. It will be ignored.\n in div (at **)',
+ );
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(2)[0])).toBe(
+ 'Warning: Unknown event handler property `on-unknown`. It will be ignored.\n in div (at **)',
+ );
+ }
});
it('should warn for unknown function event handlers', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(, container);
expect(container.firstChild.hasAttribute('onUnknown')).toBe(false);
@@ -207,32 +217,34 @@ describe('ReactDOMComponent', () => {
ReactDOM.render(, container);
expect(container.firstChild.hasAttribute('on-unknown')).toBe(false);
expect(container.firstChild['on-unknown']).toBe(undefined);
- expectDev(console.error.calls.count(0)).toBe(3);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Unknown event handler property `onUnknown`. It will be ignored.\n in div (at **)',
- );
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
- 'Warning: Unknown event handler property `onunknown`. It will be ignored.\n in div (at **)',
- );
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(2)[0])).toBe(
- 'Warning: Unknown event handler property `on-unknown`. It will be ignored.\n in div (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count(0)).toBe(3);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Unknown event handler property `onUnknown`. It will be ignored.\n in div (at **)',
+ );
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
+ 'Warning: Unknown event handler property `onunknown`. It will be ignored.\n in div (at **)',
+ );
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(2)[0])).toBe(
+ 'Warning: Unknown event handler property `on-unknown`. It will be ignored.\n in div (at **)',
+ );
+ }
});
it('should warn for badly cased React attributes', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(, container);
expect(container.firstChild.getAttribute('CHILDREN')).toBe('5');
- expectDev(console.error.calls.count(0)).toBe(1);
- expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
- 'Warning: Invalid DOM property `CHILDREN`. Did you mean `children`?\n in div (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count(0)).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
+ 'Warning: Invalid DOM property `CHILDREN`. Did you mean `children`?\n in div (at **)',
+ );
+ }
});
it('should not warn for "0" as a unitless style value', () => {
- spyOn(console, 'error');
-
class Component extends React.Component {
render() {
return ;
@@ -240,24 +252,23 @@ describe('ReactDOMComponent', () => {
}
ReactTestUtils.renderIntoDocument();
- expectDev(console.error.calls.count()).toBe(0);
});
it('should warn nicely about NaN in style', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var style = {fontSize: NaN};
var div = document.createElement('div');
ReactDOM.render(, div);
ReactDOM.render(, div);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(
- normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]),
- ).toEqual(
- 'Warning: `NaN` is an invalid value for the `fontSize` css style property.' +
- '\n in span (at **)',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toEqual(
+ 'Warning: `NaN` is an invalid value for the `fontSize` css style property.' +
+ '\n in span (at **)',
+ );
+ }
});
it('should update styles if initially null', () => {
@@ -445,7 +456,7 @@ describe('ReactDOMComponent', () => {
});
it('should reject attribute key injection attack on markup', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
for (var i = 0; i < 3; i++) {
var container = document.createElement('div');
var element = React.createElement(
@@ -455,14 +466,16 @@ describe('ReactDOMComponent', () => {
);
ReactDOM.render(element, container);
}
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toEqual(
- 'Warning: Invalid attribute name: `blah" onclick="beevil" noise="hi`',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toEqual(
+ 'Warning: Invalid attribute name: `blah" onclick="beevil" noise="hi`',
+ );
+ }
});
it('should reject attribute key injection attack on update', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
for (var i = 0; i < 3; i++) {
var container = document.createElement('div');
var beforeUpdate = React.createElement('x-foo-component', {}, null);
@@ -475,10 +488,12 @@ describe('ReactDOMComponent', () => {
);
ReactDOM.render(afterUpdate, container);
}
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toEqual(
- 'Warning: Invalid attribute name: `blah" onclick="beevil" noise="hi`',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toEqual(
+ 'Warning: Invalid attribute name: `blah" onclick="beevil" noise="hi`',
+ );
+ }
});
it('should update arbitrary attributes for tags containing dashes', () => {
@@ -723,15 +738,17 @@ describe('ReactDOMComponent', () => {
});
it('should warn about non-string "is" attribute', () => {
- spyOn(console, 'error');
+ spyOnDev(console, 'error');
var container = document.createElement('div');
ReactDOM.render(, container);
- expectDev(console.error.calls.count()).toBe(1);
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
- 'Received a `function` for a string attribute `is`. If this is expected, cast ' +
- 'the value to a string.',
- );
+ if (__DEV__) {
+ expect(console.error.calls.count()).toBe(1);
+ expect(console.error.calls.argsFor(0)[0]).toContain(
+ 'Received a `function` for a string attribute `is`. If this is expected, cast ' +
+ 'the value to a string.',
+ );
+ }
});
it('should not update when switching between null/undefined', () => {
@@ -860,14 +877,14 @@ describe('ReactDOMComponent', () => {
});
it('should work error event on