Giter Club home page Giter Club logo

factory-bot's Introduction

factory-bot

factory-bot is a factory library for Node.js. It works asynchronously and supports associations and the use of functions for generating attributes.

Installation

Node.js:

npm install factory-bot

Usage

Refer to the tutorial for a gentle introduction of building a simple user factory.

Here's the crash course:

const factory = require('factory-bot').factory;
const User    = require('../models/user');

factory.define('user', User, {
  username: 'Bob',
  score: 50,
});

factory.build('user').then(user => {
  console.log(user); // => User {username: 'Bob', score: 50}
});

Defining Factories

Define factories using the factory.define() method.

For example:

// Using objects as initializer
factory.define('product', Product, {
  // use sequences to generate values sequentially
  id: factory.sequence('Product.id', (n) => `product_${n}`),
  // use functions to compute some complex value
  launchDate: () => new Date(),
  // return a promise to populate data asynchronously
  asyncData: () => fetch('some/resource'),
});
factory.define('user', User, {
  // seq is an alias for sequence
  email: factory.seq('User.email', (n) => `user${n}@ymail.com`),

  // use the chance(http://chancejs.com/) library to generate
  // real-life like data.
  // For repeatable results, call factory.chance.seed(<value>) first.
  about: factory.chance('sentence'),

  // use assoc to associate with other models
  profileImage: factory.assoc('profile_image', '_id'),

  // or assocMany to associate multiple models
  addresses: factory.assocMany('address', 2, '_id'),

  // use assocAttrs to embed models that are not persisted
  creditCardNumber: factory.assocAttrs('credit_card', 'number', {type: 'masterCard'}),

  // use assocAttrs or assocAttrsMany to embed plain json objects
  twitterDetails: factory.assocAttrs('twitter_details'),
});
// Using functions as initializer
factory.define('account', Account, buildOptions => {
  let attrs = {
    confirmed: false,
    confirmedAt: null
  };

  // use build options to modify the returned object
  if (buildOptions.confirmedUser) {
    attrs.confirmed = true;
    attrs.confirmedAt = new Date();
  }
  return attrs;
});

// buildOptions can be passed while requesting an object
factory.build('account', {}, {confirmed: true});

Options

Options can be provided when you define a factory:

factory.define('user', User, { foo: 'bar' }, options);

Alternatively you can set options for the factory that will get applied for all model-factories:

factory.withOptions(options);

Currently the supported options are:

afterBuild: function(model, attrs, buildOptions)

Provides a function that is called after the model is built. The function should return the instance or a Promise for the instance.

afterCreate: function(model, attrs, buildOptions)

Provides a function that is called after a new model instance is saved. The function should return the instance or throw an error. For asynchronous functions, it should return a promise that resolves with the instance or rejects with the error.

factory.define('user', User, {foo: 'bar'}, {
  afterBuild: (model, attrs, buildOptions) => {
    return doSomethingAsync(model).then(() => {
      doWhateverElse(model);
      return model;
    });
  },
  afterCreate: (model, attrs, buildOptions) => {
    modify(model);
    if ('something' === 'wrong') {
      throw new Error;
    }
    maybeLog('something');
    return model;
  }
});

Extending Factories

You can extend a factory using #extend:

factory.define('user', User, { username: 'Bob', expired: false });
factory.extend('user', 'expiredUser', { expired: true });
factory.build('expiredUser').then(user => {
  console.log(user); // => User { username: 'Bob', expired: true });
});

#extend(parent, name, initializer, options = {})

The #extend method takes the same options as #define except you can provide a different Model using options.model.

Using Factories

Factory#attrs

Generates and returns model attributes as an object hash instead of the model instance. This may be useful where you need a JSON representation of the model e.g. mocking an API response.

factory.attrs('post').then(postAttrs => {
  // postAttrs is a json representation of the Post model
});

factory.attrs('post', {title: 'Foo', content: 'Bar'}).then(postAttrs => {
  // builds post json object and overrides title and content
});

factory.attrs('post', {title: 'Foo'}, {hasComments: true}).then(postAttrs => {
  // builds post json object
  // overrides title
  // invokes the initializer function with buildOptions of {hasComments: true}
});

You can use Factory#attrsMany to generate a set of model attributes

factory.attrsMany('post', 5, [{title: 'foo1'}, {title: 'foo2'}]).then(postAttrsArray => {
  // postAttrsArray is an array of 5 post json objects
  debug(postAttrsArray);
});

Factory#build

Builds a new model instance that is not persisted.

factory.build('post').then(post => {
  // post is a Post instance that is not persisted
});

The buildMany version builds an array of model instances.

factory.buildMany('post', 5).then(postsArray => {
  // postsArray is an array of 5 Post instances
});

Similar to Factory#attrs, you can pass attributes to override or buildOptions.

Factory#create(name, attrs, buildOptions)

Builds a new model instance that is persisted.

factory.create('post').then(post => {
  // post is a saved Post instance
});

Factory#createMany(name, num, attrs, buildOptions = {})

The createMany version creates an array of model instances.

factory.createMany('post', 5).then(postsArray => {
  // postsArray is an array of 5 Post saved instances
});

Similar to Factory#attrs and Factory#build, you can pass attrs to override and buildOptions. If you pass an array of attrs then each element of the array will be used as the attrs for a each model created.

Factory#createMany(name, attrs, buildOptions = {})

If you can pass an array of attrs then you can omit num and the length of the array will be used.

Factory#cleanUp

Destroys all of the created models. This is done using the adapter's destroy method. It might be useful to clear all created models before each test or testSuite.

Adapters

Adapters provide support for different databases and ORMs. Adapters can be registered for specific models, or as the 'default adapter', which is used for any models for which an adapter has not been specified. See the adapter docs for usage, but typical usage is:

const FactoryBot = require('factory-bot');
const factory = FactoryBot.factory;
const adapter = new FactoryBot.MongooseAdapter();

// use the mongoose adapter as the default adapter
factory.setAdapter(adapter);

// Or use it only for one model-factory
factory.setAdapter(adapter, 'factory-name');

ObjectAdapter

ObjectAdapter is a simple adapter that uses const model = new MyModel(), model.save() and model.destroy().

factory.setAdapter(new factory.ObjectAdapter());
class MyModel {
  save() {
    // save the model
  },
  destroy() {
    // destroy the model
  }
}
factory.define('model', MyModel);

Creating new Factories

You can create multiple factories which have different settings:

let anotherFactory = new factory.FactoryGirl();
anotherFactory.setAdapter(new MongooseAdapter()); // use the Mongoose adapter

History

This module is a fork or factory-girl, which indeed a fork of factory-lady.

This fork keeps the same API as the original module, but with bugfixes and some extra features.

License

This software is licensed under the MIT License.

factory-bot's People

Contributors

allie-wake-up avatar brettdh avatar bundacia avatar carlesnunez avatar celsomarques avatar chetanism avatar ejlangev avatar federicobond avatar imam avatar jeffheifetz avatar jesseclark avatar jmnsf avatar joselion avatar justinhallquist avatar kjjgibson avatar kmanzana avatar koshuang avatar melanievee avatar p-salido avatar petejkim avatar randyxli avatar ratson avatar rehanift avatar siboulet avatar sienic avatar simonexmachina avatar vitorbaptista avatar yads avatar yevhene avatar yourdeveloperfriend avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.