diff --git a/.jshintrc b/.jshintrc index 5665b3fe..f294f4a0 100644 --- a/.jshintrc +++ b/.jshintrc @@ -9,5 +9,25 @@ "nonew": true, "sub": true, "laxcomma": true, -"laxbreak": true +"laxbreak": true, +"globals": { + + "after": true, + "afterEach": true, + "assert": true, + "before": true, + "beforeEach": true, + "describe": true, + "expect": true, + "it": true, + + /* loopback */ + "app": true, + "assertValidDataSource": true, + "GeoPoint": true, + "loopback": true, + "memoryConnector": true, + "request": true, + "TaskEmitter": true + } } diff --git a/CHANGES.md b/CHANGES.md index 7e8d3610..4fb4984f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,21 @@ +2014-11-27, Version 2.8.2 +========================= + + * Prepend slash for nested remoting paths (Clark Wang) + + * fix jscs errors (Rob Halff) + + * enable jshint for tests (Rob Halff) + + * permit some globals (Rob Halff) + + * 'done' is not defined (Rob Halff) + + * 'memory' is already defined (Rob Halff) + + * singlequote, semicolon & /*jshint -W030 */ (Rob Halff) + + 2014-11-25, Version 2.8.1 ========================= diff --git a/Gruntfile.js b/Gruntfile.js index a9804e59..fd48c0eb 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -38,18 +38,17 @@ module.exports = function(grunt) { }, server: { src: ['server/**/*.js'] + }, + test: { + src: ['test/**/*.js'] } - // TODO tests don't pass yet - // test: { - // src: ['test/**/*.js'] - // } }, jscs: { gruntfile: 'Gruntfile.js', lib: ['lib/**/*.js'], common: ['common/**/*.js'], - server: ['server/**/*.js'] - // TODO(bajtos) - test/**/*.js + server: ['server/**/*.js'], + test: ['test/**/*.js'] }, watch: { gruntfile: { diff --git a/lib/model.js b/lib/model.js index f6a3e9af..8b55c5d4 100644 --- a/lib/model.js +++ b/lib/model.js @@ -619,6 +619,10 @@ Model.nestRemoting = function(relationName, options, cb) { acceptArgs = []; } + if (httpPath[0] !== '/') { + httpPath = '/' + httpPath; + } + // A method should return the method name to use, if it is to be // included as a nested method - a falsy return value will skip. var filter = cb || options.filterMethod || function(method, relation) { diff --git a/package.json b/package.json index c18c5292..16bf4143 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback", - "version": "2.8.1", + "version": "2.8.2", "description": "LoopBack: Open Source Framework for Node.js", "homepage": "http://loopback.io", "keywords": [ diff --git a/test/access-control.integration.js b/test/access-control.integration.js index 28e48031..01fd2a16 100644 --- a/test/access-control.integration.js +++ b/test/access-control.integration.js @@ -1,3 +1,5 @@ +/*jshint -W030 */ + var loopback = require('../'); var lt = require('loopback-testing'); var path = require('path'); @@ -8,19 +10,19 @@ var USER = {email: 'test@test.test', password: 'test'}; var CURRENT_USER = {email: 'current@test.test', password: 'test'}; var debug = require('debug')('loopback:test:access-control.integration'); -describe('access control - integration', function () { +describe('access control - integration', function() { lt.beforeEach.withApp(app); /* describe('accessToken', function() { - // it('should be a sublcass of AccessToken', function () { + // it('should be a sublcass of AccessToken', function() { // assert(app.models.accessToken.prototype instanceof loopback.AccessToken); // }); - it('should have a validate method', function () { + it('should have a validate method', function() { var token = new app.models.accessToken; - assert.equal(typeof token.validate, 'function'); + assert.equal(typeof token.validate, 'function'); }); }); @@ -58,17 +60,17 @@ describe('access control - integration', function () { }); */ - describe('/users', function () { + describe('/users', function() { lt.beforeEach.givenModel('user', USER, 'randomUser'); lt.it.shouldBeDeniedWhenCalledAnonymously('GET', '/api/users'); lt.it.shouldBeDeniedWhenCalledUnauthenticated('GET', '/api/users'); lt.it.shouldBeDeniedWhenCalledByUser(CURRENT_USER, 'GET', '/api/users'); - + lt.it.shouldBeDeniedWhenCalledAnonymously('GET', urlForUser); lt.it.shouldBeDeniedWhenCalledUnauthenticated('GET', urlForUser); - lt.it.shouldBeDeniedWhenCalledByUser(CURRENT_USER,'GET', urlForUser); + lt.it.shouldBeDeniedWhenCalledByUser(CURRENT_USER, 'GET', urlForUser); lt.it.shouldBeAllowedWhenCalledAnonymously( 'POST', '/api/users', newUserData()); @@ -131,7 +133,7 @@ describe('access control - integration', function () { } }); - describe('/banks', function () { + describe('/banks', function() { lt.beforeEach.givenModel('bank'); lt.it.shouldBeAllowedWhenCalledAnonymously('GET', '/api/banks'); @@ -159,13 +161,13 @@ describe('access control - integration', function () { } }); - describe('/accounts', function () { + describe('/accounts', function() { var count = 0; before(function() { var roleModel = loopback.getModelByType(loopback.Role); - roleModel.registerResolver('$dummy', function (role, context, callback) { - process.nextTick(function () { - if(context.remotingContext) { + roleModel.registerResolver('$dummy', function(role, context, callback) { + process.nextTick(function() { + if (context.remotingContext) { count++; } callback && callback(null, false); // Always true @@ -224,5 +226,5 @@ describe('access control - integration', function () { return '/api/accounts/' + this.account.id; } }); - + }); diff --git a/test/access-token.test.js b/test/access-token.test.js index 14905b75..e20521a8 100644 --- a/test/access-token.test.js +++ b/test/access-token.test.js @@ -6,14 +6,14 @@ var ACL = loopback.ACL; describe('loopback.token(options)', function() { beforeEach(createTestingToken); - it('should populate req.token from the query string', function (done) { + it('should populate req.token from the query string', function(done) { createTestAppAndRequest(this.token, done) .get('/?access_token=' + this.token.id) .expect(200) .end(done); }); - it('should populate req.token from an authorization header', function (done) { + it('should populate req.token from an authorization header', function(done) { createTestAppAndRequest(this.token, done) .get('/') .set('authorization', this.token.id) @@ -21,7 +21,7 @@ describe('loopback.token(options)', function() { .end(done); }); - it('should populate req.token from an X-Access-Token header', function (done) { + it('should populate req.token from an X-Access-Token header', function(done) { createTestAppAndRequest(this.token, done) .get('/') .set('X-Access-Token', this.token.id) @@ -29,9 +29,9 @@ describe('loopback.token(options)', function() { .end(done); }); - it('should populate req.token from an authorization header with bearer token', function (done) { + it('should populate req.token from an authorization header with bearer token', function(done) { var token = this.token.id; - token = 'Bearer '+ new Buffer(token).toString('base64'); + token = 'Bearer ' + new Buffer(token).toString('base64'); createTestAppAndRequest(this.token, done) .get('/') .set('authorization', this.token.id) @@ -39,7 +39,7 @@ describe('loopback.token(options)', function() { .end(done); }); - it('should populate req.token from a secure cookie', function (done) { + it('should populate req.token from a secure cookie', function(done) { var app = createTestApp(this.token, done); request(app) @@ -52,7 +52,7 @@ describe('loopback.token(options)', function() { }); }); - it('should populate req.token from a header or a secure cookie', function (done) { + it('should populate req.token from a header or a secure cookie', function(done) { var app = createTestApp(this.token, done); var id = this.token.id; request(app) @@ -88,20 +88,20 @@ describe('loopback.token(options)', function() { }); }); -describe('AccessToken', function () { +describe('AccessToken', function() { beforeEach(createTestingToken); - it('should auto-generate id', function () { + it('should auto-generate id', function() { assert(this.token.id); assert.equal(this.token.id.length, 64); }); - it('should auto-generate created date', function () { + it('should auto-generate created date', function() { assert(this.token.created); assert(Object.prototype.toString.call(this.token.created), '[object Date]'); }); - it('should be validateable', function (done) { + it('should be validateable', function(done) { this.token.validate(function(err, isValid) { assert(isValid); done(); @@ -144,7 +144,7 @@ describe('AccessToken', function () { describe('app.enableAuth()', function() { beforeEach(createTestingToken); - it('prevents remote call with 401 status on denied ACL', function (done) { + it('prevents remote call with 401 status on denied ACL', function(done) { createTestAppAndRequest(this.token, done) .del('/tests/123') .expect(401) @@ -152,7 +152,7 @@ describe('app.enableAuth()', function() { .end(done); }); - it('prevent remote call with app setting status on denied ACL', function (done) { + it('prevent remote call with app setting status on denied ACL', function(done) { createTestAppAndRequest(this.token, {app:{aclErrorStatus:403}}, done) .del('/tests/123') .expect(403) @@ -160,7 +160,7 @@ describe('app.enableAuth()', function() { .end(done); }); - it('prevent remote call with app setting status on denied ACL', function (done) { + it('prevent remote call with app setting status on denied ACL', function(done) { createTestAppAndRequest(this.token, {model:{aclErrorStatus:404}}, done) .del('/tests/123') .expect(404) @@ -168,7 +168,7 @@ describe('app.enableAuth()', function() { .end(done); }); - it('prevent remote call if the accessToken is missing and required', function (done) { + it('prevent remote call if the accessToken is missing and required', function(done) { createTestAppAndRequest(null, done) .del('/tests/123') .expect(401) @@ -210,8 +210,8 @@ describe('app.enableAuth()', function() { function createTestingToken(done) { var test = this; - Token.create({}, function (err, token) { - if(err) return done(err); + Token.create({}, function(err, token) { + if (err) return done(err); test.token = token; done(); }); @@ -223,8 +223,8 @@ function createTestAppAndRequest(testToken, settings, done) { } function createTestApp(testToken, settings, done) { - done = arguments[arguments.length-1]; - if(settings == done) settings = {}; + done = arguments[arguments.length - 1]; + if (settings == done) settings = {}; settings = settings || {}; var appSettings = settings.app || {}; @@ -238,11 +238,11 @@ function createTestApp(testToken, settings, done) { res.cookie('authorization', testToken.id, {signed: true}); res.end(); }); - app.get('/', function (req, res) { + app.get('/', function(req, res) { try { assert(req.accessToken, 'req should have accessToken'); assert(req.accessToken.id === testToken.id); - } catch(e) { + } catch (e) { return done(e); } res.send('ok'); @@ -250,15 +250,15 @@ function createTestApp(testToken, settings, done) { app.use(loopback.rest()); app.enableAuth(); - Object.keys(appSettings).forEach(function(key){ + Object.keys(appSettings).forEach(function(key) { app.set(key, appSettings[key]); }); var modelOptions = { acls: [ { - principalType: "ROLE", - principalId: "$everyone", + principalType: 'ROLE', + principalId: '$everyone', accessType: ACL.ALL, permission: ACL.DENY, property: 'deleteById' @@ -266,7 +266,7 @@ function createTestApp(testToken, settings, done) { ] }; - Object.keys(modelSettings).forEach(function(key){ + Object.keys(modelSettings).forEach(function(key) { modelOptions[key] = modelSettings[key]; }); diff --git a/test/acl.test.js b/test/acl.test.js index 1c159f25..cd18d20e 100644 --- a/test/acl.test.js +++ b/test/acl.test.js @@ -17,7 +17,7 @@ before(function() { ds = loopback.createDataSource({connector: loopback.Memory}); }); -describe('security scopes', function () { +describe('security scopes', function() { beforeEach(function() { var ds = this.ds = loopback.createDataSource({connector: loopback.Memory}); testModel = loopback.PersistedModel.extend('testModel'); @@ -29,11 +29,11 @@ describe('security scopes', function () { testModel.attachTo(ds); }); - it("should allow access to models for the given scope by wildcard", function () { - Scope.create({name: 'userScope', description: 'access user information'}, function (err, scope) { + it('should allow access to models for the given scope by wildcard', function() { + Scope.create({name: 'userScope', description: 'access user information'}, function(err, scope) { ACL.create({principalType: ACL.SCOPE, principalId: scope.id, model: 'User', property: ACL.ALL, accessType: ACL.ALL, permission: ACL.ALLOW}, - function (err, resource) { + function(err, resource) { Scope.checkPermission('userScope', 'User', ACL.ALL, ACL.ALL, checkResult); Scope.checkPermission('userScope', 'User', 'name', ACL.ALL, checkResult); Scope.checkPermission('userScope', 'User', 'name', ACL.READ, checkResult); @@ -42,25 +42,25 @@ describe('security scopes', function () { }); - it("should allow access to models for the given scope", function () { - Scope.create({name: 'testModelScope', description: 'access testModel information'}, function (err, scope) { + it('should allow access to models for the given scope', function() { + Scope.create({name: 'testModelScope', description: 'access testModel information'}, function(err, scope) { ACL.create({principalType: ACL.SCOPE, principalId: scope.id, model: 'testModel', property: 'name', accessType: ACL.READ, permission: ACL.ALLOW}, - function (err, resource) { + function(err, resource) { ACL.create({principalType: ACL.SCOPE, principalId: scope.id, model: 'testModel', property: 'name', accessType: ACL.WRITE, permission: ACL.DENY}, - function (err, resource) { + function(err, resource) { // console.log(resource); - Scope.checkPermission('testModelScope', 'testModel', ACL.ALL, ACL.ALL, function (err, perm) { + Scope.checkPermission('testModelScope', 'testModel', ACL.ALL, ACL.ALL, function(err, perm) { assert(perm.permission === ACL.DENY); // because name.WRITE == DENY }); - Scope.checkPermission('testModelScope', 'testModel', 'name', ACL.ALL, function (err, perm) { + Scope.checkPermission('testModelScope', 'testModel', 'name', ACL.ALL, function(err, perm) { assert(perm.permission === ACL.DENY); // because name.WRITE == DENY }); - Scope.checkPermission('testModelScope', 'testModel', 'name', ACL.READ, function (err, perm) { + Scope.checkPermission('testModelScope', 'testModel', 'name', ACL.READ, function(err, perm) { assert(perm.permission === ACL.ALLOW); }); - Scope.checkPermission('testModelScope', 'testModel', 'name', ACL.WRITE, function (err, perm) { + Scope.checkPermission('testModelScope', 'testModel', 'name', ACL.WRITE, function(err, perm) { assert(perm.permission === ACL.DENY); }); }); @@ -71,29 +71,29 @@ describe('security scopes', function () { }); -describe('security ACLs', function () { +describe('security ACLs', function() { it('should order ACL entries based on the matching score', function() { var acls = [ { - "model": "account", - "accessType": "*", - "permission": "DENY", - "principalType": "ROLE", - "principalId": "$everyone" + 'model': 'account', + 'accessType': '*', + 'permission': 'DENY', + 'principalType': 'ROLE', + 'principalId': '$everyone' }, { - "model": "account", - "accessType": "*", - "permission": "ALLOW", - "principalType": "ROLE", - "principalId": "$owner" + 'model': 'account', + 'accessType': '*', + 'permission': 'ALLOW', + 'principalType': 'ROLE', + 'principalId': '$owner' }, { - "model": "account", - "accessType": "READ", - "permission": "ALLOW", - "principalType": "ROLE", - "principalId": "$everyone" + 'model': 'account', + 'accessType': 'READ', + 'permission': 'ALLOW', + 'principalType': 'ROLE', + 'principalId': '$everyone' }]; var req = { model: 'account', @@ -101,7 +101,7 @@ describe('security ACLs', function () { accessType: 'WRITE' }; - acls = acls.map(function(a) { return new ACL(a)}); + acls = acls.map(function(a) { return new ACL(a); }); var perm = ACL.resolvePermission(acls, req); assert.deepEqual(perm, { model: 'account', @@ -111,18 +111,18 @@ describe('security ACLs', function () { methodNames: []}); }); - it("should allow access to models for the given principal by wildcard", function () { + it('should allow access to models for the given principal by wildcard', function() { ACL.create({principalType: ACL.USER, principalId: 'u001', model: 'User', property: ACL.ALL, - accessType: ACL.ALL, permission: ACL.ALLOW}, function (err, acl) { + accessType: ACL.ALL, permission: ACL.ALLOW}, function(err, acl) { ACL.create({principalType: ACL.USER, principalId: 'u001', model: 'User', property: ACL.ALL, - accessType: ACL.READ, permission: ACL.DENY}, function (err, acl) { + accessType: ACL.READ, permission: ACL.DENY}, function(err, acl) { - ACL.checkPermission(ACL.USER, 'u001', 'User', 'name', ACL.READ, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'User', 'name', ACL.READ, function(err, perm) { assert(perm.permission === ACL.DENY); }); - ACL.checkPermission(ACL.USER, 'u001', 'User', 'name', ACL.ALL, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'User', 'name', ACL.ALL, function(err, perm) { assert(perm.permission === ACL.DENY); }); @@ -132,26 +132,26 @@ describe('security ACLs', function () { }); - it("should allow access to models by exception", function () { + it('should allow access to models by exception', function() { ACL.create({principalType: ACL.USER, principalId: 'u001', model: 'testModel', property: ACL.ALL, - accessType: ACL.ALL, permission: ACL.DENY}, function (err, acl) { + accessType: ACL.ALL, permission: ACL.DENY}, function(err, acl) { ACL.create({principalType: ACL.USER, principalId: 'u001', model: 'testModel', property: ACL.ALL, - accessType: ACL.READ, permission: ACL.ALLOW}, function (err, acl) { + accessType: ACL.READ, permission: ACL.ALLOW}, function(err, acl) { - ACL.checkPermission(ACL.USER, 'u001', 'testModel', 'name', ACL.READ, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'testModel', 'name', ACL.READ, function(err, perm) { assert(perm.permission === ACL.ALLOW); }); - ACL.checkPermission(ACL.USER, 'u001', 'testModel', ACL.ALL, ACL.READ, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'testModel', ACL.ALL, ACL.READ, function(err, perm) { assert(perm.permission === ACL.ALLOW); }); - ACL.checkPermission(ACL.USER, 'u001', 'testModel', 'name', ACL.WRITE, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'testModel', 'name', ACL.WRITE, function(err, perm) { assert(perm.permission === ACL.DENY); }); - ACL.checkPermission(ACL.USER, 'u001', 'testModel', 'name', ACL.ALL, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'testModel', 'name', ACL.ALL, function(err, perm) { assert(perm.permission === ACL.DENY); }); @@ -161,7 +161,7 @@ describe('security ACLs', function () { }); - it("should honor defaultPermission from the model", function () { + it('should honor defaultPermission from the model', function() { var Customer = ds.createModel('Customer', { name: { type: String, @@ -178,21 +178,21 @@ describe('security ACLs', function () { Customer.settings.defaultPermission = ACL.DENY; - ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.WRITE, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.WRITE, function(err, perm) { assert(perm.permission === ACL.DENY); }); - ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.READ, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.READ, function(err, perm) { assert(perm.permission === ACL.ALLOW); }); - ACL.checkPermission(ACL.USER, 'u002', 'Customer', 'name', ACL.WRITE, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u002', 'Customer', 'name', ACL.WRITE, function(err, perm) { assert(perm.permission === ACL.DENY); }); }); - it("should honor static ACLs from the model", function () { + it('should honor static ACLs from the model', function() { var Customer = ds.createModel('Customer', { name: { type: String, @@ -213,21 +213,21 @@ describe('security ACLs', function () { ]; */ - ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.WRITE, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.WRITE, function(err, perm) { assert(perm.permission === ACL.DENY); }); - ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.READ, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.READ, function(err, perm) { assert(perm.permission === ACL.ALLOW); }); - ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.ALL, function (err, perm) { + ACL.checkPermission(ACL.USER, 'u001', 'Customer', 'name', ACL.ALL, function(err, perm) { assert(perm.permission === ACL.ALLOW); }); }); - it("should filter static ACLs by model/property", function() { + it('should filter static ACLs by model/property', function() { var Model1 = ds.createModel('Model1', { name: { type: String, @@ -254,12 +254,12 @@ describe('security ACLs', function () { assert(staticACLs.length === 1); }); - it("should check access against LDL, ACL, and Role", function () { + it('should check access against LDL, ACL, and Role', function() { // var log = console.log; var log = function() {}; // Create - User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function (err, user) { + User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) { log('User: ', user.toObject()); @@ -282,19 +282,19 @@ describe('security ACLs', function () { }); ACL.create({principalType: ACL.USER, principalId: userId, model: 'Customer', property: ACL.ALL, - accessType: ACL.ALL, permission: ACL.ALLOW}, function (err, acl) { + accessType: ACL.ALL, permission: ACL.ALLOW}, function(err, acl) { log('ACL 1: ', acl.toObject()); - Role.create({name: 'MyRole'}, function (err, myRole) { + Role.create({name: 'MyRole'}, function(err, myRole) { log('Role: ', myRole.toObject()); - myRole.principals.create({principalType: RoleMapping.USER, principalId: userId}, function (err, p) { + myRole.principals.create({principalType: RoleMapping.USER, principalId: userId}, function(err, p) { log('Principal added to role: ', p.toObject()); ACL.create({principalType: ACL.ROLE, principalId: 'MyRole', model: 'Customer', property: ACL.ALL, - accessType: ACL.READ, permission: ACL.DENY}, function (err, acl) { + accessType: ACL.READ, permission: ACL.DENY}, function(err, acl) { log('ACL 2: ', acl.toObject()); @@ -327,6 +327,3 @@ describe('security ACLs', function () { }); }); }); - - - diff --git a/test/app.test.js b/test/app.test.js index 073bf149..452089f1 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -1,3 +1,5 @@ +/*jshint -W030 */ + var async = require('async'); var path = require('path'); @@ -39,7 +41,7 @@ describe('app', function() { }); }); - it('supports "before:" and "after:" prefixes', function(done) { + it('supports `before:` and `after:` prefixes', function(done) { app.middleware('routes:before', namedHandler('routes:before')); app.middleware('routes:after', namedHandler('routes:after')); app.use(namedHandler('main')); @@ -247,7 +249,7 @@ describe('app', function() { app = loopback(); }); - it('adds the phase just before "routes" by default', function(done) { + it('adds the phase just before `routes` by default', function(done) { app.defineMiddlewarePhases('custom'); verifyMiddlewarePhases(['custom', 'routes'], done); }); @@ -305,13 +307,14 @@ describe('app', function() { }); describe('app.model(Model)', function() { - var app, db; + var app; + var db; beforeEach(function() { app = loopback(); db = loopback.createDataSource({connector: loopback.Memory}); }); - it("Expose a `Model` to remote clients", function() { + it('Expose a `Model` to remote clients', function() { var Color = PersistedModel.extend('color', {name: String}); app.model(Color); Color.attachTo(db); @@ -330,7 +333,7 @@ describe('app', function() { var Color = PersistedModel.extend('color', {name: String}); app.model(Color); Color.attachTo(db); - var classes = app.remotes().classes().map(function(c) {return c.name}); + var classes = app.remotes().classes().map(function(c) {return c.name;}); expect(classes).to.contain('color'); }); @@ -343,7 +346,7 @@ describe('app', function() { expect(app.models.Color).to.equal(Color); }); - it("emits a `modelRemoted` event", function() { + it('emits a `modelRemoted` event', function() { var Color = PersistedModel.extend('color', {name: String}); Color.shared = true; var remotedClass; @@ -376,7 +379,7 @@ describe('app', function() { }); - describe('app.model(name, config)', function () { + describe('app.model(name, config)', function() { var app; beforeEach(function() { @@ -386,7 +389,7 @@ describe('app', function() { }); }); - it('Sugar for defining a fully built model', function () { + it('Sugar for defining a fully built model', function() { app.model('foo', { dataSource: 'db' }); @@ -493,7 +496,7 @@ describe('app', function() { .expect(200, done); }); - it('updates port on "listening" event', function(done) { + it('updates port on `listening` event', function(done) { var app = loopback(); app.set('port', 0); @@ -503,7 +506,7 @@ describe('app', function() { }); }); - it('updates "url" on "listening" event', function(done) { + it('updates `url` on `listening` event', function(done) { var app = loopback(); app.set('port', 0); app.set('host', undefined); @@ -559,15 +562,15 @@ describe('app', function() { }); }); - describe.onServer('app.get("/", loopback.status())', function () { - it('should return the status of the application', function (done) { + describe.onServer('app.get(\'/\', loopback.status())', function() { + it('should return the status of the application', function(done) { var app = loopback(); app.get('/', loopback.status()); request(app) .get('/') .expect(200) .end(function(err, res) { - if(err) return done(err); + if (err) return done(err); assert.equal(typeof res.body, 'object'); assert(res.body.started); @@ -649,7 +652,8 @@ describe('app', function() { }); describe('normalizeHttpPath option', function() { - var app, db; + var app; + var db; beforeEach(function() { app = loopback(); db = loopback.createDataSource({ connector: loopback.Memory }); diff --git a/test/change.test.js b/test/change.test.js index 53bdcec9..63855528 100644 --- a/test/change.test.js +++ b/test/change.test.js @@ -1,7 +1,7 @@ var Change; var TestModel; -describe('Change', function(){ +describe('Change', function() { beforeEach(function() { var memory = loopback.createDataSource({ connector: loopback.Memory @@ -20,7 +20,7 @@ describe('Change', function(){ foo: 'bar' }; TestModel.create(test.data, function(err, model) { - if(err) return done(err); + if (err) return done(err); test.model = model; test.modelId = model.id; test.revisionForModel = Change.revisionForInst(model); @@ -28,8 +28,8 @@ describe('Change', function(){ }); }); - describe('change.id', function () { - it('should be a hash of the modelName and modelId', function () { + describe('change.id', function() { + it('should be a hash of the modelName and modelId', function() { var change = new Change({ rev: 'abc', modelName: 'foo', @@ -42,17 +42,17 @@ describe('Change', function(){ }); }); - describe('Change.rectifyModelChanges(modelName, modelIds, callback)', function () { - describe('using an existing untracked model', function () { + describe('Change.rectifyModelChanges(modelName, modelIds, callback)', function() { + describe('using an existing untracked model', function() { beforeEach(function(done) { var test = this; Change.rectifyModelChanges(this.modelName, [this.modelId], function(err, trackedChanges) { - if(err) return done(err); + if (err) return done(err); done(); }); }); - it('should create an entry', function (done) { + it('should create an entry', function(done) { var test = this; Change.find(function(err, trackedChanges) { assert.equal(trackedChanges[0].modelId, test.modelId.toString()); @@ -60,7 +60,7 @@ describe('Change', function(){ }); }); - it('should only create one change', function (done) { + it('should only create one change', function(done) { Change.count(function(err, count) { assert.equal(count, 1); done(); @@ -69,19 +69,19 @@ describe('Change', function(){ }); }); - describe('Change.findOrCreateChange(modelName, modelId, callback)', function () { - - describe('when a change doesnt exist', function () { + describe('Change.findOrCreateChange(modelName, modelId, callback)', function() { + + describe('when a change doesnt exist', function() { beforeEach(function(done) { var test = this; Change.findOrCreateChange(this.modelName, this.modelId, function(err, result) { - if(err) return done(err); + if (err) return done(err); test.result = result; done(); }); }); - it('should create an entry', function (done) { + it('should create an entry', function(done) { var test = this; Change.findById(this.result.id, function(err, change) { if (err) return done(err); @@ -91,7 +91,7 @@ describe('Change', function(){ }); }); - describe('when a change does exist', function () { + describe('when a change does exist', function() { beforeEach(function(done) { var test = this; Change.create({ @@ -106,22 +106,22 @@ describe('Change', function(){ beforeEach(function(done) { var test = this; Change.findOrCreateChange(this.modelName, this.modelId, function(err, result) { - if(err) return done(err); + if (err) return done(err); test.result = result; done(); }); }); - it('should find the entry', function (done) { - var test = this; + it('should find the entry', function(done) { + var test = this; assert.equal(test.existingChange.id, test.result.id); done(); }); }); }); - describe('change.rectify(callback)', function () { - it('should create a new change with the correct revision', function (done) { + describe('change.rectify(callback)', function() { + it('should create a new change with the correct revision', function(done) { var test = this; var change = new Change({ modelName: this.modelName, @@ -135,8 +135,8 @@ describe('Change', function(){ }); }); - describe('change.currentRevision(callback)', function () { - it('should get the correct revision', function (done) { + describe('change.currentRevision(callback)', function() { + it('should get the correct revision', function(done) { var test = this; var change = new Change({ modelName: this.modelName, @@ -150,9 +150,9 @@ describe('Change', function(){ }); }); - describe('Change.hash(str)', function () { + describe('Change.hash(str)', function() { // todo(ritch) test other hashing algorithms - it('should hash the given string', function () { + it('should hash the given string', function() { var str = 'foo'; var hash = Change.hash(str); assert(hash !== str); @@ -160,8 +160,8 @@ describe('Change', function(){ }); }); - describe('Change.revisionForInst(inst)', function () { - it('should return the same revision for the same data', function () { + describe('Change.revisionForInst(inst)', function() { + it('should return the same revision for the same data', function() { var a = { b: { b: ['c', 'd'], @@ -181,34 +181,34 @@ describe('Change', function(){ }); }); - describe('change.type()', function () { - it('CREATE', function () { + describe('change.type()', function() { + it('CREATE', function() { var change = new Change({ rev: this.revisionForModel }); assert.equal(Change.CREATE, change.type()); }); - it('UPDATE', function () { + it('UPDATE', function() { var change = new Change({ rev: this.revisionForModel, prev: this.revisionForModel }); assert.equal(Change.UPDATE, change.type()); }); - it('DELETE', function () { + it('DELETE', function() { var change = new Change({ prev: this.revisionForModel }); assert.equal(Change.DELETE, change.type()); }); - it('UNKNOWN', function () { + it('UNKNOWN', function() { var change = new Change(); assert.equal(Change.UNKNOWN, change.type()); }); }); - describe('change.getModelCtor()', function () { - it('should get the correct model class', function () { + describe('change.getModelCtor()', function() { + it('should get the correct model class', function() { var change = new Change({ modelName: this.modelName }); @@ -217,8 +217,8 @@ describe('Change', function(){ }); }); - describe('change.equals(otherChange)', function () { - it('should return true when the change is equal', function () { + describe('change.equals(otherChange)', function() { + it('should return true when the change is equal', function() { var change = new Change({ rev: this.revisionForModel }); @@ -230,7 +230,7 @@ describe('Change', function(){ assert.equal(change.equals(otherChange), true); }); - it('should return true when both changes are deletes', function () { + it('should return true when both changes are deletes', function() { var REV = 'foo'; var change = new Change({ rev: null, @@ -249,8 +249,8 @@ describe('Change', function(){ }); }); - describe('change.isBasedOn(otherChange)', function () { - it('should return true when the change is based on the other', function () { + describe('change.isBasedOn(otherChange)', function() { + it('should return true when the change is based on the other', function() { var change = new Change({ prev: this.revisionForModel }); @@ -263,7 +263,7 @@ describe('Change', function(){ }); }); - describe('Change.diff(modelName, since, remoteChanges, callback)', function () { + describe('Change.diff(modelName, since, remoteChanges, callback)', function() { beforeEach(function(done) { Change.create([ {rev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1}, @@ -272,7 +272,7 @@ describe('Change', function(){ ], done); }); - it('should return delta and conflict lists', function (done) { + it('should return delta and conflict lists', function(done) { var remoteChanges = [ // an update => should result in a delta {rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1}, diff --git a/test/data-source.test.js b/test/data-source.test.js index 113c3025..f8f14f24 100644 --- a/test/data-source.test.js +++ b/test/data-source.test.js @@ -1,16 +1,16 @@ describe('DataSource', function() { var memory; - - beforeEach(function(){ + + beforeEach(function() { memory = loopback.createDataSource({ connector: loopback.Memory }); - + assertValidDataSource(memory); }); describe('dataSource.createModel(name, properties, settings)', function() { - it("Define a model and attach it to a `DataSource`", function() { + it('Define a model and attach it to a `DataSource`', function() { var Color = memory.createModel('color', {name: String}); assert.isFunc(Color, 'find'); assert.isFunc(Color, 'findById'); @@ -31,23 +31,23 @@ describe('DataSource', function() { assert.isFunc(Color.prototype, 'destroy'); assert.isFunc(Color.prototype, 'updateAttribute'); assert.isFunc(Color.prototype, 'updateAttributes'); - assert.isFunc(Color.prototype, 'reload'); + assert.isFunc(Color.prototype, 'reload'); }); - it("should honor settings.base", function() { + it('should honor settings.base', function() { var Base = memory.createModel('base'); var Color = memory.createModel('color', {name: String}, {base: Base}); assert(Color.prototype instanceof Base); assert.equal(Color.base, Base); }); - it("should use loopback.PersistedModel as the base for DBs", function() { + it('should use loopback.PersistedModel as the base for DBs', function() { var Color = memory.createModel('color', {name: String}); assert(Color.prototype instanceof loopback.PersistedModel); assert.equal(Color.base, loopback.PersistedModel); }); - it("should use loopback.Model as the base for non DBs", function() { + it('should use loopback.Model as the base for non DBs', function() { // Mock up a non-DB connector var Connector = function() { }; @@ -67,10 +67,10 @@ describe('DataSource', function() { }); describe.skip('PersistedModel Methods', function() { - it("List the enabled and disabled methods", function() { + it('List the enabled and disabled methods', function() { var TestModel = loopback.PersistedModel.extend('TestPersistedModel'); TestModel.attachTo(loopback.memory()); - + // assert the defaults // - true: the method should be remote enabled // - false: the method should not be remote enabled @@ -97,7 +97,7 @@ describe('DataSource', function() { existsAndShared('updateAttributes', true); existsAndShared('updateAll', true); existsAndShared('reload', false); - + function existsAndShared(Model, name, isRemoteEnabled, isProto) { var scope = isProto ? Model.prototype : Model; var fn = scope[name]; diff --git a/test/e2e/remote-connector.e2e.js b/test/e2e/remote-connector.e2e.js index 47c0d7bb..a1f3332c 100644 --- a/test/e2e/remote-connector.e2e.js +++ b/test/e2e/remote-connector.e2e.js @@ -14,22 +14,22 @@ describe('RemoteConnector', function() { TestModel.attachTo(ds); }); - it('should be able to call create', function (done) { + it('should be able to call create', function(done) { TestModel.create({ foo: 'bar' }, function(err, inst) { - if(err) return done(err); + if (err) return done(err); assert(inst.id); done(); }); }); - it('should be able to call save', function (done) { + it('should be able to call save', function(done) { var m = new TestModel({ foo: 'bar' }); m.save(function(err, data) { - if(err) return done(err); + if (err) return done(err); assert(data.foo === 'bar'); done(); }); diff --git a/test/e2e/replication.e2e.js b/test/e2e/replication.e2e.js index fc42def4..502059a7 100644 --- a/test/e2e/replication.e2e.js +++ b/test/e2e/replication.e2e.js @@ -19,14 +19,14 @@ describe('Replication', function() { LocalTestModel.attachTo(memory); }); - it('should replicate local data to the remote', function (done) { + it('should replicate local data to the remote', function(done) { var RANDOM = Math.random(); LocalTestModel.create({ n: RANDOM }, function(err, created) { LocalTestModel.replicate(0, TestModel, function() { - if(err) return done(err); + if (err) return done(err); TestModel.findOne({n: RANDOM}, function(err, found) { assert.equal(created.id, found.id); done(); diff --git a/test/email.test.js b/test/email.test.js index b125f2aa..018f543c 100644 --- a/test/email.test.js +++ b/test/email.test.js @@ -3,30 +3,29 @@ var MyEmail; var assert = require('assert'); var MailConnector = require('../lib/connectors/mail'); -describe('Email connector', function () { - it('should set up SMTP', function () { +describe('Email connector', function() { + it('should set up SMTP', function() { var connector = new MailConnector({transports: [ {type: 'smtp', service: 'gmail'} ]}); assert(connector.transportForName('smtp')); }); - it('should set up DIRECT', function () { + it('should set up DIRECT', function() { var connector = new MailConnector({transports: [ {type: 'direct', name: 'localhost'} ]}); assert(connector.transportForName('direct')); }); - it('should set up STUB', function () { + it('should set up STUB', function() { var connector = new MailConnector({transports: [ {type: 'stub', service: 'gmail'} ]}); assert(connector.transportForName('stub')); }); - - it('should set up a single transport for SMTP' , function () { + it('should set up a single transport for SMTP' , function() { var connector = new MailConnector({transport: {type: 'smtp', service: 'gmail'} }); @@ -34,22 +33,21 @@ describe('Email connector', function () { assert(connector.transportForName('smtp')); }); - }); -describe('Email and SMTP', function () { +describe('Email and SMTP', function() { beforeEach(function() { MyEmail = loopback.Email.extend('my-email'); loopback.autoAttach(); }); - - it('should have a send method', function () { + + it('should have a send method', function() { assert(typeof MyEmail.send === 'function'); assert(typeof MyEmail.prototype.send === 'function'); }); - describe('MyEmail', function () { - it('MyEmail.send(options, callback)', function (done) { + describe('MyEmail', function() { + it('MyEmail.send(options, callback)', function(done) { var options = { to: 'to@to.com', from: 'from@from.com', @@ -67,7 +65,7 @@ describe('Email and SMTP', function () { }); }); - it('myEmail.send(callback)', function (done) { + it('myEmail.send(callback)', function(done) { var message = new MyEmail({ to: 'to@to.com', from: 'from@from.com', @@ -76,7 +74,7 @@ describe('Email and SMTP', function () { html: '

