From 0d73fcc258cc114a54d8582f2b064eef5664037f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nataniel=20L=C3=B3pez?= Date: Thu, 14 May 2020 21:27:33 +0000 Subject: [PATCH 1/4] Fixed postSaveHook and added databaseSettingsSource config --- CHANGELOG.md | 6 ++ README.md | 117 ++++++++++++++++++++++++++++- lib/api-create.js | 40 +++++----- lib/listener-created.js | 24 ++++-- package-lock.json | 2 +- tests/api-create.js | 154 +++++++++++++++++++++++++++++++------- tests/listener-created.js | 100 ++++++++++++++++++++++--- 7 files changed, 379 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 971eb00..e084998 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- `databaseSettings` parameter for `postSaveHook()` method +- `databaseSettingsSource` getter to specify other settings source for client DB config + +### Fixed +- `Client Create API` `postSaveHook()` client codes parameter ## [1.0.4] - 2020-05-04 ### Fixed diff --git a/README.md b/README.md index 38b9407..4a1d1bc 100644 --- a/README.md +++ b/README.md @@ -109,4 +109,119 @@ Finally, create or update `./.nycrc` to avoid coverage leaks: } ``` -:warning: If exists any customization of the files, do not add the file to the .nyrcr and add the corresponding tests. \ No newline at end of file +:warning: If exists any customization of the files, do not add the file to the .nyrcr and add the corresponding tests. + +### Getters +Both `APICreate` and `ListenerCreated` have a getter for customize the client creation settings. + +#### `databaseSettingsSource` (*`instance getter`*): Is the database config source key that will be getted from your MS database config. Default: `clientModel.databaseKey`. + +##### Example + +##### .janiscommercerc +```js +{ + "database":{ + "newClients": { + type: 'mongodb', + host: 'core-host' + // ... + }, + otherDb: { + host: 'http://clients-host:8983', + type: 'solr' + } + } +} +``` + +##### `./[MS_PATH]/api/client/post.js` +```js +'use strict'; +const { APICreate } = require('@janiscommerce/client-creator') + +class ClientCreateAPI extends APICreate { + + get databaseSettingsSource() { + return 'otherDb'; + } +} + +module.exports = ClientCreateAPI; +``` + +##### `./[MS_PATH]/event-listeners/id/client/created.js` +```js +'use strict'; +const { ServerlessHandler } = require('@janiscommerce/event-listener'); +const { ListenerCreated } = require('@janiscommerce/client-creator'); + +class ClientCreateListener extends ListenerCreated { + + get databaseSettingsSource() { + return 'otherDb'; + } +} + +module.exports.handler = (...args) => ServerlessHandler.handle(ClientCreateListener, ...args); +``` + +### Hooks +Both `APICreate` and `ListenerCreated` have a hook for post processing the client or clients created data. + +#### APICreate + +#### `postSaveHook(clientCodes, databaseSettings)` +Receives the clientCodes from the API and the databaseSettings for the created clients. + +Parameters: +- clientCodes `string Array`: The client created codes . +- databaseSettings `Object`: The database settings of the created clients. + +##### Example +```js +'use strict'; +const { APICreate } = require('@janiscommerce/client-creator') + +class ClientCreateAPI extends APICreate { + + async postSaveHook(clientCodes, databaseSettings) { + + await myPostSaveMethod(clientCodes, databaseSettings); + + clientCodes.forEach(code => { + console.log(`Saved client ${code} with host: ${databaseSettings.host}`); + }) + } +} + +module.exports = ClientCreateAPI; +``` + +#### ListenerCreated + +#### `postSaveHook(clientCode, databaseSettings)` +Receives the clientCode from the event and the databaseSettings for the created client. + +Parameters: +- clientCode `string`: The client created code . +- databaseSettings `Object`: The database settings of the created client. + +##### Example +```js +'use strict'; +const { ServerlessHandler } = require('@janiscommerce/event-listener'); +const { ListenerCreated } = require('@janiscommerce/client-creator'); + +class ClientCreateListener extends ListenerCreated { + + async postSaveHook(clientCode, databaseSettings) { + + await myPostSaveMethod(clientCode, databaseSettings); + + console.log(`Saved client ${code} with host: ${databaseSettings.host}`); + } +} + +module.exports.handler = (...args) => ServerlessHandler.handle(ClientCreateListener, ...args); +``` diff --git a/lib/api-create.js b/lib/api-create.js index c074329..8e8c2fc 100644 --- a/lib/api-create.js +++ b/lib/api-create.js @@ -7,9 +7,22 @@ const InstanceGetter = require('./helper/instance-getter'); const mongoDBIndexCreator = new MongoDBIndexCreator(); - class ClientCreateAPI extends API { + get clientModel() { + + if(!this._clientModel) { + const instanceGetter = this.session.getSessionInstance(InstanceGetter); + this._clientModel = instanceGetter.getModelInstance('client'); + } + + return this._clientModel; + } + + get databaseSettingsSource() { + return this.clientModel.databaseKey; + } + async validate(data = this.data) { if(data === null || typeof data !== 'object' || Array.isArray(data)) @@ -19,13 +32,9 @@ class ClientCreateAPI extends API { throw new Error('Invalid data: Should have a clients property and must be an array.'); } - async process({ clients } = this.data) { - - const instanceGetter = this.session.getSessionInstance(InstanceGetter); - - const clientModel = instanceGetter.getModelInstance('client'); + async process({ clients: clientCodes } = this.data) { - const databaseSettings = Settings.get('database')[clientModel.databaseKey]; + const databaseSettings = Settings.get('database')[this.databaseSettingsSource]; const clientDatabase = { dbHost: databaseSettings.host @@ -43,22 +52,19 @@ class ClientCreateAPI extends API { if(databaseSettings.password) clientDatabase.dbPassword = databaseSettings.password; - - const clientsCodes = []; - const clientsToCreate = clients.map(client => { - clientsCodes.push(client.code); + const clientsToCreate = clientCodes.map(code => { return { - code: client, - status: clientModel.constructor.statuses.active, + code, + status: this.clientModel.constructor.statuses.active, ...clientDatabase, - dbDatabase: `janis-${client}` + dbDatabase: `janis-${code}` }; }); - - await clientModel.multiSave(clientsToCreate); + await this.clientModel.multiSave(clientsToCreate); await mongoDBIndexCreator.executeForClientDatabases(); - await this.postSaveHook(clientsCodes); + + return this.postSaveHook(clientCodes, databaseSettings); } /** diff --git a/lib/listener-created.js b/lib/listener-created.js index f94f322..f9ca0d4 100644 --- a/lib/listener-created.js +++ b/lib/listener-created.js @@ -16,13 +16,23 @@ class ClientCreatedListener extends EventListener { return true; } - async process(clientCode = this.eventId) { + get clientModel() { + + if(!this._clientModel) { + const instanceGetter = this.session.getSessionInstance(InstanceGetter); + this._clientModel = instanceGetter.getModelInstance('client'); + } + + return this._clientModel; + } - const instanceGetter = this.session.getSessionInstance(InstanceGetter); + get databaseSettingsSource() { + return this.clientModel.databaseKey; + } - const clientModel = instanceGetter.getModelInstance('client'); + async process(clientCode = this.eventId) { - const databaseSettings = Settings.get('database')[clientModel.databaseKey]; + const databaseSettings = Settings.get('database')[this.databaseSettingsSource]; const clientDatabase = { dbHost: databaseSettings.host, @@ -42,14 +52,14 @@ class ClientCreatedListener extends EventListener { clientDatabase.dbPassword = databaseSettings.password; - await clientModel.save({ + await this.clientModel.save({ code: clientCode, - status: clientModel.constructor.statuses.active, + status: this.clientModel.constructor.statuses.active, ...clientDatabase }); await mongoDBIndexCreator.executeForClientCode(clientCode); - await this.postSaveHook(clientCode); + return this.postSaveHook(clientCode, databaseSettings); } /** diff --git a/package-lock.json b/package-lock.json index 2aa62e3..1cdcd28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@janiscommerce/client-creator", - "version": "1.0.3", + "version": "1.0.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/tests/api-create.js b/tests/api-create.js index f676179..812ae43 100644 --- a/tests/api-create.js +++ b/tests/api-create.js @@ -18,6 +18,9 @@ describe('APIs', () => { const fakeSettings = { newClients: { host: 'some-database-host' + }, + otherDb: { + host: 'other-database-host' } }; @@ -28,6 +31,13 @@ describe('APIs', () => { port: 27017, user: 'some-user', password: 'some-password' + }, + otherDb: { + host: 'other-database-host', + protocol: 'other-protocol://', + port: 27017, + user: 'other-user', + password: 'other-password' } }; @@ -38,6 +48,11 @@ describe('APIs', () => { dbDatabase: 'janis-some-client' }; + const expectedOtherClientObject = { + ...expectedClientObject, + dbHost: fakeSettings.otherDb.host + }; + const expectedFullClientObject = { ...expectedClientObject, dbProtocol: fakeFullSettings.newClients.protocol, @@ -50,6 +65,7 @@ describe('APIs', () => { { description: 'Should save all the received new clients to clients DB', + session: true, request: { data: { clients: [ @@ -58,20 +74,27 @@ describe('APIs', () => { ] } }, - session: true, response: { code: 200 }, before: sandbox => { + mockRequire(fakeClientPath, ClientModel); - sandbox.stub(Settings, 'get').returns(fakeSettings); - sandbox.stub(ClientModel.prototype, 'multiSave').resolves(true); - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases').resolves(); + + sandbox.stub(Settings, 'get') + .returns(fakeSettings); + + sandbox.stub(ClientModel.prototype, 'multiSave') + .resolves(true); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases') + .resolves(); + + sandbox.spy(ClientCreateAPI.prototype, 'postSaveHook'); }, after: (res, sandbox) => { - sandbox.assert.calledOnce(ClientModel.prototype.multiSave); - sandbox.assert.calledWithExactly(ClientModel.prototype.multiSave, [ + sandbox.assert.calledOnceWithExactly(ClientModel.prototype.multiSave, [ expectedClientObject, { ...expectedClientObject, @@ -79,12 +102,14 @@ describe('APIs', () => { dbDatabase: 'janis-other-client' } ]); - sandbox.assert.calledOnce(MongoDBIndexCreator.prototype.executeForClientDatabases); + + sandbox.assert.calledOnceWithExactly(ClientCreateAPI.prototype.postSaveHook, ['some-client', 'other-client'], fakeSettings.newClients); mockRequire.stop(fakeClientPath); } }, { description: 'Should save all the received new clients to clients DB with full database config', + session: true, request: { data: { clients: [ @@ -96,13 +121,20 @@ describe('APIs', () => { response: { code: 200 }, - session: true, before: sandbox => { mockRequire(fakeClientPath, ClientModel); - sandbox.stub(Settings, 'get').returns(fakeFullSettings); - sandbox.stub(ClientModel.prototype, 'multiSave').resolves(true); - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases').resolves(); + + sandbox.stub(Settings, 'get') + .returns(fakeFullSettings); + + sandbox.stub(ClientModel.prototype, 'multiSave') + .resolves(true); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases') + .resolves(); + + sandbox.spy(ClientCreateAPI.prototype, 'postSaveHook'); }, after: (res, sandbox) => { @@ -114,12 +146,63 @@ describe('APIs', () => { dbDatabase: 'janis-other-client' } ]); + sandbox.assert.calledOnce(MongoDBIndexCreator.prototype.executeForClientDatabases); + + sandbox.assert.calledOnceWithExactly(ClientCreateAPI.prototype.postSaveHook, ['some-client', 'other-client'], fakeFullSettings.newClients); + mockRequire.stop(fakeClientPath); + } + }, + { + description: 'Should save all the received new clients to clients DB using a different db config', + session: true, + request: { + data: { + clients: [ + 'some-client', + 'other-client' + ] + } + }, + response: { + code: 200 + }, + before: sandbox => { + + mockRequire(fakeClientPath, ClientModel); + + sandbox.stub(ClientCreateAPI.prototype, 'databaseSettingsSource') + .get(() => 'otherDb'); + + sandbox.stub(Settings, 'get') + .returns(fakeSettings); + + sandbox.stub(ClientModel.prototype, 'multiSave') + .resolves(true); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases') + .resolves(); + + sandbox.spy(ClientCreateAPI.prototype, 'postSaveHook'); + }, + after: (res, sandbox) => { + + sandbox.assert.calledOnceWithExactly(ClientModel.prototype.multiSave, [ + expectedOtherClientObject, + { + ...expectedOtherClientObject, + code: 'other-client', + dbDatabase: 'janis-other-client' + } + ]); + + sandbox.assert.calledOnceWithExactly(ClientCreateAPI.prototype.postSaveHook, ['some-client', 'other-client'], fakeSettings.otherDb); mockRequire.stop(fakeClientPath); } }, { description: 'Should return 500 when the client model multiSave fails', + session: true, request: { data: { clients: ['some-client'] @@ -131,11 +214,16 @@ describe('APIs', () => { before: sandbox => { mockRequire(fakeClientPath, ClientModel); - sandbox.stub(Settings, 'get').returns(fakeSettings); - sandbox.stub(ClientModel.prototype, 'multiSave').throws(); - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases').resolves(); + + sandbox.stub(Settings, 'get') + .returns(fakeSettings); + + sandbox.stub(ClientModel.prototype, 'multiSave') + .rejects(); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases') + .resolves(); }, - session: true, after: (res, sandbox) => { mockRequire.stop(fakeClientPath); @@ -147,6 +235,7 @@ describe('APIs', () => { }, { description: 'Should return 500 when the index creator fails', + session: true, request: { data: { clients: ['some-client'] @@ -155,47 +244,54 @@ describe('APIs', () => { response: { code: 500 }, - session: true, before: sandbox => { mockRequire(fakeClientPath, ClientModel); - sandbox.stub(Settings, 'get').returns(fakeSettings); - sandbox.stub(ClientModel.prototype, 'multiSave').resolves(); - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases').throws(); + + sandbox.stub(Settings, 'get') + .returns(fakeSettings); + + sandbox.stub(ClientModel.prototype, 'multiSave') + .resolves(); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases') + .rejects(); }, after: (res, sandbox) => { - mockRequire.stop(fakeClientPath); sandbox.assert.calledOnceWithExactly(ClientModel.prototype.multiSave, [ expectedClientObject ]); + sandbox.assert.calledOnce(MongoDBIndexCreator.prototype.executeForClientDatabases); + mockRequire.stop(fakeClientPath); } }, { description: 'Should return 400 when the received request data is invalid', + session: true, request: { data: ['something'] }, - session: true, response: { code: 400 } }, { description: 'Should return 400 when the received clients are invalid', + session: true, request: { data: { clients: { some: 'object' } } }, - session: true, response: { code: 400 } }, { description: 'Should return 400 when the client model is not in the corresponding path', + session: true, request: { data: { clients: [ @@ -204,15 +300,21 @@ describe('APIs', () => { ] } }, - session: true, response: { code: 500 }, before: sandbox => { + mockRequire(fakeWrongClientPath, ClientModel); - sandbox.stub(Settings, 'get').returns(fakeSettings); - sandbox.stub(ClientModel.prototype, 'multiSave').resolves(true); - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases').resolves(); + + sandbox.stub(Settings, 'get') + .returns(fakeSettings); + + sandbox.stub(ClientModel.prototype, 'multiSave') + .resolves(true); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases') + .resolves(); }, after: (res, sandbox) => { diff --git a/tests/listener-created.js b/tests/listener-created.js index 70478b5..5e70bcf 100644 --- a/tests/listener-created.js +++ b/tests/listener-created.js @@ -25,6 +25,9 @@ describe('Client Created Listener', async () => { const fakeSettings = { newClients: { host: 'some-database-host' + }, + otherDb: { + host: 'other-database-host' } }; @@ -35,6 +38,13 @@ describe('Client Created Listener', async () => { port: 27017, user: 'some-user', password: 'some-password' + }, + otherDb: { + host: 'other-database-host', + protocol: 'other-protocol://', + port: 27017, + user: 'other-user', + password: 'other-password' } }; @@ -45,6 +55,11 @@ describe('Client Created Listener', async () => { dbDatabase: 'janis-some-client' }; + const expectedOtherClientObject = { + ...expectedClientObject, + dbHost: fakeSettings.otherDb.host + }; + const expectedFullClientObject = { ...expectedClientObject, dbProtocol: fakeFullSettings.newClients.protocol, @@ -70,9 +85,15 @@ describe('Client Created Listener', async () => { before: sandbox => { mockRequire(fakeClientPath, ClientModel); - sandbox.stub(ClientModel.prototype, 'save').throws(); - sandbox.stub(Settings, 'get').returns(fakeSettings); - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode').resolves(); + + sandbox.stub(ClientModel.prototype, 'save') + .rejects(); + + sandbox.stub(Settings, 'get') + .returns(fakeSettings); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') + .resolves(); }, after: sandbox => { @@ -89,9 +110,15 @@ describe('Client Created Listener', async () => { before: sandbox => { mockRequire(fakeClientPath, ClientModel); - sandbox.stub(ClientModel.prototype, 'save').resolves(); - sandbox.stub(Settings, 'get').returns(fakeSettings); - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode').throws(); + + sandbox.stub(ClientModel.prototype, 'save') + .resolves(); + + sandbox.stub(Settings, 'get') + .returns(fakeSettings); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') + .rejects(); }, after: sandbox => { @@ -108,14 +135,23 @@ describe('Client Created Listener', async () => { before: sandbox => { mockRequire(fakeClientPath, ClientModel); - sandbox.stub(ClientModel.prototype, 'save').resolves('5dea9fc691240d00084083f9'); - sandbox.stub(Settings, 'get').returns(fakeSettings); - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode').resolves(); + + sandbox.stub(ClientModel.prototype, 'save') + .resolves('5dea9fc691240d00084083f9'); + + sandbox.stub(Settings, 'get') + .returns(fakeSettings); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') + .resolves(); + + sandbox.spy(ClientCreatedListener.prototype, 'postSaveHook'); }, after: sandbox => { sandbox.assert.calledOnceWithExactly(ClientModel.prototype.save, expectedClientObject); sandbox.assert.calledOnceWithExactly(MongoDBIndexCreator.prototype.executeForClientCode, 'some-client'); + sandbox.assert.calledOnceWithExactly(ClientCreatedListener.prototype.postSaveHook, 'some-client', fakeSettings.newClients); mockRequire.stop(fakeClientPath); }, responseCode: 200 @@ -127,14 +163,54 @@ describe('Client Created Listener', async () => { before: sandbox => { mockRequire(fakeClientPath, ClientModel); - sandbox.stub(ClientModel.prototype, 'save').resolves('5dea9fc691240d00084083f9'); - sandbox.stub(Settings, 'get').returns(fakeFullSettings); - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode').resolves(); + + sandbox.stub(ClientModel.prototype, 'save') + .resolves('5dea9fc691240d00084083f9'); + + sandbox.stub(Settings, 'get') + .returns(fakeFullSettings); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') + .resolves(); + + sandbox.spy(ClientCreatedListener.prototype, 'postSaveHook'); }, after: sandbox => { sandbox.assert.calledOnceWithExactly(ClientModel.prototype.save, expectedFullClientObject); sandbox.assert.calledOnceWithExactly(MongoDBIndexCreator.prototype.executeForClientCode, 'some-client'); + sandbox.assert.calledOnceWithExactly(ClientCreatedListener.prototype.postSaveHook, 'some-client', fakeFullSettings.newClients); + mockRequire.stop(fakeClientPath); + }, + responseCode: 200 + }, + { + description: 'Should return 200 when client model saves the new client sucessfully using a different db config', + event: validEvent, + session: true, + before: sandbox => { + + mockRequire(fakeClientPath, ClientModel); + + sandbox.stub(ClientCreatedListener.prototype, 'databaseSettingsSource') + .get(() => 'otherDb'); + + sandbox.stub(ClientModel.prototype, 'save') + .resolves('5dea9fc691240d00084083f9'); + + sandbox.stub(Settings, 'get') + .returns(fakeSettings); + + sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') + .resolves(); + + sandbox.spy(ClientCreatedListener.prototype, 'postSaveHook'); + }, + after: sandbox => { + + sandbox.assert.calledOnceWithExactly(ClientModel.prototype.save, expectedOtherClientObject); + sandbox.assert.calledOnceWithExactly(MongoDBIndexCreator.prototype.executeForClientCode, 'some-client'); + sandbox.assert.calledOnceWithExactly(ClientCreatedListener.prototype.postSaveHook, 'some-client', fakeSettings.otherDb); mockRequire.stop(fakeClientPath); }, responseCode: 200 From 96eb27234131ffedd7a6139149db4fe9ff056156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nataniel=20L=C3=B3pez?= Date: Mon, 18 May 2020 21:39:02 +0000 Subject: [PATCH 2/4] Updated clientModel --- lib/api-create.js | 6 +-- lib/listener-created.js | 6 +-- lib/model-client.js | 9 +++- tests/api-create.js | 112 ++++++++++------------------------------ 4 files changed, 35 insertions(+), 98 deletions(-) diff --git a/lib/api-create.js b/lib/api-create.js index 8e8c2fc..c4d3fda 100644 --- a/lib/api-create.js +++ b/lib/api-create.js @@ -19,10 +19,6 @@ class ClientCreateAPI extends API { return this._clientModel; } - get databaseSettingsSource() { - return this.clientModel.databaseKey; - } - async validate(data = this.data) { if(data === null || typeof data !== 'object' || Array.isArray(data)) @@ -34,7 +30,7 @@ class ClientCreateAPI extends API { async process({ clients: clientCodes } = this.data) { - const databaseSettings = Settings.get('database')[this.databaseSettingsSource]; + const databaseSettings = Settings.get('database')[this.clientModel.databaseKey]; const clientDatabase = { dbHost: databaseSettings.host diff --git a/lib/listener-created.js b/lib/listener-created.js index f9ca0d4..e2ec47a 100644 --- a/lib/listener-created.js +++ b/lib/listener-created.js @@ -26,13 +26,9 @@ class ClientCreatedListener extends EventListener { return this._clientModel; } - get databaseSettingsSource() { - return this.clientModel.databaseKey; - } - async process(clientCode = this.eventId) { - const databaseSettings = Settings.get('database')[this.databaseSettingsSource]; + const databaseSettings = Settings.get('database')[this.clientModel.databaseKey]; const clientDatabase = { dbHost: databaseSettings.host, diff --git a/lib/model-client.js b/lib/model-client.js index 5522e5d..930e98f 100644 --- a/lib/model-client.js +++ b/lib/model-client.js @@ -1,15 +1,20 @@ 'use strict'; const Model = require('@janiscommerce/model'); +const Settings = require('@janiscommerce/settings'); class Client extends Model { + static get settings() { + return Settings.get('clients') || {}; + } + get databaseKey() { - return 'newClients'; + return this.constructor.settings.databaseKey || 'core'; } static get table() { - return 'clients'; + return this.settings.table || 'clients'; } static get uniqueIndexes() { diff --git a/tests/api-create.js b/tests/api-create.js index 812ae43..6a154f0 100644 --- a/tests/api-create.js +++ b/tests/api-create.js @@ -13,52 +13,39 @@ const fakeWrongClientPath = path.join(process.cwd(), process.env.MS_PATH || '', describe('APIs', () => { - describe('Client Create API', () => { + describe.only('Client Create API', () => { const fakeSettings = { - newClients: { - host: 'some-database-host' - }, - otherDb: { - host: 'other-database-host' - } - }; - const fakeFullSettings = { - newClients: { - host: 'some-database-host', - protocol: 'some-protocol://', - port: 27017, - user: 'some-user', - password: 'some-password' + database: { + + core: { + host: 'core-database-host', + protocol: 'core-protocol://', + port: 27017, + user: 'core-user', + password: 'core-password' + }, + newClients: { + host: 'some-database-host', + protocol: 'some-protocol://', + port: 27017, + user: 'some-user', + password: 'some-password' + } }, - otherDb: { - host: 'other-database-host', - protocol: 'other-protocol://', - port: 27017, - user: 'other-user', - password: 'other-password' + clients: { + databaseKey: 'newClients' } }; const expectedClientObject = { code: 'some-client', status: ClientModel.statuses.active, - dbHost: fakeSettings.newClients.host, - dbDatabase: 'janis-some-client' - }; - - const expectedOtherClientObject = { - ...expectedClientObject, - dbHost: fakeSettings.otherDb.host - }; - - const expectedFullClientObject = { - ...expectedClientObject, - dbProtocol: fakeFullSettings.newClients.protocol, - dbPort: fakeFullSettings.newClients.port, - dbUser: fakeFullSettings.newClients.user, - dbPassword: fakeFullSettings.newClients.password + dbProtocol: fakeSettings.database.newClients.protocol, + dbPort: fakeSettings.database.newClients.port, + dbUser: fakeSettings.database.newClients.user, + dbPassword: fakeSettings.database.newClients.password }; APITest(ClientCreateAPI, '/api/client', [ @@ -82,7 +69,7 @@ describe('APIs', () => { mockRequire(fakeClientPath, ClientModel); sandbox.stub(Settings, 'get') - .returns(fakeSettings); + .callsFake(setting => fakeSettings[setting]); sandbox.stub(ClientModel.prototype, 'multiSave') .resolves(true); @@ -106,7 +93,7 @@ describe('APIs', () => { sandbox.assert.calledOnceWithExactly(ClientCreateAPI.prototype.postSaveHook, ['some-client', 'other-client'], fakeSettings.newClients); mockRequire.stop(fakeClientPath); } - }, + }/* , { description: 'Should save all the received new clients to clients DB with full database config', session: true, @@ -153,53 +140,6 @@ describe('APIs', () => { mockRequire.stop(fakeClientPath); } }, - { - description: 'Should save all the received new clients to clients DB using a different db config', - session: true, - request: { - data: { - clients: [ - 'some-client', - 'other-client' - ] - } - }, - response: { - code: 200 - }, - before: sandbox => { - - mockRequire(fakeClientPath, ClientModel); - - sandbox.stub(ClientCreateAPI.prototype, 'databaseSettingsSource') - .get(() => 'otherDb'); - - sandbox.stub(Settings, 'get') - .returns(fakeSettings); - - sandbox.stub(ClientModel.prototype, 'multiSave') - .resolves(true); - - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientDatabases') - .resolves(); - - sandbox.spy(ClientCreateAPI.prototype, 'postSaveHook'); - }, - after: (res, sandbox) => { - - sandbox.assert.calledOnceWithExactly(ClientModel.prototype.multiSave, [ - expectedOtherClientObject, - { - ...expectedOtherClientObject, - code: 'other-client', - dbDatabase: 'janis-other-client' - } - ]); - - sandbox.assert.calledOnceWithExactly(ClientCreateAPI.prototype.postSaveHook, ['some-client', 'other-client'], fakeSettings.otherDb); - mockRequire.stop(fakeClientPath); - } - }, { description: 'Should return 500 when the client model multiSave fails', session: true, @@ -323,7 +263,7 @@ describe('APIs', () => { sandbox.assert.notCalled(MongoDBIndexCreator.prototype.executeForClientDatabases); mockRequire.stop(fakeClientPath); } - } + }*/ ]); }); }); From 685d9001b648d8a703e334425cbf44262fd8b57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nataniel=20L=C3=B3pez?= Date: Tue, 19 May 2020 15:26:32 +0000 Subject: [PATCH 3/4] Fixed tests --- package-lock.json | 221 ++++++++++++++++++++++++++++---------- package.json | 5 +- tests/api-create.js | 61 ++++++++--- tests/listener-created.js | 118 +++++++++----------- tests/model-client.js | 45 +++++++- 5 files changed, 301 insertions(+), 149 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1cdcd28..1facb9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,12 +14,12 @@ } }, "@babel/generator": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz", - "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz", + "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==", "dev": true, "requires": { - "@babel/types": "^7.9.5", + "@babel/types": "^7.9.6", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" @@ -72,9 +72,9 @@ } }, "@babel/parser": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", - "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz", + "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==", "dev": true }, "@babel/template": { @@ -89,26 +89,26 @@ } }, "@babel/traverse": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", - "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz", + "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==", "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.5", + "@babel/generator": "^7.9.6", "@babel/helper-function-name": "^7.9.5", "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.0", - "@babel/types": "^7.9.5", + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" } }, "@babel/types": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", - "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz", + "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.9.5", @@ -117,12 +117,12 @@ } }, "@janiscommerce/api": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@janiscommerce/api/-/api-4.2.4.tgz", - "integrity": "sha512-LorA2N0/MpI56vf2l2O0ihLSvDUS6TWOms7y4Vbr8ec+IPo5KGWvFUgiXOepcCxI9sX17M7SOsvi1vWYWEhlbg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@janiscommerce/api/-/api-4.2.5.tgz", + "integrity": "sha512-XDKxXf87vpUdlLnqFOjhL96yPPeFEhqZBJarwJlBvpwN+Cg0ev3E7hqAPWUveHUFmAyncg0dkJOPPDZeF4BdRw==", "requires": { "@janiscommerce/api-session": "^1.3.1", - "@janiscommerce/log": "^3.1.0", + "@janiscommerce/log": "^3.1.2", "lodash.omit": "^4.5.0", "superstruct": "0.6.2" } @@ -145,6 +145,22 @@ "@janiscommerce/api": "^4.2.3", "@janiscommerce/api-session": "^1.3.1", "sinon": "^7.3.2" + }, + "dependencies": { + "sinon": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", + "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.3", + "diff": "^3.5.0", + "lolex": "^4.2.0", + "nise": "^1.5.2", + "supports-color": "^5.5.0" + } + } } }, "@janiscommerce/database-dispatcher": { @@ -175,12 +191,28 @@ "@janiscommerce/event-listener": "^1.0.2", "@janiscommerce/sls-api-response": "^1.2.1", "sinon": "^7.5.0" + }, + "dependencies": { + "sinon": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", + "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.3", + "diff": "^3.5.0", + "lolex": "^4.2.0", + "nise": "^1.5.2", + "supports-color": "^5.5.0" + } + } } }, "@janiscommerce/log": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@janiscommerce/log/-/log-3.1.1.tgz", - "integrity": "sha512-XgaA/f+jkRPUEo7czY68QVS1IKrRwJK0llT42zeRm/9OAGpWoOlN+yo4Hqc8Lwx5nPeHOxQllkt0kT2txoQ00g==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@janiscommerce/log/-/log-3.1.3.tgz", + "integrity": "sha512-tt2OmyVXmPvkqFM8RgWMJynhHnfKERIlzZi6F/8W32Ar6RUNZnlZdfOt0irrwX1sxoE+eiPYAlIWcmviNnqiFA==", "requires": { "@janiscommerce/superstruct": "^1.1.1", "aws-sdk": "^2.498.0", @@ -198,18 +230,18 @@ } }, "@janiscommerce/mongodb": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@janiscommerce/mongodb/-/mongodb-1.12.0.tgz", - "integrity": "sha512-cYUZRDlPUv2/YWVVsbKSzEUFYV/tCamMpj6EoUDofUxMOweSzWjN6z+hf3IBgx6x48C5IHNFTJXdqyacYPLkjQ==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@janiscommerce/mongodb/-/mongodb-1.13.0.tgz", + "integrity": "sha512-4uBgybNVfMJJZG76jhi2YNa9TjDG5LwXZc8AJy93TvZrDWxxtxEWW3OipnYX5RzvJm+SaTFmOf5lHdCCcUyPOA==", "requires": { "mongodb": "^3.4.1", "superstruct": "^0.6.2" } }, "@janiscommerce/mongodb-index-creator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@janiscommerce/mongodb-index-creator/-/mongodb-index-creator-1.1.3.tgz", - "integrity": "sha512-QM/TSzWz4Y9/JRgseOQizmaAhZ6vcPb9SbPX9E9V9wpafpZLYt961cD5znLXkv5AHc4D2/5yC2zhvy3ZxrnEAg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@janiscommerce/mongodb-index-creator/-/mongodb-index-creator-1.2.1.tgz", + "integrity": "sha512-LFpdccIBH4dEs0M3DVyP65G3UrL6QlvxmH7Q0wfOCCFeGFJZKEXAP14vj2DvXL698btb8cy4pzo8E1UwDZ5Wfg==", "requires": { "@janiscommerce/model": "^3.5.0", "@janiscommerce/mongodb": "^1.9.0", @@ -255,6 +287,15 @@ "type-detect": "4.0.8" } }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, "@sinonjs/formatio": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", @@ -372,9 +413,9 @@ "dev": true }, "aws-sdk": { - "version": "2.663.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.663.0.tgz", - "integrity": "sha512-xPOszNOaSXTRs8VGXaMbhTKXdlq2TlDRfFRVEGxkZrtow87hEIVZGAUSUme2e3GHqHUDnySwcufrUpUPUizOKQ==", + "version": "2.679.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.679.0.tgz", + "integrity": "sha512-bsbu3Mbwqz2DHpVSSgaSoFYsNrW+54vXN74iG++cCE7AAg9vOgCKzGul8yhR4jxxlOmGlfP9kCNrkCpjQ/Uqkg==", "requires": { "buffer": "4.9.1", "events": "1.1.1", @@ -1137,9 +1178,9 @@ "dev": true }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "growl": { @@ -1644,6 +1685,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "lodash.omit": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", @@ -1800,9 +1847,9 @@ } }, "mongodb": { - "version": "3.5.6", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.6.tgz", - "integrity": "sha512-sh3q3GLDLT4QmoDLamxtAECwC3RGjq+oNuK1ENV8+tnipIavss6sMYt77hpygqlMOCt0Sla5cl7H4SKCVBCGEg==", + "version": "3.5.7", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.7.tgz", + "integrity": "sha512-lMtleRT+vIgY/JhhTn1nyGwnSMmJkJELp+4ZbrjctrnBxuLbj6rmLuJFz8W2xUzUqWmqoyVxJLYuC58ZKpcTYQ==", "requires": { "bl": "^2.2.0", "bson": "^1.1.4", @@ -3287,9 +3334,9 @@ } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", @@ -3361,17 +3408,75 @@ "dev": true }, "sinon": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", - "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", - "requires": { - "@sinonjs/commons": "^1.4.0", - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/samsam": "^3.3.3", - "diff": "^3.5.0", - "lolex": "^4.2.0", - "nise": "^1.5.2", - "supports-color": "^5.5.0" + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz", + "integrity": "sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.2", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/formatio": "^5.0.1", + "@sinonjs/samsam": "^5.0.3", + "diff": "^4.0.2", + "nise": "^4.0.1", + "supports-color": "^7.1.0" + }, + "dependencies": { + "@sinonjs/formatio": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", + "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^5.0.2" + } + }, + "@sinonjs/samsam": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", + "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "nise": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.3.tgz", + "integrity": "sha512-EGlhjm7/4KvmmE6B/UFsKh7eHykRl9VH+au8dduHLCyWUO/hr7+N+WtTvDUwc9zHuM1IaIJs/0lQ6Ag1jDkQSg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "slash": { @@ -3423,9 +3528,9 @@ "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -3623,9 +3728,9 @@ "dev": true }, "tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", "dev": true }, "type-check": { diff --git a/package.json b/package.json index 47d491d..00cf58b 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,13 @@ "license": "ISC", "homepage": "https://github.com/janis-commerce/client-creator.git#readme", "devDependencies": { - "husky": "^2.4.1", "eslint": "^5.16.0", "eslint-config-airbnb-base": "^13.1.0", "eslint-plugin-import": "^2.17.3", + "husky": "^2.4.1", "mocha": "^5.2.0", - "nyc": "^13.1.0" + "nyc": "^13.1.0", + "sinon": "^9.0.2" }, "files": [ "lib/" diff --git a/tests/api-create.js b/tests/api-create.js index 6a154f0..39b5ec7 100644 --- a/tests/api-create.js +++ b/tests/api-create.js @@ -13,7 +13,7 @@ const fakeWrongClientPath = path.join(process.cwd(), process.env.MS_PATH || '', describe('APIs', () => { - describe.only('Client Create API', () => { + describe('Client Create API', () => { const fakeSettings = { @@ -39,13 +39,37 @@ describe('APIs', () => { } }; + const fakeBasicSettings = { + + ...fakeSettings, + + database: { + + core: { + host: fakeSettings.database.core.host + }, + newClients: { + host: fakeSettings.database.newClients.host + } + } + }; + const expectedClientObject = { code: 'some-client', status: ClientModel.statuses.active, + dbHost: fakeSettings.database.newClients.host, dbProtocol: fakeSettings.database.newClients.protocol, dbPort: fakeSettings.database.newClients.port, dbUser: fakeSettings.database.newClients.user, - dbPassword: fakeSettings.database.newClients.password + dbPassword: fakeSettings.database.newClients.password, + dbDatabase: 'janis-some-client' + }; + + const expectedBasicClientObject = { + code: expectedClientObject.code, + status: expectedClientObject.status, + dbHost: expectedClientObject.dbHost, + dbDatabase: expectedClientObject.dbDatabase }; APITest(ClientCreateAPI, '/api/client', [ @@ -69,7 +93,7 @@ describe('APIs', () => { mockRequire(fakeClientPath, ClientModel); sandbox.stub(Settings, 'get') - .callsFake(setting => fakeSettings[setting]); + .callsFake(setting => fakeBasicSettings[setting]); sandbox.stub(ClientModel.prototype, 'multiSave') .resolves(true); @@ -82,18 +106,23 @@ describe('APIs', () => { after: (res, sandbox) => { sandbox.assert.calledOnceWithExactly(ClientModel.prototype.multiSave, [ - expectedClientObject, + expectedBasicClientObject, { - ...expectedClientObject, + ...expectedBasicClientObject, code: 'other-client', dbDatabase: 'janis-other-client' } ]); - sandbox.assert.calledOnceWithExactly(ClientCreateAPI.prototype.postSaveHook, ['some-client', 'other-client'], fakeSettings.newClients); + sandbox.assert.calledOnceWithExactly( + ClientCreateAPI.prototype.postSaveHook, + ['some-client', 'other-client'], + fakeBasicSettings.database.newClients + ); + mockRequire.stop(fakeClientPath); } - }/* , + }, { description: 'Should save all the received new clients to clients DB with full database config', session: true, @@ -113,7 +142,7 @@ describe('APIs', () => { mockRequire(fakeClientPath, ClientModel); sandbox.stub(Settings, 'get') - .returns(fakeFullSettings); + .callsFake(setting => fakeSettings[setting]); sandbox.stub(ClientModel.prototype, 'multiSave') .resolves(true); @@ -126,17 +155,15 @@ describe('APIs', () => { after: (res, sandbox) => { sandbox.assert.calledOnceWithExactly(ClientModel.prototype.multiSave, [ - expectedFullClientObject, + expectedClientObject, { - ...expectedFullClientObject, + ...expectedClientObject, code: 'other-client', dbDatabase: 'janis-other-client' } ]); - sandbox.assert.calledOnce(MongoDBIndexCreator.prototype.executeForClientDatabases); - - sandbox.assert.calledOnceWithExactly(ClientCreateAPI.prototype.postSaveHook, ['some-client', 'other-client'], fakeFullSettings.newClients); + sandbox.assert.calledOnceWithExactly(ClientCreateAPI.prototype.postSaveHook, ['some-client', 'other-client'], fakeSettings.database.newClients); mockRequire.stop(fakeClientPath); } }, @@ -156,7 +183,7 @@ describe('APIs', () => { mockRequire(fakeClientPath, ClientModel); sandbox.stub(Settings, 'get') - .returns(fakeSettings); + .callsFake(setting => fakeSettings[setting]); sandbox.stub(ClientModel.prototype, 'multiSave') .rejects(); @@ -189,7 +216,7 @@ describe('APIs', () => { mockRequire(fakeClientPath, ClientModel); sandbox.stub(Settings, 'get') - .returns(fakeSettings); + .callsFake(setting => fakeSettings[setting]); sandbox.stub(ClientModel.prototype, 'multiSave') .resolves(); @@ -248,7 +275,7 @@ describe('APIs', () => { mockRequire(fakeWrongClientPath, ClientModel); sandbox.stub(Settings, 'get') - .returns(fakeSettings); + .callsFake(setting => fakeSettings[setting]); sandbox.stub(ClientModel.prototype, 'multiSave') .resolves(true); @@ -263,7 +290,7 @@ describe('APIs', () => { sandbox.assert.notCalled(MongoDBIndexCreator.prototype.executeForClientDatabases); mockRequire.stop(fakeClientPath); } - }*/ + } ]); }); }); diff --git a/tests/listener-created.js b/tests/listener-created.js index 5e70bcf..cab9283 100644 --- a/tests/listener-created.js +++ b/tests/listener-created.js @@ -23,49 +23,60 @@ describe('Client Created Listener', async () => { }; const fakeSettings = { - newClients: { - host: 'some-database-host' + + database: { + + core: { + host: 'core-database-host', + protocol: 'core-protocol://', + port: 27017, + user: 'core-user', + password: 'core-password' + }, + newClients: { + host: 'some-database-host', + protocol: 'some-protocol://', + port: 27017, + user: 'some-user', + password: 'some-password' + } }, - otherDb: { - host: 'other-database-host' + clients: { + databaseKey: 'newClients' } }; - const fakeFullSettings = { - newClients: { - host: 'some-database-host', - protocol: 'some-protocol://', - port: 27017, - user: 'some-user', - password: 'some-password' - }, - otherDb: { - host: 'other-database-host', - protocol: 'other-protocol://', - port: 27017, - user: 'other-user', - password: 'other-password' + const fakeBasicSettings = { + + ...fakeSettings, + + database: { + + core: { + host: fakeSettings.database.core.host + }, + newClients: { + host: fakeSettings.database.newClients.host + } } }; const expectedClientObject = { code: 'some-client', status: ClientModel.statuses.active, - dbHost: fakeSettings.newClients.host, + dbHost: fakeSettings.database.newClients.host, + dbProtocol: fakeSettings.database.newClients.protocol, + dbPort: fakeSettings.database.newClients.port, + dbUser: fakeSettings.database.newClients.user, + dbPassword: fakeSettings.database.newClients.password, dbDatabase: 'janis-some-client' }; - const expectedOtherClientObject = { - ...expectedClientObject, - dbHost: fakeSettings.otherDb.host - }; - - const expectedFullClientObject = { - ...expectedClientObject, - dbProtocol: fakeFullSettings.newClients.protocol, - dbPort: fakeFullSettings.newClients.port, - dbUser: fakeFullSettings.newClients.user, - dbPassword: fakeFullSettings.newClients.password + const expectedBasicClientObject = { + code: expectedClientObject.code, + status: expectedClientObject.status, + dbHost: expectedClientObject.dbHost, + dbDatabase: expectedClientObject.dbDatabase }; await EventListenerTest(handler, [ @@ -90,7 +101,7 @@ describe('Client Created Listener', async () => { .rejects(); sandbox.stub(Settings, 'get') - .returns(fakeSettings); + .callsFake(setting => fakeSettings[setting]); sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') .resolves(); @@ -115,7 +126,7 @@ describe('Client Created Listener', async () => { .resolves(); sandbox.stub(Settings, 'get') - .returns(fakeSettings); + .callsFake(setting => fakeSettings[setting]); sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') .rejects(); @@ -140,7 +151,7 @@ describe('Client Created Listener', async () => { .resolves('5dea9fc691240d00084083f9'); sandbox.stub(Settings, 'get') - .returns(fakeSettings); + .callsFake(setting => fakeBasicSettings[setting]); sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') .resolves(); @@ -149,9 +160,9 @@ describe('Client Created Listener', async () => { }, after: sandbox => { - sandbox.assert.calledOnceWithExactly(ClientModel.prototype.save, expectedClientObject); + sandbox.assert.calledOnceWithExactly(ClientModel.prototype.save, expectedBasicClientObject); sandbox.assert.calledOnceWithExactly(MongoDBIndexCreator.prototype.executeForClientCode, 'some-client'); - sandbox.assert.calledOnceWithExactly(ClientCreatedListener.prototype.postSaveHook, 'some-client', fakeSettings.newClients); + sandbox.assert.calledOnceWithExactly(ClientCreatedListener.prototype.postSaveHook, 'some-client', fakeBasicSettings.database.newClients); mockRequire.stop(fakeClientPath); }, responseCode: 200 @@ -168,7 +179,7 @@ describe('Client Created Listener', async () => { .resolves('5dea9fc691240d00084083f9'); sandbox.stub(Settings, 'get') - .returns(fakeFullSettings); + .callsFake(setting => fakeSettings[setting]); sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') .resolves(); @@ -177,40 +188,9 @@ describe('Client Created Listener', async () => { }, after: sandbox => { - sandbox.assert.calledOnceWithExactly(ClientModel.prototype.save, expectedFullClientObject); - sandbox.assert.calledOnceWithExactly(MongoDBIndexCreator.prototype.executeForClientCode, 'some-client'); - sandbox.assert.calledOnceWithExactly(ClientCreatedListener.prototype.postSaveHook, 'some-client', fakeFullSettings.newClients); - mockRequire.stop(fakeClientPath); - }, - responseCode: 200 - }, - { - description: 'Should return 200 when client model saves the new client sucessfully using a different db config', - event: validEvent, - session: true, - before: sandbox => { - - mockRequire(fakeClientPath, ClientModel); - - sandbox.stub(ClientCreatedListener.prototype, 'databaseSettingsSource') - .get(() => 'otherDb'); - - sandbox.stub(ClientModel.prototype, 'save') - .resolves('5dea9fc691240d00084083f9'); - - sandbox.stub(Settings, 'get') - .returns(fakeSettings); - - sandbox.stub(MongoDBIndexCreator.prototype, 'executeForClientCode') - .resolves(); - - sandbox.spy(ClientCreatedListener.prototype, 'postSaveHook'); - }, - after: sandbox => { - - sandbox.assert.calledOnceWithExactly(ClientModel.prototype.save, expectedOtherClientObject); + sandbox.assert.calledOnceWithExactly(ClientModel.prototype.save, expectedClientObject); sandbox.assert.calledOnceWithExactly(MongoDBIndexCreator.prototype.executeForClientCode, 'some-client'); - sandbox.assert.calledOnceWithExactly(ClientCreatedListener.prototype.postSaveHook, 'some-client', fakeSettings.otherDb); + sandbox.assert.calledOnceWithExactly(ClientCreatedListener.prototype.postSaveHook, 'some-client', fakeSettings.database.newClients); mockRequire.stop(fakeClientPath); }, responseCode: 200 diff --git a/tests/model-client.js b/tests/model-client.js index 2f0c4d8..c5c5ddc 100644 --- a/tests/model-client.js +++ b/tests/model-client.js @@ -1,21 +1,60 @@ 'use strict'; const assert = require('assert'); +const sandbox = require('sinon').createSandbox(); + +const Settings = require('@janiscommerce/settings'); const ClientModel = require('../lib/model-client'); describe('ClientModel', () => { + afterEach(() => { + sandbox.restore(); + }); + describe('Getters', () => { - it('should return the databaseKey', () => { - assert.deepStrictEqual(ClientModel.prototype.databaseKey, 'newClients'); + it('should return the core as databaseKey when is not set in settings', () => { + + sandbox.stub(Settings, 'get') + .returns({}); + + const clientModel = new ClientModel(); + + assert.deepStrictEqual(clientModel.databaseKey, 'core'); }); - it('should return the table name', () => { + it('should return the databaseKey setted in settings', () => { + + sandbox.stub(Settings, 'get') + .returns({ + databaseKey: 'some-databaseKey' + }); + + const clientModel = new ClientModel(); + + assert.deepStrictEqual(clientModel.databaseKey, 'some-databaseKey'); + }); + + it('should return clients as table name when is not set in settings', () => { + + sandbox.stub(Settings, 'get') + .returns({}); + assert.deepStrictEqual(ClientModel.table, 'clients'); }); + it('should return the table name setted in settings', () => { + + sandbox.stub(Settings, 'get') + .returns({ + table: 'some-table' + }); + + assert.deepStrictEqual(ClientModel.table, 'some-table'); + }); + it('Should return the uniqueIndexes', async () => { assert.deepStrictEqual(ClientModel.uniqueIndexes, [ 'id', From b867c197d418a57c821e47a86895788ec35aaa76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nataniel=20L=C3=B3pez?= Date: Tue, 19 May 2020 17:39:12 +0000 Subject: [PATCH 4/4] updated docs --- CHANGELOG.md | 4 ++- README.md | 84 +++++++++++++++++----------------------------------- 2 files changed, 30 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e084998..57a9c12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added - `databaseSettings` parameter for `postSaveHook()` method -- `databaseSettingsSource` getter to specify other settings source for client DB config + +### Changed +- `Client` Model now set the new clients databaseKey from config ### Fixed - `Client Create API` `postSaveHook()` client codes parameter diff --git a/README.md b/README.md index 4a1d1bc..4d1edcc 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ ## Introduction -This package includes all the generic functionality of the creation of a client at the services. It main purpose is to avoid code repetition. +This package includes all the generic functionality of the creation of a client at the services. It main purpose is to avoid code repetition. + ## Installation ```sh npm install @janiscommerce/client-creator @@ -14,6 +15,31 @@ npm install @janiscommerce/client-creator After installing this package you should create or update the following files: +### Service settings (.janiscommercerc) +You should configure the database config in your service, in order to get the correct DB config for new clients: + +#### .janiscommercerc.json +```js +{ + "database": { + "core": { // DB config where save new clients + "type": "mongodb", + "host": "core-host" + // ... + }, + "newClients": { // DB config that the clients will use + "type": "mongodb", + "host": "clients-host" + // ... + } + }, + "clients": { + "databaseKey": "newClients", // The new clients config databaseKey, + "table": "clients" // The clients table where create the clients ("clients" by default) + } +} +``` + ### ClientModel At `./[MS_PATH]/models/client.js` @@ -72,7 +98,6 @@ const { helper } = require('sls-helper'); // eslint-disable-line const functions = require('./serverless/functions.json'); const { clientFunctions } = require('@janiscommerce/client-creator'); - module.exports = helper({ hooks: [ // other hooks @@ -111,61 +136,6 @@ Finally, create or update `./.nycrc` to avoid coverage leaks: :warning: If exists any customization of the files, do not add the file to the .nyrcr and add the corresponding tests. -### Getters -Both `APICreate` and `ListenerCreated` have a getter for customize the client creation settings. - -#### `databaseSettingsSource` (*`instance getter`*): Is the database config source key that will be getted from your MS database config. Default: `clientModel.databaseKey`. - -##### Example - -##### .janiscommercerc -```js -{ - "database":{ - "newClients": { - type: 'mongodb', - host: 'core-host' - // ... - }, - otherDb: { - host: 'http://clients-host:8983', - type: 'solr' - } - } -} -``` - -##### `./[MS_PATH]/api/client/post.js` -```js -'use strict'; -const { APICreate } = require('@janiscommerce/client-creator') - -class ClientCreateAPI extends APICreate { - - get databaseSettingsSource() { - return 'otherDb'; - } -} - -module.exports = ClientCreateAPI; -``` - -##### `./[MS_PATH]/event-listeners/id/client/created.js` -```js -'use strict'; -const { ServerlessHandler } = require('@janiscommerce/event-listener'); -const { ListenerCreated } = require('@janiscommerce/client-creator'); - -class ClientCreateListener extends ListenerCreated { - - get databaseSettingsSource() { - return 'otherDb'; - } -} - -module.exports.handler = (...args) => ServerlessHandler.handle(ClientCreateListener, ...args); -``` - ### Hooks Both `APICreate` and `ListenerCreated` have a hook for post processing the client or clients created data.