objection-factory

Model factories for Objection.js

Usage no npm install needed!

<script type="module">
  import objectionFactory from 'https://cdn.skypack.dev/objection-factory';
</script>

README

objection-factory

npm version

This library allows you to define factories for your Objection.js models. You can use it to generate dummy records for your unit and integration tests. Data is generated via faker.js.

Contents

Installation

You can install this package via npm:

npm install objection-factory

Usage

const { Model } = require('objection');
// 1. Import objection-factory
const Factory = require('objection-factory');

// 2. Define your model
class User extends Factory(Model) {
  // ...
  // 3. Define the factory schema
  static get factorySchema() {
    return {
      // `faker` is an instance of the faker.js library
      firstName: this.faker.name.firstName,
      lastName: this.faker.name.lastName,
      email: this.faker.internet.email,
    };
  }
}

// 5. Use the model factory in your unit tests!
const users = await User.create({ count: 50 });
//... assertions ...
await User.cleanup();

API

This library provides a class that your models must extend in order to enable factories.

const { Model } = require('objection');
const Factory = require('objection-factory');

class User extends Factory(Model) {
  // ...
}

Below, you can find a list of methods and attributes provided by the class.

static get factorySchema

It provides the schema used for generating dummy objects. It expects to return an object where each key is a valid column name, and each field is either a faker.js method, a function, or a literal. Note that the faker attribute is already included in the library's class.

Example

  static get factorySchema() {
    return {
      firstName: this.faker.name.firstName,
      lastName: this.faker.name.lastName,
      email: this.faker.internet.email,
    };
  }

static make(options = {})

Generates one or multiple JavaScript objects in accordance with the schema specified via factorySchema. You can turn the object into a model by using fromJson.

Options

  • count: Number (default: 1)

    The amount of dummy objects that must be generated.

  • override: Object?|Array? (default: null)

    It provides defaults to override the generated data. It expects an object when count is set to 1, otherwise it expects an array of objects. If the length of the array is less than count, only some of the dummy objects—starting from the first one—will be overridden.

Returns

An object if count is set to 1, otherwise it returns an array of objects.

Example

const user = User.make();
const users = User.make({ count: 3 });
const ivy = User.make({
  count: 1,
  override: { firstName: 'Ivy' },
});

// Overrides only the names of the first two objects
const johnAndJoe = User.make({
  count: 5,
  override: [
    { firstName: 'John' },
    { firstName: 'Joe' },
  ],
});

static async create(options = {})

Generates one or multiple models, and writes them to the database, in accordance with the schema specified via factorySchema. You can turn the model into an object by using toJSON.

Options

  • count: Number (default: 1)

    The amount of dummy objects that must be generated, and written to the DB.

  • batch: Boolean (default: false)

    Indicates whether we must optimize the batch insert. It does NOT preserve the order in which you passed the records. If you don't enable this flag for a batch insert, it'll be unoptimized but the order will be preserved.

  • override: Object?|Array? (default: null)

    It provides defaults to override the generated data. It expects an object when count is set to 1, otherwise it expects an array of objects. If the length of the array is less than count, only some of the dummy objects—starting from the first one—will be overridden.

  • resolveRelationships: Boolean (default: false)

    See Relationships.

Returns

An instance of your model if count is set to 1, otherwise it returns an array of models.

Developer's Notes

The method reverts all the inserts, even the successful ones, when one of them fails. At the moment, you can't customize this behaviour.

Example

const users = await User.create({ count: 3 });
console.log(users[0] instanceof User); // true
console.log(isNaN(user[1].id)); // false

static async cleanup()

Removes all the records that have been inserted via create.

Example

await User.create({ count: 300 });
await User.cleanup();

Relationships

The create methods supports both belongs to and has many relationships. Each relationship must be defined in the relationMappings object of your model (see Objection.js' documentation). You must always specify the join property, and join.to must always point to the modelClass model.

  // ...
  user: {
    modelClass: User,
    relation: Model.BelongsToOneRelation,
    join: {
      from: `${this.tableName}.userId`,
      to: `${User.tableName}.${User.idColumn}`,
    },
  }
  // ...

You can manually specify how to resolve relationships—see the next sections—or you can let the library resolve relationships for you. You can also combine these two options.

// Automatically resolve relationships
const parentPost = await Post.create({
  resolveRelationships: true,
});

// Automatically resolve all relationships but `parent`
const posts = await Post.create({
  count: 3,
  resolveRelationships: true,
  belongsTo: {
    parent: parentPost,
  },
})

Belongs to relationships

The create method accepts a belongsTo object, where each key is a relationship name—defined in relationMappings object of your model—and each value is an array with two elements:

  1. a literal (string or number), a model definition, or an instance of a model.
  2. an object containing configuration options:
    • clear (default: false): indicates whether cleanup must remove the record associated to the relationship

If you don't need configuration options, you can skip the array.

const parentPost = await Post.create({
  resolveRelationships: true,
});

const posts = await Post.create({
  count: 3,
  belongsTo: {
    form: [Form, { clear: true }],
    user: [user, { clear: true }],
    // `parentPost` must be removed manually
    parent: parentPost,
  },
})

Has many relationships

[...]

License

objection-factory is released under the MIT License.