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;