Skip to content

Commit dfec023

Browse files
committed
[added] CustomPropType.all to allow multiple validations
This will allow us to have multiple validations applied on a single prop.
1 parent d238d23 commit dfec023

File tree

5 files changed

+101
-6
lines changed

5 files changed

+101
-6
lines changed

karma.conf.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ module.exports = function (config) {
1313
frameworks: [
1414
'mocha',
1515
'chai',
16-
'sinon'
16+
'sinon',
17+
'sinon-chai'
1718
],
1819

1920
files: [

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"karma-mocha-reporter": "^1.0.2",
6565
"karma-phantomjs-launcher": "^0.1.4",
6666
"karma-sinon": "^1.0.3",
67+
"karma-sinon-chai": "^0.3.0",
6768
"karma-sourcemap-loader": "^0.3.4",
6869
"karma-webpack": "^1.5.0",
6970
"less": "^2.4.0",
@@ -79,6 +80,7 @@
7980
"rimraf": "^2.3.2",
8081
"semver": "^4.3.4",
8182
"sinon": "^1.10.3",
83+
"sinon-chai": "^2.7.0",
8284
"style-loader": "^0.12.0",
8385
"transform-loader": "^0.2.1",
8486
"webpack": "^1.7.2",
@@ -88,4 +90,4 @@
8890
"dependencies": {
8991
"classnames": "^2.0.0"
9092
}
91-
}
93+
}

src/utils/CustomPropTypes.js

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const ANONYMOUS = '<<anonymous>>';
22

3-
let CustomPropTypes = {
3+
const CustomPropTypes = {
44
/**
55
* Checks whether a prop provides a DOM element
66
*
@@ -14,6 +14,7 @@ let CustomPropTypes = {
1414
* @returns {Error|undefined}
1515
*/
1616
mountable: createMountableChecker(),
17+
1718
/**
1819
* Checks whether a prop matches a key of an associated object
1920
*
@@ -32,7 +33,9 @@ let CustomPropTypes = {
3233
* @param componentName
3334
* @returns {Error|undefined}
3435
*/
35-
singlePropFrom: createSinglePropFromChecker
36+
singlePropFrom: createSinglePropFromChecker,
37+
38+
all
3639
};
3740

3841
/**
@@ -108,4 +111,28 @@ function createSinglePropFromChecker(arrOfProps) {
108111
return validate;
109112
}
110113

114+
function all(propTypes) {
115+
if (propTypes === undefined) {
116+
throw new Error('No validations provided');
117+
}
118+
119+
if (!(propTypes instanceof Array)) {
120+
throw new Error('Invalid argument must be an array');
121+
}
122+
123+
if (propTypes.length === 0) {
124+
throw new Error('No validations provided');
125+
}
126+
127+
return function(props, propName, componentName) {
128+
for(let i = 0; i < propTypes.length; i++) {
129+
let result = propTypes[i](props, propName, componentName);
130+
131+
if (result !== undefined && result !== null) {
132+
return result;
133+
}
134+
}
135+
};
136+
}
137+
111138
export default CustomPropTypes;

test/.eslintrc

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
},
55
"globals": {
66
"assert": true,
7+
"expect": true,
78
"sinon": true
89
},
910
"plugins": [

test/CustomPropTypesSpec.js test/utils/CustomPropTypesSpec.js

+66-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from 'react';
22
import ReactTestUtils from 'react/lib/ReactTestUtils';
3-
import CustomPropTypes from '../src/utils/CustomPropTypes';
3+
import CustomPropTypes from '../../src/utils/CustomPropTypes';
44

5-
describe('CustomPropTypes', function () {
5+
describe('CustomPropTypes', function() {
66

77
describe('mountable', function () {
88
function validate(prop) {
@@ -67,4 +67,68 @@ describe('CustomPropTypes', function () {
6767
validate(testProps).should.be.instanceOf(Error);
6868
});
6969
});
70+
71+
describe('all', function() {
72+
let validators;
73+
const props = {
74+
key: 'value'
75+
};
76+
const propName = 'key';
77+
const componentName = 'TestComponent';
78+
79+
beforeEach(function() {
80+
validators = [
81+
sinon.stub(),
82+
sinon.stub(),
83+
sinon.stub()
84+
];
85+
});
86+
87+
it('with no arguments provided', function() {
88+
expect(() => {
89+
CustomPropTypes.all();
90+
}).to.throw(Error, /No validations provided/);
91+
});
92+
93+
it('with no validations provided', function() {
94+
expect(() => {
95+
CustomPropTypes.all([]);
96+
}).to.throw(Error, /No validations provided/);
97+
});
98+
99+
it('with invalid arguments provided', function() {
100+
expect(() => {
101+
CustomPropTypes.all(1);
102+
}).to.throw(Error, /Invalid argument must be an array/);
103+
});
104+
105+
it('validates each validation', function() {
106+
const all = CustomPropTypes.all(validators);
107+
108+
let result = all(props, propName, componentName);
109+
expect(result).to.equal(undefined);
110+
111+
validators.forEach(x => {
112+
x.should.have.been.calledOnce
113+
.and.calledWith(props, propName, componentName);
114+
});
115+
});
116+
117+
it('returns first validation failure', function() {
118+
let err = new Error('Failure');
119+
validators[1].returns(err);
120+
const all = CustomPropTypes.all(validators);
121+
122+
let result = all(props, propName, componentName);
123+
expect(result).to.equal(err);
124+
125+
validators[0].should.have.been.calledOnce
126+
.and.calledWith(props, propName, componentName);
127+
128+
validators[1].should.have.been.calledOnce
129+
.and.calledWith(props, propName, componentName);
130+
131+
validators[2].should.not.have.been.called;
132+
});
133+
});
70134
});

0 commit comments

Comments
 (0)