Merge branch 'release/2.4.1' into production
This commit is contained in:
commit
6079792072
|
@ -1,65 +1,24 @@
|
||||||
|
|
||||||
### Contributing ###
|
### Contributing ###
|
||||||
|
|
||||||
Thank you for your interest in `loopback`, an open source project
|
Thank you for your interest in `loopback`, an open source project
|
||||||
administered by StrongLoop.
|
administered by StrongLoop.
|
||||||
|
|
||||||
Contributing to loopback is easy. In a few simple steps:
|
Contributing to `loopback` is easy. In a few simple steps:
|
||||||
|
|
||||||
* Ensure that your effort is aligned with the project’s roadmap by
|
* Ensure that your effort is aligned with the project's roadmap by
|
||||||
talking to the maintainers, especially if you are going to spend a
|
talking to the maintainers, especially if you are going to spend a
|
||||||
lot of time on it. This project is currently maintained by
|
lot of time on it.
|
||||||
[@ritch](https://github.com/ritch), [@raymondfeng](https://github.com/raymondfeng),
|
|
||||||
and [@bajtos](https://github.com/bajtos). The preferred channel of communication
|
|
||||||
is [LoopBack Forum](https://groups.google.com/forum/#!forum/loopbackjs) or
|
|
||||||
[Github Issues](https://github.com/strongloop/loopback/issues).
|
|
||||||
|
|
||||||
* Make something better or fix a bug.
|
* Make something better or fix a bug.
|
||||||
|
|
||||||
* Adhere to code style outlined in the
|
* Adhere to code style outlined in the [Google C++ Style Guide][] and
|
||||||
[Google Javascript Style Guide][].
|
[Google Javascript Style Guide][].
|
||||||
|
|
||||||
* [Sign your patches](#signing-patches) to indicate that your are
|
* Sign the [Contributor License Agreement](https://cla.strongloop.com/strongloop/loopback)
|
||||||
making your contribution available under the terms of the
|
|
||||||
[Contributor License Agreement](#contributor-license-agreement).
|
|
||||||
|
|
||||||
* Submit a pull request through Github.
|
* Submit a pull request through Github.
|
||||||
|
|
||||||
|
|
||||||
### Signing patches ###
|
|
||||||
|
|
||||||
Like many open source projects, we need a contributor license agreement
|
|
||||||
from you before we can merge in your changes.
|
|
||||||
|
|
||||||
In summary, by submitting your code, you are granting us a right to use
|
|
||||||
that code under the terms of this Agreement, including providing it to
|
|
||||||
others. You are also certifying that you wrote it, and that you are
|
|
||||||
allowed to license it to us. You are not giving up your copyright in
|
|
||||||
your work. The license does not change your rights to use your own
|
|
||||||
contributions for any other purpose.
|
|
||||||
|
|
||||||
Contributor License Agreements are important because they define the
|
|
||||||
chain of ownership of a piece of software. Some companies won't allow
|
|
||||||
the use of free software without clear agreements around code ownership.
|
|
||||||
That's why many open source projects collect similar agreements from
|
|
||||||
contributors. The CLA here is based on the Apache CLA.
|
|
||||||
|
|
||||||
To signify your agreement to these terms, add the following line to the
|
|
||||||
bottom of your commit message. Use your real name and an actual e-mail
|
|
||||||
address.
|
|
||||||
|
|
||||||
```
|
|
||||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively you can use the git command line to automatically add this
|
|
||||||
line, as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ git commit -sm "Replace rainbows by unicorns"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Contributor License Agreement ###
|
### Contributor License Agreement ###
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -188,7 +147,5 @@ $ git commit -sm "Replace rainbows by unicorns"
|
||||||
inaccurate in any respect. Email us at callback@strongloop.com.
|
inaccurate in any respect. Email us at callback@strongloop.com.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[Google C++ Style Guide]: https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
|
||||||
[Google Javascript Style Guide]: https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
|
[Google Javascript Style Guide]: https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
|
||||||
[license]: LICENSE
|
|
||||||
|
|
||||||
|
|
2
index.js
2
index.js
|
@ -12,7 +12,7 @@ var datasourceJuggler = require('loopback-datasource-juggler');
|
||||||
loopback.Connector = require('./lib/connectors/base-connector');
|
loopback.Connector = require('./lib/connectors/base-connector');
|
||||||
loopback.Memory = require('./lib/connectors/memory');
|
loopback.Memory = require('./lib/connectors/memory');
|
||||||
loopback.Mail = require('./lib/connectors/mail');
|
loopback.Mail = require('./lib/connectors/mail');
|
||||||
loopback.Remote = require('./lib/connectors/remote');
|
loopback.Remote = require('loopback-connector-remote');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Types
|
* Types
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
/**
|
|
||||||
* Dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var assert = require('assert');
|
|
||||||
var remoting = require('strong-remoting');
|
|
||||||
var DataAccessObject = require('loopback-datasource-juggler/lib/dao');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the RemoteConnector class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = RemoteConnector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of the connector with the given `settings`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function RemoteConnector(settings) {
|
|
||||||
assert(typeof settings === 'object', 'cannot initiaze RemoteConnector without a settings object');
|
|
||||||
this.client = settings.client;
|
|
||||||
this.adapter = settings.adapter || 'rest';
|
|
||||||
this.protocol = settings.protocol || 'http'
|
|
||||||
this.root = settings.root || '';
|
|
||||||
this.host = settings.host || 'localhost';
|
|
||||||
this.port = settings.port || 3000;
|
|
||||||
this.remotes = remoting.create();
|
|
||||||
|
|
||||||
// TODO(ritch) make sure this name works with Model.getSourceId()
|
|
||||||
this.name = 'remote-connector';
|
|
||||||
|
|
||||||
if(settings.url) {
|
|
||||||
this.url = settings.url;
|
|
||||||
} else {
|
|
||||||
this.url = this.protocol + '://' + this.host + ':' + this.port + this.root;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle mixins in the define() method
|
|
||||||
var DAO = this.DataAccessObject = function() {};
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteConnector.prototype.connect = function() {
|
|
||||||
this.remotes.connect(this.url, this.adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteConnector.initialize = function(dataSource, callback) {
|
|
||||||
var connector = dataSource.connector = new RemoteConnector(dataSource.settings);
|
|
||||||
connector.connect();
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteConnector.prototype.define = function(definition) {
|
|
||||||
var Model = definition.model;
|
|
||||||
var remotes = this.remotes;
|
|
||||||
var SharedClass;
|
|
||||||
|
|
||||||
assert(Model.sharedClass, 'cannot attach ' + Model.modelName
|
|
||||||
+ ' to a remote connector without a Model.sharedClass');
|
|
||||||
|
|
||||||
remotes.addClass(Model.sharedClass);
|
|
||||||
|
|
||||||
Model
|
|
||||||
.sharedClass
|
|
||||||
.methods()
|
|
||||||
.forEach(function(remoteMethod) {
|
|
||||||
// TODO(ritch) more elegant way of ignoring a nested shared class
|
|
||||||
if(remoteMethod.name !== 'Change'
|
|
||||||
&& remoteMethod.name !== 'Checkpoint') {
|
|
||||||
createProxyMethod(Model, remotes, remoteMethod);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function createProxyMethod(Model, remotes, remoteMethod) {
|
|
||||||
var scope = remoteMethod.isStatic ? Model : Model.prototype;
|
|
||||||
var original = scope[remoteMethod.name];
|
|
||||||
|
|
||||||
scope[remoteMethod.name] = function remoteMethodProxy() {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
var lastArgIsFunc = typeof args[args.length - 1] === 'function';
|
|
||||||
var callback;
|
|
||||||
if(lastArgIsFunc) {
|
|
||||||
callback = args.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
remotes.invoke(remoteMethod.stringName, args, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function noop() {}
|
|
|
@ -58,29 +58,9 @@ var Role = role.Role;
|
||||||
var ACLSchema = {
|
var ACLSchema = {
|
||||||
model: String, // The name of the model
|
model: String, // The name of the model
|
||||||
property: String, // The name of the property, method, scope, or relation
|
property: String, // The name of the property, method, scope, or relation
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the access type - READ/WRITE/EXECUTE
|
|
||||||
* @property accessType {String} Name of the access type - READ/WRITE/EXECUTE
|
|
||||||
*/
|
|
||||||
accessType: String,
|
accessType: String,
|
||||||
|
|
||||||
/**
|
|
||||||
* ALARM - Generate an alarm, in a system dependent way, the access specified
|
|
||||||
* in the permissions component of the ACL entry.
|
|
||||||
* ALLOW - Explicitly grants access to the resource.
|
|
||||||
* AUDIT - Log, in a system dependent way, the access specified in the
|
|
||||||
* permissions component of the ACL entry.
|
|
||||||
* DENY - Explicitly denies access to the resource.
|
|
||||||
*/
|
|
||||||
permission: String,
|
permission: String,
|
||||||
/**
|
|
||||||
* Type of the principal - Application/User/Role
|
|
||||||
*/
|
|
||||||
principalType: String,
|
principalType: String,
|
||||||
/**
|
|
||||||
* Id of the principal - such as appId, userId or roleId
|
|
||||||
*/
|
|
||||||
principalId: String
|
principalId: String
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,6 +68,16 @@ var ACLSchema = {
|
||||||
* A Model for access control meta data.
|
* A Model for access control meta data.
|
||||||
*
|
*
|
||||||
* @header ACL
|
* @header ACL
|
||||||
|
* @property {String} model Name of the model.
|
||||||
|
* @property {String} property Name of the property, method, scope, or relation.
|
||||||
|
* @property {String} accessType Type of access being granted: one of READ, WRITE, or EXECUTE.
|
||||||
|
* @property {String} permission Type of permission granted. One of:
|
||||||
|
* - ALARM: Generate an alarm, in a system-dependent way, the access specified in the permissions component of the ACL entry.
|
||||||
|
* - ALLOW: Explicitly grants access to the resource.
|
||||||
|
* - AUDIT: Log, in a system-dependent way, the access specified in the permissions component of the ACL entry.
|
||||||
|
* - DENY: Explicitly denies access to the resource.
|
||||||
|
* @property {String} principalType Type of the principal; one of: Application, Use, Role.
|
||||||
|
* @property {String} principalId ID of the principal - such as appId, userId or roleId
|
||||||
* @class
|
* @class
|
||||||
* @inherits Model
|
* @inherits Model
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -109,6 +109,33 @@ function generateKey(hmacKey, algorithm, encoding) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage client applications and organize their users.
|
* Manage client applications and organize their users.
|
||||||
|
*
|
||||||
|
* @property {String} id Generated ID.
|
||||||
|
* @property {String} name Name; required.
|
||||||
|
* @property {String} description Text description
|
||||||
|
* @property {String} icon String Icon image URL.
|
||||||
|
* @property {String} owner User ID of the developer who registers the application.
|
||||||
|
* @property {String} email E-mail address
|
||||||
|
* @property {Boolean} emailVerified Whether the e-mail is verified.
|
||||||
|
* @property {String} url OAuth 2.0 application URL.
|
||||||
|
* @property {String}[] callbackUrls The OAuth 2.0 code/token callback URL.
|
||||||
|
* @property {String} status Status of the application; Either `production`, `sandbox` (default), or `disabled`.
|
||||||
|
* @property {Date} created Date Application object was created. Default: current date.
|
||||||
|
* @property {Date} modified Date Application object was modified. Default: current date.
|
||||||
|
*
|
||||||
|
* @property {Boolean} pushSettings.apns.production Whether to use production Apple Push Notification Service (APNS) servers to send push notifications.
|
||||||
|
* If true, uses `gateway.push.apple.com:2195` and `feedback.push.apple.com:2196`.
|
||||||
|
* If false, uses `gateway.sandbox.push.apple.com:2195` and `feedback.sandbox.push.apple.com:2196`
|
||||||
|
* @property {String} pushSettings.apns.certData The certificate data loaded from the cert.pem file (APNS).
|
||||||
|
* @property {String} pushSettings.apns.keyData The key data loaded from the key.pem file (APNS).
|
||||||
|
* @property {String} pushSettings.apns.pushOptions.gateway (APNS).
|
||||||
|
* @property {Number} pushSettings.apns.pushOptions.port (APNS).
|
||||||
|
* @property {String} pushSettings.apns.feedbackOptions.gateway (APNS).
|
||||||
|
* @property {Number} pushSettings.apns.feedbackOptions.port (APNS).
|
||||||
|
* @property {Boolean} pushSettings.apns.feedbackOptions.batchFeedback (APNS).
|
||||||
|
* @property {Number} pushSettings.apns.feedbackOptions.interval (APNS).
|
||||||
|
* @property {String} pushSettings.gcm.serverApiKey: Google Cloud Messaging API key.
|
||||||
|
*
|
||||||
* @class
|
* @class
|
||||||
* @inherits {Model}
|
* @inherits {Model}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/**
|
/*!
|
||||||
* Module Dependencies.
|
* Module Dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -10,12 +10,12 @@ var PersistedModel = require('./persisted-model')
|
||||||
, assert = require('assert')
|
, assert = require('assert')
|
||||||
, debug = require('debug')('loopback:change');
|
, debug = require('debug')('loopback:change');
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* Properties
|
* Properties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var properties = {
|
var properties = {
|
||||||
id: {type: String, generated: true, id: true},
|
id: {type: String, id: true},
|
||||||
rev: {type: String},
|
rev: {type: String},
|
||||||
prev: {type: String},
|
prev: {type: String},
|
||||||
checkpoint: {type: Number},
|
checkpoint: {type: Number},
|
||||||
|
@ -23,7 +23,7 @@ var properties = {
|
||||||
modelId: {type: String}
|
modelId: {type: String}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* Options
|
* Options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -34,12 +34,12 @@ var options = {
|
||||||
/**
|
/**
|
||||||
* Change list entry.
|
* Change list entry.
|
||||||
*
|
*
|
||||||
* @property id {String} Hash of the modelName and id
|
* @property {String} id Hash of the modelName and id
|
||||||
* @property rev {String} the current model revision
|
* @property {String} rev The current model revision
|
||||||
* @property prev {String} the previous model revision
|
* @property {String} prev The previous model revision
|
||||||
* @property checkpoint {Number} the current checkpoint at time of the change
|
* @property {Number} checkpoint The current checkpoint at time of the change
|
||||||
* @property modelName {String} the model name
|
* @property {String} modelName Model name
|
||||||
* @property modelId {String} the model id
|
* @property {String} modelId Model ID
|
||||||
*
|
*
|
||||||
* @class
|
* @class
|
||||||
* @inherits {Model}
|
* @inherits {Model}
|
||||||
|
@ -515,7 +515,7 @@ function Conflict(modelId, SourceModel, TargetModel) {
|
||||||
* Fetch the conflicting models.
|
* Fetch the conflicting models.
|
||||||
*
|
*
|
||||||
* @callback {Function} callback
|
* @callback {Function} callback
|
||||||
* @param {Error}
|
* @param {Error} err
|
||||||
* @param {PersistedModel} source
|
* @param {PersistedModel} source
|
||||||
* @param {PersistedModel} target
|
* @param {PersistedModel} target
|
||||||
*/
|
*/
|
||||||
|
@ -618,12 +618,12 @@ Conflict.prototype.resolve = function(cb) {
|
||||||
/**
|
/**
|
||||||
* Determine the conflict type.
|
* Determine the conflict type.
|
||||||
*
|
*
|
||||||
* ```js
|
* Possible results are
|
||||||
* // possible results are
|
*
|
||||||
* Change.UPDATE // => source and target models were updated
|
* - `Change.UPDATE`: Source and target models were updated.
|
||||||
* Change.DELETE // => the source and or target model was deleted
|
* - `Change.DELETE`: Source and or target model was deleted.
|
||||||
* Change.UNKNOWN // => the conflict type is uknown or due to an error
|
* - `Change.UNKNOWN`: the conflict type is uknown or due to an error.
|
||||||
* ```
|
*
|
||||||
* @callback {Function} callback
|
* @callback {Function} callback
|
||||||
* @param {Error} err
|
* @param {Error} err
|
||||||
* @param {String} type The conflict type.
|
* @param {String} type The conflict type.
|
||||||
|
|
|
@ -14,16 +14,12 @@ var properties = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Email Model.
|
* @property {String} to Email addressee. Required.
|
||||||
|
* @property {String} from Email sender address. Required.
|
||||||
|
* @property {String} subject Email subject string. Required.
|
||||||
|
* @property {String} text Text body of email.
|
||||||
|
* @property {String} html HTML body of email.
|
||||||
*
|
*
|
||||||
* **Properties**
|
|
||||||
*
|
|
||||||
* - `to` - String (required)
|
|
||||||
* - `from` - String (required)
|
|
||||||
* - `subject` - String (required)
|
|
||||||
* - `text` - String
|
|
||||||
* - `html` - String
|
|
||||||
*
|
|
||||||
* @class
|
* @class
|
||||||
* @inherits {Model}
|
* @inherits {Model}
|
||||||
*/
|
*/
|
||||||
|
@ -58,4 +54,4 @@ var Email = module.exports = Model.extend('Email', properties);
|
||||||
|
|
||||||
Email.prototype.send = function() {
|
Email.prototype.send = function() {
|
||||||
throw new Error('You must connect the Email Model to a Mail connector');
|
throw new Error('You must connect the Email Model to a Mail connector');
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,6 +380,19 @@ Model.remoteMethod = function(name, options) {
|
||||||
this.sharedClass.defineMethod(name, options);
|
this.sharedClass.defineMethod(name, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable remote invocation for the method with the given name.
|
||||||
|
*
|
||||||
|
* @param {String} name The name of the method.
|
||||||
|
* @param {Boolean} isStatic Is the method static (eg. `MyModel.myMethod`)? Pass
|
||||||
|
* `false` if the method defined on the prototype (eg.
|
||||||
|
* `MyModel.prototype.myMethod`).
|
||||||
|
*/
|
||||||
|
|
||||||
|
Model.disableRemoteMethod = function(name, isStatic) {
|
||||||
|
this.sharedClass.disableMethod(name, isStatic || false);
|
||||||
|
}
|
||||||
|
|
||||||
Model.belongsToRemoting = function(relationName, relation, define) {
|
Model.belongsToRemoting = function(relationName, relation, define) {
|
||||||
var modelName = relation.modelTo && relation.modelTo.modelName;
|
var modelName = relation.modelTo && relation.modelTo.modelName;
|
||||||
modelName = modelName || 'PersistedModel';
|
modelName = modelName || 'PersistedModel';
|
||||||
|
|
|
@ -30,6 +30,9 @@ var RoleMappingSchema = {
|
||||||
* The `RoleMapping` model extends from the built in `loopback.Model` type.
|
* The `RoleMapping` model extends from the built in `loopback.Model` type.
|
||||||
*
|
*
|
||||||
* @class
|
* @class
|
||||||
|
* @property {String} id Generated ID.
|
||||||
|
* @property {String} name Name of the role.
|
||||||
|
* @property {String} Description Text description.
|
||||||
* @inherits {Model}
|
* @inherits {Model}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,12 @@ var options = {
|
||||||
* - ALLOW EVERYONE `findById`
|
* - ALLOW EVERYONE `findById`
|
||||||
* - ALLOW OWNER `updateAttributes`
|
* - ALLOW OWNER `updateAttributes`
|
||||||
*
|
*
|
||||||
|
* @property {String} username Must be unique
|
||||||
|
* @property {String} password Hidden from remote clients
|
||||||
|
* @property {String} email Must be valid email
|
||||||
|
* @property {Boolean} emailVerified Set when a user's email has been verified via `confirm()`
|
||||||
|
* @property {String} verificationToken Set when `verify()` is called
|
||||||
|
*
|
||||||
* @class
|
* @class
|
||||||
* @inherits {Model}
|
* @inherits {Model}
|
||||||
*/
|
*/
|
||||||
|
@ -169,7 +175,7 @@ User.login = function (credentials, include, fn) {
|
||||||
}else {
|
}else {
|
||||||
include = include.toLowerCase();
|
include = include.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var query = {};
|
var query = {};
|
||||||
|
|
|
@ -27,22 +27,23 @@
|
||||||
"mobile",
|
"mobile",
|
||||||
"mBaaS"
|
"mBaaS"
|
||||||
],
|
],
|
||||||
"version": "2.2.0",
|
"version": "2.4.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "grunt mocha-and-karma"
|
"test": "grunt mocha-and-karma"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "~0.9.0",
|
"async": "~0.9.0",
|
||||||
|
"bcryptjs": "~2.0.2",
|
||||||
"body-parser": "~1.8.1",
|
"body-parser": "~1.8.1",
|
||||||
"canonical-json": "0.0.4",
|
"canonical-json": "0.0.4",
|
||||||
|
"debug": "~2.0.0",
|
||||||
"ejs": "~1.0.0",
|
"ejs": "~1.0.0",
|
||||||
"express": "4.x",
|
"express": "4.x",
|
||||||
"strong-remoting": "^2.1.0",
|
|
||||||
"bcryptjs": "~2.0.2",
|
|
||||||
"debug": "~2.0.0",
|
|
||||||
"inflection": "~1.4.2",
|
"inflection": "~1.4.2",
|
||||||
|
"loopback-connector-remote": "^1.0.1",
|
||||||
"nodemailer": "~1.3.0",
|
"nodemailer": "~1.3.0",
|
||||||
"nodemailer-stub-transport": "~0.1.4",
|
"nodemailer-stub-transport": "~0.1.4",
|
||||||
|
"strong-remoting": "^2.4.0",
|
||||||
"uid2": "0.0.3",
|
"uid2": "0.0.3",
|
||||||
"underscore": "~1.7.0",
|
"underscore": "~1.7.0",
|
||||||
"underscore.string": "~2.3.3"
|
"underscore.string": "~2.3.3"
|
||||||
|
|
|
@ -84,6 +84,7 @@ describe('Change', function(){
|
||||||
it('should create an entry', function (done) {
|
it('should create an entry', function (done) {
|
||||||
var test = this;
|
var test = this;
|
||||||
Change.findById(this.result.id, function(err, change) {
|
Change.findById(this.result.id, function(err, change) {
|
||||||
|
if (err) return done(err);
|
||||||
assert.equal(change.id, test.result.id);
|
assert.equal(change.id, test.result.id);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue