factory-bot-ts
Version:
A simple library for setting up TypeScript objects as test data - heavily inspired by the awesome Ruby's factory_bot
295 lines (231 loc) • 7.25 kB
Markdown
# factory-bot-ts
A simple library for setting up [TypeScript](https://www.typescriptlang.org/) objects as test data - heavily inspired by the awesome Ruby's [factory_bot](https://github.com/thoughtbot/factory_bot).
- Fully written in [TypeScript](https://www.typescriptlang.org/)
- With (optional) type checking
- With no persistence layer
- And no promises. ☺️
## Installation
**1.** Add to your project
```sh
npm i -D factory-bot-ts
yarn add factory-bot-ts --dev
```
## Basics
**1.** Ok, suppose we've got a Ninja model..
```typescript
// ../src/models/ninja.model.ts
export enum NinjaRank {
GENIN = 'Genin',
CHUUNIN = 'Chuunin',
JONIN = 'Jonin'
}
export class Ninja {
id?: number
name?: string
username?: string
level?: NinjaRank
sensor?: boolean
constructor(attrs?: Partial<Ninja>) {
Object.assign(this, attrs)
}
}
```
**2.** We would define our factories..
```typescript
// ../src/tests/index.ts
import * as Faker from 'faker'
import { sample } from 'lodash'
import { FactoryBot } from 'factory-bot-ts'
import { Ninja, NinjaRank, Village } from '../src/models'
FactoryBot.define('ninja', {
id: () => Faker.random.number(),
name: () => Faker.name.findName(),
username: () => FactoryBot.seq(seq => `${Faker.internet.userName()}_${seq}`),
level: () => FactoryBot.rand(NinjaRank),
sensor: () => sample([true, false])
}, Ninja)
FactoryBot.define('village', {
id: () => Faker.random.uuid(),
name: () => Faker.name.findName(),
members: () => FactoryBot.buildList<Ninja>('ninja', 2)
}, Village)
export {
FactoryBot
}
```
**3.** And then we'd just use them on our tests!
```typescript
// ../src/models/ninja.model.spec.ts
import { FactoryBot } from '../src/tests'
import { Ninja, NinjaRank, Village } from '.'
export class NinjaSpec {
let instance: Ninja
before(() => {
instance = FactoryBot.build('ninja', { name: 'Kakashi Hatake' })
})
it('builds a Ninja! 👹', () => {
expect(instance).to.be.an
.instanceof(Ninja)
})
}
```
## More
Factory-bot-ts also allow us to..
**1.** Define untyped factories with static data
```typescript
FactoryBot.define('ninja', {
id: 1,
name: 'Sasuke Uchiha',
username: 'sasuke',
level: NinjaRank.GENIN,
sensor: false,
sharingan: true
})
FactoryBot.build('ninja') /* => {
id: 1,
name: 'Sasuke Uchiha',
username: 'sasuke',
level: 'Genin',
sensor: false,
sharingan: true
} */
```
**2.** Define factories with type checking
```typescript
FactoryBot.define<Ninja>('ninja', {
id: 1,
name: 'Sasuke Uchiha',
username: 'sasuke',
level: NinjaRank.GENIN,
sensor: false
}, Ninja)
FactoryBot.build('ninja') /* => Ninja {
id: 1,
name: 'Sasuke Uchiha',
username: 'sasuke',
level: 'Genin',
sensor: false
} */
```
**3.** Define factories with Dynamic data
```typescript
FactoryBot.define('ninja', {
id: () => Faker.random.number(),
name: () => Faker.name.findName(),
username: () => Faker.internet.userName(),
level: () => FactoryBot.rand(NinjaRank),
sensor: () => sample([true, false])
}, Ninja)
FactoryBot.build('ninja') /* => Ninja {
id: 43748,
name: 'Martine Romaguera MD',
username: 'Kaleb_Homenick',
level: 'Jonin',
sensor: true
} */
```
**4.** Define factories with custom, random and sequenced data
```typescript
FactoryBot.define('ninja', {
id: () => Faker.random.number(),
name: () => Faker.name.findName(),
username: () => FactoryBot.seq(seq => `${Faker.internet.userName()}_${seq}`),
level: () => FactoryBot.rand(NinjaRank),
sensor: () => sample([true, false])
}, Ninja)
FactoryBot.build<Ninja>('ninja', { name: 'Uzimaki Naruto' }) /* => Ninja {
id: 11941,
name: 'Uzimaki Naruto',
username: 'Art_Crist36_1',
level: 'Genin',
sensor: true
} */
FactoryBot.build<Ninja>('ninja', { name: 'Sasuke Uchiha', username: 'sasuke-kun' }) /* => Ninja {
id: 52565,
name: 'Sasuke Uchiha',
username: 'sasuke-kun',
level: 'Chuunin',
sensor: false
} */
```
**5.** Define chained factories
```typescript
FactoryBot.define('ninja', {
id: () => Faker.random.number(),
name: () => Faker.name.findName(),
username: () => FactoryBot.seq(seq => `${Faker.internet.userName()}_${seq}`),
level: () => FactoryBot.rand(NinjaRank),
sensor: () => sample([true, false])
}, Ninja)
FactoryBot.define('village', {
id: () => Faker.random.uuid(),
name: 'Leaf',
members: () => FactoryBot.buildList<Ninja>('ninja', 2)
}, Village)
FactoryBot.build('village') /* => Village {
id: '7ec17407-cfdb-4a3f-b434-de788eb41591',
name: 'Leaf',
members: [ Ninja {
id: 11941,
name: 'Herta Hane',
username: 'Kaleb_Homenick_5',
level: 'Genin',
sensor: true
}, Ninja {
id: 52565,
name: 'Corbin Koss',
username: 'Art_Crist36_6',
level: 'Genin',
sensor: false
}]
} */
```
**6.** Extend existing factories in order to generate specialized data
```typescript
FactoryBot.define<Ninja>('ninja', {
id: 1,
name: 'Kakashi Hatake',
username: 'kakashi',
level: NinjaRank.GENIN,
sensor: false
}, Ninja)
FactoryBot.extend<Ninja>('ninja', 'jōnin', {
level: NinjaRank.JONIN
})
FactoryBot.build<Ninja>('ninja') /* => Ninja {
id: 1,
name: 'Kakashi Hatake',
username: 'kakashi',
level: Genin,
sensor: false
} */
FactoryBot.build<Ninja>('jōnin') /* => Ninja {
id: 1,
name: 'Kakashi Hatake',
username: 'kakashi',
level: Jōnin,
sensor: false
} */
```
For more examples, please, check out the project's [specs](https://github.com/roalcantara/factory-bot-ts/blob/master/tests/factory-bot.spec.ts).
## Dependencies
To run this project we need to have:
- [Node](http://nodejs.org)
- [Yarn](http://yarnpkg.com)
## Development
1. Install the dependencies above
2. `$ git clone https://github.com/roalcantara/factory-bot-ts.git` - Clone the project
3. `$ cd factory-bot-ts` - Go into the project folder
4. `$ yarn` - Run the setup script
## Running specs
`$ yarn test` to run the specs
## How to contribute
- Bug reports and pull requests are welcome on [GitHub](https://github.com/roalcantara/factory-bot-ts)
- Follow the [Semantic Versioning Specification](http://semver.org/)
- Follow the [GitHub Flow](https://guides.github.com/introduction/flow/)
- Follow the [5 Useful Tips For A Better Commit Message](https://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message) article and the [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/) post
- Use [Commitizen cli](http://commitizen.github.io/cz-cli/) when committing
## Code of Conduct
Everyone interacting in the factory-bot-ts project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/roalcantara/factory-bot-ts/blob/master/CODE_OF_CONDUCT.md).
## License
The package is available as open source under the terms of the [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).