UNPKG

fakingoose

Version:
460 lines (373 loc) 11.4 kB
# fakingoose [![Build Status](https://app.travis-ci.com/faboulaws/fakingoose.svg?branch=master)](https://app.travis-ci.com/faboulaws/fakingoose) [![Coverage Status](https://coveralls.io/repos/github/faboulaws/fakingoose/badge.svg?branch=master)](https://coveralls.io/github/faboulaws/fakingoose?branch=master) An automatic mock data generator for mongoose using schema definition. ## Install ``` npm install fakingoose ``` ## Usage ```js const { factory } = require('fakingoose'); const entityFactory = factory(model, options); ``` #### factory(model, options) * model **\<[Schema](https://mongoosejs.com/docs/api/schema.html)\>** or **\<[Model](https://mongoosejs.com/docs/api/model.html)\>**: Mongoose [model](https://mongoosejs.com/docs/api/model.html) or [schema](https://mongoosejs.com/docs/api/schema.html). * options **\<? Object\>**: Generation options are optional. The factory would generate data for all fields based on the schema alone. For cases where there is a need for custom values, options can be used to define custom values or data generation setting per field. + options.\<propertyName\>.value **\<mixed\>**: A static value for each generated mock object. + options.\<propertyName\>.value: **\<function\>** a function for generating a dynamic value per item. This function receives the mock object as first argument. + options.\<propertyName\>.skip **\<boolean\>**: When set to `true` would skip the field. + options.\<propertyName\>.type **\<string\>**: The sub-type for this field type. For example \<String\> schema type supports `email` , `firsname` and `lastname` . + `options.\<propertyName\>.populateWithSchema`: Uses a schema to generate mocks of related models + `options.\<propertyName\>.populateWithFactory`: Uses another factory to generate mocks of related models. This options provides more flexibility than `populateWithSchema`, taking advantage of custom behaviours of factory via Factory options. + `options.\<propertyName\>.size` **\<int\>**: (Array values only) When specified, will ensure that said array field has given number of elements. By default, this is set to 2. ## Usage example ```js const mongoose = require('mongoose'); const { factory } = require('fakingoose'); const { Schema } = mongoose; const authorSchema = new Schema({ id: Schema.Types.ObjectId, title: { type: String, enum: ['Mr', 'Mrs', 'Dr'] }, fullname: String, username: String, email: String, favoriteQuote: String, }); const blogSchema = new Schema({ title: String, author: authorSchema, body: String, comments: [{ body: String, date: Date }], date: { type: Date, default: Date.now }, hidden: Boolean, meta: { votes: { type: Number, min: 0 }, favs: { type: Number, min: 0 } } }); const options = { author: { email: { type: 'email', }, username: { value: (object) => { return object.fullname.toLowerCase().replace(/\s/g, '.'); } }, favoriteQuote: { skip: true } }, }; const blogFactory = factory(blogSchema, options); const mock = blogFactory.generate({ author: { fullname: 'John Doe' } }); ``` **sample output** ```json { "title":"8tnkcjplr", "author":{ "id":"5d513f762a48134adb1868d7", "title":"Dr", "fullname":"John Doe", "username":"john.doe", "email":"re@sisuki.mc", "_id":"5d513f762a48134adb1868d8" }, "body":"ebjwad6*keskl", "comments":[ { "body":"d$*t9y3", "date":"2019-08-12T10:29:10.193Z", "_id":"5d513f762a48134adb1868d9" }, { "body":"jv5o[", "date":"2019-08-12T10:29:10.193Z", "_id":"5d513f762a48134adb1868da" } ], "hidden":false, "meta":{"votes":-3419053502758912,"favs":3323094479405056}, "_id":"5d513f762a48134adb1868db" } ``` ## Define options for nested properties To define options for nested a property use the nested property path (property names sperated by a dot). Example: ```js const options = { "meta.votes": { value: 0 }, // set value for 'votes' property under meta "meta.favs": { skip: true } // skip value for 'favs' property under meta } ``` ## Skipping multiple nested properties Multiple nested properties can be skipped from parent property. Example: ```js const accountSchema = new mongoose.Schema({ user: { generalInfo: { firstName: String, lastName: String, age: Number }, address: { postCode: String, street: String } } }); const accountFactory = factory(accountSchema, options); ``` To generate mocks without an address define options as below you have to override the default factory's options: ```js const options = { 'user.address': { skip: true } } ``` or ```js const options = { user: { address: { skip: true } } } ``` then ```js const mockObject = accountFactory.generate({}, options); ``` ## Generating ObjectId values When generating ObjectId values, you can choose to Stringify the generated ObjectId by using the `tostring` option. By default this options is `true` , so all generated ObjectIds would be converted to a String. Set `tostring` to false to disable this behaviour. Example: In the snippet below all ObjectIds generated are not stringified. ```js const friendSchema = new Schema({ id: Schema.Types.ObjectId, friendIds: [{ type: Schema.Types.ObjectId }], bestFriend: { id: Schema.Types.ObjectId } }); const amigoFactory = factory(friendSchema, { id: { tostring: false }, friendIds: { tostring: false }, 'bestFriend.id': { tostring: false } }); ``` ### Global settings To disable stringification globally use `factory.setGlobalObjectIdOptions` . Example: ```js const friendSchema = new Schema({ id: Schema.Types.ObjectId, friendIds: [{ type: Schema.Types.ObjectId }], bestFriend: { id: Schema.Types.ObjectId } }); const amigoFactory = factory(friendSchema).setGlobalObjectIdOptions({ tostring: false }); ``` ## Generating mocks for related models ([Populate](https://mongoosejs.com/docs/populate.html)) Mongoose provides an API for automatically replacing the specified paths in the document with document(s) from other collection(s). This package provides a similar functionality when generating mocks. An example: In the snippet below we have two schemas, `activitySchema` & `personSchema` . ```javascript const activitySchema = new mongoose.Schema({ name: String, value: String, }); const personSchema = new mongoose.Schema({ email: String, name: { type: String, }, activities: [{ type: mongoose.Schema.Types.ObjectId, ref: 'activity' }], }); ``` When generating mock data from the `personSchema` we should get the sample below ```javascript { email: 'l7@eiwtef%(pzitx', name: 'ym](ht7ucas*', activities: ['60f1e810a8b8ac392c3869b7', '60f1e810a8b8ac392c3869b8'], _id: '60f1e810a8b8ac392c3869b9' } ``` In some cases we might want to receive activity data instead of activity ID in the `activities` property, so we have a structure like below. ```javascript { email: ')5b2[dj@@)p91(', name: 'qo[jk!', activities: [{ name: '7^*8h^@!zp^!*hqwn', value: ']55f$hmva', _id: '60f1e51dead56f35c7ed4f62' }, { name: 'r!cv!k!p#vqfqt4a9k', value: '$@6k!z&oflj6', _id: '60f1e51dead56f35c7ed4f63' } ], _id: '60f1e51dead56f35c7ed4f64' } ``` Let's look at two seperate ways we can achieve this: * `options.\<propertyName\>.populateWithSchema`: Uses a schema to generate mocks of related models. * `options.\<propertyName\>.populateWithFactory`: Uses another factory to generate mocks of related models. This options provides more flexibility than `populateWithSchema`, taking advantage of custom behaviors of factory via Factory options. ### Example: options.populateWithFactory ```javascript const activityFactory = mocker(activitySchema) const personFactory = mocker(personSchema, { activities: { populateWithFactory: activityFactory } }) const mock = personFactory.generate() ``` ### Example: options.populateWithSchema ```javascript const myFactory = mocker(schema, { activities: { populateWithSchema: activitySchema } }) const mock = myFactory.generate() ``` ## Generating decimal ([Decimal128](https://developer.mongodb.com/quickstart/bson-data-types-decimal128)) values When generating decimal values, you can choose to Stringify the generated number by using the `tostring` option. By default this options is `true` , so all generated numbers would be converted to a String. Set `tostring` to false to disable this behaviour. Example: In the snippet below all numbers generated are not stringified. ```js const productSchema = new Schema({ price: Schema.Types.Decimal128 }); const productFactory = factory(productSchema, { price: { tostring: false } }); ``` ## Generating a variable-sized array of items per field When generating array values, you can specify a `size` parameter to ensure the array field has that many elements. By default, this is set to 2. Example: Each new user will now have 10 new statuses to start. ```js const userSchema = new mongoose.Schema({ email: String, name: { type: String, }, activities: [{ type: String, }], }); const userFactory = factory(userSchema, { activities: { size: 10 } }); ``` ### Global settings To disable stringification globally use `factory.setGlobalDecimal128Options` . Example: ```javascript const productSchema = new Schema({ price: Schema.Types.Decimal128 }); const productFactory = factory(productSchema).setGlobalDecimal128Options({ tostring: false }); ``` ## Override factory options per mock generated I some cases we want to override options that we used to initialise a factory. These options can be overridden in the `generate()` method of the factory. ### Example ```javascript const schema = new Schema({ updated: { type: Date, default: Date.now }, title: String, content: String, }); const options = { updated: { skip: true } }; const myFactory = mocker(schema, options); const mockWithoutUpdated = myFactory.generate({}); // here use options used to initilize the factory. We skip the "updated: field const mockWithoutTitle = myFactory.generate({}, { // here use custom options. We skip the "title: field title: { skip: true } }); ``` ## Supported Types * String * Array * Number * Decimal128 * ObjectId * Boolean * Mixed * Buffer * Embedded * Date * Map ## Mongoose version Support | Version | Supported | | ------- | ------------------ | | 7.x | :white_check_mark: | | 6.x | :white_check_mark: | | 5.x | :white_check_mark: | | 4.x | :white_check_mark: |