Skip to content

Commit

Permalink
[added] 'elementType' custom prop type validator
Browse files Browse the repository at this point in the history
The code has been borrowed from
the https://github.com/jquense/react-widgets project
  • Loading branch information
AlexKVal committed Jun 24, 2015
1 parent 4f0ed4f commit 0e5980f
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/utils/CustomPropTypes.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import React from 'react';

const ANONYMOUS = '<<anonymous>>';

const CustomPropTypes = {
Expand All @@ -15,6 +17,20 @@ const CustomPropTypes = {
*/
mountable: createMountableChecker(),

/**
* Checks whether a prop provides a type of element.
*
* The type of element can be provided in two forms:
* - tag name (string)
* - a return value of React.createClass(...)
*
* @param props
* @param propName
* @param componentName
* @returns {Error|undefined}
*/
elementType: createElementTypeChecker(),

/**
* Checks whether a prop matches a key of an associated object
*
Expand Down Expand Up @@ -135,4 +151,24 @@ function all(propTypes) {
};
}

function createElementTypeChecker() {
function validate(props, propName, componentName) {
let errMsg = `Invalid prop '${propName}' specified in '${componentName}'.` +
' Expected an Element `type`';

if (typeof props[propName] !== 'function') {
if (React.isValidElement(props[propName])) {
return new Error(errMsg + ', not an actual Element');
}

if (typeof props[propName] !== 'string') {
return new Error(errMsg +
' such as a tag name or return value of React.createClass(...)');
}
}
}

return createChainableTypeChecker(validate);
}

export default CustomPropTypes;
28 changes: 28 additions & 0 deletions test/utils/CustomPropTypesSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,34 @@ describe('CustomPropTypes', function() {
});
});

describe('elementType', function () {
function validate(prop) {
return CustomPropTypes.elementType({p: prop}, 'p', 'TestComponent');
}

it('Should validate OK with undifined or null values', function() {
assert.isUndefined(validate());
assert.isUndefined(validate(null));
});

it('Should validate OK with elementType values', function() {
assert.isUndefined(validate('span'));
assert.isUndefined(validate(function(){}));
});

it('Should return error with not a string or function values', function() {
let err = validate({});
assert.instanceOf(err, Error);
assert.include(err.message, 'Expected an Element `type` such as a tag name or return value of React.createClass(...)');
});

it('Should return error with react element', function() {
let err = validate(React.createElement('span'));
assert.instanceOf(err, Error);
assert.include(err.message, 'Expected an Element `type`, not an actual Element');
});
});

describe('keyOf', function () {
let obj = {'foo': 1};
function validate(prop) {
Expand Down

0 comments on commit 0e5980f

Please sign in to comment.