Merge pull request #4223 from spicyj/check-no-warn

Fail tests on any un-spied warnings
This commit is contained in:
Ben Alpert 2015-06-29 07:57:56 -07:00
commit 454d47fa09
7 changed files with 60 additions and 47 deletions

View File

@ -311,13 +311,12 @@ describe('ReactTypeScriptClass', function() {
}); });
it('throws if no render function is defined', function() { it('throws if no render function is defined', function() {
var warn = jest.genMockFn(); spyOn(console, 'error');
console.error = warn;
expect(() => React.render(React.createElement(Empty), container)).toThrow(); expect(() => React.render(React.createElement(Empty), container)).toThrow();
expect(warn.mock.calls.length).toBe(1); expect((<any>console.error).argsForCall.length).toBe(1);
expect(warn.mock.calls[0][0]).toBe( expect((<any>console.error).argsForCall[0][0]).toBe(
'Warning: Empty(...): ' + 'Warning: Empty(...): ' +
'No `render` method found on the returned component instance: you may ' + 'No `render` method found on the returned component instance: you may ' +
'have forgotten to define `render` in your component or you may have ' + 'have forgotten to define `render` in your component or you may have ' +
@ -434,38 +433,36 @@ describe('ReactTypeScriptClass', function() {
it('warns when classic properties are defined on the instance, ' + it('warns when classic properties are defined on the instance, ' +
'but does not invoke them.', function() { 'but does not invoke them.', function() {
var warn = jest.genMockFn(); spyOn(console, 'error');
console.error = warn;
getInitialStateWasCalled = false; getInitialStateWasCalled = false;
getDefaultPropsWasCalled = false; getDefaultPropsWasCalled = false;
test(React.createElement(ClassicProperties), 'SPAN', 'foo'); test(React.createElement(ClassicProperties), 'SPAN', 'foo');
expect(getInitialStateWasCalled).toBe(false); expect(getInitialStateWasCalled).toBe(false);
expect(getDefaultPropsWasCalled).toBe(false); expect(getDefaultPropsWasCalled).toBe(false);
expect(warn.mock.calls.length).toBe(4); expect((<any>console.error).argsForCall.length).toBe(4);
expect(warn.mock.calls[0][0]).toContain( expect((<any>console.error).argsForCall[0][0]).toContain(
'getInitialState was defined on ClassicProperties, ' + 'getInitialState was defined on ClassicProperties, ' +
'a plain JavaScript class.' 'a plain JavaScript class.'
); );
expect(warn.mock.calls[1][0]).toContain( expect((<any>console.error).argsForCall[1][0]).toContain(
'getDefaultProps was defined on ClassicProperties, ' + 'getDefaultProps was defined on ClassicProperties, ' +
'a plain JavaScript class.' 'a plain JavaScript class.'
); );
expect(warn.mock.calls[2][0]).toContain( expect((<any>console.error).argsForCall[2][0]).toContain(
'propTypes was defined as an instance property on ClassicProperties.' 'propTypes was defined as an instance property on ClassicProperties.'
); );
expect(warn.mock.calls[3][0]).toContain( expect((<any>console.error).argsForCall[3][0]).toContain(
'contextTypes was defined as an instance property on ClassicProperties.' 'contextTypes was defined as an instance property on ClassicProperties.'
); );
}); });
it('should warn when misspelling shouldComponentUpdate', function() { it('should warn when misspelling shouldComponentUpdate', function() {
var warn = jest.genMockFn(); spyOn(console, 'error');
console.error = warn;
test(React.createElement(MisspelledComponent1), 'SPAN', 'foo'); test(React.createElement(MisspelledComponent1), 'SPAN', 'foo');
expect(warn.mock.calls.length).toBe(1); expect((<any>console.error).argsForCall.length).toBe(1);
expect(warn.mock.calls[0][0]).toBe( expect((<any>console.error).argsForCall[0][0]).toBe(
'Warning: ' + 'Warning: ' +
'MisspelledComponent1 has a method called componentShouldUpdate(). Did ' + 'MisspelledComponent1 has a method called componentShouldUpdate(). Did ' +
'you mean shouldComponentUpdate()? The name is phrased as a question ' + 'you mean shouldComponentUpdate()? The name is phrased as a question ' +
@ -474,13 +471,12 @@ describe('ReactTypeScriptClass', function() {
}); });
it('should warn when misspelling componentWillReceiveProps', function() { it('should warn when misspelling componentWillReceiveProps', function() {
var warn = jest.genMockFn(); spyOn(console, 'error');
console.error = warn;
test(React.createElement(MisspelledComponent2), 'SPAN', 'foo'); test(React.createElement(MisspelledComponent2), 'SPAN', 'foo');
expect(warn.mock.calls.length).toBe(1); expect((<any>console.error).argsForCall.length).toBe(1);
expect(warn.mock.calls[0][0]).toBe( expect((<any>console.error).argsForCall[0][0]).toBe(
'Warning: ' + 'Warning: ' +
'MisspelledComponent2 has a method called componentWillRecieveProps(). ' + 'MisspelledComponent2 has a method called componentWillRecieveProps(). ' +
'Did you mean componentWillReceiveProps()?' 'Did you mean componentWillReceiveProps()?'
@ -488,8 +484,7 @@ describe('ReactTypeScriptClass', function() {
}); });
it('should throw AND warn when trying to access classic APIs', function() { it('should throw AND warn when trying to access classic APIs', function() {
var warn = jest.genMockFn(); spyOn(console, 'error');
console.error = warn;
var instance = test( var instance = test(
React.createElement(Inner, {name: 'foo'}), React.createElement(Inner, {name: 'foo'}),
'DIV','foo' 'DIV','foo'
@ -499,20 +494,20 @@ describe('ReactTypeScriptClass', function() {
expect(() => instance.isMounted()).toThrow(); expect(() => instance.isMounted()).toThrow();
expect(() => instance.setProps({ name: 'bar' })).toThrow(); expect(() => instance.setProps({ name: 'bar' })).toThrow();
expect(() => instance.replaceProps({ name: 'bar' })).toThrow(); expect(() => instance.replaceProps({ name: 'bar' })).toThrow();
expect(warn.mock.calls.length).toBe(5); expect((<any>console.error).argsForCall.length).toBe(5);
expect(warn.mock.calls[0][0]).toContain( expect((<any>console.error).argsForCall[0][0]).toContain(
'getDOMNode(...) is deprecated in plain JavaScript React classes' 'getDOMNode(...) is deprecated in plain JavaScript React classes'
); );
expect(warn.mock.calls[1][0]).toContain( expect((<any>console.error).argsForCall[1][0]).toContain(
'replaceState(...) is deprecated in plain JavaScript React classes' 'replaceState(...) is deprecated in plain JavaScript React classes'
); );
expect(warn.mock.calls[2][0]).toContain( expect((<any>console.error).argsForCall[2][0]).toContain(
'isMounted(...) is deprecated in plain JavaScript React classes' 'isMounted(...) is deprecated in plain JavaScript React classes'
); );
expect(warn.mock.calls[3][0]).toContain( expect((<any>console.error).argsForCall[3][0]).toContain(
'setProps(...) is deprecated in plain JavaScript React classes' 'setProps(...) is deprecated in plain JavaScript React classes'
); );
expect(warn.mock.calls[4][0]).toContain( expect((<any>console.error).argsForCall[4][0]).toContain(
'replaceProps(...) is deprecated in plain JavaScript React classes' 'replaceProps(...) is deprecated in plain JavaScript React classes'
); );
}); });

View File

@ -124,24 +124,23 @@ describe('ReactMount', function() {
var container = document.createElement('container'); var container = document.createElement('container');
container.innerHTML = React.renderToString(<div />) + ' '; container.innerHTML = React.renderToString(<div />) + ' ';
console.error = mocks.getMockFunction(); spyOn(console, 'error');
ReactMount.render(<div />, container); ReactMount.render(<div />, container);
expect(console.error.mock.calls.length).toBe(1); expect(console.error.calls.length).toBe(1);
container.innerHTML = ' ' + React.renderToString(<div />); container.innerHTML = ' ' + React.renderToString(<div />);
console.error = mocks.getMockFunction();
ReactMount.render(<div />, container); ReactMount.render(<div />, container);
expect(console.error.mock.calls.length).toBe(1); expect(console.error.calls.length).toBe(2);
}); });
it('should not warn if mounting into non-empty node', function() { it('should not warn if mounting into non-empty node', function() {
var container = document.createElement('container'); var container = document.createElement('container');
container.innerHTML = '<div></div>'; container.innerHTML = '<div></div>';
console.error = mocks.getMockFunction(); spyOn(console, 'error');
ReactMount.render(<div />, container); ReactMount.render(<div />, container);
expect(console.error.mock.calls.length).toBe(0); expect(console.error.calls.length).toBe(0);
}); });
it('should warn when mounting into document.body', function () { it('should warn when mounting into document.body', function () {

View File

@ -22,13 +22,10 @@ var ReactTestUtils;
var ReactUpdates; var ReactUpdates;
var reactComponentExpect; var reactComponentExpect;
var mocks;
describe('ReactCompositeComponent', function() { describe('ReactCompositeComponent', function() {
beforeEach(function() { beforeEach(function() {
mocks = require('mocks');
reactComponentExpect = require('reactComponentExpect'); reactComponentExpect = require('reactComponentExpect');
React = require('React'); React = require('React');
ReactCurrentOwner = require('ReactCurrentOwner'); ReactCurrentOwner = require('ReactCurrentOwner');
@ -71,7 +68,6 @@ describe('ReactCompositeComponent', function() {
}, },
}); });
console.error = mocks.getMockFunction();
spyOn(console, 'error'); spyOn(console, 'error');
}); });

View File

@ -286,6 +286,7 @@ describe('traverseAllChildren', function() {
}); });
it('should be called for each child in an iterable without keys', function() { it('should be called for each child in an iterable without keys', function() {
spyOn(console, 'error');
var threeDivIterable = { var threeDivIterable = {
'@@iterator': function() { '@@iterator': function() {
var i = 0; var i = 0;
@ -332,6 +333,8 @@ describe('traverseAllChildren', function() {
'.2' '.2'
); );
expect(console.error.calls.length).toBe(1);
expect(console.error.calls[0].args[0]).toContain('Warning: Each child in an array or iterator should have a unique "key" prop.');
}); });
it('should be called for each child in an iterable with keys', function() { it('should be called for each child in an iterable with keys', function() {

View File

@ -15,7 +15,6 @@ var React;
var ReactTestUtils; var ReactTestUtils;
var mocks; var mocks;
var warn;
describe('ReactTestUtils', function() { describe('ReactTestUtils', function() {
@ -24,13 +23,6 @@ describe('ReactTestUtils', function() {
React = require('React'); React = require('React');
ReactTestUtils = require('ReactTestUtils'); ReactTestUtils = require('ReactTestUtils');
warn = console.error;
console.error = mocks.getMockFunction();
});
afterEach(function() {
console.error = warn;
}); });
it('should have shallow rendering', function() { it('should have shallow rendering', function() {

View File

@ -14,11 +14,11 @@
'lib/postDataToURL.browser.js', 'lib/postDataToURL.browser.js',
'lib/reportTestResults.browser.js', 'lib/reportTestResults.browser.js',
'lib/jasmine-execute.js',
'../build/react.js', '../build/react.js',
'../build/react-test.js', '../build/react-test.js',
'the-files-to-test.generated.js', 'the-files-to-test.generated.js'
'lib/jasmine-execute.js'
]; ];
if (typeof Function.prototype.bind == 'undefined') { if (typeof Function.prototype.bind == 'undefined') {

View File

@ -16,4 +16,32 @@ document.write('<style> @import \'../vendor/jasmine/jasmine.css?_=' + (+new Date
window.onload = function() { window.onload = function() {
env.execute(); env.execute();
}; };
var oldError = console.error;
var newError = function() {
oldError.apply(this, arguments);
var spec = env.currentSpec;
if (spec) {
var expectationResult = new jasmine.ExpectationResult({
passed: false,
message:
'Expected test not to warn. If the warning is expected, mock it ' +
'out using spyOn(console, \'error\'); and test that the warning ' +
'occurs.',
});
spec.addMatcherResult(expectationResult);
}
};
console.error = newError;
// Make sure console.error is set back at the end of each test, or else the
// above logic won't work
env.afterEach(function() {
if (console.error !== newError && !console.error.isSpy) {
var expectationResult = new jasmine.ExpectationResult({
passed: false,
message: 'Test did not tear down console.error mock properly.',
});
env.currentSpec.addMatcherResult(expectationResult);
}
});
})(jasmine.getEnv()); })(jasmine.getEnv());