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

mongoose-revisionist

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mongoose-revisionist - npm Package Compare versions

Comparing version 0.1.2 to 0.2.0

tests/methods/diff/index.js

5

CHANGELOG.md

@@ -0,1 +1,6 @@

##0.2.0
- Removes `created`, `createdBy`, `modified` and `modifiedBy`. Those are not required for this library to function and should be details left to the user.
- Adds `diff` for versions and dates.
- Condenses the unit tests considerably by breaking out model creation.
##0.1.2

@@ -2,0 +7,0 @@ - Changes out nodeunit for mocha to get a little more control over when connections and models are created for testing. This also prevents connection thrashing.

2

package.json
{
"name": "mongoose-revisionist",
"version": "0.1.2",
"version": "0.2.0",
"description": "Oplog-like tracking for mongoose",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -9,12 +9,4 @@ Creates Mongo's oplog-like records for Mongoose operations.

The Mongoose plugin adds a handful of fields to the schema if they do not exist already:
The Mongoose plugin adds a `revision` field of type `Number` to the target schema, which is autoincremented every save. The plugin will also add a collection of revisions that are _close_ to (but not quite exactly) oplog records:
- *modified* - `Date` - when the document was last modified.
- *modifiedBy* - `String` - who/what last modified the document.
- *created* - `Date` - when the document was created.
- *createdBy* - `String` - who/what created the document.
- *revision* - `Number` - the revision of the document, autoincremented every save.
The plugin will also add a collection of revisions that are _close_ to (but not quite exactly) oplog records:
- *ts* - `Date` - the timestamp of the operation, defaults to `Date.now`.

@@ -53,9 +45,27 @@ - *v* - `Number` - the Mongoose-internal version of the document.

- *versions* - gets the valid versions for a given Mongoose document. Calls back with an array of integers.
- *getVersion* - gets a specific version of a given Mongoose document. The first argument of the call can be a version number, a date (to get by date), "current" to get the current version, or not specified, also to get the current version.
#### .versions(cb)
Gets the valid versions for a given Mongoose document. Calls back with an array of integers.
### Static Methods
#### .getVersion([versionNumber|date|'current', ] cb)
Gets a specific version of a given Mongoose document. The first argument of the call can be a version number, a date (to get by date), "current" to get the current version, or not specified, also to get the current version. Calls back with the collapsed version as it would have appeared at that number/date.
- *getVersion* - gets a specific version of a given Mongoose document. The first argument must be the document ID to retrieve. The rest is exactly the same as the intance method: The second argument of the call can be a version number, a date (to get by date), "current" to get the current version, or not specified, also to get the current version.
#### .diff(versionNumber|date, versionNumber|date, cb)
Gets the difference in versions or between dates specified. Calls back with an object with three hashes: `added`, `removed`, `updated`. Each hash has member paths denoting they were changed, as well as what the value was changed from and to along with the version the change happened in. For example:
```js
{
added: {},
updated: {
name: {
from: 'bar',
to: 'baz',
revision: 4
}
},
removed: {}
}
```
... would denote that the `name` field was updated from `bar` to `baz` in the 4th revision.
### Static Methods
Each of the above instance methods are also available as static methods on the Mongoose model. The only additional parameter required is a valid Mongo ID as the first parameter. For example, `instance.diff()` would have the signature `Model.diff(id, versionNumber|date, versionNumber| date, cb)`.
var _ = require('lodash'),
util = require('util'),
async = require('async'),
argx = require('argx'),
moment = require('moment'),
mongoose = require('mongoose');
util = require('util'),
async = require('async'),
argx = require('argx'),
moment = require('moment'),
mongoose = require('mongoose');
_.mixin({
keysDeep: function(thing) {
var paths = [];
var t = function(thing, path) {
_.each(thing, function(value, key) {
path.push(key);
keysDeep: function(thing, leafsOnly) {
var paths = [];
var t = function(thing, path) {
_.each(thing, function(value, key) {
path.push(key);
var isLeaf = true;
if (!/^[a-fA-F0-9]{24}/.test(thing[key].toString()) && (_.isObject(thing[key]) || _.isArray(thing[key]))) {
isLeaf = false;
t(thing[key], path);
}
if (leafsOnly && isLeaf) {
paths.push(path.join('.'));
}
if (!/^[a-fA-F0-9]{24}/.test(thing[key].toString()) && (_.isObject(thing[key]) || _.isArray(thing[key]))) {
t(thing[key], path);
} else {}
paths.push(path.join('.'));
path.pop();
});
};
t(thing, []);
return paths;
}
if (!leafsOnly) {
paths.push(path.join('.'));
}
path.pop();
});
};
t(thing, []);
return paths;
}
});
var revisionist = {
schema: new mongoose.Schema({
ts: {
type: Date,
default: Date.now
},
v: Number,
op: String,
ns: String,
o: mongoose.Schema.Types.Mixed,
o2: {
type: mongoose.Schema.Types.Mixed,
required: false
},
revision: Number,
referenceId: mongoose.Schema.Types.ObjectId
}),
plugin: function(schema, options) {
options = _.defaultsDeep(options || {}, {
modelName: 'Revisionist'
});
schema: new mongoose.Schema({
ts: {
type: Date,
default: Date.now
},
v: Number,
op: String,
ns: String,
o: mongoose.Schema.Types.Mixed,
o2: {
type: mongoose.Schema.Types.Mixed,
required: false
},
revision: Number,
referenceId: mongoose.Schema.Types.ObjectId
}),
plugin: function(schema, options) {
options = _.defaultsDeep(options || {}, {
modelName: 'Revisionist'
});
schema.add({
modified: Date,
modifiedBy: String,
created: Date,
createdBy: String,
revision: Number
schema.add({
revision: Number
});
schema.method('versions', function(cb) {
this.collection.conn.models[options.modelName].find({
referenceId: this._id
}, {
revision: 1
})
.exec(function(err, revisions) {
cb(err, _.uniq(revisions));
});
});
schema.method('versions', function(cb) {
this.collection.conn.models[options.modelName].find({
referenceId: this._id
}, {
revision: 1
})
.exec(function(err, revisions) {
cb(err, _.uniq(revisions));
});
schema.static('versions', function(id, cb) {
this.collection.conn.models[options.modelName].find({
referenceId: id
}, {
revision: 1
})
.exec(function(err, revisions) {
cb(err, _.uniq(revisions));
});
});
var collapse = function() {
var args = argx(arguments);
var collapse = function() {
var args = argx(arguments);
var cb = args.pop('function') || function() {},
referenceId = args.shift(),
connection = args.shift(),
values = args.remain();
var cb = args.pop('function') || function() {},
referenceId = args.shift(),
connection = args.shift(),
values = args.remain();
var version, date;
if (values.length == 0) {
version = 'current';
} else if (values.length == 1) {
if (moment.isMoment(values[0]) ||
_.isDate(values[0])) {
date = moment(values[0]);
} else {
version = values[0];
var version, date;
if (values.length == 0) {
version = 'current';
} else if (values.length == 1) {
if (moment.isMoment(values[0]) ||
_.isDate(values[0])) {
date = moment(values[0]);
} else {
version = values[0];
}
} else {
throw 'Too many arguments specified for getVersion.';
}
var query = {
referenceId: referenceId
};
if (!!version && version != 'current') {
query.revision = {
$lte: version
};
} else if (!!date) {
query.ts = {
$lte: date.toDate()
};
}
connection.models[options.modelName].find(query)
.exec(function(err, revisions) {
var collapsed = revisions.length == 0 ? undefined : {};
_.each(revisions, function(revision) {
revision = revision.toObject();
//check for 'o'
//nb: o can be omitted in the update immediately prior to a deletion
if (revision.hasOwnProperty('o')) {
if (revision.op == 'i' || (revision.op == 'u' && revision.o.hasOwnProperty('_id'))) {
_.each(revision.o['_$set'], function(value, key) {
collapsed[key] = value;
});
} else if (revision.op == 'u') {
if (revision.o.hasOwnProperty('_$set')) {
_.each(revision.o['_$set'], function(value, key) {
collapsed[key] = value;
});
}
} else {
throw 'Too many arguments specified for getVersion.';
if (revision.o.hasOwnProperty('_$unset')) {
_.each(revision.o['_$unset'], function(value, key) {
delete collapsed[key];
});
}
}
}
})
cb(err, collapsed);
});
};
var query = {
referenceId: referenceId
var diff = function() {
var args = argx(arguments);
var cb = args.pop('function') || function() {},
referenceId = args.shift(),
connection = args.shift(),
values = args.remain();
var startDate, endDate, startVersion, endVersion;
if (values.length == 2) {
if ((moment.isMoment(values[0]) || _.isDate(values[0])) &&
(moment.isMoment(values[1]) || _.isDate(values[1]))) {
startDate = moment(values[0]);
endDate = moment(values[1]);
} else {
startVersion = values[0];
endVersion = values[1];
}
} else {
throw 'invalid arguments specified for diff.';
}
var query = {
referenceId: referenceId
};
if (startDate && endDate) {
query.ts = {
$lte: endDate.toDate(),
$gte: startDate.toDate()
};
} else if (startVersion && endVersion) {
query.revision = {
$lte: endVersion,
$gte: startVersion
};
}
connection.models[options.modelName].find(query)
.exec(function(err, revisions) {
var collapsed = revisions.length == 0 ? undefined : {
added: {},
updated: {},
removed: {}
};
var modify = function(key, value, revision, collection) {
var from = (collapsed[collection][key] || {})
.to;
_.each(_.keys(collapsed), function(collectionKey) {
if (collapsed[collectionKey][key]) {
from = collapsed[collectionKey][key].to;
delete collapsed[collection][key];
}
});
collapsed[collection][key] = {
from: from,
to: (/^[a-fA-F0-9]{24}/.test(value.toString()) ? value.toString() : value),
revision: revision
};
if (!!version && version != 'current') {
query.revision = {
$lte: version
};
} else if (!!date) {
query.ts = {
$lte: date.toDate()
};
}
};
connection.models[options.modelName].find(query)
.exec(function(err, revisions) {
var collapsed = revisions.length == 0 ? undefined : {};
_.each(revisions, function(revision) {
if (revision.op == 'i' || (revision.op == 'u' && revision.o.hasOwnProperty('_id'))) {
_.each(revision.o['_$set'], function(value, key) {
collapsed[key] = value;
});
} else if (revision.op == 'u') {
if (revision.o.hasOwnProperty('_$set')) {
_.each(revision.o['_$set'], function(value, key) {
collapsed[key] = value;
});
}
if (revision.o.hasOwnProperty('_$unset')) {
_.each(revision.o['_$unset'], function(value, key) {
delete collapsed[key];
});
}
}
})
_.each(revisions, function(revision) {
if (revision.op == 'i' || (revision.op == 'u' && revision.o.hasOwnProperty('_id'))) {
_.each(_.keysDeep(revision.o['_$set'], true), function(key) {
modify(key, _.get(revision.o['_$set'], key), revision.revision, 'added');
});
cb(err, collapsed);
} else if (revision.op == 'u') {
if (revision.o.hasOwnProperty('_$set')) {
_.each(_.keysDeep(revision.o['_$set'], true), function(key) {
modify(key, _.get(revision.o['_$set'], key), revision.revision, 'updated');
});
};
}
if (revision.o.hasOwnProperty('_$unset')) {
_.each(_.keysDeep(revision.o['_$unset'], true), function(key) {
modify(key, _.get(revision.o['_$unset'], key), reivsion.revision, 'removed');
});
schema.method('getVersion', function() {
var args = [].slice.call(arguments);
args.unshift(this.collection.conn),
args.unshift(this._id);
collapse.apply(null, args);
});
}
}
})
schema.static('getVersion', function() {
var args = [].slice.call(arguments);
args.splice(1, 0, this.db);
collapse.apply(null, args);
cb(err, collapsed);
});
};
schema.pre('save', function(next) {
var self = this,
connection = this.collection.conn;
schema.method('getVersion', function() {
var args = [].slice.call(arguments);
args.unshift(this.collection.conn),
args.unshift(this._id);
collapse.apply(null, args);
});
schema.static('getVersion', function() {
var args = [].slice.call(arguments);
args.splice(1, 0, this.db);
collapse.apply(null, args);
});
if (!!options.connectionString) {
connection = mongoose.createConnection(options.connectionString);
}
schema.method('diff', function() {
var args = [].slice.call(arguments);
args.unshift(this.collection.conn),
args.unshift(this._id);
diff.apply(null, args);
});
//add the revisionist schema
var revisionistModel = connection.model(options.modelName, revisionist.schema);
schema.static('diff', function() {
var args = [].slice.call(arguments);
args.splice(1, 0, this.db);
diff.apply(null, args);
});
//get the original and update object
var original = self._original,
update = self.toObject(),
operation = 'u';
schema.pre('save', function(next) {
var self = this,
connection = this.collection.conn;
//determine what kind of operation this is
if (!original) {
operation = 'i';
self.created = moment()
.toDate();
//check createdBy
if (!self.createdBy && !self.modifiedBy) {
console.warn('mongoose-revisionist: no createdBy specified for %s in model %s', self._id, self.constructor.modelName);
self.createdBy = '[unknown]';
} else if (!self.createdBy) {
self.createdBy = self.modifiedBy;
}
}
if (!!options.connectionString) {
connection = mongoose.createConnection(options.connectionString);
}
//set the modified date
self.modified = moment()
.toDate();
//add the revisionist schema
var revisionistModel = connection.model(options.modelName, revisionist.schema);
//check modifiedBy
if (!self.modifiedBy && operation == 'i') {
self.modifiedBy = self.createdBy;
} else if (!self.modifiedBy) {
console.warn('mongoose-revisionist: no modifiedBy specified for %s in model %s', self._id, self.constructor.modelName);
self.modifiedBy = '[unknown]';
}
//get the original and update object
var original = self._original,
update = self.toObject(),
operation = 'u';
//first, determine what overlaps, and what is different in that set
var set = _.chain(original)
.keysDeep()
.intersection(_.keysDeep(update))
.map(function(key) {
var temp = self.schema.path(key);
return {
key: key,
type: (self.schema.path(key) || {})
.instance
};
})
.filter(function(key) {
return !!key.type
})
.map(function(key) {
return key.key;
})
.map(function(key) {
var getValue = function(value, instance) {
if (_.isDate(value)) {
//if the member is a date, compare the integer representation
//hack: consider using getTime() instead of +
originalValue = +originalValue;
newValue = +newValue
} else if (_.isObject(value) && /^[0-9a-fA-F]{24}$/.test(value.toString())) {
//if the member is a schema ID, compare the strings
//hack: using isObject and a hex regex also feels bad.
value = value.toString();
} else if (_.isObject(value) && instance == 'ObjectID') {
//if the member is a schema ID but is loaded - failing the schema ID check above,
//check the IDs
value = value._id.toString();
} else if (_.isArray(value)) {
//dope array for array checking
} else if (_.isObject(value)) {
//leave object alone, use _.isEqual to check
//todo: nested objects?
} else {
//otherwise, the member is an ordinary primitive, compare those
}
//determine what kind of operation this is
if (!original) {
operation = 'i';
}
return value;
},
//get the original compare value
originalValue = getValue(_.get(original, key), self.schema.path(key)
.instance),
//get the new compare value
newValue = getValue(_.get(update, key), self.schema.path(key)
.instance);
//first, determine what overlaps, and what is different in that set
var set = _.chain(original)
.keysDeep()
.intersection(_.keysDeep(update))
.map(function(key) {
var temp = self.schema.path(key);
return {
key: key,
type: (self.schema.path(key) || {})
.instance
};
})
.filter(function(key) {
return !!key.type
})
.map(function(key) {
return key.key;
})
.map(function(key) {
var getValue = function(value, instance) {
if (_.isDate(value)) {
//if the member is a date, compare the integer representation
//hack: consider using getTime() instead of +
originalValue = +originalValue;
newValue = +newValue
} else if (_.isObject(value) && /^[0-9a-fA-F]{24}$/.test(value.toString())) {
//if the member is a schema ID, compare the strings
//hack: using isObject and a hex regex also feels bad.
value = value.toString();
} else if (_.isObject(value) && instance == 'ObjectID') {
//if the member is a schema ID but is loaded - failing the schema ID check above,
//check the IDs
value = value._id.toString();
} else if (_.isArray(value)) {
//dope array for array checking
} else if (_.isObject(value)) {
//leave object alone, use _.isEqual to check
//todo: nested objects?
} else {
//otherwise, the member is an ordinary primitive, compare those
}
if (!_.isEqual(newValue, originalValue)) {
//if the values don't match, return the key with the unmodified update value
return {
key: key,
value: _.get(update, key)
};
}
})
.compact()
.reduce(function(result, member, ix) {
if (self.schema.path(member.key)
.instance == 'ObjectID' && !/^[0-9a-fA-F]{24}$/.test(member.value.toString())) {
_.set(result, member.key, member.value._id);
} else {
_.set(result, member.key, member.value);
}
return result;
}, {})
.value();
return value;
},
//get the original compare value
originalValue = getValue(_.get(original, key), self.schema.path(key)
.instance),
//get the new compare value
newValue = getValue(_.get(update, key), self.schema.path(key)
.instance);
//merge in the new values
set = _.merge(set, _.chain(update)
.keysDeep()
.difference(_.keysDeep(original))
.map(function(key) {
var temp = self.schema.path(key);
return {
key: key,
type: (self.schema.path(key) || {})
.instance
};
})
.filter(function(key) {
return !!key.type
})
.map(function(key) {
return key.key;
})
.map(function(key) {
return {
key: key,
value: _.get(update, key)
};
})
.reduce(function(result, member, ix) {
if (self.schema.path(member.key)
.instance == 'ObjectID' && !/^[0-9a-fA-F]{24}$/.test(member.value.toString())) {
_.set(result, member.key, member.value._id);
} else {
_.set(result, member.key, member.value);
}
return result;
}, {})
.value());
if (!_.isEqual(newValue, originalValue)) {
//if the values don't match, return the key with the unmodified update value
return {
key: key,
value: _.get(update, key)
};
}
})
.compact()
.reduce(function(result, member, ix) {
if (self.schema.path(member.key)
.instance == 'ObjectID' && !/^[0-9a-fA-F]{24}$/.test(member.value.toString())) {
_.set(result, member.key, member.value._id);
} else {
_.set(result, member.key, member.value);
}
return result;
}, {})
.value();
//make the unset
var unset = _.chain(original)
.keysDeep()
.difference(_.keysDeep(update))
.map(function(key) {
var temp = self.schema.path(key);
return {
key: key,
type: (self.schema.path(key) || {})
.instance
};
})
.filter(function(key) {
return !!key.type
})
.map(function(key) {
return key.key;
})
.reduce(function(result, key, ix) {
_.set(result, key, 1);
return result;
}, {})
.value();
//merge in the new values
set = _.merge(set, _.chain(update)
.keysDeep()
.difference(_.keysDeep(original))
.map(function(key) {
var temp = self.schema.path(key);
return {
key: key,
type: (self.schema.path(key) || {})
.instance
};
})
.filter(function(key) {
return !!key.type
})
.map(function(key) {
return key.key;
})
.map(function(key) {
return {
key: key,
value: _.get(update, key)
};
})
.reduce(function(result, member, ix) {
if (self.schema.path(member.key)
.instance == 'ObjectID' && !/^[0-9a-fA-F]{24}$/.test(member.value.toString())) {
_.set(result, member.key, member.value._id);
} else {
_.set(result, member.key, member.value);
}
return result;
}, {})
.value());
//make the unset
var unset = _.chain(original)
.keysDeep()
.difference(_.keysDeep(update))
.map(function(key) {
var temp = self.schema.path(key);
return {
key: key,
type: (self.schema.path(key) || {})
.instance
};
})
.filter(function(key) {
return !!key.type
})
.map(function(key) {
return key.key;
})
.reduce(function(result, key, ix) {
_.set(result, key, 1);
return result;
}, {})
.value();
var o2 = null;
if (operation == 'u') {
o2 = {
_id: original._id
};
delete set._id;
}
//create the revisionist record
(new revisionistModel({
ts: new Date(),
op: operation,
v: (original || {})
.__v,
ns: self.collection.collectionName,
o: {
'_$set': set,
'_$unset': unset
},
o2: o2,
revision: ++(original || {
revision: 0
})
.revision,
referenceId: self._id
}))
.save(function(err, revision) {
self.revision = revision.revision;
next();
});
var o2 = null;
if (operation == 'u') {
o2 = {
_id: original._id
};
delete set._id;
}
//create the revisionist record
(new revisionistModel({
ts: new Date(),
op: operation,
v: (original || {})
.__v,
ns: self.collection.collectionName,
o: {
'_$set': set,
'_$unset': unset
},
o2: o2,
revision: ++(original || {
revision: 0
})
.revision,
referenceId: self._id
}))
.save(function(err, revision) {
self.revision = revision.revision;
next();
});
schema.pre('remove', function(next) {
var self = this,
connection = this.collection.conn;
});
self.save(function(err) {
schema.pre('remove', function(next) {
var self = this,
connection = this.collection.conn;
if (!!options.connectionString) {
connection = mongoose.createConnection(options.connectionString);
}
self.save(function(err) {
//add the revisionist schema
var revisionistModel = connection.model(options.modelName, revisionist.schema);
if (!!options.connectionString) {
connection = mongoose.createConnection(options.connectionString);
}
//create the revisionist record
(new revisionistModel({
ts: new Date(),
op: 'd',
v: (self._original || {})
.__v,
ns: self.collection.collectionName,
o: {
_id: self._id
},
revision: ++(self._original || {
revision: 0
})
.revision,
referenceId: self._id
}))
.save(function(err, revision) {
self.revision = revision.revision;
next();
});
});
//add the revisionist schema
var revisionistModel = connection.model(options.modelName, revisionist.schema);
});
//create the revisionist record
(new revisionistModel({
ts: new Date(),
op: 'd',
v: (self._original || {})
.__v,
ns: self.collection.collectionName,
o: {
_id: self._id
},
revision: ++(self._original || {
revision: 0
})
.revision,
referenceId: self._id
}))
.save(function(err, revision) {
self.revision = revision.revision;
next();
});
});
schema.post('save', function() {
this._original = this.toObject();
});
});
schema.post('init', function() {
//when the db value is pulled, make a copy-on-write copy of the original values for audit purposes later
this._original = this.toObject();
//todo: add a dirty flag
});
schema.post('save', function() {
this._original = this.toObject();
});
},
schema.post('init', function() {
//when the db value is pulled, make a copy-on-write copy of the original values for audit purposes later
this._original = this.toObject();
//todo: add a dirty flag
});
},
};
module.exports = exports = revisionist;
module.exports = exports = {
"info": require("./info"),
"methods": require("./methods"),
"types": require("./types"),
"util": require("./util"),
};
module.exports = exports = {
"getVersionByDate": require("./getVersionByDate"),
"diff": require("./diff"),
"getVersion": require("./getVersion"),
"versions": require("./versions"),
};
var mongoose = require('mongoose'),
util = require('util'),
async = require('async'),
_ = require('lodash'),
logger = require('winston'),
should = require('should'),
testUtil = require('../util');
util = require('util'),
async = require('async'),
_ = require('lodash'),
logger = require('winston'),
should = require('should'),
testUtil = require('../util');
describe('composite', function() {
it('creates', function(done) {
var self = this;
async.waterfall([
it('creates', function(done) {
var self = this;
async.waterfall([
function(cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
createdBy: 'test'
});
function(cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
createdBy: 'test'
});
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[0])
.be.ok();
p.revisions.length.should.equal(1);
p.revisions[0].revision.should.equal(1);
p.revisions[0].op.should.equal('i');
done();
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[0])
.be.ok();
p.revisions.length.should.equal(1);
p.revisions[0].revision.should.equal(1);
p.revisions[0].op.should.equal('i');
done();
});
});
it('updates', function(done) {
var self = this;
async.waterfall([
it('updates', function(done) {
var self = this;
async.waterfall([
function(cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
});
function(cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
});
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
p.composite.someCompositeThing.compositeMemberOne = 'three';
p.composite.modifiedBy = 'test';
p.composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
p.revisions.length.should.equal(2);
p.revisions[1].revision.should.equal(2);
p.revisions[1].op.should.equal('u');
p.revisions[1].o['_$set'].someCompositeThing.compositeMemberOne.should.equal('three');
done();
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
p.composite.someCompositeThing.compositeMemberOne = 'three';
p.composite.modifiedBy = 'test';
p.composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
p.revisions.length.should.equal(2);
p.revisions[1].revision.should.equal(2);
p.revisions[1].op.should.equal('u');
p.revisions[1].o['_$set'].someCompositeThing.compositeMemberOne.should.equal('three');
done();
});
});
it('updates with unset', function(done) {
var self = this;
async.waterfall([
it('updates with unset', function(done) {
var self = this;
async.waterfall([
function(cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
});
function(cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
});
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
//note: for mongo to pick up a $unset from mongoose,
//note: the member must be explicitly set to undefined.
//note: setting the member to null will save as null,
//note: deleting the member will cause the member to be ignored.
p.composite.someCompositeThing.compositeMemberTwo = undefined;
p.composite.modifiedBy = 'test';
p.composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[1].o)
.be.ok();
should(p.revisions[1].o['_$unset'])
.be.ok();
should(p.revisions[1].o['_$unset'].someCompositeThing)
.be.ok();
should(p.revisions[1].o['_$unset'].someCompositeThing.compositeMemberTwo)
.be.ok();
p.revisions[1].op.should.equal('u');
done();
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
//note: for mongo to pick up a $unset from mongoose,
//note: the member must be explicitly set to undefined.
//note: setting the member to null will save as null,
//note: deleting the member will cause the member to be ignored.
p.composite.someCompositeThing.compositeMemberTwo = undefined;
p.composite.modifiedBy = 'test';
p.composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[1].o)
.be.ok();
should(p.revisions[1].o['_$unset'])
.be.ok();
should(p.revisions[1].o['_$unset'].someCompositeThing)
.be.ok();
should(p.revisions[1].o['_$unset'].someCompositeThing.compositeMemberTwo)
.be.ok();
p.revisions[1].op.should.equal('u');
done();
});
});
it('removes', function(done) {
var self = this;
async.waterfall([
it('removes', function(done) {
var self = this;
async.waterfall([
function(cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
});
function(cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
});
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
p.composite.modifiedBy = 'remove test';
p.composite.remove(function(err) {
cb(err, p)
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
},
function(p, cb) {
self.Composite.getVersion(p.composite._id, function(err, version) {
p.v1_byId = version;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[2])
.be.ok();
should(p.v1_byId)
.be.ok();
p.revisions.length.should.equal(3);
p.revisions[1].revision.should.equal(2);
p.revisions[2].op.should.equal('d');
p.v1_byId.modifiedBy.should.equal('remove test');
done();
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
p.composite.remove(function(err) {
cb(err, p)
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
},
function(p, cb) {
self.Composite.getVersion(p.composite._id, function(err, version) {
p.v1_byId = version;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[2])
.be.ok();
should(p.v1_byId)
.be.ok();
p.revisions.length.should.equal(3);
p.revisions[1].revision.should.equal(2);
p.revisions[2].op.should.equal('d');
done();
});
});
});
var mongoose = require('mongoose'),
util = require('util'),
async = require('async'),
_ = require('lodash'),
should = require('should'),
logger = require('winston'),
testUtil = require('../util');
util = require('util'),
async = require('async'),
_ = require('lodash'),
should = require('should'),
logger = require('winston'),
testUtil = require('../util');
describe('composite with array', function() {
it('creates', function(done) {
var self = this;
async.waterfall([
it('creates', function(done) {
var self = this;
async.waterfall([
function(cb) {
var composite = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
createdBy: 'test'
});
function(cb) {
var composite = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
createdBy: 'test'
});
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[0])
.be.ok();
p.revisions.length.should.equal(1);
p.revisions[0].revision.should.equal(1);
p.revisions[0].op.should.equal('i');
done();
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[0])
.be.ok();
p.revisions.length.should.equal(1);
p.revisions[0].revision.should.equal(1);
p.revisions[0].op.should.equal('i');
done();
});
});
it('updates', function(done) {
var self = this;
async.waterfall([
it('updates', function(done) {
var self = this;
async.waterfall([
function(cb) {
var composite = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
});
function(cb) {
var composite = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
});
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
p.composite.compositeArray[0].arrayMemberOne = 'three';
p.composite.modifiedBy = 'test';
p.composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
p.composite.compositeArray[0].arrayMemberOne = 'three';
p.composite.modifiedBy = 'test';
p.composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
p.revisions.length.should.equal(2);
p.revisions[1].revision.should.equal(2);
p.revisions[1].op.should.equal('u');
p.revisions[1].o['_$set'].compositeArray[0].arrayMemberOne.should.equal('three');
done();
});
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
p.revisions.length.should.equal(2);
p.revisions[1].revision.should.equal(2);
p.revisions[1].op.should.equal('u');
p.revisions[1].o['_$set'].compositeArray[0].arrayMemberOne.should.equal('three');
done();
});
});
it('updates with unset', function(done) {
var self = this;
async.waterfall([
it('updates with unset', function(done) {
var self = this;
async.waterfall([
function(cb) {
var composite = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
});
function(cb) {
var composite = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
});
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
//note: for mongo to pick up a $unset from mongoose,
//note: the member must be explicitly set to undefined.
//note: setting the member to null will save as null,
//note: deleting the member will cause the member to be ignored.
p.composite.compositeArray[0].arrayMemberTwo = undefined;
p.composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[1].o)
.be.ok();
should(p.revisions[1].o['_$unset'])
.be.ok();
should(p.revisions[1].o['_$unset'].compositeArray)
.be.ok();
should(p.revisions[1].o['_$unset'].compositeArray[0].arrayMemberTwo)
.be.ok();
p.revisions[1].op.should.equal('u');
done();
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
//note: for mongo to pick up a $unset from mongoose,
//note: the member must be explicitly set to undefined.
//note: setting the member to null will save as null,
//note: deleting the member will cause the member to be ignored.
p.composite.compositeArray[0].arrayMemberTwo = undefined;
p.composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[1].o)
.be.ok();
should(p.revisions[1].o['_$unset'])
.be.ok();
should(p.revisions[1].o['_$unset'].compositeArray)
.be.ok();
should(p.revisions[1].o['_$unset'].compositeArray[0].arrayMemberTwo)
.be.ok();
p.revisions[1].op.should.equal('u');
done();
});
});
it('removes', function(done) {
var self = this;
async.waterfall([
it('removes', function(done) {
var self = this;
async.waterfall([
function(cb) {
var composite = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
compositeArray: {
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
},
});
function(cb) {
var composite = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
compositeArray: {
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
},
});
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
p.composite.modifiedBy = 'remove test';
p.composite.remove(function(err) {
cb(err, p)
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
},
function(p, cb) {
self.CompositeWithArray.getVersion(p.composite._id, function(err, version) {
p.v1_byId = version;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[2])
.be.ok();
should(p.v1_byId)
.be.ok();
composite.save(function(err, composite) {
cb(err, {
composite: composite
});
});
},
function(p, cb) {
p.composite.remove(function(err) {
cb(err, p)
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.composite._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
},
function(p, cb) {
self.CompositeWithArray.getVersion(p.composite._id, function(err, version) {
p.v1_byId = version;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[2])
.be.ok();
should(p.v1_byId)
.be.ok();
p.revisions.length.should.equal(3);
p.revisions[1].revision.should.equal(2);
p.revisions[2].op.should.equal('d');
p.v1_byId.modifiedBy.should.equal('remove test');
done();
});
p.revisions.length.should.equal(3);
p.revisions[1].revision.should.equal(2);
p.revisions[2].op.should.equal('d');
done();
});
});
});

@@ -1,6 +0,7 @@

module.exports = exports = {
"composite": require("./composite"),
"compositeWithArray": require("./compositeWithArray"),
"reference": require("./reference"),
"simple": require("./simple"),
};
require('../util');
describe('types', function(){
require("./composite");
require("./compositeWithArray");
require("./reference");
require("./simple");
});
var mongoose = require('mongoose'),
util = require('util'),
async = require('async'),
_ = require('lodash'),
should = require('should'),
logger = require('winston'),
testUtil = require('../util');
util = require('util'),
async = require('async'),
_ = require('lodash'),
should = require('should'),
logger = require('winston'),
testUtil = require('../util');
describe('reference', function() {
it('creates', function(done) {
var self = this;
async.waterfall([
it('creates', function(done) {
var self = this;
async.waterfall([
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
createdBy: 'test'
});
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
createdBy: 'test'
});
composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
var compositeWithArray = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
createdBy: 'test'
});
composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
var compositeWithArray = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
createdBy: 'test'
});
compositeWithArray.save(function(err, compositeWithArray) {
p.compositeWithArray = compositeWithArray;
cb(err, p);
});
},
function(p, cb) {
var reference = new self.Reference({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
simple: p.simple,
composite: p.composite,
compositeArray: p.compositeWithArray
});
compositeWithArray.save(function(err, compositeWithArray) {
p.compositeWithArray = compositeWithArray;
cb(err, p);
});
},
function(p, cb) {
var reference = new self.Reference({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
simple: p.simple,
composite: p.composite,
compositeArray: p.compositeWithArray
});
reference.save(function(err, reference) {
p.reference = reference;
cb(err, p);
});
},
reference.save(function(err, reference) {
p.reference = reference;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.reference._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[0])
.be.ok();
p.revisions.length.should.equal(1);
p.revisions[0].revision.should.equal(1);
p.revisions[0].op.should.equal('i');
done();
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.reference._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[0])
.be.ok();
p.revisions.length.should.equal(1);
p.revisions[0].revision.should.equal(1);
p.revisions[0].op.should.equal('i');
done();
});
});
it('updates', function(done) {
var self = this;
async.waterfall([
it('updates', function(done) {
var self = this;
async.waterfall([
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
createdBy: 'test'
});
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
var composite = new self.Composite({
name: 'stuff',
telephone: '999-999-9999',
someCompositeThing: {
compositeMemberOne: 'one',
compositeMemberTwo: 'two'
},
createdBy: 'test'
});
composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
var compositeWithArray = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
createdBy: 'test'
});
composite.save(function(err, composite) {
p.composite = composite;
cb(err, p);
});
},
function(p, cb) {
var compositeWithArray = new self.CompositeWithArray({
name: 'stuff',
telephone: '999-999-9999',
compositeArray: [{
arrayMemberOne: 'one',
arrayMemberTwo: 'two'
}],
createdBy: 'test'
});
compositeWithArray.save(function(err, compositeWithArray) {
p.compositeWithArray = compositeWithArray;
cb(err, p);
});
},
function(p, cb) {
var reference = new self.Reference({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
simple: p.simple,
composite: p.composite,
compositeArray: p.compositeWithArray
});
compositeWithArray.save(function(err, compositeWithArray) {
p.compositeWithArray = compositeWithArray;
cb(err, p);
});
},
function(p, cb) {
var reference = new self.Reference({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test',
simple: p.simple,
composite: p.composite,
compositeArray: p.compositeWithArray
});
reference.save(function(err, reference) {
p.reference = reference;
cb(err, p);
});
},
function(p, cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
reference.save(function(err, reference) {
p.reference = reference;
cb(err, p);
});
},
function(p, cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
simple.save(function(err, simple) {
p.simple2 = simple;
cb(err, p);
});
},
function(p, cb) {
p.reference.simple = p.simple2;
p.reference.save(function(err, reference) {
p.reference = reference;
cb(err, p);
});
},
simple.save(function(err, simple) {
p.simple2 = simple;
cb(err, p);
});
},
function(p, cb) {
p.reference.simple = p.simple2;
p.reference.save(function(err, reference) {
p.reference = reference;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.reference._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
p.revisions.length.should.equal(2);
p.revisions[1].revision.should.equal(2);
p.revisions[1].op.should.equal('u');
done();
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.reference._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
p.revisions.length.should.equal(2);
p.revisions[1].revision.should.equal(2);
p.revisions[1].op.should.equal('u');
done();
});
});
it('updates with unset');
it('removes');
it('updates with unset', function(done) {
var self = this;
async.waterfall([
function(cb) {
testUtil.shorthand.reference(self, cb);
},
function(p, cb) {
//note: for mongo to pick up a $unset from mongoose,
//note: the member must be explicitly set to undefined.
//note: setting the member to null will save as null,
//note: deleting the member will cause the member to be ignored.
p.reference.composite = undefined;
p.reference.save(function(err, reference) {
p.reference = reference;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.reference._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[3])
.be.ok();
should(p.revisions[3].o)
.be.ok();
should(p.revisions[3].o['_$unset'])
.be.ok();
should(p.revisions[3].o['_$unset'].composite)
.be.ok();
p.revisions[3].op.should.equal('u');
done();
});
});
it('removes', function(done) {
var self = this;
async.waterfall([
function(cb) {
testUtil.shorthand.reference(self, cb);
},
function(p, cb) {
p.reference.remove(function(err) {
cb(err, p)
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.reference._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
},
function(p, cb) {
self.Simple.getVersion(p.simple._id, function(err, version) {
p.v1_byId = version;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[2])
.be.ok();
should(p.v1_byId)
.be.ok();
p.revisions.length.should.equal(5);
p.revisions[1].revision.should.equal(2);
p.revisions[4].op.should.equal('d');
done();
});
});
});
var mongoose = require('mongoose'),
util = require('util'),
async = require('async'),
_ = require('lodash'),
should = require('should'),
logger = require('winston'),
testUtil = require('../util');
util = require('util'),
async = require('async'),
_ = require('lodash'),
should = require('should'),
logger = require('winston'),
testUtil = require('../util');
describe('simple', function() {
it('creates', function(done) {
var self = this;
async.waterfall([
it('creates', function(done) {
var self = this;
async.waterfall([
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.simple._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[0])
.be.ok();
p.revisions.length.should.equal(1);
p.revisions[0].revision.should.equal(1);
p.revisions[0].op.should.equal('i');
done();
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.simple._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[0])
.be.ok();
p.revisions.length.should.equal(1);
p.revisions[0].revision.should.equal(1);
p.revisions[0].op.should.equal('i');
done();
});
});
it('updates', function(done) {
var self = this;
async.waterfall([
it('updates', function(done) {
var self = this;
async.waterfall([
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
p.simple.name = 'more stuff';
p.simple.modifiedBy = 'test';
p.simple.save(function(err, simple) {
p.simple = simple;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.simple._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
p.revisions.length.should.equal(2);
p.revisions[1].revision.should.equal(2);
p.revisions[1].op.should.equal('u');
p.revisions[1].o['_$set'].name.should.equal('more stuff');
done();
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
p.simple.name = 'more stuff';
p.simple.modifiedBy = 'test';
p.simple.save(function(err, simple) {
p.simple = simple;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.simple._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
p.revisions.length.should.equal(2);
p.revisions[1].revision.should.equal(2);
p.revisions[1].op.should.equal('u');
p.revisions[1].o['_$set'].name.should.equal('more stuff');
done();
});
});
it('updates with unset', function(done) {
var self = this;
async.waterfall([
it('updates with unset', function(done) {
var self = this;
async.waterfall([
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
//note: for mongo to pick up a $unset from mongoose,
//note: the member must be explicitly set to undefined.
//note: setting the member to null will save as null,
//note: deleting the member will cause the member to be ignored.
p.simple.telephone = undefined;
p.simple.save(function(err, simple) {
p.simple = simple;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.simple._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[1].o)
.be.ok();
should(p.revisions[1].o['_$unset'])
.be.ok();
should(p.revisions[1].o['_$unset'].telephone)
.be.ok();
p.revisions[1].op.should.equal('u');
done();
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
//note: for mongo to pick up a $unset from mongoose,
//note: the member must be explicitly set to undefined.
//note: setting the member to null will save as null,
//note: deleting the member will cause the member to be ignored.
p.simple.telephone = undefined;
p.simple.save(function(err, simple) {
p.simple = simple;
cb(err, p);
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.simple._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[1].o)
.be.ok();
should(p.revisions[1].o['_$unset'])
.be.ok();
should(p.revisions[1].o['_$unset'].telephone)
.be.ok();
p.revisions[1].op.should.equal('u');
done();
});
});
it('removes', function(done){
var self = this;
async.waterfall([
it('removes', function(done) {
var self = this;
async.waterfall([
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
function(cb) {
var simple = new self.Simple({
name: 'stuff',
telephone: '999-999-9999',
createdBy: 'test'
});
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
p.simple.modifiedBy = 'remove test';
p.simple.remove(function(err) {
cb(err, p)
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.simple._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
},
function(p, cb) {
self.Simple.getVersion(p.simple._id, function(err, version) {
p.v1_byId = version;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[2])
.be.ok();
should(p.v1_byId)
.be.ok();
simple.save(function(err, simple) {
cb(err, {
simple: simple
});
});
},
function(p, cb) {
p.simple.remove(function(err) {
cb(err, p)
});
},
function(p, cb) {
self.connection.db.collection('revisionists', function(err, revisionistCollection) {
p.revisionistModel = revisionistCollection;
cb(err, p);
});
},
function(p, cb) {
p.revisionistModel.find({
referenceId: p.simple._id
})
.toArray(function(err, revisions) {
p.revisions = revisions;
cb(err, p);
});
},
function(p, cb) {
self.Simple.getVersion(p.simple._id, function(err, version) {
p.v1_byId = version;
cb(err, p);
});
}
], function(err, p) {
if (err) return done(err);
should(p.revisions)
.be.ok();
should(p.revisions[1])
.be.ok();
should(p.revisions[2])
.be.ok();
should(p.v1_byId)
.be.ok();
p.revisions.length.should.equal(3);
p.revisions[1].revision.should.equal(2);
p.revisions[2].op.should.equal('d');
p.v1_byId.modifiedBy.should.equal('remove test');
done();
});
p.revisions.length.should.equal(3);
p.revisions[1].revision.should.equal(2);
p.revisions[2].op.should.equal('d');
done();
});
});
});
module.exports = exports = {
"fixDates": require("./fixDates"),
"models": require("./models"),
"setup": require("./setup"),
"shorthand": require("./shorthand"),
};

@@ -30,2 +30,3 @@ var logger = require('winston'),

after(function(done) {
logger.silly('closing connection');
this.connection.close();

@@ -32,0 +33,0 @@ done();

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