html

' }); - message.send(function (err, mail) { + message.send(function(err, mail) { assert(mail.response); assert(mail.envelope); assert(mail.messageId); @@ -85,5 +83,3 @@ describe('Email and SMTP', function () { }); }); }); - - diff --git a/test/geo-point.test.js b/test/geo-point.test.js index bc84f717..aea82b8e 100644 --- a/test/geo-point.test.js +++ b/test/geo-point.test.js @@ -1,6 +1,6 @@ describe('GeoPoint', function() { describe('geoPoint.distanceTo(geoPoint, options)', function() { - it("Get the distance to another `GeoPoint`", function() { + it('Get the distance to another `GeoPoint`', function() { var here = new GeoPoint({lat: 10, lng: 10}); var there = new GeoPoint({lat: 5, lng: 5}); var distance = here.distanceTo(there, {type: 'meters'}); @@ -10,16 +10,16 @@ describe('GeoPoint', function() { }); describe('GeoPoint.distanceBetween(a, b, options)', function() { - it("Get the distance between two points", function() { + it('Get the distance between two points', function() { var here = new GeoPoint({lat: 10, lng: 10}); var there = new GeoPoint({lat: 5, lng: 5}); var distance = GeoPoint.distanceBetween(here, there, {type: 'feet'}); - + assert.equal(Math.floor(distance), 2568169); }); }); - - describe('GeoPoint()', function(){ + + describe('GeoPoint()', function() { it('Create from string', function() { var point = new GeoPoint('1.234,5.678'); assert.equal(point.lng, 1.234); @@ -45,11 +45,11 @@ describe('GeoPoint', function() { var Model = loopback.createModel('geo-model', { geo: {type: 'GeoPoint'} }); - + var m = new Model({ geo: '1.222,3.444' }); - + assert(m.geo instanceof GeoPoint); assert.equal(m.geo.lng, 1.222); assert.equal(m.geo.lat, 3.444); diff --git a/test/hidden-properties.test.js b/test/hidden-properties.test.js index d30d32f7..c5e80e9a 100644 --- a/test/hidden-properties.test.js +++ b/test/hidden-properties.test.js @@ -1,22 +1,22 @@ var loopback = require('../'); -describe('hidden properties', function () { - beforeEach(function (done) { +describe('hidden properties', function() { + beforeEach(function(done) { var app = this.app = loopback(); var Product = this.Product = loopback.PersistedModel.extend('product', {}, {hidden: ['secret']} ); Product.attachTo(loopback.memory()); - + var Category = this.Category = loopback.PersistedModel.extend('category'); Category.attachTo(loopback.memory()); Category.hasMany(Product); - + app.model(Product); app.model(Category); app.use(loopback.rest()); - + Category.create({ name: 'my category' }, function(err, category) { @@ -32,29 +32,29 @@ describe('hidden properties', function () { this.Category.destroyAll(function() { Product.destroyAll(done); }); - }) - - it('should hide a property remotely', function (done) { - request(this.app) - .get('/products') - .expect('Content-Type', /json/) - .expect(200) - .end(function(err, res){ - if(err) return done(err); - var product = res.body[0]; - assert.equal(product.secret, undefined); - done(); - }); }); - it('should hide a property of nested models', function (done) { + it('should hide a property remotely', function(done) { + request(this.app) + .get('/products') + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) return done(err); + var product = res.body[0]; + assert.equal(product.secret, undefined); + done(); + }); + }); + + it('should hide a property of nested models', function(done) { var app = this.app; request(app) .get('/categories?filter[include]=products') .expect('Content-Type', /json/) .expect(200) - .end(function(err, res){ - if(err) return done(err); + .end(function(err, res) { + if (err) return done(err); var category = res.body[0]; var product = category.products[0]; assert.equal(product.secret, undefined); diff --git a/test/loopback.test.js b/test/loopback.test.js index 1bd996ed..8f217f6a 100644 --- a/test/loopback.test.js +++ b/test/loopback.test.js @@ -36,7 +36,7 @@ describe('loopback', function() { }); describe('data source created by loopback', function() { - it('should create model extending Model by default', function () { + it('should create model extending Model by default', function() { var dataSource = loopback.createDataSource({ connector: loopback.Memory }); @@ -52,8 +52,8 @@ describe('loopback', function() { }); }); - describe('loopback.autoAttach', function () { - it('doesn\'t overwrite model with datasource configured', function () { + describe('loopback.autoAttach', function() { + it('doesn\'t overwrite model with datasource configured', function() { var ds1 = loopback.createDataSource('db1', { connector: loopback.Memory }); @@ -79,12 +79,12 @@ describe('loopback', function() { }); describe('loopback.remoteMethod(Model, fn, [options]);', function() { - it("Setup a remote method.", function() { + it('Setup a remote method.', function() { var Product = loopback.createModel('product', {price: Number}); Product.stats = function(fn) { // ... - } + }; loopback.remoteMethod( Product.stats, @@ -102,9 +102,9 @@ describe('loopback', function() { }); }); - describe('loopback.createModel(name, properties, options)', function () { - describe('options.base', function () { - it('should extend from options.base', function () { + describe('loopback.createModel(name, properties, options)', function() { + describe('options.base', function() { + it('should extend from options.base', function() { var MyModel = loopback.createModel('MyModel', {}, { foo: { bar: 'bat' @@ -122,8 +122,8 @@ describe('loopback', function() { }); }); - describe('loopback.getModel and getModelByType', function () { - it('should be able to get model by name', function () { + describe('loopback.getModel and getModelByType', function() { + it('should be able to get model by name', function() { var MyModel = loopback.createModel('MyModel', {}, { foo: { bar: 'bat' @@ -139,7 +139,7 @@ describe('loopback', function() { assert(loopback.getModel('MyCustomModel') === MyCustomModel); assert(loopback.findModel('Invalid') === undefined); }); - it('should be able to get model by type', function () { + it('should be able to get model by type', function() { var MyModel = loopback.createModel('MyModel', {}, { foo: { bar: 'bat' diff --git a/test/memory.test.js b/test/memory.test.js index 88a3d176..7d9feb70 100644 --- a/test/memory.test.js +++ b/test/memory.test.js @@ -1,4 +1,4 @@ -describe('Memory Connector', function(){ +describe('Memory Connector', function() { it('Create a model using the memory connector', function(done) { // use the built in memory function // to create a memory data source @@ -6,30 +6,30 @@ describe('Memory Connector', function(){ // or create it using the standard // data source creation api - var memory = loopback.createDataSource({ + memory = loopback.createDataSource({ connector: loopback.Memory }); - + // create a model using the // memory data source var properties = { name: String, price: Number }; - + var Product = memory.createModel('product', properties); - + Product.create([ {name: 'apple', price: 0.79}, {name: 'pear', price: 1.29}, {name: 'orange', price: 0.59}, ], count); - + function count() { - Product.count(function (err, count) { + Product.count(function(err, count) { assert.equal(count, 3); done(); }); } }); -}); \ No newline at end of file +}); diff --git a/test/model.application.test.js b/test/model.application.test.js index 5d8a92a5..49ea38e4 100644 --- a/test/model.application.test.js +++ b/test/model.application.test.js @@ -2,13 +2,13 @@ var loopback = require(('../')); var assert = require('assert'); var Application = loopback.Application; -describe('Application', function () { +describe('Application', function() { var registeredApp = null; - it('Create a new application', function (done) { + it('Create a new application', function(done) { Application.create({owner: 'rfeng', name: 'MyApp1', - description: 'My first mobile application'}, function (err, result) { + description: 'My first mobile application'}, function(err, result) { var app = result; assert.equal(app.owner, 'rfeng'); assert.equal(app.name, 'MyApp1'); @@ -25,7 +25,7 @@ describe('Application', function () { }); }); - it('Create a new application with push settings', function (done) { + it('Create a new application with push settings', function(done) { Application.create({owner: 'rfeng', name: 'MyAppWithPush', description: 'My push mobile application', @@ -49,7 +49,7 @@ describe('Application', function () { serverApiKey: 'serverKey' } }}, - function (err, result) { + function(err, result) { var app = result; assert.deepEqual(app.pushSettings.toObject(), { apns: { @@ -75,9 +75,9 @@ describe('Application', function () { }); }); - beforeEach(function (done) { + beforeEach(function(done) { Application.register('rfeng', 'MyApp2', - {description: 'My second mobile application'}, function (err, result) { + {description: 'My second mobile application'}, function(err, result) { var app = result; assert.equal(app.owner, 'rfeng'); assert.equal(app.name, 'MyApp2'); @@ -94,8 +94,8 @@ describe('Application', function () { }); }); - it('Reset keys', function (done) { - Application.resetKeys(registeredApp.id, function (err, result) { + it('Reset keys', function(done) { + Application.resetKeys(registeredApp.id, function(err, result) { var app = result; assert.equal(app.owner, 'rfeng'); assert.equal(app.name, 'MyApp2'); @@ -119,67 +119,67 @@ describe('Application', function () { }); }); - it('Authenticate with application id & clientKey', function (done) { + it('Authenticate with application id & clientKey', function(done) { Application.authenticate(registeredApp.id, registeredApp.clientKey, - function (err, result) { + function(err, result) { assert.equal(result.application.id, registeredApp.id); assert.equal(result.keyType, 'clientKey'); done(err, result); }); }); - it('Authenticate with application id & javaScriptKey', function (done) { + it('Authenticate with application id & javaScriptKey', function(done) { Application.authenticate(registeredApp.id, registeredApp.javaScriptKey, - function (err, result) { + function(err, result) { assert.equal(result.application.id, registeredApp.id); assert.equal(result.keyType, 'javaScriptKey'); done(err, result); }); }); - it('Authenticate with application id & restApiKey', function (done) { + it('Authenticate with application id & restApiKey', function(done) { Application.authenticate(registeredApp.id, registeredApp.restApiKey, - function (err, result) { + function(err, result) { assert.equal(result.application.id, registeredApp.id); assert.equal(result.keyType, 'restApiKey'); done(err, result); }); }); - it('Authenticate with application id & masterKey', function (done) { + it('Authenticate with application id & masterKey', function(done) { Application.authenticate(registeredApp.id, registeredApp.masterKey, - function (err, result) { + function(err, result) { assert.equal(result.application.id, registeredApp.id); assert.equal(result.keyType, 'masterKey'); done(err, result); }); }); - it('Authenticate with application id & windowsKey', function (done) { + it('Authenticate with application id & windowsKey', function(done) { Application.authenticate(registeredApp.id, registeredApp.windowsKey, - function (err, result) { + function(err, result) { assert.equal(result.application.id, registeredApp.id); assert.equal(result.keyType, 'windowsKey'); done(err, result); }); }); - it('Fail to authenticate with application id & invalid key', function (done) { + it('Fail to authenticate with application id & invalid key', function(done) { Application.authenticate(registeredApp.id, 'invalid-key', - function (err, result) { + function(err, result) { assert(!result); done(err, result); }); }); }); -describe('Application subclass', function () { - it('should use subclass model name', function (done) { +describe('Application subclass', function() { + it('should use subclass model name', function(done) { var MyApp = Application.extend('MyApp'); var ds = loopback.createDataSource({connector: loopback.Memory}); MyApp.attachTo(ds); MyApp.register('rfeng', 'MyApp123', - {description: 'My 123 mobile application'}, function (err, result) { + {description: 'My 123 mobile application'}, function(err, result) { var app = result; assert.equal(app.owner, 'rfeng'); assert.equal(app.name, 'MyApp123'); @@ -192,12 +192,12 @@ describe('Application subclass', function () { assert(app.created); assert(app.modified); // Remove all instances from Application model to avoid left-over data - Application.destroyAll(function () { - MyApp.findById(app.id, function (err, myApp) { + Application.destroyAll(function() { + MyApp.findById(app.id, function(err, myApp) { assert(!err); assert(myApp); - Application.findById(app.id, function (err, myApp) { + Application.findById(app.id, function(err, myApp) { assert(!err); assert(myApp === null); done(err, myApp); @@ -207,4 +207,3 @@ describe('Application subclass', function () { }); }); }); - diff --git a/test/model.test.js b/test/model.test.js index d0fceb5a..2f32032d 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -15,7 +15,7 @@ describe('Model / PersistedModel', function() { }); describe('Model.validatesUniquenessOf(property, options)', function() { - it("Ensure the value for `property` is unique", function(done) { + it('Ensure the value for `property` is unique', function(done) { var User = PersistedModel.extend('user', { 'first': String, 'last': String, @@ -31,17 +31,17 @@ describe('Model / PersistedModel', function() { }); User.attachTo(dataSource); - + User.validatesUniquenessOf('email', {message: 'email is not unique'}); - + var joe = new User({email: 'joe@joe.com'}); var joe2 = new User({email: 'joe@joe.com'}); - joe.save(function () { - joe2.save(function (err) { + joe.save(function() { + joe2.save(function(err) { assert(err, 'should get a validation error'); assert(joe2.errors.email, 'model should have email error'); - + done(); }); }); @@ -49,14 +49,14 @@ describe('Model / PersistedModel', function() { }); describe('Model.attachTo(dataSource)', function() { - it("Attach a model to a [DataSource](#data-source)", function() { + it('Attach a model to a [DataSource](#data-source)', function() { var MyModel = loopback.createModel('my-model', {name: String}); var dataSource = loopback.createDataSource({ connector: loopback.Memory }); - + MyModel.attachTo(dataSource); - + MyModel.find(function(err, results) { assert(results.length === 0, 'should have data access methods after attaching to a data source'); }); @@ -64,13 +64,13 @@ describe('Model / PersistedModel', function() { }); }); -describe.onServer('Remote Methods', function(){ +describe.onServer('Remote Methods', function() { var User; var dataSource; var app; - beforeEach(function () { + beforeEach(function() { User = PersistedModel.extend('user', { 'first': String, 'last': String, @@ -89,13 +89,13 @@ describe.onServer('Remote Methods', function(){ User.attachTo(dataSource); - User.login = function (username, password, fn) { - if(username === 'foo' && password === 'bar') { + User.login = function(username, password, fn) { + if (username === 'foo' && password === 'bar') { fn(null, 123); } else { throw new Error('bad username and password!'); } - } + }; loopback.remoteMethod( User.login, @@ -113,19 +113,19 @@ describe.onServer('Remote Methods', function(){ app.use(loopback.rest()); app.model(User); }); - + describe('Model.destroyAll(callback)', function() { - it("Delete all Model instances from data source", function(done) { + it('Delete all Model instances from data source', function(done) { (new TaskEmitter()) .task(User, 'create', {first: 'jill'}) .task(User, 'create', {first: 'bob'}) .task(User, 'create', {first: 'jan'}) .task(User, 'create', {first: 'sam'}) .task(User, 'create', {first: 'suzy'}) - .on('done', function () { - User.count(function (err, count) { - User.destroyAll(function () { - User.count(function (err, count) { + .on('done', function() { + User.count(function(err, count) { + User.destroyAll(function() { + User.count(function(err, count) { assert.equal(count, 0); done(); }); @@ -135,14 +135,14 @@ describe.onServer('Remote Methods', function(){ }); }); - describe('Example Remote Method', function () { + describe('Example Remote Method', function() { it('Call the method using HTTP / REST', function(done) { request(app) .get('/users/sign-in?username=foo&password=bar') .expect('Content-Type', /json/) .expect(200) - .end(function(err, res){ - if(err) return done(err); + .end(function(err, res) { + if (err) return done(err); assert.equal(res.body, 123); done(); }); @@ -156,15 +156,15 @@ describe.onServer('Remote Methods', function(){ }); }); - describe('Model.beforeRemote(name, fn)', function(){ + describe('Model.beforeRemote(name, fn)', function() { it('Run a function before a remote method is called by a client', function(done) { var hookCalled = false; - + User.beforeRemote('create', function(ctx, user, next) { hookCalled = true; next(); }); - + // invoke save request(app) .post('/users') @@ -172,18 +172,18 @@ describe.onServer('Remote Methods', function(){ .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { - if(err) return done(err); + if (err) return done(err); assert(hookCalled, 'hook wasnt called'); done(); }); }); }); - describe('Model.afterRemote(name, fn)', function(){ + describe('Model.afterRemote(name, fn)', function() { it('Run a function after a remote method is called by a client', function(done) { var beforeCalled = false; var afterCalled = false; - + User.beforeRemote('create', function(ctx, user, next) { assert(!afterCalled); beforeCalled = true; @@ -194,7 +194,7 @@ describe.onServer('Remote Methods', function(){ afterCalled = true; next(); }); - + // invoke save request(app) .post('/users') @@ -202,7 +202,7 @@ describe.onServer('Remote Methods', function(){ .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { - if(err) return done(err); + if (err) return done(err); assert(beforeCalled, 'before hook was not called'); assert(afterCalled, 'after hook was not called'); done(); @@ -210,11 +210,11 @@ describe.onServer('Remote Methods', function(){ }); }); - describe('Remote Method invoking context', function () { + describe('Remote Method invoking context', function() { describe('ctx.req', function() { - it("The express ServerRequest object", function(done) { + it('The express ServerRequest object', function(done) { var hookCalled = false; - + User.beforeRemote('create', function(ctx, user, next) { hookCalled = true; assert(ctx.req); @@ -225,7 +225,7 @@ describe.onServer('Remote Methods', function(){ assert(ctx.res.end); next(); }); - + // invoke save request(app) .post('/users') @@ -233,7 +233,7 @@ describe.onServer('Remote Methods', function(){ .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { - if(err) return done(err); + if (err) return done(err); assert(hookCalled); done(); }); @@ -241,9 +241,9 @@ describe.onServer('Remote Methods', function(){ }); describe('ctx.res', function() { - it("The express ServerResponse object", function(done) { + it('The express ServerResponse object', function(done) { var hookCalled = false; - + User.beforeRemote('create', function(ctx, user, next) { hookCalled = true; assert(ctx.req); @@ -254,7 +254,7 @@ describe.onServer('Remote Methods', function(){ assert(ctx.res.end); next(); }); - + // invoke save request(app) .post('/users') @@ -262,28 +262,28 @@ describe.onServer('Remote Methods', function(){ .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { - if(err) return done(err); + if (err) return done(err); assert(hookCalled); done(); }); }); }); - }) + }); describe('Model.hasMany(Model)', function() { - it("Define a one to many relationship", function(done) { + it('Define a one to many relationship', function(done) { var Book = dataSource.createModel('book', {title: String, author: String}); var Chapter = dataSource.createModel('chapter', {title: String}); - + // by referencing model Book.hasMany(Chapter); - + Book.create({title: 'Into the Wild', author: 'Jon Krakauer'}, function(err, book) { // using 'chapters' scope for build: var c = book.chapters.build({title: 'Chapter 1'}); - book.chapters.create({title: 'Chapter 2'}, function () { - c.save(function () { - Chapter.count({bookId: book.id}, function (err, count) { + book.chapters.create({title: 'Chapter 2'}, function() { + c.save(function() { + Chapter.count({bookId: book.id}, function(err, count) { assert.equal(count, 2); book.chapters({where: {title: 'Chapter 1'}}, function(err, chapters) { assert.equal(chapters.length, 1); @@ -296,8 +296,8 @@ describe.onServer('Remote Methods', function(){ }); }); }); - - describe('Model.properties', function(){ + + describe('Model.properties', function() { it('Normalized properties passed in originally by loopback.createModel()', function() { var props = { s: String, @@ -306,57 +306,56 @@ describe.onServer('Remote Methods', function(){ d: Date, g: loopback.GeoPoint }; - + var MyModel = loopback.createModel('foo', props); - - Object.keys(MyModel.definition.properties).forEach(function (key) { + + Object.keys(MyModel.definition.properties).forEach(function(key) { var p = MyModel.definition.properties[key]; var o = MyModel.definition.properties[key]; assert(p); assert(o); assert(typeof p.type === 'function'); - - if(typeof o === 'function') { + + if (typeof o === 'function') { // the normalized property // should match the given property assert( - p.type.name === o.name - || + p.type.name === o.name || p.type.name === o - ) + ); } }); }); }); - - describe('Model.extend()', function(){ + + describe('Model.extend()', function() { it('Create a new model by extending an existing model', function() { var User = loopback.PersistedModel.extend('test-user', { email: String }); - - User.foo = function () { + + User.foo = function() { return 'bar'; - } - - User.prototype.bar = function () { + }; + + User.prototype.bar = function() { return 'foo'; - } - + }; + var MyUser = User.extend('my-user', { a: String, b: String }); - + assert.equal(MyUser.prototype.bar, User.prototype.bar); assert.equal(MyUser.foo, User.foo); - + var user = new MyUser({ email: 'foo@bar.com', a: 'foo', b: 'bar' }); - + assert.equal(user.email, 'foo@bar.com'); assert.equal(user.a, 'foo'); assert.equal(user.b, 'bar'); @@ -379,7 +378,6 @@ describe.onServer('Remote Methods', function(){ user1Triggered = true; }); - var user2Triggered = false; User2.once('x', function(event) { user2Triggered = true; @@ -396,7 +394,7 @@ describe.onServer('Remote Methods', function(){ }); - describe('Model.checkAccessTypeForMethod(remoteMethod)', function () { + describe('Model.checkAccessTypeForMethod(remoteMethod)', function() { shouldReturn('create', ACL.WRITE); shouldReturn('updateOrCreate', ACL.WRITE); shouldReturn('upsert', ACL.WRITE); @@ -411,7 +409,7 @@ describe.onServer('Remote Methods', function(){ shouldReturn('unkown-model-method', ACL.EXECUTE); function shouldReturn(methodName, expectedAccessType) { - describe(methodName, function () { + describe(methodName, function() { it('should return ' + expectedAccessType, function() { var remoteMethod = {name: methodName}; assert.equal( @@ -424,7 +422,7 @@ describe.onServer('Remote Methods', function(){ }); describe('Model.getChangeModel()', function() { - it('Get the Change Model', function () { + it('Get the Change Model', function() { var UserChange = User.getChangeModel(); var change = new UserChange(); assert(change instanceof Change); @@ -432,7 +430,7 @@ describe.onServer('Remote Methods', function(){ }); describe('Model.getSourceId(callback)', function() { - it('Get the Source Id', function (done) { + it('Get the Source Id', function(done) { User.getSourceId(function(err, id) { assert.equal('memory-user', id); done(); @@ -441,7 +439,7 @@ describe.onServer('Remote Methods', function(){ }); describe('Model.checkpoint(callback)', function() { - it('Create a checkpoint', function (done) { + it('Create a checkpoint', function(done) { var Checkpoint = User.getChangeModel().getCheckpointModel(); var tasks = [ getCurrentCheckpoint, @@ -451,7 +449,7 @@ describe.onServer('Remote Methods', function(){ var current; async.series(tasks, function(err) { - if(err) return done(err); + if (err) return done(err); assert.equal(result, current + 1); done(); diff --git a/test/relations.integration.js b/test/relations.integration.js index 04460223..4ba459f2 100644 --- a/test/relations.integration.js +++ b/test/relations.integration.js @@ -1,3 +1,5 @@ +/*jshint -W030 */ + var loopback = require('../'); var lt = require('loopback-testing'); var path = require('path'); @@ -8,7 +10,7 @@ var expect = require('chai').expect; var debug = require('debug')('loopback:test:relations.integration'); var async = require('async'); -describe('relations - integration', function () { +describe('relations - integration', function() { lt.beforeEach.withApp(app); @@ -35,7 +37,7 @@ describe('relations - integration', function () { }); }); - describe('/store/:id/widgets', function () { + describe('/store/:id/widgets', function() { beforeEach(function() { this.url = '/api/stores/' + this.store.id + '/widgets'; }); @@ -53,7 +55,7 @@ describe('relations - integration', function () { this.res.text); this.widgets = this.res.body; this.widget = this.res.body && this.res.body[0]; - }); + }); it('should be an array', function() { assert(Array.isArray(this.widgets)); }); @@ -79,7 +81,7 @@ describe('relations - integration', function () { this.http = this.post(this.url, this.newWidget); this.http.send(this.newWidget); this.http.end(function(err) { - if(err) return done(err); + if (err) return done(err); this.req = this.http.req; this.res = this.http.res; done(); @@ -91,7 +93,7 @@ describe('relations - integration', function () { describe('widget (response.body)', function() { beforeEach(function() { this.widget = this.res.body; - }); + }); it('should be an object', function() { assert(typeof this.widget === 'object'); assert(!Array.isArray(this.widget)); @@ -102,20 +104,20 @@ describe('relations - integration', function () { assert.equal(this.widget.name, this.newWidgetName); }); }); - it('should have a single widget with storeId', function (done) { + it('should have a single widget with storeId', function(done) { this.app.models.widget.count({ storeId: this.store.id }, function(err, count) { - if(err) return done(err); + if (err) return done(err); assert.equal(count, 2); done(); }); }); }); }); - - describe('/stores/:id/widgets/:fk - 200', function () { - beforeEach(function (done) { + + describe('/stores/:id/widgets/:fk - 200', function() { + beforeEach(function(done) { var self = this; this.store.widgets.create({ name: this.widgetName @@ -125,27 +127,27 @@ describe('relations - integration', function () { done(); }); }); - lt.describe.whenCalledRemotely('GET', '/stores/:id/widgets/:fk', function () { - it('should succeed with statusCode 200', function () { + lt.describe.whenCalledRemotely('GET', '/stores/:id/widgets/:fk', function() { + it('should succeed with statusCode 200', function() { assert.equal(this.res.statusCode, 200); assert.equal(this.res.body.id, this.widget.id); }); }); }); - describe('/stores/:id/widgets/:fk - 404', function () { - beforeEach(function () { + describe('/stores/:id/widgets/:fk - 404', function() { + beforeEach(function() { this.url = '/api/stores/' + this.store.id + '/widgets/123456'; }); - lt.describe.whenCalledRemotely('GET', '/stores/:id/widgets/:fk', function () { - it('should fail with statusCode 404', function () { + lt.describe.whenCalledRemotely('GET', '/stores/:id/widgets/:fk', function() { + it('should fail with statusCode 404', function() { assert.equal(this.res.statusCode, 404); assert.equal(this.res.body.error.status, 404); }); }); }); - - describe('/store/:id/widgets/count', function () { + + describe('/store/:id/widgets/count', function() { beforeEach(function() { this.url = '/api/stores/' + this.store.id + '/widgets/count'; }); @@ -158,8 +160,8 @@ describe('relations - integration', function () { }); }); }); - - describe('/store/:id/widgets/count - filtered (matches)', function () { + + describe('/store/:id/widgets/count - filtered (matches)', function() { beforeEach(function() { this.url = '/api/stores/' + this.store.id + '/widgets/count?where[name]=foo'; }); @@ -172,8 +174,8 @@ describe('relations - integration', function () { }); }); }); - - describe('/store/:id/widgets/count - filtered (no matches)', function () { + + describe('/store/:id/widgets/count - filtered (no matches)', function() { beforeEach(function() { this.url = '/api/stores/' + this.store.id + '/widgets/count?where[name]=bar'; }); @@ -187,8 +189,8 @@ describe('relations - integration', function () { }); }); - describe('/widgets/:id/store', function () { - beforeEach(function (done) { + describe('/widgets/:id/store', function() { + beforeEach(function(done) { var self = this; this.store.widgets.create({ name: this.widgetName @@ -198,8 +200,8 @@ describe('relations - integration', function () { done(); }); }); - lt.describe.whenCalledRemotely('GET', '/api/widgets/:id/store', function () { - it('should succeed with statusCode 200', function () { + lt.describe.whenCalledRemotely('GET', '/api/widgets/:id/store', function() { + it('should succeed with statusCode 200', function() { assert.equal(this.res.statusCode, 200); assert.equal(this.res.body.id, this.store.id); }); @@ -213,10 +215,10 @@ describe('relations - integration', function () { async.series([ // Clean up models - function (done) { - app.models.physician.destroyAll(function (err) { - app.models.patient.destroyAll(function (err) { - app.models.appointment.destroyAll(function (err) { + function(done) { + app.models.physician.destroyAll(function(err) { + app.models.patient.destroyAll(function(err) { + app.models.appointment.destroyAll(function(err) { done(); }); }); @@ -224,44 +226,44 @@ describe('relations - integration', function () { }, // Create a physician - function (done) { + function(done) { app.models.physician.create({ name: 'ph1' - }, function (err, physician) { + }, function(err, physician) { root.physician = physician; done(); }); }, // Create a patient - connecting ? function (done) { + connecting ? function(done) { root.physician.patients.create({ name: 'pa1' - }, function (err, patient) { + }, function(err, patient) { root.patient = patient; root.relUrl = '/api/physicians/' + root.physician.id + '/patients/rel/' + root.patient.id; done(); }); - } : function (done) { + } : function(done) { app.models.patient.create({ name: 'pa1' - }, function (err, patient) { + }, function(err, patient) { root.patient = patient; root.relUrl = '/api/physicians/' + root.physician.id + '/patients/rel/' + root.patient.id; done(); }); - }], function (err, done) { + }], function(err, done) { cb(err, root); }); } - describe('PUT /physicians/:id/patients/rel/:fk', function () { + describe('PUT /physicians/:id/patients/rel/:fk', function() { - before(function (done) { + before(function(done) { var self = this; - setup(false, function (err, root) { + setup(false, function(err, root) { self.url = root.relUrl; self.patient = root.patient; self.physician = root.physician; @@ -269,25 +271,25 @@ describe('relations - integration', function () { }); }); - lt.describe.whenCalledRemotely('PUT', '/api/physicians/:id/patients/rel/:fk', function () { - it('should succeed with statusCode 200', function () { + lt.describe.whenCalledRemotely('PUT', '/api/physicians/:id/patients/rel/:fk', function() { + it('should succeed with statusCode 200', function() { assert.equal(this.res.statusCode, 200); assert.equal(this.res.body.patientId, this.patient.id); assert.equal(this.res.body.physicianId, this.physician.id); }); - it('should create a record in appointment', function (done) { + it('should create a record in appointment', function(done) { var self = this; - app.models.appointment.find(function (err, apps) { + app.models.appointment.find(function(err, apps) { assert.equal(apps.length, 1); assert.equal(apps[0].patientId, self.patient.id); done(); }); }); - it('should connect physician to patient', function (done) { + it('should connect physician to patient', function(done) { var self = this; - self.physician.patients(function (err, patients) { + self.physician.patients(function(err, patients) { assert.equal(patients.length, 1); assert.equal(patients[0].id, self.patient.id); done(); @@ -296,11 +298,11 @@ describe('relations - integration', function () { }); }); - describe('PUT /physicians/:id/patients/rel/:fk with data', function () { + describe('PUT /physicians/:id/patients/rel/:fk with data', function() { - before(function (done) { + before(function(done) { var self = this; - setup(false, function (err, root) { + setup(false, function(err, root) { self.url = root.relUrl; self.patient = root.patient; self.physician = root.physician; @@ -311,17 +313,17 @@ describe('relations - integration', function () { var NOW = Date.now(); var data = { date: new Date(NOW) }; - lt.describe.whenCalledRemotely('PUT', '/api/physicians/:id/patients/rel/:fk', data, function () { - it('should succeed with statusCode 200', function () { + lt.describe.whenCalledRemotely('PUT', '/api/physicians/:id/patients/rel/:fk', data, function() { + it('should succeed with statusCode 200', function() { assert.equal(this.res.statusCode, 200); assert.equal(this.res.body.patientId, this.patient.id); assert.equal(this.res.body.physicianId, this.physician.id); assert.equal(new Date(this.res.body.date).getTime(), NOW); }); - it('should create a record in appointment', function (done) { + it('should create a record in appointment', function(done) { var self = this; - app.models.appointment.find(function (err, apps) { + app.models.appointment.find(function(err, apps) { assert.equal(apps.length, 1); assert.equal(apps[0].patientId, self.patient.id); assert.equal(apps[0].physicianId, self.physician.id); @@ -330,9 +332,9 @@ describe('relations - integration', function () { }); }); - it('should connect physician to patient', function (done) { + it('should connect physician to patient', function(done) { var self = this; - self.physician.patients(function (err, patients) { + self.physician.patients(function(err, patients) { assert.equal(patients.length, 1); assert.equal(patients[0].id, self.patient.id); done(); @@ -341,11 +343,11 @@ describe('relations - integration', function () { }); }); - describe('HEAD /physicians/:id/patients/rel/:fk', function () { + describe('HEAD /physicians/:id/patients/rel/:fk', function() { - before(function (done) { + before(function(done) { var self = this; - setup(true, function (err, root) { + setup(true, function(err, root) { self.url = root.relUrl; self.patient = root.patient; self.physician = root.physician; @@ -353,18 +355,18 @@ describe('relations - integration', function () { }); }); - lt.describe.whenCalledRemotely('HEAD', '/api/physicians/:id/patients/rel/:fk', function () { - it('should succeed with statusCode 200', function () { + lt.describe.whenCalledRemotely('HEAD', '/api/physicians/:id/patients/rel/:fk', function() { + it('should succeed with statusCode 200', function() { assert.equal(this.res.statusCode, 200); }); }); }); - describe('HEAD /physicians/:id/patients/rel/:fk that does not exist', function () { + describe('HEAD /physicians/:id/patients/rel/:fk that does not exist', function() { - before(function (done) { + before(function(done) { var self = this; - setup(true, function (err, root) { + setup(true, function(err, root) { self.url = '/api/physicians/' + root.physician.id + '/patients/rel/' + '999'; self.patient = root.patient; @@ -373,18 +375,18 @@ describe('relations - integration', function () { }); }); - lt.describe.whenCalledRemotely('HEAD', '/api/physicians/:id/patients/rel/:fk', function () { - it('should succeed with statusCode 404', function () { + lt.describe.whenCalledRemotely('HEAD', '/api/physicians/:id/patients/rel/:fk', function() { + it('should succeed with statusCode 404', function() { assert.equal(this.res.statusCode, 404); }); }); }); - describe('DELETE /physicians/:id/patients/rel/:fk', function () { + describe('DELETE /physicians/:id/patients/rel/:fk', function() { - before(function (done) { + before(function(done) { var self = this; - setup(true, function (err, root) { + setup(true, function(err, root) { self.url = root.relUrl; self.patient = root.patient; self.physician = root.physician; @@ -392,41 +394,41 @@ describe('relations - integration', function () { }); }); - it('should create a record in appointment', function (done) { + it('should create a record in appointment', function(done) { var self = this; - app.models.appointment.find(function (err, apps) { + app.models.appointment.find(function(err, apps) { assert.equal(apps.length, 1); assert.equal(apps[0].patientId, self.patient.id); done(); }); }); - it('should connect physician to patient', function (done) { + it('should connect physician to patient', function(done) { var self = this; - self.physician.patients(function (err, patients) { + self.physician.patients(function(err, patients) { assert.equal(patients.length, 1); assert.equal(patients[0].id, self.patient.id); done(); }); }); - lt.describe.whenCalledRemotely('DELETE', '/api/physicians/:id/patients/rel/:fk', function () { - it('should succeed with statusCode 204', function () { + lt.describe.whenCalledRemotely('DELETE', '/api/physicians/:id/patients/rel/:fk', function() { + it('should succeed with statusCode 204', function() { assert.equal(this.res.statusCode, 204); }); - it('should remove the record in appointment', function (done) { + it('should remove the record in appointment', function(done) { var self = this; - app.models.appointment.find(function (err, apps) { + app.models.appointment.find(function(err, apps) { assert.equal(apps.length, 0); done(); }); }); - it('should remove the connection between physician and patient', function (done) { + it('should remove the connection between physician and patient', function(done) { var self = this; // Need to refresh the cache - self.physician.patients(true, function (err, patients) { + self.physician.patients(true, function(err, patients) { assert.equal(patients.length, 0); done(); }); @@ -434,11 +436,11 @@ describe('relations - integration', function () { }); }); - describe('GET /physicians/:id/patients/:fk', function () { + describe('GET /physicians/:id/patients/:fk', function() { - before(function (done) { + before(function(done) { var self = this; - setup(true, function (err, root) { + setup(true, function(err, root) { self.url = '/api/physicians/' + root.physician.id + '/patients/' + root.patient.id; self.patient = root.patient; @@ -447,19 +449,19 @@ describe('relations - integration', function () { }); }); - lt.describe.whenCalledRemotely('GET', '/api/physicians/:id/patients/:fk', function () { - it('should succeed with statusCode 200', function () { + lt.describe.whenCalledRemotely('GET', '/api/physicians/:id/patients/:fk', function() { + it('should succeed with statusCode 200', function() { assert.equal(this.res.statusCode, 200); assert.equal(this.res.body.id, this.physician.id); }); }); }); - describe('DELETE /physicians/:id/patients/:fk', function () { + describe('DELETE /physicians/:id/patients/:fk', function() { - before(function (done) { + before(function(done) { var self = this; - setup(true, function (err, root) { + setup(true, function(err, root) { self.url = '/api/physicians/' + root.physician.id + '/patients/' + root.patient.id; self.patient = root.patient; @@ -468,31 +470,31 @@ describe('relations - integration', function () { }); }); - lt.describe.whenCalledRemotely('DELETE', '/api/physicians/:id/patients/:fk', function () { - it('should succeed with statusCode 204', function () { + lt.describe.whenCalledRemotely('DELETE', '/api/physicians/:id/patients/:fk', function() { + it('should succeed with statusCode 204', function() { assert.equal(this.res.statusCode, 204); }); - it('should remove the record in appointment', function (done) { + it('should remove the record in appointment', function(done) { var self = this; - app.models.appointment.find(function (err, apps) { + app.models.appointment.find(function(err, apps) { assert.equal(apps.length, 0); done(); }); }); - it('should remove the connection between physician and patient', function (done) { + it('should remove the connection between physician and patient', function(done) { var self = this; // Need to refresh the cache - self.physician.patients(true, function (err, patients) { + self.physician.patients(true, function(err, patients) { assert.equal(patients.length, 0); done(); }); }); - it('should remove the record in patient', function (done) { + it('should remove the record in patient', function(done) { var self = this; - app.models.patient.find(function (err, patients) { + app.models.patient.find(function(err, patients) { assert.equal(patients.length, 0); done(); }); @@ -612,13 +614,13 @@ describe('relations - integration', function () { }); describe('embedsOne', function() { - + before(function defineGroupAndPosterModels() { var group = app.model( 'group', - { properties: { name: 'string' }, + { properties: { name: 'string' }, dataSource: 'db', - plural: 'groups' + plural: 'groups' } ); var poster = app.model( @@ -627,7 +629,7 @@ describe('relations - integration', function () { ); group.embedsOne(poster, { as: 'cover' }); }); - + before(function createImage(done) { var test = this; app.models.group.create({ name: 'Group 1' }, @@ -638,46 +640,46 @@ describe('relations - integration', function () { group.save(done); }); }); - + after(function(done) { this.app.models.group.destroyAll(done); }); - + it('includes the embedded models', function(done) { var url = '/api/groups/' + this.group.id; - + this.get(url) .expect(200, function(err, res) { expect(res.body.name).to.be.equal('Group 1'); - expect(res.body.poster).to.be.eql( + expect(res.body.poster).to.be.eql( { url: 'http://image.url' } ); done(); }); }); - + it('returns the embedded model', function(done) { var url = '/api/groups/' + this.group.id + '/cover'; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql( + expect(res.body).to.be.eql( { url: 'http://image.url' } ); done(); }); }); - + }); - + describe('embedsMany', function() { - + before(function defineProductAndCategoryModels() { var todoList = app.model( 'todoList', - { properties: { name: 'string' }, + { properties: { name: 'string' }, dataSource: 'db', - plural: 'todo-lists' + plural: 'todo-lists' } ); var todoItem = app.model( @@ -702,52 +704,52 @@ describe('relations - integration', function () { after(function(done) { this.app.models.todoList.destroyAll(done); }); - + it('includes the embedded models', function(done) { var url = '/api/todo-lists/' + this.todoList.id; this.get(url) .expect(200, function(err, res) { expect(res.body.name).to.be.equal('List A'); - expect(res.body.todoItems).to.be.eql([ + expect(res.body.todoItems).to.be.eql([ { content: 'Todo 1', id: 1 }, { content: 'Todo 2', id: 2 } ]); done(); }); }); - + it('returns the embedded models', function(done) { var url = '/api/todo-lists/' + this.todoList.id + '/items'; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { content: 'Todo 1', id: 1 }, { content: 'Todo 2', id: 2 } ]); done(); }); }); - + it('filters the embedded models', function(done) { var url = '/api/todo-lists/' + this.todoList.id + '/items'; url += '?filter[where][id]=2'; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { content: 'Todo 2', id: 2 } ]); done(); }); }); - + it('creates embedded models', function(done) { var url = '/api/todo-lists/' + this.todoList.id + '/items'; - + var expected = { content: 'Todo 3', id: 3 }; - + this.post(url) .send({ content: 'Todo 3' }) .expect(200, function(err, res) { @@ -755,13 +757,13 @@ describe('relations - integration', function () { done(); }); }); - + it('returns the embedded models', function(done) { var url = '/api/todo-lists/' + this.todoList.id + '/items'; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { content: 'Todo 1', id: 1 }, { content: 'Todo 2', id: 2 }, { content: 'Todo 3', id: 3 } @@ -769,10 +771,10 @@ describe('relations - integration', function () { done(); }); }); - + it('returns an embedded model by (internal) id', function(done) { var url = '/api/todo-lists/' + this.todoList.id + '/items/3'; - + this.get(url) .expect(200, function(err, res) { expect(res.body).to.be.eql( @@ -781,30 +783,30 @@ describe('relations - integration', function () { done(); }); }); - + it('removes an embedded model', function(done) { var expectedProduct = this.product; var url = '/api/todo-lists/' + this.todoList.id + '/items/2'; - + this.del(url) .expect(200, function(err, res) { done(); }); }); - + it('returns the embedded models - verify', function(done) { var url = '/api/todo-lists/' + this.todoList.id + '/items'; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { content: 'Todo 1', id: 1 }, { content: 'Todo 3', id: 3 } ]); done(); }); }); - + it('returns a 404 response when embedded model is not found', function(done) { var url = '/api/todo-lists/' + this.todoList.id + '/items/2'; this.get(url).expect(404, function(err, res) { @@ -813,29 +815,29 @@ describe('relations - integration', function () { done(); }); }); - + it.skip('checks if an embedded model exists - ok', function(done) { var url = '/api/todo-lists/' + this.todoList.id + '/items/3'; - + this.head(url) .expect(200, function(err, res) { done(); }); }); - + it.skip('checks if an embedded model exists - fail', function(done) { var url = '/api/todo-lists/' + this.todoList.id + '/items/2'; - + this.head(url) .expect(404, function(err, res) { done(); }); }); - + }); - + describe('referencesMany', function() { - + before(function defineProductAndCategoryModels() { var recipe = app.model( 'recipe', @@ -851,8 +853,8 @@ describe('relations - integration', function () { ); recipe.referencesMany(ingredient); // contrived example for test: - recipe.hasOne(photo, { as: 'picture', options: { - http: { path: 'image' } + recipe.hasOne(photo, { as: 'picture', options: { + http: { path: 'image' } } }); }); @@ -862,15 +864,15 @@ describe('relations - integration', function () { function(err, recipe) { if (err) return done(err); test.recipe = recipe; - recipe.ingredients.create({ - name: 'Chocolate' }, + recipe.ingredients.create({ + name: 'Chocolate' }, function(err, ing) { test.ingredient1 = ing.id; recipe.picture.create({ name: 'Photo 1' }, done); }); }); }); - + before(function createIngredient(done) { var test = this; app.models.ingredient.create({ name: 'Sugar' }, function(err, ing) { @@ -887,11 +889,11 @@ describe('relations - integration', function () { }); }); }); - + it('keeps an array of ids', function(done) { var url = '/api/recipes/' + this.recipe.id; var test = this; - + this.get(url) .expect(200, function(err, res) { expect(res.body.ingredientIds).to.eql([test.ingredient1]); @@ -899,11 +901,11 @@ describe('relations - integration', function () { done(); }); }); - + it('creates referenced models', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients'; var test = this; - + this.post(url) .send({ name: 'Butter' }) .expect(200, function(err, res) { @@ -912,14 +914,14 @@ describe('relations - integration', function () { done(); }); }); - + it('has created models', function(done) { var url = '/api/ingredients'; var test = this; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, { name: 'Sugar', id: test.ingredient2 }, { name: 'Butter', id: test.ingredient3 } @@ -927,40 +929,40 @@ describe('relations - integration', function () { done(); }); }); - + it('returns the referenced models', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients'; var test = this; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, { name: 'Butter', id: test.ingredient3 } ]); done(); }); }); - + it('filters the referenced models', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients'; url += '?filter[where][name]=Butter'; var test = this; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { name: 'Butter', id: test.ingredient3 } ]); done(); }); }); - + it('includes the referenced models', function(done) { var url = '/api/recipes/findOne?filter[where][id]=' + this.recipe.id; url += '&filter[include]=ingredients'; var test = this; - + this.get(url) .expect(200, function(err, res) { expect(res.body.ingredientIds).to.eql([ @@ -978,7 +980,7 @@ describe('relations - integration', function () { var url = '/api/recipes/' + this.recipe.id + '/ingredients/'; url += this.ingredient3; var test = this; - + this.get(url) .expect(200, function(err, res) { expect(res.body).to.be.eql( @@ -987,13 +989,13 @@ describe('relations - integration', function () { done(); }); }); - + it('keeps an array of ids - verify', function(done) { var url = '/api/recipes/' + this.recipe.id; var test = this; - + var expected = [test.ingredient1, test.ingredient3]; - + this.get(url) .expect(200, function(err, res) { expect(res.body.ingredientIds).to.eql(expected); @@ -1001,50 +1003,50 @@ describe('relations - integration', function () { done(); }); }); - + it('destroys a referenced model', function(done) { var expectedProduct = this.product; var url = '/api/recipes/' + this.recipe.id + '/ingredients/'; url += this.ingredient3; - + this.del(url) .expect(200, function(err, res) { done(); }); }); - + it('has destroyed a referenced model', function(done) { var url = '/api/ingredients'; var test = this; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, { name: 'Sugar', id: test.ingredient2 } ]); done(); }); }); - + it('returns the referenced models - verify', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients'; var test = this; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 } ]); done(); }); }); - + it('creates/links a reference by id', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients'; url += '/rel/' + this.ingredient2; var test = this; - + this.put(url) .expect(200, function(err, res) { expect(res.body).to.be.eql( @@ -1053,62 +1055,62 @@ describe('relations - integration', function () { done(); }); }); - + it('returns the referenced models - verify', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients'; var test = this; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, { name: 'Sugar', id: test.ingredient2 } ]); done(); }); }); - + it('removes/unlinks a reference by id', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients'; url += '/rel/' + this.ingredient1; var test = this; - + this.del(url) .expect(200, function(err, res) { done(); }); }); - + it('returns the referenced models - verify', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients'; var test = this; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { name: 'Sugar', id: test.ingredient2 } ]); done(); }); }); - + it('has not destroyed an unlinked model', function(done) { var url = '/api/ingredients'; var test = this; - + this.get(url) .expect(200, function(err, res) { - expect(res.body).to.be.eql([ + expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, { name: 'Sugar', id: test.ingredient2 } ]); done(); }); }); - + it('uses a custom relation path', function(done) { var url = '/api/recipes/' + this.recipe.id + '/image'; - + this.get(url) .expect(200, function(err, res) { expect(err).to.not.exist; @@ -1116,31 +1118,31 @@ describe('relations - integration', function () { done(); }); }); - + it.skip('checks if a referenced model exists - ok', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients/'; url += this.ingredient1; - + this.head(url) .expect(200, function(err, res) { done(); }); }); - + it.skip('checks if an referenced model exists - fail', function(done) { var url = '/api/recipes/' + this.recipe.id + '/ingredients/'; url += this.ingredient3; - + this.head(url) .expect(404, function(err, res) { done(); }); }); - + }); - + describe('nested relations', function() { - + before(function defineModels() { var Book = app.model( 'Book', @@ -1165,54 +1167,54 @@ describe('relations - integration', function () { Book.hasMany(Page); Page.hasMany(Note); Image.belongsTo(Book); - + Book.nestRemoting('pages'); Image.nestRemoting('book'); - + expect(Book.prototype['__findById__pages__notes']).to.be.a.function; expect(Image.prototype['__findById__book__pages']).to.be.a.function; - + Page.beforeRemote('prototype.__findById__notes', function(ctx, result, next) { ctx.res.set('x-before', 'before'); next(); }); - + Page.afterRemote('prototype.__findById__notes', function(ctx, result, next) { ctx.res.set('x-after', 'after'); next(); }); - + }); - + before(function createBook(done) { var test = this; - app.models.Book.create({ name: 'Book 1' }, + app.models.Book.create({ name: 'Book 1' }, function(err, book) { if (err) return done(err); test.book = book; - book.pages.create({ name: 'Page 1' }, - function(err, page) { - if (err) return done(err); - test.page = page; - page.notes.create({ text: 'Page Note 1' }, - function(err, note) { - test.note = note; - done(); - }); + book.pages.create({ name: 'Page 1' }, + function(err, page) { + if (err) return done(err); + test.page = page; + page.notes.create({ text: 'Page Note 1' }, + function(err, note) { + test.note = note; + done(); + }); }); }); }); - + before(function createCover(done) { var test = this; - app.models.Image.create({ name: 'Cover 1', book: test.book }, + app.models.Image.create({ name: 'Cover 1', book: test.book }, function(err, image) { if (err) return done(err); test.image = image; done(); }); }); - + it('has regular relationship routes - pages', function(done) { var test = this; this.get('/api/books/' + test.book.id + '/pages') @@ -1221,9 +1223,9 @@ describe('relations - integration', function () { expect(res.body).to.have.length(1); expect(res.body[0].name).to.equal('Page 1'); done(); - }); + }); }); - + it('has regular relationship routes - notes', function(done) { var test = this; this.get('/api/pages/' + test.page.id + '/notes/' + test.note.id) @@ -1233,9 +1235,9 @@ describe('relations - integration', function () { expect(res.body).to.be.an.object; expect(res.body.text).to.equal('Page Note 1'); done(); - }); + }); }); - + it('has a basic error handler', function(done) { var test = this; this.get('/api/books/unknown/pages/' + test.page.id + '/notes') @@ -1244,9 +1246,9 @@ describe('relations - integration', function () { var expected = 'could not find a model with id unknown'; expect(res.body.error.message).to.equal(expected); done(); - }); + }); }); - + it('enables nested relationship routes - belongsTo find', function(done) { var test = this; this.get('/api/images/' + test.image.id + '/book/pages') @@ -1255,9 +1257,9 @@ describe('relations - integration', function () { expect(res.body).to.have.length(1); expect(res.body[0].name).to.equal('Page 1'); done(); - }); + }); }); - + it('enables nested relationship routes - belongsTo findById', function(done) { var test = this; this.get('/api/images/' + test.image.id + '/book/pages/' + test.page.id) @@ -1265,9 +1267,9 @@ describe('relations - integration', function () { expect(res.body).to.be.an.object; expect(res.body.name).to.equal('Page 1'); done(); - }); + }); }); - + it('enables nested relationship routes - hasMany find', function(done) { var test = this; this.get('/api/books/' + test.book.id + '/pages/' + test.page.id + '/notes') @@ -1276,9 +1278,9 @@ describe('relations - integration', function () { expect(res.body).to.have.length(1); expect(res.body[0].text).to.equal('Page Note 1'); done(); - }); + }); }); - + it('enables nested relationship routes - hasMany findById', function(done) { var test = this; this.get('/api/books/' + test.book.id + '/pages/' + test.page.id + '/notes/' + test.note.id) @@ -1287,10 +1289,22 @@ describe('relations - integration', function () { expect(res.headers['x-after']).to.equal('after'); expect(res.body).to.be.an.object; expect(res.body.text).to.equal('Page Note 1'); - done(); + done(); + }); + }); + + it('should have proper http.path for remoting', function() { + [app.models.Book, app.models.Image].forEach(function(Model) { + Model.sharedClass.methods().forEach(function(method) { + var http = Array.isArray(method.http) ? method.http : [method.http]; + http.forEach(function(opt) { + // destroyAll has been shared but missing http property + if (opt.path === undefined) return; + expect(opt.path, method.stringName).to.match(/^\/.*/); + }); + }); }); }); - }); - + }); diff --git a/test/remote-connector.test.js b/test/remote-connector.test.js index b99c8f74..39a078e8 100644 --- a/test/remote-connector.test.js +++ b/test/remote-connector.test.js @@ -46,7 +46,7 @@ describe('RemoteConnector', function() { }); }); - it('should support the save method', function (done) { + it('should support the save method', function(done) { var calledServerCreate = false; var RemoteModel = loopback.PersistedModel.extend('TestModel'); RemoteModel.attachTo(this.remote); @@ -57,7 +57,7 @@ describe('RemoteConnector', function() { calledServerCreate = true; data.id = 1; cb(null, data); - } + }; ServerModel.setupRemoting(); diff --git a/test/remoting-coercion.test.js b/test/remoting-coercion.test.js index 5c667673..6dab48e0 100644 --- a/test/remoting-coercion.test.js +++ b/test/remoting-coercion.test.js @@ -13,7 +13,7 @@ describe('remoting coercion', function() { assert(inst instanceof TestModel); assert(inst.foo === 'bar'); cb(); - } + }; TestModel.remoteMethod('test', { accepts: {arg: 'inst', type: 'TestModel', http: {source: 'body'}}, http: {path: '/test', verb: 'post'} @@ -26,9 +26,9 @@ describe('remoting coercion', function() { foo: 'bar' }) .end(function(err) { - if(err) return done(err); + if (err) return done(err); assert(called); done(); }); }); -}) +}); diff --git a/test/remoting.integration.js b/test/remoting.integration.js index 0ba0e90f..23bf1351 100644 --- a/test/remoting.integration.js +++ b/test/remoting.integration.js @@ -5,38 +5,38 @@ var SIMPLE_APP = path.join(__dirname, 'fixtures', 'simple-integration-app'); var app = require(path.join(SIMPLE_APP, 'app.js')); var assert = require('assert'); -describe('remoting - integration', function () { +describe('remoting - integration', function() { lt.beforeEach.withApp(app); lt.beforeEach.givenModel('store'); - afterEach(function (done) { + afterEach(function(done) { this.app.models.store.destroyAll(done); }); - describe('app.remotes.options', function () { - it("should load remoting options", function () { + describe('app.remotes.options', function() { + it('should load remoting options', function() { var remotes = app.remotes(); - assert.deepEqual(remotes.options, {"json": {"limit": "1kb", "strict": false}, - "urlencoded": {"limit": "8kb", "extended": true}}); + assert.deepEqual(remotes.options, {'json': {'limit': '1kb', 'strict': false}, + 'urlencoded': {'limit': '8kb', 'extended': true}}); }); - it("rest handler", function () { + it('rest handler', function() { var handler = app.handler('rest'); assert(handler); }); - it('should accept request that has entity below 1kb', function (done) { + it('should accept request that has entity below 1kb', function(done) { // Build an object that is smaller than 1kb - var name = ""; + var name = ''; for (var i = 0; i < 256; i++) { - name += "11"; + name += '11'; } this.http = this.post('/api/stores'); this.http.send({ - "name": name + 'name': name }); - this.http.end(function (err) { + this.http.end(function(err) { if (err) return done(err); this.req = this.http.req; this.res = this.http.res; @@ -45,17 +45,17 @@ describe('remoting - integration', function () { }.bind(this)); }); - it('should reject request that has entity beyond 1kb', function (done) { + it('should reject request that has entity beyond 1kb', function(done) { // Build an object that is larger than 1kb - var name = ""; + var name = ''; for (var i = 0; i < 2048; i++) { - name += "11111111111"; + name += '11111111111'; } this.http = this.post('/api/stores'); this.http.send({ - "name": name + 'name': name }); - this.http.end(function (err) { + this.http.end(function(err) { if (err) return done(err); this.req = this.http.req; this.res = this.http.res; @@ -81,7 +81,7 @@ describe('remoting - integration', function () { m.name, '(', m.accepts.map(function(a) { - return a.arg + ':' + a.type + return a.arg + ':' + a.type; }).join(','), ')', formatReturns(m), @@ -148,7 +148,6 @@ describe('remoting - integration', function () { expect(methods).to.include.members(expectedMethods); }); - it('should have correct signatures for belongsTo methods', function() { @@ -168,7 +167,6 @@ describe('remoting - integration', function () { expect(methods).to.include.members(expectedMethods); }); - it('should have correct signatures for hasMany methods', function() { diff --git a/test/replication.test.js b/test/replication.test.js index 286535b3..787a9314 100644 --- a/test/replication.test.js +++ b/test/replication.test.js @@ -15,7 +15,7 @@ describe('Replication / Change APIs', function() { trackChanges: true }); SourceModel.attachTo(dataSource); - + var TargetModel = this.TargetModel = PersistedModel.extend('TargetModel', {}, { trackChanges: true }); @@ -23,11 +23,11 @@ describe('Replication / Change APIs', function() { this.createInitalData = function(cb) { SourceModel.create({name: 'foo'}, function(err, inst) { - if(err) return cb(err); + if (err) return cb(err); test.model = inst; // give loopback a chance to register the change - // TODO(ritch) get rid of this... + // TODO(ritch) get rid of this... setTimeout(function() { SourceModel.replicate(TargetModel, cb); }, 100); @@ -36,10 +36,10 @@ describe('Replication / Change APIs', function() { }); describe('Model.changes(since, filter, callback)', function() { - it('Get changes since the given checkpoint', function (done) { + it('Get changes since the given checkpoint', function(done) { var test = this; this.SourceModel.create({name: 'foo'}, function(err) { - if(err) return done(err); + if (err) return done(err); setTimeout(function() { test.SourceModel.changes(test.startingCheckpoint, {}, function(err, changes) { assert.equal(changes.length, 1); @@ -51,7 +51,7 @@ describe('Replication / Change APIs', function() { }); describe('Model.replicate(since, targetModel, options, callback)', function() { - it('Replicate data using the target model', function (done) { + it('Replicate data using the target model', function(done) { var test = this; var options = {}; var sourceData; @@ -62,26 +62,26 @@ describe('Replication / Change APIs', function() { }); function replicate() { - test.SourceModel.replicate(test.startingCheckpoint, test.TargetModel, + test.SourceModel.replicate(test.startingCheckpoint, test.TargetModel, options, function(err, conflicts) { assert(conflicts.length === 0); async.parallel([ function(cb) { test.SourceModel.find(function(err, result) { - if(err) return cb(err); + if (err) return cb(err); sourceData = result; cb(); }); }, function(cb) { test.TargetModel.find(function(err, result) { - if(err) return cb(err); + if (err) return cb(err); targetData = result; cb(); }); } ], function(err) { - if(err) return done(err); + if (err) return done(err); assert.deepEqual(sourceData, targetData); done(); @@ -103,22 +103,22 @@ describe('Replication / Change APIs', function() { async.parallel([ function(cb) { SourceModel.findOne(function(err, inst) { - if(err) return cb(err); + if (err) return cb(err); inst.name = 'source update'; inst.save(cb); }); }, function(cb) { TargetModel.findOne(function(err, inst) { - if(err) return cb(err); + if (err) return cb(err); inst.name = 'target update'; inst.save(cb); }); } ], function(err) { - if(err) return done(err); + if (err) return done(err); SourceModel.replicate(TargetModel, function(err, conflicts) { - if(err) return done(err); + if (err) return done(err); test.conflicts = conflicts; test.conflict = conflicts[0]; done(); @@ -175,22 +175,22 @@ describe('Replication / Change APIs', function() { async.parallel([ function(cb) { SourceModel.findOne(function(err, inst) { - if(err) return cb(err); + if (err) return cb(err); test.model = inst; inst.remove(cb); }); }, function(cb) { TargetModel.findOne(function(err, inst) { - if(err) return cb(err); + if (err) return cb(err); inst.name = 'target update'; inst.save(cb); }); } ], function(err) { - if(err) return done(err); + if (err) return done(err); SourceModel.replicate(TargetModel, function(err, conflicts) { - if(err) return done(err); + if (err) return done(err); test.conflicts = conflicts; test.conflict = conflicts[0]; done(); @@ -244,7 +244,7 @@ describe('Replication / Change APIs', function() { async.parallel([ function(cb) { SourceModel.findOne(function(err, inst) { - if(err) return cb(err); + if (err) return cb(err); test.model = inst; inst.name = 'source update'; inst.save(cb); @@ -252,14 +252,14 @@ describe('Replication / Change APIs', function() { }, function(cb) { TargetModel.findOne(function(err, inst) { - if(err) return cb(err); + if (err) return cb(err); inst.remove(cb); }); } ], function(err) { - if(err) return done(err); + if (err) return done(err); SourceModel.replicate(TargetModel, function(err, conflicts) { - if(err) return done(err); + if (err) return done(err); test.conflicts = conflicts; test.conflict = conflicts[0]; done(); @@ -313,21 +313,21 @@ describe('Replication / Change APIs', function() { async.parallel([ function(cb) { SourceModel.findOne(function(err, inst) { - if(err) return cb(err); + if (err) return cb(err); test.model = inst; inst.remove(cb); }); }, function(cb) { TargetModel.findOne(function(err, inst) { - if(err) return cb(err); + if (err) return cb(err); inst.remove(cb); }); } ], function(err) { - if(err) return done(err); + if (err) return done(err); SourceModel.replicate(TargetModel, function(err, conflicts) { - if(err) return done(err); + if (err) return done(err); test.conflicts = conflicts; test.conflict = conflicts[0]; done(); diff --git a/test/rest.middleware.test.js b/test/rest.middleware.test.js index 89877af7..4a8243d9 100644 --- a/test/rest.middleware.test.js +++ b/test/rest.middleware.test.js @@ -86,7 +86,7 @@ describe('loopback.rest', function() { app.use(loopback.rest()); request(app).get('/mymodels') - .set('Accept', 'text/html,application/xml;q=0.9,*/*;q=0.8') + .set('Accept', 'text/html,application/xml;q= 0.9,*/*;q= 0.8') .expect('Content-Type', 'application/json; charset=utf-8') .expect(200, done); }); @@ -103,7 +103,7 @@ describe('loopback.rest', function() { .set('Authorization', token.id) .expect(200) .end(done); - }); + }, done); }); it('does not include loopback.token when auth not enabled', function(done) { @@ -127,7 +127,7 @@ describe('loopback.rest', function() { expect(res.body.id).to.equal(null); done(); }); - }); + }, done); }); describe('context propagation', function() { @@ -255,7 +255,7 @@ describe('loopback.rest', function() { dataSource: 'db' }); } - function givenLoggedInUser(cb) { + function givenLoggedInUser(cb, done) { var credentials = { email: 'user@example.com', password: 'pwd' }; var User = app.models.user; User.create(credentials, diff --git a/test/role.test.js b/test/role.test.js index 7e02f7ab..dfedc6cc 100644 --- a/test/role.test.js +++ b/test/role.test.js @@ -10,7 +10,7 @@ function checkResult(err, result) { assert(!err); } -describe('role model', function () { +describe('role model', function() { var ds; beforeEach(function() { @@ -22,22 +22,22 @@ describe('role model', function () { RoleMapping.attachTo(ds); }); - it("should define role/role relations", function () { - Role.create({name: 'user'}, function (err, userRole) { - Role.create({name: 'admin'}, function (err, adminRole) { - userRole.principals.create({principalType: RoleMapping.ROLE, principalId: adminRole.id}, function (err, mapping) { - Role.find(function (err, roles) { + it('should define role/role relations', function() { + Role.create({name: 'user'}, function(err, userRole) { + Role.create({name: 'admin'}, function(err, adminRole) { + userRole.principals.create({principalType: RoleMapping.ROLE, principalId: adminRole.id}, function(err, mapping) { + Role.find(function(err, roles) { assert.equal(roles.length, 2); }); - RoleMapping.find(function (err, mappings) { + RoleMapping.find(function(err, mappings) { assert.equal(mappings.length, 1); assert.equal(mappings[0].principalType, RoleMapping.ROLE); assert.equal(mappings[0].principalId, adminRole.id); }); - userRole.principals(function (err, principals) { + userRole.principals(function(err, principals) { assert.equal(principals.length, 1); }); - userRole.roles(function (err, roles) { + userRole.roles(function(err, roles) { assert.equal(roles.length, 1); }); }); @@ -46,25 +46,25 @@ describe('role model', function () { }); - it("should define role/user relations", function () { + it('should define role/user relations', function() { - User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function (err, user) { + User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) { // console.log('User: ', user.id); - Role.create({name: 'userRole'}, function (err, role) { - role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function (err, p) { - Role.find(function (err, roles) { + Role.create({name: 'userRole'}, function(err, role) { + role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function(err, p) { + Role.find(function(err, roles) { assert(!err); assert.equal(roles.length, 1); assert.equal(roles[0].name, 'userRole'); }); - role.principals(function (err, principals) { + role.principals(function(err, principals) { assert(!err); // console.log(principals); assert.equal(principals.length, 1); assert.equal(principals[0].principalType, RoleMapping.USER); assert.equal(principals[0].principalId, user.id); }); - role.users(function (err, users) { + role.users(function(err, users) { assert(!err); assert.equal(users.length, 1); assert.equal(users[0].principalType, RoleMapping.USER); @@ -76,29 +76,28 @@ describe('role model', function () { }); + it('should automatically generate role id', function() { - it("should automatically generate role id", function () { - - User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function (err, user) { + User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) { // console.log('User: ', user.id); - Role.create({name: 'userRole'}, function (err, role) { + Role.create({name: 'userRole'}, function(err, role) { assert(role.id); - role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function (err, p) { + role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function(err, p) { assert(p.id); assert.equal(p.roleId, role.id); - Role.find(function (err, roles) { + Role.find(function(err, roles) { assert(!err); assert.equal(roles.length, 1); assert.equal(roles[0].name, 'userRole'); }); - role.principals(function (err, principals) { + role.principals(function(err, principals) { assert(!err); // console.log(principals); assert.equal(principals.length, 1); assert.equal(principals[0].principalType, RoleMapping.USER); assert.equal(principals[0].principalId, user.id); }); - role.users(function (err, users) { + role.users(function(err, users) { assert(!err); assert.equal(users.length, 1); assert.equal(users[0].principalType, RoleMapping.USER); @@ -110,45 +109,45 @@ describe('role model', function () { }); - it("should support getRoles() and isInRole()", function () { - User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function (err, user) { + it('should support getRoles() and isInRole()', function() { + User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) { // console.log('User: ', user.id); - Role.create({name: 'userRole'}, function (err, role) { - role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function (err, p) { + Role.create({name: 'userRole'}, function(err, role) { + role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function(err, p) { // Role.find(console.log); // role.principals(console.log); - Role.isInRole('userRole', {principalType: RoleMapping.USER, principalId: user.id}, function (err, exists) { + Role.isInRole('userRole', {principalType: RoleMapping.USER, principalId: user.id}, function(err, exists) { assert(!err && exists === true); }); - Role.isInRole('userRole', {principalType: RoleMapping.APP, principalId: user.id}, function (err, exists) { + Role.isInRole('userRole', {principalType: RoleMapping.APP, principalId: user.id}, function(err, exists) { assert(!err && exists === false); }); - Role.isInRole('userRole', {principalType: RoleMapping.USER, principalId: 100}, function (err, exists) { + Role.isInRole('userRole', {principalType: RoleMapping.USER, principalId: 100}, function(err, exists) { assert(!err && exists === false); }); - Role.getRoles({principalType: RoleMapping.USER, principalId: user.id}, function (err, roles) { + Role.getRoles({principalType: RoleMapping.USER, principalId: user.id}, function(err, roles) { assert.equal(roles.length, 3); // everyone, authenticated, userRole - assert(roles.indexOf(role.id) >=0); - assert(roles.indexOf(Role.EVERYONE) >=0); - assert(roles.indexOf(Role.AUTHENTICATED) >=0); + assert(roles.indexOf(role.id) >= 0); + assert(roles.indexOf(Role.EVERYONE) >= 0); + assert(roles.indexOf(Role.AUTHENTICATED) >= 0); }); - Role.getRoles({principalType: RoleMapping.APP, principalId: user.id}, function (err, roles) { + Role.getRoles({principalType: RoleMapping.APP, principalId: user.id}, function(err, roles) { assert.equal(roles.length, 2); - assert(roles.indexOf(Role.EVERYONE) >=0); - assert(roles.indexOf(Role.AUTHENTICATED) >=0); + assert(roles.indexOf(Role.EVERYONE) >= 0); + assert(roles.indexOf(Role.AUTHENTICATED) >= 0); }); - Role.getRoles({principalType: RoleMapping.USER, principalId: 100}, function (err, roles) { + Role.getRoles({principalType: RoleMapping.USER, principalId: 100}, function(err, roles) { assert.equal(roles.length, 2); - assert(roles.indexOf(Role.EVERYONE) >=0); - assert(roles.indexOf(Role.AUTHENTICATED) >=0); + assert(roles.indexOf(Role.EVERYONE) >= 0); + assert(roles.indexOf(Role.AUTHENTICATED) >= 0); }); - Role.getRoles({principalType: RoleMapping.USER, principalId: null}, function (err, roles) { + Role.getRoles({principalType: RoleMapping.USER, principalId: null}, function(err, roles) { assert.equal(roles.length, 2); - assert(roles.indexOf(Role.EVERYONE) >=0); - assert(roles.indexOf(Role.UNAUTHENTICATED) >=0); + assert(roles.indexOf(Role.EVERYONE) >= 0); + assert(roles.indexOf(Role.UNAUTHENTICATED) >= 0); }); }); }); @@ -156,7 +155,7 @@ describe('role model', function () { }); - it("should support owner role resolver", function () { + it('should support owner role resolver', function() { var Album = ds.createModel('Album', { name: String, @@ -171,36 +170,36 @@ describe('role model', function () { } }); - User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function (err, user) { - Role.isInRole(Role.AUTHENTICATED, {principalType: ACL.USER, principalId: user.id}, function (err, yes) { + User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) { + Role.isInRole(Role.AUTHENTICATED, {principalType: ACL.USER, principalId: user.id}, function(err, yes) { assert(!err && yes); }); - Role.isInRole(Role.AUTHENTICATED, {principalType: ACL.USER, principalId: null}, function (err, yes) { + Role.isInRole(Role.AUTHENTICATED, {principalType: ACL.USER, principalId: null}, function(err, yes) { assert(!err && !yes); }); - Role.isInRole(Role.UNAUTHENTICATED, {principalType: ACL.USER, principalId: user.id}, function (err, yes) { + Role.isInRole(Role.UNAUTHENTICATED, {principalType: ACL.USER, principalId: user.id}, function(err, yes) { assert(!err && !yes); }); - Role.isInRole(Role.UNAUTHENTICATED, {principalType: ACL.USER, principalId: null}, function (err, yes) { + Role.isInRole(Role.UNAUTHENTICATED, {principalType: ACL.USER, principalId: null}, function(err, yes) { assert(!err && yes); }); - Role.isInRole(Role.EVERYONE, {principalType: ACL.USER, principalId: user.id}, function (err, yes) { + Role.isInRole(Role.EVERYONE, {principalType: ACL.USER, principalId: user.id}, function(err, yes) { assert(!err && yes); }); - Role.isInRole(Role.EVERYONE, {principalType: ACL.USER, principalId: null}, function (err, yes) { + Role.isInRole(Role.EVERYONE, {principalType: ACL.USER, principalId: null}, function(err, yes) { assert(!err && yes); }); // console.log('User: ', user.id); - Album.create({name: 'Album 1', userId: user.id}, function (err, album1) { - Role.isInRole(Role.OWNER, {principalType: ACL.USER, principalId: user.id, model: Album, id: album1.id}, function (err, yes) { + Album.create({name: 'Album 1', userId: user.id}, function(err, album1) { + Role.isInRole(Role.OWNER, {principalType: ACL.USER, principalId: user.id, model: Album, id: album1.id}, function(err, yes) { assert(!err && yes); }); - Album.create({name: 'Album 2'}, function (err, album2) { - Role.isInRole(Role.OWNER, {principalType: ACL.USER, principalId: user.id, model: Album, id: album2.id}, function (err, yes) { + Album.create({name: 'Album 2'}, function(err, album2) { + Role.isInRole(Role.OWNER, {principalType: ACL.USER, principalId: user.id, model: Album, id: album2.id}, function(err, yes) { assert(!err && !yes); }); }); @@ -210,7 +209,3 @@ describe('role model', function () { }); }); - - - - diff --git a/test/support.js b/test/support.js index 81d420e1..1ef0eefc 100644 --- a/test/support.js +++ b/test/support.js @@ -1,7 +1,7 @@ /** * loopback test setup and support. */ - + assert = require('assert'); expect = require('chai').expect; loopback = require('../'); @@ -16,7 +16,7 @@ var RemoteObjects = require('strong-remoting'); // for tests using the built-in User model loopback.User.settings.saltWorkFactor = 4; -beforeEach(function () { +beforeEach(function() { this.app = app = loopback(); // setup default data sources @@ -35,7 +35,7 @@ beforeEach(function () { loopback.autoAttach(); }); -assertValidDataSource = function (dataSource) { +assertValidDataSource = function(dataSource) { // has methods assert.isFunc(dataSource, 'createModel'); assert.isFunc(dataSource, 'discoverModelDefinitions'); @@ -44,9 +44,9 @@ assertValidDataSource = function (dataSource) { assert.isFunc(dataSource, 'disableRemote'); assert.isFunc(dataSource, 'defineOperation'); assert.isFunc(dataSource, 'operations'); -} +}; -assert.isFunc = function (obj, name) { +assert.isFunc = function(obj, name) { assert(obj, 'cannot assert function ' + name + ' on object that doesnt exist'); assert(typeof obj[name] === 'function', name + ' is not a function'); -} +}; diff --git a/test/user.test.js b/test/user.test.js index 710cc5ca..8b8ee4f3 100644 --- a/test/user.test.js +++ b/test/user.test.js @@ -6,7 +6,7 @@ var userMemory = loopback.createDataSource({ connector: 'memory' }); -describe('User', function(){ +describe('User', function() { var validCredentials = {email: 'foo@bar.com', password: 'bar'}; var validCredentialsEmailVerified = {email: 'foo1@bar.com', password: 'bar1', emailVerified: true}; var validCredentialsEmailVerifiedOverREST = {email: 'foo2@bar.com', password: 'bar2', emailVerified: true}; @@ -21,32 +21,32 @@ describe('User', function(){ // Update the AccessToken relation to use the subclass of User AccessToken.belongsTo(User); - + // allow many User.afterRemote's to be called User.setMaxListeners(0); }); - - beforeEach(function (done) { + + beforeEach(function(done) { app.enableAuth(); app.use(loopback.token()); app.use(loopback.rest()); app.model(User); - + User.create(validCredentials, function(err, user) { User.create(validCredentialsEmailVerified, done); }); }); - - afterEach(function (done) { - User.destroyAll(function (err) { + + afterEach(function(done) { + User.destroyAll(function(err) { User.accessToken.destroyAll(done); }); }); - - describe('User.create', function(){ + + describe('User.create', function() { it('Create a new user', function(done) { - User.create({email: 'f@b.com', password: 'bar'}, function (err, user) { + User.create({email: 'f@b.com', password: 'bar'}, function(err, user) { assert(!err); assert(user.id); assert(user.email); @@ -54,13 +54,13 @@ describe('User', function(){ }); }); - it('credentials/challenges are object types', function (done) { + it('credentials/challenges are object types', function(done) { User.create({email: 'f1@b.com', password: 'bar1', credentials: {cert: 'xxxxx', key: '111'}, challenges: {x: 'X', a: 1} - }, function (err, user) { + }, function(err, user) { assert(!err); - User.findById(user.id, function (err, user) { + User.findById(user.id, function(err, user) { assert(user.id); assert(user.email); assert.deepEqual(user.credentials, {cert: 'xxxxx', key: '111'}); @@ -70,12 +70,12 @@ describe('User', function(){ }); }); - it('Email is required', function (done) { - User.create({password: '123'}, function (err) { + it('Email is required', function(done) { + User.create({password: '123'}, function(err) { assert(err); - assert.equal(err.name, "ValidationError"); + assert.equal(err.name, 'ValidationError'); assert.equal(err.statusCode, 422); - assert.equal(err.details.context, "user"); + assert.equal(err.details.context, 'user'); assert.deepEqual(err.details.codes.email, [ 'presence', 'format.blank' @@ -84,27 +84,27 @@ describe('User', function(){ done(); }); }); - + // will change in future versions where password will be optional by default it('Password is required', function(done) { - var u = new User({email: "123@456.com"}); - - User.create({email: 'c@d.com'}, function (err) { + var u = new User({email: '123@456.com'}); + + User.create({email: 'c@d.com'}, function(err) { assert(err); done(); }); }); - + it('Requires a valid email', function(done) { - User.create({email: 'foo@', password: '123'}, function (err) { + User.create({email: 'foo@', password: '123'}, function(err) { assert(err); done(); }); }); - + it('Requires a unique email', function(done) { - User.create({email: 'a@b.com', password: 'foobar'}, function () { - User.create({email: 'a@b.com', password: 'batbaz'}, function (err) { + User.create({email: 'a@b.com', password: 'foobar'}, function() { + User.create({email: 'a@b.com', password: 'batbaz'}, function(err) { assert(err, 'should error because the email is not unique!'); done(); }); @@ -112,24 +112,24 @@ describe('User', function(){ }); it('Requires a unique username', function(done) { - User.create({email: 'a@b.com', username: 'abc', password: 'foobar'}, function () { - User.create({email: 'b@b.com', username: 'abc', password: 'batbaz'}, function (err) { + User.create({email: 'a@b.com', username: 'abc', password: 'foobar'}, function() { + User.create({email: 'b@b.com', username: 'abc', password: 'batbaz'}, function(err) { assert(err, 'should error because the username is not unique!'); done(); }); }); - }); - + }); + it('Requires a password to login with basic auth', function(done) { - User.create({email: 'b@c.com'}, function (err) { - User.login({email: 'b@c.com'}, function (err, accessToken) { + User.create({email: 'b@c.com'}, function(err) { + User.login({email: 'b@c.com'}, function(err, accessToken) { assert(!accessToken, 'should not create a accessToken without a valid password'); assert(err, 'should not login without a password'); done(); }); }); }); - + it('Hashes the given password', function() { var u = new User({username: 'foo', password: 'bar'}); assert(u.password !== 'bar'); @@ -141,26 +141,26 @@ describe('User', function(){ .expect('Content-Type', /json/) .expect(200) .send(validCredentialsEmailVerifiedOverREST) - .end(function(err, res){ + .end(function(err, res) { assert(!res.body.emailVerified); done(); }); }); }); - + describe('User.login', function() { it('Login a user by providing credentials', function(done) { - User.login(validCredentials, function (err, accessToken) { + User.login(validCredentials, function(err, accessToken) { assert(accessToken.userId); assert(accessToken.id); assert.equal(accessToken.id.length, 64); - + done(); }); }); it('Login a user by providing credentials with TTL', function(done) { - User.login(validCredentialsWithTTL, function (err, accessToken) { + User.login(validCredentialsWithTTL, function(err, accessToken) { assert(accessToken.userId); assert(accessToken.id); assert.equal(accessToken.ttl, validCredentialsWithTTL.ttl); @@ -175,16 +175,16 @@ describe('User', function(){ // Override createAccessToken User.prototype.createAccessToken = function(ttl, cb) { // Reduce the ttl by half for testing purpose - this.accessTokens.create({ttl: ttl /2 }, cb); + this.accessTokens.create({ttl: ttl / 2 }, cb); }; - User.login(validCredentialsWithTTL, function (err, accessToken) { + User.login(validCredentialsWithTTL, function(err, accessToken) { assert(accessToken.userId); assert(accessToken.id); assert.equal(accessToken.ttl, 1800); assert.equal(accessToken.id.length, 64); User.findById(accessToken.userId, function(err, user) { - user.createAccessToken(120, function (err, accessToken) { + user.createAccessToken(120, function(err, accessToken) { assert(accessToken.userId); assert(accessToken.id); assert.equal(accessToken.ttl, 60); @@ -203,15 +203,15 @@ describe('User', function(){ .expect('Content-Type', /json/) .expect(200) .send(validCredentials) - .end(function(err, res){ - if(err) return done(err); + .end(function(err, res) { + if (err) return done(err); var accessToken = res.body; - + assert(accessToken.userId); assert(accessToken.id); assert.equal(accessToken.id.length, 64); assert(accessToken.user === undefined); - + done(); }); }); @@ -222,7 +222,7 @@ describe('User', function(){ .expect('Content-Type', /json/) .expect(401) .send(invalidCredentials) - .end(function(err, res){ + .end(function(err, res) { done(); }); }); @@ -233,7 +233,7 @@ describe('User', function(){ .expect('Content-Type', /json/) .expect(400) .send(incompleteCredentials) - .end(function(err, res){ + .end(function(err, res) { done(); }); }); @@ -245,7 +245,7 @@ describe('User', function(){ .expect('Content-Type', /json/) .expect(400) .send(validCredentials) - .end(function(err, res){ + .end(function(err, res) { done(); }); }); @@ -284,7 +284,7 @@ describe('User', function(){ it('Login should only allow correct credentials', function(done) { User.create({email: 'foo22@bar.com', password: 'bar'}, function(user, err) { - User.login({email: 'foo44@bar.com', password: 'bar'}, function(err, accessToken) { + User.login({email: 'foo44@bar.com', password: 'bar'}, function(err, accessToken) { assert(err); assert(!accessToken); done(); @@ -309,14 +309,14 @@ describe('User', function(){ }); it('Login a user by without email verification', function(done) { - User.login(validCredentials, function (err, accessToken) { + User.login(validCredentials, function(err, accessToken) { assert(err); done(); }); }); it('Login a user by with email verification', function(done) { - User.login(validCredentialsEmailVerified, function (err, accessToken) { + User.login(validCredentialsEmailVerified, function(err, accessToken) { assertGoodToken(accessToken); done(); }); @@ -328,8 +328,8 @@ describe('User', function(){ .expect('Content-Type', /json/) .expect(200) .send(validCredentialsEmailVerified) - .end(function(err, res){ - if(err) return done(err); + .end(function(err, res) { + if (err) return done(err); var accessToken = res.body; assertGoodToken(accessToken); @@ -353,7 +353,8 @@ describe('User', function(){ }); describe('User.login requiring realm', function() { - var User, AccessToken; + var User; + var AccessToken; before(function() { User = loopback.User.extend('RealmUser', {}, @@ -511,20 +512,20 @@ describe('User', function(){ }); }); }); - + describe('User.logout', function() { it('Logout a user by providing the current accessToken id (using node)', function(done) { login(logout); - + function login(fn) { User.login({email: 'foo@bar.com', password: 'bar'}, fn); } - + function logout(err, accessToken) { User.logout(accessToken.id, verify(accessToken.id, done)); } }); - + it('Logout a user by providing the current accessToken id (over rest)', function(done) { login(logout); function login(fn) { @@ -533,17 +534,17 @@ describe('User', function(){ .expect('Content-Type', /json/) .expect(200) .send({email: 'foo@bar.com', password: 'bar'}) - .end(function(err, res){ - if(err) return done(err); + .end(function(err, res) { + if (err) return done(err); var accessToken = res.body; - + assert(accessToken.userId); assert(accessToken.id); - + fn(null, accessToken.id); }); } - + function logout(err, token) { request(app) .post('/users/logout') @@ -552,74 +553,74 @@ describe('User', function(){ .end(verify(token, done)); } }); - + function verify(token, done) { assert(token); - - return function (err) { - if(err) return done(err); - - AccessToken.findById(token, function (err, accessToken) { + + return function(err) { + if (err) return done(err); + + AccessToken.findById(token, function(err, accessToken) { assert(!accessToken, 'accessToken should not exist after logging out'); done(err); }); - } + }; } }); - - describe('user.hasPassword(plain, fn)', function(){ + + describe('user.hasPassword(plain, fn)', function() { it('Determine if the password matches the stored password', function(done) { var u = new User({username: 'foo', password: 'bar'}); - u.hasPassword('bar', function (err, isMatch) { + u.hasPassword('bar', function(err, isMatch) { assert(isMatch, 'password doesnt match'); done(); - }); + }); }); - + it('should match a password when saved', function(done) { var u = new User({username: 'a', password: 'b', email: 'z@z.net'}); - - u.save(function (err, user) { - User.findById(user.id, function (err, uu) { - uu.hasPassword('b', function (err, isMatch) { + + u.save(function(err, user) { + User.findById(user.id, function(err, uu) { + uu.hasPassword('b', function(err, isMatch) { assert(isMatch); done(); }); }); }); }); - + it('should match a password after it is changed', function(done) { - User.create({email: 'foo@baz.net', username: 'bat', password: 'baz'}, function (err, user) { - User.findById(user.id, function (err, foundUser) { - assert(foundUser); - foundUser.hasPassword('baz', function (err, isMatch) { - assert(isMatch); - foundUser.password = 'baz2'; - foundUser.save(function (err, updatedUser) { - updatedUser.hasPassword('baz2', function (err, isMatch) { - assert(isMatch); - User.findById(user.id, function (err, uu) { - uu.hasPassword('baz2', function (err, isMatch) { - assert(isMatch); - done(); - }); - }); - }); - }); - }); - }); - }); + User.create({email: 'foo@baz.net', username: 'bat', password: 'baz'}, function(err, user) { + User.findById(user.id, function(err, foundUser) { + assert(foundUser); + foundUser.hasPassword('baz', function(err, isMatch) { + assert(isMatch); + foundUser.password = 'baz2'; + foundUser.save(function(err, updatedUser) { + updatedUser.hasPassword('baz2', function(err, isMatch) { + assert(isMatch); + User.findById(user.id, function(err, uu) { + uu.hasPassword('baz2', function(err, isMatch) { + assert(isMatch); + done(); + }); + }); + }); + }); + }); + }); + }); }); }); - - describe('Verification', function(){ - describe('user.verify(options, fn)', function(){ + describe('Verification', function() { + + describe('user.verify(options, fn)', function() { it('Verify a user\'s email address', function(done) { User.afterRemote('create', function(ctx, user, next) { assert(user, 'afterRemote should include result'); - + var options = { type: 'email', to: user.email, @@ -628,8 +629,8 @@ describe('User', function(){ protocol: ctx.req.protocol, host: ctx.req.get('host') }; - - user.verify(options, function (err, result) { + + user.verify(options, function(err, result) { assert(result.email); assert(result.email.response); assert(result.token); @@ -639,21 +640,21 @@ describe('User', function(){ done(); }); }); - + request(app) .post('/users') .expect('Content-Type', /json/) .expect(200) .send({email: 'bar@bat.com', password: 'bar'}) - .end(function(err, res){ - if(err) return done(err); + .end(function(err, res) { + if (err) return done(err); }); }); it('Verify a user\'s email address with custom header', function(done) { User.afterRemote('create', function(ctx, user, next) { assert(user, 'afterRemote should include result'); - + var options = { type: 'email', to: user.email, @@ -663,31 +664,31 @@ describe('User', function(){ host: ctx.req.get('host'), headers: {'message-id':'custom-header-value'} }; - - user.verify(options, function (err, result) { + + user.verify(options, function(err, result) { assert(result.email); assert.equal(result.email.messageId, 'custom-header-value'); done(); }); }); - + request(app) .post('/users') .expect('Content-Type', /json/) .expect(200) .send({email: 'bar@bat.com', password: 'bar'}) - .end(function(err, res){ - if(err) return done(err); + .end(function(err, res) { + if (err) return done(err); }); }); }); - describe('User.confirm(options, fn)', function () { + describe('User.confirm(options, fn)', function() { var options; function testConfirm(testFunc, done) { - User.afterRemote('create', function (ctx, user, next) { + User.afterRemote('create', function(ctx, user, next) { assert(user, 'afterRemote should include result'); options = { @@ -699,7 +700,7 @@ describe('User', function(){ host: ctx.req.get('host') }; - user.verify(options, function (err, result) { + user.verify(options, function(err, result) { if (err) { return done(err); } @@ -712,21 +713,21 @@ describe('User', function(){ .expect('Content-Type', /json/) .expect(302) .send({email: 'bar@bat.com', password: 'bar'}) - .end(function (err, res) { + .end(function(err, res) { if (err) { return done(err); } }); } - it('Confirm a user verification', function (done) { - testConfirm(function (result, done) { + it('Confirm a user verification', function(done) { + testConfirm(function(result, done) { request(app) - .get('/users/confirm?uid=' + (result.uid ) + .get('/users/confirm?uid=' + (result.uid) + '&token=' + encodeURIComponent(result.token) + '&redirect=' + encodeURIComponent(options.redirect)) .expect(302) - .end(function (err, res) { + .end(function(err, res) { if (err) { return done(err); } @@ -735,14 +736,14 @@ describe('User', function(){ }, done); }); - it('Report error for invalid user id during verification', function (done) { - testConfirm(function (result, done) { + it('Report error for invalid user id during verification', function(done) { + testConfirm(function(result, done) { request(app) .get('/users/confirm?uid=' + (result.uid + '_invalid') + '&token=' + encodeURIComponent(result.token) + '&redirect=' + encodeURIComponent(options.redirect)) .expect(404) - .end(function (err, res) { + .end(function(err, res) { if (err) { return done(err); } @@ -752,14 +753,14 @@ describe('User', function(){ }, done); }); - it('Report error for invalid token during verification', function (done) { - testConfirm(function (result, done) { + it('Report error for invalid token during verification', function(done) { + testConfirm(function(result, done) { request(app) .get('/users/confirm?uid=' + result.uid + '&token=' + encodeURIComponent(result.token) + '_invalid' + '&redirect=' + encodeURIComponent(options.redirect)) .expect(400) - .end(function (err, res) { + .end(function(err, res) { if (err) return done(err); assert(res.body.error); done(); @@ -769,25 +770,25 @@ describe('User', function(){ }); }); - describe('Password Reset', function () { - describe('User.resetPassword(options, cb)', function () { - it('Creates a temp accessToken to allow a user to change password', function (done) { + describe('Password Reset', function() { + describe('User.resetPassword(options, cb)', function() { + it('Creates a temp accessToken to allow a user to change password', function(done) { var calledBack = false; var email = 'foo@bar.com'; User.resetPassword({ email: email - }, function () { + }, function() { calledBack = true; }); - User.once('resetPasswordRequest', function (info) { + User.once('resetPasswordRequest', function(info) { assert(info.email); assert(info.accessToken); assert(info.accessToken.id); assert.equal(info.accessToken.ttl / 60, 15); assert(calledBack); - info.accessToken.user(function (err, user) { + info.accessToken.user(function(err, user) { assert.equal(user.email, email); done(); }); diff --git a/test/util/model-tests.js b/test/util/model-tests.js index 58a5c0c2..9a72e861 100644 --- a/test/util/model-tests.js +++ b/test/util/model-tests.js @@ -8,187 +8,202 @@ var RemoteObjects = require('strong-remoting'); module.exports = function defineModelTestsWithDataSource(options) { -describe('Model Tests', function() { + describe('Model Tests', function() { - var User, dataSource; + var User; + var dataSource; - if(options.beforeEach) { - beforeEach(options.beforeEach); - } - - beforeEach(function() { - var test = this; - - // setup a model / datasource - dataSource = this.dataSource || loopback.createDataSource(options.dataSource); - - var extend = PersistedModel.extend; - - // create model hook - PersistedModel.extend = function() { - var extendedModel = extend.apply(PersistedModel, arguments); - - if(options.onDefine) { - options.onDefine.call(test, extendedModel); - } - - return extendedModel; + if (options.beforeEach) { + beforeEach(options.beforeEach); } - User = PersistedModel.extend('user', { - 'first': String, - 'last': String, - 'age': Number, - 'password': String, - 'gender': String, - 'domain': String, - 'email': String - }, { - trackChanges: true + beforeEach(function() { + var test = this; + + // setup a model / datasource + dataSource = this.dataSource || loopback.createDataSource(options.dataSource); + + var extend = PersistedModel.extend; + + // create model hook + PersistedModel.extend = function() { + var extendedModel = extend.apply(PersistedModel, arguments); + + if (options.onDefine) { + options.onDefine.call(test, extendedModel); + } + + return extendedModel; + }; + + User = PersistedModel.extend('user', { + 'first': String, + 'last': String, + 'age': Number, + 'password': String, + 'gender': String, + 'domain': String, + 'email': String + }, { + trackChanges: true + }); + + // enable destroy all for testing + User.destroyAll.shared = true; + User.attachTo(dataSource); }); - // enable destroy all for testing - User.destroyAll.shared = true; - User.attachTo(dataSource); - }); - - describe('Model.validatesPresenceOf(properties...)', function() { - it("Require a model to include a property to be considered valid", function() { - User.validatesPresenceOf('first', 'last', 'age'); - var joe = new User({first: 'joe'}); - assert(joe.isValid() === false, 'model should not validate'); - assert(joe.errors.last, 'should have a missing last error'); - assert(joe.errors.age, 'should have a missing age error'); + describe('Model.validatesPresenceOf(properties...)', function() { + it('Require a model to include a property to be considered valid', function() { + User.validatesPresenceOf('first', 'last', 'age'); + var joe = new User({first: 'joe'}); + assert(joe.isValid() === false, 'model should not validate'); + assert(joe.errors.last, 'should have a missing last error'); + assert(joe.errors.age, 'should have a missing age error'); + }); }); - }); - describe('Model.validatesLengthOf(property, options)', function() { - it("Require a property length to be within a specified range", function() { - User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}}); - var joe = new User({password: '1234'}); - assert(joe.isValid() === false, 'model should not be valid'); - assert(joe.errors.password, 'should have password error'); + describe('Model.validatesLengthOf(property, options)', function() { + it('Require a property length to be within a specified range', function() { + User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}}); + var joe = new User({password: '1234'}); + assert(joe.isValid() === false, 'model should not be valid'); + assert(joe.errors.password, 'should have password error'); + }); }); - }); - describe('Model.validatesInclusionOf(property, options)', function() { - it("Require a value for `property` to be in the specified array", function() { - User.validatesInclusionOf('gender', {in: ['male', 'female']}); - var foo = new User({gender: 'bar'}); - assert(foo.isValid() === false, 'model should not be valid'); - assert(foo.errors.gender, 'should have gender error'); + describe('Model.validatesInclusionOf(property, options)', function() { + it('Require a value for `property` to be in the specified array', function() { + User.validatesInclusionOf('gender', {in: ['male', 'female']}); + var foo = new User({gender: 'bar'}); + assert(foo.isValid() === false, 'model should not be valid'); + assert(foo.errors.gender, 'should have gender error'); + }); }); - }); - describe('Model.validatesExclusionOf(property, options)', function() { - it("Require a value for `property` to not exist in the specified array", function() { - User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']}); - var foo = new User({domain: 'www'}); - var bar = new User({domain: 'billing'}); - var bat = new User({domain: 'admin'}); - assert(foo.isValid() === false); - assert(bar.isValid() === false); - assert(bat.isValid() === false); - assert(foo.errors.domain, 'model should have a domain error'); - assert(bat.errors.domain, 'model should have a domain error'); - assert(bat.errors.domain, 'model should have a domain error'); + describe('Model.validatesExclusionOf(property, options)', function() { + it('Require a value for `property` to not exist in the specified array', function() { + User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']}); + var foo = new User({domain: 'www'}); + var bar = new User({domain: 'billing'}); + var bat = new User({domain: 'admin'}); + assert(foo.isValid() === false); + assert(bar.isValid() === false); + assert(bat.isValid() === false); + assert(foo.errors.domain, 'model should have a domain error'); + assert(bat.errors.domain, 'model should have a domain error'); + assert(bat.errors.domain, 'model should have a domain error'); + }); }); - }); - describe('Model.validatesNumericalityOf(property, options)', function() { - it("Require a value for `property` to be a specific type of `Number`", function() { - User.validatesNumericalityOf('age', {int: true}); - var joe = new User({age: 10.2}); - assert(joe.isValid() === false); - var bob = new User({age: 0}); - assert(bob.isValid() === true); - assert(joe.errors.age, 'model should have an age error'); + describe('Model.validatesNumericalityOf(property, options)', function() { + it('Require a value for `property` to be a specific type of `Number`', function() { + User.validatesNumericalityOf('age', {int: true}); + var joe = new User({age: 10.2}); + assert(joe.isValid() === false); + var bob = new User({age: 0}); + assert(bob.isValid() === true); + assert(joe.errors.age, 'model should have an age error'); + }); }); - }); - describe('myModel.isValid()', function() { - it("Validate the model instance", function() { - User.validatesNumericalityOf('age', {int: true}); - var user = new User({first: 'joe', age: 'flarg'}) - var valid = user.isValid(); - assert(valid === false); - assert(user.errors.age, 'model should have age error'); - }); - - it('Asynchronously validate the model', function(done) { - User.validatesNumericalityOf('age', {int: true}); - var user = new User({first: 'joe', age: 'flarg'}); - user.isValid(function (valid) { + describe('myModel.isValid()', function() { + it('Validate the model instance', function() { + User.validatesNumericalityOf('age', {int: true}); + var user = new User({first: 'joe', age: 'flarg'}); + var valid = user.isValid(); assert(valid === false); assert(user.errors.age, 'model should have age error'); - done(); }); - }); - }); - describe('Model.create([data], [callback])', function() { - it("Create an instance of Model with given data and save to the attached data source", function(done) { - User.create({first: 'Joe', last: 'Bob'}, function(err, user) { - assert(user instanceof User); - done(); - }); - }); - }); - - describe('model.save([options], [callback])', function() { - it("Save an instance of a Model to the attached data source", function(done) { - var joe = new User({first: 'Joe', last: 'Bob'}); - joe.save(function(err, user) { - assert(user.id); - assert(!err); - assert(!user.errors); - done(); - }); - }); - }); - - describe('model.updateAttributes(data, [callback])', function() { - it("Save specified attributes to the attached data source", function(done) { - User.create({first: 'joe', age: 100}, function (err, user) { - assert(!err); - assert.equal(user.first, 'joe'); - - user.updateAttributes({ - first: 'updatedFirst', - last: 'updatedLast' - }, function (err, updatedUser) { - assert(!err); - assert.equal(updatedUser.first, 'updatedFirst'); - assert.equal(updatedUser.last, 'updatedLast'); - assert.equal(updatedUser.age, 100); + it('Asynchronously validate the model', function(done) { + User.validatesNumericalityOf('age', {int: true}); + var user = new User({first: 'joe', age: 'flarg'}); + user.isValid(function(valid) { + assert(valid === false); + assert(user.errors.age, 'model should have age error'); done(); }); }); }); - }); - describe('Model.upsert(data, callback)', function() { - it("Update when record with id=data.id found, insert otherwise", function(done) { - User.upsert({first: 'joe', id: 7}, function (err, user) { - assert(!err); - assert.equal(user.first, 'joe'); - - User.upsert({first: 'bob', id: 7}, function (err, updatedUser) { - assert(!err); - assert.equal(updatedUser.first, 'bob'); + describe('Model.create([data], [callback])', function() { + it('Create an instance of Model with given data and save to the attached data source', function(done) { + User.create({first: 'Joe', last: 'Bob'}, function(err, user) { + assert(user instanceof User); done(); }); }); }); - }); - describe('model.destroy([callback])', function() { - it("Remove a model from the attached data source", function(done) { - User.create({first: 'joe', last: 'bob'}, function (err, user) { - User.findById(user.id, function (err, foundUser) { - assert.equal(user.id, foundUser.id); - foundUser.destroy(function () { - User.findById(user.id, function (err, notFound) { + describe('model.save([options], [callback])', function() { + it('Save an instance of a Model to the attached data source', function(done) { + var joe = new User({first: 'Joe', last: 'Bob'}); + joe.save(function(err, user) { + assert(user.id); + assert(!err); + assert(!user.errors); + done(); + }); + }); + }); + + describe('model.updateAttributes(data, [callback])', function() { + it('Save specified attributes to the attached data source', function(done) { + User.create({first: 'joe', age: 100}, function(err, user) { + assert(!err); + assert.equal(user.first, 'joe'); + + user.updateAttributes({ + first: 'updatedFirst', + last: 'updatedLast' + }, function(err, updatedUser) { + assert(!err); + assert.equal(updatedUser.first, 'updatedFirst'); + assert.equal(updatedUser.last, 'updatedLast'); + assert.equal(updatedUser.age, 100); + done(); + }); + }); + }); + }); + + describe('Model.upsert(data, callback)', function() { + it('Update when record with id=data.id found, insert otherwise', function(done) { + User.upsert({first: 'joe', id: 7}, function(err, user) { + assert(!err); + assert.equal(user.first, 'joe'); + + User.upsert({first: 'bob', id: 7}, function(err, updatedUser) { + assert(!err); + assert.equal(updatedUser.first, 'bob'); + done(); + }); + }); + }); + }); + + describe('model.destroy([callback])', function() { + it('Remove a model from the attached data source', function(done) { + User.create({first: 'joe', last: 'bob'}, function(err, user) { + User.findById(user.id, function(err, foundUser) { + assert.equal(user.id, foundUser.id); + foundUser.destroy(function() { + User.findById(user.id, function(err, notFound) { + assert.equal(notFound, null); + done(); + }); + }); + }); + }); + }); + }); + + describe('Model.deleteById(id, [callback])', function() { + it('Delete a model instance from the attached data source', function(done) { + User.create({first: 'joe', last: 'bob'}, function(err, user) { + User.deleteById(user.id, function(err) { + User.findById(user.id, function(err, notFound) { assert.equal(notFound, null); done(); }); @@ -196,52 +211,37 @@ describe('Model Tests', function() { }); }); }); - }); - describe('Model.deleteById(id, [callback])', function () { - it("Delete a model instance from the attached data source", function (done) { - User.create({first: 'joe', last: 'bob'}, function (err, user) { - User.deleteById(user.id, function (err) { - User.findById(user.id, function (err, notFound) { - assert.equal(notFound, null); - done(); - }); - }); - }); - }); - }); - - describe('Model.findById(id, callback)', function() { - it("Find an instance by id", function(done) { - User.create({first: 'michael', last: 'jordan', id: 23}, function () { - User.findById(23, function (err, user) { - assert.equal(user.id, 23); - assert.equal(user.first, 'michael'); - assert.equal(user.last, 'jordan'); - done(); - }); - }); - }); - }); - - describe('Model.count([query], callback)', function() { - it("Query count of Model instances in data source", function(done) { - (new TaskEmitter()) - .task(User, 'create', {first: 'jill', age: 100}) - .task(User, 'create', {first: 'bob', age: 200}) - .task(User, 'create', {first: 'jan'}) - .task(User, 'create', {first: 'sam'}) - .task(User, 'create', {first: 'suzy'}) - .on('done', function () { - User.count({age: {gt: 99}}, function (err, count) { - assert.equal(count, 2); + describe('Model.findById(id, callback)', function() { + it('Find an instance by id', function(done) { + User.create({first: 'michael', last: 'jordan', id: 23}, function() { + User.findById(23, function(err, user) { + assert.equal(user.id, 23); + assert.equal(user.first, 'michael'); + assert.equal(user.last, 'jordan'); done(); }); }); + }); }); + + describe('Model.count([query], callback)', function() { + it('Query count of Model instances in data source', function(done) { + (new TaskEmitter()) + .task(User, 'create', {first: 'jill', age: 100}) + .task(User, 'create', {first: 'bob', age: 200}) + .task(User, 'create', {first: 'jan'}) + .task(User, 'create', {first: 'sam'}) + .task(User, 'create', {first: 'suzy'}) + .on('done', function() { + User.count({age: {gt: 99}}, function(err, count) { + assert.equal(count, 2); + done(); + }); + }); + }); + }); + }); -}); - - -} +};