Skip to content

Commit

Permalink
Merge pull request #24 from markalfred/init
Browse files Browse the repository at this point in the history
Add init() method and documentation
  • Loading branch information
markalfred authored Aug 10, 2018
2 parents 5ce12b5 + 662de0f commit fdc6344
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 41 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
// New: => { foo: 'foo', bar: { bar: 'bar' } }
```

* Generator callbacks now receive `propName` as their first argument, and their definitions' argument as the second.
* `generateProps.init()` *must* be called prior to components being imported or `generateProps()` being called.

Non-breaking Changes:

* Generator callbacks now receive the `propName` as an argument.
Expand Down
58 changes: 29 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ $ npm install --save-dev react-generate-props

## Usage

**Important:**
Initialize the library *before* importing any components into your test suite.

```js
// test-helper.js

import { init } from 'react-generate-props'
init()
```

Define your component's propTypes.

```jsx
Expand Down Expand Up @@ -66,20 +76,7 @@ import generateProps from 'react-generate-props'
import Component from './component.jsx'

const props = generateProps(Component)
assertEqual(props, { title: 'string', followers: 1, user: { loggedIn: true, name: 'string' } })

render(<Component {...props}/>)

/***
Result:
<div>
<h1>string</h1>
<small>1</small>
<p>Hello, string</p>
</div>
***/
// => { title: 'title', followers: 1, user: { loggedIn: true, name: 'name' } }
```

## API
Expand Down Expand Up @@ -127,25 +124,28 @@ generateProps(Counter)
{
required: true,
// default: true. When true, props marked as .isRequired will be generated.

optional: false,
// default: false. When true, props *not* marked as .isRequired will be generated.

generators: {
// Can be used to override this lib's default generators.
// Each key is a prop type, each value is a function,
// each function receives its definition's arguments.
bool: () => false,
function: () => spy(),
instanceOf: (klass) => new klass(),
oneOf: (values) => values[values.length - 1]
// Each key is a prop type, each value is a function.
// Each function receives the propName as its first argument,
// followed by that prop type's argument, if it takes one.

bool: (propName) => false,
function: (propName) => spy(),
number: (propName) => propName.length,
instanceOf: (propName, klass) => new klass(),
oneOf: (propName, values) => values[values.length - 1]
}
}
```

## One More Example

```jsx
```js
const propTypes = {
name: PropTypes.string.isRequired,
loggedIn: PropTypes.bool,
Expand All @@ -158,13 +158,13 @@ generateProps(propTypes)
generateProps(propTypes, { optional: true })
// => { name: 'string', loggedIn: true, userType: 'admin' }

generateProps(propTypes, {
generateProps(propTypes, {
optional: true,
generators: {
string: () => 'Alice',
bool: () => false,
oneOf: (values) => values[values.length - 1]
generators: {
string: (propName) => 'Alice',
bool: (propName) => propName === 'loggedIn',
oneOf: (propName, values) => values[values.length - 1]
}
})
// => { name: 'Alice', loggedIn: false, userType: 'user' }
// => { name: 'Alice', loggedIn: true, userType: 'user' }
```
20 changes: 17 additions & 3 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ const React = require('react')
const PropTypes = require('./prop-types')

let options
let initialized = false;

const wrapPropTypes = () => {
initialized = true;
// Adds a .type key which allows the type to be derived during the
// evaluation process. This is necessary for complex types which
// return the result of a generator function, leaving no way to
Expand All @@ -27,8 +29,6 @@ const wrapPropTypes = () => {
})
}

wrapPropTypes()

const GENERATORS = {
// Simple types
array: (propName) => [propName],
Expand Down Expand Up @@ -59,7 +59,15 @@ const shouldGenerate = (propType) => {
)
}

const generateOneProp = (propType, propName, wrapInArray=true) => {
const initError = new Error(
'generateProps.init() must be called at the beginning of your test suite'
)

const generateOneProp = (propType, propName, wrapInArray = true) => {
if (propType.type === undefined && initialized === false) {
throw initError
}

const generate = options.generators[propType.type].bind(this, propName)
const arg = propType.arg
if (generate) {
Expand All @@ -82,6 +90,10 @@ const forceGenerateOneProp = (propType, propName) => {
}

const generateProps = (arg, opts) => {
if (initialized === false) {
throw initError
}

options = _.defaults({}, opts, { required: true, optional: false })
if (opts && opts.generators) {
options.generators = _.defaults({}, opts.generators, GENERATORS)
Expand All @@ -108,4 +120,6 @@ const generateProps = (arg, opts) => {
.value()
}

Object.assign(generateProps, { init: wrapPropTypes })

module.exports = generateProps
31 changes: 22 additions & 9 deletions test/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,32 @@ const ComponentAsFunction = () => 'component'

const generateProps = require('../src/main')

describe('generateProps', () => {
describe('given a bad argument', () => {
describe('generateProps (incorrect)', () => {
describe('when called before generateProps.init() was called', () => {
it('throws an error', () => {
// TODO: Add plain objects, or things like "React" to this.
const badArgs = [null, undefined, 0, 1, -1, false, true, [], NaN, '', 'string']

for (let arg of badArgs) {
let fnCall = () => generateProps(arg)
fnCall.should.throw(TypeError, 'generateProps expected a propType object or a React Component')
}
const fnCall = () => generateProps({})
fnCall.should.throw(Error, 'generateProps.init() must be called at the beginning of your test suite')
})
})

describe('given the bad argument', () => {
// TODO: Add plain objects, or things like "React" to this.
const badArgs = [null, undefined, 0, 1, -1, false, true, [], NaN, '', 'string']

for (let arg of badArgs) {
describe('(' + arg + ')', () => {
it('throws an error', () => {
generateProps.init()
let fnCall = () => generateProps(arg)
fnCall.should.throw(TypeError, 'generateProps expected a propType object or a React Component')
})
})
}
})
})

describe('generateProps (correct)', () => {
before(() => { generateProps.init() })
describe('given a required array', () => {
it('generates an array', () => {
const propTypes = { myArray: PropTypes.array.isRequired }
Expand Down

0 comments on commit fdc6344

Please sign in to comment.