1.3.0 • Published 7 days ago

@mdf.js/faker v1.3.0

Weekly downloads
-
License
MIT
Repository
github
Last release
7 days ago

@mdf.js/faker

Node Version Typescript Version Known Vulnerabilities


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:

  1. Factory definition
  2. 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.

1.4.0-beta.54

7 days ago

1.4.0-beta.53

7 days ago

1.4.0-beta.51

10 days ago

1.4.0-beta.52

9 days ago

1.4.0-beta.50

10 days ago

1.4.0-beta.48

15 days ago

1.4.0-beta.47

18 days ago

1.4.0-beta.41

19 days ago

1.4.0-beta.42

19 days ago

1.4.0-beta.43

19 days ago

1.4.0-beta.39

26 days ago

1.4.0-beta.29

28 days ago

1.4.0-beta.25

29 days ago

1.4.0-beta.12

2 months ago

1.4.0-beta.11

3 months ago

1.4.0-beta.10

3 months ago

1.4.0-beta.8

3 months ago

1.4.0-beta.1

4 months ago

1.2.2-ci.1

10 months ago

1.3.0

10 months ago

1.2.2

11 months ago

1.2.2-beta.1

11 months ago

1.2.1

11 months ago

1.2.1-beta.2

11 months ago

1.2.1-beta.1

11 months ago