@samitouri / QOS-React-2 / commits / 2cac321b27

Change ReactPropTypes invariant's to console.warn.

cpojer committed Jan 16, 2014 at 11:10 UTC 2cac321b2704ea1356c8657f79a2b2bc4dab3927
5 files changed +495 -275
src/core/ReactCompositeComponent.js
+19 -13
@@ -837,11 +837,13 @@ var ReactCompositeComponentMixin = {
837 for (var contextName in contextTypes) {
838 maskedContext[contextName] = context[contextName];
839 }
840 - this._checkPropTypes(
841 - contextTypes,
842 - maskedContext,
843 - ReactPropTypeLocations.context
844 - );
840 + if (__DEV__) {
841 + this._checkPropTypes(
842 + contextTypes,
843 + maskedContext,
844 + ReactPropTypeLocations.context
845 + );
846 + }
847 }
848 return maskedContext;
849 },
@@ -861,11 +863,13 @@ var ReactCompositeComponentMixin = {
863 'use getChildContext().',
864 displayName
865 );
864 - this._checkPropTypes(
865 - this.constructor.childContextTypes,
866 - childContext,
867 - ReactPropTypeLocations.childContext
868 - );
866 + if (__DEV__) {
867 + this._checkPropTypes(
868 + this.constructor.childContextTypes,
869 + childContext,
870 + ReactPropTypeLocations.childContext
871 + );
872 + }
873 for (var name in childContext) {
874 invariant(
875 name in this.constructor.childContextTypes,
@@ -896,9 +900,11 @@ var ReactCompositeComponentMixin = {
900 props[propName] = defaultProps[propName];
901 }
902 }
899 - var propTypes = this.constructor.propTypes;
900 - if (propTypes) {
901 - this._checkPropTypes(propTypes, props, ReactPropTypeLocations.prop);
903 + if (__DEV__) {
904 + var propTypes = this.constructor.propTypes;
905 + if (propTypes) {
906 + this._checkPropTypes(propTypes, props, ReactPropTypeLocations.prop);
907 + }
908 }
909 return props;
910 },
src/core/ReactPropTypes.js
+10 -10
@@ -21,8 +21,8 @@
21 var ReactComponent = require('ReactComponent');
22 var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
23
24 +var warning = require('warning');
25 var createObjectFrom = require('createObjectFrom');
25 -var invariant = require('invariant');
26
27 /**
28 * Collection of methods that allow declaration and validation of props that are
@@ -57,7 +57,7 @@ var invariant = require('invariant');
57 * // An optional string or URI prop named "href".
58 * href: function(props, propName, componentName) {
59 * var propValue = props[propName];
60 - * invariant(
60 + * warning(
61 * propValue == null ||
62 * typeof propValue === 'string' ||
63 * propValue instanceof URI,
@@ -147,7 +147,7 @@ function createPrimitiveTypeChecker(expectedType) {
147 if (!shouldThrow) {
148 return isValid;
149 }
150 - invariant(
150 + warning(
151 isValid,
152 'Invalid %s `%s` of type `%s` supplied to `%s`, expected `%s`.',
153 ReactPropTypeLocationNames[location],
@@ -169,7 +169,7 @@ function createEnumTypeChecker(expectedValues) {
169 if (!shouldThrow) {
170 return isValid;
171 }
172 - invariant(
172 + warning(
173 isValid,
174 'Invalid %s `%s` supplied to `%s`, expected one of %s.',
175 ReactPropTypeLocationNames[location],
@@ -199,7 +199,7 @@ function createShapeTypeChecker(shapeTypes) {
199 if (!shouldThrow) {
200 return isValid;
201 }
202 - invariant(
202 + warning(
203 isValid,
204 'Invalid %s `%s` of type `%s` supplied to `%s`, expected `object`.',
205 ReactPropTypeLocationNames[location],
@@ -219,7 +219,7 @@ function createInstanceTypeChecker(expectedClass) {
219 if (!shouldThrow) {
220 return isValid;
221 }
222 - invariant(
222 + warning(
223 isValid,
224 'Invalid %s `%s` supplied to `%s`, expected instance of `%s`.',
225 ReactPropTypeLocationNames[location],
@@ -239,7 +239,7 @@ function createRenderableTypeChecker() {
239 if (!shouldThrow) {
240 return isValid;
241 }
242 - invariant(
242 + warning(
243 isValid,
244 'Invalid %s `%s` supplied to `%s`, expected a renderable prop.',
245 ReactPropTypeLocationNames[location],
@@ -258,7 +258,7 @@ function createComponentTypeChecker() {
258 if (!shouldThrow) {
259 return isValid;
260 }
261 - invariant(
261 + warning(
262 isValid,
263 'Invalid %s `%s` supplied to `%s`, expected a React component.',
264 ReactPropTypeLocationNames[location],
@@ -288,7 +288,7 @@ function createChainableTypeChecker(validate) {
288 if (!shouldThrow) {
289 return isValid;
290 }
291 - invariant(
291 + warning(
292 isValid,
293 'Required %s `%s` was not specified in `%s`.',
294 ReactPropTypeLocationNames[location],
@@ -320,7 +320,7 @@ function createUnionTypeChecker(arrayOfValidators) {
320 break;
321 }
322 }
323 - invariant(
323 + warning(
324 isValid,
325 'Invalid %s `%s` supplied to `%s`.',
326 ReactPropTypeLocationNames[location],
src/core/__tests__/ReactCompositeComponent-test.js
+67 -62
@@ -32,6 +32,7 @@ var ReactDoNotBindDeprecated;
32 var cx;
33 var reactComponentExpect;
34 var mocks;
35 +var warn;
36
37 describe('ReactCompositeComponent', function() {
38
@@ -80,6 +81,13 @@ describe('ReactCompositeComponent', function() {
81 <b></b>;
82 }
83 });
84 +
85 + warn = console.warn;
86 + console.warn = mocks.getMockFunction();
87 + });
88 +
89 + afterEach(function() {
90 + console.warn = warn;
91 });
92
93 it('should support rendering to different child types over time', function() {
@@ -275,11 +283,11 @@ describe('ReactCompositeComponent', function() {
283 reactComponentExpect(instance).scalarPropsEqual({key: 'testKey'});
284 reactComponentExpect(instance).scalarStateEqual({key: 'testKeyState'});
285
278 - expect(function() {
279 - ReactTestUtils.renderIntoDocument(<Component key={null} />);
280 - }).toThrow(
281 - 'Invariant Violation: Required prop `key` was not specified in ' +
282 - '`Component`.'
286 + ReactTestUtils.renderIntoDocument(<Component key={null} />);
287 +
288 + expect(console.warn.mock.calls.length).toBe(1);
289 + expect(console.warn.mock.calls[0][0]).toBe(
290 + 'Warning: Required prop `key` was not specified in `Component`.'
291 );
292 });
293
@@ -294,12 +302,11 @@ describe('ReactCompositeComponent', function() {
302 }
303 });
304
297 - var instance = <Component />;
298 - expect(function() {
299 - ReactTestUtils.renderIntoDocument(instance);
300 - }).toThrow(
301 - 'Invariant Violation: Required prop `key` was not specified in ' +
302 - '`Component`.'
305 + ReactTestUtils.renderIntoDocument(<Component />);
306 +
307 + expect(console.warn.mock.calls.length).toBe(1);
308 + expect(console.warn.mock.calls[0][0]).toBe(
309 + 'Warning: Required prop `key` was not specified in `Component`.'
310 );
311 });
312
@@ -313,23 +320,23 @@ describe('ReactCompositeComponent', function() {
320 }
321 });
322
316 - expect(function() {
317 - ReactTestUtils.renderIntoDocument(<Component />);
318 - }).toThrow(
319 - 'Invariant Violation: Required prop `key` was not specified in ' +
320 - '`Component`.'
323 + ReactTestUtils.renderIntoDocument(<Component />);
324 + ReactTestUtils.renderIntoDocument(<Component key={42} />);
325 +
326 + expect(console.warn.mock.calls.length).toBe(2);
327 + expect(console.warn.mock.calls[0][0]).toBe(
328 + 'Warning: Required prop `key` was not specified in `Component`.'
329 );
330
323 - expect(function() {
324 - ReactTestUtils.renderIntoDocument(<Component key={42} />);
325 - }).toThrow(
326 - 'Invariant Violation: Invalid prop `key` of type `number` supplied to ' +
331 + expect(console.warn.mock.calls[1][0]).toBe(
332 + 'Warning: Invalid prop `key` of type `number` supplied to ' +
333 '`Component`, expected `string`.'
334 );
335
330 - expect(function() {
331 - ReactTestUtils.renderIntoDocument(<Component key="string" />);
332 - }).not.toThrow();
336 + ReactTestUtils.renderIntoDocument(<Component key="string" />);
337 +
338 + // Should not error for strings
339 + expect(console.warn.mock.calls.length).toBe(2);
340 });
341
342 it('should throw on invalid prop types', function() {
@@ -853,25 +860,27 @@ describe('ReactCompositeComponent', function() {
860 }
861 });
862
856 - expect(function() {
857 - ReactTestUtils.renderIntoDocument(<Component />);
858 - }).toThrow(
859 - 'Invariant Violation: Required context `foo` was not specified in ' +
860 - '`Component`.'
863 + ReactTestUtils.renderIntoDocument(<Component />);
864 +
865 + expect(console.warn.mock.calls.length).toBe(1);
866 + expect(console.warn.mock.calls[0][0]).toBe(
867 + 'Warning: Required context `foo` was not specified in `Component`.'
868 );
869
863 - expect(function() {
864 - React.withContext({foo: 'bar'}, function() {
865 - ReactTestUtils.renderIntoDocument(<Component />);
866 - });
867 - }).not.toThrow();
870 + React.withContext({foo: 'bar'}, function() {
871 + ReactTestUtils.renderIntoDocument(<Component />);
872 + });
873
869 - expect(function() {
870 - React.withContext({foo: 123}, function() {
871 - ReactTestUtils.renderIntoDocument(<Component />);
872 - });
873 - }).toThrow(
874 - 'Invariant Violation: Invalid context `foo` of type `number` supplied ' +
874 + // Previous call should not error
875 + expect(console.warn.mock.calls.length).toBe(1);
876 +
877 + React.withContext({foo: 123}, function() {
878 + ReactTestUtils.renderIntoDocument(<Component />);
879 + });
880 +
881 + expect(console.warn.mock.calls.length).toBe(2);
882 + expect(console.warn.mock.calls[1][0]).toBe(
883 + 'Warning: Invalid context `foo` of type `number` supplied ' +
884 'to `Component`, expected `string`.'
885 );
886 });
@@ -892,35 +901,31 @@ describe('ReactCompositeComponent', function() {
901 }
902 });
903
895 - expect(function() {
896 - ReactTestUtils.renderIntoDocument(
897 - <Component testContext={{bar: 123}} />
898 - );
899 - }).toThrow(
900 - 'Invariant Violation: Required child context `foo` was not specified ' +
901 - 'in `Component`.'
904 + ReactTestUtils.renderIntoDocument(<Component testContext={{bar: 123}} />);
905 +
906 + expect(console.warn.mock.calls.length).toBe(1);
907 + expect(console.warn.mock.calls[0][0]).toBe(
908 + 'Warning: Required child context `foo` was not specified in `Component`.'
909 );
910
904 - expect(function() {
905 - ReactTestUtils.renderIntoDocument(
906 - <Component testContext={{foo: 123}} />
907 - );
908 - }).toThrow(
909 - 'Invariant Violation: Invalid child context `foo` of type `number` ' +
911 + ReactTestUtils.renderIntoDocument(<Component testContext={{foo: 123}} />);
912 +
913 + expect(console.warn.mock.calls.length).toBe(2);
914 + expect(console.warn.mock.calls[1][0]).toBe(
915 + 'Warning: Invalid child context `foo` of type `number` ' +
916 'supplied to `Component`, expected `string`.'
917 );
918
913 - expect(function() {
914 - ReactTestUtils.renderIntoDocument(
915 - <Component testContext={{foo: 'foo', bar: 123}} />
916 - );
917 - }).not.toThrow();
919 + ReactTestUtils.renderIntoDocument(
920 + <Component testContext={{foo: 'foo', bar: 123}} />
921 + );
922
919 - expect(function() {
920 - ReactTestUtils.renderIntoDocument(
921 - <Component testContext={{foo: 'foo'}} />
922 - );
923 - }).not.toThrow();
923 + ReactTestUtils.renderIntoDocument(
924 + <Component testContext={{foo: 'foo'}} />
925 + );
926 +
927 + // Previous calls should not log errors
928 + expect(console.warn.mock.calls.length).toBe(2);
929 });
930
931 it('should filter out context not in contextTypes', function() {
src/core/__tests__/ReactPropTypes-test.js
+357 -190
@@ -25,17 +25,16 @@ var Props = require('ReactPropTypes');
25 var React = require('React');
26 var ReactPropTypeLocations = require('ReactPropTypeLocations');
27
28 +var warn;
29 +var mocks;
30 +
31 function typeCheck(declaration, value) {
32 var props = {};
33 if (arguments.length > 1) {
34 props.testProp = value;
35 }
33 - return declaration.bind(
34 - null,
35 - props,
36 - 'testProp',
37 - 'testComponent',
38 - ReactPropTypeLocations.prop
36 + return declaration(
37 + props, 'testProp', 'testComponent', ReactPropTypeLocations.prop
38 );
39 }
40
@@ -49,156 +48,240 @@ describe('Primitive Types', function() {
48 beforeEach(function() {
49 require('mock-modules').dumpCache();
50
51 + mocks = require('mocks');
52 ReactTestUtils = require('ReactTestUtils');
53 +
54 + warn = console.warn;
55 + console.warn = mocks.getMockFunction();
56 });
57
55 - it("should throw for invalid strings", function() {
56 - expect(typeCheck(Props.string, [])).toThrow(
57 - 'Invariant Violation: Invalid prop `testProp` of type `array` ' +
58 + afterEach(function() {
59 + console.warn = warn;
60 + });
61 +
62 + it("should warn for invalid strings", function() {
63 + typeCheck(Props.string, []);
64 + typeCheck(Props.string, false);
65 + typeCheck(Props.string, 1);
66 + typeCheck(Props.string, {});
67 +
68 + expect(console.warn.mock.calls.length).toBe(4);
69 +
70 + expect(console.warn.mock.calls[0][0]).toBe(
71 + 'Warning: Invalid prop `testProp` of type `array` ' +
72 'supplied to `testComponent`, expected `string`.'
73 );
60 - expect(typeCheck(Props.string, false)).toThrow(
61 - 'Invariant Violation: Invalid prop `testProp` of type `boolean` ' +
74 + expect(console.warn.mock.calls[1][0]).toBe(
75 + 'Warning: Invalid prop `testProp` of type `boolean` ' +
76 'supplied to `testComponent`, expected `string`.'
77 );
64 - expect(typeCheck(Props.string, 1)).toThrow(
65 - 'Invariant Violation: Invalid prop `testProp` of type `number` ' +
78 + expect(console.warn.mock.calls[2][0]).toBe(
79 + 'Warning: Invalid prop `testProp` of type `number` ' +
80 'supplied to `testComponent`, expected `string`.'
81 );
68 - expect(typeCheck(Props.string, {})).toThrow(
69 - 'Invariant Violation: Invalid prop `testProp` of type `object` ' +
82 + expect(console.warn.mock.calls[3][0]).toBe(
83 + 'Warning: Invalid prop `testProp` of type `object` ' +
84 'supplied to `testComponent`, expected `string`.'
85 );
86 });
87
74 - it("should not throw for valid values", function() {
75 - expect(typeCheck(Props.array, [])).not.toThrow();
76 - expect(typeCheck(Props.bool, false)).not.toThrow();
77 - expect(typeCheck(Props.func, function() {})).not.toThrow();
78 - expect(typeCheck(Props.number, 0)).not.toThrow();
79 - expect(typeCheck(Props.object, {})).not.toThrow();
80 - expect(typeCheck(Props.string, '')).not.toThrow();
88 + it("should not warn for valid values", function() {
89 + typeCheck(Props.array, []);
90 + typeCheck(Props.bool, false);
91 + typeCheck(Props.func, function() {});
92 + typeCheck(Props.number, 0);
93 + typeCheck(Props.object, {});
94 + typeCheck(Props.string, '');
95 +
96 + // No warnings should have been logged.
97 + expect(console.warn.mock.calls.length).toBe(0);
98 });
99
83 - it("should be implicitly optional and not throw without values", function() {
84 - expect(typeCheck(Props.string, null)).not.toThrow();
85 - expect(typeCheck(Props.string, undefined)).not.toThrow();
100 + it("should be implicitly optional and not warn without values", function() {
101 + typeCheck(Props.string, null);
102 + typeCheck(Props.string, undefined);
103 +
104 + // No warnings should have been logged.
105 + expect(console.warn.mock.calls.length).toBe(0);
106 });
107
88 - it("should throw for missing required values", function() {
89 - expect(typeCheck(Props.string.isRequired, null)).toThrow(
90 - 'Invariant Violation: Required prop `testProp` was not specified in ' +
108 + it("should warn for missing required values", function() {
109 + typeCheck(Props.string.isRequired, null);
110 + typeCheck(Props.string.isRequired, undefined);
111 +
112 + expect(console.warn.mock.calls.length).toBe(2);
113 +
114 + expect(console.warn.mock.calls[0][0]).toBe(
115 + 'Warning: Required prop `testProp` was not specified in ' +
116 '`testComponent`.'
117 );
93 - expect(typeCheck(Props.string.isRequired, undefined)).toThrow(
94 - 'Invariant Violation: Required prop `testProp` was not specified in ' +
118 + expect(console.warn.mock.calls[1][0]).toBe(
119 + 'Warning: Required prop `testProp` was not specified in ' +
120 '`testComponent`.'
121 );
122 });
123
124 it("should have a weak version that returns true/false", function() {
100 - expect(typeCheck(Props.string.weak, null)()).toEqual(true);
101 - expect(typeCheck(Props.string.weak.isRequired, null)()).toEqual(false);
102 - expect(typeCheck(Props.string.isRequired.weak, null)()).toEqual(false);
125 + expect(typeCheck(Props.string.weak, null)).toEqual(true);
126 + expect(typeCheck(Props.string.weak.isRequired, null)).toEqual(false);
127 + expect(typeCheck(Props.string.isRequired.weak, null)).toEqual(false);
128 });
129 });
130
131 describe('Enum Types', function() {
132 beforeEach(function() {
133 require('mock-modules').dumpCache();
134 + mocks = require('mocks');
135 + warn = console.warn;
136 + console.warn = mocks.getMockFunction();
137 });
138
111 - it("should throw for invalid strings", function() {
112 - expect(typeCheck(Props.oneOf(['red', 'blue']), true)).toThrow(
113 - 'Invariant Violation: Invalid prop `testProp` supplied to ' +
139 + afterEach(function() {
140 + console.warn = warn;
141 + });
142 +
143 + it("should warn for invalid strings", function() {
144 + typeCheck(Props.oneOf(['red', 'blue']), true);
145 + typeCheck(Props.oneOf(['red', 'blue']), []);
146 + typeCheck(Props.oneOf(['red', 'blue']), '');
147 +
148 + expect(console.warn.mock.calls.length).toBe(3);
149 +
150 + expect(console.warn.mock.calls[0][0]).toBe(
151 + 'Warning: Invalid prop `testProp` supplied to ' +
152 '`testComponent`, expected one of ["blue","red"].'
153 );
116 - expect(typeCheck(Props.oneOf(['red', 'blue']), [])).toThrow(
117 - 'Invariant Violation: Invalid prop `testProp` supplied to ' +
154 +
155 + expect(console.warn.mock.calls[1][0]).toBe(
156 + 'Warning: Invalid prop `testProp` supplied to ' +
157 '`testComponent`, expected one of ["blue","red"].'
158 );
120 - expect(typeCheck(Props.oneOf(['red', 'blue']), '')).toThrow(
121 - 'Invariant Violation: Invalid prop `testProp` supplied to ' +
159 +
160 + expect(console.warn.mock.calls[2][0]).toBe(
161 + 'Warning: Invalid prop `testProp` supplied to ' +
162 '`testComponent`, expected one of ["blue","red"].'
163 );
164 });
165
126 - it("should not throw for valid values", function() {
127 - expect(typeCheck(Props.oneOf(['red', 'blue']), 'red')).not.toThrow();
128 - expect(typeCheck(Props.oneOf(['red', 'blue']), 'blue')).not.toThrow();
166 + it("should not warn for valid values", function() {
167 + typeCheck(Props.oneOf(['red', 'blue']), 'red');
168 + typeCheck(Props.oneOf(['red', 'blue']), 'blue');
169 +
170 + // No warnings should have been logged.
171 + expect(console.warn.mock.calls.length).toBe(0);
172 });
173
131 - it("should be implicitly optional and not throw without values", function() {
132 - expect(typeCheck(Props.oneOf(['red', 'blue']), null)).not.toThrow();
133 - expect(typeCheck(Props.oneOf(['red', 'blue']), undefined)).not.toThrow();
174 + it("should be implicitly optional and not warn without values", function() {
175 + typeCheck(Props.oneOf(['red', 'blue']), null);
176 + typeCheck(Props.oneOf(['red', 'blue']), undefined);
177 +
178 + // No warnings should have been logged.
179 + expect(console.warn.mock.calls.length).toBe(0);
180 });
181
182 it("should have a weak version that returns true/false", function() {
183 var checker = Props.oneOf(['red', 'blue']);
138 - expect(typeCheck(checker.weak, null)()).toEqual(true);
139 - expect(typeCheck(checker.weak.isRequired, null)()).toEqual(false);
140 - expect(typeCheck(checker.isRequired.weak, null)()).toEqual(false);
184 + expect(typeCheck(checker.weak, null)).toEqual(true);
185 + expect(typeCheck(checker.weak.isRequired, null)).toEqual(false);
186 + expect(typeCheck(checker.isRequired.weak, null)).toEqual(false);
187 });
188 });
189
190 describe('Shape Types', function() {
191 beforeEach(function() {
192 require('mock-modules').dumpCache();
193 + mocks = require('mocks');
194 + warn = console.warn;
195 + console.warn = mocks.getMockFunction();
196 + });
197 +
198 + afterEach(function() {
199 + console.warn = warn;
200 });
201
149 - it("should throw for non objects", function() {
150 - expect(typeCheck(Props.shape({}), 'some string')).toThrow(
151 - 'Invariant Violation: Invalid prop `testProp` of type `string` ' +
202 + it("should warn for non objects", function() {
203 + typeCheck(Props.shape({}), 'some string');
204 + typeCheck(Props.shape({}), ['array']);
205 +
206 + expect(console.warn.mock.calls.length).toBe(2);
207 +
208 + expect(console.warn.mock.calls[0][0]).toBe(
209 + 'Warning: Invalid prop `testProp` of type `string` ' +
210 'supplied to `testComponent`, expected `object`.'
211 );
154 - expect(typeCheck(Props.shape({}), ['array'])).toThrow(
155 - 'Invariant Violation: Invalid prop `testProp` of type `array` ' +
212 + expect(console.warn.mock.calls[1][0]).toBe(
213 + 'Warning: Invalid prop `testProp` of type `array` ' +
214 'supplied to `testComponent`, expected `object`.'
215 );
216 });
217
160 - it("should not throw for empty values", function() {
161 - expect(typeCheck(Props.shape({}), undefined)).not.toThrow();
162 - expect(typeCheck(Props.shape({}), null)).not.toThrow();
163 - expect(typeCheck(Props.shape({}), {})).not.toThrow();
218 + it("should not warn for empty values", function() {
219 + typeCheck(Props.shape({}), undefined);
220 + typeCheck(Props.shape({}), null);
221 + typeCheck(Props.shape({}), {});
222 +
223 + // No warnings should have been logged.
224 + expect(console.warn.mock.calls.length).toBe(0);
225 });
226
166 - it("should throw for empty required value", function() {
167 - expect(typeCheck(Props.shape({}).isRequired, undefined)).toThrow(
168 - 'Invariant Violation: Required prop `testProp` was not specified in ' +
227 + it("should warn for empty required value", function() {
228 + typeCheck(Props.shape({}).isRequired, undefined);
229 + typeCheck(Props.shape({}).isRequired, null);
230 +
231 + expect(console.warn.mock.calls.length).toBe(2);
232 +
233 + expect(console.warn.mock.calls[0][0]).toBe(
234 + 'Warning: Required prop `testProp` was not specified in ' +
235 '`testComponent`.'
236 );
171 - expect(typeCheck(Props.shape({}).isRequired, null)).toThrow(
172 - 'Invariant Violation: Required prop `testProp` was not specified in ' +
237 + expect(console.warn.mock.calls[1][0]).toBe(
238 + 'Warning: Required prop `testProp` was not specified in ' +
239 '`testComponent`.'
240 );
175 - expect(typeCheck(Props.shape({}).isRequired, {})).not.toThrow();
241 +
242 + // Should not warn
243 + typeCheck(Props.shape({}).isRequired, {});
244 + expect(console.warn.mock.calls.length).toBe(2);
245 });
246
178 - it("should not throw for non specified types", function() {
179 - expect(typeCheck(Props.shape({}), {key: 1})).not.toThrow();
247 + it("should not warn for non specified types", function() {
248 + typeCheck(Props.shape({}), {key: 1});
249 +
250 + // No warnings should have been logged.
251 + expect(console.warn.mock.calls.length).toBe(0);
252 });
253
182 - it("should not throw for valid types", function() {
183 - expect(typeCheck(Props.shape({
254 + it("should not warn for valid types", function() {
255 + typeCheck(Props.shape({
256 key: Props.number
185 - }), {key: 1})).not.toThrow();
257 + }), {key: 1});
258 +
259 + // No warnings should have been logged.
260 + expect(console.warn.mock.calls.length).toBe(0);
261 });
262
188 - it("should throw for required valid types", function() {
189 - expect(typeCheck(Props.shape({
263 + it("should warn for required valid types", function() {
264 + typeCheck(Props.shape({
265 key: Props.number.isRequired
191 - }), {})).toThrow(
192 - 'Invariant Violation: Required prop `key` was not specified in ' +
266 + }), {});
267 +
268 + expect(console.warn.mock.calls.length).toBe(1);
269 +
270 + expect(console.warn.mock.calls[0][0]).toBe(
271 + 'Warning: Required prop `key` was not specified in ' +
272 '`testComponent`.'
273 );
274 });
275
197 - it("should throw for invalid key types", function() {
198 - expect(typeCheck(Props.shape({
276 + it("should warn for invalid key types", function() {
277 + typeCheck(Props.shape({
278 key: Props.number
200 - }), {key: 'abc'})).toThrow(
201 - 'Invariant Violation: Invalid prop `key` of type `string` supplied to ' +
279 + }), {key: 'abc'});
280 +
281 + expect(console.warn.mock.calls.length).toBe(1);
282 +
283 + expect(console.warn.mock.calls[0][0]).toBe(
284 + 'Warning: Invalid prop `key` of type `string` supplied to ' +
285 '`testComponent`, expected `number`.'
286 );
287 });
@@ -207,45 +290,76 @@ describe('Shape Types', function() {
290 describe('Instance Types', function() {
291 beforeEach(function() {
292 require('mock-modules').dumpCache();
293 + mocks = require('mocks');
294 + warn = console.warn;
295 + console.warn = mocks.getMockFunction();
296 + });
297 +
298 + afterEach(function() {
299 + console.warn = warn;
300 });
301
212 - it("should throw for invalid instances", function() {
302 + it("should warn for invalid instances", function() {
303 function Person() {}
304 var name = Person.name || '<<anonymous>>';
305 + typeCheck(Props.instanceOf(Person), false);
306 + typeCheck(Props.instanceOf(Person), {});
307 + typeCheck(Props.instanceOf(Person), '');
308
216 - expect(typeCheck(Props.instanceOf(Person), false)).toThrow(
217 - 'Invariant Violation: Invalid prop `testProp` supplied to ' +
309 + expect(console.warn.mock.calls.length).toBe(3);
310 +
311 + expect(console.warn.mock.calls[0][0]).toBe(
312 + 'Warning: Invalid prop `testProp` supplied to ' +
313 '`testComponent`, expected instance of `' + name + '`.'
314 );
220 - expect(typeCheck(Props.instanceOf(Person), {})).toThrow(
221 - 'Invariant Violation: Invalid prop `testProp` supplied to ' +
315 +
316 + expect(console.warn.mock.calls[1][0]).toBe(
317 + 'Warning: Invalid prop `testProp` supplied to ' +
318 '`testComponent`, expected instance of `' + name + '`.'
319 );
224 - expect(typeCheck(Props.instanceOf(Person), '')).toThrow(
225 - 'Invariant Violation: Invalid prop `testProp` supplied to ' +
320 +
321 + expect(console.warn.mock.calls[2][0]).toBe(
322 + 'Warning: Invalid prop `testProp` supplied to ' +
323 '`testComponent`, expected instance of `' + name + '`.'
324 );
325 });
326
230 - it("should not throw for valid values", function() {
327 + it("should not warn for valid values", function() {
328 function Person() {}
329 function Engineer() {}
330 Engineer.prototype = new Person();
331
235 - expect(typeCheck(Props.instanceOf(Person), new Person())).not.toThrow();
236 - expect(typeCheck(Props.instanceOf(Person), new Engineer())).not.toThrow();
332 + typeCheck(Props.instanceOf(Person), new Person());
333 + typeCheck(Props.instanceOf(Person), new Engineer());
334 +
335 + // No warnings should have been logged.
336 + expect(console.warn.mock.calls.length).toBe(0);
337 });
338 });
339
340 describe('Component Type', function() {
341 + beforeEach(function() {
342 + require('mock-modules').dumpCache();
343 + mocks = require('mocks');
344 + warn = console.warn;
345 + console.warn = mocks.getMockFunction();
346 + });
347 +
348 + afterEach(function() {
349 + console.warn = warn;
350 + });
351 +
352 it('should support components', () => {
242 - expect(typeCheck(Props.component, <div />)).not.toThrow();
353 + typeCheck(Props.component, <div />);
354 +
355 + // No warnings should have been logged.
356 + expect(console.warn.mock.calls.length).toBe(0);
357 });
358
359 it('should not support multiple components or scalar values', () => {
246 - [[<div />, <div />], 123, 'foo', false].forEach((value) => {
247 - expect(typeCheck(Props.component, value)).toThrow();
248 - });
360 + var list = [[<div />, <div />], 123, 'foo', false];
361 + list.forEach((value) => typeCheck(Props.component, value));
362 + expect(console.warn.mock.calls.length).toBe(list.length);
363 });
364
365 var Component = React.createClass({
@@ -259,75 +373,93 @@ describe('Component Type', function() {
373 });
374
375 it('should be able to define a single child as children', () => {
262 - expect(() => {
263 - var instance =
264 - <Component>
265 - <div />
266 - </Component>;
267 - ReactTestUtils.renderIntoDocument(instance);
268 - }).not.toThrow();
269 - });
270 -
271 - it('should throw when passing more than one child', () => {
272 - expect(() => {
273 - var instance =
274 - <Component>
275 - <div />
276 - <div />
277 - </Component>;
278 - ReactTestUtils.renderIntoDocument(instance);
279 - }).toThrow();
280 - });
281 -
282 - it('should throw when passing no children and isRequired is set', () => {
283 - expect(() => {
284 - var instance = <Component />;
285 - ReactTestUtils.renderIntoDocument(instance);
286 - }).toThrow();
376 + var instance =
377 + <Component>
378 + <div />
379 + </Component>;
380 + ReactTestUtils.renderIntoDocument(instance);
381 +
382 + // No warnings should have been logged.
383 + expect(console.warn.mock.calls.length).toBe(0);
384 + });
385 +
386 + it('should warn when passing more than one child', () => {
387 + var instance =
388 + <Component>
389 + <div />
390 + <div />
391 + </Component>;
392 + ReactTestUtils.renderIntoDocument(instance);
393 + expect(console.warn.mock.calls.length).toBe(1);
394 + });
395 +
396 + it('should warn when passing no children and isRequired is set', () => {
397 + var instance = <Component />;
398 + ReactTestUtils.renderIntoDocument(instance);
399 +
400 + expect(console.warn.mock.calls.length).toBe(1);
401 });
402 });
403
404 describe('Union Types', function() {
405 beforeEach(function() {
406 require('mock-modules').dumpCache();
407 + mocks = require('mocks');
408 + warn = console.warn;
409 + console.warn = mocks.getMockFunction();
410 });
411
295 - it('should throw if none of the types are valid', function() {
412 + afterEach(function() {
413 + console.warn = warn;
414 + });
415 +
416 + it('should warn if none of the types are valid', function() {
417 var checker = Props.oneOfType([
418 Props.string,
419 Props.number
420 ]);
300 - expect(typeCheck(checker, [])).toThrow(
301 - 'Invariant Violation: Invalid prop `testProp` ' +
302 - 'supplied to `testComponent`.'
303 - );
304 -
421 + typeCheck(checker, []);
422 checker = Props.oneOfType([
423 Props.string.isRequired,
424 Props.number.isRequired
425 ]);
309 - expect(typeCheck(checker, null)).toThrow(
310 - 'Invariant Violation: Invalid prop `testProp` ' +
426 + typeCheck(checker, null);
427 +
428 + expect(console.warn.mock.calls.length).toBe(2);
429 +
430 + expect(console.warn.mock.calls[0][0]).toBe(
431 + 'Warning: Invalid prop `testProp` ' +
432 + 'supplied to `testComponent`.'
433 + );
434 +
435 + expect(console.warn.mock.calls[1][0]).toBe(
436 + 'Warning: Invalid prop `testProp` ' +
437 'supplied to `testComponent`.'
438 );
439 });
440
315 - it('should not throw if one of the types are valid', function() {
441 + it('should not warn if one of the types are valid', function() {
442 var checker = Props.oneOfType([
443 Props.string,
444 Props.number
445 ]);
320 - expect(typeCheck(checker, null)).not.toThrow();
321 - expect(typeCheck(checker, 'foo')).not.toThrow();
322 - expect(typeCheck(checker, 123)).not.toThrow();
446 + typeCheck(checker, null);
447 + expect(console.warn.mock.calls.length).toBe(0);
448 + typeCheck(checker, 'foo');
449 + expect(console.warn.mock.calls.length).toBe(0);
450 + typeCheck(checker, 123);
451 + expect(console.warn.mock.calls.length).toBe(0);
452
453 checker = Props.oneOfType([
454 Props.string,
455 Props.number.isRequired
456 ]);
328 - expect(typeCheck(checker, null)).not.toThrow();
329 - expect(typeCheck(checker, 'foo')).not.toThrow();
330 - expect(typeCheck(checker, 123)).not.toThrow();
457 + typeCheck(checker, null);
458 + expect(console.warn.mock.calls.length).toBe(0);
459 + typeCheck(checker, 'foo');
460 + expect(console.warn.mock.calls.length).toBe(0);
461 + typeCheck(checker, 123);
462 + expect(console.warn.mock.calls.length).toBe(0);
463 });
464
465 describe('React Component Types', function() {
@@ -337,103 +469,138 @@ describe('Union Types', function() {
469
470 var myFunc = function() {};
471
340 - it('should throw for invalid values', function() {
341 - expect(typeCheck(Props.renderable, false)).toThrow(
342 - 'Invariant Violation: Invalid prop `testProp` supplied to ' +
472 + it('should warn for invalid values', function() {
473 + typeCheck(Props.renderable, false);
474 + typeCheck(Props.renderable, myFunc);
475 + typeCheck(Props.renderable, {key: myFunc});
476 +
477 + expect(console.warn.mock.calls.length).toBe(3);
478 +
479 + expect(console.warn.mock.calls[0][0]).toBe(
480 + 'Warning: Invalid prop `testProp` supplied to ' +
481 '`testComponent`, expected a renderable prop.'
482 );
345 - expect(typeCheck(Props.renderable, myFunc)).toThrow(
346 - 'Invariant Violation: Invalid prop `testProp` supplied to ' +
483 +
484 + expect(console.warn.mock.calls[1][0]).toBe(
485 + 'Warning: Invalid prop `testProp` supplied to ' +
486 '`testComponent`, expected a renderable prop.'
487 );
349 - expect(typeCheck(Props.renderable, {key: myFunc})).toThrow(
350 - 'Invariant Violation: Invalid prop `testProp` supplied to ' +
488 +
489 + expect(console.warn.mock.calls[2][0]).toBe(
490 + 'Warning: Invalid prop `testProp` supplied to ' +
491 '`testComponent`, expected a renderable prop.'
492 );
493 });
494
355 - it('should not throw for valid values', function() {
495 + it('should not warn for valid values', function() {
496 // DOM component
357 - expect(typeCheck(Props.renderable, <div />)).not.toThrow();
497 + typeCheck(Props.renderable, <div />);
498 + expect(console.warn.mock.calls.length).toBe(0);
499 // Custom component
359 - expect(typeCheck(Props.renderable, <MyComponent />)).not.toThrow();
500 + typeCheck(Props.renderable, <MyComponent />);
501 + expect(console.warn.mock.calls.length).toBe(0);
502 // String
361 - expect(typeCheck(Props.renderable, 'Some string')).not.toThrow();
503 + typeCheck(Props.renderable, 'Some string');
504 + expect(console.warn.mock.calls.length).toBe(0);
505 // Empty array
363 - expect(typeCheck(Props.renderable, [])).not.toThrow();
506 + typeCheck(Props.renderable, []);
507 + expect(console.warn.mock.calls.length).toBe(0);
508 // Empty object
365 - expect(typeCheck(Props.renderable, {})).not.toThrow();
509 + typeCheck(Props.renderable, {});
510 + expect(console.warn.mock.calls.length).toBe(0);
511 // Array of renderable things
367 - expect(
368 - typeCheck(Props.renderable, [
369 - 123,
370 - 'Some string',
371 - <div />,
372 - ['Another string', [456], <span />, <MyComponent />],
373 - <MyComponent />
374 - ])
375 - ).not.toThrow();
512 +
513 + typeCheck(Props.renderable, [
514 + 123,
515 + 'Some string',
516 + <div />,
517 + ['Another string', [456], <span />, <MyComponent />],
518 + <MyComponent />
519 + ]);
520 + expect(console.warn.mock.calls.length).toBe(0);
521 +
522 // Object of rendereable things
377 - expect(
378 - typeCheck(Props.renderable, {
379 - k0: 123,
380 - k1: 'Some string',
381 - k2: <div />,
382 - k3: {
383 - k30: <MyComponent />,
384 - k31: {k310: <a />},
385 - k32: 'Another string'
386 - }
387 - })
388 - ).not.toThrow();
523 + typeCheck(Props.renderable, {
524 + k0: 123,
525 + k1: 'Some string',
526 + k2: <div />,
527 + k3: {
528 + k30: <MyComponent />,
529 + k31: {k310: <a />},
530 + k32: 'Another string'
531 + }
532 + });
533 + expect(console.warn.mock.calls.length).toBe(0);
534 });
535
391 - it('should not throw for null/undefined if not required', function() {
392 - expect(typeCheck(Props.renderable, null)).not.toThrow();
393 - expect(typeCheck(Props.renderable, undefined)).not.toThrow();
536 + it('should not warn for null/undefined if not required', function() {
537 + typeCheck(Props.renderable, null);
538 + typeCheck(Props.renderable, undefined);
539 +
540 + // No warnings should have been logged.
541 + expect(console.warn.mock.calls.length).toBe(0);
542 });
543
396 - it('should throw for missing required values', function() {
397 - expect(typeCheck(Props.renderable.isRequired, null)).toThrow(
398 - 'Invariant Violation: Required prop `testProp` was not specified in ' +
544 + it('should warn for missing required values', function() {
545 + typeCheck(Props.renderable.isRequired, null);
546 + typeCheck(Props.renderable.isRequired, undefined);
547 +
548 + expect(console.warn.mock.calls.length).toBe(2);
549 +
550 + expect(console.warn.mock.calls[0][0]).toBe(
551 + 'Warning: Required prop `testProp` was not specified in ' +
552 '`testComponent`.'
553 );
401 - expect(typeCheck(Props.renderable.isRequired, undefined)).toThrow(
402 - 'Invariant Violation: Required prop `testProp` was not specified in ' +
554 + expect(console.warn.mock.calls[1][0]).toBe(
555 + 'Warning: Required prop `testProp` was not specified in ' +
556 '`testComponent`.'
557 );
558 });
559
560 it('should accept empty array & object for required props', function() {
408 - expect(typeCheck(Props.renderable.isRequired, [])).not.toThrow();
409 - expect(typeCheck(Props.renderable.isRequired, {})).not.toThrow();
561 + typeCheck(Props.renderable.isRequired, []);
562 + typeCheck(Props.renderable.isRequired, {});
563 +
564 + // No warnings should have been logged.
565 + expect(console.warn.mock.calls.length).toBe(0);
566 });
567 });
568
569 describe('Any type', function() {
570 it('should should accept any value', function() {
415 - expect(typeCheck(Props.any, 1)).not.toThrow();
416 - expect(typeCheck(Props.any, 'str')).not.toThrow();
417 - expect(typeCheck(Props.any.isRequired, 1)).not.toThrow();
418 - expect(typeCheck(Props.any.isRequired, 'str')).not.toThrow();
419 -
420 - expect(typeCheck(Props.any, null)).not.toThrow();
421 - expect(typeCheck(Props.any, undefined)).not.toThrow();
422 -
423 - expect(typeCheck(Props.any.isRequired, null)).toThrow(
424 - 'Invariant Violation: Required prop `testProp` was not specified in ' +
571 + typeCheck(Props.any, 1);
572 + expect(console.warn.mock.calls.length).toBe(0);
573 + typeCheck(Props.any, 'str');
574 + expect(console.warn.mock.calls.length).toBe(0);
575 + typeCheck(Props.any.isRequired, 1);
576 + expect(console.warn.mock.calls.length).toBe(0);
577 + typeCheck(Props.any.isRequired, 'str');
578 + expect(console.warn.mock.calls.length).toBe(0);
579 +
580 + typeCheck(Props.any, null);
581 + expect(console.warn.mock.calls.length).toBe(0);
582 + typeCheck(Props.any, undefined);
583 + expect(console.warn.mock.calls.length).toBe(0);
584 +
585 + typeCheck(Props.any.isRequired, null);
586 + typeCheck(Props.any.isRequired, undefined);
587 +
588 + expect(console.warn.mock.calls.length).toBe(2);
589 + expect(console.warn.mock.calls[0][0]).toBe(
590 + 'Warning: Required prop `testProp` was not specified in ' +
591 '`testComponent`.'
592 );
427 - expect(typeCheck(Props.any.isRequired, undefined)).toThrow(
428 - 'Invariant Violation: Required prop `testProp` was not specified in ' +
593 +
594 + expect(console.warn.mock.calls[1][0]).toBe(
595 + 'Warning: Required prop `testProp` was not specified in ' +
596 '`testComponent`.'
597 );
598 });
599
600 it('should have a weak version that returns true/false', function() {
434 - expect(typeCheck(Props.any.weak, null)()).toEqual(true);
435 - expect(typeCheck(Props.any.weak.isRequired, null)()).toEqual(false);
436 - expect(typeCheck(Props.any.isRequired.weak, null)()).toEqual(false);
601 + expect(typeCheck(Props.any.weak, null)).toEqual(true);
602 + expect(typeCheck(Props.any.weak.isRequired, null)).toEqual(false);
603 + expect(typeCheck(Props.any.isRequired.weak, null)).toEqual(false);
604 });
605 });
606 });
src/vendor/core/warning.js new
+42
@@ -0,0 +1,42 @@
1 +/**
2 + * Copyright 2014 Facebook, Inc.
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + *
16 + * @providesModule warning
17 + */
18 +
19 +
20 +/**
21 + * Similar to invariant but only logs a warning if the condition is not met.
22 + * This can be used to log issues in development environments in critical
23 + * paths. Removing the logging code for production environments will keep the
24 + * same logic and follow the same code paths.
25 + */
26 +function warning(condition, format, ...args) {
27 + if (format === undefined) {
28 + throw new Error(
29 + '`warning(condition, format, ...args)` requires an error message argument'
30 + );
31 + }
32 +
33 + if (!condition) {
34 + var argIndex = 0;
35 + console.warn(
36 + 'Warning: ' +
37 + format.replace(/%s/g, () => args[argIndex++])
38 + );
39 + }
40 +}
41 +
42 +module.exports = warning;