From f9702b0acea233428503e66d5784625a6656504e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 1 Apr 2016 11:14:26 +0200 Subject: [PATCH] Use eslint with loopback config Drop jshint and jscs in favour of eslint. Fix style violations. While we are at this, reduce the max line length from 150 to 100. --- .eslintignore | 2 + .eslintrc | 10 + .jshintignore | 1 - .jshintrc | 34 --- Gruntfile.js | 104 ++++--- common/models/access-token.js | 6 +- common/models/acl.js | 39 +-- common/models/application.js | 5 +- common/models/change.js | 23 +- common/models/checkpoint.js | 7 +- common/models/email.js | 1 - common/models/role.js | 34 +-- common/models/scope.js | 2 +- common/models/user.js | 60 ++-- example/client-server/client.js | 2 +- example/client-server/models.js | 16 +- example/client-server/server.js | 8 +- example/colors/app.js | 10 +- example/context/app.js | 2 +- example/mobile-models/app.js | 49 ++-- example/replication/app.js | 74 ++--- example/simple-data-source/app.js | 12 +- index.js | 2 +- lib/access-context.js | 2 +- lib/application.js | 13 +- lib/builtin-models.js | 2 +- lib/connectors/mail.js | 4 +- lib/express-middleware.js | 2 +- lib/loopback.js | 14 +- lib/model.js | 141 +++++---- lib/persisted-model.js | 180 ++++++------ lib/registry.js | 5 +- lib/server-app.js | 2 +- package.json | 4 +- server/current-context.js | 1 - server/middleware/context.js | 2 +- server/middleware/status.js | 2 +- test/access-control.integration.js | 15 +- test/access-token.test.js | 36 +-- test/acl.test.js | 270 ++++++++++-------- test/app.test.js | 86 +++--- test/change-stream.test.js | 22 +- test/change.test.js | 74 +++-- test/checkpoint.test.js | 13 +- test/data-source.test.js | 17 +- test/e2e/remote-connector.e2e.js | 6 +- test/e2e/replication.e2e.js | 8 +- test/email.test.js | 29 +- test/error-handler.test.js | 6 +- test/fixtures/access-control/server/server.js | 2 +- test/fixtures/e2e/server/models.js | 2 +- .../user-integration-app/server/server.js | 2 +- test/geo-point.test.js | 16 +- test/helpers/loopback-testing-helper.js | 8 +- test/hidden-properties.test.js | 6 +- test/integration.test.js | 8 +- test/karma.conf.js | 16 +- test/loopback.test.js | 187 ++++++------ test/memory.test.js | 10 +- test/model.application.test.js | 44 +-- test/model.test.js | 109 ++++--- test/registries.test.js | 10 +- test/relations.integration.js | 137 ++++----- test/remote-connector.test.js | 13 +- test/remoting-coercion.test.js | 8 +- test/remoting.integration.js | 53 ++-- test/replication.rest.test.js | 42 +-- test/replication.test.js | 133 +++++---- test/rest.middleware.test.js | 110 +++---- test/role.test.js | 128 +++++---- test/support.js | 6 +- test/user.integration.js | 24 +- test/user.test.js | 224 ++++++++------- test/util/model-tests.js | 78 +++-- 74 files changed, 1397 insertions(+), 1438 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc delete mode 100644 .jshintignore delete mode 100644 .jshintrc diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..009af543 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +dist +coverage diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..f3fa72da --- /dev/null +++ b/.eslintrc @@ -0,0 +1,10 @@ +{ + "extends": "loopback", + "rules": { + "max-len": ["error", 100, 4, { + "ignoreComments": true, + "ignoreUrls": true, + "ignorePattern": "^\\s*var\\s.+=\\s*(require\\s*\\()|(/)" + }] + } +} diff --git a/.jshintignore b/.jshintignore deleted file mode 100644 index 3c3629e6..00000000 --- a/.jshintignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 34bede23..00000000 --- a/.jshintrc +++ /dev/null @@ -1,34 +0,0 @@ -{ - "node": true, - "camelcase": true, - "eqnull": true, - "indent": 2, - "undef": true, - "quotmark": "single", - "newcap": true, - "nonew": true, - "sub": true, - "laxcomma": true, - "laxbreak": true, - "globals": { - /* mocha */ - "after": true, - "afterEach": true, - "assert": true, - "before": true, - "beforeEach": true, - "context": 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/Gruntfile.js b/Gruntfile.js index 3df91996..068ab36f 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,6 +1,5 @@ /*global module:false*/ module.exports = function(grunt) { - // Do not report warnings from unit-tests exercising deprecated paths process.env.NO_DEPRECATION = 'loopback'; @@ -18,58 +17,59 @@ module.exports = function(grunt) { // Task configuration. uglify: { options: { - banner: '<%= banner %>' + banner: '<%= banner %>', }, dist: { files: { - 'dist/loopback.min.js': ['dist/loopback.js'] - } - } - }, - jshint: { - options: { - jshintrc: true + 'dist/loopback.min.js': ['dist/loopback.js'], + }, }, + }, + eslint: { gruntfile: { - src: 'Gruntfile.js' + src: 'Gruntfile.js', }, lib: { - src: ['lib/**/*.js'] + src: ['lib/**/*.js'], }, common: { - src: ['common/**/*.js'] + src: ['common/**/*.js'], }, browser: { - src: ['browser/**/*.js'] + src: ['browser/**/*.js'], }, server: { - src: ['server/**/*.js'] + src: ['server/**/*.js'], }, test: { - src: ['test/**/*.js'] - } - }, - jscs: { - gruntfile: 'Gruntfile.js', - lib: ['lib/**/*.js'], - common: ['common/**/*.js'], - server: ['server/**/*.js'], - browser: ['browser/**/*.js'], - test: ['test/**/*.js'] + src: ['test/**/*.js'], + }, }, watch: { gruntfile: { - files: '<%= jshint.gruntfile.src %>', - tasks: ['jshint:gruntfile'] + files: '<%= eslint.gruntfile.src %>', + tasks: ['eslint:gruntfile'], + }, + browser: { + files: ['<%= eslint.browser.src %>'], + tasks: ['eslint:browser'], + }, + common: { + files: ['<%= eslint.common.src %>'], + tasks: ['eslint:common'], }, lib: { - files: ['<%= jshint.lib.src %>'], - tasks: ['jshint:lib'] + files: ['<%= eslint.lib.src %>'], + tasks: ['eslint:lib'], + }, + server: { + files: ['<%= eslint.server.src %>'], + tasks: ['eslint:server'], }, test: { - files: ['<%= jshint.test.src %>'], - tasks: ['jshint:test'] - } + files: ['<%= eslint.test.src %>'], + tasks: ['eslint:test'], + }, }, browserify: { dist: { @@ -78,24 +78,24 @@ module.exports = function(grunt) { }, options: { ignore: ['nodemailer', 'passport', 'bcrypt'], - standalone: 'loopback' - } - } + standalone: 'loopback', + }, + }, }, mochaTest: { 'unit': { src: 'test/*.js', options: { reporter: 'dot', - } + }, }, 'unit-xml': { src: 'test/*.js', options: { reporter: 'xunit', - captureFile: 'xunit.xml' - } - } + captureFile: 'xunit.xml', + }, + }, }, karma: { 'unit-once': { @@ -109,7 +109,7 @@ module.exports = function(grunt) { // CI friendly test output junitReporter: { - outputFile: 'karma-xunit.xml' + outputFile: 'karma-xunit.xml', }, browserify: { @@ -117,8 +117,8 @@ module.exports = function(grunt) { // Fatal error: Maximum call stack size exceeded debug: false, // Disable watcher, grunt will exit after the first run - watch: false - } + watch: false, + }, }, unit: { configFile: 'test/karma.conf.js', @@ -134,7 +134,7 @@ module.exports = function(grunt) { // list of files / patterns to load in the browser files: [ 'test/e2e/remote-connector.e2e.js', - 'test/e2e/replication.e2e.js' + 'test/e2e/replication.e2e.js', ], // list of files to exclude @@ -171,7 +171,7 @@ module.exports = function(grunt) { // - PhantomJS // - IE (only Windows) browsers: [ - 'Chrome' + 'Chrome', ], // If browser does not capture in given timeout [ms], kill it @@ -190,7 +190,7 @@ module.exports = function(grunt) { 'passport-local', 'superagent', 'supertest', - 'bcrypt' + 'bcrypt', ], // transform: ['coffeeify'], // debug: true, @@ -199,19 +199,18 @@ module.exports = function(grunt) { }, // Add browserify to preprocessors - preprocessors: {'test/e2e/*': ['browserify']} - } - } - } + preprocessors: { 'test/e2e/*': ['browserify'] }, + }, + }, + }, }); // These plugins provide necessary tasks. grunt.loadNpmTasks('grunt-browserify'); grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-eslint'); grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-jscs'); grunt.loadNpmTasks('grunt-karma'); grunt.registerTask('e2e-server', function() { @@ -229,10 +228,9 @@ module.exports = function(grunt) { grunt.registerTask('default', ['browserify']); grunt.registerTask('test', [ - 'jscs', - 'jshint', + 'eslint', process.env.JENKINS_HOME ? 'mochaTest:unit-xml' : 'mochaTest:unit', - 'karma:unit-once']); + 'karma:unit-once']); // alias for sl-ci-run and `npm test` grunt.registerTask('mocha-and-karma', ['test']); diff --git a/common/models/access-token.js b/common/models/access-token.js index 27cf5206..3c66c939 100644 --- a/common/models/access-token.js +++ b/common/models/access-token.js @@ -27,7 +27,6 @@ var DEFAULT_TOKEN_LEN = 64; */ module.exports = function(AccessToken) { - // Workaround for https://github.com/strongloop/loopback/issues/292 AccessToken.definition.rawProperties.created.default = AccessToken.definition.properties.created.default = function() { @@ -42,7 +41,7 @@ module.exports = function(AccessToken) { * ``` */ - AccessToken.ANONYMOUS = new AccessToken({id: '$anonymous'}); + AccessToken.ANONYMOUS = new AccessToken({ id: '$anonymous' }); /** * Create a cryptographically random access token id. @@ -165,8 +164,7 @@ module.exports = function(AccessToken) { var headers = options.headers || []; var cookies = options.cookies || []; var i = 0; - var length; - var id; + var length, id; // https://github.com/strongloop/loopback/issues/1326 if (options.searchDefaultTokenKeys !== false) { diff --git a/common/models/acl.js b/common/models/acl.js index 2a7306b1..60af1a70 100644 --- a/common/models/acl.js +++ b/common/models/acl.js @@ -78,7 +78,6 @@ assert(Role, 'Role model must be defined before ACL model'); */ module.exports = function(ACL) { - ACL.ALL = AccessContext.ALL; ACL.DEFAULT = AccessContext.DEFAULT; // Not specified @@ -112,7 +111,8 @@ module.exports = function(ACL) { score = score * 4; var ruleValue = rule[props[i]] || ACL.ALL; var requestedValue = req[props[i]] || ACL.ALL; - var isMatchingMethodName = props[i] === 'property' && req.methodNames.indexOf(ruleValue) !== -1; + var isMatchingMethodName = props[i] === 'property' && + req.methodNames.indexOf(ruleValue) !== -1; var isMatchingAccessType = ruleValue === requestedValue; if (props[i] === 'accessType' && !isMatchingAccessType) { @@ -278,7 +278,7 @@ module.exports = function(ACL) { principalType: acl.principalType, principalId: acl.principalId, // TODO: Should it be a name? accessType: acl.accessType || ACL.ALL, - permission: acl.permission + permission: acl.permission, })); } }); @@ -300,7 +300,7 @@ module.exports = function(ACL) { principalType: acl.principalType, principalId: acl.principalId, accessType: acl.accessType, - permission: acl.permission + permission: acl.permission, })); }); } @@ -325,9 +325,10 @@ module.exports = function(ACL) { principalId = principalId.toString(); } property = property || ACL.ALL; - var propertyQuery = (property === ACL.ALL) ? undefined : {inq: [property, ACL.ALL]}; + var propertyQuery = (property === ACL.ALL) ? undefined : { inq: [property, ACL.ALL] }; accessType = accessType || ACL.ALL; - var accessTypeQuery = (accessType === ACL.ALL) ? undefined : {inq: [accessType, ACL.ALL, ACL.EXECUTE]}; + var accessTypeQuery = (accessType === ACL.ALL) ? undefined : + { inq: [accessType, ACL.ALL, ACL.EXECUTE] }; var req = new AccessRequest(model, property, accessType); @@ -345,8 +346,8 @@ module.exports = function(ACL) { } var self = this; - this.find({where: {principalType: principalType, principalId: principalId, - model: model, property: propertyQuery, accessType: accessTypeQuery}}, + this.find({ where: { principalType: principalType, principalId: principalId, + model: model, property: propertyQuery, accessType: accessTypeQuery }}, function(err, dynACLs) { if (err) { if (callback) callback(err); @@ -399,13 +400,13 @@ module.exports = function(ACL) { var modelName = context.modelName; var methodNames = context.methodNames; - var propertyQuery = (property === ACL.ALL) ? undefined : {inq: methodNames.concat([ACL.ALL])}; + var propertyQuery = (property === ACL.ALL) ? undefined : { inq: methodNames.concat([ACL.ALL]) }; var accessTypeQuery = (accessType === ACL.ALL) ? undefined : (accessType === ACL.REPLICATE) ? - {inq: [ACL.REPLICATE, ACL.WRITE, ACL.ALL]} : - {inq: [accessType, ACL.ALL]}; + { inq: [ACL.REPLICATE, ACL.WRITE, ACL.ALL] } : + { inq: [accessType, ACL.ALL] }; var req = new AccessRequest(modelName, property, accessType, ACL.DEFAULT, methodNames); @@ -414,8 +415,8 @@ module.exports = function(ACL) { var self = this; var roleModel = registry.getModelByType(Role); - this.find({where: {model: model.modelName, property: propertyQuery, - accessType: accessTypeQuery}}, function(err, acls) { + this.find({ where: { model: model.modelName, property: propertyQuery, + accessType: accessTypeQuery }}, function(err, acls) { if (err) { if (callback) callback(err); return; @@ -485,7 +486,7 @@ module.exports = function(ACL) { model: model, property: method, method: method, - modelId: modelId + modelId: modelId, }); this.checkAccessForContext(context, function(err, access) { @@ -518,15 +519,15 @@ module.exports = function(ACL) { this.resolveRelatedModels(); switch (type) { case ACL.ROLE: - this.roleModel.findOne({where: {or: [{name: id}, {id: id}]}}, cb); + this.roleModel.findOne({ where: { or: [{ name: id }, { id: id }] }}, cb); break; case ACL.USER: this.userModel.findOne( - {where: {or: [{username: id}, {email: id}, {id: id}]}}, cb); + { where: { or: [{ username: id }, { email: id }, { id: id }] }}, cb); break; case ACL.APP: this.applicationModel.findOne( - {where: {or: [{name: id}, {email: id}, {id: id}]}}, cb); + { where: { or: [{ name: id }, { email: id }, { id: id }] }}, cb); break; default: process.nextTick(function() { @@ -559,8 +560,8 @@ module.exports = function(ACL) { where: { roleId: role.id, principalType: principalType, - principalId: String(principalId) - } + principalId: String(principalId), + }, }, function(err, result) { if (err) return cb(err); return cb(null, !!result); diff --git a/common/models/application.js b/common/models/application.js index 0b609797..75204f9f 100644 --- a/common/models/application.js +++ b/common/models/application.js @@ -65,7 +65,6 @@ function generateKey(hmacKey, algorithm, encoding) { */ module.exports = function(Application) { - // Workaround for https://github.com/strongloop/loopback/issues/292 Application.definition.rawProperties.created.default = Application.definition.properties.created.default = function() { @@ -122,7 +121,7 @@ module.exports = function(Application) { } cb = cb || utils.createPromiseCallback(); - var props = {owner: owner, name: name}; + var props = { owner: owner, name: name }; for (var p in options) { if (!(p in props)) { props[p] = options[p]; @@ -195,7 +194,7 @@ module.exports = function(Application) { if (app[keyNames[i]] === key) { result = { application: app, - keyType: keyNames[i] + keyType: keyNames[i], }; break; } diff --git a/common/models/change.js b/common/models/change.js index 3b347ec5..8ef6064a 100644 --- a/common/models/change.js +++ b/common/models/change.js @@ -6,7 +6,7 @@ var PersistedModel = require('../../lib/loopback').PersistedModel; var loopback = require('../../lib/loopback'); var utils = require('../../lib/utils'); var crypto = require('crypto'); -var CJSON = {stringify: require('canonical-json')}; +var CJSON = { stringify: require('canonical-json') }; var async = require('async'); var assert = require('assert'); var debug = require('debug')('loopback:change'); @@ -31,7 +31,6 @@ var deprecate = require('depd')('loopback'); */ module.exports = function(Change) { - /*! * Constants */ @@ -154,7 +153,7 @@ module.exports = function(Change) { var ch = new Change({ id: id, modelName: modelName, - modelId: modelId + modelId: modelId, }); ch.debug('creating change'); Change.updateOrCreate(ch, callback); @@ -400,7 +399,7 @@ module.exports = function(Change) { callback = callback || utils.createPromiseCallback(); if (!Array.isArray(remoteChanges) || remoteChanges.length === 0) { - callback(null, {deltas: [], conflicts: []}); + callback(null, { deltas: [], conflicts: [] }); return callback.promise; } var remoteChangeIndex = {}; @@ -415,8 +414,8 @@ module.exports = function(Change) { this.find({ where: { modelName: modelName, - modelId: {inq: modelIds} - } + modelId: { inq: modelIds }, + }, }, function(err, allLocalChanges) { if (err) return callback(err); var deltas = []; @@ -462,7 +461,7 @@ module.exports = function(Change) { callback(null, { deltas: deltas, - conflicts: conflicts + conflicts: conflicts, }); }); return callback.promise; @@ -586,12 +585,11 @@ module.exports = function(Change) { var conflict = this; var SourceModel = this.SourceModel; var TargetModel = this.TargetModel; - var source; - var target; + var source, target; async.parallel([ getSourceModel, - getTargetModel + getTargetModel, ], done); function getSourceModel(cb) { @@ -627,12 +625,11 @@ module.exports = function(Change) { Conflict.prototype.changes = function(cb) { var conflict = this; - var sourceChange; - var targetChange; + var sourceChange, targetChange; async.parallel([ getSourceChange, - getTargetChange + getTargetChange, ], done); function getSourceChange(cb) { diff --git a/common/models/checkpoint.js b/common/models/checkpoint.js index 59cc33de..45eb65d0 100644 --- a/common/models/checkpoint.js +++ b/common/models/checkpoint.js @@ -16,7 +16,6 @@ var assert = require('assert'); */ module.exports = function(Checkpoint) { - // Workaround for https://github.com/strongloop/loopback/issues/292 Checkpoint.definition.rawProperties.time.default = Checkpoint.definition.properties.time.default = function() { @@ -37,8 +36,8 @@ module.exports = function(Checkpoint) { }; Checkpoint._getSingleton = function(cb) { - var query = {limit: 1}; // match all instances, return only one - var initialData = {seq: 1}; + var query = { limit: 1 }; // match all instances, return only one + var initialData = { seq: 1 }; this.findOrCreate(query, initialData, cb); }; @@ -55,7 +54,7 @@ module.exports = function(Checkpoint) { var originalSeq = cp.seq; cp.seq++; // Update the checkpoint but only if it was not changed under our hands - Checkpoint.updateAll({id: cp.id, seq: originalSeq}, {seq: cp.seq}, function(err, info) { + Checkpoint.updateAll({ id: cp.id, seq: originalSeq }, { seq: cp.seq }, function(err, info) { if (err) return cb(err); // possible outcomes // 1) seq was updated to seq+1 - exactly what we wanted! diff --git a/common/models/email.js b/common/models/email.js index f7362802..f69eaf47 100644 --- a/common/models/email.js +++ b/common/models/email.js @@ -11,7 +11,6 @@ */ module.exports = function(Email) { - /** * Send an email with the given `options`. * diff --git a/common/models/role.js b/common/models/role.js index a176fec1..87bdee06 100644 --- a/common/models/role.js +++ b/common/models/role.js @@ -15,18 +15,17 @@ assert(RoleMapping, 'RoleMapping model must be defined before Role model'); * @header Role object */ module.exports = function(Role) { - // Workaround for https://github.com/strongloop/loopback/issues/292 Role.definition.rawProperties.created.default = Role.definition.properties.created.default = function() { - return new Date(); - }; + return new Date(); + }; // Workaround for https://github.com/strongloop/loopback/issues/292 Role.definition.rawProperties.modified.default = Role.definition.properties.modified.default = function() { - return new Date(); - }; + return new Date(); + }; Role.resolveRelatedModels = function() { if (!this.userModel) { @@ -39,7 +38,6 @@ module.exports = function(Role) { // Set up the connection to users/applications/roles once the model Role.once('dataSourceAttached', function(roleModel) { - ['users', 'applications', 'roles'].forEach(function(rel) { /** * Fetch all users assigned to this role @@ -64,14 +62,14 @@ module.exports = function(Role) { var relsToModels = { users: roleModel.userModel, applications: roleModel.applicationModel, - roles: roleModel + roles: roleModel, }; var ACL = loopback.ACL; var relsToTypes = { users: ACL.USER, applications: ACL.APP, - roles: ACL.ROLE + roles: ACL.ROLE, }; var model = relsToModels[rel]; @@ -94,7 +92,7 @@ module.exports = function(Role) { } roleModel.roleMappingModel.find({ - where: {roleId: this.id, principalType: principalType} + where: { roleId: this.id, principalType: principalType }, }, function(err, mappings) { var ids; if (err) { @@ -104,13 +102,12 @@ module.exports = function(Role) { return m.principalId; }); query.where = query.where || {}; - query.where.id = {inq: ids}; + query.where.id = { inq: ids }; model.find(query, function(err, models) { callback(err, models); }); }); } - }); // Special roles @@ -305,7 +302,6 @@ module.exports = function(Role) { } var inRole = context.principals.some(function(p) { - var principalType = p.type || undefined; var principalId = p.id || undefined; @@ -322,7 +318,7 @@ module.exports = function(Role) { } var roleMappingModel = this.roleMappingModel; - this.findOne({where: {name: role}}, function(err, result) { + this.findOne({ where: { name: role }}, function(err, result) { if (err) { if (callback) callback(err); return; @@ -338,14 +334,15 @@ module.exports = function(Role) { var principalType = p.type || undefined; var principalId = p.id || undefined; var roleId = result.id.toString(); + var principalIdIsString = typeof principalId === 'string'; - if (principalId !== null && principalId !== undefined && (typeof principalId !== 'string')) { + if (principalId !== null && principalId !== undefined && !principalIdIsString) { principalId = principalId.toString(); } if (principalType && principalId) { - roleMappingModel.findOne({where: {roleId: roleId, - principalType: principalType, principalId: principalId}}, + roleMappingModel.findOne({ where: { roleId: roleId, + principalType: principalType, principalId: principalId }}, function(err, result) { debug('Role mapping found: %j', result); done(!err && result); // The only arg is the result @@ -360,7 +357,6 @@ module.exports = function(Role) { if (callback) callback(null, inRole); }); }); - }; /** @@ -421,8 +417,8 @@ module.exports = function(Role) { if (principalType && principalId) { // Please find() treat undefined matches all values inRoleTasks.push(function(done) { - roleMappingModel.find({where: {principalType: principalType, - principalId: principalId}}, function(err, mappings) { + roleMappingModel.find({ where: { principalType: principalType, + principalId: principalId }}, function(err, mappings) { debug('Role mappings found: %s %j', err, mappings); if (err) { if (done) done(err); diff --git a/common/models/scope.js b/common/models/scope.js index 3c713b53..5509d9bc 100644 --- a/common/models/scope.js +++ b/common/models/scope.js @@ -36,7 +36,7 @@ module.exports = function(Scope) { assert(aclModel, 'ACL model must be defined before Scope.checkPermission is called'); - this.findOne({where: {name: scope}}, function(err, scope) { + this.findOne({ where: { name: scope }}, function(err, scope) { if (err) { if (callback) callback(err); } else { diff --git a/common/models/user.js b/common/models/user.js index 6032f1af..2889bbd1 100644 --- a/common/models/user.js +++ b/common/models/user.js @@ -69,7 +69,6 @@ var debug = require('debug')('loopback:user'); */ module.exports = function(User) { - /** * Create access token for the logged in user. This method can be overridden to * customize how access tokens are generated @@ -99,7 +98,7 @@ module.exports = function(User) { var userModel = this.constructor; ttl = Math.min(ttl || userModel.settings.ttl, userModel.settings.maxTTL); this.accessTokens.create({ - ttl: ttl + ttl: ttl, }, cb); return cb.promise; }; @@ -216,7 +215,7 @@ module.exports = function(User) { return fn.promise; } - self.findOne({where: query}, function(err, user) { + self.findOne({ where: query }, function(err, user) { var defaultError = new Error('login failed'); defaultError.statusCode = 401; defaultError.code = 'LOGIN_FAILED'; @@ -369,11 +368,14 @@ module.exports = function(User) { assert(typeof options === 'object', 'options required when calling user.verify()'); assert(options.type, 'You must supply a verification type (options.type)'); assert(options.type === 'email', 'Unsupported verification type'); - assert(options.to || this.email, 'Must include options.to when calling user.verify() or the user must have an email property'); + assert(options.to || this.email, + 'Must include options.to when calling user.verify() ' + + 'or the user must have an email property'); assert(options.from, 'Must include options.from when calling user.verify()'); options.redirect = options.redirect || '/'; - options.template = path.resolve(options.template || path.join(__dirname, '..', '..', 'templates', 'verify.ejs')); + var defaultTemplate = path.join(__dirname, '..', '..', 'templates', 'verify.ejs'); + options.template = path.resolve(options.template || defaultTemplate); options.user = this; options.protocol = options.protocol || 'http'; @@ -423,7 +425,8 @@ module.exports = function(User) { function sendEmail(user) { options.verifyHref += '&token=' + user.verificationToken; - options.text = options.text || 'Please verify your email by opening this link in a web browser:\n\t{href}'; + options.text = options.text || 'Please verify your email by opening ' + + 'this link in a web browser:\n\t{href}'; options.text = options.text.replace('{href}', options.verifyHref); @@ -440,7 +443,7 @@ module.exports = function(User) { if (err) { fn(err); } else { - fn(null, {email: email, token: user.verificationToken, uid: user.id}); + fn(null, { email: email, token: user.verificationToken, uid: user.id }); } }); } @@ -531,7 +534,7 @@ module.exports = function(User) { return cb.promise; } - UserModel.findOne({ where: {email: options.email} }, function(err, user) { + UserModel.findOne({ where: { email: options.email }}, function(err, user) { if (err) { return cb(err); } @@ -543,7 +546,7 @@ module.exports = function(User) { } // create a short lived access token for temp login to change password // TODO(ritch) - eventually this should only allow password change - user.accessTokens.create({ttl: ttl}, function(err, accessToken) { + user.accessTokens.create({ ttl: ttl }, function(err, accessToken) { if (err) { return cb(err); } @@ -551,7 +554,7 @@ module.exports = function(User) { UserModel.emit('resetPasswordRequest', { email: options.email, accessToken: accessToken, - user: user + user: user, }); }); }); @@ -633,10 +636,10 @@ module.exports = function(User) { { description: 'Login a user with username/email and password.', accepts: [ - {arg: 'credentials', type: 'object', required: true, http: {source: 'body'}}, - {arg: 'include', type: ['string'], http: {source: 'query' }, + { arg: 'credentials', type: 'object', required: true, http: { source: 'body' }}, + { arg: 'include', type: ['string'], http: { source: 'query' }, description: 'Related objects to include in the response. ' + - 'See the description of return value for more details.'} + 'See the description of return value for more details.' }, ], returns: { arg: 'accessToken', type: 'object', root: true, @@ -644,9 +647,9 @@ module.exports = function(User) { 'The response body contains properties of the AccessToken created on login.\n' + 'Depending on the value of `include` parameter, the body may contain ' + 'additional properties:\n\n' + - ' - `user` - `{User}` - Data of the currently logged in user. (`include=user`)\n\n' + ' - `user` - `{User}` - Data of the currently logged in user. (`include=user`)\n\n', }, - http: {verb: 'post'} + http: { verb: 'post' }, } ); @@ -655,17 +658,17 @@ module.exports = function(User) { { description: 'Logout a user with access token.', accepts: [ - {arg: 'access_token', type: 'string', required: true, http: function(ctx) { + { arg: 'access_token', type: 'string', required: true, http: function(ctx) { var req = ctx && ctx.req; var accessToken = req && req.accessToken; var tokenID = accessToken && accessToken.id; return tokenID; }, description: 'Do not supply this argument, it is automatically extracted ' + - 'from request headers.' - } + 'from request headers.', + }, ], - http: {verb: 'all'} + http: { verb: 'all' }, } ); @@ -674,11 +677,11 @@ module.exports = function(User) { { description: 'Confirm a user registration with email verification token.', accepts: [ - {arg: 'uid', type: 'string', required: true}, - {arg: 'token', type: 'string', required: true}, - {arg: 'redirect', type: 'string'} + { arg: 'uid', type: 'string', required: true }, + { arg: 'token', type: 'string', required: true }, + { arg: 'redirect', type: 'string' }, ], - http: {verb: 'get', path: '/confirm'} + http: { verb: 'get', path: '/confirm' }, } ); @@ -687,9 +690,9 @@ module.exports = function(User) { { description: 'Reset password for a user with email.', accepts: [ - {arg: 'options', type: 'object', required: true, http: {source: 'body'}} + { arg: 'options', type: 'object', required: true, http: { source: 'body' }}, ], - http: {verb: 'post', path: '/reset'} + http: { verb: 'post', path: '/reset' }, } ); @@ -714,12 +717,12 @@ module.exports = function(User) { // email validation regex var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - UserModel.validatesFormatOf('email', {with: re, message: 'Must provide a valid email'}); + UserModel.validatesFormatOf('email', { with: re, message: 'Must provide a valid email' }); // FIXME: We need to add support for uniqueness of composite keys in juggler if (!(UserModel.settings.realmRequired || UserModel.settings.realmDelimiter)) { - UserModel.validatesUniquenessOf('email', {message: 'Email already exists'}); - UserModel.validatesUniquenessOf('username', {message: 'User already exists'}); + UserModel.validatesUniquenessOf('email', { message: 'Email already exists' }); + UserModel.validatesUniquenessOf('username', { message: 'User already exists' }); } return UserModel; @@ -730,5 +733,4 @@ module.exports = function(User) { */ User.setup(); - }; diff --git a/example/client-server/client.js b/example/client-server/client.js index 436e266b..df8c451b 100644 --- a/example/client-server/client.js +++ b/example/client-server/client.js @@ -3,7 +3,7 @@ var client = loopback(); var CartItem = require('./models').CartItem; var remote = loopback.createDataSource({ connector: loopback.Remote, - url: 'http://localhost:3000' + url: 'http://localhost:3000', }); client.model(CartItem); diff --git a/example/client-server/models.js b/example/client-server/models.js index 34d5c8ba..b1ac634f 100644 --- a/example/client-server/models.js +++ b/example/client-server/models.js @@ -1,15 +1,15 @@ var loopback = require('../../'); var CartItem = exports.CartItem = loopback.PersistedModel.extend('CartItem', { - tax: {type: Number, default: 0.1}, + tax: { type: Number, default: 0.1 }, price: Number, item: String, - qty: {type: Number, default: 0}, - cartId: Number + qty: { type: Number, default: 0 }, + cartId: Number, }); CartItem.sum = function(cartId, callback) { - this.find({where: {cartId: 1}}, function(err, items) { + this.find({ where: { cartId: 1 }}, function(err, items) { var total = items .map(function(item) { return item.total(); @@ -20,15 +20,15 @@ CartItem.sum = function(cartId, callback) { callback(null, total); }); -} +}; CartItem.remoteMethod('sum', { - accepts: {arg: 'cartId', type: 'number'}, - returns: {arg: 'total', type: 'number'} + accepts: { arg: 'cartId', type: 'number' }, + returns: { arg: 'total', type: 'number' }, } ); CartItem.prototype.total = function() { return this.price * this.qty * 1 + this.tax; -} +}; diff --git a/example/client-server/server.js b/example/client-server/server.js index 7e466a56..5e9bf17e 100644 --- a/example/client-server/server.js +++ b/example/client-server/server.js @@ -2,7 +2,7 @@ var loopback = require('../../'); var server = module.exports = loopback(); var CartItem = require('./models').CartItem; var memory = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); server.use(loopback.rest()); @@ -12,9 +12,9 @@ CartItem.attachTo(memory); // test data CartItem.create([ - {item: 'red hat', qty: 6, price: 19.99, cartId: 1}, - {item: 'green shirt', qty: 1, price: 14.99, cartId: 1}, - {item: 'orange pants', qty: 58, price: 9.99, cartId: 1} + { item: 'red hat', qty: 6, price: 19.99, cartId: 1 }, + { item: 'green shirt', qty: 1, price: 14.99, cartId: 1 }, + { item: 'orange pants', qty: 58, price: 9.99, cartId: 1 }, ]); CartItem.sum(1, function(err, total) { diff --git a/example/colors/app.js b/example/colors/app.js index e182f926..f43ab366 100644 --- a/example/colors/app.js +++ b/example/colors/app.js @@ -4,16 +4,16 @@ var app = loopback(); app.use(loopback.rest()); var schema = { - name: String + name: String, }; var Color = app.model('color', schema); -app.dataSource('db', {adapter: 'memory'}).attach(Color); +app.dataSource('db', { adapter: 'memory' }).attach(Color); -Color.create({name: 'red'}); -Color.create({name: 'green'}); -Color.create({name: 'blue'}); +Color.create({ name: 'red' }); +Color.create({ name: 'green' }); +Color.create({ name: 'blue' }); app.listen(3000); diff --git a/example/context/app.js b/example/context/app.js index 12cedc07..1ae5d6c7 100644 --- a/example/context/app.js +++ b/example/context/app.js @@ -14,7 +14,7 @@ app.use(function saveHostToContext(req, res, next) { app.use(loopback.rest()); var Color = loopback.createModel('color', { 'name': String }); -Color.beforeRemote('**', function (ctx, unused, next) { +Color.beforeRemote('**', function(ctx, unused, next) { // Inside LoopBack code, you can read the property from the context var ns = loopback.getCurrentContext(); console.log('Request to host', ns && ns.get('host')); diff --git a/example/mobile-models/app.js b/example/mobile-models/app.js index e7e3c582..bfb7e245 100644 --- a/example/mobile-models/app.js +++ b/example/mobile-models/app.js @@ -5,41 +5,42 @@ var app = loopback(); app.use(loopback.rest()); -var dataSource = loopback.createDataSource('db', {connector: loopback.Memory}); +var dataSource = loopback.createDataSource('db', { connector: loopback.Memory }); var Application = models.Application(dataSource); app.model(Application); -var data = {pushSettings: [ - { "platform": "apns", - "apns": { - "pushOptions": { - "gateway": "gateway.sandbox.push.apple.com", - "cert": "credentials/apns_cert_dev.pem", - "key": "credentials/apns_key_dev.pem" - }, +var data = { pushSettings: [ + { 'platform': 'apns', + 'apns': { + 'pushOptions': { + 'gateway': 'gateway.sandbox.push.apple.com', + 'cert': 'credentials/apns_cert_dev.pem', + 'key': 'credentials/apns_key_dev.pem', + }, - "feedbackOptions": { - "gateway": "feedback.sandbox.push.apple.com", - "cert": "credentials/apns_cert_dev.pem", - "key": "credentials/apns_key_dev.pem", - "batchFeedback": true, - "interval": 300 - } - }} -]} + 'feedbackOptions': { + 'gateway': 'feedback.sandbox.push.apple.com', + 'cert': 'credentials/apns_cert_dev.pem', + 'key': 'credentials/apns_key_dev.pem', + 'batchFeedback': true, + 'interval': 300, + }, + }}, +] }; Application.create(data, function(err, data) { - console.log('Created: ', data.toObject()); + console.log('Created: ', data.toObject()); }); -Application.register('rfeng', 'MyApp', {description: 'My first mobile application'}, function (err, result) { +Application.register('rfeng', 'MyApp', { description: 'My first mobile application' }, +function(err, result) { + console.log(result.toObject()); + + result.resetKeys(function(err, result) { console.log(result.toObject()); - - result.resetKeys(function (err, result) { - console.log(result.toObject()); - }); + }); }); diff --git a/example/replication/app.js b/example/replication/app.js index ab6e6987..98d0f2f6 100644 --- a/example/replication/app.js +++ b/example/replication/app.js @@ -1,8 +1,8 @@ var loopback = require('../../'); var app = loopback(); -var db = app.dataSource('db', {connector: loopback.Memory}); -var Color = app.model('color', {dataSource: 'db', options: {trackChanges: true}}); -var Color2 = app.model('color2', {dataSource: 'db', options: {trackChanges: true}}); +var db = app.dataSource('db', { connector: loopback.Memory }); +var Color = app.model('color', { dataSource: 'db', options: { trackChanges: true }}); +var Color2 = app.model('color2', { dataSource: 'db', options: { trackChanges: true }}); var target = Color2; var source = Color; var SPEED = process.env.SPEED || 100; @@ -12,60 +12,60 @@ var steps = [ createSomeInitialSourceData, - replicateSourceToTarget, - list.bind(this, source, 'current SOURCE data'), - list.bind(this, target, 'current TARGET data'), + replicateSourceToTarget, + list.bind(this, source, 'current SOURCE data'), + list.bind(this, target, 'current TARGET data'), updateSomeTargetData, - replicateSourceToTarget, - list.bind(this, source, 'current SOURCE data '), - list.bind(this, target, 'current TARGET data (includes conflicting update)'), + replicateSourceToTarget, + list.bind(this, source, 'current SOURCE data '), + list.bind(this, target, 'current TARGET data (includes conflicting update)'), updateSomeSourceDataCausingAConflict, - replicateSourceToTarget, - list.bind(this, source, 'current SOURCE data (now has a conflict)'), - list.bind(this, target, 'current TARGET data (includes conflicting update)'), + replicateSourceToTarget, + list.bind(this, source, 'current SOURCE data (now has a conflict)'), + list.bind(this, target, 'current TARGET data (includes conflicting update)'), resolveAllConflicts, - replicateSourceToTarget, - list.bind(this, source, 'current SOURCE data (conflict resolved)'), - list.bind(this, target, 'current TARGET data (conflict resolved)'), + replicateSourceToTarget, + list.bind(this, source, 'current SOURCE data (conflict resolved)'), + list.bind(this, target, 'current TARGET data (conflict resolved)'), createMoreSourceData, - replicateSourceToTarget, - list.bind(this, source, 'current SOURCE data'), - list.bind(this, target, 'current TARGET data'), + replicateSourceToTarget, + list.bind(this, source, 'current SOURCE data'), + list.bind(this, target, 'current TARGET data'), createEvenMoreSourceData, - replicateSourceToTarget, - list.bind(this, source, 'current SOURCE data'), - list.bind(this, target, 'current TARGET data'), + replicateSourceToTarget, + list.bind(this, source, 'current SOURCE data'), + list.bind(this, target, 'current TARGET data'), deleteAllSourceData, - replicateSourceToTarget, - list.bind(this, source, 'current SOURCE data (empty)'), - list.bind(this, target, 'current TARGET data (empty)'), + replicateSourceToTarget, + list.bind(this, source, 'current SOURCE data (empty)'), + list.bind(this, target, 'current TARGET data (empty)'), createSomeNewSourceData, - replicateSourceToTarget, - list.bind(this, source, 'current SOURCE data'), - list.bind(this, target, 'current TARGET data') + replicateSourceToTarget, + list.bind(this, source, 'current SOURCE data'), + list.bind(this, target, 'current TARGET data'), ]; run(steps); function createSomeInitialSourceData() { Color.create([ - {name: 'red'}, - {name: 'blue'}, - {name: 'green'} + { name: 'red' }, + { name: 'blue' }, + { name: 'green' }, ]); } @@ -76,7 +76,7 @@ function replicateSourceToTarget() { } function resolveAllConflicts() { - if(conflicts.length) { + if (conflicts.length) { conflicts.forEach(function(conflict) { conflict.resolve(); }); @@ -91,11 +91,11 @@ function updateSomeTargetData() { } function createMoreSourceData() { - Color.create({name: 'orange'}); + Color.create({ name: 'orange' }); } function createEvenMoreSourceData() { - Color.create({name: 'black'}); + Color.create({ name: 'black' }); } function updateSomeSourceDataCausingAConflict() { @@ -111,9 +111,9 @@ function deleteAllSourceData() { function createSomeNewSourceData() { Color.create([ - {name: 'violet'}, - {name: 'amber'}, - {name: 'olive'} + { name: 'violet' }, + { name: 'amber' }, + { name: 'olive' }, ]); } @@ -130,7 +130,7 @@ function list(model, msg) { function run(steps) { setInterval(function() { var step = steps.shift(); - if(step) { + if (step) { console.log(step.name); step(); } diff --git a/example/simple-data-source/app.js b/example/simple-data-source/app.js index 3964df77..f0a8c135 100644 --- a/example/simple-data-source/app.js +++ b/example/simple-data-source/app.js @@ -4,17 +4,17 @@ var app = loopback(); app.use(loopback.rest()); -var dataSource = app.dataSource('db', {adapter: 'memory'}); +var dataSource = app.dataSource('db', { adapter: 'memory' }); var Color = dataSource.define('color', { - 'name': String + 'name': String, }); -Color.create({name: 'red'}); -Color.create({name: 'green'}); -Color.create({name: 'blue'}); +Color.create({ name: 'red' }); +Color.create({ name: 'green' }); +Color.create({ name: 'blue' }); -Color.all(function () { +Color.all(function() { console.log(arguments); }); diff --git a/index.js b/index.js index 1512239a..2209e642 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ /** * loopback ~ public api */ - + var loopback = module.exports = require('./lib/loopback'); var datasourceJuggler = require('loopback-datasource-juggler'); diff --git a/lib/access-context.js b/lib/access-context.js index 75ec5016..cb606f5d 100644 --- a/lib/access-context.js +++ b/lib/access-context.js @@ -91,7 +91,7 @@ AccessContext.permissionOrder = { ALLOW: 1, ALARM: 2, AUDIT: 3, - DENY: 4 + DENY: 4, }; /** diff --git a/lib/application.js b/lib/application.js index dd5fdb73..44e35b1d 100644 --- a/lib/application.js +++ b/lib/application.js @@ -326,7 +326,7 @@ app.enableAuth = function(options) { app.model(Model, { dataSource: options.dataSource, - public: m === 'User' + public: m === 'User', }); }); } @@ -365,20 +365,19 @@ app.enableAuth = function(options) { } else if (allowed) { next(); } else { - var messages = { 403: { message: 'Access Denied', - code: 'ACCESS_DENIED' + code: 'ACCESS_DENIED', }, 404: { message: ('could not find ' + modelName + ' with id ' + modelId), - code: 'MODEL_NOT_FOUND' + code: 'MODEL_NOT_FOUND', }, 401: { message: 'Authorization Required', - code: 'AUTHORIZATION_REQUIRED' - } + code: 'AUTHORIZATION_REQUIRED', + }, }; var e = new Error(messages[errStatusCode].message || messages[403].message); @@ -480,7 +479,7 @@ function setSharedMethodSharedProperties(model, app, modelConfigs) { }); // set sharedMethod.shared using the merged settings - var sharedMethods = model.sharedClass.methods({includeDisabled: true}); + var sharedMethods = model.sharedClass.methods({ includeDisabled: true }); sharedMethods.forEach(function(sharedMethod) { // use the specific setting if it exists var hasSpecificSetting = settings.hasOwnProperty(sharedMethod.name); diff --git a/lib/builtin-models.js b/lib/builtin-models.js index 78bf6399..74443333 100644 --- a/lib/builtin-models.js +++ b/lib/builtin-models.js @@ -47,7 +47,7 @@ module.exports = function(registry) { var dataSourceTypes = { DB: 'db', - MAIL: 'mail' + MAIL: 'mail', }; registry.Email.autoAttach = dataSourceTypes.MAIL; diff --git a/lib/connectors/mail.js b/lib/connectors/mail.js index a36984c3..d4b01939 100644 --- a/lib/connectors/mail.js +++ b/lib/connectors/mail.js @@ -18,7 +18,6 @@ module.exports = MailConnector; */ function MailConnector(settings) { - assert(typeof settings === 'object', 'cannot initialize MailConnector without a settings object'); var transports = settings.transports; @@ -156,7 +155,8 @@ Mailer.send = function(options, fn) { } if (transport) { - assert(transport.sendMail, 'You must supply an Email.settings.transports containing a valid transport'); + assert(transport.sendMail, + 'You must supply an Email.settings.transports containing a valid transport'); transport.sendMail(options, fn); } else { console.warn('Warning: No email transport specified for sending email.' + diff --git a/lib/express-middleware.js b/lib/express-middleware.js index f058a74a..a27a7daf 100644 --- a/lib/express-middleware.js +++ b/lib/express-middleware.js @@ -32,7 +32,7 @@ var middlewareModules = { 'favicon': 'serve-favicon', 'directory': 'serve-index', // 'static': 'serve-static', - 'vhost': 'vhost' + 'vhost': 'vhost', }; middlewares.bodyParser = safeRequire('body-parser'); diff --git a/lib/loopback.js b/lib/loopback.js index fad265a0..08bcec3a 100644 --- a/lib/loopback.js +++ b/lib/loopback.js @@ -52,17 +52,17 @@ loopback.registry = new Registry(); Object.defineProperties(loopback, { Model: { - get: function() { return this.registry.getModel('Model'); } + get: function() { return this.registry.getModel('Model'); }, }, PersistedModel: { - get: function() { return this.registry.getModel('PersistedModel'); } + get: function() { return this.registry.getModel('PersistedModel'); }, }, defaultDataSources: { - get: function() { return this.registry.defaultDataSources; } + get: function() { return this.registry.defaultDataSources; }, }, modelBuilder: { - get: function() { return this.registry.modelBuilder; } - } + get: function() { return this.registry.modelBuilder; }, + }, }); /*! @@ -196,7 +196,7 @@ loopback.remoteMethod = function(fn, options) { fn[key] = options[key]; }); } - fn.http = fn.http || {verb: 'get'}; + fn.http = fn.http || { verb: 'get' }; }; /** @@ -213,7 +213,7 @@ loopback.template = function(file) { var templates = this._templates || (this._templates = {}); var str = templates[file] || (templates[file] = fs.readFileSync(file, 'utf8')); return ejs.compile(str, { - filename: file + filename: file, }); }; diff --git a/lib/model.js b/lib/model.js index b766ded3..0b2fd1f4 100644 --- a/lib/model.js +++ b/lib/model.js @@ -7,7 +7,6 @@ var SharedClass = require('strong-remoting').SharedClass; var extend = require('util')._extend; module.exports = function(registry) { - /** * The base class for **all models**. * @@ -176,16 +175,16 @@ module.exports = function(registry) { var idDesc = ModelCtor.modelName + ' id'; ModelCtor.sharedCtor.accepts = [ - {arg: 'id', type: 'any', required: true, http: {source: 'path'}, - description: idDesc} + { arg: 'id', type: 'any', required: true, http: { source: 'path' }, + description: idDesc }, // {arg: 'instance', type: 'object', http: {source: 'body'}} ]; ModelCtor.sharedCtor.http = [ - {path: '/:id'} + { path: '/:id' }, ]; - ModelCtor.sharedCtor.returns = {root: true}; + ModelCtor.sharedCtor.returns = { root: true }; // before remote hook ModelCtor.beforeRemote = function(name, fn) { @@ -227,7 +226,6 @@ module.exports = function(registry) { // resolve relation functions sharedClass.resolve(function resolver(define) { - var relations = ModelCtor.relations || {}; // get the relations @@ -250,9 +248,11 @@ module.exports = function(registry) { // handle scopes var scopes = ModelCtor.scopes || {}; + /* eslint-disable one-var */ for (var scopeName in scopes) { ModelCtor.scopeRemoting(scopeName, scopes[scopeName], define); } + /* eslint-enable one-var */ }); return ModelCtor; @@ -307,7 +307,7 @@ module.exports = function(registry) { sharedMethod: sharedMethod, modelId: modelId, accessType: this._getAccessTypeForMethod(sharedMethod), - remotingContext: ctx + remotingContext: ctx, }, function(err, accessRequest) { if (err) return callback(err); callback(null, accessRequest.isAllowed()); @@ -323,7 +323,7 @@ module.exports = function(registry) { Model._getAccessTypeForMethod = function(method) { if (typeof method === 'string') { - method = {name: method}; + method = { name: method }; } assert( typeof method === 'object', @@ -353,7 +353,7 @@ module.exports = function(registry) { } switch (method.name) { - case'create': + case 'create': return ACL.WRITE; case 'updateOrCreate': return ACL.WRITE; @@ -442,11 +442,11 @@ module.exports = function(registry) { var pathName = (relation.options.http && relation.options.http.path) || relationName; define('__get__' + relationName, { isStatic: false, - http: {verb: 'get', path: '/' + pathName}, - accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}}, + http: { verb: 'get', path: '/' + pathName }, + accepts: { arg: 'refresh', type: 'boolean', http: { source: 'query' }}, accessType: 'READ', description: 'Fetches belongsTo relation ' + relationName + '.', - returns: {arg: relationName, type: modelName, root: true} + returns: { arg: relationName, type: modelName, root: true }, }, fn); }; @@ -467,37 +467,37 @@ module.exports = function(registry) { define('__get__' + relationName, { isStatic: false, - http: {verb: 'get', path: '/' + pathName}, - accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}}, + http: { verb: 'get', path: '/' + pathName }, + accepts: { arg: 'refresh', type: 'boolean', http: { source: 'query' }}, description: 'Fetches hasOne relation ' + relationName + '.', accessType: 'READ', - returns: {arg: relationName, type: relation.modelTo.modelName, root: true}, - rest: {after: convertNullToNotFoundError.bind(null, toModelName)} + returns: { arg: relationName, type: relation.modelTo.modelName, root: true }, + rest: { after: convertNullToNotFoundError.bind(null, toModelName) }, }); define('__create__' + relationName, { isStatic: false, - http: {verb: 'post', path: '/' + pathName}, - accepts: {arg: 'data', type: toModelName, http: {source: 'body'}}, + http: { verb: 'post', path: '/' + pathName }, + accepts: { arg: 'data', type: toModelName, http: { source: 'body' }}, description: 'Creates a new instance in ' + relationName + ' of this model.', accessType: 'WRITE', - returns: {arg: 'data', type: toModelName, root: true} + returns: { arg: 'data', type: toModelName, root: true }, }); define('__update__' + relationName, { isStatic: false, - http: {verb: 'put', path: '/' + pathName}, - accepts: {arg: 'data', type: toModelName, http: {source: 'body'}}, + http: { verb: 'put', path: '/' + pathName }, + accepts: { arg: 'data', type: toModelName, http: { source: 'body' }}, description: 'Update ' + relationName + ' of this model.', accessType: 'WRITE', - returns: {arg: 'data', type: toModelName, root: true} + returns: { arg: 'data', type: toModelName, root: true }, }); define('__destroy__' + relationName, { isStatic: false, - http: {verb: 'delete', path: '/' + pathName}, + http: { verb: 'delete', path: '/' + pathName }, description: 'Deletes ' + relationName + ' of this model.', - accessType: 'WRITE' + accessType: 'WRITE', }); }; @@ -508,41 +508,41 @@ module.exports = function(registry) { var findByIdFunc = this.prototype['__findById__' + relationName]; define('__findById__' + relationName, { isStatic: false, - http: {verb: 'get', path: '/' + pathName + '/:fk'}, - accepts: {arg: 'fk', type: 'any', + http: { verb: 'get', path: '/' + pathName + '/:fk' }, + accepts: { arg: 'fk', type: 'any', description: 'Foreign key for ' + relationName, required: true, - http: {source: 'path'}}, + http: { source: 'path' }}, description: 'Find a related item by id for ' + relationName + '.', accessType: 'READ', - returns: {arg: 'result', type: toModelName, root: true}, - rest: {after: convertNullToNotFoundError.bind(null, toModelName)} + returns: { arg: 'result', type: toModelName, root: true }, + rest: { after: convertNullToNotFoundError.bind(null, toModelName) }, }, findByIdFunc); var destroyByIdFunc = this.prototype['__destroyById__' + relationName]; define('__destroyById__' + relationName, { isStatic: false, - http: {verb: 'delete', path: '/' + pathName + '/:fk'}, - accepts: {arg: 'fk', type: 'any', + http: { verb: 'delete', path: '/' + pathName + '/:fk' }, + accepts: { arg: 'fk', type: 'any', description: 'Foreign key for ' + relationName, required: true, - http: {source: 'path'}}, + http: { source: 'path' }}, description: 'Delete a related item by id for ' + relationName + '.', accessType: 'WRITE', - returns: [] + returns: [], }, destroyByIdFunc); var updateByIdFunc = this.prototype['__updateById__' + relationName]; define('__updateById__' + relationName, { isStatic: false, - http: {verb: 'put', path: '/' + pathName + '/:fk'}, + http: { verb: 'put', path: '/' + pathName + '/:fk' }, accepts: [ - {arg: 'fk', type: 'any', + { arg: 'fk', type: 'any', description: 'Foreign key for ' + relationName, required: true, - http: {source: 'path'}}, - {arg: 'data', type: toModelName, http: {source: 'body'}} + http: { source: 'path' }}, + { arg: 'data', type: toModelName, http: { source: 'body' }}, ], description: 'Update a related item by id for ' + relationName + '.', accessType: 'WRITE', - returns: {arg: 'result', type: toModelName, root: true} + returns: { arg: 'result', type: toModelName, root: true }, }, updateByIdFunc); if (relation.modelThrough || relation.type === 'referencesMany') { @@ -551,31 +551,31 @@ module.exports = function(registry) { var accepts = []; if (relation.type === 'hasMany' && relation.modelThrough) { // Restrict: only hasManyThrough relation can have additional properties - accepts.push({arg: 'data', type: modelThrough.modelName, http: {source: 'body'}}); + accepts.push({ arg: 'data', type: modelThrough.modelName, http: { source: 'body' }}); } var addFunc = this.prototype['__link__' + relationName]; define('__link__' + relationName, { isStatic: false, - http: {verb: 'put', path: '/' + pathName + '/rel/:fk'}, - accepts: [{arg: 'fk', type: 'any', + http: { verb: 'put', path: '/' + pathName + '/rel/:fk' }, + accepts: [{ arg: 'fk', type: 'any', description: 'Foreign key for ' + relationName, required: true, - http: {source: 'path'}}].concat(accepts), + http: { source: 'path' }}].concat(accepts), description: 'Add a related item by id for ' + relationName + '.', accessType: 'WRITE', - returns: {arg: relationName, type: modelThrough.modelName, root: true} + returns: { arg: relationName, type: modelThrough.modelName, root: true }, }, addFunc); var removeFunc = this.prototype['__unlink__' + relationName]; define('__unlink__' + relationName, { isStatic: false, - http: {verb: 'delete', path: '/' + pathName + '/rel/:fk'}, - accepts: {arg: 'fk', type: 'any', + http: { verb: 'delete', path: '/' + pathName + '/rel/:fk' }, + accepts: { arg: 'fk', type: 'any', description: 'Foreign key for ' + relationName, required: true, - http: {source: 'path'}}, + http: { source: 'path' }}, description: 'Remove the ' + relationName + ' relation to an item by id.', accessType: 'WRITE', - returns: [] + returns: [], }, removeFunc); // FIXME: [rfeng] How to map a function with callback(err, true|false) to HEAD? @@ -583,13 +583,13 @@ module.exports = function(registry) { var existsFunc = this.prototype['__exists__' + relationName]; define('__exists__' + relationName, { isStatic: false, - http: {verb: 'head', path: '/' + pathName + '/rel/:fk'}, - accepts: {arg: 'fk', type: 'any', + http: { verb: 'head', path: '/' + pathName + '/rel/:fk' }, + accepts: { arg: 'fk', type: 'any', description: 'Foreign key for ' + relationName, required: true, - http: {source: 'path'}}, + http: { source: 'path' }}, description: 'Check the existence of ' + relationName + ' relation to an item by id.', accessType: 'READ', - returns: {arg: 'exists', type: 'boolean', root: true}, + returns: { arg: 'exists', type: 'boolean', root: true }, rest: { // After hook to map exists to 200/404 for HEAD after: function(ctx, cb) { @@ -604,8 +604,8 @@ module.exports = function(registry) { } else { cb(); } - } - } + }, + }, }, existsFunc); } }; @@ -628,38 +628,37 @@ module.exports = function(registry) { define('__get__' + scopeName, { isStatic: isStatic, - http: {verb: 'get', path: '/' + pathName}, - accepts: {arg: 'filter', type: 'object'}, + http: { verb: 'get', path: '/' + pathName }, + accepts: { arg: 'filter', type: 'object' }, description: 'Queries ' + scopeName + ' of ' + this.modelName + '.', accessType: 'READ', - returns: {arg: scopeName, type: [toModelName], root: true} + returns: { arg: scopeName, type: [toModelName], root: true }, }); define('__create__' + scopeName, { isStatic: isStatic, - http: {verb: 'post', path: '/' + pathName}, - accepts: {arg: 'data', type: toModelName, http: {source: 'body'}}, + http: { verb: 'post', path: '/' + pathName }, + accepts: { arg: 'data', type: toModelName, http: { source: 'body' }}, description: 'Creates a new instance in ' + scopeName + ' of this model.', accessType: 'WRITE', - returns: {arg: 'data', type: toModelName, root: true} + returns: { arg: 'data', type: toModelName, root: true }, }); define('__delete__' + scopeName, { isStatic: isStatic, - http: {verb: 'delete', path: '/' + pathName}, + http: { verb: 'delete', path: '/' + pathName }, description: 'Deletes all ' + scopeName + ' of this model.', - accessType: 'WRITE' + accessType: 'WRITE', }); define('__count__' + scopeName, { isStatic: isStatic, - http: {verb: 'get', path: '/' + pathName + '/count'}, - accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'}, + http: { verb: 'get', path: '/' + pathName + '/count' }, + accepts: { arg: 'where', type: 'object', description: 'Criteria to match model instances' }, description: 'Counts ' + scopeName + ' of ' + this.modelName + '.', accessType: 'READ', - returns: {arg: 'count', type: 'number'} + returns: { arg: 'count', type: 'number' }, }); - }; /** @@ -696,8 +695,7 @@ module.exports = function(registry) { var paramName = options.paramName || 'nk'; var http = [].concat(sharedToClass.http || [])[0]; - var httpPath; - var acceptArgs; + var httpPath, acceptArgs; if (relation.multiple) { httpPath = pathName + '/:' + paramName; @@ -705,8 +703,8 @@ module.exports = function(registry) { { arg: paramName, type: 'any', http: { source: 'path' }, description: 'Foreign key for ' + relation.name + '.', - required: true - } + required: true, + }, ]; } else { httpPath = pathName; @@ -830,9 +828,10 @@ module.exports = function(registry) { } }); }); - } else { - throw new Error('Relation `' + relationName + '` does not exist for model `' + this.modelName + '`'); + var msg = 'Relation `' + relationName + + '` does not exist for model `' + this.modelName + '`'; + throw new Error(msg); } }; diff --git a/lib/persisted-model.js b/lib/persisted-model.js index b1cf3a8e..87b548bd 100644 --- a/lib/persisted-model.js +++ b/lib/persisted-model.js @@ -555,28 +555,30 @@ module.exports = function(registry) { setRemoting(PersistedModel, 'create', { description: 'Create a new instance of the model and persist it into the data source.', accessType: 'WRITE', - accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}}, - returns: {arg: 'data', type: typeName, root: true}, - http: {verb: 'post', path: '/'} + accepts: { arg: 'data', type: 'object', http: { source: 'body' }, description: + 'Model instance data' }, + returns: { arg: 'data', type: typeName, root: true }, + http: { verb: 'post', path: '/' }, }); setRemoting(PersistedModel, 'upsert', { aliases: ['updateOrCreate'], description: 'Update an existing model instance or insert a new one into the data source.', accessType: 'WRITE', - accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}}, - returns: {arg: 'data', type: typeName, root: true}, - http: {verb: 'put', path: '/'} + accepts: { arg: 'data', type: 'object', http: { source: 'body' }, description: + 'Model instance data' }, + returns: { arg: 'data', type: typeName, root: true }, + http: { verb: 'put', path: '/' }, }); setRemoting(PersistedModel, 'exists', { description: 'Check whether a model instance exists in the data source.', accessType: 'READ', - accepts: {arg: 'id', type: 'any', description: 'Model id', required: true}, - returns: {arg: 'exists', type: 'boolean'}, + accepts: { arg: 'id', type: 'any', description: 'Model id', required: true }, + returns: { arg: 'exists', type: 'boolean' }, http: [ - {verb: 'get', path: '/:id/exists'}, - {verb: 'head', path: '/:id'} + { verb: 'get', path: '/:id/exists' }, + { verb: 'head', path: '/:id' }, ], rest: { // After hook to map exists to 200/404 for HEAD @@ -596,8 +598,8 @@ module.exports = function(registry) { } else { cb(); } - } - } + }, + }, }); setRemoting(PersistedModel, 'findById', { @@ -605,44 +607,46 @@ module.exports = function(registry) { accessType: 'READ', accepts: [ { arg: 'id', type: 'any', description: 'Model id', required: true, - http: {source: 'path'}}, + http: { source: 'path' }}, { arg: 'filter', type: 'object', - description: 'Filter defining fields and include'} + description: 'Filter defining fields and include' }, ], - returns: {arg: 'data', type: typeName, root: true}, - http: {verb: 'get', path: '/:id'}, - rest: {after: convertNullToNotFoundError} + returns: { arg: 'data', type: typeName, root: true }, + http: { verb: 'get', path: '/:id' }, + rest: { after: convertNullToNotFoundError }, }); setRemoting(PersistedModel, 'find', { description: 'Find all instances of the model matched by filter from the data source.', accessType: 'READ', - accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'}, - returns: {arg: 'data', type: [typeName], root: true}, - http: {verb: 'get', path: '/'} + accepts: { arg: 'filter', type: 'object', description: + 'Filter defining fields, where, include, order, offset, and limit' }, + returns: { arg: 'data', type: [typeName], root: true }, + http: { verb: 'get', path: '/' }, }); setRemoting(PersistedModel, 'findOne', { description: 'Find first instance of the model matched by filter from the data source.', accessType: 'READ', - accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'}, - returns: {arg: 'data', type: typeName, root: true}, - http: {verb: 'get', path: '/findOne'}, - rest: {after: convertNullToNotFoundError} + accepts: { arg: 'filter', type: 'object', description: + 'Filter defining fields, where, include, order, offset, and limit' }, + returns: { arg: 'data', type: typeName, root: true }, + http: { verb: 'get', path: '/findOne' }, + rest: { after: convertNullToNotFoundError }, }); setRemoting(PersistedModel, 'destroyAll', { description: 'Delete all matching records.', accessType: 'WRITE', - accepts: {arg: 'where', type: 'object', description: 'filter.where object'}, + accepts: { arg: 'where', type: 'object', description: 'filter.where object' }, returns: { arg: 'count', type: 'object', description: 'The number of instances deleted', - root: true + root: true, }, - http: {verb: 'del', path: '/'}, - shared: false + http: { verb: 'del', path: '/' }, + shared: false, }); setRemoting(PersistedModel, 'updateAll', { @@ -650,44 +654,44 @@ module.exports = function(registry) { description: 'Update instances of the model matched by where from the data source.', accessType: 'WRITE', accepts: [ - {arg: 'where', type: 'object', http: {source: 'query'}, - description: 'Criteria to match model instances'}, - {arg: 'data', type: 'object', http: {source: 'body'}, - description: 'An object of model property name/value pairs'}, + { arg: 'where', type: 'object', http: { source: 'query' }, + description: 'Criteria to match model instances' }, + { arg: 'data', type: 'object', http: { source: 'body' }, + description: 'An object of model property name/value pairs' }, ], returns: { arg: 'count', description: 'The number of instances updated', type: 'object', - root: true + root: true, }, - http: {verb: 'post', path: '/update'} + http: { verb: 'post', path: '/update' }, }); setRemoting(PersistedModel, 'deleteById', { aliases: ['destroyById', 'removeById'], description: 'Delete a model instance by id from the data source.', accessType: 'WRITE', - accepts: {arg: 'id', type: 'any', description: 'Model id', required: true, - http: {source: 'path'}}, - http: {verb: 'del', path: '/:id'}, - returns: {arg: 'count', type: 'object', root: true} + accepts: { arg: 'id', type: 'any', description: 'Model id', required: true, + http: { source: 'path' }}, + http: { verb: 'del', path: '/:id' }, + returns: { arg: 'count', type: 'object', root: true }, }); setRemoting(PersistedModel, 'count', { description: 'Count instances of the model matched by where from the data source.', accessType: 'READ', - accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'}, - returns: {arg: 'count', type: 'number'}, - http: {verb: 'get', path: '/count'} + accepts: { arg: 'where', type: 'object', description: 'Criteria to match model instances' }, + returns: { arg: 'count', type: 'number' }, + http: { verb: 'get', path: '/count' }, }); setRemoting(PersistedModel.prototype, 'updateAttributes', { description: 'Update attributes for a model instance and persist it into the data source.', accessType: 'WRITE', - accepts: {arg: 'data', type: 'object', http: {source: 'body'}, description: 'An object of model property name/value pairs'}, - returns: {arg: 'data', type: typeName, root: true}, - http: {verb: 'put', path: '/'} + accepts: { arg: 'data', type: 'object', http: { source: 'body' }, description: 'An object of model property name/value pairs' }, + returns: { arg: 'data', type: typeName, root: true }, + http: { verb: 'put', path: '/' }, }); if (options.trackChanges || options.enableRemoteReplication) { @@ -695,12 +699,12 @@ module.exports = function(registry) { description: 'Get a set of deltas and conflicts since the given checkpoint.', accessType: 'READ', accepts: [ - {arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'}, - {arg: 'remoteChanges', type: 'array', description: 'an array of change objects', - http: {source: 'body'}} + { arg: 'since', type: 'number', description: 'Find deltas since this checkpoint' }, + { arg: 'remoteChanges', type: 'array', description: 'an array of change objects', + http: { source: 'body' }}, ], - returns: {arg: 'result', type: 'object', root: true}, - http: {verb: 'post', path: '/diff'} + returns: { arg: 'result', type: 'object', root: true }, + http: { verb: 'post', path: '/diff' }, }); setRemoting(PersistedModel, 'changes', { @@ -708,11 +712,13 @@ module.exports = function(registry) { 'Provide a filter object to reduce the number of results returned.', accessType: 'READ', accepts: [ - {arg: 'since', type: 'number', description: 'Only return changes since this checkpoint'}, - {arg: 'filter', type: 'object', description: 'Only include changes that match this filter'} + { arg: 'since', type: 'number', description: + 'Only return changes since this checkpoint' }, + { arg: 'filter', type: 'object', description: + 'Only include changes that match this filter' }, ], - returns: {arg: 'changes', type: 'array', root: true}, - http: {verb: 'get', path: '/changes'} + returns: { arg: 'changes', type: 'array', root: true }, + http: { verb: 'get', path: '/changes' }, }); setRemoting(PersistedModel, 'checkpoint', { @@ -722,15 +728,15 @@ module.exports = function(registry) { // We need to allow this method for users that don't have full // WRITE permissions. accessType: 'REPLICATE', - returns: {arg: 'checkpoint', type: 'object', root: true}, - http: {verb: 'post', path: '/checkpoint'} + returns: { arg: 'checkpoint', type: 'object', root: true }, + http: { verb: 'post', path: '/checkpoint' }, }); setRemoting(PersistedModel, 'currentCheckpoint', { description: 'Get the current checkpoint.', accessType: 'READ', - returns: {arg: 'checkpoint', type: 'object', root: true}, - http: {verb: 'get', path: '/checkpoint'} + returns: { arg: 'checkpoint', type: 'object', root: true }, + http: { verb: 'get', path: '/checkpoint' }, }); setRemoting(PersistedModel, 'createUpdates', { @@ -739,16 +745,16 @@ module.exports = function(registry) { // It is called by the replication algorithm to compile a list // of changes to apply on the target. accessType: 'READ', - accepts: {arg: 'deltas', type: 'array', http: {source: 'body'}}, - returns: {arg: 'updates', type: 'array', root: true}, - http: {verb: 'post', path: '/create-updates'} + accepts: { arg: 'deltas', type: 'array', http: { source: 'body' }}, + returns: { arg: 'updates', type: 'array', root: true }, + http: { verb: 'post', path: '/create-updates' }, }); setRemoting(PersistedModel, 'bulkUpdate', { description: 'Run multiple updates at once. Note: this is not atomic.', accessType: 'WRITE', - accepts: {arg: 'updates', type: 'array'}, - http: {verb: 'post', path: '/bulk-update'} + accepts: { arg: 'updates', type: 'array' }, + http: { verb: 'post', path: '/bulk-update' }, }); setRemoting(PersistedModel, 'findLastChange', { @@ -756,30 +762,30 @@ module.exports = function(registry) { accessType: 'READ', accepts: { arg: 'id', type: 'any', required: true, http: { source: 'path' }, - description: 'Model id' + description: 'Model id', }, returns: { arg: 'result', type: this.Change.modelName, root: true }, - http: { verb: 'get', path: '/:id/changes/last' } + http: { verb: 'get', path: '/:id/changes/last' }, }); setRemoting(PersistedModel, 'updateLastChange', { description: [ 'Update the properties of the most recent change record', - 'kept for this instance.' + 'kept for this instance.', ], accessType: 'WRITE', accepts: [ { arg: 'id', type: 'any', required: true, http: { source: 'path' }, - description: 'Model id' + description: 'Model id', }, { - arg: 'data', type: 'object', http: {source: 'body'}, - description: 'An object of Change property name/value pairs' + arg: 'data', type: 'object', http: { source: 'body' }, + description: 'An object of Change property name/value pairs', }, ], returns: { arg: 'result', type: this.Change.modelName, root: true }, - http: { verb: 'put', path: '/:id/changes/last' } + http: { verb: 'put', path: '/:id/changes/last' }, }); } @@ -789,14 +795,14 @@ module.exports = function(registry) { setRemoting(PersistedModel, 'rectifyAllChanges', { description: 'Rectify all Model changes.', accessType: 'WRITE', - http: {verb: 'post', path: '/rectify-all'} + http: { verb: 'post', path: '/rectify-all' }, }); setRemoting(PersistedModel, 'rectifyChange', { description: 'Tell loopback that a change to the model with the given id has occurred.', accessType: 'WRITE', - accepts: {arg: 'id', type: 'any', http: {source: 'path'}}, - http: {verb: 'post', path: '/:id/rectify-change'} + accepts: { arg: 'id', type: 'any', http: { source: 'path' }}, + http: { verb: 'post', path: '/:id/rectify-change' }, }); } @@ -804,18 +810,18 @@ module.exports = function(registry) { description: 'Create a change stream.', accessType: 'READ', http: [ - {verb: 'post', path: '/change-stream'}, - {verb: 'get', path: '/change-stream'} + { verb: 'post', path: '/change-stream' }, + { verb: 'get', path: '/change-stream' }, ], accepts: { arg: 'options', - type: 'object' + type: 'object', }, returns: { arg: 'changes', type: 'ReadableStream', - json: true - } + json: true, + }, }); }; @@ -870,14 +876,14 @@ module.exports = function(registry) { // TODO(ritch) this whole thing could be optimized a bit more Change.find({ where: { checkpoint: { gte: since }, - modelName: this.modelName + modelName: this.modelName, }}, function(err, changes) { if (err) return callback(err); if (!Array.isArray(changes) || changes.length === 0) return callback(null, []); var ids = changes.map(function(change) { return change.getModelId(); }); - filter.where[idName] = {inq: ids}; + filter.where[idName] = { inq: ids }; model.find(filter, function(err, models) { if (err) return callback(err); var modelIds = models.map(function(m) { @@ -1004,16 +1010,14 @@ module.exports = function(registry) { 'You must enable change tracking before replicating' ); - var diff; - var updates; - var newSourceCp, newTargetCp; + var diff, updates, newSourceCp, newTargetCp; var tasks = [ checkpoints, getSourceChanges, getDiffFromTarget, createSourceUpdates, - bulkUpdate + bulkUpdate, ]; async.waterfall(tasks, done); @@ -1136,7 +1140,7 @@ module.exports = function(registry) { deltas.forEach(function(change) { change = new Change(change); var type = change.type(); - var update = {type: type, change: change}; + var update = { type: type, change: change }; switch (type) { case Change.CREATE: case Change.UPDATE: @@ -1521,7 +1525,7 @@ module.exports = function(registry) { this.Change = BaseChangeModel.extend(this.modelName + '-change', {}, { - trackModel: this + trackModel: this, } ); @@ -1575,7 +1579,7 @@ module.exports = function(registry) { PersistedModel.findLastChange = function(id, cb) { var Change = this.getChangeModel(); - Change.findOne({ where: { modelId: id } }, cb); + Change.findOne({ where: { modelId: id }}, cb); }; PersistedModel.updateLastChange = function(id, data, cb) { @@ -1611,7 +1615,7 @@ module.exports = function(registry) { var idName = this.getIdName(); var Model = this; - var changes = new PassThrough({objectMode: true}); + var changes = new PassThrough({ objectMode: true }); var writeable = true; changes.destroy = function() { @@ -1661,7 +1665,7 @@ module.exports = function(registry) { var change = { target: target, where: where, - data: data + data: data, }; switch (type) { diff --git a/lib/registry.js b/lib/registry.js index 5ee4ce85..35d247e2 100644 --- a/lib/registry.js +++ b/lib/registry.js @@ -89,7 +89,6 @@ function Registry() { */ Registry.prototype.createModel = function(name, properties, options) { - if (arguments.length === 1 && typeof name === 'object') { var config = name; name = config.name; @@ -208,7 +207,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) { 'super': true, relations: true, acls: true, - dataSource: true + dataSource: true, }; if (typeof config.options === 'object' && config.options !== null) { for (var p in config.options) { @@ -390,7 +389,7 @@ Registry.prototype.memory = function(name) { if (!memory) { memory = this._memoryDataSources[name] = this.createDataSource({ - connector: 'memory' + connector: 'memory', }); } diff --git a/lib/server-app.js b/lib/server-app.js index 237a6254..6ef92270 100644 --- a/lib/server-app.js +++ b/lib/server-app.js @@ -265,7 +265,7 @@ proto.lazyrouter = function() { self._requestHandlingPhases = [ 'initial', 'session', 'auth', 'parse', - 'routes', 'files', 'final' + 'routes', 'files', 'final', ]; }; diff --git a/package.json b/package.json index e27b882f..65ac7132 100644 --- a/package.json +++ b/package.json @@ -63,13 +63,13 @@ "browserify": "^10.0.0", "chai": "^2.1.1", "es5-shim": "^4.1.0", + "eslint-config-loopback": "^1.0.0", "grunt": "^0.4.5", "grunt-browserify": "^3.5.0", "grunt-cli": "^0.1.13", - "grunt-contrib-jshint": "^0.11.0", "grunt-contrib-uglify": "^0.9.1", "grunt-contrib-watch": "^0.6.1", - "grunt-jscs": "^1.5.0", + "grunt-eslint": "^18.0.0", "grunt-karma": "^0.10.1", "grunt-mocha-test": "^0.12.7", "karma": "^0.12.31", diff --git a/server/current-context.js b/server/current-context.js index 6b8304e2..887a9b5e 100644 --- a/server/current-context.js +++ b/server/current-context.js @@ -4,7 +4,6 @@ var cls = require('continuation-local-storage'); var domain = require('domain'); module.exports = function(loopback) { - /** * Get the current context object. The context is preserved * across async calls, it behaves like a thread-local storage. diff --git a/server/middleware/context.js b/server/middleware/context.js index 95352018..274f6f1d 100644 --- a/server/middleware/context.js +++ b/server/middleware/context.js @@ -44,7 +44,7 @@ function context(options) { // Run the code in the context of the namespace if (enableHttpContext) { // Set up the transport context - ns.set('http', {req: req, res: res}); + ns.set('http', { req: req, res: res }); } next(); }); diff --git a/server/middleware/status.js b/server/middleware/status.js index 3e930811..6df2c2f3 100644 --- a/server/middleware/status.js +++ b/server/middleware/status.js @@ -23,7 +23,7 @@ function status() { return function(req, res) { res.send({ started: started, - uptime: (Date.now() - Number(started)) / 1000 + uptime: (Date.now() - Number(started)) / 1000, }); }; } diff --git a/test/access-control.integration.js b/test/access-control.integration.js index 66f10d60..3f6107c8 100644 --- a/test/access-control.integration.js +++ b/test/access-control.integration.js @@ -1,17 +1,14 @@ -/*jshint -W030 */ - var loopback = require('../'); var lt = require('./helpers/loopback-testing-helper'); var path = require('path'); var ACCESS_CONTROL_APP = path.join(__dirname, 'fixtures', 'access-control'); var app = require(path.join(ACCESS_CONTROL_APP, 'server/server.js')); var assert = require('assert'); -var USER = {email: 'test@test.test', password: 'test'}; -var CURRENT_USER = {email: 'current@test.test', password: 'test'}; +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() { - lt.beforeEach.withApp(app); /* @@ -61,7 +58,6 @@ describe('access control - integration', function() { */ describe('/users', function() { - lt.beforeEach.givenModel('user', USER, 'randomUser'); lt.it.shouldBeDeniedWhenCalledAnonymously('GET', '/api/users'); @@ -128,7 +124,7 @@ describe('access control - integration', function() { userCounter = userCounter ? ++userCounter : 1; return { email: 'new-' + userCounter + '@test.test', - password: 'test' + password: 'test', }; } }); @@ -200,13 +196,13 @@ describe('access control - integration', function() { // Create an account under the given user app.models.account.create({ userId: self.user.id, - balance: 100 + balance: 100, }, function(err, act) { self.url = '/api/accounts/' + act.id; done(); }); - }); + lt.describe.whenCalledRemotely('PUT', '/api/accounts/:id', function() { lt.it.shouldBeAllowed(); }); @@ -226,5 +222,4 @@ 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 9e57cba2..d3866c6c 100644 --- a/test/access-token.test.js +++ b/test/access-token.test.js @@ -1,7 +1,7 @@ var loopback = require('../'); var extend = require('util')._extend; var Token = loopback.AccessToken.extend('MyToken'); -var ds = loopback.createDataSource({connector: loopback.Memory}); +var ds = loopback.createDataSource({ connector: loopback.Memory }); Token.attachTo(ds); var ACL = loopback.ACL; @@ -36,7 +36,7 @@ describe('loopback.token(options)', function() { var tokenId = this.token.id; var app = createTestApp( this.token, - { token: { searchDefaultTokenKeys: false } }, + { token: { searchDefaultTokenKeys: false }}, done); var agent = request.agent(app); @@ -144,7 +144,7 @@ describe('loopback.token(options)', function() { .set('authorization', id) .end(function(err, res) { assert(!err); - assert.deepEqual(res.body, {userId: userId}); + assert.deepEqual(res.body, { userId: userId }); done(); }); }); @@ -159,7 +159,7 @@ describe('loopback.token(options)', function() { .set('authorization', id) .end(function(err, res) { assert(!err); - assert.deepEqual(res.body, {userId: userId, state: 1}); + assert.deepEqual(res.body, { userId: userId, state: 1 }); done(); }); }); @@ -174,7 +174,7 @@ describe('loopback.token(options)', function() { .set('authorization', id) .end(function(err, res) { assert(!err); - assert.deepEqual(res.body, {userId: userId, state: 1}); + assert.deepEqual(res.body, { userId: userId, state: 1 }); done(); }); }); @@ -227,7 +227,7 @@ describe('AccessToken', function() { it('supports two-arg variant with no options', function(done) { var expectedTokenId = this.token.id; var req = mockRequest({ - headers: { 'authorization': expectedTokenId } + headers: { 'authorization': expectedTokenId }, }); Token.findForRequest(req, function(err, token) { @@ -247,7 +247,7 @@ describe('AccessToken', function() { // express helpers param: function(name) { return this._params[name]; }, - header: function(name) { return this.headers[name]; } + header: function(name) { return this.headers[name]; }, }, opts); } @@ -274,7 +274,7 @@ describe('app.enableAuth()', function() { }); it('prevent remote call with app setting status on denied ACL', function(done) { - createTestAppAndRequest(this.token, {app:{aclErrorStatus:403}}, done) + createTestAppAndRequest(this.token, { app: { aclErrorStatus: 403 }}, done) .del('/tests/123') .expect(403) .set('authorization', this.token.id) @@ -290,7 +290,7 @@ describe('app.enableAuth()', function() { }); it('prevent remote call with app setting status on denied ACL', function(done) { - createTestAppAndRequest(this.token, {model:{aclErrorStatus:404}}, done) + createTestAppAndRequest(this.token, { model: { aclErrorStatus: 404 }}, done) .del('/tests/123') .expect(404) .set('authorization', this.token.id) @@ -328,7 +328,7 @@ describe('app.enableAuth()', function() { }; TestModel.remoteMethod('getToken', { returns: { arg: 'token', type: 'object' }, - http: { verb: 'GET', path: '/token' } + http: { verb: 'GET', path: '/token' }, }); var app = loopback(); @@ -355,7 +355,7 @@ describe('app.enableAuth()', function() { function createTestingToken(done) { var test = this; - Token.create({userId: '123'}, function(err, token) { + Token.create({ userId: '123' }, function(err, token) { if (err) return done(err); test.token = token; done(); @@ -376,7 +376,7 @@ function createTestApp(testToken, settings, done) { var modelSettings = settings.model || {}; var tokenSettings = extend({ model: Token, - currentUserLiteral: 'me' + currentUserLiteral: 'me', }, settings.token); var app = loopback(); @@ -384,8 +384,8 @@ function createTestApp(testToken, settings, done) { app.use(loopback.cookieParser('secret')); app.use(loopback.token(tokenSettings)); app.get('/token', function(req, res) { - res.cookie('authorization', testToken.id, {signed: true}); - res.cookie('access_token', testToken.id, {signed: true}); + res.cookie('authorization', testToken.id, { signed: true }); + res.cookie('access_token', testToken.id, { signed: true }); res.end(); }); app.get('/', function(req, res) { @@ -401,7 +401,7 @@ function createTestApp(testToken, settings, done) { res.status(req.accessToken ? 200 : 401).end(); }); app.use('/users/:uid', function(req, res) { - var result = {userId: req.params.uid}; + var result = { userId: req.params.uid }; if (req.query.state) { result.state = req.query.state; } else if (req.url !== '/') { @@ -423,9 +423,9 @@ function createTestApp(testToken, settings, done) { principalId: '$everyone', accessType: ACL.ALL, permission: ACL.DENY, - property: 'deleteById' - } - ] + property: 'deleteById', + }, + ], }; Object.keys(modelSettings).forEach(function(key) { diff --git a/test/acl.test.js b/test/acl.test.js index d8706eec..ebe0ffb9 100644 --- a/test/acl.test.js +++ b/test/acl.test.js @@ -14,12 +14,12 @@ function checkResult(err, result) { var ds = null; before(function() { - ds = loopback.createDataSource({connector: loopback.Memory}); + ds = loopback.createDataSource({ connector: loopback.Memory }); }); describe('security scopes', function() { beforeEach(function() { - var ds = this.ds = loopback.createDataSource({connector: loopback.Memory}); + var ds = this.ds = loopback.createDataSource({ connector: loopback.Memory }); testModel = loopback.PersistedModel.extend('testModel'); ACL.attachTo(ds); Role.attachTo(ds); @@ -30,45 +30,53 @@ describe('security scopes', function() { }); 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) { + 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) { 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); }); }); - }); 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) { - ACL.create({principalType: ACL.SCOPE, principalId: scope.id, - model: 'testModel', property: 'name', accessType: ACL.WRITE, permission: ACL.DENY}, - function(err, resource) { - // console.log(resource); - 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) { - assert(perm.permission === ACL.DENY); // because name.WRITE == DENY - }); - 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) { - assert(perm.permission === ACL.DENY); - }); + 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) { + ACL.create({ principalType: ACL.SCOPE, principalId: scope.id, + model: 'testModel', property: 'name', + accessType: ACL.WRITE, permission: ACL.DENY, + }, function(err, resource) { + // console.log(resource); + 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) { + assert(perm.permission === ACL.DENY); // because name.WRITE == DENY + }); + 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) { + assert(perm.permission === ACL.DENY); }); }); + }); }); - }); - }); describe('security ACLs', function() { @@ -79,26 +87,26 @@ describe('security ACLs', function() { 'accessType': '*', 'permission': 'DENY', 'principalType': 'ROLE', - 'principalId': '$everyone' + 'principalId': '$everyone', }, { 'model': 'account', 'accessType': '*', 'permission': 'ALLOW', 'principalType': 'ROLE', - 'principalId': '$owner' + 'principalId': '$owner', }, { 'model': 'account', 'accessType': 'READ', 'permission': 'ALLOW', 'principalType': 'ROLE', - 'principalId': '$everyone' + 'principalId': '$everyone', }]; var req = { model: 'account', property: 'find', - accessType: 'WRITE' + accessType: 'WRITE', }; acls = acls.map(function(a) { return new ACL(a); }); @@ -108,17 +116,19 @@ describe('security ACLs', function() { property: 'find', accessType: 'WRITE', permission: 'ALLOW', - methodNames: []}); + methodNames: [] }); }); it('should allow access to models for the given principal by wildcard', function() { // jscs:disable validateIndentation - ACL.create({principalType: ACL.USER, principalId: 'u001', model: 'User', property: ACL.ALL, - 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) { - + ACL.create({ + principalType: ACL.USER, principalId: 'u001', model: 'User', property: ACL.ALL, + 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) { ACL.checkPermission(ACL.USER, 'u001', 'User', 'name', ACL.READ, function(err, perm) { assert(perm.permission === ACL.DENY); }); @@ -126,52 +136,55 @@ describe('security ACLs', function() { ACL.checkPermission(ACL.USER, 'u001', 'User', 'name', ACL.ALL, function(err, perm) { assert(perm.permission === ACL.DENY); }); - }); - }); - }); 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) { - - ACL.create({principalType: ACL.USER, principalId: 'u001', model: 'testModel', property: ACL.ALL, - accessType: ACL.READ, permission: ACL.ALLOW}, function(err, acl) { - - ACL.create({principalType: ACL.USER, principalId: 'u002', model: 'testModel', property: ACL.ALL, - accessType: ACL.EXECUTE, permission: ACL.ALLOW}, function(err, acl) { - - ACL.checkPermission(ACL.USER, 'u001', 'testModel', 'name', ACL.READ, function(err, perm) { + ACL.create({ + principalType: ACL.USER, principalId: 'u001', model: 'testModel', property: ACL.ALL, + 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) { + ACL.create({ + principalType: ACL.USER, principalId: 'u002', model: 'testModel', property: ACL.ALL, + accessType: ACL.EXECUTE, permission: ACL.ALLOW, + }, function(err, acl) { + 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); }); - ACL.checkPermission(ACL.USER, 'u002', 'testModel', 'name', ACL.WRITE, function(err, perm) { + ACL.checkPermission(ACL.USER, 'u002', 'testModel', 'name', ACL.WRITE, + function(err, perm) { assert(perm.permission === ACL.ALLOW); }); - ACL.checkPermission(ACL.USER, 'u002', 'testModel', 'name', ACL.READ, function(err, perm) { + ACL.checkPermission(ACL.USER, 'u002', 'testModel', 'name', ACL.READ, + function(err, perm) { assert(perm.permission === ACL.ALLOW); }); - }); }); - }); - }); it('should honor defaultPermission from the model', function() { @@ -179,19 +192,23 @@ describe('security ACLs', function() { name: { type: String, acls: [ - {principalType: ACL.USER, principalId: 'u001', accessType: ACL.WRITE, permission: ACL.DENY}, - {principalType: ACL.USER, principalId: 'u001', accessType: ACL.ALL, permission: ACL.ALLOW} - ] - } + { principalType: ACL.USER, principalId: 'u001', + accessType: ACL.WRITE, permission: ACL.DENY }, + { principalType: ACL.USER, principalId: 'u001', + accessType: ACL.ALL, permission: ACL.ALLOW }, + ], + }, }, { acls: [ - {principalType: ACL.USER, principalId: 'u001', accessType: ACL.ALL, permission: ACL.ALLOW} - ] + { principalType: ACL.USER, principalId: 'u001', + accessType: ACL.ALL, permission: ACL.ALLOW }, + ], }); 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); }); @@ -202,7 +219,6 @@ describe('security ACLs', function() { 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() { @@ -210,16 +226,21 @@ describe('security ACLs', function() { name: { type: String, acls: [ - {principalType: ACL.USER, principalId: 'u001', accessType: ACL.WRITE, permission: ACL.DENY}, - {principalType: ACL.USER, principalId: 'u001', accessType: ACL.ALL, permission: ACL.ALLOW} - ] - } + { principalType: ACL.USER, principalId: 'u001', + accessType: ACL.WRITE, permission: ACL.DENY }, + { principalType: ACL.USER, principalId: 'u001', + accessType: ACL.ALL, permission: ACL.ALLOW }, + ], + }, }, { acls: [ - {principalType: ACL.USER, principalId: 'u001', accessType: ACL.ALL, permission: ACL.ALLOW}, - {principalType: ACL.USER, principalId: 'u002', accessType: ACL.EXECUTE, permission: ACL.ALLOW}, - {principalType: ACL.USER, principalId: 'u003', accessType: ACL.EXECUTE, permission: ACL.DENY} - ] + { principalType: ACL.USER, principalId: 'u001', + accessType: ACL.ALL, permission: ACL.ALLOW }, + { principalType: ACL.USER, principalId: 'u002', + accessType: ACL.EXECUTE, permission: ACL.ALLOW }, + { principalType: ACL.USER, principalId: 'u003', + accessType: ACL.EXECUTE, permission: ACL.DENY }, + ], }); /* @@ -228,26 +249,30 @@ 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); }); - ACL.checkPermission(ACL.USER, 'u002', 'Customer', 'name', ACL.READ, function(err, perm) { + ACL.checkPermission(ACL.USER, 'u002', 'Customer', 'name', ACL.READ, + function(err, perm) { assert(perm.permission === ACL.ALLOW); }); - ACL.checkPermission(ACL.USER, 'u003', 'Customer', 'name', ACL.WRITE, function(err, perm) { + ACL.checkPermission(ACL.USER, 'u003', 'Customer', 'name', ACL.WRITE, + function(err, perm) { assert(perm.permission === ACL.DENY); }); - }); it('should filter static ACLs by model/property', function() { @@ -255,21 +280,21 @@ describe('security ACLs', function() { name: { type: String, acls: [ - {principalType: ACL.USER, principalId: 'u001', - accessType: ACL.WRITE, permission: ACL.DENY}, - {principalType: ACL.USER, principalId: 'u001', - accessType: ACL.ALL, permission: ACL.ALLOW} - ] - } + { principalType: ACL.USER, principalId: 'u001', + accessType: ACL.WRITE, permission: ACL.DENY }, + { principalType: ACL.USER, principalId: 'u001', + accessType: ACL.ALL, permission: ACL.ALLOW }, + ], + }, }, { acls: [ - {principalType: ACL.USER, principalId: 'u001', property: 'name', - accessType: ACL.ALL, permission: ACL.ALLOW}, - {principalType: ACL.USER, principalId: 'u002', property: 'findOne', - accessType: ACL.ALL, permission: ACL.ALLOW}, - {principalType: ACL.USER, principalId: 'u003', property: ['findOne', 'findById'], - accessType: ACL.ALL, permission: ACL.ALLOW} - ] + { principalType: ACL.USER, principalId: 'u001', property: 'name', + accessType: ACL.ALL, permission: ACL.ALLOW }, + { principalType: ACL.USER, principalId: 'u002', property: 'findOne', + accessType: ACL.ALL, permission: ACL.ALLOW }, + { principalType: ACL.USER, principalId: 'u003', property: ['findOne', 'findById'], + accessType: ACL.ALL, permission: ACL.ALLOW }, + ], }); var staticACLs = ACL.getStaticACLs('Model1', 'name'); @@ -288,8 +313,7 @@ describe('security ACLs', function() { 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()); var userId = user.id; @@ -299,56 +323,62 @@ describe('security ACLs', function() { name: { type: String, acls: [ - {principalType: ACL.USER, principalId: userId, accessType: ACL.WRITE, permission: ACL.DENY}, - {principalType: ACL.USER, principalId: userId, accessType: ACL.ALL, permission: ACL.ALLOW} - ] - } + { principalType: ACL.USER, principalId: userId, + accessType: ACL.WRITE, permission: ACL.DENY }, + { principalType: ACL.USER, principalId: userId, + accessType: ACL.ALL, permission: ACL.ALLOW }, + ], + }, }, { acls: [ - {principalType: ACL.USER, principalId: userId, accessType: ACL.ALL, permission: ACL.ALLOW} + { principalType: ACL.USER, principalId: userId, + accessType: ACL.ALL, permission: ACL.ALLOW }, ], - defaultPermission: 'DENY' + defaultPermission: 'DENY', }); - ACL.create({principalType: ACL.USER, principalId: userId, model: 'Customer', property: ACL.ALL, - accessType: ACL.ALL, permission: ACL.ALLOW}, function(err, acl) { - + ACL.create({ + principalType: ACL.USER, principalId: userId, + model: 'Customer', property: ACL.ALL, + 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) { - + ACL.create({ + principalType: ACL.ROLE, principalId: 'MyRole', + model: 'Customer', property: ACL.ALL, + accessType: ACL.READ, permission: ACL.DENY, + }, function(err, acl) { log('ACL 2: ', acl.toObject()); ACL.checkAccessForContext({ principals: [ - {type: ACL.USER, id: userId} + { type: ACL.USER, id: userId }, ], model: 'Customer', property: 'name', - accessType: ACL.READ + accessType: ACL.READ, }, function(err, access) { assert(!err && access.permission === ACL.ALLOW); }); ACL.checkAccessForContext({ principals: [ - {type: ACL.ROLE, id: Role.EVERYONE} + { type: ACL.ROLE, id: Role.EVERYONE }, ], model: 'Customer', property: 'name', - accessType: ACL.READ + accessType: ACL.READ, }, function(err, access) { assert(!err && access.permission === ACL.DENY); }); - }); }); }); @@ -363,11 +393,11 @@ describe('access check', function() { app = loopback(); app.use(loopback.rest()); app.enableAuth(); - app.dataSource('test', {connector: 'memory'}); + app.dataSource('test', { connector: 'memory' }); }); it('should occur before other remote hooks', function(done) { - var MyTestModel = app.model('MyTestModel', {base: 'PersistedModel', dataSource: 'test'}); + var MyTestModel = app.model('MyTestModel', { base: 'PersistedModel', dataSource: 'test' }); var checkAccessCalled = false; var beforeHookCalled = false; diff --git a/test/app.test.js b/test/app.test.js index 1144db2e..8da684f8 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -1,5 +1,3 @@ -/*jshint -W030 */ - var async = require('async'); var path = require('path'); @@ -13,8 +11,7 @@ var it = require('./util/it'); describe('app', function() { describe.onServer('.middleware(phase, handler)', function() { - var app; - var steps; + var app, steps; beforeEach(function setup() { app = loopback(); @@ -24,7 +21,7 @@ describe('app', function() { it('runs middleware in phases', function(done) { var PHASES = [ 'initial', 'session', 'auth', 'parse', - 'routes', 'files', 'final' + 'routes', 'files', 'final', ]; PHASES.forEach(function(name) { @@ -36,7 +33,7 @@ describe('app', function() { if (err) return done(err); expect(steps).to.eql([ 'initial', 'session', 'auth', 'parse', - 'main', 'routes', 'files', 'final' + 'main', 'routes', 'files', 'final', ]); done(); }); @@ -233,8 +230,7 @@ describe('app', function() { }); it('exposes express helpers on req and res objects', function(done) { - var req; - var res; + var req, res; app.middleware('initial', function(rq, rs, next) { req = rq; @@ -250,7 +246,7 @@ describe('app', function() { 'param', 'params', 'query', - 'res' + 'res', ]); expect(getObjectAndPrototypeKeys(res), 'response').to.include.members([ @@ -262,7 +258,7 @@ describe('app', function() { 'req', 'send', 'sendFile', - 'set' + 'set', ]); done(); @@ -316,13 +312,12 @@ describe('app', function() { }); it('correctly mounts express apps', function(done) { - var data; - var mountWasEmitted; + var data, mountWasEmitted; var subapp = express(); subapp.use(function(req, res, next) { data = { mountpath: req.app.mountpath, - parent: req.app.parent + parent: req.app.parent, }; next(); }); @@ -335,14 +330,13 @@ describe('app', function() { expect(mountWasEmitted, 'mountWasEmitted').to.be.true; expect(data).to.eql({ mountpath: '/mountpath', - parent: app + parent: app, }); done(); }); }); it('restores req & res on return from mounted express app', function(done) { - // jshint proto:true var expected = {}; var actual = {}; @@ -414,28 +408,28 @@ describe('app', function() { app.middlewareFromConfig(handlerFactory, { enabled: true, phase: 'session', - params: expectedConfig + params: expectedConfig, }); // Config as a value (single arg) app.middlewareFromConfig(handlerFactory, { enabled: true, phase: 'session:before', - params: 'before' + params: 'before', }); // Config as a list of args app.middlewareFromConfig(handlerFactory, { enabled: true, phase: 'session:after', - params: ['after', 2] + params: ['after', 2], }); // Disabled by configuration app.middlewareFromConfig(handlerFactory, { enabled: false, phase: 'initial', - params: null + params: null, }); // This should be triggered with matching verbs @@ -443,7 +437,7 @@ describe('app', function() { enabled: true, phase: 'routes:before', methods: ['get', 'head'], - params: {x: 1} + params: { x: 1 }, }); // This should be skipped as the verb doesn't match @@ -451,7 +445,7 @@ describe('app', function() { enabled: true, phase: 'routes:before', methods: ['post'], - params: {x: 2} + params: { x: 2 }, }); executeMiddlewareHandlers(app, function(err) { @@ -460,7 +454,7 @@ describe('app', function() { ['before'], [expectedConfig], ['after', 2], - [{x: 1}] + [{ x: 1 }], ]); done(); }); @@ -477,7 +471,7 @@ describe('app', function() { }, { phase: 'initial', - paths: ['/scope', /^\/(a|b)/] + paths: ['/scope', /^\/(a|b)/], }); async.eachSeries( @@ -508,7 +502,7 @@ describe('app', function() { 'first', 'initial', // this was the original first phase 'routes', - 'subapps' + 'subapps', ], done); }); @@ -519,7 +513,7 @@ describe('app', function() { 'auth', 'routes', 'subapps', // add 'final', - 'last' // add + 'last', // add ]); verifyMiddlewarePhases([ 'initial', @@ -527,7 +521,7 @@ describe('app', function() { 'auth', 'routes', 'subapps', // new 'files', 'final', - 'last' // new + 'last', // new ], done); }); @@ -555,15 +549,14 @@ describe('app', function() { }); describe('app.model(Model)', function() { - var app; - var db; + var app, db; beforeEach(function() { app = loopback(); - db = loopback.createDataSource({connector: loopback.Memory}); + db = loopback.createDataSource({ connector: loopback.Memory }); }); it('Expose a `Model` to remote clients', function() { - var Color = PersistedModel.extend('color', {name: String}); + var Color = PersistedModel.extend('color', { name: String }); app.model(Color); Color.attachTo(db); @@ -571,22 +564,22 @@ describe('app', function() { }); it('uses singlar name as app.remoteObjects() key', function() { - var Color = PersistedModel.extend('color', {name: String}); + var Color = PersistedModel.extend('color', { name: String }); app.model(Color); Color.attachTo(db); expect(app.remoteObjects()).to.eql({ color: Color }); }); it('uses singular name as shared class name', function() { - var Color = PersistedModel.extend('color', {name: String}); + 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'); }); it('registers existing models to app.models', function() { - var Color = db.createModel('color', {name: String}); + var Color = db.createModel('color', { name: String }); app.model(Color); expect(Color.app).to.be.equal(app); expect(Color.shared).to.equal(true); @@ -595,7 +588,7 @@ describe('app', function() { }); it('emits a `modelRemoted` event', function() { - var Color = PersistedModel.extend('color', {name: String}); + var Color = PersistedModel.extend('color', { name: String }); Color.shared = true; var remotedClass; app.on('modelRemoted', function(sharedClass) { @@ -610,7 +603,7 @@ describe('app', function() { app.use(loopback.rest()); request(app).get('/colors').expect(404, function(err, res) { if (err) return done(err); - var Color = PersistedModel.extend('color', {name: String}); + var Color = PersistedModel.extend('color', { name: String }); app.model(Color); Color.attachTo(db); request(app).get('/colors').expect(200, done); @@ -628,7 +621,6 @@ describe('app', function() { it('should not require dataSource', function() { app.model('MyTestModel', {}); }); - }); describe('app.model(name, config)', function() { @@ -637,13 +629,13 @@ describe('app', function() { beforeEach(function() { app = loopback(); app.dataSource('db', { - connector: 'memory' + connector: 'memory', }); }); it('Sugar for defining a fully built model', function() { app.model('foo', { - dataSource: 'db' + dataSource: 'db', }); var Foo = app.models.foo; @@ -655,7 +647,7 @@ describe('app', function() { it('interprets extra first-level keys as options', function() { app.model('foo', { dataSource: 'db', - base: 'User' + base: 'User', }); expect(app.models.foo.definition.settings.base).to.equal('User'); @@ -666,8 +658,8 @@ describe('app', function() { dataSource: 'db', base: 'User', options: { - base: 'Application' - } + base: 'Application', + }, }); expect(app.models.foo.definition.settings.base).to.equal('Application'); @@ -676,7 +668,7 @@ describe('app', function() { it('honors config.public options', function() { app.model('foo', { dataSource: 'db', - public: false + public: false, }); expect(app.models.foo.app).to.equal(app); expect(app.models.foo.shared).to.equal(false); @@ -684,12 +676,11 @@ describe('app', function() { it('defaults config.public to be true', function() { app.model('foo', { - dataSource: 'db' + dataSource: 'db', }); expect(app.models.foo.app).to.equal(app); expect(app.models.foo.shared).to.equal(true); }); - }); describe('app.model(ModelCtor, config)', function() { @@ -943,8 +934,7 @@ describe('app', function() { }); describe('normalizeHttpPath option', function() { - var app; - var db; + var app, db; beforeEach(function() { app = loopback(); db = loopback.createDataSource({ connector: loopback.Memory }); @@ -955,7 +945,7 @@ describe('app', function() { 'UserAccount', { name: String }, { - remoting: { normalizeHttpPath: true } + remoting: { normalizeHttpPath: true }, }); app.model(UserAccount); UserAccount.attachTo(db); diff --git a/test/change-stream.test.js b/test/change-stream.test.js index ab740521..9f2390fa 100644 --- a/test/change-stream.test.js +++ b/test/change-stream.test.js @@ -2,11 +2,11 @@ describe('PersistedModel.createChangeStream()', function() { describe('configured to source changes locally', function() { before(function() { var test = this; - var app = loopback({localRegistry: true}); - var ds = app.dataSource('ds', {connector: 'memory'}); + var app = loopback({ localRegistry: true }); + var ds = app.dataSource('ds', { connector: 'memory' }); this.Score = app.model('Score', { dataSource: 'ds', - changeDataSource: false // use only local observers + changeDataSource: false, // use only local observers }); }); @@ -20,13 +20,13 @@ describe('PersistedModel.createChangeStream()', function() { done(); }); - Score.create({team: 'foo'}); + Score.create({ team: 'foo' }); }); }); it('should detect update', function(done) { var Score = this.Score; - Score.create({team: 'foo'}, function(err, newScore) { + Score.create({ team: 'foo' }, function(err, newScore) { Score.createChangeStream(function(err, changes) { changes.on('data', function(change) { expect(change.type).to.equal('update'); @@ -34,7 +34,7 @@ describe('PersistedModel.createChangeStream()', function() { done(); }); newScore.updateAttributes({ - bat: 'baz' + bat: 'baz', }); }); }); @@ -42,7 +42,7 @@ describe('PersistedModel.createChangeStream()', function() { it('should detect delete', function(done) { var Score = this.Score; - Score.create({team: 'foo'}, function(err, newScore) { + Score.create({ team: 'foo' }, function(err, newScore) { Score.createChangeStream(function(err, changes) { changes.on('data', function(change) { expect(change.type).to.equal('remove'); @@ -60,17 +60,17 @@ describe('PersistedModel.createChangeStream()', function() { describe.skip('configured to source changes using pubsub', function() { before(function() { var test = this; - var app = loopback({localRegistry: true}); - var db = app.dataSource('ds', {connector: 'memory'}); + var app = loopback({ localRegistry: true }); + var db = app.dataSource('ds', { connector: 'memory' }); var ps = app.dataSource('ps', { host: 'localhost', port: '12345', connector: 'pubsub', - pubsubAdapter: 'mqtt' + pubsubAdapter: 'mqtt', }); this.Score = app.model('Score', { dataSource: 'db', - changeDataSource: 'ps' + changeDataSource: 'ps', }); }); diff --git a/test/change.test.js b/test/change.test.js index 2f43c037..9be1b51c 100644 --- a/test/change.test.js +++ b/test/change.test.js @@ -1,20 +1,19 @@ var async = require('async'); var expect = require('chai').expect; -var Change; -var TestModel; +var Change, TestModel; describe('Change', function() { beforeEach(function() { var memory = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); TestModel = loopback.PersistedModel.extend('ChangeTestModel', { - id: { id: true, type: 'string', defaultFn: 'guid' } + id: { id: true, type: 'string', defaultFn: 'guid' }, }, { - trackChanges: true + trackChanges: true, }); this.modelName = TestModel.modelName; TestModel.attachTo(memory); @@ -24,7 +23,7 @@ describe('Change', function() { beforeEach(function(done) { var test = this; test.data = { - foo: 'bar' + foo: 'bar', }; TestModel.create(test.data, function(err, model) { if (err) return done(err); @@ -46,7 +45,7 @@ describe('Change', function() { var change = new Change({ rev: 'abc', modelName: 'foo', - modelId: 'bar' + modelId: 'bar', }); var hash = Change.hash([change.modelName, change.modelId].join('-')); @@ -115,7 +114,6 @@ describe('Change', function() { }); describe('Change.findOrCreateChange(modelName, modelId, callback)', function() { - describe('when a change doesnt exist', function() { beforeEach(function(done) { var test = this; @@ -162,7 +160,7 @@ describe('Change', function() { var test = this; Change.create({ modelName: test.modelName, - modelId: test.modelId + modelId: test.modelId, }, function(err, change) { test.existingChange = change; done(); @@ -192,7 +190,7 @@ describe('Change', function() { Change.findOrCreate( { modelName: this.modelName, - modelId: this.modelId + modelId: this.modelId, }, function(err, ch) { change = ch; @@ -228,7 +226,7 @@ describe('Change', function() { expect(change.prev, 'prev').to.equal(originalRev); expect(change.rev, 'rev').to.equal(test.revisionForModel); next(); - } + }, ], done); function rectify(next) { @@ -299,7 +297,7 @@ describe('Change', function() { var test = this; var change = new Change({ modelName: this.modelName, - modelId: this.modelId + modelId: this.modelId, }); change.currentRevision(function(err, rev) { @@ -314,7 +312,7 @@ describe('Change', function() { var test = this; var change = new Change({ modelName: this.modelName, - modelId: this.modelId + modelId: this.modelId, }); change.currentRevision() @@ -341,14 +339,14 @@ describe('Change', function() { var a = { b: { b: ['c', 'd'], - c: ['d', 'e'] - } + c: ['d', 'e'], + }, }; var b = { b: { c: ['d', 'e'], - b: ['c', 'd'] - } + b: ['c', 'd'], + }, }; var aRev = Change.revisionForInst(a); @@ -360,20 +358,20 @@ describe('Change', function() { describe('change.type()', function() { it('CREATE', function() { var change = new Change({ - rev: this.revisionForModel + rev: this.revisionForModel, }); assert.equal(Change.CREATE, change.type()); }); it('UPDATE', function() { var change = new Change({ rev: this.revisionForModel, - prev: this.revisionForModel + prev: this.revisionForModel, }); assert.equal(Change.UPDATE, change.type()); }); it('DELETE', function() { var change = new Change({ - prev: this.revisionForModel + prev: this.revisionForModel, }); assert.equal(Change.DELETE, change.type()); }); @@ -386,7 +384,7 @@ describe('Change', function() { describe('change.getModelCtor()', function() { it('should get the correct model class', function() { var change = new Change({ - modelName: this.modelName + modelName: this.modelName, }); assert.equal(change.getModelCtor(), TestModel); @@ -396,11 +394,11 @@ describe('Change', function() { describe('change.equals(otherChange)', function() { it('should return true when the change is equal', function() { var change = new Change({ - rev: this.revisionForModel + rev: this.revisionForModel, }); var otherChange = new Change({ - rev: this.revisionForModel + rev: this.revisionForModel, }); assert.equal(change.equals(otherChange), true); @@ -415,7 +413,7 @@ describe('Change', function() { var otherChange = new Change({ rev: undefined, - prev: REV + prev: REV, }); assert.equal(change.type(), Change.DELETE); @@ -428,11 +426,11 @@ describe('Change', 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 + prev: this.revisionForModel, }); var otherChange = new Change({ - rev: this.revisionForModel + rev: this.revisionForModel, }); assert.equal(change.isBasedOn(otherChange), true); @@ -442,20 +440,20 @@ describe('Change', function() { describe('Change.diff(modelName, since, remoteChanges, callback)', function() { beforeEach(function(done) { Change.create([ - {rev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1}, - {rev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1}, - {rev: 'bat', modelName: this.modelName, modelId: 11, checkpoint: 1}, + { rev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1 }, + { rev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1 }, + { rev: 'bat', modelName: this.modelName, modelId: 11, checkpoint: 1 }, ], 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}, + { rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1 }, // no change => should not result in a delta / conflict - {rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1}, + { rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1 }, // a conflict => should result in a conflict - {rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1}, + { rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1 }, ]; Change.diff(this.modelName, 0, remoteChanges, function(err, diff) { @@ -469,11 +467,11 @@ describe('Change', function() { it('should return delta and conflict lists - promise variant', function(done) { var remoteChanges = [ // an update => should result in a delta - {rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1}, + { rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1 }, // no change => should not result in a delta / conflict - {rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1}, + { rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1 }, // a conflict => should result in a conflict - {rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1}, + { rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1 }, ]; Change.diff(this.modelName, 0, remoteChanges) @@ -491,7 +489,7 @@ describe('Change', function() { prev: 'foo', modelName: this.modelName, modelId: '9', - checkpoint: 2 + checkpoint: 2, }; Change.diff(this.modelName, 0, [updateRecord], function(err, diff) { if (err) return done(err); @@ -516,7 +514,7 @@ describe('Change', function() { prev: 'foo-prev', modelName: this.modelName, modelId: '9', - checkpoint: 2 + checkpoint: 2, }; // IMPORTANT: the diff call excludes the local change // with rev=foo CP=1 @@ -543,7 +541,7 @@ describe('Change', function() { prev: 'new-prev', modelName: this.modelName, modelId: 'new-id', - checkpoint: 2 + checkpoint: 2, }; Change.diff(this.modelName, 0, [updateRecord], function(err, diff) { diff --git a/test/checkpoint.test.js b/test/checkpoint.test.js index c824d02e..b3959007 100644 --- a/test/checkpoint.test.js +++ b/test/checkpoint.test.js @@ -8,7 +8,7 @@ describe('Checkpoint', function() { describe('bumpLastSeq() and current()', function() { beforeEach(function() { var memory = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); Checkpoint.attachTo(memory); }); @@ -23,14 +23,14 @@ describe('Checkpoint', function() { expect(seq).to.equal(3); next(); }); - } + }, ], done); }); it('Should be no race condition for current() when calling in parallel', function(done) { async.parallel([ function(next) { Checkpoint.current(next); }, - function(next) { Checkpoint.current(next); } + function(next) { Checkpoint.current(next); }, ], function(err, list) { if (err) return done(err); Checkpoint.find(function(err, data) { @@ -44,7 +44,7 @@ describe('Checkpoint', function() { it('Should be no race condition for bumpLastSeq() when calling in parallel', function(done) { async.parallel([ function(next) { Checkpoint.bumpLastSeq(next); }, - function(next) { Checkpoint.bumpLastSeq(next); } + function(next) { Checkpoint.bumpLastSeq(next); }, ], function(err, list) { if (err) return done(err); Checkpoint.find(function(err, data) { @@ -57,14 +57,15 @@ describe('Checkpoint', function() { expect(data[0].seq).to.equal(2); // In this particular case, since the new last seq is always 2, both results // should be 2. - expect(list.map(function(it) {return it.seq;})) + expect(list.map(function(it) { return it.seq; })) .to.eql([2, 2]); done(); }); }); }); - it('Checkpoint.current() for non existing checkpoint should initialize checkpoint', function(done) { + it('Checkpoint.current() for non existing checkpoint should initialize checkpoint', + function(done) { Checkpoint.current(function(err, seq) { expect(seq).to.equal(1); done(err); diff --git a/test/data-source.test.js b/test/data-source.test.js index 662c0718..5d7384c8 100644 --- a/test/data-source.test.js +++ b/test/data-source.test.js @@ -3,7 +3,7 @@ describe('DataSource', function() { beforeEach(function() { memory = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); assertValidDataSource(memory); @@ -11,7 +11,7 @@ describe('DataSource', function() { describe('dataSource.createModel(name, properties, settings)', function() { it('Define a model and attach it to a `DataSource`', function() { - var Color = memory.createModel('color', {name: String}); + var Color = memory.createModel('color', { name: String }); assert.isFunc(Color, 'find'); assert.isFunc(Color, 'findById'); assert.isFunc(Color, 'findOne'); @@ -36,13 +36,13 @@ describe('DataSource', function() { it('should honor settings.base', function() { var Base = memory.createModel('base'); - var Color = memory.createModel('color', {name: String}, {base: 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() { - var Color = memory.createModel('color', {name: String}); + var Color = memory.createModel('color', { name: String }); assert(Color.prototype instanceof loopback.PersistedModel); assert.equal(Color.base, loopback.PersistedModel); }); @@ -56,14 +56,13 @@ describe('DataSource', function() { }; var ds = loopback.createDataSource({ - connector: new Connector() + connector: new Connector(), }); - var Color = ds.createModel('color', {name: String}); + var Color = ds.createModel('color', { name: String }); assert(Color.prototype instanceof Color.registry.getModel('Model')); assert.equal(Color.base.modelName, 'PersistedModel'); }); - }); describe.skip('PersistedModel Methods', function() { @@ -103,7 +102,9 @@ describe('DataSource', function() { var fn = scope[name]; var actuallyEnabled = Model.getRemoteMethod(name); assert(fn, name + ' should be defined!'); - assert(actuallyEnabled === isRemoteEnabled, name + ' ' + (isRemoteEnabled ? 'should' : 'should not') + ' be remote enabled'); + assert(actuallyEnabled === isRemoteEnabled, + name + ' ' + (isRemoteEnabled ? 'should' : 'should not') + + ' be remote enabled'); } }); }); diff --git a/test/e2e/remote-connector.e2e.js b/test/e2e/remote-connector.e2e.js index 1a342471..15ae6896 100644 --- a/test/e2e/remote-connector.e2e.js +++ b/test/e2e/remote-connector.e2e.js @@ -9,14 +9,14 @@ describe('RemoteConnector', function() { // setup the remote connector var ds = loopback.createDataSource({ url: 'http://127.0.0.1:3000/api', - connector: loopback.Remote + connector: loopback.Remote, }); TestModel.attachTo(ds); }); it('should be able to call create', function(done) { TestModel.create({ - foo: 'bar' + foo: 'bar', }, function(err, inst) { if (err) return done(err); assert(inst.id); @@ -26,7 +26,7 @@ describe('RemoteConnector', function() { it('should be able to call save', function(done) { var m = new TestModel({ - foo: 'bar' + foo: 'bar', }); m.save(function(err, data) { if (err) return done(err); diff --git a/test/e2e/replication.e2e.js b/test/e2e/replication.e2e.js index 24f6967e..87fbfd5c 100644 --- a/test/e2e/replication.e2e.js +++ b/test/e2e/replication.e2e.js @@ -3,7 +3,7 @@ var loopback = require('../../'); var models = require('../fixtures/e2e/models'); var TestModel = models.TestModel; var LocalTestModel = TestModel.extend('LocalTestModel', {}, { - trackChanges: true + trackChanges: true, }); var assert = require('assert'); @@ -12,7 +12,7 @@ describe('Replication', function() { // setup the remote connector var ds = loopback.createDataSource({ url: 'http://127.0.0.1:3000/api', - connector: loopback.Remote + connector: loopback.Remote, }); TestModel.attachTo(ds); var memory = loopback.memory(); @@ -23,11 +23,11 @@ describe('Replication', function() { var RANDOM = Math.random(); LocalTestModel.create({ - n: RANDOM + n: RANDOM, }, function(err, created) { LocalTestModel.replicate(0, TestModel, function() { if (err) return done(err); - TestModel.findOne({n: RANDOM}, function(err, found) { + 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 018f543c..49cf189d 100644 --- a/test/email.test.js +++ b/test/email.test.js @@ -5,34 +5,33 @@ var MailConnector = require('../lib/connectors/mail'); describe('Email connector', function() { it('should set up SMTP', function() { - var connector = new MailConnector({transports: [ - {type: 'smtp', service: 'gmail'} - ]}); + var connector = new MailConnector({ transports: [ + { type: 'smtp', service: 'gmail' }, + ] }); assert(connector.transportForName('smtp')); }); it('should set up DIRECT', function() { - var connector = new MailConnector({transports: [ - {type: 'direct', name: 'localhost'} - ]}); + var connector = new MailConnector({ transports: [ + { type: 'direct', name: 'localhost' }, + ] }); assert(connector.transportForName('direct')); }); it('should set up STUB', function() { - var connector = new MailConnector({transports: [ - {type: 'stub', service: 'gmail'} - ]}); + var connector = new MailConnector({ transports: [ + { type: 'stub', service: 'gmail' }, + ] }); assert(connector.transportForName('stub')); }); - it('should set up a single transport for SMTP' , function() { - var connector = new MailConnector({transport: - {type: 'smtp', service: 'gmail'} + it('should set up a single transport for SMTP', function() { + var connector = new MailConnector({ transport: + { type: 'smtp', service: 'gmail' }, }); assert(connector.transportForName('smtp')); }); - }); describe('Email and SMTP', function() { @@ -53,7 +52,7 @@ describe('Email and SMTP', function() { from: 'from@from.com', subject: 'subject', text: 'text', - html: '

html

' + html: '

html

', }; MyEmail.send(options, function(err, mail) { @@ -71,7 +70,7 @@ describe('Email and SMTP', function() { from: 'from@from.com', subject: 'subject', text: 'text', - html: '

html

' + html: '

html

', }); message.send(function(err, mail) { diff --git a/test/error-handler.test.js b/test/error-handler.test.js index 0494f2ef..b5956614 100644 --- a/test/error-handler.test.js +++ b/test/error-handler.test.js @@ -4,9 +4,7 @@ var assert = require('assert'); var request = require('supertest'); describe('loopback.errorHandler(options)', function() { - it('should return default middleware when options object is not present', function(done) { - //arrange var app = loopback(); app.use(loopback.urlNotFound()); @@ -22,7 +20,6 @@ describe('loopback.errorHandler(options)', function() { }); it('should delete stack when options.includeStack is false', function(done) { - //arrange var app = loopback(); app.use(loopback.urlNotFound()); @@ -47,7 +44,7 @@ describe('loopback.errorHandler(options)', function() { includeStack: false, log: function customLogger(err, str, req) { errorLogged = err; - } + }, })); //act @@ -58,6 +55,5 @@ describe('loopback.errorHandler(options)', function() { .to.have.property('message', 'Cannot GET /url-does-not-exist'); done(); }); - }); }); diff --git a/test/fixtures/access-control/server/server.js b/test/fixtures/access-control/server/server.js index ef251648..a151ee25 100644 --- a/test/fixtures/access-control/server/server.js +++ b/test/fixtures/access-control/server/server.js @@ -5,7 +5,7 @@ var app = module.exports = loopback(); boot(app, __dirname); var apiPath = '/api'; -app.use(loopback.token({model: app.models.accessToken})); +app.use(loopback.token({ model: app.models.accessToken })); app.use(apiPath, loopback.rest()); app.use(loopback.urlNotFound()); diff --git a/test/fixtures/e2e/server/models.js b/test/fixtures/e2e/server/models.js index dc36ca03..5e6c235d 100644 --- a/test/fixtures/e2e/server/models.js +++ b/test/fixtures/e2e/server/models.js @@ -2,5 +2,5 @@ var loopback = require('../../../../index'); var PersistedModel = loopback.PersistedModel; exports.TestModel = PersistedModel.extend('TestModel', {}, { - trackChanges: true + trackChanges: true, }); diff --git a/test/fixtures/user-integration-app/server/server.js b/test/fixtures/user-integration-app/server/server.js index 1d3d6720..aaed9050 100644 --- a/test/fixtures/user-integration-app/server/server.js +++ b/test/fixtures/user-integration-app/server/server.js @@ -3,7 +3,7 @@ var boot = require('loopback-boot'); var app = module.exports = loopback(); app.enableAuth(); boot(app, __dirname); -app.use(loopback.token({model: app.models.AccessToken})); +app.use(loopback.token({ model: app.models.AccessToken })); var apiPath = '/api'; app.use(apiPath, loopback.rest()); app.use(loopback.urlNotFound()); diff --git a/test/geo-point.test.js b/test/geo-point.test.js index 9372caae..f992e2a0 100644 --- a/test/geo-point.test.js +++ b/test/geo-point.test.js @@ -1,9 +1,9 @@ describe('GeoPoint', function() { describe('geoPoint.distanceTo(geoPoint, options)', 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'}); + var here = new GeoPoint({ lat: 10, lng: 10 }); + var there = new GeoPoint({ lat: 5, lng: 5 }); + var distance = here.distanceTo(there, { type: 'meters' }); assert.equal(Math.floor(distance), 782777); }); @@ -11,9 +11,9 @@ describe('GeoPoint', function() { describe('GeoPoint.distanceBetween(a, b, options)', 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'}); + 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); }); @@ -43,11 +43,11 @@ describe('GeoPoint', function() { }); it('Create as Model property', function() { var Model = loopback.createModel('geo-model', { - geo: {type: 'GeoPoint'} + geo: { type: 'GeoPoint' }, }); var m = new Model({ - geo: '1.222,3.444' + geo: '1.222,3.444', }); assert(m.geo instanceof GeoPoint); diff --git a/test/helpers/loopback-testing-helper.js b/test/helpers/loopback-testing-helper.js index c5069050..286de97e 100644 --- a/test/helpers/loopback-testing-helper.js +++ b/test/helpers/loopback-testing-helper.js @@ -4,7 +4,7 @@ var _beforeEach = {}; var helpers = { describe: _describe, it: _it, - beforeEach: _beforeEach + beforeEach: _beforeEach, }; module.exports = helpers; @@ -119,7 +119,7 @@ _beforeEach.givenAnUnauthenticatedToken = function(attrs, optionalHandler) { }; _beforeEach.givenAnAnonymousToken = function(attrs, optionalHandler) { - _beforeEach.givenModel('accessToken', {id: '$anonymous'}, optionalHandler); + _beforeEach.givenModel('accessToken', { id: '$anonymous' }, optionalHandler); }; _describe.whenCalledRemotely = function(verb, url, data, cb) { @@ -145,7 +145,9 @@ _describe.whenCalledRemotely = function(verb, url, data, cb) { if (methodForVerb === 'delete') methodForVerb = 'del'; if (this.request === undefined) { - throw new Error('App is not specified. Please use lt.beforeEach.withApp to specify the app.'); + var msg = 'App is not specified. ' + + 'Please use lt.beforeEach.withApp to specify the app.'; + throw new Error(msg); } this.http = this.request[methodForVerb](this.url); diff --git a/test/hidden-properties.test.js b/test/hidden-properties.test.js index c5e80e9a..a32db105 100644 --- a/test/hidden-properties.test.js +++ b/test/hidden-properties.test.js @@ -5,7 +5,7 @@ describe('hidden properties', function() { var app = this.app = loopback(); var Product = this.Product = loopback.PersistedModel.extend('product', {}, - {hidden: ['secret']} + { hidden: ['secret'] } ); Product.attachTo(loopback.memory()); @@ -18,11 +18,11 @@ describe('hidden properties', function() { app.use(loopback.rest()); Category.create({ - name: 'my category' + name: 'my category', }, function(err, category) { category.products.create({ name: 'pencil', - secret: 'a secret' + secret: 'a secret', }, done); }); }); diff --git a/test/integration.test.js b/test/integration.test.js index 7aae5dc0..f88ed1b7 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -24,7 +24,7 @@ describe('loopback application', function() { function setupAppWithStreamingMethod() { app.dataSource('db', { connector: loopback.Memory, - defaultForType: 'db' + defaultForType: 'db', }); var db = app.datasources.db; @@ -52,9 +52,9 @@ describe('loopback application', function() { loopback.remoteMethod(Streamer.read, { http: { method: 'post' }, accepts: [ - { arg: 'req', type: 'Object', http: { source: 'req' } }, - { arg: 'res', type: 'Object', http: { source: 'res' } } - ] + { arg: 'req', type: 'Object', http: { source: 'req' }}, + { arg: 'res', type: 'Object', http: { source: 'res' }}, + ], }); app.enableAuth(); diff --git a/test/karma.conf.js b/test/karma.conf.js index f7792367..c1710fe7 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -26,7 +26,7 @@ module.exports = function(config) { 'test/replication.test.js', 'test/change.test.js', 'test/checkpoint.test.js', - 'test/app.test.js' + 'test/app.test.js', ], // list of files / patterns to exclude @@ -52,7 +52,7 @@ module.exports = function(config) { // - PhantomJS // - IE (only Windows) browsers: [ - 'Chrome' + 'Chrome', ], // Which plugins to enable @@ -61,16 +61,16 @@ module.exports = function(config) { 'karma-mocha', 'karma-phantomjs-launcher', 'karma-chrome-launcher', - 'karma-junit-reporter' + 'karma-junit-reporter', ], // If browser does not capture in given timeout [ms], kill it captureTimeout: 60000, // to avoid DISCONNECTED messages - browserDisconnectTimeout : 10000, // default 2000 - browserDisconnectTolerance : 1, // default 0 - browserNoActivityTimeout : 60000, //default 10000 + browserDisconnectTimeout: 10000, // default 2000 + browserDisconnectTolerance: 1, // default 0 + browserNoActivityTimeout: 60000, //default 10000 // Continuous Integration mode // if true, it capture browsers, run tests and exit @@ -97,7 +97,7 @@ module.exports = function(config) { 'passport', 'passport-local', 'superagent', - 'supertest' + 'supertest', ], // transform: ['coffeeify'], debug: true, @@ -106,6 +106,6 @@ module.exports = function(config) { }, // Add browserify to preprocessors - preprocessors: {'test/*': ['browserify']} + preprocessors: { 'test/*': ['browserify'] }, }); }; diff --git a/test/loopback.test.js b/test/loopback.test.js index dca31228..a9240615 100644 --- a/test/loopback.test.js +++ b/test/loopback.test.js @@ -105,7 +105,7 @@ describe('loopback', function() { 'urlNotFound', 'urlencoded', 'version', - 'vhost' + 'vhost', ]; var actual = Object.getOwnPropertyNames(loopback); @@ -135,7 +135,7 @@ describe('loopback', function() { describe('loopback.createDataSource(options)', function() { it('Create a data source with a connector.', function() { var dataSource = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); assert(dataSource.connector); }); @@ -144,7 +144,7 @@ describe('loopback', function() { describe('data source created by loopback', function() { it('should create model extending Model by default', function() { var dataSource = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); var m1 = dataSource.createModel('m1', {}); assert(m1.prototype instanceof loopback.Model); @@ -161,14 +161,14 @@ describe('loopback', function() { describe('loopback.autoAttach', function() { it('doesn\'t overwrite model with datasource configured', function() { var ds1 = loopback.createDataSource('db1', { - connector: loopback.Memory + connector: loopback.Memory, }); // setup default data sources loopback.setDefaultDataSourceForType('db', ds1); var ds2 = loopback.createDataSource('db2', { - connector: loopback.Memory + connector: loopback.Memory, }); var model1 = ds2.createModel('m1', {}); @@ -186,7 +186,7 @@ describe('loopback', function() { describe('loopback.remoteMethod(Model, fn, [options]);', function() { it('Setup a remote method.', function() { - var Product = loopback.createModel('product', {price: Number}); + var Product = loopback.createModel('product', { price: Number }); Product.stats = function(fn) { // ... @@ -195,8 +195,8 @@ describe('loopback', function() { loopback.remoteMethod( Product.stats, { - returns: {arg: 'stats', type: 'array'}, - http: {path: '/info', verb: 'get'} + returns: { arg: 'stats', type: 'array' }, + http: { path: '/info', verb: 'get' }, } ); @@ -213,14 +213,14 @@ describe('loopback', function() { it('should extend from options.base', function() { var MyModel = loopback.createModel('MyModel', {}, { foo: { - bar: 'bat' - } + bar: 'bat', + }, }); var MyCustomModel = loopback.createModel('MyCustomModel', {}, { base: 'MyModel', foo: { - bat: 'baz' - } + bat: 'baz', + }, }); assert(MyCustomModel.super_ === MyModel); assert.deepEqual(MyCustomModel.settings.foo, { bar: 'bat', bat: 'baz' }); @@ -232,14 +232,14 @@ describe('loopback', function() { it('should be able to get model by name', function() { var MyModel = loopback.createModel('MyModel', {}, { foo: { - bar: 'bat' - } + bar: 'bat', + }, }); var MyCustomModel = loopback.createModel('MyCustomModel', {}, { base: 'MyModel', foo: { - bat: 'baz' - } + bat: 'baz', + }, }); assert(loopback.getModel('MyModel') === MyModel); assert(loopback.getModel('MyCustomModel') === MyCustomModel); @@ -249,14 +249,14 @@ describe('loopback', function() { it('should be able to get model by type', function() { var MyModel = loopback.createModel('MyModel', {}, { foo: { - bar: 'bat' - } + bar: 'bat', + }, }); var MyCustomModel = loopback.createModel('MyCustomModel', {}, { base: 'MyModel', foo: { - bat: 'baz' - } + bat: 'baz', + }, }); assert(loopback.getModelByType(MyModel) === MyCustomModel); assert(loopback.getModelByType(MyCustomModel) === MyCustomModel); @@ -273,13 +273,13 @@ describe('loopback', function() { methods: { staticMethod: { isStatic: true, - http: { path: '/static' } + http: { path: '/static' }, }, instanceMethod: { isStatic: false, - http: { path: '/instance' } - } - } + http: { path: '/instance' }, + }, + }, }); var methodNames = TestModel.sharedClass.methods().map(function(m) { @@ -288,7 +288,7 @@ describe('loopback', function() { expect(methodNames).to.include.members([ 'staticMethod', - 'prototype.instanceMethod' + 'prototype.instanceMethod', ]); }); }); @@ -296,7 +296,7 @@ describe('loopback', function() { describe('loopback.createModel(config)', function() { it('creates the model', function() { var model = loopback.createModel({ - name: uniqueModelName + name: uniqueModelName, }); expect(model.prototype).to.be.instanceof(loopback.Model); @@ -305,7 +305,7 @@ describe('loopback', function() { it('interprets extra first-level keys as options', function() { var model = loopback.createModel({ name: uniqueModelName, - base: 'User' + base: 'User', }); expect(model.prototype).to.be.instanceof(loopback.User); @@ -316,8 +316,8 @@ describe('loopback', function() { name: uniqueModelName, base: 'User', options: { - base: 'Application' - } + base: 'Application', + }, }); expect(model.prototype).to.be.instanceof(loopback.Application); @@ -333,9 +333,9 @@ describe('loopback', function() { relations: { owner: { type: 'belongsTo', - model: 'User' - } - } + model: 'User', + }, + }, }); expect(model.settings.relations).to.have.property('owner'); @@ -346,23 +346,23 @@ describe('loopback', function() { relations: { owner: { type: 'belongsTo', - model: 'User' - } - } + model: 'User', + }, + }, }); loopback.configureModel(model, { dataSource: false, relations: { owner: { - model: 'Application' - } - } + model: 'Application', + }, + }, }); expect(model.settings.relations.owner).to.eql({ type: 'belongsTo', - model: 'Application' + model: 'Application', }); }); @@ -375,9 +375,9 @@ describe('loopback', function() { relations: { owner: { type: 'belongsTo', - model: 'User' - } - } + model: 'User', + }, + }, }); var owner = model.prototype.owner; @@ -393,9 +393,9 @@ describe('loopback', function() { accessType: 'EXECUTE', principalType: 'ROLE', principalId: '$everyone', - permission: 'DENY' - } - ] + permission: 'DENY', + }, + ], }); loopback.configureModel(model, { @@ -406,9 +406,9 @@ describe('loopback', function() { accessType: 'EXECUTE', principalType: 'ROLE', principalId: 'admin', - permission: 'ALLOW' - } - ] + permission: 'ALLOW', + }, + ], }); expect(model.settings.acls).eql([ @@ -417,15 +417,15 @@ describe('loopback', function() { accessType: 'EXECUTE', principalType: 'ROLE', principalId: '$everyone', - permission: 'DENY' + permission: 'DENY', }, { property: 'find', accessType: 'EXECUTE', principalType: 'ROLE', principalId: 'admin', - permission: 'ALLOW' - } + permission: 'ALLOW', + }, ]); }); @@ -437,9 +437,9 @@ describe('loopback', function() { accessType: 'EXECUTE', principalType: 'ROLE', principalId: '$everyone', - permission: 'DENY' - } - ] + permission: 'DENY', + }, + ], }); loopback.configureModel(model, { @@ -450,9 +450,9 @@ describe('loopback', function() { accessType: 'EXECUTE', principalType: 'ROLE', principalId: '$everyone', - permission: 'ALLOW' - } - ] + permission: 'ALLOW', + }, + ], }); expect(model.settings.acls).eql([ @@ -461,15 +461,15 @@ describe('loopback', function() { accessType: 'EXECUTE', principalType: 'ROLE', principalId: '$everyone', - permission: 'ALLOW' - } + permission: 'ALLOW', + }, ]); }); it('updates existing settings', function() { var model = loopback.Model.extend(uniqueModelName, {}, { ttl: 10, - emailVerificationRequired: false + emailVerificationRequired: false, }); var baseName = model.settings.base.name; @@ -479,8 +479,8 @@ describe('loopback', function() { options: { ttl: 20, realmRequired: true, - base: 'X' - } + base: 'X', + }, }); expect(model.settings).to.have.property('ttl', 20); @@ -499,13 +499,13 @@ describe('loopback', function() { methods: { staticMethod: { isStatic: true, - http: { path: '/static' } + http: { path: '/static' }, }, instanceMethod: { isStatic: false, - http: { path: '/instance' } - } - } + http: { path: '/instance' }, + }, + }, }); var methodNames = TestModel.sharedClass.methods().map(function(m) { @@ -514,7 +514,7 @@ describe('loopback', function() { expect(methodNames).to.include.members([ 'staticMethod', - 'prototype.instanceMethod' + 'prototype.instanceMethod', ]); }); }); @@ -538,7 +538,7 @@ describe('loopback', function() { 'ACL', 'Scope', 'Change', - 'Checkpoint' + 'Checkpoint', ]; expect(Object.keys(loopback)).to.include.members(expectedModelNames); @@ -551,8 +551,7 @@ describe('loopback', function() { }); describe.onServer('loopback.getCurrentContext', function() { - var runInOtherDomain; - var runnerInterval; + var runInOtherDomain, runnerInterval; before(function setupRunInOtherDomain() { var emitterInOtherDomain = new EventEmitter(); @@ -594,7 +593,7 @@ describe('loopback', function() { TestModel.remoteMethod('test', { accepts: { arg: 'inst', type: uniqueModelName }, returns: { root: true }, - http: { path: '/test', verb: 'get' } + http: { path: '/test', verb: 'get' }, }); // after remote hook @@ -602,7 +601,7 @@ describe('loopback', function() { var tmpCtx = loopback.getCurrentContext(); if (tmpCtx) { ctxx.result.data = tmpCtx.get('data'); - }else { + } else { ctxx.result.data = 'context not available'; } next(); @@ -645,9 +644,9 @@ describe('loopback', function() { dataSource: null, methods: { staticMethod: { - http: { path: '/static' } - } - } + http: { path: '/static' }, + }, + }, }); var methodNames = getAllMethodNamesWithoutClassName(TestModel); @@ -661,9 +660,9 @@ describe('loopback', function() { dataSource: null, methods: { 'prototype.instanceMethod': { - http: { path: '/instance' } - } - } + http: { path: '/instance' }, + }, + }, }); var methodNames = getAllMethodNamesWithoutClassName(TestModel); @@ -673,15 +672,17 @@ describe('loopback', function() { it('throws an error when "isStatic:true" and method name starts with "prototype."', function() { var TestModel = loopback.createModel(uniqueModelName); - expect(function() { loopback.configureModel(TestModel, { - dataSource: null, - methods: { - 'prototype.instanceMethod': { - isStatic: true, - http: { path: '/instance' } - } - } - });}).to.throw(Error, new Error('Remoting metadata for' + TestModel.modelName + + expect(function() { + loopback.configureModel(TestModel, { + dataSource: null, + methods: { + 'prototype.instanceMethod': { + isStatic: true, + http: { path: '/instance' }, + }, + }, + }); + }).to.throw(Error, new Error('Remoting metadata for' + TestModel.modelName + ' "isStatic" does not match new method name-based style.')); }); @@ -692,9 +693,9 @@ describe('loopback', function() { methods: { staticMethod: { isStatic: true, - http: { path: '/static' } - } - } + http: { path: '/static' }, + }, + }, }); var methodNames = getAllMethodNamesWithoutClassName(TestModel); @@ -709,9 +710,9 @@ describe('loopback', function() { methods: { 'prototype.instanceMethod': { isStatic: false, - http: { path: '/instance' } - } - } + http: { path: '/instance' }, + }, + }, }); var methodNames = getAllMethodNamesWithoutClassName(TestModel); diff --git a/test/memory.test.js b/test/memory.test.js index 7d9feb70..01b47c78 100644 --- a/test/memory.test.js +++ b/test/memory.test.js @@ -7,22 +7,22 @@ describe('Memory Connector', function() { // or create it using the standard // data source creation api memory = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); // create a model using the // memory data source var properties = { name: String, - price: Number + 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}, + { name: 'apple', price: 0.79 }, + { name: 'pear', price: 1.29 }, + { name: 'orange', price: 0.59 }, ], count); function count() { diff --git a/test/model.application.test.js b/test/model.application.test.js index 96d8ab75..b3ac7634 100644 --- a/test/model.application.test.js +++ b/test/model.application.test.js @@ -7,7 +7,7 @@ describe('Application', function() { it('honors `application.register` - promise variant', function(done) { Application.register('rfeng', 'MyTestApp', - {description: 'My test application'}, function(err, result) { + { description: 'My test application' }, function(err, result) { var app = result; assert.equal(app.owner, 'rfeng'); assert.equal(app.name, 'MyTestApp'); @@ -18,7 +18,7 @@ describe('Application', function() { it('honors `application.register` - promise variant', function(done) { Application.register('rfeng', 'MyTestApp', - {description: 'My test application'}) + { description: 'My test application' }) .then(function(result) { var app = result; assert.equal(app.owner, 'rfeng'); @@ -32,9 +32,9 @@ describe('Application', function() { }); it('Create a new application', function(done) { - Application.create({owner: 'rfeng', + 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'); @@ -52,7 +52,7 @@ describe('Application', function() { }); it('Create a new application with push settings', function(done) { - Application.create({owner: 'rfeng', + Application.create({ owner: 'rfeng', name: 'MyAppWithPush', description: 'My push mobile application', pushSettings: { @@ -62,18 +62,18 @@ describe('Application', function() { keyData: 'key', pushOptions: { gateway: 'gateway.sandbox.push.apple.com', - port: 2195 + port: 2195, }, feedbackOptions: { gateway: 'feedback.sandbox.push.apple.com', port: 2196, interval: 300, - batchFeedback: true - } + batchFeedback: true, + }, }, gcm: { - serverApiKey: 'serverKey' - } + serverApiKey: 'serverKey', + }, }}, function(err, result) { var app = result; @@ -84,18 +84,18 @@ describe('Application', function() { keyData: 'key', pushOptions: { gateway: 'gateway.sandbox.push.apple.com', - port: 2195 + port: 2195, }, feedbackOptions: { gateway: 'feedback.sandbox.push.apple.com', port: 2196, interval: 300, - batchFeedback: true - } + batchFeedback: true, + }, }, gcm: { - serverApiKey: 'serverKey' - } + serverApiKey: 'serverKey', + }, }); done(err, result); }); @@ -103,7 +103,7 @@ describe('Application', function() { 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'); @@ -211,10 +211,10 @@ describe('Application', function() { function(done) { Application.authenticate(registeredApp.id, registeredApp.clientKey) .then(function(result) { - assert.equal(result.application.id, registeredApp.id); - assert.equal(result.keyType, 'clientKey'); - done(); - }) + assert.equal(result.application.id, registeredApp.id); + assert.equal(result.keyType, 'clientKey'); + done(); + }) .catch(function(err) { done(err); }); @@ -280,10 +280,10 @@ describe('Application', function() { describe('Application subclass', function() { it('should use subclass model name', function(done) { var MyApp = Application.extend('MyApp'); - var ds = loopback.createDataSource({connector: loopback.Memory}); + 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'); diff --git a/test/model.test.js b/test/model.test.js index b9a16f36..f9a16e0a 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -10,8 +10,8 @@ var describe = require('./util/describe'); describe('Model / PersistedModel', function() { defineModelTestsWithDataSource({ dataSource: { - connector: loopback.Memory - } + connector: loopback.Memory, + }, }); describe('Model.validatesUniquenessOf(property, options)', function() { @@ -23,19 +23,19 @@ describe('Model / PersistedModel', function() { 'password': String, 'gender': String, 'domain': String, - 'email': String + 'email': String, }); var dataSource = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); User.attachTo(dataSource); - User.validatesUniquenessOf('email', {message: 'email is not unique'}); + User.validatesUniquenessOf('email', { message: 'email is not unique' }); - var joe = new User({email: 'joe@joe.com'}); - var joe2 = new User({email: 'joe@joe.com'}); + var joe = new User({ email: 'joe@joe.com' }); + var joe2 = new User({ email: 'joe@joe.com' }); joe.save(function() { joe2.save(function(err) { @@ -50,25 +50,23 @@ describe('Model / PersistedModel', function() { describe('Model.attachTo(dataSource)', function() { it('Attach a model to a [DataSource](#data-source)', function() { - var MyModel = loopback.createModel('my-model', {name: String}); + var MyModel = loopback.createModel('my-model', { name: String }); var dataSource = loopback.createDataSource({ - connector: loopback.Memory + 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'); + assert(results.length === 0, + 'should have data access methods after attaching to a data source'); }); }); }); }); describe.onServer('Remote Methods', function() { - - var User, Post; - var dataSource; - var app; + var User, Post, dataSource, app; beforeEach(function() { User = PersistedModel.extend('user', { @@ -79,21 +77,21 @@ describe.onServer('Remote Methods', function() { 'password': String, 'gender': String, 'domain': String, - 'email': String + 'email': String, }, { - trackChanges: true + trackChanges: true, }); Post = PersistedModel.extend('post', { id: { id: true, type: String, defaultFn: 'guid' }, title: String, - content: String + content: String, }, { - trackChanges: true + trackChanges: true, }); dataSource = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); User.attachTo(dataSource); @@ -113,11 +111,11 @@ describe.onServer('Remote Methods', function() { User.login, { accepts: [ - {arg: 'username', type: 'string', required: true}, - {arg: 'password', type: 'string', required: true} + { arg: 'username', type: 'string', required: true }, + { arg: 'password', type: 'string', required: true }, ], - returns: {arg: 'sessionId', type: 'any', root: true}, - http: {path: '/sign-in', verb: 'get'} + returns: { arg: 'sessionId', type: 'any', root: true }, + http: { path: '/sign-in', verb: 'get' }, } ); @@ -129,11 +127,11 @@ describe.onServer('Remote Methods', function() { describe('Model.destroyAll(callback)', function() { 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'}) + .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() { @@ -178,7 +176,7 @@ describe.onServer('Remote Methods', function() { it('Call the findById with filter.fields using HTTP / REST', function(done) { request(app) .post('/users') - .send({first: 'x', last: 'y'}) + .send({ first: 'x', last: 'y' }) .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { @@ -201,7 +199,7 @@ describe.onServer('Remote Methods', function() { it('Call the findById with filter.include using HTTP / REST', function(done) { request(app) .post('/users') - .send({first: 'x', last: 'y'}) + .send({ first: 'x', last: 'y' }) .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { @@ -210,7 +208,7 @@ describe.onServer('Remote Methods', function() { assert(userId); request(app) .post('/users/' + userId + '/posts') - .send({title: 'T1', content: 'C1'}) + .send({ title: 'T1', content: 'C1' }) .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { @@ -230,7 +228,6 @@ describe.onServer('Remote Methods', function() { }); }); }); - }); describe('Model.beforeRemote(name, fn)', function() { @@ -245,7 +242,7 @@ describe.onServer('Remote Methods', function() { // invoke save request(app) .post('/users') - .send({data: {first: 'foo', last: 'bar'}}) + .send({ data: { first: 'foo', last: 'bar' }}) .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { @@ -275,7 +272,7 @@ describe.onServer('Remote Methods', function() { // invoke save request(app) .post('/users') - .send({data: {first: 'foo', last: 'bar'}}) + .send({ data: { first: 'foo', last: 'bar' }}) .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { @@ -324,7 +321,7 @@ describe.onServer('Remote Methods', function() { // invoke save request(app) .post('/users') - .send({data: {first: 'foo', last: 'bar'}}) + .send({ data: { first: 'foo', last: 'bar' }}) .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { @@ -353,7 +350,7 @@ describe.onServer('Remote Methods', function() { // invoke save request(app) .post('/users') - .send({data: {first: 'foo', last: 'bar'}}) + .send({ data: { first: 'foo', last: 'bar' }}) .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { @@ -367,20 +364,20 @@ describe.onServer('Remote Methods', function() { describe('Model.hasMany(Model)', function() { 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}); + 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) { + 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() { + 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) { + Chapter.count({ bookId: book.id }, function(err, count) { assert.equal(count, 2); - book.chapters({where: {title: 'Chapter 1'}}, function(err, chapters) { + book.chapters({ where: { title: 'Chapter 1' }}, function(err, chapters) { assert.equal(chapters.length, 1); assert.equal(chapters[0].title, 'Chapter 1'); done(); @@ -396,10 +393,10 @@ describe.onServer('Remote Methods', function() { it('Normalized properties passed in originally by loopback.createModel()', function() { var props = { s: String, - n: {type: 'Number'}, - o: {type: 'String', min: 10, max: 100}, + n: { type: 'Number' }, + o: { type: 'String', min: 10, max: 100 }, d: Date, - g: loopback.GeoPoint + g: loopback.GeoPoint, }; var MyModel = loopback.createModel('foo', props); @@ -426,7 +423,7 @@ describe.onServer('Remote Methods', 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 + email: String, }); User.foo = function() { @@ -439,7 +436,7 @@ describe.onServer('Remote Methods', function() { var MyUser = User.extend('my-user', { a: String, - b: String + b: String, }); assert.equal(MyUser.prototype.bar, User.prototype.bar); @@ -448,7 +445,7 @@ describe.onServer('Remote Methods', function() { var user = new MyUser({ email: 'foo@bar.com', a: 'foo', - b: 'bar' + b: 'bar', }); assert.equal(user.email, 'foo@bar.com'); @@ -461,11 +458,11 @@ describe.onServer('Remote Methods', function() { it('create isolated emitters for subclasses', function() { var User1 = loopback.createModel('User1', { 'first': String, - 'last': String + 'last': String, }); var User2 = loopback.createModel('User2', { - 'name': String + 'name': String, }); var user1Triggered = false; @@ -486,7 +483,6 @@ describe.onServer('Remote Methods', function() { assert(user1Triggered); assert(!user2Triggered); }); - }); describe('Model.checkAccessTypeForMethod(remoteMethod)', function() { @@ -506,7 +502,7 @@ describe.onServer('Remote Methods', function() { function shouldReturn(methodName, expectedAccessType) { describe(methodName, function() { it('should return ' + expectedAccessType, function() { - var remoteMethod = {name: methodName}; + var remoteMethod = { name: methodName }; assert.equal( User._getAccessTypeForMethod(remoteMethod), expectedAccessType @@ -538,10 +534,9 @@ describe.onServer('Remote Methods', function() { var Checkpoint = User.getChangeModel().getCheckpointModel(); var tasks = [ getCurrentCheckpoint, - checkpoint + checkpoint, ]; - var result; - var current; + var result, current; async.series(tasks, function(err) { if (err) return done(err); @@ -615,7 +610,7 @@ describe.onServer('Remote Methods', function() { 'removeById', 'count', 'prototype.updateAttributes', - 'createChangeStream' + 'createChangeStream', ]); }); }); diff --git a/test/registries.test.js b/test/registries.test.js index 8f44ac42..688af98d 100644 --- a/test/registries.test.js +++ b/test/registries.test.js @@ -5,11 +5,11 @@ describe('Registry', function() { var appBar = loopback(); var modelName = 'MyModel'; var subModelName = 'Sub' + modelName; - var settings = {base: 'PersistedModel'}; + var settings = { base: 'PersistedModel' }; appFoo.set('perAppRegistries', true); appBar.set('perAppRegistries', true); - var dsFoo = appFoo.dataSource('dsFoo', {connector: 'memory'}); - var dsBar = appFoo.dataSource('dsBar', {connector: 'memory'}); + var dsFoo = appFoo.dataSource('dsFoo', { connector: 'memory' }); + var dsBar = appFoo.dataSource('dsBar', { connector: 'memory' }); var FooModel = appFoo.model(modelName, settings); var FooSubModel = appFoo.model(subModelName, settings); @@ -26,9 +26,9 @@ describe('Registry', function() { expect(appFoo.models[modelName]).to.not.equal(appBar.models[modelName]); - BarModel.create({name: 'bar'}, function(err, bar) { + BarModel.create({ name: 'bar' }, function(err, bar) { assert(!err); - bar.subMyModels.create({parent: 'bar'}, function(err) { + bar.subMyModels.create({ parent: 'bar' }, function(err) { assert(!err); FooSubModel.find(function(err, foos) { assert(!err); diff --git a/test/relations.integration.js b/test/relations.integration.js index cbc59e34..ef84bd23 100644 --- a/test/relations.integration.js +++ b/test/relations.integration.js @@ -1,5 +1,3 @@ -/*jshint -W030 */ - var loopback = require('../'); var lt = require('./helpers/loopback-testing-helper'); var path = require('path'); @@ -11,14 +9,13 @@ var debug = require('debug')('loopback:test:relations.integration'); var async = require('async'); describe('relations - integration', function() { - lt.beforeEach.withApp(app); lt.beforeEach.givenModel('store'); beforeEach(function(done) { this.widgetName = 'foo'; this.store.widgets.create({ - name: this.widgetName + name: this.widgetName, }, function() { done(); }); @@ -28,37 +25,36 @@ describe('relations - integration', function() { }); describe('polymorphicHasMany', function() { - before(function defineProductAndCategoryModels() { var Team = app.model( 'Team', { properties: { name: 'string' }, - dataSource: 'db' + dataSource: 'db', } ); var Reader = app.model( 'Reader', { properties: { name: 'string' }, - dataSource: 'db' + dataSource: 'db', } ); var Picture = app.model( 'Picture', - { properties: { name: 'string', imageableId: 'number', imageableType: 'string'}, - dataSource: 'db' + { properties: { name: 'string', imageableId: 'number', imageableType: 'string' }, + dataSource: 'db', } ); Reader.hasMany(Picture, { polymorphic: { // alternative syntax as: 'imageable', // if not set, default to: reference foreignKey: 'imageableId', // defaults to 'as + Id' - discriminator: 'imageableType' // defaults to 'as + Type' - } }); + discriminator: 'imageableType', // defaults to 'as + Type' + }}); Picture.belongsTo('imageable', { polymorphic: { foreignKey: 'imageableId', - discriminator: 'imageableType' - } }); + discriminator: 'imageableType', + }}); Reader.belongsTo(Team); }); @@ -89,14 +85,14 @@ describe('relations - integration', function() { it('includes the related child model', function(done) { var url = '/api/readers/' + this.reader.id; this.get(url) - .query({'filter': {'include' : 'pictures'}}) + .query({ 'filter': { 'include': 'pictures' }}) .expect(200, function(err, res) { if (err) return done(err); // console.log(res.body); expect(res.body.name).to.be.equal('Reader 1'); expect(res.body.pictures).to.be.eql([ - { name: 'Picture 1', id: 1, imageableId: 1, imageableType: 'Reader'}, - { name: 'Picture 2', id: 2, imageableId: 1, imageableType: 'Reader'}, + { name: 'Picture 1', id: 1, imageableId: 1, imageableType: 'Reader' }, + { name: 'Picture 2', id: 2, imageableId: 1, imageableType: 'Reader' }, ]); done(); }); @@ -105,13 +101,13 @@ describe('relations - integration', function() { it('includes the related parent model', function(done) { var url = '/api/pictures'; this.get(url) - .query({'filter': {'include' : 'imageable'}}) + .query({ 'filter': { 'include': 'imageable' }}) .expect(200, function(err, res) { if (err) return done(err); // console.log(res.body); expect(res.body[0].name).to.be.equal('Picture 1'); expect(res.body[1].name).to.be.equal('Picture 2'); - expect(res.body[0].imageable).to.be.eql({ name: 'Reader 1', id: 1, teamId: 1}); + expect(res.body[0].imageable).to.be.eql({ name: 'Reader 1', id: 1, teamId: 1 }); done(); }); }); @@ -119,17 +115,19 @@ describe('relations - integration', function() { it('includes related models scoped to the related parent model', function(done) { var url = '/api/pictures'; this.get(url) - .query({'filter': {'include' : {'relation': 'imageable', 'scope': { 'include' : 'team'}}}}) + .query({ 'filter': { 'include': { + 'relation': 'imageable', + 'scope': { 'include': 'team' }, + }}}) .expect(200, function(err, res) { if (err) return done(err); expect(res.body[0].name).to.be.equal('Picture 1'); expect(res.body[1].name).to.be.equal('Picture 2'); expect(res.body[0].imageable.name).to.be.eql('Reader 1'); - expect(res.body[0].imageable.team).to.be.eql({ name: 'Team 1', id: 1}); + expect(res.body[0].imageable.team).to.be.eql({ name: 'Team 1', id: 1 }); done(); }); }); - }); describe('/store/superStores', function() { @@ -148,7 +146,6 @@ describe('relations - integration', function() { this.url = '/api/stores/' + this.store.id + '/widgets'; }); lt.describe.whenCalledRemotely('GET', '/api/stores/:id/widgets', function() { - it('should succeed with statusCode 200', function() { assert.equal(this.res.statusCode, 200); }); @@ -180,7 +177,7 @@ describe('relations - integration', function() { beforeEach(function() { this.newWidgetName = 'baz'; this.newWidget = { - name: this.newWidgetName + name: this.newWidgetName, }; }); beforeEach(function(done) { @@ -212,7 +209,7 @@ describe('relations - integration', function() { }); it('should have a single widget with storeId', function(done) { this.app.models.widget.count({ - storeId: this.store.id + storeId: this.store.id, }, function(err, count) { if (err) return done(err); assert.equal(count, 2); @@ -226,7 +223,7 @@ describe('relations - integration', function() { beforeEach(function(done) { var self = this; this.store.widgets.create({ - name: this.widgetName + name: this.widgetName, }, function(err, widget) { self.widget = widget; self.url = '/api/stores/' + self.store.id + '/widgets/' + widget.id; @@ -299,7 +296,7 @@ describe('relations - integration', function() { beforeEach(function(done) { var self = this; this.store.widgets.create({ - name: this.widgetName + name: this.widgetName, }, function(err, widget) { self.widget = widget; self.url = '/api/widgets/' + self.widget.id + '/store'; @@ -315,7 +312,6 @@ describe('relations - integration', function() { }); describe('hasMany through', function() { - function setup(connecting, cb) { var root = {}; @@ -334,7 +330,7 @@ describe('relations - integration', function() { // Create a physician function(done) { app.models.physician.create({ - name: 'ph1' + name: 'ph1', }, function(err, physician) { root.physician = physician; done(); @@ -344,7 +340,7 @@ describe('relations - integration', function() { // Create a patient connecting ? function(done) { root.physician.patients.create({ - name: 'pa1' + name: 'pa1', }, function(err, patient) { root.patient = patient; root.relUrl = '/api/physicians/' + root.physician.id + @@ -353,7 +349,7 @@ describe('relations - integration', function() { }); } : function(done) { app.models.patient.create({ - name: 'pa1' + name: 'pa1', }, function(err, patient) { root.patient = patient; root.relUrl = '/api/physicians/' + root.physician.id + @@ -366,7 +362,6 @@ describe('relations - integration', function() { } describe('PUT /physicians/:id/patients/rel/:fk', function() { - before(function(done) { var self = this; setup(false, function(err, root) { @@ -405,7 +400,6 @@ describe('relations - integration', function() { }); describe('PUT /physicians/:id/patients/rel/:fk with data', function() { - before(function(done) { var self = this; setup(false, function(err, root) { @@ -450,7 +444,6 @@ describe('relations - integration', function() { }); describe('HEAD /physicians/:id/patients/rel/:fk', function() { - before(function(done) { var self = this; setup(true, function(err, root) { @@ -469,7 +462,6 @@ describe('relations - integration', function() { }); describe('HEAD /physicians/:id/patients/rel/:fk that does not exist', function() { - before(function(done) { var self = this; setup(true, function(err, root) { @@ -489,7 +481,6 @@ describe('relations - integration', function() { }); describe('DELETE /physicians/:id/patients/rel/:fk', function() { - before(function(done) { var self = this; setup(true, function(err, root) { @@ -543,7 +534,6 @@ describe('relations - integration', function() { }); describe('GET /physicians/:id/patients/:fk', function() { - before(function(done) { var self = this; setup(true, function(err, root) { @@ -564,7 +554,6 @@ describe('relations - integration', function() { }); describe('DELETE /physicians/:id/patients/:fk', function() { - before(function(done) { var self = this; setup(true, function(err, root) { @@ -605,7 +594,6 @@ describe('relations - integration', function() { done(); }); }); - }); }); }); @@ -630,7 +618,7 @@ describe('relations - integration', function() { beforeEach(function createProductsInCategory(done) { var test = this; this.category.products.create({ - name: 'a-product' + name: 'a-product', }, function(err, product) { if (err) return done(err); test.product = product; @@ -659,8 +647,8 @@ describe('relations - integration', function() { expect(res.body).to.eql([ { id: expectedProduct.id, - name: expectedProduct.name - } + name: expectedProduct.name, + }, ]); done(); }); @@ -674,8 +662,8 @@ describe('relations - integration', function() { expect(res.body).to.eql([ { id: expectedProduct.id, - name: expectedProduct.name - } + name: expectedProduct.name, + }, ]); done(); }); @@ -693,8 +681,8 @@ describe('relations - integration', function() { expect(res.body.products).to.eql([ { id: expectedProduct.id, - name: expectedProduct.name - } + name: expectedProduct.name, + }, ]); done(); }); @@ -713,8 +701,8 @@ describe('relations - integration', function() { expect(res.body.products).to.eql([ { id: expectedProduct.id, - name: expectedProduct.name - } + name: expectedProduct.name, + }, ]); done(); }); @@ -722,13 +710,12 @@ describe('relations - integration', function() { }); describe('embedsOne', function() { - before(function defineGroupAndPosterModels() { var group = app.model( 'group', { properties: { name: 'string' }, dataSource: 'db', - plural: 'groups' + plural: 'groups', } ); var poster = app.model( @@ -825,17 +812,15 @@ describe('relations - integration', function() { var url = '/api/groups/' + this.group.id + '/cover'; this.get(url).expect(404, done); }); - }); describe('embedsMany', function() { - before(function defineProductAndCategoryModels() { var todoList = app.model( 'todoList', { properties: { name: 'string' }, dataSource: 'db', - plural: 'todo-lists' + plural: 'todo-lists', } ); var todoItem = app.model( @@ -870,7 +855,7 @@ describe('relations - integration', function() { expect(res.body.name).to.be.equal('List A'); expect(res.body.todoItems).to.be.eql([ { content: 'Todo 1', id: 1 }, - { content: 'Todo 2', id: 2 } + { content: 'Todo 2', id: 2 }, ]); done(); }); @@ -884,7 +869,7 @@ describe('relations - integration', function() { if (err) return done(err); expect(res.body).to.be.eql([ { content: 'Todo 1', id: 1 }, - { content: 'Todo 2', id: 2 } + { content: 'Todo 2', id: 2 }, ]); done(); }); @@ -898,7 +883,7 @@ describe('relations - integration', function() { .expect(200, function(err, res) { if (err) return done(err); expect(res.body).to.be.eql([ - { content: 'Todo 2', id: 2 } + { content: 'Todo 2', id: 2 }, ]); done(); }); @@ -926,7 +911,7 @@ describe('relations - integration', function() { expect(res.body).to.be.eql([ { content: 'Todo 1', id: 1 }, { content: 'Todo 2', id: 2 }, - { content: 'Todo 3', id: 3 } + { content: 'Todo 3', id: 3 }, ]); done(); }); @@ -963,7 +948,7 @@ describe('relations - integration', function() { if (err) return done(err); expect(res.body).to.be.eql([ { content: 'Todo 1', id: 1 }, - { content: 'Todo 3', id: 3 } + { content: 'Todo 3', id: 3 }, ]); done(); }); @@ -997,11 +982,9 @@ describe('relations - integration', function() { done(); }); }); - }); describe('referencesMany', function() { - before(function defineProductAndCategoryModels() { var recipe = app.model( 'recipe', @@ -1018,8 +1001,8 @@ describe('relations - integration', function() { recipe.referencesMany(ingredient); // contrived example for test: recipe.hasOne(photo, { as: 'picture', options: { - http: { path: 'image' } - } }); + http: { path: 'image' }, + }}); }); before(function createRecipe(done) { @@ -1090,7 +1073,7 @@ describe('relations - integration', function() { expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, { name: 'Sugar', id: test.ingredient2 }, - { name: 'Butter', id: test.ingredient3 } + { name: 'Butter', id: test.ingredient3 }, ]); done(); }); @@ -1105,7 +1088,7 @@ describe('relations - integration', function() { if (err) return done(err); expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, - { name: 'Butter', id: test.ingredient3 } + { name: 'Butter', id: test.ingredient3 }, ]); done(); }); @@ -1120,7 +1103,7 @@ describe('relations - integration', function() { .expect(200, function(err, res) { if (err) return done(err); expect(res.body).to.be.eql([ - { name: 'Butter', id: test.ingredient3 } + { name: 'Butter', id: test.ingredient3 }, ]); done(); }); @@ -1135,11 +1118,11 @@ describe('relations - integration', function() { .expect(200, function(err, res) { if (err) return done(err); expect(res.body.ingredientIds).to.eql([ - test.ingredient1, test.ingredient3 + test.ingredient1, test.ingredient3, ]); expect(res.body.ingredients).to.eql([ { name: 'Chocolate', id: test.ingredient1 }, - { name: 'Butter', id: test.ingredient3 } + { name: 'Butter', id: test.ingredient3 }, ]); done(); }); @@ -1195,7 +1178,7 @@ describe('relations - integration', function() { if (err) return done(err); expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, - { name: 'Sugar', id: test.ingredient2 } + { name: 'Sugar', id: test.ingredient2 }, ]); done(); }); @@ -1209,7 +1192,7 @@ describe('relations - integration', function() { .expect(200, function(err, res) { if (err) return done(err); expect(res.body).to.be.eql([ - { name: 'Chocolate', id: test.ingredient1 } + { name: 'Chocolate', id: test.ingredient1 }, ]); done(); }); @@ -1238,7 +1221,7 @@ describe('relations - integration', function() { if (err) return done(err); expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, - { name: 'Sugar', id: test.ingredient2 } + { name: 'Sugar', id: test.ingredient2 }, ]); done(); }); @@ -1263,7 +1246,7 @@ describe('relations - integration', function() { .expect(200, function(err, res) { if (err) return done(err); expect(res.body).to.be.eql([ - { name: 'Sugar', id: test.ingredient2 } + { name: 'Sugar', id: test.ingredient2 }, ]); done(); }); @@ -1278,7 +1261,7 @@ describe('relations - integration', function() { if (err) return done(err); expect(res.body).to.be.eql([ { name: 'Chocolate', id: test.ingredient1 }, - { name: 'Sugar', id: test.ingredient2 } + { name: 'Sugar', id: test.ingredient2 }, ]); done(); }); @@ -1315,11 +1298,9 @@ describe('relations - integration', function() { done(); }); }); - }); describe('nested relations', function() { - before(function defineModels() { var Book = app.model( 'Book', @@ -1357,7 +1338,7 @@ describe('relations - integration', function() { throw new Error('This should not crash the app'); }; - Page.remoteMethod('__throw__errors', { isStatic: false, http: { path: '/throws', verb: 'get' } }); + Page.remoteMethod('__throw__errors', { isStatic: false, http: { path: '/throws', verb: 'get' }}); Book.nestRemoting('pages'); Book.nestRemoting('chapters'); @@ -1375,7 +1356,6 @@ describe('relations - integration', function() { ctx.res.set('x-after', 'after'); next(); }); - }); before(function createBook(done) { @@ -1573,7 +1553,7 @@ describe('relations - integration', function() { var url = '/api/customers/' + cust.id + '/profile'; this.post(url) - .send({points: 10}) + .send({ points: 10 }) .expect(200, function(err, res) { if (err) { return done(err); @@ -1600,7 +1580,7 @@ describe('relations - integration', function() { it('should not create the referenced model twice', function(done) { var url = '/api/customers/' + cust.id + '/profile'; this.post(url) - .send({points: 20}) + .send({ points: 20 }) .expect(500, function(err, res) { done(err); }); @@ -1609,7 +1589,7 @@ describe('relations - integration', function() { it('should update the referenced model', function(done) { var url = '/api/customers/' + cust.id + '/profile'; this.put(url) - .send({points: 100}) + .send({ points: 100 }) .expect(200, function(err, res) { if (err) { return done(err); @@ -1636,5 +1616,4 @@ describe('relations - integration', function() { }); }); }); - }); diff --git a/test/remote-connector.test.js b/test/remote-connector.test.js index e267c2e8..5e241b1a 100644 --- a/test/remote-connector.test.js +++ b/test/remote-connector.test.js @@ -2,8 +2,7 @@ var loopback = require('../'); var defineModelTestsWithDataSource = require('./util/model-tests'); describe('RemoteConnector', function() { - var remoteApp; - var remote; + var remoteApp, remote; defineModelTestsWithDataSource({ beforeEach: function(done) { @@ -14,7 +13,7 @@ describe('RemoteConnector', function() { test.dataSource = loopback.createDataSource({ host: 'localhost', port: remoteApp.get('port'), - connector: loopback.Remote + connector: loopback.Remote, }); done(); }); @@ -23,10 +22,10 @@ describe('RemoteConnector', function() { var RemoteModel = Model.extend('Remote' + Model.modelName, {}, { plural: Model.pluralModelName }); RemoteModel.attachTo(loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, })); remoteApp.model(RemoteModel); - } + }, }); beforeEach(function(done) { @@ -41,7 +40,7 @@ describe('RemoteConnector', function() { test.remote = loopback.createDataSource({ host: 'localhost', port: remoteApp.get('port'), - connector: loopback.Remote + connector: loopback.Remote, }); done(); }); @@ -62,7 +61,7 @@ describe('RemoteConnector', function() { ServerModel.setupRemoting(); - var m = new RemoteModel({foo: 'bar'}); + var m = new RemoteModel({ foo: 'bar' }); m.save(function(err, inst) { if (err) return done(err); assert(inst instanceof RemoteModel); diff --git a/test/remoting-coercion.test.js b/test/remoting-coercion.test.js index 6dab48e0..1b06d77d 100644 --- a/test/remoting-coercion.test.js +++ b/test/remoting-coercion.test.js @@ -7,7 +7,7 @@ describe('remoting coercion', function() { var app = loopback(); app.use(loopback.rest()); - var TestModel = app.model('TestModel', {base: 'Model', dataSource: null, public: true}); + var TestModel = app.model('TestModel', { base: 'Model', dataSource: null, public: true }); TestModel.test = function(inst, cb) { called = true; assert(inst instanceof TestModel); @@ -15,15 +15,15 @@ describe('remoting coercion', function() { cb(); }; TestModel.remoteMethod('test', { - accepts: {arg: 'inst', type: 'TestModel', http: {source: 'body'}}, - http: {path: '/test', verb: 'post'} + accepts: { arg: 'inst', type: 'TestModel', http: { source: 'body' }}, + http: { path: '/test', verb: 'post' }, }); request(app) .post('/TestModels/test') .set('Content-Type', 'application/json') .send({ - foo: 'bar' + foo: 'bar', }) .end(function(err) { if (err) return done(err); diff --git a/test/remoting.integration.js b/test/remoting.integration.js index 198c378c..646fc923 100644 --- a/test/remoting.integration.js +++ b/test/remoting.integration.js @@ -6,7 +6,6 @@ var app = require(path.join(SIMPLE_APP, 'server/server.js')); var assert = require('assert'); describe('remoting - integration', function() { - lt.beforeEach.withApp(app); lt.beforeEach.givenModel('store'); @@ -17,8 +16,8 @@ describe('remoting - integration', 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() { @@ -34,7 +33,7 @@ describe('remoting - integration', function() { } this.http = this.post('/api/stores'); this.http.send({ - 'name': name + 'name': name, }); this.http.end(function(err) { if (err) return done(err); @@ -53,7 +52,7 @@ describe('remoting - integration', function() { } this.http = this.post('/api/stores'); this.http.send({ - 'name': name + 'name': name, }); this.http.end(function(err) { if (err) return done(err); @@ -88,7 +87,7 @@ describe('remoting - integration', function() { ' ', m.getHttpMethod(), ' ', - m.getFullPath() + m.getFullPath(), ].join(''); } @@ -121,7 +120,7 @@ describe('remoting - integration', function() { 'deleteById(id:any):object DELETE /stores/:id', 'count(where:object):number GET /stores/count', 'prototype.updateAttributes(data:object):store PUT /stores/:id', - 'createChangeStream(options:object):ReadableStream POST /stores/change-stream' + 'createChangeStream(options:object):ReadableStream POST /stores/change-stream', ]; // The list of methods is from docs: @@ -143,7 +142,7 @@ describe('remoting - integration', function() { '__get__superStores(filter:object):store GET /stores/superStores', '__create__superStores(data:store):store POST /stores/superStores', '__delete__superStores() DELETE /stores/superStores', - '__count__superStores(where:object):number GET /stores/superStores/count' + '__count__superStores(where:object):number GET /stores/superStores/count', ]; expect(methods).to.include.members(expectedMethods); @@ -151,7 +150,6 @@ describe('remoting - integration', function() { it('should have correct signatures for belongsTo methods', function() { - var widgetClass = findClass('widget'); var methods = widgetClass.methods .filter(function(m) { @@ -162,15 +160,14 @@ describe('remoting - integration', function() { }); var expectedMethods = [ - 'prototype.__get__store(refresh:boolean):store ' + - 'GET /widgets/:id/store' + 'prototype.__get__store(refresh:boolean):store ' + + 'GET /widgets/:id/store', ]; expect(methods).to.include.members(expectedMethods); }); it('should have correct signatures for hasMany methods', function() { - var physicianClass = findClass('store'); var methods = physicianClass.methods .filter(function(m) { @@ -181,29 +178,28 @@ describe('remoting - integration', function() { }); var expectedMethods = [ - 'prototype.__findById__widgets(fk:any):widget ' + + 'prototype.__findById__widgets(fk:any):widget ' + 'GET /stores/:id/widgets/:fk', - 'prototype.__destroyById__widgets(fk:any) ' + + 'prototype.__destroyById__widgets(fk:any) ' + 'DELETE /stores/:id/widgets/:fk', - 'prototype.__updateById__widgets(fk:any,data:widget):widget ' + + 'prototype.__updateById__widgets(fk:any,data:widget):widget ' + 'PUT /stores/:id/widgets/:fk', - 'prototype.__get__widgets(filter:object):widget ' + + 'prototype.__get__widgets(filter:object):widget ' + 'GET /stores/:id/widgets', - 'prototype.__create__widgets(data:widget):widget ' + + 'prototype.__create__widgets(data:widget):widget ' + 'POST /stores/:id/widgets', - 'prototype.__delete__widgets() ' + + 'prototype.__delete__widgets() ' + 'DELETE /stores/:id/widgets', - 'prototype.__count__widgets(where:object):number ' + - 'GET /stores/:id/widgets/count' + 'prototype.__count__widgets(where:object):number ' + + 'GET /stores/:id/widgets/count', ]; expect(methods).to.include.members(expectedMethods); }); it('should have correct signatures for hasMany-through methods', function() { // jscs:disable validateIndentation - - var physicianClass = findClass('physician'); - var methods = physicianClass.methods + var physicianClass = findClass('physician'); + var methods = physicianClass.methods .filter(function(m) { return m.name.indexOf('prototype.__') === 0; }) @@ -211,7 +207,7 @@ describe('remoting - integration', function() { return formatMethod(m); }); - var expectedMethods = [ + var expectedMethods = [ 'prototype.__findById__patients(fk:any):patient ' + 'GET /physicians/:id/patients/:fk', 'prototype.__destroyById__patients(fk:any) ' + @@ -231,10 +227,9 @@ describe('remoting - integration', function() { 'prototype.__delete__patients() ' + 'DELETE /physicians/:id/patients', 'prototype.__count__patients(where:object):number ' + - 'GET /physicians/:id/patients/count' - ]; - expect(methods).to.include.members(expectedMethods); - }); + 'GET /physicians/:id/patients/count', + ]; + expect(methods).to.include.members(expectedMethods); + }); }); - }); diff --git a/test/replication.rest.test.js b/test/replication.rest.test.js index 6316457f..e6794cb1 100644 --- a/test/replication.rest.test.js +++ b/test/replication.rest.test.js @@ -10,10 +10,12 @@ describe('Replication over REST', function() { var PETER = { id: 'p', username: 'peter', email: 'p@t.io', password: 'p' }; var EMERY = { id: 'e', username: 'emery', email: 'e@t.io', password: 'p' }; + /* eslint-disable one-var */ var serverApp, serverUrl, ServerUser, ServerCar, serverCars; var aliceId, peterId, aliceToken, peterToken, emeryToken, request; var clientApp, LocalUser, LocalCar, RemoteUser, RemoteCar, clientCars; var conflictedCarId; + /* eslint-enable one-var */ before(setupServer); before(setupClient); @@ -322,7 +324,7 @@ describe('Replication over REST', function() { .to.have.property('fullname', 'Alice Smith'); next(); }); - } + }, ], done); }); @@ -347,7 +349,7 @@ describe('Replication over REST', function() { .to.not.have.property('fullname'); next(); }); - } + }, ], done); }); @@ -367,7 +369,7 @@ describe('Replication over REST', function() { }); var USER_PROPS = { - id: { type: 'string', id: true } + id: { type: 'string', id: true }, }; var USER_OPTS = { @@ -375,13 +377,13 @@ describe('Replication over REST', function() { plural: 'Users', // use the same REST path in all models trackChanges: true, strict: 'throw', - persistUndefinedAsNull: true + persistUndefinedAsNull: true, }; var CAR_PROPS = { id: { type: 'string', id: true, defaultFn: 'guid' }, model: { type: 'string', required: true }, - maker: { type: 'string' } + maker: { type: 'string' }, }; var CAR_OPTS = { @@ -395,30 +397,30 @@ describe('Replication over REST', function() { { principalType: 'ROLE', principalId: '$everyone', - permission: 'DENY' + permission: 'DENY', }, // allow all authenticated users to read data { principalType: 'ROLE', principalId: '$authenticated', permission: 'ALLOW', - accessType: 'READ' + accessType: 'READ', }, // allow Alice to pull changes { principalType: 'USER', principalId: ALICE.id, permission: 'ALLOW', - accessType: 'REPLICATE' + accessType: 'REPLICATE', }, // allow Peter to write data { principalType: 'USER', principalId: PETER.id, permission: 'ALLOW', - accessType: 'WRITE' - } - ] + accessType: 'WRITE', + }, + ], }; function setupServer(done) { @@ -435,9 +437,9 @@ describe('Replication over REST', function() { user: { type: 'belongsTo', model: 'ServerUser', - foreignKey: 'userId' - } - } + foreignKey: 'userId', + }, + }, }); serverApp.model(ServerToken, { dataSource: 'db', public: false }); serverApp.model(loopback.ACL, { dataSource: 'db', public: false }); @@ -448,7 +450,7 @@ describe('Replication over REST', function() { serverApp.model(ServerUser, { dataSource: 'db', public: true, - relations: { accessTokens: { model: 'ServerToken' } } + relations: { accessTokens: { model: 'ServerToken' }}, }); ServerCar = loopback.createModel('ServerCar', CAR_PROPS, CAR_OPTS); @@ -476,7 +478,7 @@ describe('Replication over REST', function() { clientApp.dataSource('db', { connector: 'memory' }); clientApp.dataSource('remote', { connector: 'remote', - url: serverUrl + url: serverUrl, }); // NOTE(bajtos) At the moment, all models share the same Checkpoint @@ -510,7 +512,7 @@ describe('Replication over REST', function() { trackChanges: false, // Enable remote replication in order to get remoting API metadata // used by the remoting connector - enableRemoteReplication: true + enableRemoteReplication: true, }); } @@ -548,14 +550,14 @@ describe('Replication over REST', function() { ServerCar.create( [ { id: 'Ford-Mustang', maker: 'Ford', model: 'Mustang' }, - { id: 'Audi-R8', maker: 'Audi', model: 'R8' } + { id: 'Audi-R8', maker: 'Audi', model: 'R8' }, ], function(err, cars) { if (err) return next(err); serverCars = cars.map(carToString); next(); }); - } + }, ], done); } @@ -600,7 +602,7 @@ describe('Replication over REST', function() { function setAccessToken(token) { clientApp.dataSources.remote.connector.remotes.auth = { bearer: new Buffer(token).toString('base64'), - sendImmediately: true + sendImmediately: true, }; } diff --git a/test/replication.test.js b/test/replication.test.js index ecdffbf8..c12d0249 100644 --- a/test/replication.test.js +++ b/test/replication.test.js @@ -8,8 +8,7 @@ var expect = require('chai').expect; var debug = require('debug')('test'); describe('Replication / Change APIs', function() { - var dataSource, SourceModel, TargetModel; - var useSinceFilter; + var dataSource, SourceModel, TargetModel, useSinceFilter; var tid = 0; // per-test unique id used e.g. to build unique model names beforeEach(function() { @@ -17,18 +16,18 @@ describe('Replication / Change APIs', function() { useSinceFilter = false; var test = this; dataSource = this.dataSource = loopback.createDataSource({ - connector: loopback.Memory + connector: loopback.Memory, }); SourceModel = this.SourceModel = PersistedModel.extend( 'SourceModel-' + tid, - { id: { id: true, type: String, defaultFn: 'guid' } }, + { id: { id: true, type: String, defaultFn: 'guid' }}, { trackChanges: true }); SourceModel.attachTo(dataSource); TargetModel = this.TargetModel = PersistedModel.extend( 'TargetModel-' + tid, - { id: { id: true, type: String, defaultFn: 'guid' } }, + { id: { id: true, type: String, defaultFn: 'guid' }}, { trackChanges: true }); // NOTE(bajtos) At the moment, all models share the same Checkpoint @@ -44,7 +43,7 @@ describe('Replication / Change APIs', function() { test.startingCheckpoint = -1; this.createInitalData = function(cb) { - SourceModel.create({name: 'foo'}, function(err, inst) { + SourceModel.create({ name: 'foo' }, function(err, inst) { if (err) return cb(err); test.model = inst; SourceModel.replicate(TargetModel, cb); @@ -54,7 +53,7 @@ describe('Replication / Change APIs', function() { describe('optimization check rectifyChange Vs rectifyAllChanges', function() { beforeEach(function initialData(done) { - var data = [{name: 'John', surname: 'Doe'}, {name: 'Jane', surname: 'Roe'}]; + var data = [{ name: 'John', surname: 'Doe' }, { name: 'Jane', surname: 'Roe' }]; async.waterfall([ function(callback) { SourceModel.create(data, callback); @@ -68,7 +67,7 @@ describe('Replication / Change APIs', function() { it('should call rectifyAllChanges if no id is passed for rectifyOnDelete', function(done) { var calls = mockSourceModelRectify(); - SourceModel.destroyAll({name: 'John'}, function(err, data) { + SourceModel.destroyAll({ name: 'John' }, function(err, data) { if (err) return done(err); expect(calls).to.eql(['rectifyAllChanges']); done(); @@ -77,24 +76,25 @@ describe('Replication / Change APIs', function() { it('should call rectifyAllChanges if no id is passed for rectifyOnSave', function(done) { var calls = mockSourceModelRectify(); - var newData = {'name': 'Janie'}; - SourceModel.update({name: 'Jane'}, newData, function(err, data) { + var newData = { 'name': 'Janie' }; + SourceModel.update({ name: 'Jane' }, newData, function(err, data) { if (err) return done(err); expect(calls).to.eql(['rectifyAllChanges']); done(); }); }); - it('rectifyOnDelete for Delete should call rectifyChange instead of rectifyAllChanges', function(done) { + it('rectifyOnDelete for Delete should call rectifyChange instead of rectifyAllChanges', + function(done) { var calls = mockTargetModelRectify(); async.waterfall([ function(callback) { - SourceModel.destroyAll({name: 'John'}, callback); + SourceModel.destroyAll({ name: 'John' }, callback); }, function(data, callback) { SourceModel.replicate(TargetModel, callback); // replicate should call `rectifyOnSave` and then `rectifyChange` not `rectifyAllChanges` through `after save` operation - } + }, ], function(err, results) { if (err) return done(err); expect(calls).to.eql(['rectifyChange']); @@ -102,17 +102,18 @@ describe('Replication / Change APIs', function() { }); }); - it('rectifyOnSave for Update should call rectifyChange instead of rectifyAllChanges', function(done) { + it('rectifyOnSave for Update should call rectifyChange instead of rectifyAllChanges', + function(done) { var calls = mockTargetModelRectify(); - var newData = {'name': 'Janie'}; + var newData = { 'name': 'Janie' }; async.waterfall([ function(callback) { - SourceModel.update({name: 'Jane'}, newData, callback); + SourceModel.update({ name: 'Jane' }, newData, callback); }, function(data, callback) { SourceModel.replicate(TargetModel, callback); // replicate should call `rectifyOnSave` and then `rectifyChange` not `rectifyAllChanges` through `after save` operation - } + }, ], function(err, result) { if (err) return done(err); expect(calls).to.eql(['rectifyChange']); @@ -120,9 +121,10 @@ describe('Replication / Change APIs', function() { }); }); - it('rectifyOnSave for Create should call rectifyChange instead of rectifyAllChanges', function(done) { + it('rectifyOnSave for Create should call rectifyChange instead of rectifyAllChanges', + function(done) { var calls = mockTargetModelRectify(); - var newData = [{name: 'Janie', surname: 'Doe'}]; + var newData = [{ name: 'Janie', surname: 'Doe' }]; async.waterfall([ function(callback) { SourceModel.create(newData, callback); @@ -130,7 +132,7 @@ describe('Replication / Change APIs', function() { function(data, callback) { SourceModel.replicate(TargetModel, callback); // replicate should call `rectifyOnSave` and then `rectifyChange` not `rectifyAllChanges` through `after save` operation - } + }, ], function(err, result) { if (err) return done(err); expect(calls).to.eql(['rectifyChange']); @@ -174,7 +176,7 @@ describe('Replication / Change APIs', function() { describe('Model.changes(since, filter, callback)', function() { it('Get changes since the given checkpoint', function(done) { var test = this; - this.SourceModel.create({name: 'foo'}, function(err) { + this.SourceModel.create({ name: 'foo' }, function(err) { if (err) return done(err); setTimeout(function() { test.SourceModel.changes(test.startingCheckpoint, {}, function(err, changes) { @@ -192,7 +194,6 @@ describe('Replication / Change APIs', function() { if (err) return done(err); SourceModel.changes(FUTURE_CHECKPOINT, {}, function(err, changes) { if (err) return done(err); - /*jshint -W030 */ expect(changes).to.be.empty; done(); }); @@ -201,11 +202,9 @@ describe('Replication / Change APIs', function() { }); describe('Model.replicate(since, targetModel, options, callback)', function() { - function assertTargetModelEqualsSourceModel(conflicts, sourceModel, targetModel, done) { - var sourceData; - var targetData; + var sourceData, targetData; assert(conflicts.length === 0); async.parallel([ @@ -222,7 +221,7 @@ describe('Replication / Change APIs', function() { targetData = result; cb(); }); - } + }, ], function(err) { if (err) return done(err); @@ -235,7 +234,7 @@ describe('Replication / Change APIs', function() { var test = this; var options = {}; - this.SourceModel.create({name: 'foo'}, function(err) { + this.SourceModel.create({ name: 'foo' }, function(err) { if (err) return done(err); test.SourceModel.replicate(test.startingCheckpoint, test.TargetModel, options, function(err, conflicts) { @@ -251,7 +250,7 @@ describe('Replication / Change APIs', function() { var test = this; var options = {}; - this.SourceModel.create({name: 'foo'}, function(err) { + this.SourceModel.create({ name: 'foo' }, function(err) { if (err) return done(err); test.SourceModel.replicate(test.startingCheckpoint, test.TargetModel, options) @@ -289,7 +288,7 @@ describe('Replication / Change APIs', function() { expect(getIds(list)).to.eql(['2']); next(); }); - } + }, ], done); }); @@ -321,7 +320,7 @@ describe('Replication / Change APIs', function() { expect(getIds(list)).to.eql(['2']); next(); }); - } + }, ], done); }); @@ -433,7 +432,7 @@ describe('Replication / Change APIs', function() { expect(getIds(list), 'target ids').to.eql(['init', 'racer']); next(); }); - } + }, ], done); }); @@ -453,11 +452,11 @@ describe('Replication / Change APIs', function() { expect(conflicts, 'conflicts').to.eql([]); expect(newCheckpoints, 'currentCheckpoints').to.eql({ source: sourceCp + 1, - target: targetCp + 1 + target: targetCp + 1, }); cb(); }); - } + }, ], done); function bumpSourceCheckpoint(cb) { @@ -487,14 +486,14 @@ describe('Replication / Change APIs', function() { TargetModel.currentCheckpoint(function(err, cp) { if (err) return next(err); TargetModel.getChangeModel().find( - { where: { checkpoint: { gte: cp } } }, + { where: { checkpoint: { gte: cp }}}, function(err, changes) { if (err) return done(err); expect(changes).to.have.length(0); done(); }); }); - } + }, ], done); }); @@ -513,14 +512,14 @@ describe('Replication / Change APIs', function() { connector.updateAttributes( TargetModel.modelName, '1', - {name: '3rd-party'}, + { name: '3rd-party' }, cb); } else { // 2.x connectors require `options` connector.updateAttributes( TargetModel.modelName, '1', - {name: '3rd-party'}, + { name: '3rd-party' }, {}, // options cb); } @@ -540,7 +539,7 @@ describe('Replication / Change APIs', function() { }, replicateExpectingSuccess(), - verifyInstanceWasReplicated(SourceModel, TargetModel, '1') + verifyInstanceWasReplicated(SourceModel, TargetModel, '1'), ], done); }); @@ -555,13 +554,13 @@ describe('Replication / Change APIs', function() { if (connector.create.length <= 3) { connector.create( TargetModel.modelName, - {id: '1', name: '3rd-party'}, + { id: '1', name: '3rd-party' }, cb); } else { // 2.x connectors require `options` connector.create( TargetModel.modelName, - {id: '1', name: '3rd-party'}, + { id: '1', name: '3rd-party' }, {}, // options cb); } @@ -581,7 +580,7 @@ describe('Replication / Change APIs', function() { }, replicateExpectingSuccess(), - verifyInstanceWasReplicated(SourceModel, TargetModel, '1') + verifyInstanceWasReplicated(SourceModel, TargetModel, '1'), ], done); }); @@ -599,14 +598,14 @@ describe('Replication / Change APIs', function() { connector.updateAttributes( TargetModel.modelName, '1', - {name: '3rd-party'}, + { name: '3rd-party' }, cb); } else { // 2.x connectors require `options` connector.updateAttributes( TargetModel.modelName, '1', - {name: '3rd-party'}, + { name: '3rd-party' }, {}, // options cb); } @@ -626,7 +625,7 @@ describe('Replication / Change APIs', function() { }, replicateExpectingSuccess(), - verifyInstanceWasReplicated(SourceModel, TargetModel, '1') + verifyInstanceWasReplicated(SourceModel, TargetModel, '1'), ], done); }); @@ -657,7 +656,7 @@ describe('Replication / Change APIs', function() { next(); }, replicateExpectingSuccess(), - verifyInstanceWasReplicated(SourceModel, TargetModel, '1') + verifyInstanceWasReplicated(SourceModel, TargetModel, '1'), ], done); }); }); @@ -686,7 +685,7 @@ describe('Replication / Change APIs', function() { inst.name = 'target update'; inst.save(cb); }); - } + }, ], function(err) { if (err) return done(err); SourceModel.replicate(TargetModel, function(err, conflicts) { @@ -724,11 +723,11 @@ describe('Replication / Change APIs', function() { this.conflict.models(function(err, source, target) { assert.deepEqual(source.toJSON(), { id: test.model.id, - name: 'source update' + name: 'source update', }); assert.deepEqual(target.toJSON(), { id: test.model.id, - name: 'target update' + name: 'target update', }); done(); }); @@ -758,7 +757,7 @@ describe('Replication / Change APIs', function() { inst.name = 'target update'; inst.save(cb); }); - } + }, ], function(err) { if (err) return done(err); SourceModel.replicate(TargetModel, function(err, conflicts) { @@ -797,7 +796,7 @@ describe('Replication / Change APIs', function() { assert.equal(source, null); assert.deepEqual(target.toJSON(), { id: test.model.id, - name: 'target update' + name: 'target update', }); done(); }); @@ -827,7 +826,7 @@ describe('Replication / Change APIs', function() { if (err) return cb(err); inst.remove(cb); }); - } + }, ], function(err) { if (err) return done(err); SourceModel.replicate(TargetModel, function(err, conflicts) { @@ -866,7 +865,7 @@ describe('Replication / Change APIs', function() { assert.equal(target, null); assert.deepEqual(source.toJSON(), { id: test.model.id, - name: 'source update' + name: 'source update', }); done(); }); @@ -895,7 +894,7 @@ describe('Replication / Change APIs', function() { if (err) return cb(err); inst.remove(cb); }); - } + }, ], function(err) { if (err) return done(err); SourceModel.replicate(TargetModel, function(err, conflicts) { @@ -958,7 +957,7 @@ describe('Replication / Change APIs', function() { }; SourceModel.findOrCreate( - { where: { name: 'does-not-exist' } }, + { where: { name: 'does-not-exist' }}, { name: 'created' }, function(err, inst) { if (err) return done(err); @@ -1070,14 +1069,14 @@ describe('Replication / Change APIs', function() { }); }, replicateExpectingSuccess(), - verifySourceWasReplicated() + verifySourceWasReplicated(), ], done); }); beforeEach(function setupThirdModel() { AnotherModel = this.AnotherModel = PersistedModel.extend( 'AnotherModel-' + tid, - { id: { id: true, type: String, defaultFn: 'guid' } }, + { id: { id: true, type: String, defaultFn: 'guid' }}, { trackChanges: true }); // NOTE(bajtos) At the moment, all models share the same Checkpoint @@ -1107,7 +1106,7 @@ describe('Replication / Change APIs', function() { expect(getIds(list)).to.not.contain(sourceInstance.id); next(); }); - } + }, ], done); }); @@ -1119,7 +1118,7 @@ describe('Replication / Change APIs', function() { updateSourceInstanceNameTo('updated'), updateSourceInstanceNameTo('again'), replicateExpectingSuccess(), - verifySourceWasReplicated() + verifySourceWasReplicated(), ], done); }); @@ -1141,7 +1140,7 @@ describe('Replication / Change APIs', function() { async.series([ // Note that ClientA->Server was already replicated during setup replicateExpectingSuccess(Server, ClientB), - verifySourceWasReplicated(ClientB) + verifySourceWasReplicated(ClientB), ], done); }); @@ -1158,7 +1157,7 @@ describe('Replication / Change APIs', function() { replicateExpectingSuccess(ClientA, Server), replicateExpectingSuccess(Server, ClientB), - verifySourceWasReplicated(ClientB) + verifySourceWasReplicated(ClientB), ], done); }); @@ -1167,7 +1166,7 @@ describe('Replication / Change APIs', function() { deleteSourceInstance(), replicateExpectingSuccess(ClientA, Server), replicateExpectingSuccess(Server, ClientB), - verifySourceWasReplicated(ClientB) + verifySourceWasReplicated(ClientB), ], done); }); @@ -1183,7 +1182,7 @@ describe('Replication / Change APIs', function() { it('propagates CREATE', function(done) { async.series([ sync(ClientA, Server), - sync(ClientB, Server) + sync(ClientB, Server), ], done); }); @@ -1207,7 +1206,6 @@ describe('Replication / Change APIs', function() { // ClientB fetches the created & updated instance from the server sync(ClientB, Server), ], done); - }); it('does not report false conflicts', function(done) { @@ -1227,7 +1225,7 @@ describe('Replication / Change APIs', function() { sync(ClientB, Server), // client A fetches the changes - sync(ClientA, Server) + sync(ClientA, Server), ], done); }); @@ -1325,7 +1323,7 @@ describe('Replication / Change APIs', function() { // and sync back to ClientA too sync(ClientA, Server), - verifyInstanceWasReplicated(ClientB, ClientA, sourceInstanceId) + verifyInstanceWasReplicated(ClientB, ClientA, sourceInstanceId), ], cb); } @@ -1363,7 +1361,7 @@ describe('Replication / Change APIs', function() { // and sync back to ClientA too sync(ClientA, Server), - verifyInstanceWasReplicated(ClientB, ClientA, sourceInstanceId) + verifyInstanceWasReplicated(ClientB, ClientA, sourceInstanceId), ], cb); } @@ -1383,11 +1381,10 @@ describe('Replication / Change APIs', function() { // NOTE(bajtos) It's important to replicate from the client to the // server first, so that we can resolve any conflicts at the client replicateExpectingSuccess(client, server), - replicateExpectingSuccess(server, client) + replicateExpectingSuccess(server, client), ], next); }; } - }); function updateSourceInstanceNameTo(value) { diff --git a/test/rest.middleware.test.js b/test/rest.middleware.test.js index 5757c44b..d1a98a4b 100644 --- a/test/rest.middleware.test.js +++ b/test/rest.middleware.test.js @@ -4,7 +4,7 @@ describe('loopback.rest', function() { var MyModel; beforeEach(function() { var ds = app.dataSource('db', { connector: loopback.Memory }); - MyModel = ds.createModel('MyModel', {name: String}); + MyModel = ds.createModel('MyModel', { name: String }); loopback.autoAttach(); }); @@ -20,7 +20,7 @@ describe('loopback.rest', function() { app.set('legacyExplorer', false); app.model(MyModel); app.use(loopback.rest()); - MyModel.create({name: 'm1'}, function(err, inst) { + MyModel.create({ name: 'm1' }, function(err, inst) { request(app) .del('/mymodels/' + inst.id) .expect(200, function(err, res) { @@ -61,7 +61,7 @@ describe('loopback.rest', function() { .expect(200) .end(function(err, res) { if (err) return done(err); - expect(res.body).to.eql({exists: false}); + expect(res.body).to.eql({ exists: false }); done(); }); }); @@ -69,7 +69,7 @@ describe('loopback.rest', function() { it('should report 200 for GET /:id found', function(done) { app.model(MyModel); app.use(loopback.rest()); - MyModel.create({name: 'm1'}, function(err, inst) { + MyModel.create({ name: 'm1' }, function(err, inst) { request(app).get('/mymodels/' + inst.id) .expect(200) .end(done); @@ -79,7 +79,7 @@ describe('loopback.rest', function() { it('should report 200 for HEAD /:id found', function(done) { app.model(MyModel); app.use(loopback.rest()); - MyModel.create({name: 'm2'}, function(err, inst) { + MyModel.create({ name: 'm2' }, function(err, inst) { request(app).head('/mymodels/' + inst.id) .expect(200) .end(done); @@ -89,12 +89,12 @@ describe('loopback.rest', function() { it('should report 200 for GET /:id/exists found', function(done) { app.model(MyModel); app.use(loopback.rest()); - MyModel.create({name: 'm2'}, function(err, inst) { + MyModel.create({ name: 'm2' }, function(err, inst) { request(app).get('/mymodels/' + inst.id + '/exists') .expect(200) .end(function(err, res) { if (err) return done(err); - expect(res.body).to.eql({exists: true}); + expect(res.body).to.eql({ exists: true }); done(); }); }); @@ -105,7 +105,7 @@ describe('loopback.rest', function() { // NOTE it is crucial to set `remoting` before creating any models var supportedTypes = ['json', 'application/javascript', 'text/javascript']; - app.set('remoting', { rest: { supportedTypes: supportedTypes } }); + app.set('remoting', { rest: { supportedTypes: supportedTypes }}); app.model(MyModel); app.use(loopback.rest()); @@ -120,7 +120,7 @@ describe('loopback.rest', function() { var ds = app.dataSource('db', { connector: loopback.Memory }); var CustomModel = ds.createModel('CustomModel', { name: String }, - { http: { 'path': 'domain1/CustomModelPath' } + { http: { 'path': 'domain1/CustomModelPath' }, }); app.model(CustomModel); @@ -133,7 +133,7 @@ describe('loopback.rest', function() { var ds = app.dataSource('db', { connector: loopback.Memory }); var CustomModel = ds.createModel('CustomModel', { name: String }, - { http: { path: 'domain%20one/CustomModelPath' } + { http: { path: 'domain%20one/CustomModelPath' }, }); app.model(CustomModel); @@ -163,8 +163,8 @@ describe('loopback.rest', function() { cb(null, req.accessToken ? req.accessToken.id : null); }; loopback.remoteMethod(User.getToken, { - accepts: [{ type: 'object', http: { source: 'req' } }], - returns: [{ type: 'object', name: 'id' }] + accepts: [{ type: 'object', http: { source: 'req' }}], + returns: [{ type: 'object', name: 'id' }], }); app.use(loopback.rest()); @@ -240,15 +240,15 @@ describe('loopback.rest', function() { cb(null, req && req.accessToken ? req.accessToken.id : null); }; // Set up the ACL - User.settings.acls.push({principalType: 'ROLE', + User.settings.acls.push({ principalType: 'ROLE', principalId: '$authenticated', permission: 'ALLOW', - property: 'getToken'}); + property: 'getToken' }); loopback.remoteMethod(User.getToken, { accepts: [], returns: [ - { type: 'object', name: 'id' } - ] + { type: 'object', name: 'id' }, + ], }); }); @@ -276,7 +276,7 @@ describe('loopback.rest', function() { it('should enable context with loopback.rest', function(done) { app.enableAuth(); - app.set('remoting', { context: { enableHttpContext: true } }); + app.set('remoting', { context: { enableHttpContext: true }}); app.use(loopback.rest()); invokeGetToken(done); @@ -312,8 +312,8 @@ describe('loopback.rest', function() { loopback.remoteMethod(User.getToken, { accepts: [], returns: [ - { type: 'object', name: 'id' } - ] + { type: 'object', name: 'id' }, + ], }); invokeGetToken(done); @@ -326,9 +326,9 @@ describe('loopback.rest', function() { // the global model registry app.model('accessToken', { options: { - base: 'AccessToken' + base: 'AccessToken', }, - dataSource: 'db' + dataSource: 'db', }); return app.model('user', { options: { @@ -337,11 +337,11 @@ describe('loopback.rest', function() { accessTokens: { model: 'accessToken', type: 'hasMany', - foreignKey: 'userId' - } - } + foreignKey: 'userId', + }, + }, }, - dataSource: 'db' + dataSource: 'db', }); } function givenLoggedInUser(cb, done) { @@ -363,11 +363,11 @@ describe('loopback.rest', function() { describe('with specific definitions in model-config.json', function() { it('should not be exposed when the definition value is false', function(done) { - var app = require(getFixturePath('model-config-defined-false')); - request(app) + var app = require(getFixturePath('model-config-defined-false')); + request(app) .get('/todos') .expect(404, done); - }); + }); it('should be exposed when the definition value is true', function(done) { var app = require(getFixturePath('model-config-defined-true')); @@ -380,18 +380,18 @@ describe('loopback.rest', function() { describe('with default definitions in model-config.json', function() { it('should not be exposed when the definition value is false', function(done) { - var app = require(getFixturePath('model-config-default-false')); - request(app) + var app = require(getFixturePath('model-config-default-false')); + request(app) .get('/todos') .expect(404, done); - }); + }); it('should be exposed when the definition value is true', function(done) { var app = require(getFixturePath('model-config-default-true')); app.models.Todo.create([ - {content: 'a'}, - {content: 'b'}, - {content: 'c'} + { content: 'a' }, + { content: 'b' }, + { content: 'c' }, ], function() { request(app) .del('/todos') @@ -408,36 +408,36 @@ describe('loopback.rest', function() { describe('with specific definitions in config.json', function() { it('should not be exposed when the definition value is false', function(done) { - var app = require(getFixturePath('config-defined-false')); - request(app) + var app = require(getFixturePath('config-defined-false')); + request(app) .get('/todos') .expect(404, done); - }); + }); it('should be exposed when the definition value is true', function(done) { - var app = require(getFixturePath('config-defined-true')); - request(app) + var app = require(getFixturePath('config-defined-true')); + request(app) .get('/todos') .expect(200, done); - }); + }); }); describe('with default definitions in config.json', function() { it('should not be exposed when the definition value is false', function(done) { - var app = require(getFixturePath('config-default-false')); - request(app) + var app = require(getFixturePath('config-default-false')); + request(app) .get('/todos') .expect(404, done); - }); + }); it('should be exposed when the definition value is true', function(done) { var app = require(getFixturePath('config-default-true')); app.models.Todo.create([ - {content: 'a'}, - {content: 'b'}, - {content: 'c'} + { content: 'a' }, + { content: 'b' }, + { content: 'c' }, ], function() { request(app) .del('/todos') @@ -457,20 +457,20 @@ describe('loopback.rest', function() { // consequence, this causes the tests in user.integration to fail. describe.skip('with definitions in both config.json and model-config.json', function() { - it('should prioritize the settings in model-config.json', function(done) { - var app = require(getFixturePath('both-configs-set')); - request(app) + it('should prioritize the settings in model-config.json', function(done) { + var app = require(getFixturePath('both-configs-set')); + request(app) .del('/todos') .expect(404, done); - }); + }); - it('should fall back to config.json settings if setting is not found in' + + it('should fall back to config.json settings if setting is not found in' + 'model-config.json', function(done) { - var app = require(getFixturePath('both-configs-set')); - request(app) + var app = require(getFixturePath('both-configs-set')); + request(app) .get('/todos') .expect(404, done); - }); - }); + }); + }); }); }); diff --git a/test/role.test.js b/test/role.test.js index 3053a0af..2129fcb7 100644 --- a/test/role.test.js +++ b/test/role.test.js @@ -18,7 +18,7 @@ describe('role model', function() { var ds; beforeEach(function() { - ds = loopback.createDataSource({connector: 'memory'}); + ds = loopback.createDataSource({ connector: 'memory' }); // Re-attach the models so that they can have isolated store to avoid // pollutions from other tests ACL.attachTo(ds); @@ -36,9 +36,10 @@ describe('role model', function() { }); 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.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); }); @@ -56,15 +57,14 @@ describe('role model', 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.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); @@ -85,16 +85,15 @@ describe('role model', 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) { @@ -117,45 +116,52 @@ describe('role model', function() { }); }); }); - }); it('should support getRoles() and isInRole()', 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.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); }); - 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); }); - 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); }); - 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); @@ -163,54 +169,60 @@ describe('role model', function() { }); }); }); - }); it('should support owner role resolver', function() { - var Album = ds.createModel('Album', { name: String, - userId: Number + userId: Number, }, { relations: { user: { type: 'belongsTo', model: 'User', - foreignKey: 'userId' - } - } + foreignKey: 'userId', + }, + }, }); - 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) { + var role = { principalType: ACL.USER, principalId: user.id, model: Album, id: album1.id }; + Role.isInRole(Role.OWNER, role, 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 = { principalType: ACL.USER, principalId: user.id, model: Album, id: album2.id }; + Role.isInRole(Role.OWNER, role, function(err, yes) { assert(!err && !yes); }); }); @@ -225,35 +237,35 @@ describe('role model', function() { User.create({ username: 'john', email: 'john@gmail.com', - password: 'jpass' + password: 'jpass', }, function(err, u) { if (err) return done(err); user = u; User.create({ username: 'mary', email: 'mary@gmail.com', - password: 'mpass' + password: 'mpass', }, function(err, u) { if (err) return done(err); Application.create({ - name: 'demo' + name: 'demo', }, function(err, a) { if (err) return done(err); app = a; Role.create({ - name: 'admin' + name: 'admin', }, function(err, r) { if (err) return done(err); role = r; var principals = [ { principalType: ACL.USER, - principalId: user.id + principalId: user.id, }, { principalType: ACL.APP, - principalId: app.id - } + principalId: app.id, + }, ]; async.each(principals, function(p, done) { role.principals.create(p, done); @@ -344,7 +356,6 @@ describe('role model', function() { done(); }); }); - }); describe('listByPrincipalType', function() { @@ -371,9 +382,10 @@ describe('role model', function() { mappings.forEach(function(principalType) { var Model = principalTypesToModels[principalType]; - Model.create({name:'test', email:'x@y.com', password: 'foobar'}, function(err, model) { - Role.create({name:'testRole'}, function(err, role) { - role.principals.create({principalType: principalType, principalId: model.id}, function(err, p) { + Model.create({ name: 'test', email: 'x@y.com', password: 'foobar' }, function(err, model) { + Role.create({ name: 'testRole' }, function(err, role) { + role.principals.create({ principalType: principalType, principalId: model.id }, + function(err, p) { var pluralName = Model.pluralModelName.toLowerCase(); role[pluralName](function(err, models) { assert(!err); @@ -389,10 +401,11 @@ describe('role model', function() { }); it('should apply query', function(done) { - User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) { - Role.create({name: 'userRole'}, function(err, role) { - role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function(err, p) { - var query = {fields:['id', 'name']}; + User.create({ name: 'Raymond', email: 'x@y.com', password: 'foobar' }, function(err, user) { + Role.create({ name: 'userRole' }, function(err, role) { + role.principals.create({ principalType: RoleMapping.USER, principalId: user.id }, + function(err, p) { + var query = { fields: ['id', 'name'] }; sandbox.spy(User, 'find'); role.users(query, function(err, users) { assert(!err); @@ -406,5 +419,4 @@ describe('role model', function() { }); }); }); - }); diff --git a/test/support.js b/test/support.js index 0f925a38..b3fef0b3 100644 --- a/test/support.js +++ b/test/support.js @@ -21,14 +21,14 @@ beforeEach(function() { // setup default data sources loopback.setDefaultDataSourceForType('db', { - connector: loopback.Memory + connector: loopback.Memory, }); loopback.setDefaultDataSourceForType('mail', { connector: loopback.Mail, transports: [ - {type: 'STUB'} - ] + { type: 'STUB' }, + ], }); }); diff --git a/test/user.integration.js b/test/user.integration.js index 9cada628..0f502f85 100644 --- a/test/user.integration.js +++ b/test/user.integration.js @@ -1,4 +1,3 @@ -/*jshint -W030 */ var loopback = require('../'); var lt = require('./helpers/loopback-testing-helper'); var path = require('path'); @@ -7,7 +6,6 @@ var app = require(path.join(SIMPLE_APP, 'server/server.js')); var expect = require('chai').expect; describe('users - integration', function() { - lt.beforeEach.withApp(app); before(function(done) { @@ -15,7 +13,7 @@ describe('users - integration', function() { // other tests app.models.User.hasMany(app.models.post); app.models.User.hasMany(app.models.AccessToken, - {options: {disableInclude: true}}); + { options: { disableInclude: true }}); app.models.AccessToken.belongsTo(app.models.User); app.models.User.destroyAll(function(err) { if (err) return done(err); @@ -30,12 +28,11 @@ describe('users - integration', function() { }); describe('base-user', function() { - var userId; - var accessToken; + var userId, accessToken; it('should create a new user', function(done) { this.post('/api/users') - .send({username: 'x', email: 'x@y.com', password: 'x'}) + .send({ username: 'x', email: 'x@y.com', password: 'x' }) .expect(200, function(err, res) { if (err) return done(err); expect(res.body.id).to.exist; @@ -48,7 +45,7 @@ describe('users - integration', function() { var url = '/api/users/login'; this.post(url) - .send({username: 'x', email: 'x@y.com', password: 'x'}) + .send({ username: 'x', email: 'x@y.com', password: 'x' }) .expect(200, function(err, res) { if (err) { return done(err); @@ -62,7 +59,7 @@ describe('users - integration', function() { it('should create post for a given user', function(done) { var url = '/api/users/' + userId + '/posts?access_token=' + accessToken; this.post(url) - .send({title: 'T1', content: 'C1'}) + .send({ title: 'T1', content: 'C1' }) .expect(200, function(err, res) { if (err) { return done(err); @@ -93,14 +90,13 @@ describe('users - integration', function() { }); describe('sub-user', function() { - var userId; - var accessToken; + var userId, accessToken; it('should create a new user', function(done) { var url = '/api/myUsers'; this.post(url) - .send({username: 'x', email: 'x@y.com', password: 'x'}) + .send({ username: 'x', email: 'x@y.com', password: 'x' }) .expect(200, function(err, res) { if (err) { return done(err); @@ -115,7 +111,7 @@ describe('users - integration', function() { var url = '/api/myUsers/login'; this.post(url) - .send({username: 'x', email: 'x@y.com', password: 'x'}) + .send({ username: 'x', email: 'x@y.com', password: 'x' }) .expect(200, function(err, res) { if (err) { return done(err); @@ -129,7 +125,7 @@ describe('users - integration', function() { it('should create blog for a given user', function(done) { var url = '/api/myUsers/' + userId + '/blogs?access_token=' + accessToken; this.post(url) - .send({title: 'T1', content: 'C1'}) + .send({ title: 'T1', content: 'C1' }) .expect(200, function(err, res) { if (err) { console.error(err); @@ -157,6 +153,4 @@ describe('users - integration', function() { }); }); }); - }); - diff --git a/test/user.test.js b/test/user.test.js index f306332c..75fd67d7 100644 --- a/test/user.test.js +++ b/test/user.test.js @@ -1,23 +1,25 @@ require('./support'); var loopback = require('../'); -var User; -var AccessToken; +var User, AccessToken; var MailConnector = require('../lib/connectors/mail'); var userMemory = loopback.createDataSource({ - connector: 'memory' + connector: 'memory', }); describe('User', function() { var validCredentialsEmail = 'foo@bar.com'; - var validCredentials = {email: validCredentialsEmail, password: 'bar'}; - var validCredentialsEmailVerified = {email: 'foo1@bar.com', password: 'bar1', emailVerified: true}; - var validCredentialsEmailVerifiedOverREST = {email: 'foo2@bar.com', password: 'bar2', emailVerified: true}; - var validCredentialsWithTTL = {email: 'foo@bar.com', password: 'bar', ttl: 3600}; - var validCredentialsWithTTLAndScope = {email: 'foo@bar.com', password: 'bar', ttl: 3600, scope: 'all'}; - var validMixedCaseEmailCredentials = {email: 'Foo@bar.com', password: 'bar'}; - var invalidCredentials = {email: 'foo1@bar.com', password: 'invalid'}; - var incompleteCredentials = {password: 'bar1'}; + var validCredentials = { email: validCredentialsEmail, password: 'bar' }; + var validCredentialsEmailVerified = { + email: 'foo1@bar.com', password: 'bar1', emailVerified: true }; + var validCredentialsEmailVerifiedOverREST = { + email: 'foo2@bar.com', password: 'bar2', emailVerified: true }; + var validCredentialsWithTTL = { email: 'foo@bar.com', password: 'bar', ttl: 3600 }; + var validCredentialsWithTTLAndScope = { + email: 'foo@bar.com', password: 'bar', ttl: 3600, scope: 'all' }; + var validMixedCaseEmailCredentials = { email: 'Foo@bar.com', password: 'bar' }; + var invalidCredentials = { email: 'foo1@bar.com', password: 'invalid' }; + var incompleteCredentials = { password: 'bar1' }; var defaultApp; @@ -26,23 +28,22 @@ describe('User', function() { // to the wrong app instance defaultApp = loopback.User.app; loopback.User.app = null; - User = loopback.User.extend('TestUser', {}, {http: {path: 'test-users'}}); + User = loopback.User.extend('TestUser', {}, { http: { path: 'test-users' }}); AccessToken = loopback.AccessToken.extend('TestAccessToken'); User.email = loopback.Email.extend('email'); loopback.autoAttach(); // Update the AccessToken relation to use the subclass of User - AccessToken.belongsTo(User, {as: 'user', foreignKey: 'userId'}); - User.hasMany(AccessToken, {as: 'accessTokens', foreignKey: 'userId'}); + AccessToken.belongsTo(User, { as: 'user', foreignKey: 'userId' }); + User.hasMany(AccessToken, { as: 'accessTokens', foreignKey: 'userId' }); // allow many User.afterRemote's to be called User.setMaxListeners(0); - }); beforeEach(function(done) { app.enableAuth(); - app.use(loopback.token({model: AccessToken})); + app.use(loopback.token({ model: AccessToken })); app.use(loopback.rest()); app.model(User); @@ -60,7 +61,7 @@ describe('User', 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); @@ -70,7 +71,7 @@ describe('User', function() { it('Create a new user (email case-sensitivity off)', function(done) { User.settings.caseSensitiveEmail = false; - User.create({email: 'F@b.com', password: 'bar'}, function(err, user) { + User.create({ email: 'F@b.com', password: 'bar' }, function(err, user) { if (err) return done(err); assert(user.id); assert.equal(user.email, user.email.toLowerCase()); @@ -79,7 +80,7 @@ describe('User', function() { }); it('Create a new user (email case-sensitive)', function(done) { - User.create({email: 'F@b.com', password: 'bar'}, function(err, user) { + User.create({ email: 'F@b.com', password: 'bar' }, function(err, user) { if (err) return done(err); assert(user.id); assert(user.email); @@ -89,30 +90,30 @@ describe('User', function() { }); 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} + User.create({ email: 'f1@b.com', password: 'bar1', + credentials: { cert: 'xxxxx', key: '111' }, + challenges: { x: 'X', a: 1 }, }, function(err, user) { assert(!err); User.findById(user.id, function(err, user) { assert(user.id); assert(user.email); - assert.deepEqual(user.credentials, {cert: 'xxxxx', key: '111'}); - assert.deepEqual(user.challenges, {x: 'X', a: 1}); + assert.deepEqual(user.credentials, { cert: 'xxxxx', key: '111' }); + assert.deepEqual(user.challenges, { x: 'X', a: 1 }); done(); }); }); }); it('Email is required', function(done) { - User.create({password: '123'}, function(err) { + User.create({ password: '123' }, function(err) { assert(err); assert.equal(err.name, 'ValidationError'); assert.equal(err.statusCode, 422); assert.equal(err.details.context, User.modelName); assert.deepEqual(err.details.codes.email, [ 'presence', - 'format.null' + 'format.null', ]); done(); @@ -121,24 +122,24 @@ describe('User', function() { // 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'}); + var u = new User({ email: '123@456.com' }); - User.create({email: 'c@d.com'}, function(err) { + 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(); }); @@ -147,9 +148,9 @@ describe('User', function() { it('Requires a unique email (email case-sensitivity off)', function(done) { User.settings.caseSensitiveEmail = false; - User.create({email: 'A@b.com', password: 'foobar'}, function(err) { + User.create({ email: 'A@b.com', password: 'foobar' }, function(err) { if (err) return done(err); - User.create({email: 'a@b.com', password: 'batbaz'}, function(err) { + User.create({ email: 'a@b.com', password: 'batbaz' }, function(err) { assert(err, 'should error because the email is not unique!'); done(); }); @@ -157,8 +158,8 @@ describe('User', function() { }); it('Requires a unique email (email case-sensitive)', function(done) { - User.create({email: 'A@b.com', password: 'foobar'}, function(err, user1) { - User.create({email: 'a@b.com', password: 'batbaz'}, function(err, user2) { + User.create({ email: 'A@b.com', password: 'foobar' }, function(err, user1) { + User.create({ email: 'a@b.com', password: 'batbaz' }, function(err, user2) { if (err) return done(err); assert.notEqual(user1.email, user2.email); done(); @@ -167,8 +168,8 @@ 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(); }); @@ -176,8 +177,8 @@ describe('User', function() { }); 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'); assert.equal(err.code, 'LOGIN_FAILED'); @@ -187,20 +188,19 @@ describe('User', function() { }); it('Hashes the given password', function() { - var u = new User({username: 'foo', password: 'bar'}); + var u = new User({ username: 'foo', password: 'bar' }); assert(u.password !== 'bar'); }); it('does not hash the password if it\'s already hashed', function() { - var u1 = new User({username: 'foo', password: 'bar'}); + var u1 = new User({ username: 'foo', password: 'bar' }); assert(u1.password !== 'bar'); - var u2 = new User({username: 'foo', password: u1.password}); + var u2 = new User({ username: 'foo', password: u1.password }); assert(u2.password === u1.password); }); describe('custom password hash', function() { - var defaultHashPassword; - var defaultValidatePassword; + var defaultHashPassword, defaultValidatePassword; beforeEach(function() { defaultHashPassword = User.hashPassword; @@ -225,7 +225,7 @@ describe('User', function() { it('Reports invalid password', function() { try { - var u = new User({username: 'foo', password: 'aa'}); + var u = new User({ username: 'foo', password: 'aa' }); assert(false, 'Error should have been thrown'); } catch (e) { // Ignore @@ -233,7 +233,7 @@ describe('User', function() { }); it('Hashes the given password', function() { - var u = new User({username: 'foo', password: 'bar'}); + var u = new User({ username: 'foo', password: 'bar' }); assert(u.password === 'BAR'); }); }); @@ -264,7 +264,7 @@ describe('User', function() { it('Should be able to find lowercase email with mixed-case email query', function(done) { User.settings.caseSensitiveEmail = false; - User.find({where:{email: validMixedCaseEmailCredentials.email}}, function(err, result) { + User.find({ where: { email: validMixedCaseEmailCredentials.email }}, function(err, result) { if (err) done(err); assert(result[0], 'The query did not find the user'); assert.equal(result[0].email, validCredentialsEmail); @@ -355,7 +355,7 @@ 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) { assert(accessToken.userId); @@ -383,7 +383,7 @@ describe('User', function() { // Override createAccessToken User.prototype.createAccessToken = function(ttl, options, cb) { // Reduce the ttl by half for testing purpose - this.accessTokens.create({ttl: ttl / 2, scopes: options.scope}, cb); + this.accessTokens.create({ ttl: ttl / 2, scopes: options.scope }, cb); }; User.login(validCredentialsWithTTLAndScope, function(err, accessToken) { assert(accessToken.userId); @@ -393,7 +393,7 @@ describe('User', function() { assert.equal(accessToken.scopes, 'all'); User.findById(accessToken.userId, function(err, user) { - user.createAccessToken(120, {scope: 'default'}, function(err, accessToken) { + user.createAccessToken(120, { scope: 'default' }, function(err, accessToken) { assert(accessToken.userId); assert(accessToken.id); assert.equal(accessToken.ttl, 60); @@ -575,22 +575,26 @@ describe('User', function() { it('Require valid and complete credentials for email verification error', function(done) { User.login({ email: validCredentialsEmail }, function(err, accessToken) { // strongloop/loopback#931 - // error message should be "login failed" and not "login failed as the email has not been verified" - assert(err && !/verified/.test(err.message), ('expecting "login failed" error message, received: "' + err.message + '"')); + // error message should be "login failed" + // and not "login failed as the email has not been verified" + assert(err && !/verified/.test(err.message), + 'expecting "login failed" error message, received: "' + err.message + '"'); assert.equal(err.code, 'LOGIN_FAILED'); done(); }); }); - it('Require valid and complete credentials for email verification error - promise variant', function(done) { + it('Require valid and complete credentials for email verification error - promise variant', + function(done) { User.login({ email: validCredentialsEmail }) .then(function(accessToken) { - done(); - }) + done(); + }) .catch(function(err) { // strongloop/loopback#931 // error message should be "login failed" and not "login failed as the email has not been verified" - assert(err && !/verified/.test(err.message), ('expecting "login failed" error message, received: "' + err.message + '"')); + assert(err && !/verified/.test(err.message), + 'expecting "login failed" error message, received: "' + err.message + '"'); assert.equal(err.code, 'LOGIN_FAILED'); done(); }); @@ -653,7 +657,9 @@ describe('User', function() { }); }); - it('Login a user over REST require complete and valid credentials for email verification error message', function(done) { + it('Login user over REST require complete and valid credentials ' + + 'for email verification error message', + function(done) { request(app) .post('/test-users/login') .expect('Content-Type', /json/) @@ -664,9 +670,11 @@ describe('User', function() { return done(err); } // strongloop/loopback#931 - // error message should be "login failed" and not "login failed as the email has not been verified" + // error message should be "login failed" + // and not "login failed as the email has not been verified" var errorResponse = res.body.error; - assert(errorResponse && !/verified/.test(errorResponse.message), ('expecting "login failed" error message, received: "' + errorResponse.message + '"')); + assert(errorResponse && !/verified/.test(errorResponse.message), + 'expecting "login failed" error message, received: "' + errorResponse.message + '"'); assert.equal(errorResponse.code, 'LOGIN_FAILED'); done(); }); @@ -687,23 +695,21 @@ describe('User', function() { done(); }); }); - }); describe('User.login requiring realm', function() { - var User; - var AccessToken; + var User, AccessToken; before(function() { User = loopback.User.extend('RealmUser', {}, - {realmRequired: true, realmDelimiter: ':'}); + { realmRequired: true, realmDelimiter: ':' }); AccessToken = loopback.AccessToken.extend('RealmAccessToken'); loopback.autoAttach(); // Update the AccessToken relation to use the subclass of User - AccessToken.belongsTo(User, {as: 'user', foreignKey: 'userId'}); - User.hasMany(AccessToken, {as: 'accessTokens', foreignKey: 'userId'}); + AccessToken.belongsTo(User, { as: 'user', foreignKey: 'userId' }); + User.hasMany(AccessToken, { as: 'accessTokens', foreignKey: 'userId' }); // allow many User.afterRemote's to be called User.setMaxListeners(0); @@ -713,53 +719,53 @@ describe('User', function() { realm: 'realm1', username: 'foo100', email: 'foo100@bar.com', - password: 'pass100' + password: 'pass100', }; var realm2User = { realm: 'realm2', username: 'foo100', email: 'foo100@bar.com', - password: 'pass200' + password: 'pass200', }; var credentialWithoutRealm = { username: 'foo100', email: 'foo100@bar.com', - password: 'pass100' + password: 'pass100', }; var credentialWithBadPass = { realm: 'realm1', username: 'foo100', email: 'foo100@bar.com', - password: 'pass001' + password: 'pass001', }; var credentialWithBadRealm = { realm: 'realm3', username: 'foo100', email: 'foo100@bar.com', - password: 'pass100' + password: 'pass100', }; var credentialWithRealm = { realm: 'realm1', username: 'foo100', - password: 'pass100' + password: 'pass100', }; var credentialRealmInUsername = { username: 'realm1:foo100', - password: 'pass100' + password: 'pass100', }; var credentialRealmInEmail = { email: 'realm1:foo100@bar.com', - password: 'pass100' + password: 'pass100', }; - var user1; + var user1 = null; beforeEach(function(done) { User.create(realm1User, function(err, u) { if (err) { @@ -771,11 +777,11 @@ describe('User', function() { }); afterEach(function(done) { - User.deleteAll({realm: 'realm1'}, function(err) { + User.deleteAll({ realm: 'realm1' }, function(err) { if (err) { return done(err); } - User.deleteAll({realm: 'realm2'}, done); + User.deleteAll({ realm: 'realm2' }, done); }); }); @@ -860,7 +866,7 @@ describe('User', function() { login(logout); function login(fn) { - User.login({email: 'foo@bar.com', password: 'bar'}, fn); + User.login({ email: 'foo@bar.com', password: 'bar' }, fn); } function logout(err, accessToken) { @@ -868,11 +874,12 @@ describe('User', function() { } }); - it('Logout a user by providing the current accessToken id (using node) - promise variant', function(done) { + it('Logout a user by providing the current accessToken id (using node) - promise variant', + function(done) { login(logout); function login(fn) { - User.login({email: 'foo@bar.com', password: 'bar'}, fn); + User.login({ email: 'foo@bar.com', password: 'bar' }, fn); } function logout(err, accessToken) { @@ -891,7 +898,7 @@ describe('User', function() { .post('/test-users/login') .expect('Content-Type', /json/) .expect(200) - .send({email: 'foo@bar.com', password: 'bar'}) + .send({ email: 'foo@bar.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -932,7 +939,7 @@ describe('User', 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'}); + var u = new User({ username: 'foo', password: 'bar' }); u.hasPassword('bar', function(err, isMatch) { assert(isMatch, 'password doesnt match'); done(); @@ -940,7 +947,7 @@ describe('User', function() { }); it('Determine if the password matches the stored password - promise variant', function(done) { - var u = new User({username: 'foo', password: 'bar'}); + var u = new User({ username: 'foo', password: 'bar' }); u.hasPassword('bar') .then(function(isMatch) { assert(isMatch, 'password doesnt match'); @@ -952,7 +959,7 @@ describe('User', function() { }); it('should match a password when saved', function(done) { - var u = new User({username: 'a', password: 'b', email: 'z@z.net'}); + var u = new User({ username: 'a', password: 'b', email: 'z@z.net' }); u.save(function(err, user) { User.findById(user.id, function(err, uu) { @@ -965,7 +972,7 @@ describe('User', function() { }); 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.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) { @@ -989,7 +996,6 @@ describe('User', 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) { @@ -1001,7 +1007,7 @@ describe('User', function() { from: 'noreply@myapp.org', redirect: '/', protocol: ctx.req.protocol, - host: ctx.req.get('host') + host: ctx.req.get('host'), }; user.verify(options, function(err, result) { @@ -1019,7 +1025,7 @@ describe('User', function() { .post('/test-users') .expect('Content-Type', /json/) .expect(200) - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -1037,7 +1043,7 @@ describe('User', function() { from: 'noreply@myapp.org', redirect: '/', protocol: ctx.req.protocol, - host: ctx.req.get('host') + host: ctx.req.get('host'), }; user.verify(options) @@ -1057,7 +1063,7 @@ describe('User', function() { request(app) .post('/test-users') - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .expect('Content-Type', /json/) .expect(200) .end(function(err, res) { @@ -1078,7 +1084,7 @@ describe('User', function() { redirect: '/', protocol: ctx.req.protocol, host: ctx.req.get('host'), - headers: {'message-id':'custom-header-value'} + headers: { 'message-id': 'custom-header-value' }, }; user.verify(options, function(err, result) { @@ -1092,7 +1098,7 @@ describe('User', function() { .post('/test-users') .expect('Content-Type', /json/) .expect(200) - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -1120,7 +1126,7 @@ describe('User', function() { process.nextTick(function() { cb(null, 'token-123456'); }); - } + }, }; user.verify(options, function(err, result) { @@ -1138,7 +1144,7 @@ describe('User', function() { .post('/test-users') .expect('Content-Type', /json/) .expect(200) - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -1162,7 +1168,7 @@ describe('User', function() { process.nextTick(function() { cb(new Error('Fake error')); }); - } + }, }; user.verify(options, function(err, result) { @@ -1177,7 +1183,7 @@ describe('User', function() { .post('/test-users') .expect('Content-Type', /json/) .expect(200) - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -1197,7 +1203,7 @@ describe('User', function() { redirect: '/', protocol: 'http', host: 'myapp.org', - port: 3000 + port: 3000, }; user.verify(options, function(err, result) { @@ -1211,7 +1217,7 @@ describe('User', function() { .post('/test-users') .expect('Content-Type', /json/) .expect(200) - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -1230,7 +1236,7 @@ describe('User', function() { redirect: '/', protocol: 'http', host: 'myapp.org', - port: 80 + port: 80, }; user.verify(options, function(err, result) { @@ -1244,7 +1250,7 @@ describe('User', function() { .post('/test-users') .expect('Content-Type', /json/) .expect(200) - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -1263,7 +1269,7 @@ describe('User', function() { redirect: '/', protocol: 'https', host: 'myapp.org', - port: 3000 + port: 3000, }; user.verify(options, function(err, result) { @@ -1277,7 +1283,7 @@ describe('User', function() { .post('/test-users') .expect('Content-Type', /json/) .expect(200) - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -1296,7 +1302,7 @@ describe('User', function() { redirect: '/', protocol: 'https', host: 'myapp.org', - port: 443 + port: 443, }; user.verify(options, function(err, result) { @@ -1310,7 +1316,7 @@ describe('User', function() { .post('/test-users') .expect('Content-Type', /json/) .expect(200) - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -1320,7 +1326,11 @@ describe('User', function() { }); it('should hide verification tokens from user JSON', function(done) { - var user = new User({email: 'bar@bat.com', password: 'bar', verificationToken: 'a-token' }); + var user = new User({ + email: 'bar@bat.com', + password: 'bar', + verificationToken: 'a-token', + }); var data = user.toJSON(); assert(!('verificationToken' in data)); done(); @@ -1340,7 +1350,7 @@ describe('User', function() { from: 'noreply@myapp.org', redirect: 'http://foo.com/bar', protocol: ctx.req.protocol, - host: ctx.req.get('host') + host: ctx.req.get('host'), }; user.verify(options, function(err, result) { @@ -1355,7 +1365,7 @@ describe('User', function() { .post('/test-users') .expect('Content-Type', /json/) .expect(302) - .send({email: 'bar@bat.com', password: 'bar'}) + .send({ email: 'bar@bat.com', password: 'bar' }) .end(function(err, res) { if (err) { return done(err); @@ -1478,7 +1488,7 @@ describe('User', function() { var calledBack = false; User.resetPassword({ - email: email + email: email, }, function() { calledBack = true; }); diff --git a/test/util/model-tests.js b/test/util/model-tests.js index cd89f307..f86fcdf6 100644 --- a/test/util/model-tests.js +++ b/test/util/model-tests.js @@ -7,11 +7,8 @@ var PersistedModel = loopback.PersistedModel; var RemoteObjects = require('strong-remoting'); module.exports = function defineModelTestsWithDataSource(options) { - describe('Model Tests', function() { - - var User; - var dataSource; + var User, dataSource; if (options.beforeEach) { beforeEach(options.beforeEach); @@ -44,9 +41,9 @@ module.exports = function defineModelTestsWithDataSource(options) { 'password': String, 'gender': String, 'domain': String, - 'email': String + 'email': String, }, { - trackChanges: true + trackChanges: true, }); User.attachTo(dataSource); @@ -59,7 +56,7 @@ module.exports = function defineModelTestsWithDataSource(options) { 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'}); + 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'); @@ -68,8 +65,8 @@ module.exports = function defineModelTestsWithDataSource(options) { 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'}); + 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'); }); @@ -77,8 +74,8 @@ module.exports = function defineModelTestsWithDataSource(options) { 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'}); + 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'); }); @@ -86,10 +83,10 @@ module.exports = function defineModelTestsWithDataSource(options) { 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'}); + 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); @@ -101,10 +98,10 @@ module.exports = function defineModelTestsWithDataSource(options) { 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}); + User.validatesNumericalityOf('age', { int: true }); + var joe = new User({ age: 10.2 }); assert(joe.isValid() === false); - var bob = new User({age: 0}); + var bob = new User({ age: 0 }); assert(bob.isValid() === true); assert(joe.errors.age, 'model should have an age error'); }); @@ -112,16 +109,16 @@ module.exports = function defineModelTestsWithDataSource(options) { describe('myModel.isValid()', function() { it('Validate the model instance', function() { - User.validatesNumericalityOf('age', {int: true}); - var user = new User({first: 'joe', age: 'flarg'}); + 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.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'); @@ -131,8 +128,9 @@ module.exports = function defineModelTestsWithDataSource(options) { }); 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) { + 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(); }); @@ -141,7 +139,7 @@ module.exports = function defineModelTestsWithDataSource(options) { 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'}); + var joe = new User({ first: 'Joe', last: 'Bob' }); joe.save(function(err, user) { assert(user.id); assert(!err); @@ -153,13 +151,13 @@ module.exports = function defineModelTestsWithDataSource(options) { 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) { + User.create({ first: 'joe', age: 100 }, function(err, user) { assert(!err); assert.equal(user.first, 'joe'); user.updateAttributes({ first: 'updatedFirst', - last: 'updatedLast' + last: 'updatedLast', }, function(err, updatedUser) { assert(!err); assert.equal(updatedUser.first, 'updatedFirst'); @@ -173,11 +171,11 @@ module.exports = function defineModelTestsWithDataSource(options) { 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) { + 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) { + User.upsert({ first: 'bob', id: 7 }, function(err, updatedUser) { assert(!err); assert.equal(updatedUser.first, 'bob'); done(); @@ -188,13 +186,13 @@ module.exports = function defineModelTestsWithDataSource(options) { 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.create({ first: 'joe', last: 'bob' }, function(err, user) { User.findById(user.id, function(err, foundUser) { if (err) return done(err); assert.equal(user.id, foundUser.id); User.deleteById(foundUser.id, function(err) { if (err) return done(err); - User.find({ where: { id: user.id } }, function(err, found) { + User.find({ where: { id: user.id }}, function(err, found) { if (err) return done(err); assert.equal(found.length, 0); done(); @@ -207,7 +205,7 @@ module.exports = function defineModelTestsWithDataSource(options) { 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.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); @@ -220,7 +218,7 @@ module.exports = function defineModelTestsWithDataSource(options) { describe('Model.findById(id, callback)', function() { it('Find an instance by id', function(done) { - User.create({first: 'michael', last: 'jordan', id: 23}, function() { + 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'); @@ -234,20 +232,18 @@ module.exports = function defineModelTestsWithDataSource(options) { 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'}) + .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) { + User.count({ age: { gt: 99 }}, function(err, count) { assert.equal(count, 2); done(); }); }); }); }); - }); - };