@mdf.js/faker v1.3.0
@mdf.js/faker
Table of contents
Introduction
Faker is a tool to generate fake data for testing purposes based on rosie package with some improvements.
To use @mdf.js/faker
you first define a factory. The factory is defined in terms of attributes, sequences, options, callbacks, and can inherit from other factories. Once the factory is defined you use it to build objects.
Installation
- npm
npm install @mdf.js/faker
- yarn
yarn add @mdf.js/faker
Information
There are two phases of use:
- Factory definition
- Object building
Factory Definition: Define a factory, specifying attributes, sequences, options, and callbacks:
import { Factory } from '@mdf.js/faker';
interface Player {
id: number;
name: string;
position: string;
}
interface Game {
id: number;
is_over: boolean;
created_at: Date;
random_seed: number;
players: Player[];
}
const playerFactory = new Factory<Player>()
.sequence('id')
.sequence('name', i => {
return 'player' + i;
})
// Define `position` to depend on `id`.
.attr('position', ['id'], id => {
const positions = ['pitcher', '1st base', '2nd base', '3rd base'];
return positions[id % positions.length];
});
const gameFactory = new Factory<Game>()
.sequence('id')
.attr('is_over', false)
.attr('created_at', () => new Date())
.attr('random_seed', () => Math.random())
// Default to two players. If players were given, fill in
// whatever attributes might be missing.
.attr('players', ['players'], players => {
if (!players) {
players = [{}, {}];
}
return players.map(data => playerFactory.build(data));
});
const disabledPlayer = new Factory().extend(playerFactory).attr('state', 'disabled');
Object Building: Build an object, passing in attributes that you want to override:
const game = gameFactory.build({ is_over: true });
// Built object (note scores are random):
//{
// id: 1,
// is_over: true, // overriden when building
// created_at: Fri Apr 15 2011 12:02:25 GMT-0400 (EDT),
// random_seed: 0.8999513240996748,
// players: [
// {id: 1, name:'Player 1'},
// {id: 2, name:'Player 2'}
// ]
//}
Programmatic Generation of Attributes
You can specify options that are used to programmatically generate the attributes:
import { Factory } from '@mdf.js/faker';
import moment from 'moment';
interface Match {
matchDate: string;
homeScore: number;
awayScore: number;
}
const matchFactory = new Factory<Match>()
.attr('seasonStart', '2016-01-01')
.option('numMatches', 2)
.attr('matches', ['numMatches', 'seasonStart'], (numMatches, seasonStart) => {
const matches = [];
for (const i = 1; i <= numMatches; i++) {
matches.push({
matchDate: moment(seasonStart).add(i, 'week').format('YYYY-MM-DD'),
homeScore: Math.floor(Math.random() * 5),
awayScore: Math.floor(Math.random() * 5),
});
}
return matches;
});
matchFactory.build({ seasonStart: '2016-03-12' }, { numMatches: 3 });
// Built object (note scores are random):
//{
// seasonStart: '2016-03-12',
// matches: [
// { matchDate: '2016-03-19', homeScore: 3, awayScore: 1 },
// { matchDate: '2016-03-26', homeScore: 0, awayScore: 4 },
// { matchDate: '2016-04-02', homeScore: 1, awayScore: 0 }
// ]
//}
In the example numMatches
is defined as an option
, not as an attribute
. Therefore numMatches
is not part of the output, it is only used to generate the matches
array.
In the same example seasonStart
is defined as an attribute
, therefore it appears in the output, and can also be used in the generator function that creates the matches
array.
Batch Specification of Attributes
The convenience function attrs
simplifies the common case of specifying multiple attributes in a batch. Rewriting the game
example from above:
const gameFactory = new Factory()
.sequence('id')
.attrs({
is_over: false,
created_at: () => new Date(),
random_seed: () => Math.random(),
})
.attr('players', ['players'], players => {
/* etc. */
});
Post Build Callback
You can also define a callback function to be run after building an object:
interface Coach {
id: number;
players: Player[];
}
const coachFactory = new Factory()
.option('buildPlayer', false)
.sequence('id')
.attr('players', ['id', 'buildPlayer'], (id, buildPlayer) => {
if (buildPlayer) {
return [Factory.build('player', { coach_id: id })];
}
})
.after((coach, options) => {
if (options.buildPlayer) {
console.log('built player:', coach.players[0]);
}
});
Factory.build({}, { buildPlayer: true });
Multiple callbacks can be registered, and they will be executed in the order they are registered. The callbacks can manipulate the built object before it is returned to the callee.
If the callback doesn't return anything, @mdf.js/faker
will return build object as final result. If the callback returns a value, @mdf.js/faker
will use that as final result instead.
Associate a Factory with an existing Class
This is an advanced use case that you can probably happily ignore, but store this away in case you need it.
When you define a factory you can optionally provide a class definition, and anything built by the factory will be passed through the constructor of the provided class.
Specifically, the output of .build
is used as the input to the constructor function, so the returned object is an instance of the specified class:
class SimpleClass {
constructor(args) {
this.moops = 'correct';
this.args = args;
}
isMoopsCorrect() {
return this.moops;
}
}
testFactory = Factory.define('test', SimpleClass).attr('some_var', 4);
testInstance = testFactory.build({ stuff: 2 });
console.log(JSON.stringify(testInstance, {}, 2));
// Output:
// {
// "moops": "correct",
// "args": {
// "stuff": 2,
// "some_var": 4
// }
// }
console.log(testInstance.isMoopsCorrect());
// Output:
// correct
Mind. Blown.
Use
To use @mdf.js/faker
in node, you'll need to import it first:
import { Factory } from '@mdf.js/faker';
// or with `require`
const Factory = require('@mdf.js/faker').Factory;
You might also choose to use unregistered factories, as it fits better with node's module pattern:
// factories/game.js
import { Factory } from '@mdf.js/faker';
export default new Factory().sequence('id').attr('is_over', false);
// etc
To use the unregistered Game
factory defined above:
import Game from './factories/game';
const game = Game.build({ is_over: true });
You can also extend an existing unregistered factory:
// factories/scored-game.js
import { Factory } from '@mdf.js/faker';
import Game from './game';
export default new Factory().extend(Game).attrs({
score: 10,
});
License
Copyright 2022 Mytra Control S.L. All rights reserved.
Use of this source code is governed by an MIT-style license that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
7 days ago
7 days ago
10 days ago
9 days ago
10 days ago
15 days ago
18 days ago
19 days ago
19 days ago
19 days ago
26 days ago
28 days ago
29 days ago
2 months ago
3 months ago
3 months ago
3 months ago
4 months ago
10 months ago
10 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago