diff --git a/README.md b/README.md index e828d0c..752f238 100644 --- a/README.md +++ b/README.md @@ -284,6 +284,10 @@ PropTypes.checkPropTypes(myPropTypes, props, 'age', 'MyComponent'); // `MyComponent`, expected `number`. ``` +## PropTypes.resetWarningCache() + +`PropTypes.checkPropTypes(...)` only `console.error.log(...)`s a given message once. To reset the cache while testing call `PropTypes.resetWarningCache()` + ### License prop-types is [MIT licensed](./LICENSE). diff --git a/__tests__/PropTypesDevelopmentReact15.js b/__tests__/PropTypesDevelopmentReact15.js index d95dd1c..866ca5b 100644 --- a/__tests__/PropTypesDevelopmentReact15.js +++ b/__tests__/PropTypesDevelopmentReact15.js @@ -112,7 +112,7 @@ describe('PropTypesDevelopmentReact15', () => { describe('checkPropTypes', () => { it('should warn for invalid validators', () => { - spyOn(console, 'error') + spyOn(console, 'error'); const propTypes = { foo: undefined }; const props = { foo: 'foo' }; PropTypes.checkPropTypes( @@ -128,6 +128,51 @@ describe('PropTypesDevelopmentReact15', () => { ); }); + it('should only warn once for identical validator failures', () => { + spyOn(console, 'error'); + const propTypes = { foo: undefined }; + const props = { foo: 'foo' }; + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + expect(console.error.calls.count()).toEqual(1); + }); + + describe('checkPropTypes.resetWarningCache', () => { + it('should reset warning cache', () => { + spyOn(console, 'error'); + const propTypes = { foo: undefined }; + const props = { foo: 'foo' }; + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + PropTypes.checkPropTypes.resetWarningCache(); + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + expect(console.error.calls.count()).toEqual(2); + }); + }); + it('does not return a value from a validator', () => { spyOn(console, 'error'); const propTypes = { @@ -181,6 +226,30 @@ describe('PropTypesDevelopmentReact15', () => { }); }); + describe('resetWarningCache', () => { + it('should reset warning cache', () => { + spyOn(console, 'error'); + const propTypes = { foo: undefined }; + const props = { foo: 'foo' }; + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + PropTypes.resetWarningCache(); + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + expect(console.error.calls.count()).toEqual(2); + }); + }); + describe('Primitive Types', () => { it('should warn for invalid strings', () => { typeCheckFail( diff --git a/__tests__/PropTypesDevelopmentStandalone-test.js b/__tests__/PropTypesDevelopmentStandalone-test.js index 6841d9c..58fd1fb 100644 --- a/__tests__/PropTypesDevelopmentStandalone-test.js +++ b/__tests__/PropTypesDevelopmentStandalone-test.js @@ -124,6 +124,51 @@ describe('PropTypesDevelopmentStandalone', () => { ); }); + it('should only warn once for identical validator failures', () => { + spyOn(console, 'error'); + const propTypes = { foo: undefined }; + const props = { foo: 'foo' }; + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + expect(console.error.calls.count()).toEqual(1); + }); + + describe('checkPropTypes.resetWarningCache', () => { + it('should reset warning cache', () => { + spyOn(console, 'error') + const propTypes = { foo: undefined }; + const props = { foo: 'foo' }; + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + PropTypes.checkPropTypes.resetWarningCache(); + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + expect(console.error.calls.count()).toEqual(2); + }); + }); + it('does not return a value from a validator', () => { spyOn(console, 'error'); const propTypes = { @@ -177,6 +222,30 @@ describe('PropTypesDevelopmentStandalone', () => { }); }); + describe('resetWarningCache', () => { + it('should reset warning cache', () => { + spyOn(console, 'error'); + const propTypes = { foo: undefined }; + const props = { foo: 'foo' }; + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + PropTypes.resetWarningCache(); + PropTypes.checkPropTypes( + propTypes, + props, + 'prop', + 'testComponent', + null, + ); + expect(console.error.calls.count()).toEqual(2); + }); + }); + describe('Primitive Types', () => { it('should warn for invalid strings', () => { typeCheckFail( @@ -725,7 +794,7 @@ describe('PropTypesDevelopmentStandalone', () => { it('should support objects with a null prototype', () => { const nullObj = Object.create(null); - nullObj.test = "a property"; + nullObj.test = 'a property'; typeCheckPass(PropTypes.objectOf(PropTypes.string), nullObj); }); diff --git a/__tests__/PropTypesProductionReact15-test.js b/__tests__/PropTypesProductionReact15-test.js index bedd577..1cda0bb 100644 --- a/__tests__/PropTypesProductionReact15-test.js +++ b/__tests__/PropTypesProductionReact15-test.js @@ -968,4 +968,26 @@ describe('PropTypesProductionReact15', () => { expectNoop(PropTypes.symbol, CoreSymbol('core-js')); }); }); + + describe('checkPropTypes', function() { + describe('checkPropTypes.resetWarningCache', () => { + it('should provide empty function', () => { + spyOn(console, 'error'); + + var spy = jest.fn(); + PropTypes.checkPropTypes.resetWarningCache(); + expect(spy).not.toBeCalled(); + }); + }); + }); + + describe('resetWarningCache', () => { + it('should provide empty function', () => { + spyOn(console, 'error'); + + var spy = jest.fn(); + PropTypes.resetWarningCache(); + expect(spy).not.toBeCalled(); + }); + }); }); diff --git a/__tests__/PropTypesProductionStandalone-test.js b/__tests__/PropTypesProductionStandalone-test.js index 7030201..3b2693c 100644 --- a/__tests__/PropTypesProductionStandalone-test.js +++ b/__tests__/PropTypesProductionStandalone-test.js @@ -232,5 +232,25 @@ describe('PropTypesProductionStandalone', function() { typeCheckPass(spy, 'no way'); expect(spy).not.toBeCalled(); }); + + describe('checkPropTypes.resetWarningCache', () => { + it('should provide empty function', () => { + spyOn(console, 'error'); + + var spy = jest.fn(); + PropTypes.checkPropTypes.resetWarningCache(); + expect(spy).not.toBeCalled(); + }); + }); + }); + + describe('resetWarningCache', () => { + it('should provide empty function', () => { + spyOn(console, 'error'); + + var spy = jest.fn(); + PropTypes.resetWarningCache(); + expect(spy).not.toBeCalled(); + }); }); }); diff --git a/checkPropTypes.js b/checkPropTypes.js index 30dc92d..c0e2096 100644 --- a/checkPropTypes.js +++ b/checkPropTypes.js @@ -89,4 +89,15 @@ function checkPropTypes(typeSpecs, values, location, componentName, getStack) { } } +/** + * Resets warning cache when testing. + * + * @private + */ +checkPropTypes.resetWarningCache = function() { + if (process.env.NODE_ENV !== 'production') { + loggedTypeFailures = {}; + } +} + module.exports = checkPropTypes; diff --git a/factoryWithThrowingShims.js b/factoryWithThrowingShims.js index 79b60f2..e0f8062 100644 --- a/factoryWithThrowingShims.js +++ b/factoryWithThrowingShims.js @@ -10,6 +10,8 @@ var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); function emptyFunction() {} +function emptyFunctionWithReset() {} +emptyFunctionWithReset.resetWarningCache = emptyFunction; module.exports = function() { function shim(props, propName, componentName, location, propFullName, secret) { @@ -49,10 +51,12 @@ module.exports = function() { oneOf: getShim, oneOfType: getShim, shape: getShim, - exact: getShim + exact: getShim, + + checkPropTypes: emptyFunctionWithReset, + resetWarningCache: emptyFunction }; - ReactPropTypes.checkPropTypes = emptyFunction; ReactPropTypes.PropTypes = ReactPropTypes; return ReactPropTypes; diff --git a/factoryWithTypeCheckers.js b/factoryWithTypeCheckers.js index 1942d0e..3da0013 100644 --- a/factoryWithTypeCheckers.js +++ b/factoryWithTypeCheckers.js @@ -550,6 +550,7 @@ module.exports = function(isValidElement, throwOnDirectAccess) { } ReactPropTypes.checkPropTypes = checkPropTypes; + ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache; ReactPropTypes.PropTypes = ReactPropTypes; return ReactPropTypes;