From d6a5c768fd2f390f8ec8236ea736964619420f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 11 Dec 2017 14:45:43 +0100 Subject: [PATCH 1/2] Refactor tests to use local per-app model registry Refactor tests to stop sharing global models between different test suites and use local per-app model registry instead. Also clean up all test code to use `const` and `let` instead of `var`. --- test/helper.js | 35 ++------- test/integration/promise-support.js | 36 +++++---- test/models.test.js | 48 ++++++------ test/remote-connector.test.js | 116 ++++++++++++++-------------- test/remote-models.test.js | 86 +++++++++++---------- 5 files changed, 158 insertions(+), 163 deletions(-) diff --git a/test/helper.js b/test/helper.js index 9a18d0d..bf0075c 100644 --- a/test/helper.js +++ b/test/helper.js @@ -10,14 +10,12 @@ var loopback = require('loopback'); var remoteConnector = require('..'); exports.createMemoryDataSource = createMemoryDataSource; -exports.createModel = createModel; exports.createRemoteDataSource = createRemoteDataSource; -exports.createRemoteDataSourceWithOptions = createRemoteDataSourceWithOptions; exports.createRestAppAndListen = createRestAppAndListen; exports.getUserProperties = getUserProperties; function createRestAppAndListen() { - var app = loopback(); + const app = loopback({localRegistry: true}); app.set('host', '127.0.0.1'); app.set('port', 0); @@ -34,38 +32,17 @@ function createRestAppAndListen() { return app; } -function createMemoryDataSource() { - return loopback.createDataSource({connector: 'memory'}); +function createMemoryDataSource(app) { + return app.dataSource('db', {connector: 'memory'}); } -function createRemoteDataSource(remoteApp) { - return loopback.createDataSource({ - url: 'http://' + remoteApp.get('host') + ':' + remoteApp.get('port'), +function createRemoteDataSource(app, serverApp) { + return app.dataSource('remote', { + url: 'http://' + serverApp.get('host') + ':' + serverApp.get('port'), connector: remoteConnector }); } -function createRemoteDataSourceWithOptions(remoteApp, options) { - return loopback.createDataSource({ - url: 'http://anyURL.com', - connector: remoteConnector, - options: options - }); -} - -/** - * Used to create models based on a set of options. May associate or link to an - * app. - */ -function createModel(options) { - var modelOptions = extend({ forceId: false }, options.options); - var Model = loopback.PersistedModel.extend(options.parent, options.properties, - modelOptions); - if (options.app) options.app.model(Model); - if (options.datasource) Model.attachTo(options.datasource); - return Model; -} - function getUserProperties() { return { 'first': String, diff --git a/test/integration/promise-support.js b/test/integration/promise-support.js index e312f94..64c1575 100644 --- a/test/integration/promise-support.js +++ b/test/integration/promise-support.js @@ -1,9 +1,16 @@ -var assert = require('assert'); -var helper = require('../helper'); -var Promise = require('bluebird'); +// Copyright IBM Corp. 2016. All Rights Reserved. +// Node module: loopback-connector-remote +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT -var globalPromiseSetManually = false; -var User; +'use strict'; + +const assert = require('assert'); +const helper = require('../helper'); +const Promise = require('bluebird'); + +let globalPromiseSetManually = false; +let User; describe('promise support', function() { before(setGlobalPromise); @@ -12,21 +19,21 @@ describe('promise support', function() { context('create', function() { it('supports promises', function() { - var retval = User.create(); + const retval = User.create(); assert(retval && typeof retval.then === 'function'); }); }); context('find', function() { it('supports promises', function() { - var retval = User.find(); + const retval = User.find(); assert(retval && typeof retval.then === 'function'); }); }); context('findById', function() { it('supports promises', function() { - var retval = User.findById(1); + const retval = User.findById(1); assert(retval && typeof retval.then === 'function'); }); }); @@ -40,12 +47,15 @@ function setGlobalPromise() { } function createUserModel() { - User = helper.createModel({ - parent: 'user', - app: helper.createRestAppAndListen(), - datasource: helper.createMemoryDataSource(), - properties: helper.getUserProperties() + const app = helper.createRestAppAndListen(); + const db = helper.createMemoryDataSource(app); + + User = app.registry.createModel({ + name: 'user', + properties: helper.getUserProperties(), + options: {forceId: false}, }); + app.model(User, {dataSource: db}); } function resetGlobalPromise() { diff --git a/test/models.test.js b/test/models.test.js index 3201344..96782e9 100644 --- a/test/models.test.js +++ b/test/models.test.js @@ -5,27 +5,31 @@ 'use strict'; -var assert = require('assert'); -var helper = require('./helper'); -var TaskEmitter = require('strong-task-emitter'); +const assert = require('assert'); +const helper = require('./helper'); +const loopback = require('loopback'); +const TaskEmitter = require('strong-task-emitter'); describe('Model tests', function() { - var User; + let User; beforeEach(function() { - User = helper.createModel({ - parent: 'user', - app: helper.createRestAppAndListen(), - datasource: helper.createMemoryDataSource(), - properties: helper.getUserProperties() + const app = helper.createRestAppAndListen(); + const db = helper.createMemoryDataSource(app); + + User = app.registry.createModel({ + name: 'user', + properties: helper.getUserProperties(), + options: {forceId: false}, }); + app.model(User, {dataSource: db}); }); describe('Model.validatesPresenceOf(properties...)', function() { it('should require a model to include a property to be considered valid', function() { User.validatesPresenceOf('first', 'last', 'age'); - var joe = new User({first: 'joe'}); + const 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'); @@ -37,7 +41,7 @@ describe('Model tests', function() { function() { User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}}); - var joe = new User({password: '1234'}); + const joe = new User({password: '1234'}); assert(joe.isValid() === false, 'model should not be valid'); assert(joe.errors.password, 'should have password error'); }); @@ -47,7 +51,7 @@ describe('Model tests', function() { it('should require a value for `property` to be in the specified array', function() { User.validatesInclusionOf('gender', {in: ['male', 'female']}); - var foo = new User({gender: 'bar'}); + const foo = new User({gender: 'bar'}); assert(foo.isValid() === false, 'model should not be valid'); assert(foo.errors.gender, 'should have gender error'); }); @@ -57,9 +61,9 @@ describe('Model tests', function() { it('should 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'}); + const foo = new User({domain: 'www'}); + const bar = new User({domain: 'billing'}); + const bat = new User({domain: 'admin'}); assert(foo.isValid() === false); assert(bar.isValid() === false); assert(bat.isValid() === false); @@ -73,9 +77,9 @@ describe('Model tests', function() { it('should 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}); + const joe = new User({age: 10.2}); assert(joe.isValid() === false); - var bob = new User({age: 0}); + const bob = new User({age: 0}); assert(bob.isValid() === true); assert(joe.errors.age, 'model should have an age error'); }); @@ -84,15 +88,15 @@ describe('Model tests', function() { describe('myModel.isValid()', function() { it('should validate the model instance', function() { User.validatesNumericalityOf('age', {int: true}); - var user = new User({first: 'joe', age: 'flarg'}); - var valid = user.isValid(); + const user = new User({first: 'joe', age: 'flarg'}); + const valid = user.isValid(); assert(valid === false); assert(user.errors.age, 'model should have age error'); }); it('should validate the model asynchronously', function(done) { User.validatesNumericalityOf('age', {int: true}); - var user = new User({first: 'joe', age: 'flarg'}); + const user = new User({first: 'joe', age: 'flarg'}); user.isValid(function(valid) { assert(valid === false); assert(user.errors.age, 'model should have age error'); @@ -115,7 +119,7 @@ describe('Model tests', function() { describe('model.save([options], [callback])', function() { it('should save an instance of a Model to the attached data source', function(done) { - var joe = new User({first: 'Joe', last: 'Bob'}); + const joe = new User({first: 'Joe', last: 'Bob'}); joe.save(function(err, user) { if (err) return done(err); assert(user.id); @@ -218,7 +222,7 @@ describe('Model tests', function() { describe('Model.count([query], callback)', function() { it('should return the count of Model instances in data source', function(done) { - var taskEmitter = new TaskEmitter(); + const taskEmitter = new TaskEmitter(); taskEmitter .task(User, 'create', {first: 'jill', age: 100}) .task(User, 'create', {first: 'bob', age: 200}) diff --git a/test/remote-connector.test.js b/test/remote-connector.test.js index 25b57b9..6a2e6f2 100644 --- a/test/remote-connector.test.js +++ b/test/remote-connector.test.js @@ -5,43 +5,45 @@ 'use strict'; -var assert = require('assert'); -var helper = require('./helper'); +const assert = require('assert'); +const helper = require('./helper'); +const loopback = require('loopback'); describe('RemoteConnector', function() { - var ctx = this; + let serverApp, clientApp, ServerModel, ClientModel; before(function setupServer(done) { - ctx.serverApp = helper.createRestAppAndListen(); - ctx.ServerModel = helper.createModel({ - parent: 'TestModel', - app: ctx.serverApp, - datasource: helper.createMemoryDataSource() + const app = serverApp = helper.createRestAppAndListen(); + const db = helper.createMemoryDataSource(app); + + ServerModel = app.registry.createModel({ + name: 'TestModel', }); - ctx.serverApp.locals.handler.on('listening', function() { done(); }); + app.model(ServerModel, {dataSource: db}); + + app.locals.handler.on('listening', function() { done(); }); }); - before(function setupRemoteClient(done) { - ctx.remoteApp = helper.createRestAppAndListen(); - ctx.RemoteModel = helper.createModel({ - parent: 'TestModel', - app: ctx.remoteApp, - datasource: helper.createRemoteDataSource(ctx.serverApp) + before(function setupRemoteClient() { + const app = clientApp = loopback({localRegistry: true}); + const remoteDs = helper.createRemoteDataSource(clientApp, serverApp); + + ClientModel = app.registry.createModel({ + name: 'TestModel', }); - ctx.remoteApp.locals.handler.on('listening', function() { done(); }); + app.model(ClientModel, {dataSource: remoteDs}); }); after(function() { - ctx.serverApp.locals.handler.close(); - ctx.remoteApp.locals.handler.close(); - ctx.ServerModel = null; - ctx.RemoteModel = null; + serverApp.locals.handler.close(); + ServerModel = null; + ClientModel = null; }); it('should support the save method', function(done) { - var calledServerCreate = false; + let calledServerCreate = false; - ctx.ServerModel.create = function(data, options, cb, callback) { + ServerModel.create = function(data, options, cb, callback) { if (typeof options === 'function') { callback = cb; cb = options; @@ -54,20 +56,20 @@ describe('RemoteConnector', function() { else cb(null, data); }; - var m = new ctx.RemoteModel({foo: 'bar'}); + const m = new ClientModel({foo: 'bar'}); m.save(function(err, instance) { if (err) return done(err); assert(instance); - assert(instance instanceof ctx.RemoteModel); + assert(instance instanceof ClientModel); assert(calledServerCreate); done(); }); }); it('should support aliases', function(done) { - var calledServerUpsert = false; - ctx.ServerModel.patchOrCreate = - ctx.ServerModel.upsert = function(id, options, cb) { + let calledServerUpsert = false; + ServerModel.patchOrCreate = + ServerModel.upsert = function(id, options, cb) { if (typeof options === 'function') { cb = options; options = {}; @@ -77,10 +79,10 @@ describe('RemoteConnector', function() { cb(); }; - ctx.RemoteModel.updateOrCreate({}, function(err, instance) { + ClientModel.updateOrCreate({}, function(err, instance) { if (err) return done(err); assert(instance); - assert(instance instanceof ctx.RemoteModel); + assert(instance instanceof ClientModel); assert(calledServerUpsert, 'server upsert should have been called'); done(); }); @@ -88,46 +90,45 @@ describe('RemoteConnector', function() { }); describe('Custom Path', function() { - var ctx = this; + let serverApp, clientApp, ServerModel, ClientModel; before(function setupServer(done) { - ctx.serverApp = helper.createRestAppAndListen(); - ctx.ServerModel = helper.createModel({ - parent: 'TestModel', - app: ctx.serverApp, - datasource: helper.createMemoryDataSource(), + const app = serverApp = helper.createRestAppAndListen(); + const db = helper.createMemoryDataSource(app); + + ServerModel = app.registry.createModel({ + name: 'TestModel', options: { http: {path: '/custom'} } }); - ctx.serverApp.locals.handler.on('listening', function() { done(); }); + app.model(ServerModel, {dataSource: db}); + + serverApp.locals.handler.on('listening', function() { done(); }); }); - before(function setupRemoteClient(done) { - ctx.remoteApp = helper.createRestAppAndListen(); - ctx.RemoteModel = helper.createModel({ - parent: 'TestModel', - app: ctx.remoteApp, - datasource: helper.createRemoteDataSource(ctx.serverApp), + before(function setupRemoteClient() { + const app = clientApp = loopback({localRegistry: true}); + const remoteDs = helper.createRemoteDataSource(clientApp, serverApp); + + ClientModel = app.registry.createModel({ + name: 'TestModel', options: { dataSource: 'remote', http: {path: '/custom'} } }); - ctx.remoteApp.locals.handler.on('listening', function() { done(); }); + app.model(ClientModel, {dataSource: remoteDs}); }); - after(function(done) - { - ctx.serverApp.locals.handler.close(); - ctx.remoteApp.locals.handler.close(); - ctx.ServerModel = null; - ctx.RemoteModel = null; - done(); + after(function() { + serverApp.locals.handler.close(); + ServerModel = null; + ClientModel = null; }); it('should support http.path configuration', function(done) { - ctx.RemoteModel.create({}, function(err, instance) { + ClientModel.create({}, function(err, instance) { if (err) return done(err); assert(instance); done(); @@ -137,12 +138,13 @@ describe('Custom Path', function() { describe('RemoteConnector with options', () => { it('should have the remoting options passed to the remote object', () => { - const serverApp = helper.createRestAppAndListen(); + const app = loopback(); + const dataSource = app.dataSource('remote', { + url: 'http://example.com', + connector: require('..'), + options: {'test': 'abc'}, + }); - const datasource = helper.createRemoteDataSourceWithOptions( - serverApp, - {'test': 'abc'}); - - assert.deepEqual(datasource.connector.remotes.options, {test: 'abc'}); + assert.deepEqual(dataSource.connector.remotes.options, {test: 'abc'}); }); }); diff --git a/test/remote-models.test.js b/test/remote-models.test.js index fcabee2..21383f8 100644 --- a/test/remote-models.test.js +++ b/test/remote-models.test.js @@ -5,48 +5,50 @@ 'use strict'; -var assert = require('assert'); -var helper = require('./helper'); -var TaskEmitter = require('strong-task-emitter'); +const assert = require('assert'); +const helper = require('./helper'); +const loopback = require('loopback'); +const TaskEmitter = require('strong-task-emitter'); describe('Remote model tests', function() { - var ctx = this; + let serverApp, ServerModel, clientApp, ClientModel; - beforeEach(function(done) { - ctx.serverApp = helper.createRestAppAndListen(); - ctx.ServerModel = helper.createModel({ - parent: 'TestModel', - app: ctx.serverApp, - datasource: helper.createMemoryDataSource(), - properties: helper.userProperties + beforeEach(function setupServer(done) { + const app = serverApp = helper.createRestAppAndListen(); + const db = helper.createMemoryDataSource(app); + + ServerModel = app.registry.createModel({ + name: 'TestModel', + properties: helper.userProperties, + options: {forceId: false}, }); - ctx.serverApp.locals.handler.on('listening', function() { done(); }); + app.model(ServerModel, {dataSource: db}); + + serverApp.locals.handler.on('listening', function() { done(); }); }); - beforeEach(function setupRemoteClient(done) { - ctx.remoteApp = helper.createRestAppAndListen(); - ctx.RemoteModel = helper.createModel({ - parent: 'TestModel', - app: ctx.remoteApp, - datasource: helper.createRemoteDataSource(ctx.serverApp), - properties: helper.userProperties + beforeEach(function setupRemoteClient() { + const app = clientApp = loopback({localRegistry: true}); + const remoteDs = helper.createRemoteDataSource(clientApp, serverApp); + + ClientModel = app.registry.createModel({ + name: 'TestModel', }); - ctx.remoteApp.locals.handler.on('listening', function() { done(); }); + app.model(ClientModel, {dataSource: remoteDs}); }); afterEach(function() { - ctx.serverApp.locals.handler.close(); - ctx.remoteApp.locals.handler.close(); - ctx.ServerModel = null; - ctx.RemoteModel = null; + serverApp.locals.handler.close(); + ServerModel = null; + ClientModel = null; }); describe('Model.create([data], [callback])', function() { it('should create an instance and save to the attached data source', function(done) { - ctx.RemoteModel.create({first: 'Joe', last: 'Bob'}, function(err, user) { + ClientModel.create({first: 'Joe', last: 'Bob'}, function(err, user) { if (err) return done(err); - assert(user instanceof ctx.RemoteModel); + assert(user instanceof ClientModel); done(); }); }); @@ -55,7 +57,7 @@ describe('Remote model tests', function() { describe('model.save([options], [callback])', function() { it('should save an instance of a Model to the attached data source', function(done) { - var joe = new ctx.RemoteModel({first: 'Joe', last: 'Bob'}); + const joe = new ClientModel({first: 'Joe', last: 'Bob'}); joe.save(function(err, user) { if (err) return done(err); assert(user.id); @@ -68,7 +70,7 @@ describe('Remote model tests', function() { describe('model.updateAttributes(data, [callback])', function() { it('should save specified attributes to the attached data source', function(done) { - ctx.ServerModel.create({first: 'joe', age: 100}, function(err, user) { + ServerModel.create({first: 'joe', age: 100}, function(err, user) { if (err) return done(err); assert.equal(user.first, 'joe'); @@ -89,11 +91,11 @@ describe('Remote model tests', function() { describe('Model.upsert(data, callback)', function() { it('should update when a record with id=data.id is found, insert otherwise', function(done) { - ctx.RemoteModel.upsert({first: 'joe', id: 7}, function(err, user) { + ClientModel.upsert({first: 'joe', id: 7}, function(err, user) { if (err) return done(err); assert.equal(user.first, 'joe'); - ctx.RemoteModel.upsert({first: 'bob', id: 7}, function(err, + ClientModel.upsert({first: 'bob', id: 7}, function(err, updatedUser) { if (err) return done(err); assert.equal(updatedUser.first, 'bob'); @@ -106,11 +108,11 @@ describe('Remote model tests', function() { describe('Model.deleteById(id, [callback])', function() { it('should delete a model instance from the attached data source', function(done) { - ctx.ServerModel.create({first: 'joe', last: 'bob'}, function(err, user) { + ServerModel.create({first: 'joe', last: 'bob'}, function(err, user) { if (err) return done(err); - ctx.RemoteModel.deleteById(user.id, function(err) { + ClientModel.deleteById(user.id, function(err) { if (err) return done(err); - ctx.RemoteModel.findById(user.id, function(err, notFound) { + ClientModel.findById(user.id, function(err, notFound) { assert.equal(notFound, null); assert(err && err.statusCode === 404, 'should have failed with HTTP 404'); @@ -124,10 +126,10 @@ describe('Remote model tests', function() { describe('Model.findById(id, callback)', function() { it('should find an instance by id from the attached data source', function(done) { - ctx.ServerModel.create({first: 'michael', last: 'jordan', id: 23}, + ServerModel.create({first: 'michael', last: 'jordan', id: 23}, function(err) { if (err) return done(err); - ctx.RemoteModel.findById(23, function(err, user) { + ClientModel.findById(23, function(err, user) { if (err) return done(err); assert.equal(user.id, 23); assert.equal(user.first, 'michael'); @@ -141,16 +143,16 @@ describe('Remote model tests', function() { describe('Model.count([query], callback)', function() { it('should return the count of Model instances from both data source', function(done) { - var taskEmitter = new TaskEmitter(); + const taskEmitter = new TaskEmitter(); taskEmitter - .task(ctx.ServerModel, 'create', {first: 'jill', age: 100}) - .task(ctx.RemoteModel, 'create', {first: 'bob', age: 200}) - .task(ctx.RemoteModel, 'create', {first: 'jan'}) - .task(ctx.ServerModel, 'create', {first: 'sam'}) - .task(ctx.ServerModel, 'create', {first: 'suzy'}) + .task(ServerModel, 'create', {first: 'jill', age: 100}) + .task(ClientModel, 'create', {first: 'bob', age: 200}) + .task(ClientModel, 'create', {first: 'jan'}) + .task(ServerModel, 'create', {first: 'sam'}) + .task(ServerModel, 'create', {first: 'suzy'}) .on('done', function(err) { if (err) return done(err); - ctx.RemoteModel.count({age: {gt: 99}}, function(err, count) { + ClientModel.count({age: {gt: 99}}, function(err, count) { if (err) return done(err); assert.equal(count, 2); done(); From 55cb88f7272050e4cb9210a2727916a3304c7f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 11 Dec 2017 14:51:48 +0100 Subject: [PATCH 2/2] Add eslint to npm test, fix linter issues --- .eslintignore | 1 + .eslintrc | 133 +--------------------------- Gruntfile.js | 36 +++----- index.js | 6 -- lib/relations.js | 2 +- lib/remote-connector.js | 5 +- package.json | 9 +- test/helper.js | 6 +- test/models.test.js | 158 +++++++++++++++++----------------- test/remote-connector.test.js | 8 +- test/remote-models.test.js | 148 +++++++++++++++---------------- 11 files changed, 184 insertions(+), 328 deletions(-) create mode 100644 .eslintignore delete mode 100644 index.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..4ebc8ae --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +coverage diff --git a/.eslintrc b/.eslintrc index 962ec7c..70bcff8 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,134 +1,3 @@ { - "env": { - "browser": false, - "node": true, - "amd": true - }, - - "rules": { - "no-alert": 2, - "no-array-constructor": 2, - "no-bitwise": 2, - "no-caller": 2, - "no-catch-shadow": 2, - "no-comma-dangle": 2, - "no-cond-assign": 2, - "no-console": 1, - "no-constant-condition": 2, - "no-control-regex": 2, - "no-debugger": 2, - "no-delete-var": 2, - "no-div-regex": 1, - "no-dupe-keys": 2, - "no-else-return": 2, - "no-empty": 2, - "no-empty-class": 2, - "no-empty-label": 2, - "no-eq-null": 2, - "no-eval": 2, - "no-ex-assign": 2, - "no-extend-native": 2, - "no-extra-boolean-cast": 2, - "no-extra-parens": 1, - "no-extra-semi": 2, - "no-extra-strict": 2, - "no-fallthrough": 2, - "no-floating-decimal": 1, - "no-func-assign": 2, - "no-global-strict": 2, - "no-implied-eval": 2, - "no-inner-declarations": [2, "functions"], - "no-invalid-regexp": 2, - "no-iterator": 2, - "no-label-var": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-lonely-if": 2, - "no-loop-func": 2, - "no-mixed-requires": [2, false], - "no-multi-str": 2, - "no-native-reassign": 2, - "no-negated-in-lhs": 2, - "no-nested-ternary": 1, - "no-new": 2, - "no-new-func": 2, - "no-new-object": 2, - "no-new-require": 1, - "no-new-wrappers": 2, - "no-obj-calls": 2, - "no-octal": 2, - "no-octal-escape": 2, - "no-path-concat": 0, - "no-plusplus": 2, - "no-process-exit": 2, - "no-proto": 2, - "no-redeclare": 2, - "no-regex-spaces": 2, - "no-restricted-modules": 0, - "no-return-assign": 2, - "no-script-url": 2, - "no-self-compare": 0, - "no-sequences": 2, - "no-shadow": 2, - "no-shadow-restricted-names": 2, - "no-spaced-func": 2, - "no-space-before-semi": 2, - "no-sparse-arrays": 2, - "no-sync": 0, - "no-ternary": 2, - "no-trailing-spaces": 2, - "no-undef": 2, - "no-undefined": 1, - "no-undef-init": 2, - "no-underscore-dangle": 0, - "no-unreachable": 2, - "no-unused-expressions": 2, - "no-unused-vars": [2, {"vars": "all", "args": "after-used"}], - "no-use-before-define": 2, - "no-warning-comments": [1, { "terms": ["todo", "fixme", "xxx"], "location": "start" }], - "no-with": 2, - "no-wrap-func": 2, - "no-mixed-spaces-and-tabs": [2, false], - - "block-scoped-var": 1, - "brace-style": [2, "1tbs"], - "camelcase": 2, - "complexity": [0, 11], - "consistent-return": 2, - "consistent-this": [2, "that"], - "curly": [2, "all"], - "default-case": 1, - "dot-notation": 2, - "eol-last": 2, - "eqeqeq": 2, - "func-names": 0, - "func-style": [2, "declaration"], - "guard-for-in": 1, - "max-depth": [0, 4], - "max-len": [1, 80, 4], - "max-nested-callbacks": [1, 2], - "max-params": [0, 3], - "max-statements": [0, 10], - "handle-callback-err": 1, - "new-cap": 2, - "new-parens": 2, - "one-var": 0, - "quote-props": 1, - "quotes": [2, "single"], - "radix": 2, - "semi": 2, - "sort-vars": 1, - "space-after-keywords": [2, "always"], - "space-in-brackets": [1, "never"], - "space-infix-ops": 2, - "space-return-throw-case": 2, - "space-unary-word-ops": 1, - "strict": 0, - "use-isnan": 2, - "valid-jsdoc": 2, - "valid-typeof": 2, - "wrap-iife": 1, - "wrap-regex": 1, - "yoda": [2, "never"] - } + "extends": "loopback" } diff --git a/Gruntfile.js b/Gruntfile.js index 1714fc5..e17e208 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -3,7 +3,9 @@ // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT -/*global module:false*/ +'use strict'; + +/* global module:false */ module.exports = function(grunt) { // Project configuration. grunt.initConfig({ @@ -15,46 +17,34 @@ module.exports = function(grunt) { '* Copyright (c) <%= grunt.template.today("yyyy") %> ' + '<%= pkg.author.name %>;' + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n', - // Task configuration. - jshint: { - options: { - jshintrc: true - }, - gruntfile: { - src: 'Gruntfile.js' - }, - libTest: { - src: ['lib/**/*.js', 'test/**/*.js'] - } - }, mochaTest: { 'integration': { src: 'test/integration/*.js', options: { - reporter: 'dot' - } + reporter: 'dot', + }, }, 'integration-xml': { src: 'test/integration/*.js', options: { reporter: 'xunit', - captureFile: 'xintegration.xml' - } + captureFile: 'xintegration.xml', + }, }, 'unit': { src: 'test/*.js', options: { - reporter: 'dot' - } + reporter: 'dot', + }, }, 'unit-xml': { src: 'test/*.js', options: { reporter: 'xunit', - captureFile: 'xunit.xml' - } - } - } + captureFile: 'xunit.xml', + }, + }, + }, }); // These plugins provide necessary tasks. diff --git a/index.js b/index.js deleted file mode 100644 index c1b944e..0000000 --- a/index.js +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright IBM Corp. 2014. All Rights Reserved. -// Node module: loopback-connector-remote -// This file is licensed under the MIT License. -// License text available at https://opensource.org/licenses/MIT - -module.exports = require('./lib/remote-connector'); \ No newline at end of file diff --git a/lib/relations.js b/lib/relations.js index f0bbc69..7636a9b 100644 --- a/lib/relations.js +++ b/lib/relations.js @@ -231,6 +231,6 @@ function defineRelationProperty(modelClass, def) { return that['__findById__' + def.name].apply(that, arguments); }; return scope; - } + }, }); } diff --git a/lib/remote-connector.js b/lib/remote-connector.js index b7dc650..b28e081 100644 --- a/lib/remote-connector.js +++ b/lib/remote-connector.js @@ -29,7 +29,7 @@ module.exports = RemoteConnector; function RemoteConnector(settings) { assert(typeof settings === 'object', - 'cannot initialize RemoteConnector without a settings object'); + 'cannot initialize RemoteConnector without a settings object'); this.client = settings.client; this.adapter = settings.adapter || 'rest'; this.protocol = settings.protocol || 'http'; @@ -48,7 +48,6 @@ function RemoteConnector(settings) { // handle mixins in the define() method var DAO = this.DataAccessObject = function() { }; - } RemoteConnector.prototype.connect = function() { @@ -67,7 +66,7 @@ RemoteConnector.prototype.define = function(definition) { var remotes = this.remotes; assert(Model.sharedClass, - 'cannot attach ' + + 'cannot attach ' + Model.modelName + ' to a remote connector without a Model.sharedClass'); diff --git a/package.json b/package.json index 647d621..e30a246 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "loopback-connector-remote", "version": "3.2.0", "description": "Remote REST API connector for Loopback", - "main": "index.js", + "main": "lib/remote-connector.js", "keywords": [ "web", "restful", @@ -10,7 +10,9 @@ "StrongLoop" ], "scripts": { - "test": "grunt" + "test": "grunt", + "posttest": "npm run lint", + "lint": "eslint ." }, "engines": { "node": ">=4.0.0" @@ -29,6 +31,8 @@ }, "homepage": "http://loopback.io", "dependencies": { + "eslint": "^4.13.0", + "eslint-config-loopback": "^8.0.0", "loopback-datasource-juggler": "^3.0.0", "strong-remoting": "^3.0.0" }, @@ -37,7 +41,6 @@ "bluebird": "^3.3.5", "grunt": "^1.0.1", "grunt-cli": "^1.2.0", - "grunt-contrib-jshint": "^1.0.0", "grunt-mocha-test": "^0.12.7", "loopback": "^3.0.0", "mocha": "^3.0.2", diff --git a/test/helper.js b/test/helper.js index bf0075c..893ecb3 100644 --- a/test/helper.js +++ b/test/helper.js @@ -22,7 +22,7 @@ function createRestAppAndListen() { app.set('legacyExplorer', false); app.set('remoting', { - errorHandler: { debug: true, log: false }, + errorHandler: {debug: true, log: false}, context: false, }); @@ -39,7 +39,7 @@ function createMemoryDataSource(app) { function createRemoteDataSource(app, serverApp) { return app.dataSource('remote', { url: 'http://' + serverApp.get('host') + ':' + serverApp.get('port'), - connector: remoteConnector + connector: remoteConnector, }); } @@ -51,6 +51,6 @@ function getUserProperties() { 'password': String, 'gender': String, 'domain': String, - 'email': String + 'email': String, }; } diff --git a/test/models.test.js b/test/models.test.js index 96782e9..6af219a 100644 --- a/test/models.test.js +++ b/test/models.test.js @@ -27,34 +27,34 @@ describe('Model tests', function() { describe('Model.validatesPresenceOf(properties...)', function() { it('should require a model to include a property to be considered valid', - function() { - User.validatesPresenceOf('first', 'last', 'age'); - const 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'); - }); + function() { + User.validatesPresenceOf('first', 'last', 'age'); + const joe = new User({first: 'joe'}); + assert(joe.isValid() === false, 'model should not validate'); + assert(joe.errors.last, 'should have a missing last error'); + assert(joe.errors.age, 'should have a missing age error'); + }); }); describe('Model.validatesLengthOf(property, options)', function() { it('should require a property length to be within a specified range', - function() { - User.validatesLengthOf('password', {min: 5, message: {min: + function() { + User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}}); - const joe = new User({password: '1234'}); - assert(joe.isValid() === false, 'model should not be valid'); - assert(joe.errors.password, 'should have password error'); - }); + const joe = new User({password: '1234'}); + assert(joe.isValid() === false, 'model should not be valid'); + assert(joe.errors.password, 'should have password error'); + }); }); describe('Model.validatesInclusionOf(property, options)', function() { it('should require a value for `property` to be in the specified array', - function() { - User.validatesInclusionOf('gender', {in: ['male', 'female']}); - const foo = new User({gender: 'bar'}); - assert(foo.isValid() === false, 'model should not be valid'); - assert(foo.errors.gender, 'should have gender error'); - }); + function() { + User.validatesInclusionOf('gender', {in: ['male', 'female']}); + const foo = new User({gender: 'bar'}); + assert(foo.isValid() === false, 'model should not be valid'); + assert(foo.errors.gender, 'should have gender error'); + }); }); describe('Model.validatesExclusionOf(property, options)', function() { @@ -107,63 +107,63 @@ describe('Model tests', function() { describe('Model.create([data], [callback])', function() { it('should create an instance and save to the attached data source', - function(done) { - User.create({first: 'Joe', last: 'Bob'}, function(err, user) { - if (err) return done(err); - assert(user instanceof User); - done(); + function(done) { + User.create({first: 'Joe', last: 'Bob'}, function(err, user) { + if (err) return done(err); + assert(user instanceof User); + done(); + }); }); - }); }); describe('model.save([options], [callback])', function() { it('should save an instance of a Model to the attached data source', - function(done) { - const joe = new User({first: 'Joe', last: 'Bob'}); - joe.save(function(err, user) { - if (err) return done(err); - assert(user.id); - assert(!user.errors); - done(); + function(done) { + const joe = new User({first: 'Joe', last: 'Bob'}); + joe.save(function(err, user) { + if (err) return done(err); + assert(user.id); + assert(!user.errors); + done(); + }); }); - }); }); describe('model.updateAttributes(data, [callback])', function() { it('should save specified attributes to the attached data source', - function(done) { - User.create({first: 'joe', age: 100}, function(err, user) { - if (err) return done(err); - assert.equal(user.first, 'joe'); - - user.updateAttributes({ - first: 'updatedFirst', - last: 'updatedLast' - }, function(err, updatedUser) { + function(done) { + User.create({first: 'joe', age: 100}, function(err, user) { if (err) return done(err); - assert.equal(updatedUser.first, 'updatedFirst'); - assert.equal(updatedUser.last, 'updatedLast'); - assert.equal(updatedUser.age, 100); - done(); + assert.equal(user.first, 'joe'); + + user.updateAttributes({ + first: 'updatedFirst', + last: 'updatedLast', + }, function(err, updatedUser) { + if (err) return done(err); + assert.equal(updatedUser.first, 'updatedFirst'); + assert.equal(updatedUser.last, 'updatedLast'); + assert.equal(updatedUser.age, 100); + done(); + }); }); }); - }); }); describe('Model.upsert(data, callback)', function() { it('should update when a record with id=data.id is found, insert otherwise', - function(done) { - User.upsert({first: 'joe', id: 7}, function(err, user) { - if (err) return done(err); - assert.equal(user.first, 'joe'); - - User.upsert({first: 'bob', id: 7}, function(err, updatedUser) { + function(done) { + User.upsert({first: 'joe', id: 7}, function(err, user) { if (err) return done(err); - assert.equal(updatedUser.first, 'bob'); - done(); + assert.equal(user.first, 'joe'); + + User.upsert({first: 'bob', id: 7}, function(err, updatedUser) { + if (err) return done(err); + assert.equal(updatedUser.first, 'bob'); + done(); + }); }); }); - }); }); describe('model.destroy([callback])', function() { @@ -188,19 +188,19 @@ describe('Model tests', function() { describe('Model.deleteById(id, [callback])', function() { it('should delete a model instance from the attached data source', - function(done) { - User.create({first: 'joe', last: 'bob'}, function(err, user) { - if (err) return done(err); - User.deleteById(user.id, function(err) { + function(done) { + User.create({first: 'joe', last: 'bob'}, function(err, user) { if (err) return done(err); - User.findById(user.id, function(err, notFound) { + User.deleteById(user.id, function(err) { if (err) return done(err); - assert.equal(notFound, null); - done(); + User.findById(user.id, function(err, notFound) { + if (err) return done(err); + assert.equal(notFound, null); + done(); + }); }); }); }); - }); }); describe('Model.findById(id, callback)', function() { @@ -221,21 +221,21 @@ describe('Model tests', function() { describe('Model.count([query], callback)', function() { it('should return the count of Model instances in data source', - function(done) { - const taskEmitter = new TaskEmitter(); - taskEmitter - .task(User, 'create', {first: 'jill', age: 100}) - .task(User, 'create', {first: 'bob', age: 200}) - .task(User, 'create', {first: 'jan'}) - .task(User, 'create', {first: 'sam'}) - .task(User, 'create', {first: 'suzy'}) - .on('done', function() { - User.count({age: {gt: 99}}, function(err, count) { - if (err) return done(err); - assert.equal(count, 2); - done(); + function(done) { + const taskEmitter = new TaskEmitter(); + taskEmitter + .task(User, 'create', {first: 'jill', age: 100}) + .task(User, 'create', {first: 'bob', age: 200}) + .task(User, 'create', {first: 'jan'}) + .task(User, 'create', {first: 'sam'}) + .task(User, 'create', {first: 'suzy'}) + .on('done', function() { + User.count({age: {gt: 99}}, function(err, count) { + if (err) return done(err); + assert.equal(count, 2); + done(); + }); }); - }); - }); + }); }); }); diff --git a/test/remote-connector.test.js b/test/remote-connector.test.js index 6a2e6f2..0445590 100644 --- a/test/remote-connector.test.js +++ b/test/remote-connector.test.js @@ -99,8 +99,8 @@ describe('Custom Path', function() { ServerModel = app.registry.createModel({ name: 'TestModel', options: { - http: {path: '/custom'} - } + http: {path: '/custom'}, + }, }); app.model(ServerModel, {dataSource: db}); @@ -115,8 +115,8 @@ describe('Custom Path', function() { name: 'TestModel', options: { dataSource: 'remote', - http: {path: '/custom'} - } + http: {path: '/custom'}, + }, }); app.model(ClientModel, {dataSource: remoteDs}); }); diff --git a/test/remote-models.test.js b/test/remote-models.test.js index 21383f8..9b7d1dc 100644 --- a/test/remote-models.test.js +++ b/test/remote-models.test.js @@ -45,119 +45,119 @@ describe('Remote model tests', function() { describe('Model.create([data], [callback])', function() { it('should create an instance and save to the attached data source', - function(done) { - ClientModel.create({first: 'Joe', last: 'Bob'}, function(err, user) { - if (err) return done(err); - assert(user instanceof ClientModel); - done(); + function(done) { + ClientModel.create({first: 'Joe', last: 'Bob'}, function(err, user) { + if (err) return done(err); + assert(user instanceof ClientModel); + done(); + }); }); - }); }); describe('model.save([options], [callback])', function() { it('should save an instance of a Model to the attached data source', - function(done) { - const joe = new ClientModel({first: 'Joe', last: 'Bob'}); - joe.save(function(err, user) { - if (err) return done(err); - assert(user.id); - assert(!user.errors); - done(); + function(done) { + const joe = new ClientModel({first: 'Joe', last: 'Bob'}); + joe.save(function(err, user) { + if (err) return done(err); + assert(user.id); + assert(!user.errors); + done(); + }); }); - }); }); describe('model.updateAttributes(data, [callback])', function() { it('should save specified attributes to the attached data source', - function(done) { - ServerModel.create({first: 'joe', age: 100}, function(err, user) { - if (err) return done(err); - assert.equal(user.first, 'joe'); - - user.updateAttributes({ - first: 'updatedFirst', - last: 'updatedLast' - }, function(err, updatedUser) { + function(done) { + ServerModel.create({first: 'joe', age: 100}, function(err, user) { if (err) return done(err); - assert.equal(updatedUser.first, 'updatedFirst'); - assert.equal(updatedUser.last, 'updatedLast'); - assert.equal(updatedUser.age, 100); - done(); + assert.equal(user.first, 'joe'); + + user.updateAttributes({ + first: 'updatedFirst', + last: 'updatedLast', + }, function(err, updatedUser) { + if (err) return done(err); + assert.equal(updatedUser.first, 'updatedFirst'); + assert.equal(updatedUser.last, 'updatedLast'); + assert.equal(updatedUser.age, 100); + done(); + }); }); }); - }); }); describe('Model.upsert(data, callback)', function() { it('should update when a record with id=data.id is found, insert otherwise', - function(done) { - ClientModel.upsert({first: 'joe', id: 7}, function(err, user) { - if (err) return done(err); - assert.equal(user.first, 'joe'); - - ClientModel.upsert({first: 'bob', id: 7}, function(err, - updatedUser) { + function(done) { + ClientModel.upsert({first: 'joe', id: 7}, function(err, user) { if (err) return done(err); - assert.equal(updatedUser.first, 'bob'); - done(); + assert.equal(user.first, 'joe'); + + ClientModel.upsert({first: 'bob', id: 7}, function(err, + updatedUser) { + if (err) return done(err); + assert.equal(updatedUser.first, 'bob'); + done(); + }); }); }); - }); }); describe('Model.deleteById(id, [callback])', function() { it('should delete a model instance from the attached data source', - function(done) { - ServerModel.create({first: 'joe', last: 'bob'}, function(err, user) { - if (err) return done(err); - ClientModel.deleteById(user.id, function(err) { + function(done) { + ServerModel.create({first: 'joe', last: 'bob'}, function(err, user) { if (err) return done(err); - ClientModel.findById(user.id, function(err, notFound) { - assert.equal(notFound, null); - assert(err && err.statusCode === 404, - 'should have failed with HTTP 404'); - done(); + ClientModel.deleteById(user.id, function(err) { + if (err) return done(err); + ClientModel.findById(user.id, function(err, notFound) { + assert.equal(notFound, null); + assert(err && err.statusCode === 404, + 'should have failed with HTTP 404'); + done(); + }); }); }); }); - }); }); describe('Model.findById(id, callback)', function() { it('should find an instance by id from the attached data source', - function(done) { - ServerModel.create({first: 'michael', last: 'jordan', id: 23}, + function(done) { + ServerModel.create({first: 'michael', last: 'jordan', id: 23}, function(err) { - if (err) return done(err); - ClientModel.findById(23, function(err, user) { - if (err) return done(err); - assert.equal(user.id, 23); - assert.equal(user.first, 'michael'); - assert.equal(user.last, 'jordan'); - done(); - }); + if (err) return done(err); + ClientModel.findById(23, function(err, user) { + if (err) return done(err); + assert.equal(user.id, 23); + assert.equal(user.first, 'michael'); + assert.equal(user.last, 'jordan'); + done(); + }); + }); }); - }); }); describe('Model.count([query], callback)', function() { it('should return the count of Model instances from both data source', - function(done) { - const taskEmitter = new TaskEmitter(); - taskEmitter - .task(ServerModel, 'create', {first: 'jill', age: 100}) - .task(ClientModel, 'create', {first: 'bob', age: 200}) - .task(ClientModel, 'create', {first: 'jan'}) - .task(ServerModel, 'create', {first: 'sam'}) - .task(ServerModel, 'create', {first: 'suzy'}) - .on('done', function(err) { - if (err) return done(err); - ClientModel.count({age: {gt: 99}}, function(err, count) { + function(done) { + const taskEmitter = new TaskEmitter(); + taskEmitter + .task(ServerModel, 'create', {first: 'jill', age: 100}) + .task(ClientModel, 'create', {first: 'bob', age: 200}) + .task(ClientModel, 'create', {first: 'jan'}) + .task(ServerModel, 'create', {first: 'sam'}) + .task(ServerModel, 'create', {first: 'suzy'}) + .on('done', function(err) { if (err) return done(err); - assert.equal(count, 2); - done(); + ClientModel.count({age: {gt: 99}}, function(err, count) { + if (err) return done(err); + assert.equal(count, 2); + done(); + }); }); - }); - }); + }); }); });