├── .envrc
├── test
├── utils
│ └── test-helper.js
├── mocha.opts
└── main.js
├── .babelrc
├── .travis.yml
├── src
├── prop-types.js
└── main.js
├── .gitignore
├── LICENSE
├── CHANGELOG.md
├── package.json
└── README.md
/.envrc:
--------------------------------------------------------------------------------
1 | export PATH=./node_modules/.bin:$PATH
2 |
--------------------------------------------------------------------------------
/test/utils/test-helper.js:
--------------------------------------------------------------------------------
1 | require('chai').should()
2 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env"]
3 | }
4 |
--------------------------------------------------------------------------------
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --recursive
2 | --require test/utils/test-helper
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "6"
4 | after_success:
5 | - npm run coveralls
6 |
--------------------------------------------------------------------------------
/src/prop-types.js:
--------------------------------------------------------------------------------
1 | let PropTypes
2 |
3 | try { PropTypes = require('prop-types') }
4 | catch (e) { PropTypes = require('react').PropTypes }
5 |
6 | module.exports = PropTypes
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
39 | .env
40 | dist
41 | .DS_Store
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Mark Battersby
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [Unreleased]
2 |
3 |
4 | Changes that have landed in master but are not yet released.
5 |
6 |
7 |
8 | ## 0.5.0 (August 17, 2018)
9 | * #18 - Generator can now accept a single type and will generate it.
10 | ```js
11 | generate(PropType.bool.isRequired)
12 | // => true
13 | ```
14 |
15 | * #27 - Generator now generates Symbols.
16 |
17 | ## 0.4.0 (August 10, 2018)
18 | Breaking Changes:
19 |
20 | * #21 - Default generators now produce values that match their `propName`.
21 | ```js
22 | generate({ foo: PropType.string, bar: PropTypes.object })
23 | // Old: => { foo: 'string', bar: {} }
24 | // New: => { foo: 'foo', bar: { bar: 'bar' } }
25 | ```
26 |
27 | * #21 - Generator callbacks now receive `propName` as their first argument, and their definitions' argument as the second.
28 |
29 | * #19 - `generateProps.init()` *must* be called prior to components being imported or `generateProps()` being called.
30 |
31 | Non-breaking Changes:
32 |
33 | * #17 - Fixed: Deeply nested props wouldn't respect opts argument.
34 | ```js
35 | generate({
36 | foo: PropType.shape({
37 | bar: PropType.shape({
38 | baz: PropType.string
39 | })
40 | })
41 | }, { optional: true })
42 | // Old: => { foo: {} }
43 | // New: => { foo: { bar: { baz: 'baz' } } }
44 | ```
45 |
46 | ## 0.3.0 (October 5, 2017)
47 | * Generators are now deterministic by default. Previously, snapshot tests might break if `oneOf` or `oneOfType` were used.
48 | * `opts` can now be passed as the second arg to `generateProps` to generate or omit required or optional types. Default: `{ required: true, optional: false }`
49 | * Generators can be overridden via the `opts` argument. Syntax: `generateProps(Component, { generators: { bool: () => false } })`
50 | * `string`, `any`, and `node` generators now return exactly those strings. (`'string'`, `'any'`, or `'node'`)
51 | * React 16 and the `prop-types` package are now supported.
52 |
53 | ### A Note On React v15.3 - v16.0
54 | If you are using React v15.3 or higher, you should port your PropTypes to the
55 | new `prop-type` lib. https://github.com/facebook/prop-types
56 |
57 | ## 0.2.0 (October 18, 2016)
58 | ## 0.1.0 (October 18, 2016)
59 | ## 0.0.1 (July 14, 2016)
60 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-generate-props",
3 | "version": "0.6.1",
4 | "description": "Generate default props based on your React component's PropTypes",
5 | "main": "dist/main.js",
6 | "engines": {
7 | "node": ">=6.0.0"
8 | },
9 | "files": [
10 | "dist/*",
11 | "src/*"
12 | ],
13 | "dependencies": {
14 | "lodash": "^4.13.1"
15 | },
16 | "devDependencies": {
17 | "@babel/cli": "^7.5.5",
18 | "@babel/core": "^7.5.5",
19 | "@babel/preset-env": "^7.5.5",
20 | "chai": "^4.2.0",
21 | "coveralls": "^3.0.5",
22 | "istanbul": "^0.4.4",
23 | "mocha": "^6.2.0",
24 | "mocha-lcov-reporter": "^1.2.0",
25 | "prop-types": "^15.6.0",
26 | "react": "^16.0.0"
27 | },
28 | "peerDependencies": {
29 | "react": "0.13.x || 0.14.x || ^15.0.0-0 || 15.x || 16.x"
30 | },
31 | "scripts": {
32 | "build": "babel src -d dist",
33 | "preversion": "npm run build",
34 | "coverage": "istanbul cover _mocha",
35 | "precoveralls": "npm run coverage -- --report lcovonly",
36 | "coveralls": "cat ./coverage/lcov.info | coveralls",
37 | "postcoveralls": "rm -rf ./coverage",
38 | "test": "npm run react:no-prop-types && npm run react:with-prop-types",
39 | "react:clean": "rm -rf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils node_modules/prop-types",
40 | "react:no-prop-types": "npm run react:13 && mocha && npm run react:14.8 && mocha && npm run react:15.2 && mocha",
41 | "react:13": "npm run react:clean && npm i --no-save --no-progress react@0.13 && rm -rf node_modules/prop-types",
42 | "react:14.8": "npm run react:clean && npm i --no-save --no-progress react@0.14.8 react-dom@0.14.8 react-addons-test-utils@0.14.8 && rm -rf node_modules/prop-types",
43 | "react:15.2": "npm run react:clean && npm i --no-save --no-progress react@15.2 react-dom@15 react-addons-test-utils@15.2 && rm -rf node_modules/prop-types",
44 | "react:with-prop-types": "npm run react:14 && mocha && npm run react:15 && mocha && npm run react:16 && mocha",
45 | "react:14": "npm run react:clean && npm i --no-save --no-progress react@0.14 react-dom@0.14 react-addons-test-utils@0.14",
46 | "react:15": "npm run react:clean && npm i --no-save --no-progress react@15 react-dom@15 react-addons-test-utils@15",
47 | "react:16": "npm run react:clean && npm i --no-save --no-progress react@16 prop-types"
48 | },
49 | "repository": {
50 | "type": "git",
51 | "url": "git+https://github.com/markalfred/react-generate-props.git"
52 | },
53 | "keywords": [
54 | "react",
55 | "prop",
56 | "props",
57 | "proptypes",
58 | "generate",
59 | "generator"
60 | ],
61 | "author": "Mark Battersby",
62 | "license": "MIT",
63 | "bugs": {
64 | "url": "https://github.com/markalfred/react-generate-props/issues"
65 | },
66 | "homepage": "https://github.com/markalfred/react-generate-props#readme"
67 | }
68 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash')
2 | const React = require('react')
3 | const PropTypes = require('./prop-types')
4 |
5 | let options
6 | let initialized = false
7 |
8 | const addHiddenProperties = (obj, prop, value) => {
9 | addHiddenProperty(obj, prop, value)
10 | addHiddenProperty(obj.isRequired, prop, value)
11 | return obj
12 | }
13 |
14 | const addHiddenProperty = (obj, prop, value) =>
15 | Object.defineProperty(obj, prop, { enumerable: false, value })
16 |
17 | const wrapPropTypes = () => {
18 | initialized = true
19 | // Adds a .type key which allows the type to be derived during the
20 | // evaluation process. This is necessary for complex types which
21 | // return the result of a generator function, leaving no way to
22 | // determine which type instantiated it.
23 |
24 | const original = _.cloneDeep(PropTypes)
25 |
26 | _.each(_.keys(GENERATORS), (k) => {
27 | if (PropTypes[k] === undefined) return
28 | if (PropTypes[k].isRequired !== undefined) {
29 | // Simple type. Just extend the object
30 | PropTypes[k] = addHiddenProperties(PropTypes[k], 'type', k)
31 | } else {
32 | // Complex type. Must extend the creator's return value
33 | PropTypes[k] = (arg) => {
34 | let res = original[k](arg)
35 | res = addHiddenProperties(res, 'type', k)
36 | res = addHiddenProperties(res, 'arg', arg)
37 | return res
38 | }
39 | }
40 | })
41 | }
42 |
43 | const GENERATORS = {
44 | // Simple types
45 | array: (propName) => propName ? [propName] : [],
46 | bool: () => true,
47 | func: () => () => {},
48 | number: () => 1,
49 | object: (propName) => propName ? ({ [propName]: propName }): {},
50 | string: (propName) => propName || 'string',
51 | any: (propName) => propName || 'any',
52 | element: (propName) => React.createElement('div', propName),
53 | node: (propName) => propName || 'node',
54 | symbol: (propName) => Symbol(propName),
55 |
56 | // Complex types
57 | arrayOf: (propName, type) => {
58 | const res = generateOneProp(type, propName, false)
59 | return res ? [res] : []
60 | },
61 | instanceOf: (propName, klass) => new klass(),
62 | objectOf: (propName, type) => ({ key: generateOneProp(type, propName, false) }),
63 | oneOf: (propName, values) => _.first(values),
64 | oneOfType: (propName, types) => forceGenerateOneProp(_.first(types), propName),
65 | shape: (propName, shape) => generateProps(shape, options),
66 | exact: (propName, shape) => generateProps(shape, options)
67 | }
68 |
69 | const shouldGenerate = (propType) => {
70 | return (
71 | // Generate required props, and this is the required version
72 | (options.required && !propType.isRequired) ||
73 | // Generate optional props, and this is the optional version
74 | (options.optional && !!propType.isRequired)
75 | )
76 | }
77 |
78 | const initError = new Error(
79 | 'generateProps.init() must be called at the beginning of your test suite'
80 | )
81 |
82 | const generateOneProp = (propType, propName, wrapInArray = true) => {
83 | if (propType.type === undefined && initialized === false) {
84 | throw initError
85 | }
86 |
87 | const generate = options.generators[propType.type].bind(this, propName)
88 | const arg = propType.arg
89 | if (generate) {
90 | if (shouldGenerate(propType)) {
91 | if (wrapInArray) {
92 | return [propName, generate(arg)]
93 | } else {
94 | return generate(arg)
95 | }
96 | }
97 | }
98 | }
99 |
100 | const forceGenerateOneProp = (propType, propName) => {
101 | const generate = GENERATORS[propType.type].bind(this, propName)
102 | const arg = propType.arg
103 | if (generate) {
104 | return generate(arg)
105 | }
106 | }
107 |
108 | const generateProps = (arg, opts) => {
109 | if (initialized === false) {
110 | throw initError
111 | }
112 |
113 | options = _.defaults({}, opts, { required: true, optional: false })
114 | if (opts && opts.generators) {
115 | options.generators = _.defaults({}, opts.generators, GENERATORS)
116 | } else {
117 | options.generators = GENERATORS
118 | }
119 |
120 | let propTypes
121 |
122 | if (!arg) {
123 | throw new TypeError('generateProps expected a propType object or a React Component')
124 | }
125 |
126 | if (arg.type && GENERATORS[arg.type]) {
127 | return generateOneProp(arg, undefined, false)
128 | } else if (arg.propTypes && arg.propTypes.type && GENERATORS[arg.propTypes.type]) {
129 | return generateOneProp(arg.propTypes, undefined, false)
130 | }
131 |
132 | if (_.isPlainObject(arg.propTypes)) {
133 | propTypes = arg.propTypes
134 | } else if (_.isPlainObject(arg)) {
135 | propTypes = arg
136 | } else {
137 | throw new TypeError('generateProps expected a propType object or a React Component')
138 | }
139 |
140 | return _(propTypes)
141 | .map(generateOneProp)
142 | .compact()
143 | .fromPairs()
144 | .value()
145 | }
146 |
147 | Object.assign(generateProps, { init: wrapPropTypes })
148 |
149 | module.exports = generateProps
150 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-generate-props
2 | Generate default props based on your React component's PropTypes
3 |
4 | [](https://travis-ci.org/markalfred/react-generate-props)
5 | [](https://coveralls.io/github/markalfred/react-generate-props?branch=master)
6 |
7 | ```js
8 | generateProps({ name: PropTypes.string, number: PropTypes.number })
9 | // => { name: 'name', number: 1 }
10 | ```
11 |
12 | ## Installation
13 | ```bash
14 | $ npm install --save-dev react-generate-props
15 | ```
16 |
17 | ## Usage
18 |
19 | **Important:**
20 | Initialize the library *before* importing any components into your test suite.
21 |
22 | ```js
23 | // test-helper.js
24 |
25 | import { init } from 'react-generate-props'
26 | init()
27 | ```
28 |
29 | Define your component's propTypes.
30 |
31 | ```jsx
32 | const Counter = ({ count }) =>
{count}
33 | Counter.propTypes = { count: PropTypes.number.isRequired }
34 | export default Counter
35 | ```
36 |
37 | Pass the component to this library. It will generate reasonable props based on the defined types.
38 |
39 | ```js
40 | import generateProps from 'react-generate-props'
41 | import Counter from './counter'
42 | generateProps(Counter)
43 | // => { count: 1 }
44 | ```
45 |
46 | Use these default props to reduce boilerplate and prop type validation errors in your tests! :tada:
47 |
48 | ## Example
49 |
50 | A more in-depth example.
51 |
52 | ```jsx
53 | // component.jsx
54 |
55 | class Component extends React.Component {
56 | static propTypes = {
57 | title: PropTypes.string.isRequired,
58 | followers: PropTypes.number.isRequired,
59 | user: PropTypes.shape({
60 | loggedIn: PropTypes.bool.isRequired,
61 | name: PropTypes.string.isRequired
62 | }).isRequired
63 | }
64 |
65 | render() {
66 |
67 |
{this.props.title}
68 |
{this.props.followers}
69 | {this.props.user.loggedIn &&
Hello, {this.props.user.name}.
}
70 |
71 | }
72 | }
73 |
74 | export default Component
75 | ```
76 |
77 | ```jsx
78 | // component-test.js
79 |
80 | import generateProps from 'react-generate-props'
81 | import Component from './component.jsx'
82 |
83 | const props = generateProps(Component)
84 | // => { title: 'title', followers: 1, user: { loggedIn: true, name: 'name' } }
85 |
86 | render()
87 | /* =>
88 |
89 |
title
90 |
1
91 |
Hello, name.
92 |
93 | */
94 |
95 | ```
96 |
97 | ## API
98 |
99 | The library takes two arguments.
100 |
101 | ```js
102 | generateProps(schema, opts)
103 | ```
104 |
105 | #### `schema`: An Object, Function, or Class containing a PropTypes definition, or a single PropType. All of the following are valid:
106 |
107 | Plain Object
108 | ```js
109 | const Counter = { count: PropTypes.number.isRequired }
110 | ```
111 |
112 | Plain Object with a `propTypes` key
113 | ```js
114 | const Counter = { propTypes: { count: PropTypes.number.isRequired } }
115 | ```
116 |
117 | Functional Component
118 | ```js
119 | const Counter = ({ counter }) => {/* ... */}
120 | Counter.propTypes = { count: PropTypes.number.isRequired }
121 | ```
122 |
123 | `React.Component` Class
124 | ```js
125 | class Counter extends React.Component {
126 | static propTypes = { count: PropTypes.number.isRequired }
127 | }
128 | ```
129 |
130 | Single PropType
131 | ```js
132 | const Counter = PropTypes.shape({ count: PropTypes.number.isRequired }).isRequired
133 | ```
134 |
135 | In each of these cases, the effect would be the same
136 | ```js
137 | generateProps(Counter)
138 | // => { count: 1 }
139 | ```
140 |
141 | #### `opts`: An Object which may contain the following:
142 |
143 | ```js
144 | {
145 | required: true,
146 | // default: true. When true, props marked as .isRequired will be generated.
147 |
148 | optional: false,
149 | // default: false. When true, props *not* marked as .isRequired will be generated.
150 |
151 | generators: {
152 | // Can be used to override this lib's default generators.
153 | // Each key is a prop type, each value is a function.
154 | // Each function receives the propName as its first argument,
155 | // followed by that prop type's argument, if it takes one.
156 |
157 | bool: (propName) => false,
158 | function: (propName) => spy(),
159 | number: (propName) => propName.length,
160 | instanceOf: (propName, klass) => new klass(),
161 | oneOf: (propName, values) => values[values.length - 1]
162 | }
163 | }
164 | ```
165 |
166 | ## One More Example
167 |
168 | ```js
169 | const propTypes = {
170 | name: PropTypes.string.isRequired,
171 | loggedIn: PropTypes.bool,
172 | userType: PropTypes.oneOf(['admin', 'user']).isRequired
173 | }
174 |
175 | generateProps(propTypes)
176 | // => { name: 'string', userType: 'admin' }
177 |
178 | generateProps(propTypes, { optional: true })
179 | // => { name: 'string', loggedIn: true, userType: 'admin' }
180 |
181 | generateProps(propTypes, {
182 | optional: true,
183 | generators: {
184 | string: (propName) => 'Alice',
185 | bool: (propName) => propName === 'loggedIn',
186 | oneOf: (propName, values) => values[values.length - 1]
187 | }
188 | })
189 | // => { name: 'Alice', loggedIn: true, userType: 'user' }
190 | ```
191 |
--------------------------------------------------------------------------------
/test/main.js:
--------------------------------------------------------------------------------
1 | const React = require('react')
2 | const PropTypes = require('../src/prop-types')
3 |
4 | const ComponentAsClass = class extends React.Component { render() { 'component' } }
5 | const ComponentAsFunction = () => 'component'
6 |
7 | const generateProps = require('../src/main')
8 |
9 | describe('generateProps (incorrect)', () => {
10 | describe('when called before generateProps.init() was called', () => {
11 | it('throws an error', () => {
12 | const fnCall = () => generateProps({})
13 | fnCall.should.throw(Error, 'generateProps.init() must be called at the beginning of your test suite')
14 | })
15 | })
16 |
17 | describe('given the bad argument', () => {
18 | // TODO: Add plain objects, or things like "React" to this.
19 | const badArgs = [null, undefined, 0, 1, -1, false, true, [], NaN, '', 'string']
20 |
21 | for (let arg of badArgs) {
22 | describe('(' + arg + ')', () => {
23 | it('throws an error', () => {
24 | generateProps.init()
25 | let fnCall = () => generateProps(arg)
26 | fnCall.should.throw(TypeError, 'generateProps expected a propType object or a React Component')
27 | })
28 | })
29 | }
30 | })
31 | })
32 |
33 | describe('generateProps (correct)', () => {
34 | before(() => { generateProps.init() })
35 | describe('given a required array', () => {
36 | it('generates an array', () => {
37 | const propTypes = { myArray: PropTypes.array.isRequired }
38 | ComponentAsClass.propTypes = propTypes
39 | ComponentAsFunction.propTypes = propTypes
40 |
41 | const expected = { myArray: ['myArray'] }
42 |
43 | generateProps(propTypes).should.deep.equal(expected)
44 | generateProps({ propTypes }).should.deep.equal(expected)
45 | generateProps(ComponentAsClass).should.deep.equal(expected)
46 | generateProps(ComponentAsFunction).should.deep.equal(expected)
47 | generateProps(propTypes.myArray).should.deep.equal([])
48 | })
49 | })
50 |
51 | describe('given a required bool', () => {
52 | it('generates a bool', () => {
53 | const propTypes = { myBool: PropTypes.bool.isRequired }
54 | ComponentAsClass.propTypes = propTypes
55 | ComponentAsFunction.propTypes = propTypes
56 |
57 | const expected = { myBool: true }
58 |
59 | generateProps(propTypes).should.deep.equal(expected)
60 | generateProps({ propTypes }).should.deep.equal(expected)
61 | generateProps(ComponentAsClass).should.deep.equal(expected)
62 | generateProps(ComponentAsFunction).should.deep.equal(expected)
63 | generateProps(propTypes.myBool).should.equal(true)
64 | })
65 | })
66 |
67 | describe('given a required func', () => {
68 | it('generates a func', () => {
69 | const propTypes = { myFunc: PropTypes.func.isRequired }
70 | ComponentAsClass.propTypes = propTypes
71 | ComponentAsFunction.propTypes = propTypes
72 |
73 | generateProps(propTypes).myFunc.should.be.a('function')
74 | generateProps({ propTypes }).myFunc.should.be.a('function')
75 | generateProps(ComponentAsClass).myFunc.should.be.a('function')
76 | generateProps(ComponentAsFunction).myFunc.should.be.a('function')
77 | generateProps(propTypes.myFunc).should.be.a('function')
78 | })
79 | })
80 |
81 | describe('given a required number', () => {
82 | it('generates a number', () => {
83 | const propTypes = { myNumber: PropTypes.number.isRequired }
84 | ComponentAsClass.propTypes = propTypes
85 | ComponentAsFunction.propTypes = propTypes
86 |
87 | const expected = { myNumber: 1 }
88 |
89 | generateProps(propTypes).should.deep.equal(expected)
90 | generateProps({ propTypes }).should.deep.equal(expected)
91 | generateProps(ComponentAsClass).should.deep.equal(expected)
92 | generateProps(ComponentAsFunction).should.deep.equal(expected)
93 | generateProps(propTypes.myNumber).should.equal(1)
94 | })
95 | })
96 |
97 | describe('given a required object', () => {
98 | it('generates an object', () => {
99 | const propTypes = { myObject: PropTypes.object.isRequired }
100 | ComponentAsClass.propTypes = propTypes
101 | ComponentAsFunction.propTypes = propTypes
102 |
103 | const expected = { myObject: { myObject: 'myObject' } }
104 |
105 | generateProps(propTypes).should.deep.equal(expected)
106 | generateProps({ propTypes }).should.deep.equal(expected)
107 | generateProps(ComponentAsClass).should.deep.equal(expected)
108 | generateProps(ComponentAsFunction).should.deep.equal(expected)
109 | generateProps(propTypes.myObject).should.deep.equal({})
110 | })
111 | })
112 |
113 | describe('given a required string', () => {
114 | it('generates a string', () => {
115 | const propTypes = { myString: PropTypes.string.isRequired }
116 | ComponentAsClass.propTypes = propTypes
117 | ComponentAsFunction.propTypes = propTypes
118 |
119 | const expected = { myString: 'myString' }
120 |
121 | generateProps(propTypes).should.deep.equal(expected)
122 | generateProps({ propTypes }).should.deep.equal(expected)
123 | generateProps(ComponentAsClass).should.deep.equal(expected)
124 | generateProps(ComponentAsFunction).should.deep.equal(expected)
125 | generateProps(propTypes.myString).should.deep.equal('string')
126 | })
127 | })
128 |
129 | describe('given a required any', () => {
130 | it('generates an any', () => {
131 | const propTypes = { myAny: PropTypes.any.isRequired }
132 | ComponentAsClass.propTypes = propTypes
133 | ComponentAsFunction.propTypes = propTypes
134 |
135 | const expected = { myAny: 'myAny' }
136 |
137 | generateProps(propTypes).should.deep.equal(expected)
138 | generateProps({ propTypes }).should.deep.equal(expected)
139 | generateProps(ComponentAsClass).should.deep.equal(expected)
140 | generateProps(ComponentAsFunction).should.deep.equal(expected)
141 | generateProps(propTypes.myAny).should.deep.equal('any')
142 | })
143 | })
144 |
145 | describe('given a required element', () => {
146 | it('generates a react element', () => {
147 | const propTypes = { myElement: PropTypes.element.isRequired }
148 | ComponentAsClass.propTypes = propTypes
149 | ComponentAsFunction.propTypes = propTypes
150 |
151 | const expected = { myElement: React.createElement('div', 'myElement') }
152 |
153 | generateProps(propTypes).should.deep.equal(expected)
154 | generateProps({ propTypes }).should.deep.equal(expected)
155 | generateProps(ComponentAsClass).should.deep.equal(expected)
156 | generateProps(ComponentAsFunction).should.deep.equal(expected)
157 | generateProps(propTypes.myElement).should.deep.equal(React.createElement('div'))
158 | })
159 | })
160 |
161 | describe('given a required node', () => {
162 | it('generates a node', () => {
163 | const propTypes = { myNode: PropTypes.node.isRequired }
164 | ComponentAsClass.propTypes = propTypes
165 | ComponentAsFunction.propTypes = propTypes
166 |
167 | const expected = { myNode: 'myNode' }
168 |
169 | generateProps(propTypes).should.deep.equal(expected)
170 | generateProps({ propTypes }).should.deep.equal(expected)
171 | generateProps(ComponentAsClass).should.deep.equal(expected)
172 | generateProps(ComponentAsFunction).should.deep.equal(expected)
173 | generateProps(propTypes.myNode).should.deep.equal('node')
174 | })
175 | })
176 |
177 | describe('given a required symbol', () => {
178 | it('generates a symbol', () => {
179 | if (PropTypes.symbol === undefined) return
180 |
181 | const propTypes = { mySymbol: PropTypes.symbol.isRequired }
182 | ComponentAsClass.propTypes = propTypes
183 | ComponentAsFunction.propTypes = propTypes
184 |
185 | const expected = 'Symbol(mySymbol)'
186 |
187 | generateProps(propTypes).mySymbol.toString().should.equal(expected)
188 | generateProps({ propTypes }).mySymbol.toString().should.equal(expected)
189 | generateProps(ComponentAsClass).mySymbol.toString().should.equal(expected)
190 | generateProps(ComponentAsFunction).mySymbol.toString().should.equal(expected)
191 | generateProps(propTypes.mySymbol).toString().should.equal('Symbol()')
192 | })
193 | })
194 |
195 | describe('given a required arrayOf', () => {
196 | describe('required arrays', () => {
197 | it('generates an array of arrays', () => {
198 | const propTypes = { myArrayOfArrays: PropTypes.arrayOf(PropTypes.array.isRequired).isRequired }
199 | ComponentAsClass.propTypes = propTypes
200 | ComponentAsFunction.propTypes = propTypes
201 |
202 | const expected = { myArrayOfArrays: [['myArrayOfArrays']] }
203 |
204 | generateProps(propTypes).should.deep.equal(expected)
205 | generateProps({ propTypes }).should.deep.equal(expected)
206 | generateProps(ComponentAsClass).should.deep.equal(expected)
207 | generateProps(ComponentAsFunction).should.deep.equal(expected)
208 | generateProps(propTypes.myArrayOfArrays).should.deep.equal([[]])
209 | })
210 | })
211 |
212 | describe('required bools', () => {
213 | it('generates an array of bools', () => {
214 | const propTypes = { myArrayOfBools: PropTypes.arrayOf(PropTypes.bool.isRequired).isRequired }
215 | ComponentAsClass.propTypes = propTypes
216 | ComponentAsFunction.propTypes = propTypes
217 |
218 | const expected = { myArrayOfBools: [true] }
219 |
220 | generateProps(propTypes).should.deep.equal(expected)
221 | generateProps({ propTypes }).should.deep.equal(expected)
222 | generateProps(ComponentAsClass).should.deep.equal(expected)
223 | generateProps(ComponentAsFunction).should.deep.equal(expected)
224 | generateProps(propTypes.myArrayOfBools).should.deep.equal([true])
225 | })
226 | })
227 |
228 | describe('required funcs', () => {
229 | it('generates an array of funcs', () => {
230 | const propTypes = { myArrayOfFuncs: PropTypes.arrayOf(PropTypes.func.isRequired).isRequired }
231 | ComponentAsClass.propTypes = propTypes
232 | ComponentAsFunction.propTypes = propTypes
233 |
234 | generateProps(propTypes).myArrayOfFuncs[0].should.be.a('function')
235 | generateProps({ propTypes }).myArrayOfFuncs[0].should.be.a('function')
236 | generateProps(ComponentAsClass).myArrayOfFuncs[0].should.be.a('function')
237 | generateProps(ComponentAsFunction).myArrayOfFuncs[0].should.be.a('function')
238 | generateProps(propTypes.myArrayOfFuncs)[0].should.be.a('function')
239 | })
240 | })
241 |
242 | describe('required numbers', () => {
243 | it('generates an array of numbers', () => {
244 | const propTypes = { myArrayOfNumbers: PropTypes.arrayOf(PropTypes.number.isRequired).isRequired }
245 | ComponentAsClass.propTypes = propTypes
246 | ComponentAsFunction.propTypes = propTypes
247 |
248 | const expected = { myArrayOfNumbers: [1] }
249 |
250 | generateProps(propTypes).should.deep.equal(expected)
251 | generateProps({ propTypes }).should.deep.equal(expected)
252 | generateProps(ComponentAsClass).should.deep.equal(expected)
253 | generateProps(ComponentAsFunction).should.deep.equal(expected)
254 | generateProps(propTypes.myArrayOfNumbers).should.deep.equal([1])
255 | })
256 | })
257 |
258 | describe('required objects', () => {
259 | it('generates an array of objects', () => {
260 | const propTypes = { myArrayOfObjects: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired }
261 | ComponentAsClass.propTypes = propTypes
262 | ComponentAsFunction.propTypes = propTypes
263 |
264 | const expected = { myArrayOfObjects: [{ myArrayOfObjects: 'myArrayOfObjects' }] }
265 |
266 | generateProps(propTypes).should.deep.equal(expected)
267 | generateProps({ propTypes }).should.deep.equal(expected)
268 | generateProps(ComponentAsClass).should.deep.equal(expected)
269 | generateProps(ComponentAsFunction).should.deep.equal(expected)
270 | generateProps(propTypes.myArrayOfObjects).should.deep.equal([{}])
271 | })
272 | })
273 |
274 | describe('required strings', () => {
275 | it('generates an array of strings', () => {
276 | const propTypes = { myArrayOfStrings: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired }
277 | ComponentAsClass.propTypes = propTypes
278 | ComponentAsFunction.propTypes = propTypes
279 |
280 | const expected = { myArrayOfStrings: ['myArrayOfStrings'] }
281 |
282 | generateProps(propTypes).should.deep.equal(expected)
283 | generateProps({ propTypes }).should.deep.equal(expected)
284 | generateProps(ComponentAsClass).should.deep.equal(expected)
285 | generateProps(ComponentAsFunction).should.deep.equal(expected)
286 | generateProps(propTypes.myArrayOfStrings).should.deep.equal(['string'])
287 | })
288 | })
289 |
290 | describe('required anys', () => {
291 | it('generates an array of anys', () => {
292 | const propTypes = { myArrayOfAnys: PropTypes.arrayOf(PropTypes.any.isRequired).isRequired }
293 | ComponentAsClass.propTypes = propTypes
294 | ComponentAsFunction.propTypes = propTypes
295 |
296 | const expected = { myArrayOfAnys: ['myArrayOfAnys'] }
297 |
298 | generateProps(propTypes).should.deep.equal(expected)
299 | generateProps({ propTypes }).should.deep.equal(expected)
300 | generateProps(ComponentAsClass).should.deep.equal(expected)
301 | generateProps(ComponentAsFunction).should.deep.equal(expected)
302 | generateProps(propTypes.myArrayOfAnys).should.deep.equal(['any'])
303 | })
304 | })
305 | })
306 |
307 | describe('given a required instanceOf(MyClass)', () => {
308 | it('generates a an instance of MyClass', () => {
309 | class MyClass {}
310 |
311 | const propTypes = { myInstance: PropTypes.instanceOf(MyClass).isRequired }
312 | ComponentAsClass.propTypes = propTypes
313 | ComponentAsFunction.propTypes = propTypes
314 |
315 | const expected = { myInstance: new MyClass() }
316 |
317 | generateProps(propTypes).should.deep.equal(expected)
318 | generateProps({ propTypes }).should.deep.equal(expected)
319 | generateProps(ComponentAsClass).should.deep.equal(expected)
320 | generateProps(ComponentAsFunction).should.deep.equal(expected)
321 | generateProps(propTypes.myInstance).should.deep.equal(new MyClass())
322 | })
323 | })
324 |
325 | describe('given a required objectOf', () => {
326 | describe('required arrays', () => {
327 | it('generates an array of arrays', () => {
328 | const propTypes = { myObjectOfArrays: PropTypes.objectOf(PropTypes.array.isRequired).isRequired }
329 | ComponentAsClass.propTypes = propTypes
330 | ComponentAsFunction.propTypes = propTypes
331 |
332 | const expected = { myObjectOfArrays: { key: ['myObjectOfArrays'] } }
333 |
334 | generateProps(propTypes).should.deep.equal(expected)
335 | generateProps({ propTypes }).should.deep.equal(expected)
336 | generateProps(ComponentAsClass).should.deep.equal(expected)
337 | generateProps(ComponentAsFunction).should.deep.equal(expected)
338 | generateProps(propTypes.myObjectOfArrays).should.deep.equal({ key: [] })
339 | })
340 | })
341 |
342 | describe('required bools', () => {
343 | it('generates an array of bools', () => {
344 | const propTypes = { myObjectOfBools: PropTypes.objectOf(PropTypes.bool.isRequired).isRequired }
345 | ComponentAsClass.propTypes = propTypes
346 | ComponentAsFunction.propTypes = propTypes
347 |
348 | const expected = { myObjectOfBools: { key: true } }
349 |
350 | generateProps(propTypes).should.deep.equal(expected)
351 | generateProps({ propTypes }).should.deep.equal(expected)
352 | generateProps(ComponentAsClass).should.deep.equal(expected)
353 | generateProps(ComponentAsFunction).should.deep.equal(expected)
354 | generateProps(propTypes.myObjectOfBools).should.deep.equal({ key: true })
355 | })
356 | })
357 |
358 | describe('required funcs', () => {
359 | it('generates an array of funcs', () => {
360 | const propTypes = { myObjectOfFuncs: PropTypes.objectOf(PropTypes.func.isRequired).isRequired }
361 | ComponentAsClass.propTypes = propTypes
362 | ComponentAsFunction.propTypes = propTypes
363 |
364 | generateProps(propTypes).myObjectOfFuncs.key.should.be.a('function')
365 | generateProps({ propTypes }).myObjectOfFuncs.key.should.be.a('function')
366 | generateProps(ComponentAsClass).myObjectOfFuncs.key.should.be.a('function')
367 | generateProps(ComponentAsFunction).myObjectOfFuncs.key.should.be.a('function')
368 | generateProps(propTypes.myObjectOfFuncs).key.should.be.a('function')
369 | })
370 | })
371 |
372 | describe('required numbers', () => {
373 | it('generates an array of numbers', () => {
374 | const propTypes = { myObjectOfNumbers: PropTypes.objectOf(PropTypes.number.isRequired).isRequired }
375 | ComponentAsClass.propTypes = propTypes
376 | ComponentAsFunction.propTypes = propTypes
377 |
378 | const expected = { myObjectOfNumbers: { key: 1 } }
379 |
380 | generateProps(propTypes).should.deep.equal(expected)
381 | generateProps({ propTypes }).should.deep.equal(expected)
382 | generateProps(ComponentAsClass).should.deep.equal(expected)
383 | generateProps(ComponentAsFunction).should.deep.equal(expected)
384 | generateProps(propTypes.myObjectOfNumbers).should.deep.equal({ key: 1 })
385 | })
386 | })
387 |
388 | describe('required objects', () => {
389 | it('generates an array of objects', () => {
390 | const propTypes = { myObjectOfObjects: PropTypes.objectOf(PropTypes.object.isRequired).isRequired }
391 | ComponentAsClass.propTypes = propTypes
392 | ComponentAsFunction.propTypes = propTypes
393 |
394 | const expected = { myObjectOfObjects: { key: { myObjectOfObjects: 'myObjectOfObjects' } } }
395 |
396 | generateProps(propTypes).should.deep.equal(expected)
397 | generateProps({ propTypes }).should.deep.equal(expected)
398 | generateProps(ComponentAsClass).should.deep.equal(expected)
399 | generateProps(ComponentAsFunction).should.deep.equal(expected)
400 | generateProps(propTypes.myObjectOfObjects).should.deep.equal({ key: {} })
401 | })
402 | })
403 |
404 | describe('required strings', () => {
405 | it('generates an array of strings', () => {
406 | const propTypes = { myObjectOfStrings: PropTypes.objectOf(PropTypes.string.isRequired).isRequired }
407 | ComponentAsClass.propTypes = propTypes
408 | ComponentAsFunction.propTypes = propTypes
409 |
410 | const expected = { myObjectOfStrings: { key: 'myObjectOfStrings' } }
411 |
412 | generateProps(propTypes).should.deep.equal(expected)
413 | generateProps({ propTypes }).should.deep.equal(expected)
414 | generateProps(ComponentAsClass).should.deep.equal(expected)
415 | generateProps(ComponentAsFunction).should.deep.equal(expected)
416 | generateProps(propTypes.myObjectOfStrings).should.deep.equal({ key: 'string' })
417 | })
418 | })
419 |
420 | describe('required anys', () => {
421 | it('generates an array of anys', () => {
422 | const propTypes = { myObjectOfAnys: PropTypes.objectOf(PropTypes.any.isRequired).isRequired }
423 | ComponentAsClass.propTypes = propTypes
424 | ComponentAsFunction.propTypes = propTypes
425 |
426 | const expected = { myObjectOfAnys: { key: 'myObjectOfAnys' } }
427 |
428 | generateProps(propTypes).should.deep.equal(expected)
429 | generateProps({ propTypes }).should.deep.equal(expected)
430 | generateProps(ComponentAsClass).should.deep.equal(expected)
431 | generateProps(ComponentAsFunction).should.deep.equal(expected)
432 | generateProps(propTypes.myObjectOfAnys).should.deep.equal({ key: 'any' })
433 | })
434 | })
435 | })
436 |
437 | describe('given a required oneOf', () => {
438 | describe('foo or bar', () => {
439 | it('generates the first option, foo', () => {
440 | const propTypes = { myFooOrBar: PropTypes.oneOf(['foo', 'bar']).isRequired }
441 | ComponentAsClass.propTypes = propTypes
442 | ComponentAsFunction.propTypes = propTypes
443 |
444 | const expected = 'foo'
445 |
446 | generateProps(propTypes).myFooOrBar.should.equal(expected)
447 | generateProps({ propTypes }).myFooOrBar.should.equal(expected)
448 | generateProps(ComponentAsClass).myFooOrBar.should.equal(expected)
449 | generateProps(ComponentAsFunction).myFooOrBar.should.equal(expected)
450 | generateProps(propTypes.myFooOrBar).should.equal(expected)
451 | })
452 | })
453 | })
454 |
455 | describe('given a required oneOfType', () => {
456 | describe('bool or', () => {
457 | describe('number', () => {
458 | it('generates the first option, a bool', () => {
459 | const propTypes = { myBoolOrNumber: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]).isRequired }
460 | ComponentAsClass.propTypes = propTypes
461 | ComponentAsFunction.propTypes = propTypes
462 |
463 | const expected = true
464 |
465 | generateProps(propTypes).myBoolOrNumber.should.equal(expected)
466 | generateProps({ propTypes }).myBoolOrNumber.should.equal(expected)
467 | generateProps(ComponentAsClass).myBoolOrNumber.should.equal(expected)
468 | generateProps(ComponentAsFunction).myBoolOrNumber.should.equal(expected)
469 | })
470 | })
471 | })
472 | })
473 |
474 | describe('given a required shape', () => {
475 | describe('with a required array value', () => {
476 | it('generates an object with an array value', () => {
477 | const propTypes = { myShape: PropTypes.shape({ myArray: PropTypes.array.isRequired }).isRequired }
478 | ComponentAsClass.propTypes = propTypes
479 | ComponentAsFunction.propTypes = propTypes
480 |
481 | const expected = { myShape: { myArray: ['myArray'] } }
482 |
483 | generateProps(propTypes).should.deep.equal(expected)
484 | generateProps({ propTypes }).should.deep.equal(expected)
485 | generateProps(ComponentAsClass).should.deep.equal(expected)
486 | generateProps(ComponentAsFunction).should.deep.equal(expected)
487 | generateProps(propTypes.myShape).should.deep.equal(expected.myShape)
488 | })
489 |
490 | describe('and a required bool', () => {
491 | it('generates an object with an array value and a bool value', () => {
492 | const propTypes = {
493 | myShape: PropTypes.shape({
494 | myArray: PropTypes.array.isRequired,
495 | myBool: PropTypes.bool.isRequired
496 | }).isRequired
497 | }
498 | ComponentAsClass.propTypes = propTypes
499 | ComponentAsFunction.propTypes = propTypes
500 |
501 | const expected = { myShape: { myArray: ['myArray'], myBool: true } }
502 |
503 | generateProps(propTypes).should.deep.equal(expected)
504 | generateProps({ propTypes }).should.deep.equal(expected)
505 | generateProps(ComponentAsClass).should.deep.equal(expected)
506 | generateProps(ComponentAsFunction).should.deep.equal(expected)
507 | generateProps(propTypes.myShape).should.deep.equal(expected.myShape)
508 | })
509 | })
510 |
511 | describe('and a required shape', () => {
512 | describe('with a required number', () => {
513 | it('generates an object with an array value and a sub-object with bool value', () => {
514 | const propTypes = {
515 | myShape: PropTypes.shape({
516 | myArray: PropTypes.array.isRequired,
517 | mySubShape: PropTypes.shape({
518 | myNumber: PropTypes.number.isRequired
519 | }).isRequired
520 | }).isRequired
521 | }
522 | ComponentAsClass.propTypes = propTypes
523 | ComponentAsFunction.propTypes = propTypes
524 |
525 | const expected = { myShape: { myArray: ['myArray'], mySubShape: { myNumber: 1 } } }
526 |
527 | generateProps(propTypes).should.deep.equal(expected)
528 | generateProps({ propTypes }).should.deep.equal(expected)
529 | generateProps(ComponentAsClass).should.deep.equal(expected)
530 | generateProps(ComponentAsFunction).should.deep.equal(expected)
531 | generateProps(propTypes.myShape).should.deep.equal(expected.myShape)
532 | })
533 | })
534 | })
535 | })
536 | })
537 |
538 | describe('given a required exact', () => {
539 | describe('with a required array value', () => {
540 | it('generates an object with an array value', () => {
541 | if (!PropTypes.exact) return
542 |
543 | const propTypes = { myExact: PropTypes.exact({ myArray: PropTypes.array.isRequired }).isRequired }
544 | ComponentAsClass.propTypes = propTypes
545 | ComponentAsFunction.propTypes = propTypes
546 |
547 | const expected = { myExact: { myArray: ['myArray'] } }
548 |
549 | generateProps(propTypes).should.deep.equal(expected)
550 | generateProps({ propTypes }).should.deep.equal(expected)
551 | generateProps(ComponentAsClass).should.deep.equal(expected)
552 | generateProps(ComponentAsFunction).should.deep.equal(expected)
553 | generateProps(propTypes.myExact).should.deep.equal(expected.myExact)
554 | })
555 |
556 | describe('and a required bool', () => {
557 | it('generates an object with an array value and a bool value', () => {
558 | if (!PropTypes.exact) return
559 |
560 | const propTypes = {
561 | myExact: PropTypes.exact({
562 | myArray: PropTypes.array.isRequired,
563 | myBool: PropTypes.bool.isRequired
564 | }).isRequired
565 | }
566 | ComponentAsClass.propTypes = propTypes
567 | ComponentAsFunction.propTypes = propTypes
568 |
569 | const expected = { myExact: { myArray: ['myArray'], myBool: true } }
570 |
571 | generateProps(propTypes).should.deep.equal(expected)
572 | generateProps({ propTypes }).should.deep.equal(expected)
573 | generateProps(ComponentAsClass).should.deep.equal(expected)
574 | generateProps(ComponentAsFunction).should.deep.equal(expected)
575 | generateProps(propTypes.myExact).should.deep.equal(expected.myExact)
576 | })
577 | })
578 |
579 | describe('and a required shape', () => {
580 | describe('with a required number', () => {
581 | it('generates an object with an array value and a sub-object with bool value', () => {
582 | if (!PropTypes.exact) return
583 |
584 | const propTypes = {
585 | myExact: PropTypes.exact({
586 | myArray: PropTypes.array.isRequired,
587 | mySubShape: PropTypes.shape({
588 | myNumber: PropTypes.number.isRequired
589 | }).isRequired
590 | }).isRequired
591 | }
592 | ComponentAsClass.propTypes = propTypes
593 | ComponentAsFunction.propTypes = propTypes
594 |
595 | const expected = { myExact: { myArray: ['myArray'], mySubShape: { myNumber: 1 } } }
596 |
597 | generateProps(propTypes).should.deep.equal(expected)
598 | generateProps({ propTypes }).should.deep.equal(expected)
599 | generateProps(ComponentAsClass).should.deep.equal(expected)
600 | generateProps(ComponentAsFunction).should.deep.equal(expected)
601 | generateProps(propTypes.myExact).should.deep.equal(expected.myExact)
602 | })
603 | })
604 | })
605 | })
606 | })
607 | })
608 |
609 | describe('generateProps(opts)', () => {
610 | const propTypes = {
611 | optionalArray: PropTypes.array,
612 | requiredArray: PropTypes.array.isRequired,
613 | optionalBool: PropTypes.bool,
614 | requiredBool: PropTypes.bool.isRequired,
615 | optionalNumber: PropTypes.number,
616 | requiredNumber: PropTypes.number.isRequired,
617 | optionalObject: PropTypes.object,
618 | requiredObject: PropTypes.object.isRequired,
619 | optionalString: PropTypes.string,
620 | requiredString: PropTypes.string.isRequired,
621 | optionalAny: PropTypes.any,
622 | requiredAny: PropTypes.any.isRequired,
623 | optionalElement: PropTypes.element,
624 | requiredElement: PropTypes.element.isRequired,
625 | optionalNode: PropTypes.node,
626 | requiredNode: PropTypes.node.isRequired
627 | }
628 |
629 | const required = {
630 | requiredArray: ['requiredArray'],
631 | requiredBool: true,
632 | requiredNumber: 1,
633 | requiredObject: { requiredObject: 'requiredObject' },
634 | requiredString: 'requiredString',
635 | requiredAny: 'requiredAny',
636 | requiredElement: React.createElement('div', 'requiredElement'),
637 | requiredNode: 'requiredNode'
638 | }
639 |
640 | const optional = {
641 | optionalArray: ['optionalArray'],
642 | optionalBool: true,
643 | optionalNumber: 1,
644 | optionalObject: { optionalObject: 'optionalObject' },
645 | optionalString: 'optionalString',
646 | optionalAny: 'optionalAny',
647 | optionalElement: React.createElement('div', 'optionalElement'),
648 | optionalNode: 'optionalNode'
649 | }
650 |
651 | describe('given opts = ', () => {
652 | describe('undefined', () => {
653 | it('generates required props only by default', () => {
654 | const expected = required
655 | generateProps(propTypes).should.deep.equal(expected)
656 | })
657 | })
658 |
659 | describe('{ required: true }', () => {
660 | it('generates required props', () => {
661 | const expected = required
662 | generateProps(propTypes, { required: true }).should.deep.equal(expected)
663 | })
664 | })
665 |
666 | describe('{ required: false }', () => {
667 | it('does not generate required props', () => {
668 | const expected = {}
669 | generateProps(propTypes, { required: false }).should.deep.equal(expected)
670 | })
671 | })
672 |
673 | describe('{ optional: true }', () => {
674 | it('generates optional props', () => {
675 | const expected = Object.assign({}, required, optional)
676 | generateProps(propTypes, { optional: true }).should.deep.equal(expected)
677 | })
678 |
679 | it('generates optional props in nested objects', () => {
680 | const expected = Object.assign({}, required, optional)
681 | generateProps({ wrappingShape: PropTypes.shape(propTypes) }, { optional: true })
682 | .should.deep.equal({ wrappingShape: expected })
683 | })
684 | })
685 |
686 | describe('{ optional: false }', () => {
687 | it('does not generate optional props', () => {
688 | const expected = required
689 | generateProps(propTypes, { optional: false }).should.deep.equal(expected)
690 | })
691 | })
692 | })
693 |
694 | describe('given opts.generators = ', () => {
695 | describe('with bool override', () => {
696 | it('generates a custom bool', () => {
697 | const opts = { generators: { bool: () => false } }
698 | generateProps(propTypes, opts).requiredBool.should.be.false
699 | })
700 | })
701 | })
702 | })
703 |
704 | describe('PropTypes.checkPropTypes', () => {
705 | before(() => {
706 | generateProps.init()
707 | global._errorBackup = global.console.error
708 | global.console.error = err => { throw err }
709 | })
710 | after(() => {
711 | global.console.error = global._errorBackup
712 | })
713 |
714 | it('handles a generated shape', () => {
715 | const shape = PropTypes.shape({ myAny: PropTypes.any.isRequired }).isRequired
716 | const props = generateProps(shape)
717 | const fn = () => PropTypes.checkPropTypes
718 | ? PropTypes.checkPropTypes(shape, props)
719 | : shape(props)
720 | fn.should.not.throw()
721 | })
722 | })
723 |
--------------------------------------------------------------------------------