Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

factory-girl

Package Overview
Dependencies
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

factory-girl - npm Package Compare versions

Comparing version 3.1.0 to 3.2.0-beta

test/utils/adapters.js

371

index.js
/* global window, define */
(function(factory) {
(function (factory) {
if (typeof exports !== 'undefined') {

@@ -8,3 +8,3 @@ module.exports = factory();

else if (typeof define === 'function' && define.amd) {
define(['factory-girl-object-adapter'], function(ObjectAdapter) {
define(['factory-girl-object-adapter'], function (ObjectAdapter) {
var _factory = factory();

@@ -18,11 +18,11 @@ _factory.ObjectAdapter = ObjectAdapter;

}
}(function() {
var Factory = function() {
}(function () {
var Factory = function () {
var factory = this,
factories = {},
defaultAdapter = new Adapter(),
adapters = {},
created = [];
factories = {},
defaultAdapter = new Adapter(),
adapters = {},
created = [];
factory.define = function(name, model, attributes, options) {
factory.define = function (name, model, attributes, options) {
options = options || {};

@@ -37,4 +37,4 @@

var builderProxy = function(fnName) {
return function() {
var builderProxy = function (fnName) {
return function () {
var builder = new Builder();

@@ -53,6 +53,18 @@ return builder[fnName].apply(builder, arguments);

factory.assoc = function(name, key, attrs) {
factory.assoc = function (name, key, attrs, buildOptions) {
attrs = attrs || {};
buildOptions = buildOptions || {};
return function (callback) {
factory.create(name, attrs, buildOptions, function (err, doc) {
if (err) return callback(err);
callback(null, key ? doc[key] : doc);
});
};
};
factory.assocBuild = function(name, key, attrs, buildOptions) {
attrs = attrs || {};
buildOptions = buildOptions || {};
return function(callback) {
factory.create(name, attrs, function(err, doc) {
factory.build(name, attrs, buildOptions, function(err, doc) {
if (err) return callback(err);

@@ -64,12 +76,39 @@ callback(null, key ? doc[key] : doc);

factory.assocMany = function(name, key, num, attrsArray) {
if (arguments.length < 4) {
if (typeof key === 'number') {
attrsArray = num;
num = key;
key = null;
}
factory.assocMany = function (name, key, num, attrsArray, buildOptionsArray) {
if (typeof key === 'number') {
buildOptionsArray = attrsArray;
attrsArray = num;
num = key;
key = null;
}
buildOptionsArray = buildOptionsArray || [];
attrsArray = attrsArray || [];
return function (callback) {
factory.createMany(name, attrsArray, num, buildOptionsArray, function (err, docs) {
if (err) return callback(err);
if (key) {
for (var i = 0; i < docs.length; ++i) {
docs[i] = docs[i][key];
}
}
callback(null, docs);
});
};
};
factory.assocBuildMany = function(name, key, num, attrsArray, buildOptionsArray) {
if (typeof key === 'number') {
buildOptionsArray = attrsArray;
attrsArray = num;
num = key;
key = null;
}
buildOptionsArray = buildOptionsArray || [];
attrsArray = attrsArray || [];
return function(callback) {
factory.createMany(name, attrsArray, num, function(err, docs) {
factory.buildMany(name, attrsArray, num, buildOptionsArray, function(err, docs) {
if (err) return callback(err);

@@ -86,3 +125,3 @@ if (key) {

factory.sequence = function(fn) {
factory.sequence = function (fn) {
var result;

@@ -92,3 +131,3 @@ var sequenceNum = 1;

if (!fn || fn.length < 2) {
result = function() {
result = function () {
if (fn) {

@@ -103,3 +142,3 @@ return fn(sequenceNum++);

else {
result = function(cb) {
result = function (cb) {
return fn(sequenceNum++, cb);

@@ -113,7 +152,7 @@ };

factory.adapterFor = function(name) {
factory.adapterFor = function (name) {
return adapters[name] || defaultAdapter;
};
factory.setAdapter = function(adapter, name) {
factory.setAdapter = function (adapter, name) {
if (name) {

@@ -127,3 +166,3 @@ adapters[name] = adapter;

factory.promisify = function(promiseLibrary) {
factory.promisify = function (promiseLibrary) {
var promisify = promiseLibrary.promisify || promiseLibrary.denodeify;

@@ -138,4 +177,4 @@ if (!promisify) throw new Error("No 'promisify' or 'denodeify' method found in supplied promise library");

var promisifiedBuilderProxy = function(fnName) {
return function() {
var promisifiedBuilderProxy = function (fnName) {
return function () {
var builder = new Builder();

@@ -159,8 +198,8 @@ builder.promisify(promisify);

factory.cleanup = function(callback) {
asyncForEach(created.reverse(), function(tuple, cb) {
factory.cleanup = function (callback) {
asyncForEach(created.reverse(), function (tuple, cb) {
var name = tuple[0],
doc = tuple[1],
adapter = factory.adapterFor(name),
model = factories[name].model;
doc = tuple[1],
adapter = factory.adapterFor(name),
model = factories[name].model;
adapter.destroy(doc, model, cb);

@@ -171,7 +210,7 @@ }, callback);

var Builder = function() {
var Builder = function () {
var builder = this;
builder.options = {};
builder.promisify = function(promisify) {
builder.promisify = function (promisify) {
builder.attrs = promisify(builder.attrs);

@@ -184,3 +223,3 @@ builder.build = promisify(builder.build);

builder.withOptions = function(options) {
builder.withOptions = function (options) {
merge(builder.options, options);

@@ -190,12 +229,17 @@ return builder;

builder.create = function(name, attrs, callback) {
builder.create = function (name, attrs, buildOptions, callback) {
if (!factories[name]) {
return callback(new Error("No factory defined for model '" + name + "'"));
}
if (typeof attrs === 'function') {
callback = attrs;
attrs = {};
buildOptions = {};
} else if (typeof buildOptions === 'function') {
callback = buildOptions;
buildOptions = {};
}
if (!factories[name]) {
return callback(new Error("No factory defined for model '" + name + "'"));
}
builder._build(name, attrs, function(err, doc, resultingAttrs) {
builder._build(name, attrs, buildOptions, function (err, doc, resultingAttrs) {
if (err) return callback(err);

@@ -212,3 +256,3 @@ save(name, doc, resultingAttrs, callback);

var oldCallback = callback;
return function(error, doc, attrs) {
return function (error, doc, attrs) {
return oldCallback(error, doc);

@@ -219,47 +263,69 @@ }

builder.attrs = function(name, attrs, callback) {
builder.attrs = function (name, attrs, buildOptions, callback) {
if (!factories[name]) {
return callback(new Error("No factory defined for model '" + name + "'"));
}
if (typeof attrs === 'function') {
callback = attrs;
attrs = {};
buildOptions = {};
} else if (typeof buildOptions === 'function') {
callback = buildOptions;
buildOptions = {};
}
if (!factories[name]) {
return callback(new Error("No factory defined for model '" + name + "'"));
var definedAttributes = factories[name].attributes;
if (typeof definedAttributes === 'function') {
definedAttributes = definedAttributes(buildOptions);
} else {
definedAttributes = copy(definedAttributes);
}
attrs = merge(copy(factories[name].attributes), attrs);
attrs = merge(definedAttributes, attrs);
asyncForEach(keys(attrs), function(key, cb) {
var fn = attrs[key];
if (typeof fn === 'function') {
if (!fn.length) {
attrs[key] = fn.call(attrs);
function populateAttrs(attrs, cb1) {
asyncForEach(keys(attrs), function (key, cb) {
var fn = attrs[key];
if (typeof fn === 'function') {
if (!fn.length) {
attrs[key] = fn.call(attrs);
cb();
}
else {
fn.call(attrs, function (err, value) {
if (err) return cb(err);
attrs[key] = value;
cb();
});
}
} else if(typeof fn === 'object') {
populateAttrs(fn, cb)
} else {
cb();
}
else {
fn.call(attrs, function(err, value) {
if (err) return cb(err);
attrs[key] = value;
cb();
});
}
}
else {
cb();
}
}, function(err) {
if (err) return callback(err);
}, function (err) {
if (err) return cb1(err);
callback(null, attrs);
});
cb1(null, attrs);
});
}
populateAttrs(attrs, callback);
};
builder.build = function(name, attrs, callback) {
builder.build = function (name, attrs, buildOptions, callback) {
if (typeof attrs === 'function') {
callback = attrs;
attrs = {};
buildOptions = {};
} else if (typeof buildOptions === 'function') {
callback = buildOptions;
buildOptions = {};
}
return builder._build(name, attrs, wrapCallback(callback));
return builder._build(name, attrs, buildOptions, wrapCallback(callback));
};
builder._build = function(name, attrs, callback) {
builder._build = function (name, attrs, buildOptions, callback) {
if (!factories[name]) {

@@ -271,6 +337,6 @@ return callback(new Error("No factory defined for model '" + name + "'"));

builder.attrs(name, attrs, function(err, resultingAttrs) {
builder.attrs(name, attrs, buildOptions, function (err, resultingAttrs) {
if (err) return callback(err);
var adapter = factory.adapterFor(name),
doc = adapter.build(model, resultingAttrs);
doc = adapter.build(model, resultingAttrs);

@@ -286,3 +352,3 @@ if (factories[name].options.afterBuild) {

builder.buildSync = function(name, attrs) {
builder.buildSync = function (name, attrs) {
if (!factories[name]) {

@@ -307,3 +373,3 @@ throw new Error("No factory defined for model '" + name + "'");

builder.buildMany = function(name, attrsArray, num, callback) {
builder.buildMany = function (name, attrsArray, num, callback) {
var args = parseBuildManyArgs.apply(null, arguments);

@@ -313,14 +379,14 @@ buildMany(args);

builder.createMany = function(name, attrsArray, num, callback) {
builder.createMany = function (name, attrsArray, num, buildOptionsArray, callback) {
var args = parseBuildManyArgs.apply(null, arguments),
results = [];
results = [];
callback = args.callback;
args.callback = function(err, docs, resultingAttrsArray) {
args.callback = function (err, docs, resultingAttrsArray) {
if (err) return callback(err);
asyncForEach(docs, function(doc, cb, index) {
save(name, doc, resultingAttrsArray[index], function(err) {
asyncForEach(docs, function (doc, cb, index) {
save(name, doc, resultingAttrsArray[index], function (err) {
if (!err) results[index] = doc;
cb(err);
});
}, function(err) {
}, function (err) {
callback(err, results);

@@ -333,13 +399,15 @@ });

function buildMany(args) {
var results = [],
resultingAttrsArray = [];
asyncForEach(args.attrsArray, function(attrs, cb, index) {
builder._build(args.name, attrs, function(err, doc, resultingAttrs) {
var results = [];
var resultingAttrsArray = [];
var buildOptions = args.buildOptionsArray;
asyncForEach(args.attrsArray, function (attrs, cb, index) {
builder._build(args.name, attrs, buildOptions[index] || {}, function (err, doc, resultingAttrs) {
if (!err) {
results[index] = doc;
resultingAttrsArray[index] = resultingAttrs;
results[index] = doc;
resultingAttrsArray[index] = resultingAttrs;
}
cb(err);
});
}, function(err) {
}, function (err) {
args.callback(err, results, resultingAttrsArray);

@@ -349,25 +417,89 @@ });

function parseBuildManyArgs(name, attrsArray, num, callback) {
if (typeof num == 'function') { // name, Array, callback
callback = num;
num = attrsArray.length;
function parseBuildManyArgs(name, attrsArray, num, buildOptionsArray, callback) {
function buildObjectArray(obj, count) {
var arr = [];
for(var i = 0; i < count; i++) {
arr[i] = obj;
}
return arr;
}
if (typeof attrsArray == 'number') { // name, num, callback
num = attrsArray;
attrsArray = null;
}
if (!(attrsArray instanceof Array)) { // name, Object, num, callback
if (typeof num != 'number') throw new Error("num must be specified when attrsArray is not an array");
var attrs = attrsArray;
attrsArray = new Array(num);
for (var i = 0; i < num; i++) {
attrsArray[i] = attrs;
if(attrsArray instanceof Array) {
// name, attrsArray, callback
// name, attrsArray, buildOptionsArray, callback
// name, attrsArray, buildOptionsObject, callback
// name, attrsArray, num, callback
// name, attrsArray, num, buildOptionsArray, callback
// name, attrsArray, num, buildOptionsObject, callback
if(typeof num === 'function') {
callback = num;
num = attrsArray.length;
buildOptionsArray = new Array(num);
} else if(num instanceof Array) {
callback = buildOptionsArray;
buildOptionsArray = num;
num = Math.max(attrsArray.length, buildOptionsArray.length);
attrsArray.length = buildOptionsArray.length = num;
} else if(typeof num === 'object') {
callback = buildOptionsArray;
buildOptionsArray = buildObjectArray(num, attrsArray.length);
num = attrsArray.length;
} else if(typeof num === 'number') {
attrsArray.length = num;
if(typeof buildOptionsArray === 'function') {
callback = buildOptionsArray;
buildOptionsArray = new Array(num);
} else if(buildOptionsArray instanceof Array) {
buildOptionsArray.length = num;
} else if(typeof buildOptionsArray === 'object') {
buildOptionsArray = buildObjectArray(buildOptionsArray, num);
} else {
throw new Error('Invalid parameters type found');
}
} else {
throw new Error('Invalid parameters type found');
}
} else if(typeof attrsArray === 'number') {
// name, num, callback
// name, num, buildOptionsArray, callback
// name, num, buildOptionsObject, callback
if(typeof num === 'function') {
callback = num;
num = attrsArray;
attrsArray = new Array(num);
buildOptionsArray = new Array(num);
} else if(num instanceof Array) {
callback = buildOptionsArray;
buildOptionsArray = num;
num = attrsArray;
attrsArray = new Array(num);
buildOptionsArray.length = num;
} else if(typeof num === 'object') {
callback = buildOptionsArray;
var buildOption1 = num;
num = attrsArray;
buildOptionsArray = buildObjectArray(buildOption1, num);
attrsArray = new Array(num);
} else {
throw new Error('Invalid parameters type found');
}
} else if(typeof attrsArray === 'object') {
// name, Object, num, callback
// name, Object, num, buildOptionsArray, callback
// name, Object, num, buildOptionsObject, callback
attrsArray = buildObjectArray(attrsArray, num);
if(typeof buildOptionsArray === 'function') {
callback = buildOptionsArray;
buildOptionsArray = new Array(num);
} else if(buildOptionsArray instanceof Array) {
buildOptionsArray.length = num;
} else if(typeof buildOptionsArray === 'object') {
buildOptionsArray = buildObjectArray(buildOptionsArray, num);
} else {
throw new Error('Invalid parameters type found');
}
}
if (!attrsArray) {
attrsArray = new Array(num);
}
else if( attrsArray.length !== num ) {
attrsArray.length = num;
}
return {

@@ -377,2 +509,3 @@ name: name,

num: num,
buildOptionsArray: buildOptionsArray,
callback: wrapCallback(callback)

@@ -398,5 +531,6 @@ };

var Adapter = function() {};
var Adapter = function () {
};
Adapter.prototype.build = function(Model, props) {
Adapter.prototype.build = function (Model, props) {
var doc = new Model();

@@ -406,6 +540,6 @@ this.set(props, doc, Model);

};
Adapter.prototype.get = function(doc, attr, Model) {
Adapter.prototype.get = function (doc, attr, Model) {
return doc[attr];
};
Adapter.prototype.set = function(props, doc, Model) {
Adapter.prototype.set = function (props, doc, Model) {
var key;

@@ -418,9 +552,9 @@ for (key in props) {

};
Adapter.prototype.save = function(doc, Model, cb) {
Adapter.prototype.save = function (doc, Model, cb) {
doc.save(cb);
};
/**
Be aware that the model may have already been destroyed
Be aware that the model may have already been destroyed
*/
Adapter.prototype.destroy = function(doc, Model, cb) {
Adapter.prototype.destroy = function (doc, Model, cb) {
doc.destroy(cb);

@@ -438,2 +572,3 @@ };

}
function keys(obj) {

@@ -443,3 +578,4 @@ var rv = [], key;

if (obj.hasOwnProperty(key)) {
rv.push(key);
rv.push(key);
rv.push(key);
}

@@ -449,5 +585,7 @@ }

}
function asyncForEach(array, handler, callback) {
var length = array.length,
index = -1;
index = -1;
function processNext(err) {

@@ -463,2 +601,3 @@ if (err) return callback(err);

}
processNext();

@@ -465,0 +604,0 @@ }

@@ -6,3 +6,3 @@ {

"author": "Simon Wade",
"version": "3.1.0",
"version": "3.2.0-beta",
"keywords": [

@@ -34,6 +34,5 @@ "factory",

"bluebird": "^2.9.25",
"chai": "^3.0.0",
"chai": "^3.5.0",
"mocha": "^2.2.5",
"should": "^6.0.3",
"sinon": "^1.14.1"
"should": "^6.0.3"
},

@@ -40,0 +39,0 @@ "scripts": {

@@ -59,2 +59,38 @@ # factory-girl

### Initializer function
You can provide a function instead of an object to initialize models.
You can pass the `buildOptions` object to the `factory.attrs`, `factory.build`, `factory.create` and the same object will be passed on to the initializer function.
```javascript
var factory = require('factory-girl');
var User = require('../models/user');
factory.define('user', User, function (buildOptions) {
var attrs = {
email: factory.sequence(function(n) {
return 'user' + n + '@demo.com';
}),
// async functions can be used by accepting a callback as an argument
async: function(callback) {
somethingAsync(callback);
},
// you can refer to other attributes using `this`
username: function() {
return this.email;
},
confirmed: false,
confirmedAt: null
};
if (buildOptions.confirmedUser) {
attrs.confirmed = true;
attrs.confirmedAt = new Date();
}
});
factory.build('user', function(err, user) {
console.log(user.attributes);
// => {state: 'active', email: 'user1@demo.com', async: 'foo', username: 'user1@demo.com'}
});
```
### Options

@@ -112,8 +148,11 @@

});
factory.build('post', function(err, post) {
factory.create('post', function(err, post) {
console.log(post.attributes);
// => { user_id: 1, comments: [{ text: 'hello' }, { text: 'hello' }] }
// => { id: 1, user_id: 1, comments: [{ text: 'hello' }, { text: 'hello' }] }
});
```
Be aware that `assoc()` will always create associated records, even when `factory.build()` is called.
You can use `assocBuild()`, which will always build associated records.
## Defining Sequences

@@ -155,2 +194,12 @@

In case you have defined your factory with an [initializer function](#initializer-function), you can pass on `buildOptions` to be passed to the initializer function.
```javascript
factory.attrs('user', {}, { confirmedUser: true }, function (err, userAttrs) {
// userAttrs is a user attributes
console.log(userAttrs);
}
```
Note that in case you want to pass buildOptions, you have to pass attributes parameter as well. Otherwise, the buildOptions will be treated as attribute parameters.
### Factory#build

@@ -169,2 +218,12 @@

In case you have defined your factory with an [initializer function](#initializer-function), you can pass on `buildOptions` to be passed to the initializer function.
```javascript
factory.build('user', {}, { confirmedUser: true }, function (err, userAttrs) {
// userAttrs is a user attributes
console.log(userAttrs);
}
```
Note that in case you want to pass buildOptions, you have to pass attributes parameter as well. Otherwise, the buildOptions will be treated as attribute parameters.
### Factory#create

@@ -180,6 +239,37 @@

### Factory#assoc
In case you have defined your factory with an [initializer function](#initializer-function), you can pass on `buildOptions` to be passed to the initializer function.
You can optionally provide attributes to the associated factory by passing an object as third argument.
```javascript
factory.create('user', {}, { confirmedUser: true }, function (err, userAttrs) {
// userAttrs is a user attributes
console.log(userAttrs);
}
```
Note that in case you want to pass buildOptions, you have to pass attributes parameter as well. Otherwise, the buildOptions will be treated as attribute parameters.
### Factory#assoc(model, key = null, attrs = null, buildOptions = null)
Defines an attribute of a model that creates an associated instance of another model.
Use the `key` argument to return an attribute of the associated instance.
You can optionally provide attributes to the associated factory by passing an object as third
argument.
Be aware that `assoc()` will always _create_ associated records, even when `factory.build()` is
called. You can use `assocBuild()`, which will always build associated records.
### Factory#assocBuild(model, key = null, attrs = null, buildOptions = null)
Same as `#assoc`, but builds the associated models rather than creating them.
### Factory#assocMany(model, key, num, attrs = null, buildOptions = null)
Creates multiple entries.
### Factory#assocManyBuild
Same as `#assocMany`, but builds the associated models rather than creating them.
### Factory#buildMany

@@ -193,11 +283,51 @@

});
factory.buildMany('post', 10, [{withImage: true}, {veryLong: true}], function(err, posts) {
// build 10 posts, using build options for first two
});
factory.buildMany('post', 10, {withImage: true}, function(err, posts) {
// build 10 posts, using same build options for all of them
});
factory.buildMany('post', [{title: 'Foo'}, {title: 'Bar'}], function(err, posts) {
// build 2 posts using the specified attributes
});
factory.buildMany('post', [{title: 'Foo'}, {title: 'Bar'}], [{withImage: true}], function(err, posts) {
// build 2 posts using the specified attributes
// build first post using the build option
});
factory.buildMany('post', [{title: 'Foo'}, {title: 'Bar'}], {withImage: true}, function(err, posts) {
// build first 2 posts using the specified attributes using same build options for all of them
});
factory.buildMany('post', [{title: 'Foo'}, {title: 'Bar'}], 10, function(err, posts) {
// build 10 posts using the specified attributes for the first and second
});
factory.buildMany('post', [{title: 'Foo'}, {title: 'Bar'}], 10, [{withImage: true}, {veryLong: true}], function(err, posts) {
// build 10 posts using the specified attributes and build options for the first and second
});
factory.buildMany('post', [{title: 'Foo'}, {title: 'Bar'}], 10, {withImage: true}, function(err, posts) {
// build 10 posts using the specified attributes for the first and second
// uses same build options for all of them
});
factory.buildMany('post', {title: 'Foo'}, 10, function(err, posts) {
// build 10 posts using the specified attributes for all of them
});
factory.buildMany('post', {title: 'Foo'}, 10, [{withImage: true}, {veryLong: true}], function(err, posts) {
// build 10 posts using the specified attributes for all of them but using build options only for first two
});
factory.buildMany('post', {title: 'Foo'}, 10, {withImage: true}, function(err, posts) {
// build 10 posts using the specified attributes and build options for all of them
});
```

@@ -204,0 +334,0 @@

/* global describe, beforeEach, afterEach */
var factory = require('..');
var should = require('should');
var should = require('chai').should();
var context = describe;
var sinon = require('sinon');
require('./utils/factories');
var adapters = require('./utils/adapters');
var models = require('./utils/models');
describe('factory', function() {
var Model, Person, Job, Post;
var Person = models.Person;
var Job = models.Job;
var Company = models.Company;
var Post = models.Post;
var BlogPost = models.BlogPost;
var User = models.User;
before(function() {
Model = function() {};
describe('factory', function () {
describe('#attrs', function () {
Model.prototype.save = function(callback) {
this.saveCalled = true;
callback();
};
Model.prototype.destroy = function(callback) {
this.destroyCalled = true;
callback();
};
context('attributes defined by function', function () {
it('correctly generates attrs', function (done) {
factory.attrs('user', function (err, userAttrs) {
if(err) done(err);
userAttrs.should.eql({
username: 'username_1',
password: 'dummy_password',
facebook: {},
twitter: {}
});
Person = function() {};
Person.prototype = new Model();
done();
});
});
Job = function() {};
Job.prototype = new Model();
it('correctly overrides attrs', function (done) {
factory.attrs('user', {
username: 'john_wayne',
facebook: {id: 'john_wayne'}
}, function (err, userAttrs) {
if(err) done(err);
userAttrs.should.eql({
username: 'john_wayne',
password: 'dummy_password',
facebook: {id: 'john_wayne'},
twitter: {}
});
Company = function() {};
Company.prototype = new Model();
done();
});
});
Post = function() {};
Post.prototype = new Model();
});
it('correctly generates attrs for given buildOptions', function (done) {
factory.attrs('user', {}, { facebookUser: true }, function (err, userAttrs) {
if(err) done(err);
userAttrs.should.eql({
username: 'username_1',
password: 'dummy_password',
facebook: {
id: 'dummy_fb_id_1',
token: 'fb_token1234567',
email: 'fb_email_1@fb.com',
name: 'John Doe'
},
twitter: {}
});
beforeEach(function() {
var nameCounter = 1, emailCounter = 1;
factory.define('person', Person, {
name: function(cb) {
process.nextTick(function() { // Zalgo begone!!
cb(null, "Person " + nameCounter++);
done();
});
},
email: function() {
return "email" + (emailCounter++) + "@noemail.com";
},
age: 25,
job: factory.assoc('job', null, { company: 'Bazqux Co.' }),
title: factory.assoc('job', 'title')
});
});
factory.define('job', Job, {
title: 'Engineer',
company: 'Foobar Inc.',
duties: {
cleaning: false,
writing: true,
computing: true
}
it('correctly generates attrs', function (done) {
factory.attrs('job', function (err, jobAttrs) {
jobAttrs.should.eql({
title: 'Engineer',
company: 'Foobar Inc.',
duties: {
cleaning: false,
writing: true,
computing: true
}
});
done();
});
});
factory.define('company', Company, {
name: 'Fruit Company',
employees: factory.assocMany('person', 3),
managers: factory.assocMany('person', 'name', 2)
it('correctly overrides attrs', function (done) {
var overrides = {title: 'Developer'};
factory.attrs('job', overrides, function (err, jobAttrs) {
jobAttrs.title.should.eql(overrides.title);
jobAttrs.company.should.eql('Foobar Inc.');
done();
});
});
factory.define('post', Post, {
num: factory.sequence(),
email: factory.sequence(function(n) {
return 'email' + n + '@test.com';
}),
name: factory.seq(function(n, cb) {
process.nextTick(function() {
cb(null, 'Post' + n);
});
})
it('correctly handles nested attributes', function (done) {
factory.attrs('company', function (err, companyAttrs) {
companyAttrs.employees.should.be.instanceof(Array);
companyAttrs.employees.length.should.eql(3);
companyAttrs.managers.should.be.instanceof(Array);
companyAttrs.managers.length.should.eql(2);
done();
});
});
});
describe('#attrs', function() {
it('correctly generates attrs', function(done) {
factory.attrs('job', function(err, jobAttrs) {
jobAttrs.should.eql({
title: 'Engineer',
company: 'Foobar Inc.',
duties: {
cleaning: false,
writing: true,
computing: true
}
});
done();
});
});
describe('#build', function () {
it('correctly overrides attrs', function(done) {
var overrides = { title: 'Developer' };
context('attributes defined by function', function () {
it('builds the object correctly', function (done) {
factory.build('user', {}, { twitterUser: true }, function (err, user) {
if(err) done(err);
factory.attrs('job', overrides, function(err, jobAttrs) {
jobAttrs.title.should.eql(overrides.title);
jobAttrs.company.should.eql('Foobar Inc.');
done();
});
(user instanceof User).should.be.true;
user.username.should.eql('username_1');
user.twitter.id.should.eql('dummy_tw_id_1');
user.facebook.should.eql({});
done();
});
});
it('correctly handles nested attributes', function(done) {
factory.attrs('company', function(err, companyAttrs) {
companyAttrs.employees.should.be.instanceof(Array);
companyAttrs.employees.length.should.eql(3);
it('builds the object correctly with overrides', function (done) {
factory.build('user', { twitter: { id: 'twitter_id' } }, { twitterUser: true }, function (err, user) {
if(err) done(err);
companyAttrs.managers.should.be.instanceof(Array);
companyAttrs.managers.length.should.eql(2);
(user instanceof User).should.be.true;
user.username.should.eql('username_1');
user.twitter.id.should.eql('twitter_id');
user.facebook.should.eql({});
done();
});
done();
});
});
});
describe('#build', function() {
it('builds, but does not save the object', function(done) {
factory.build('job', function(err, job) {
});
it('builds, but does not save the object', function (done) {
factory.build('job', function (err, job) {
(job instanceof Job).should.be.true;

@@ -126,8 +150,13 @@ job.title.should.eql('Engineer');

job.should.not.have.property('saveCalled');
done();
});
context('passing attributes as second argument', function() {
it('sets them', function(done) {
factory.build('job', { title: "Artist", company: "Bazqux Co.", duties: { cleaning: true, writing: false } }, function(err, job) {
context('passing attributes as second argument', function () {
it('sets them', function (done) {
factory.build('job', {
title: "Artist",
company: "Bazqux Co.",
duties: {cleaning: true, writing: false}
}, function (err, job) {
(job instanceof Job).should.be.true;

@@ -140,2 +169,3 @@ job.title.should.eql('Artist');

job.duties.computing.should.be.true;
done();

@@ -146,42 +176,26 @@ });

context('defined with an afterBuild handler', function() {
var spy;
context('defined with an afterBuild handler', function () {
it('allows afterBuild to mutate the model', function (done) {
factory.build('job_with_after_build', function (err, job) {
job.title.should.eql('Astronaut');
beforeEach(function() {
spy = sinon.spy();
factory.define('job with after build', Job, {
title: 'Engineer',
company: 'Foobar Inc.'
}, {
afterBuild: function(doc, options, done) {
spy.apply(null, arguments);
doc.title = 'Astronaut';
done(null, doc);
}
done();
});
});
it('calls afterBuild', function() {
factory.build('job with after build', function(err, job) {
spy.called.should.be.true;
});
});
it('calls afterBuild with buildMany', function (done) {
var num = 10;
factory.buildMany('job_with_after_build', num, function (err, jobs) {
jobs.forEach(function (job) {
job.title.should.eql('Astronaut');
});
it('allows afterBuild to mutate the model', function() {
factory.build('job with after build', function(err, job) {
job.title.should.eql('Astronaut');
done();
});
});
it('calls afterBuild with buildMany', function() {
var num = 10;
factory.buildMany('job with after build', num, function(err) {
spy.callCount.should.equal(num);
});
});
});
context('factory containing an association', function() {
it('is able to handle that', function(done) {
factory.build('person', { age: 30 }, function(err, person) {
context('factory containing an association', function () {
it('is able to handle that', function (done) {
factory.build('person', {age: 30}, function (err, person) {
(person instanceof Person).should.be.true;

@@ -191,2 +205,3 @@ person.should.not.have.property('saveCalled');

person.age.should.eql(30);
person.title.should.eql('Engineer', "assoc(model, attr) works as expected");
(person.job instanceof Job).should.be.true;

@@ -202,5 +217,5 @@ person.job.title.should.eql('Engineer');

context('factory containing a multi association', function() {
it('is able to handle that', function(done){
factory.build('company', function(err, company) {
context('factory containing a multi association', function () {
it('is able to handle that', function (done) {
factory.build('company', function (err, company) {
(company instanceof Company).should.be.true;

@@ -213,13 +228,13 @@ company.should.not.have.property('saveCalled');

(company.employees[0] instanceof Person).should.be.true;
company.employees[0].name.should.eql('Person 2');
company.employees[0].name.should.eql('Person 1');
(company.employees[1] instanceof Person).should.be.true;
company.employees[1].name.should.eql('Person 3');
company.employees[1].name.should.eql('Person 2');
(company.employees[2] instanceof Person).should.be.true;
company.employees[2].name.should.eql('Person 4');
company.employees[2].name.should.eql('Person 3');
(company.managers instanceof Array).should.be.true;
company.managers.length.should.eql(2);
(company.managers[0] instanceof Person).should.be.false;
company.managers[0].should.eql('Person 5');
company.managers[0].should.eql('Person 4');
(company.managers[1] instanceof Person).should.be.false;
company.managers[1].should.eql('Person 6');
company.managers[1].should.eql('Person 5');
done();

@@ -230,10 +245,13 @@ });

context('factory containing a sequence', function() {
it('is able to handle that', function(done) {
factory.build('post', function(err, post) {
(post instanceof Post).should.be.true;
post.num.should.eql(1);
post.email.should.equal('email1@test.com');
post.name.should.equal('Post1');
done();
context('factory containing a sequence', function () {
it('is able to handle that', function (done) {
factory.build('post', function (err, post1) {
factory.build('post', function (err, post2) {
(post2 instanceof Post).should.be.true;
(post2.num - post1.num).should.eql(1);
post2.name.should.contain(post2.num);
post2.email.should.have.string(post2.num);
done();
});
})

@@ -245,5 +263,19 @@ });

describe('#create', function() {
it('builds and saves the object', function(done) {
factory.create('job', function(err, job) {
describe('#create', function () {
it('creates objects with attributes defined by function', function (done) {
factory.create('user', {}, { facebookUser: true, twitterUser: true }, function (err, user) {
if(err) done(err);
(user instanceof User).should.be.true;
user.facebook.id.should.eql('dummy_fb_id_1');
user.twitter.id.should.eql('dummy_tw_id_2');
user.saveCalled.should.be.true;
done();
});
});
it('builds and saves the object', function (done) {
factory.create('job', function (err, job) {
(job instanceof Job).should.be.true;

@@ -257,23 +289,10 @@ job.title.should.eql('Engineer');

context('yields errors', function() {
before(function() {
var Faulty = function() {};
Faulty.prototype.save = function(callback) {
callback(new Error('Save failed'));
};
factory.define('faulty', Faulty, {});
});
afterEach(function() {
context('yields errors', function () {
afterEach(function () {
factory.setAdapter(null, 'faulty');
});
it('from the adapter', function(done) {
var FaultyAdapter = function() {};
FaultyAdapter.prototype = new factory.Adapter();
FaultyAdapter.prototype.save = function(doc, Model, cb) {
cb(new Error('Save failed'));
};
factory.setAdapter(new FaultyAdapter(), 'faulty');
factory.create('faulty', function(err, faulty) {
it('from the adapter', function (done) {
factory.setAdapter(new adapters.FaultyAdapter(), 'faulty');
factory.create('faulty', function (err, faulty) {
(err instanceof Error).should.be.true;

@@ -285,4 +304,4 @@ err.message.should.eql('Save failed');

it('from the model', function(done) {
factory.create('faulty', function(err, faulty) {
it('from the model', function (done) {
factory.create('faulty', function (err, faulty) {
(err instanceof Error).should.be.true;

@@ -295,5 +314,8 @@ err.message.should.eql('Save failed');

context('passing attributes as second argument', function() {
it('sets them', function(done) {
factory.create('job', { title: "Artist", company: "Bazqux Co." }, function(err, job) {
context('passing attributes as second argument', function () {
it('sets them', function (done) {
factory.create('job', {
title: "Artist",
company: "Bazqux Co."
}, function (err, job) {
(job instanceof Job).should.be.true;

@@ -308,43 +330,25 @@ job.title.should.eql('Artist');

context('defined with an afterCreate handler', function() {
var spy;
context('defined with an afterCreate handler', function () {
it('allows afterCreate to mutate the model', function (done) {
factory.create('job_with_after_create', function (err, job) {
job.title.should.eql('Astronaut');
beforeEach(function() {
spy = sinon.spy();
factory.define('job with after create', Job, {
title: 'Engineer',
company: 'Foobar Inc.'
}, {
afterCreate: function(doc, options, done) {
spy.apply(null, arguments);
doc.title = 'Astronaut';
done(null, doc);
}
done();
});
});
it('calls afterCreate', function() {
factory.create('job with after create', function(err, job) {
spy.called.should.be.true;
});
});
it('calls afterCreate with createMany', function (done) {
var num = 10;
factory.createMany('job_with_after_create', num, function (err, jobs) {
jobs.forEach(function (job) {
job.title.should.eql('Astronaut');
});
it('allows afterCreate to mutate the model', function() {
factory.create('job with after create', function(err, job) {
job.title.should.eql('Astronaut');
done();
});
});
it('calls afterCreate with createMany', function() {
var num = 10;
factory.createMany('job with after create', num, function(err) {
spy.callCount.should.equal(num);
});
});
});
});
describe('#buildMany', function() {
describe('#buildMany', function () {
it('builds a given set of objects', function (done) {

@@ -360,5 +364,37 @@ var attrsArray = [{title: 'Scientist'}, {}];

jobs[1].title.should.eql('Engineer');
done();
});
});
it('builds a given set of objects with build options', function (done) {
var attrsArray = [{username: 'ironman'}, {username: 'hulk'}, {username: 'hawkeye'}];
var buildOptionsArray = [{facebookUser: true}, {twitterUser: true}];
factory.buildMany('user', attrsArray, buildOptionsArray, function (err, users) {
if (err) return done(err);
users.length.should.eql(3);
var ironman = users[0];
var hulk = users[1];
var hawkeye = users[2];
(ironman instanceof User).should.be.true;
ironman.username.should.eql('ironman');
should.exist(ironman.facebook.id);
should.not.exist(ironman.twitter.id);
ironman.should.not.have.property('saveCalled');
hulk.username.should.eql('hulk');
should.not.exist(hulk.facebook.id);
should.exist(hulk.twitter.id);
hulk.should.not.have.property('saveCalled');
hawkeye.username.should.eql('hawkeye');
should.not.exist(hawkeye.facebook.id);
should.not.exist(hawkeye.twitter.id);
hawkeye.should.not.have.property('saveCalled');
done();
});
});
it('builds more than the given set of objects', function (done) {

@@ -373,5 +409,25 @@ var attrsArray = [{title: 'Scientist'}, {}];

jobs[9].title.should.eql('Engineer');
done();
});
});
it('builds more than the given set of objects and build options', function (done) {
var attrsArray = [{username: 'ironman', password: 'd0n7-7ry'}, {username: 'hulk'}, {username: 'hawkeye'}];
var buildOptionsArray = [{facebookUser: true}, {twitterUser: true}];
factory.buildMany('user', attrsArray, 10, buildOptionsArray, function (err, users) {
if (err) return done(err);
users.length.should.eql(10);
var ironman = users[0];
(ironman instanceof User).should.be.true;
ironman.password.should.eql('d0n7-7ry');
users[9].password.should.eql('dummy_password');
should.not.exist(users[9].twitter.id);
done();
});
});
it('builds a number of objects', function (done) {

@@ -384,5 +440,7 @@ factory.buildMany('job', 10, function (err, jobs) {

jobs[9].title.should.eql('Engineer');
done();
});
});
it('builds a number of objects with the same attrs', function (done) {

@@ -396,7 +454,25 @@ factory.buildMany('job', {title: 'Scientist'}, 10, function (err, jobs) {

jobs[9].title.should.eql('Scientist');
done();
});
});
it('operates correctly with sequences', function(done) {
factory.buildMany('post', 3, function(err, posts) {
it('builds a number of objects with the same attrs and build options', function (done) {
factory.buildMany('user', {password: 'bad-idea'}, 10, {twitterUser: true}, function (err, users) {
if (err) return done(err);
users.length.should.eql(10);
var user = users[0];
(user instanceof User).should.be.true;
user.password.should.eql('bad-idea');
should.exist(user.twitter.id);
users[9].password.should.eql('bad-idea');
should.exist(users[9].twitter.id);
done();
});
});
it('operates correctly with sequences', function (done) {
factory.buildMany('post', 3, function (err, posts) {
(posts[2].num - posts[1].num).should.eql(1);

@@ -409,3 +485,3 @@ (posts[1].num - posts[0].num).should.eql(1);

describe('#createMany', function() {
describe('#createMany', function () {
it('creates a given set of objects', function (done) {

@@ -422,5 +498,37 @@ var attrsArray = [{title: 'Scientist'}, {}];

jobs[1].saveCalled.should.be.true;
done();
});
});
it('creates a given set of objects with build options', function (done) {
var attrsArray = [{username: 'ironman'}, {username: 'hulk'}, {username: 'hawkeye'}];
var buildOptionsArray = [{facebookUser: true}, {twitterUser: true}];
factory.createMany('user', attrsArray, buildOptionsArray, function (err, users) {
if (err) return done(err);
users.length.should.eql(3);
var ironman = users[0];
var hulk = users[1];
var hawkeye = users[2];
(ironman instanceof User).should.be.true;
ironman.username.should.eql('ironman');
should.exist(ironman.facebook.id);
should.not.exist(ironman.twitter.id);
ironman.saveCalled.should.be.true;
hulk.username.should.eql('hulk');
should.not.exist(hulk.facebook.id);
should.exist(hulk.twitter.id);
hulk.saveCalled.should.be.true;
hawkeye.username.should.eql('hawkeye');
should.not.exist(hawkeye.facebook.id);
should.not.exist(hawkeye.twitter.id);
hawkeye.saveCalled.should.be.true;
done();
});
});
it('creates more than the given set of objects', function (done) {

@@ -436,5 +544,27 @@ var attrsArray = [{title: 'Scientist'}];

jobs[9].title.should.eql('Engineer');
done();
});
});
it('creates more than the given set of objects and build options', function (done) {
var attrsArray = [{username: 'ironman', password: 'd0n7-7ry'}, {username: 'hulk'}, {username: 'hawkeye'}];
var buildOptionsArray = [{facebookUser: true}, {twitterUser: true}];
factory.createMany('user', attrsArray, 10, buildOptionsArray, function (err, users) {
if (err) return done(err);
users.length.should.eql(10);
var ironman = users[0];
(ironman instanceof User).should.be.true;
ironman.saveCalled.should.be.true;
ironman.password.should.eql('d0n7-7ry');
users[9].password.should.eql('dummy_password');
should.not.exist(users[9].twitter.id);
users[9].saveCalled.should.be.true;
done();
});
});
it('creates a number of objects', function (done) {

@@ -449,2 +579,3 @@ factory.createMany('job', 10, function (err, jobs) {

jobs[9].title.should.eql('Engineer');
done();

@@ -454,6 +585,7 @@ });

it("allows the creation of many objects", function(done) {
it("allows the creation of many objects", function (done) {
factory.createMany('job', 1000, function (err, jobs) {
if (err) return done(err);
jobs.length.should.eql(1000);
done();

@@ -464,7 +596,7 @@ });

describe('#cleanup', function() {
it('removes created models', function(done) {
factory.create('person', function(err, person) {
factory.create('job', function(err, job) {
factory.cleanup(function(err) {
describe('#cleanup', function () {
it('removes created models', function (done) {
factory.create('person', function (err, person) {
factory.create('job', function (err, job) {
factory.cleanup(function (err) {
person.destroyCalled.should.be.true;

@@ -480,4 +612,4 @@ person.job.destroyCalled.should.be.true;

describe('Factory class', function() {
it('can be used to create new Factories', function() {
describe('Factory class', function () {
it('can be used to create new Factories', function () {
var another = new factory.Factory();

@@ -489,6 +621,6 @@ another.should.not.eql(factory);

});
another.build('anotherModel', function(err, job) {
another.build('anotherModel', function (err, job) {
job.title.should.eql('Scientist');
});
factory.build('anotherModel', function(err) {
factory.build('anotherModel', function (err) {
should.exist(err);

@@ -499,4 +631,4 @@ });

describe('ObjectAdapter', function() {
it('can be used to return raw objects', function() {
describe('ObjectAdapter', function () {
it('can be used to return raw objects', function () {
var another = new factory.Factory();

@@ -508,3 +640,3 @@ another.setAdapter(new factory.ObjectAdapter(), 'anotherModel');

});
another.build('anotherModel', function(err, job) {
another.build('anotherModel', function (err, job) {
job.constructor.should.eql(Object);

@@ -515,18 +647,7 @@ });

describe('#buildSync', function() {
var Post;
beforeEach(function() {
Post = function() {};
Post.prototype = new Model();
factory.define('post', Post, {
heading: 'The Importance of Being Ernest',
title: function() {
return this.heading;
}
});
});
describe('#buildSync', function () {
it('builds, but does not save the object', function() {
var post = factory.buildSync('post');
(post instanceof Post).should.be.true;
it('builds, but does not save the object', function () {
var post = factory.buildSync('blogpost');
(post instanceof BlogPost).should.be.true;
post.heading.should.eql('The Importance of Being Ernest');

@@ -536,6 +657,6 @@ post.should.not.have.property('saveCalled');

context('passing attributes as second argument', function() {
it('sets them', function() {
var post = factory.buildSync('post', { title: "Bazqux Co." });
(post instanceof Post).should.be.true;
context('passing attributes as second argument', function () {
it('sets them', function () {
var post = factory.buildSync('blogpost', {title: "Bazqux Co."});
(post instanceof BlogPost).should.be.true;
post.heading.should.eql('The Importance of Being Ernest');

@@ -547,19 +668,18 @@ post.title.should.eql('Bazqux Co.');

it('allows synchronous function properties', function() {
var post = factory.buildSync('post');
(post instanceof Post).should.be.true;
it('allows synchronous function properties', function () {
var post = factory.buildSync('blogpost');
(post instanceof BlogPost).should.be.true;
post.title.should.eql('The Importance of Being Ernest');
});
it('throws if the factory has async properties', function() {
(function() {
it('throws if the factory has async properties', function () {
(function () {
factory.buildSync('person');
}).should.throw();
});
});
describe('#withOptions', function() {
it('chains to expose the builder functions', function() {
var builder = factory.withOptions({ key: 'value' });
describe('#withOptions', function () {
it('chains to expose the builder functions', function () {
var builder = factory.withOptions({key: 'value'});

@@ -572,3 +692,3 @@ builder.should.have.property('build');

var job = builder.buildSync('job', { title: 'Mechanic' });
var job = builder.buildSync('job', {title: 'Mechanic'});
(job instanceof Job).should.be.true;

@@ -579,38 +699,22 @@ job.company.should.eql('Foobar Inc.');

it('passes options through to defined afterCreate handler', function() {
factory.define('job with after create', Job, {
title: 'Engineer',
company: 'Foobar Inc.'
}, {
afterCreate: function(doc, options, done) {
options.key.should.eql('value');
done(null, doc);
}
it('passes options through to defined afterCreate handler', function () {
var builder = factory.withOptions({key: 'value'});
builder.create('job_with_after_create', function (err, job) {
job._key.should.eql('value');
});
var builder = factory.withOptions({ key: 'value' });
builder.create('job with after create', function() {});
});
it('allows for chaining to merge options', function() {
factory.define('job with after create', Job, {
title: 'Engineer',
company: 'Foobar Inc.'
}, {
afterCreate: function(doc, options, done) {
options.key.should.eql('value 2');
options.anotherKey.should.eql('value');
done(null, doc);
}
it('allows for chaining to merge options', function () {
var builder = factory.withOptions({key: 'value 2', anotherKey: 'value'});
builder.create('job_with_after_create', function (err, job) {
job._key.should.eql('value 2');
job._anotherKey.should.eql('value');
});
var builder = factory.withOptions({ key: 'value 2', anotherKey: 'value' });
builder.create('job with after create', function() {});
});
});
describe('#promisify', function() {
describe('#promisify', function () {
var promisifiedFactory;
before(function() {
before(function () {
var Promise = require('bluebird');

@@ -620,4 +724,4 @@ promisifiedFactory = factory.promisify(Promise);

it('promisifies #build', function(done) {
promisifiedFactory.build('job').then(function(job) {
it('promisifies #build', function (done) {
promisifiedFactory.build('job').then(function (job) {
(job instanceof Job).should.be.true;

@@ -630,4 +734,4 @@ job.title.should.eql('Engineer');

it('works with chained builders too', function(done) {
promisifiedFactory.withOptions({}).build('job').then(function(job) {
it('works with chained builders too', function (done) {
promisifiedFactory.withOptions({}).build('job').then(function (job) {
(job instanceof Job).should.be.true;

@@ -640,3 +744,2 @@ job.title.should.eql('Engineer');

});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc