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

Add PropTypes.component to demand a single React component.

cpojer committed Jan 9, 2014 at 11:39 UTC b713c2c6968d7513305ea5285825698c2eab90c5
2 files changed +75 -1
src/core/ReactPropTypes.js
+21 -1
@@ -86,7 +86,8 @@ var Props = {
86
87 instanceOf: createInstanceTypeChecker,
88
89 - renderable: createRenderableTypeChecker()
89 + renderable: createRenderableTypeChecker(),
90 + component: createComponentTypeChecker()
91
92 };
93
@@ -200,6 +201,25 @@ function createRenderableTypeChecker() {
201 return createChainableTypeChecker(validateRenderableType);
202 }
203
204 +function createComponentTypeChecker() {
205 + function validateComponentType(
206 + shouldThrow, propValue, propName, componentName, location
207 + ) {
208 + var isValid = ReactComponent.isValidComponent(propValue);
209 + if (!shouldThrow) {
210 + return isValid;
211 + }
212 + invariant(
213 + isValid,
214 + 'Invalid %s `%s` supplied to `%s`, expected a React component.',
215 + ReactPropTypeLocationNames[location],
216 + propName,
217 + componentName
218 + );
219 + }
220 + return createChainableTypeChecker(validateComponentType);
221 +}
222 +
223 function createChainableTypeChecker(validate) {
224 function checkType(
225 isRequired, shouldThrow, props, propName, componentName, location
src/core/__tests__/ReactPropTypes-test.js
+54
@@ -19,6 +19,8 @@
19
20 "use strict";
21
22 +var ReactTestUtils;
23 +
24 var Props = require('ReactPropTypes');
25 var React = require('React');
26 var ReactPropTypeLocations = require('ReactPropTypeLocations');
@@ -46,6 +48,8 @@ var MyComponent = React.createClass({
48 describe('Primitive Types', function() {
49 beforeEach(function() {
50 require('mock-modules').dumpCache();
51 +
52 + ReactTestUtils = require('ReactTestUtils');
53 });
54
55 it("should throw for invalid strings", function() {
@@ -170,6 +174,56 @@ describe('Instance Types', function() {
174 });
175 });
176
177 +describe('Component Type', function() {
178 + it('should support components', () => {
179 + expect(typeCheck(Props.component, <div />)).not.toThrow();
180 + });
181 +
182 + it('should not support multiple components or scalar values', () => {
183 + [[<div />, <div />], 123, 'foo', false].forEach((value) => {
184 + expect(typeCheck(Props.component, value)).toThrow();
185 + });
186 + });
187 +
188 + var Component = React.createClass({
189 + propTypes: {
190 + children: Props.component.isRequired
191 + },
192 +
193 + render: function() {
194 + return <div>{this.props.children}</div>;
195 + }
196 + });
197 +
198 + it('should be able to define a single child as children', () => {
199 + expect(() => {
200 + var instance =
201 + <Component>
202 + <div />
203 + </Component>;
204 + ReactTestUtils.renderIntoDocument(instance);
205 + }).not.toThrow();
206 + });
207 +
208 + it('should throw when passing more than one child', () => {
209 + expect(() => {
210 + var instance =
211 + <Component>
212 + <div />
213 + <div />
214 + </Component>;
215 + ReactTestUtils.renderIntoDocument(instance);
216 + }).toThrow();
217 + });
218 +
219 + it('should throw when passing no children and isRequired is set', () => {
220 + expect(() => {
221 + var instance = <Component />;
222 + ReactTestUtils.renderIntoDocument(instance);
223 + }).toThrow();
224 + });
225 +});
226 +
227 describe('Union Types', function() {
228 beforeEach(function() {
229 require('mock-modules').dumpCache();