diff --git a/package.json b/package.json index 1bb682e..494ce96 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "switcher-client", - "version": "3.1.1", + "version": "3.1.2", "description": "Client JS SDK for working with Switcher-API", "main": "./src/index.js", "types": "./src/index.d.ts", diff --git a/sonar-project.properties b/sonar-project.properties index c2cea32..aea43fe 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,7 +1,7 @@ sonar.projectKey=switcherapi_switcher-client-master sonar.projectName=switcher-client-master sonar.organization=switcherapi -sonar.projectVersion=3.1.1 +sonar.projectVersion=3.1.2 sonar.links.homepage=https://github.com/switcherapi/switcher-client-master sonar.javascript.lcov.reportPaths=coverage/lcov.info diff --git a/src/index.js b/src/index.js index 13fb2c8..2ac5074 100644 --- a/src/index.js +++ b/src/index.js @@ -278,7 +278,7 @@ class Switcher { Switcher.context, this._key, this._input, showReason); if (Switcher.options.logger) - ExecutionLogger.add(this._key, this._input, responseCriteria); + ExecutionLogger.add(responseCriteria, this._key, this._input); return responseCriteria.result; } @@ -287,7 +287,7 @@ class Switcher { if (this._nextRun < Date.now()) { this._nextRun = Date.now() + this._delay; services.checkCriteria(Switcher.context, this._key, this._input, showReason) - .then(response => ExecutionLogger.add(this._key, this._input, response)); + .then(response => ExecutionLogger.add(response, this._key, this._input)); } return ExecutionLogger.getExecution(this._key, this._input).response.result; @@ -307,7 +307,7 @@ class Switcher { this._key, this._input, Switcher.snapshot); if (Switcher.options.logger) - ExecutionLogger.add(this._key, response); + ExecutionLogger.add(response, this._key, this._input); return response.result; } diff --git a/src/lib/utils/executionLogger.js b/src/lib/utils/executionLogger.js index 24e42a0..bee15c3 100644 --- a/src/lib/utils/executionLogger.js +++ b/src/lib/utils/executionLogger.js @@ -11,7 +11,7 @@ class ExecutionLogger { * @param input * @param response */ - static add(key, input, response) { + static add(response, key, input) { for (let index = 0; index < logger.length; index++) { const log = logger[index]; if (log.key === key && JSON.stringify(log.input) === JSON.stringify(input)) { diff --git a/test/fixture/utils.js b/test/fixture/utils.js deleted file mode 100644 index c44ac92..0000000 --- a/test/fixture/utils.js +++ /dev/null @@ -1,17 +0,0 @@ -function given(fetchStub, order, expect) { - fetchStub.onCall(order).returns(Promise.resolve(expect)); -} - -function givenError(fetchStub, order, expect) { - fetchStub.onCall(order).throws(expect); -} - -function throws(fetchStub, expect) { - fetchStub.throws(expect); -} - -module.exports = { - given, - givenError, - throws -}; \ No newline at end of file diff --git a/test/helper/utils.js b/test/helper/utils.js new file mode 100644 index 0000000..f850229 --- /dev/null +++ b/test/helper/utils.js @@ -0,0 +1,39 @@ +function given(fetchStub, order, expect) { + fetchStub.onCall(order).returns(Promise.resolve(expect)); +} + +function givenError(fetchStub, order, expect) { + fetchStub.onCall(order).throws(expect); +} + +function throws(fetchStub, expect) { + fetchStub.throws(expect); +} + +const generateAuth = (token, seconds) => { + return { + token, + exp: (Date.now() + (seconds * 1000)) / 1000 + }; +}; + +const generateStatus = (status) => { + return { + status + }; +}; + +const generateResult = (result) => { + return { + result + }; +}; + +module.exports = { + given, + givenError, + throws, + generateAuth, + generateStatus, + generateResult +}; \ No newline at end of file diff --git a/test/playground/index.js b/test/playground/index.js index a858959..8042eda 100644 --- a/test/playground/index.js +++ b/test/playground/index.js @@ -124,4 +124,4 @@ const testWatchSnapshot = async () => { (err) => console.log(err)); }; -testWatchSnapshot(); \ No newline at end of file +testSimpleAPICall(true); \ No newline at end of file diff --git a/test/switcher-client.test.js b/test/switcher-client.test.js index 97aa8a7..fb06603 100644 --- a/test/switcher-client.test.js +++ b/test/switcher-client.test.js @@ -8,14 +8,17 @@ const { StrategiesType } = require('../src/lib/snapshot'); describe('E2E test - Switcher offline:', function () { let switcher; - const apiKey = '[api_key]'; - const domain = 'Business'; - const component = 'business-service'; - const environment = 'default'; - const url = 'http://localhost:3000'; + + const contextSettings = { + apiKey: '[api_key]', + domain: 'Business', + component: 'business-service', + environment: 'default', + url: 'http://localhost:3000' + }; this.beforeAll(async function() { - Switcher.buildContext({ url, apiKey, domain, component, environment }, { + Switcher.buildContext(contextSettings, { offline: true, logger: true }); @@ -96,7 +99,7 @@ describe('E2E test - Switcher offline:', function () { const result = await switcher.isItOn(); assert.isFalse(result); - assert.equal(Switcher.getLogger('FF2FOR2023')[0].input.reason, + assert.equal(Switcher.getLogger('FF2FOR2023')[0].response.reason, `Strategy '${StrategiesType.PAYLOAD}' does not agree`); }); @@ -108,28 +111,28 @@ describe('E2E test - Switcher offline:', function () { const result = await switcher.isItOn(); assert.isFalse(result); - assert.equal(Switcher.getLogger('FF2FOR2020')[0].input.reason, + assert.equal(Switcher.getLogger('FF2FOR2020')[0].response.reason, `Strategy '${StrategiesType.NETWORK}' does not agree`); }); it('should be invalid - Input not provided', async function () { const result = await switcher.isItOn('FF2FOR2020'); assert.isFalse(result); - assert.equal(Switcher.getLogger('FF2FOR2020')[0].input.reason, + assert.equal(Switcher.getLogger('FF2FOR2020')[0].response.reason, `Strategy '${StrategiesType.NETWORK}' did not receive any input`); }); it('should be invalid - Switcher config disabled', async function () { const result = await switcher.isItOn('FF2FOR2031'); assert.isFalse(result); - assert.equal(Switcher.getLogger('FF2FOR2031')[0].input.reason, + assert.equal(Switcher.getLogger('FF2FOR2031')[0].response.reason, 'Config disabled'); }); it('should be invalid - Switcher group disabled', async function () { const result = await switcher.isItOn('FF2FOR2040'); assert.isFalse(result); - assert.equal(Switcher.getLogger('FF2FOR2040')[0].input.reason, + assert.equal(Switcher.getLogger('FF2FOR2040')[0].response.reason, 'Group disabled'); }); @@ -163,7 +166,7 @@ describe('E2E test - Switcher offline:', function () { it('should enable test mode which will prevent a snapshot to be watchable', async function () { //given - Switcher.buildContext({ url, apiKey, domain, component, environment }, { + Switcher.buildContext(contextSettings, { offline: true, logger: true }); @@ -179,7 +182,7 @@ describe('E2E test - Switcher offline:', function () { it('should be invalid - Offline mode cannot load snapshot from an invalid path', async function () { this.timeout(3000); - Switcher.buildContext({ url, apiKey, domain, component, environment }, { + Switcher.buildContext(contextSettings, { offline: true, snapshotLocation: '//somewhere/' }); @@ -192,7 +195,7 @@ describe('E2E test - Switcher offline:', function () { it('should be valid - Offline mode', async function () { this.timeout(3000); - Switcher.buildContext({ url, apiKey, domain, component, environment }, { + Switcher.buildContext(contextSettings, { offline: true, snapshotLocation: 'generated-snapshots/' }); diff --git a/test/switcher-integrated.test.js b/test/switcher-integrated.test.js index cc4a702..727b550 100644 --- a/test/switcher-integrated.test.js +++ b/test/switcher-integrated.test.js @@ -20,30 +20,29 @@ const { const { given, givenError, - throws -} = require('./fixture/utils'); - -const generateAuth = (token, seconds) => { - return { - token, - exp: (Date.now()+(seconds*1000))/1000 - }; -}; - -const generateResult = (result) => { - return { - result - }; -}; + throws, + generateAuth, + generateResult +} = require('./helper/utils'); describe('Integrated test - Switcher:', function () { + let contextSettings; + this.afterAll(function() { fs.unwatchFile('./snapshot/default.json'); }); this.beforeEach(function() { Switcher.setTestEnabled(); + + contextSettings = { + apiKey: '[api_key]', + domain: 'Business', + component: 'business-service', + environment: 'default', + url: 'http://localhost:3000' + }; }); describe('check criteria (e2e):', function () { @@ -65,7 +64,7 @@ describe('Integrated test - Switcher:', function () { given(fetchStub, 2, { json: () => generateResult(true) }); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); await switcher.prepare('FLAG_1'); @@ -90,7 +89,7 @@ describe('Integrated test - Switcher:', function () { given(fetchStub, 6, { json: () => generateResult(true), status: 200 }); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); switcher.throttle(1000); @@ -130,7 +129,7 @@ describe('Integrated test - Switcher:', function () { clientAuth.returns(generateAuth('[auth_token]', 5)); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); await switcher.prepare('FLAG_1', [ @@ -143,6 +142,15 @@ describe('Integrated test - Switcher:', function () { checkPayload(JSON.stringify({ name: 'User 1' })) ]); + assert.sameDeepMembers(switcher._input, [ + [ 'VALUE_VALIDATION', 'User 1' ], + [ 'NUMERIC_VALIDATION', '1' ], + [ 'NETWORK_VALIDATION', '192.168.0.1' ], + [ 'DATE_VALIDATION', '2019-12-01T08:30' ], + [ 'TIME_VALIDATION', '08:00' ], + [ 'REGEX_VALIDATION', '\\bUSER_[0-9]{1,2}\\b' ], + [ 'PAYLOAD_VALIDATION', '{"name":"User 1"}' ] + ]); assert.isTrue(await switcher.isItOn()); }); @@ -153,7 +161,7 @@ describe('Integrated test - Switcher:', function () { given(fetchStub, 0, { json: () => response, status: 200 }); //test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); await assert.isFulfilled(Switcher.checkSwitchers(['FEATURE01', 'FEATURE02'])); }); @@ -164,7 +172,7 @@ describe('Integrated test - Switcher:', function () { given(fetchStub, 0, { json: () => response, status: 200 }); //test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); await assert.isRejected(Switcher.checkSwitchers(['FEATURE01', 'FEATURE02']), 'Something went wrong: Something went wrong: [FEATURE02] not found'); }); @@ -176,7 +184,7 @@ describe('Integrated test - Switcher:', function () { given(fetchStub, 0, { json: () => response, status: 422 }); //test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); await assert.isRejected(Switcher.checkSwitchers([]), 'Something went wrong: Switcher Key is required'); }); @@ -187,7 +195,7 @@ describe('Integrated test - Switcher:', function () { given(fetchStub, 0, { errno: 'ERROR' }); //test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); await assert.isRejected(Switcher.checkSwitchers('FEATURE02')); }); @@ -197,7 +205,7 @@ describe('Integrated test - Switcher:', function () { // given API responding properly clientAuth.returns(generateAuth('[auth_token]', 1)); - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); const spyPrepare = sinon.spy(switcher, 'prepare'); @@ -231,7 +239,7 @@ describe('Integrated test - Switcher:', function () { clientAuth.returns(generateAuth('[auth_token]', 5)); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); assert.isTrue(await switcher.isItOn('MY_FLAG', [ checkValue('User 1'), @@ -246,7 +254,7 @@ describe('Integrated test - Switcher:', function () { clientAuth.returns(generateAuth('[auth_token]', 5)); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); await switcher.prepare('MY_FLAG'); @@ -279,7 +287,7 @@ describe('Integrated test - Switcher:', function () { clientAuth.returns(generateAuth('[auth_token]', 5)); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); await switcher.prepare(undefined, [ checkValue('User 1'), @@ -311,7 +319,7 @@ describe('Integrated test - Switcher:', function () { clientAuth.returns(generateAuth(undefined, 1)); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); await assert.isRejected(switcher.isItOn('MY_FLAG', [ @@ -326,7 +334,7 @@ describe('Integrated test - Switcher:', function () { clientAuth.returns(generateAuth('[auth_token]', 5)); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); await switcher.prepare('MY_WRONG_FLAG', ['THIS IS WRONG']); @@ -338,7 +346,7 @@ describe('Integrated test - Switcher:', function () { this.timeout(6000); // setup context to read the snapshot in case the API does not respond - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }, { + Switcher.buildContext(contextSettings, { silentMode: true, retryAfter: '2s' }); @@ -388,7 +396,7 @@ describe('Integrated test - Switcher:', function () { throws(fetchStub, { errno: 'ECONNREFUSED' }); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }); + Switcher.buildContext(contextSettings); let switcher = Switcher.factory(); await assert.isRejected(switcher.isItOn('FF2FOR2030'), @@ -400,7 +408,7 @@ describe('Integrated test - Switcher:', function () { given(fetchStub, 0, { status: 503 }); // test - Switcher.buildContext({ url: 'url', apiKey: 'apiKey', domain: 'domain', component: 'component', environment: 'default' }, { + Switcher.buildContext(contextSettings, { silentMode: true }); diff --git a/test/switcher-snapshot.test.js b/test/switcher-snapshot.test.js index f93d237..4c180d1 100644 --- a/test/switcher-snapshot.test.js +++ b/test/switcher-snapshot.test.js @@ -8,20 +8,7 @@ const { Switcher } = require('../src/index'); const fetch = require('node-fetch'); const services = require('../src/lib/remote'); const fs = require('fs'); -const { given, givenError } = require('./fixture/utils'); - -const generateAuth = (token, seconds) => { - return { - token, - exp: (Date.now()+(seconds*1000))/1000 - }; -}; - -const generateStatus = (status) => { - return { - status - }; -}; +const { given, givenError, generateAuth, generateStatus } = require('./helper/utils'); describe('E2E test - Switcher offline - Snapshot:', function () { const apiKey = '[api_key]';