From e6ac24e4c564d3d821fdaa264333361cf567ece7 Mon Sep 17 00:00:00 2001 From: Pranav Joglekar Date: Wed, 4 Sep 2024 09:57:02 +0530 Subject: [PATCH] Fix failing tests & add tests for vault.js --- test/unit/pm-variables-tracking.test.js | 36 +---- test/unit/pm-variables.test.js | 24 +--- test/unit/sandbox-libraries/pm.test.js | 127 ++++++++---------- test/unit/vault.test.js | 166 ++++++++++++++++++++++++ 4 files changed, 227 insertions(+), 126 deletions(-) create mode 100644 test/unit/vault.test.js diff --git a/test/unit/pm-variables-tracking.test.js b/test/unit/pm-variables-tracking.test.js index 392cf818..b7ea6df4 100644 --- a/test/unit/pm-variables-tracking.test.js +++ b/test/unit/pm-variables-tracking.test.js @@ -26,14 +26,8 @@ describe('pm api variables', function () { assert.equal(pm.collectionVariables.mutations.count(), 0); pm.collectionVariables.set('foo', 'foo'); assert.equal(pm.collectionVariables.mutations.count(), 1); - - assert.equal(pm.vault.mutations.count(), 0); - pm.vault.set('foo', 'foo'); - assert.equal(pm.vault.mutations.count(), 1); `, { - context: { - vaultSecrets: {} // enable pm.vault - } + context: {} }, done); }); }); @@ -49,11 +43,8 @@ describe('pm api variables', function () { pm.environment.set('foo', 'environment'); pm.globals.set('foo', 'global'); pm.collectionVariables.set('foo', 'collectionVariables'); - pm.vault.set('foo', 'vaultVariable'); `, { - context: { - vaultSecrets: {} // enable pm.vault - } + context: {} }, function (err, result) { if (err) { return done(err); @@ -71,9 +62,6 @@ describe('pm api variables', function () { expect(result.collectionVariables.mutations).to.be.ok; expect(new sdk.MutationTracker(result.collectionVariables.mutations).count()).to.equal(1); - expect(result.vaultSecrets.mutations).to.be.ok; - expect(new sdk.MutationTracker(result.vaultSecrets.mutations).count()).to.equal(1); - done(); }); }); @@ -109,27 +97,12 @@ describe('pm api variables', function () { assert.equal(pm.collectionVariables.get('bar'), 'bar value'); pm.collectionVariables.set('foo', 'collectionVariables'); - - assert.equal(pm.vault.get('bar'), 'bar value'); - pm.vault.set('foo', 'vault'); `, { context: { globals: scopeDefinition, _variables: scopeDefinition, environment: scopeDefinition, - collectionVariables: scopeDefinition, - vaultSecrets: { - prefix: 'vault:', - values: [ - { key: 'vault:bar', value: 'bar value' } - ], - mutations: { - autoCompact: true, - compacted: { - 'vault:bar': ['vault:bar', 'bar value'] - } - } - } + collectionVariables: scopeDefinition } }, function (err, result) { if (err) { @@ -148,9 +121,6 @@ describe('pm api variables', function () { expect(result.collectionVariables.mutations).to.be.ok; expect(new sdk.MutationTracker(result.collectionVariables.mutations).count()).to.equal(1); - expect(result.vaultSecrets.mutations).to.be.ok; - expect(new sdk.MutationTracker(result.vaultSecrets.mutations).count()).to.equal(1); - done(); }); }); diff --git a/test/unit/pm-variables.test.js b/test/unit/pm-variables.test.js index 25da12f8..55e1167f 100644 --- a/test/unit/pm-variables.test.js +++ b/test/unit/pm-variables.test.js @@ -30,15 +30,13 @@ describe('pm.variables', function () { describe('.set', function () { before(function (done) { - var vaultSecretList = new sdk.VariableList(null, { key: 'vault:key-0', value: 'value-0' }), - globalVarList = new sdk.VariableList(null, { key: 'key-1', value: 'value-1' }), + var globalVarList = new sdk.VariableList(null, { key: 'key-1', value: 'value-1' }), collectionVarList = new sdk.VariableList(null, { key: 'key-2', value: 'value-2' }), envVarList = new sdk.VariableList(null, { key: 'key-3', value: 'value-3' }), contextData = { 'key-4': 'value-4' }, localVarList = new sdk.VariableList(null, { key: 'key-5', value: 'value-5' }); ctx.execute(` - pm.variables.set("vault:key-0", "modified"); pm.variables.set("key-1", "modified"); pm.variables.set("key-2", "modified"); pm.variables.set("key-3", "modified"); @@ -48,7 +46,6 @@ describe('pm.variables', function () { `, { timeout: 200, context: { - vaultSecrets: new sdk.VariableScope(vaultSecretList), globals: new sdk.VariableScope(globalVarList), collectionVariables: new sdk.VariableScope(collectionVarList), environment: new sdk.VariableScope(envVarList), @@ -67,7 +64,6 @@ describe('pm.variables', function () { it('should return the modified variables in the result', function () { expect(executionResults).to.deep.nested.include({ '_variables.values': [ { type: 'any', value: 'modified', key: 'key-5' }, - { type: 'any', value: 'modified', key: 'vault:key-0' }, { type: 'any', value: 'modified', key: 'key-1' }, { type: 'any', value: 'modified', key: 'key-2' }, { type: 'any', value: 'modified', key: 'key-3' }, @@ -78,9 +74,6 @@ describe('pm.variables', function () { it('should not modify the globals, environment, collection and data variables', function () { expect(executionResults).to.deep.nested.include({ - 'vaultSecrets.values': [ - { type: 'any', value: 'value-0', key: 'vault:key-0' } - ], 'globals.values': [ { type: 'any', value: 'value-1', key: 'key-1' } ], @@ -135,11 +128,7 @@ describe('pm.variables', function () { describe('.get', function () { it('should honour the precendence', function (done) { - var vaultSecretList = new sdk.VariableList(null, [ - { key: 'vault:key-0', value: 'value-0' }, - { key: 'vault:key-1', value: 'value-0' } - ]), - globalVarList = new sdk.VariableList(null, [ + var globalVarList = new sdk.VariableList(null, [ { key: 'vault:key-1', value: 'value-1' }, { key: 'key-1', value: 'value-1' }, { key: 'key-2', value: 'value-1' }, @@ -178,13 +167,11 @@ describe('pm.variables', function () { 'key-3': 'value-3', 'key-4': 'value-4', 'key-5': 'value-5', - 'vault:key-0': 'value-0', 'vault:key-1': 'value-1' }); `, { timeout: 200, context: { - vaultSecrets: new sdk.VariableScope(vaultSecretList), globals: new sdk.VariableScope(globalVarList), collectionVariables: new sdk.VariableScope(collectionVarList), environment: new sdk.VariableScope(envVarList), @@ -201,8 +188,7 @@ describe('pm.variables', function () { }); it('should return appropriate variables', function (done) { - var vaultSecretList = new sdk.VariableList(null, { key: 'vault:key-0', value: 'value-0' }), - globalVarList = new sdk.VariableList(null, { key: 'key-1', value: 'value-1' }), + var globalVarList = new sdk.VariableList(null, { key: 'key-1', value: 'value-1' }), collectionVarList = new sdk.VariableList(null, { key: 'key-2', value: 'value-2' }), envVarList = new sdk.VariableList(null, { key: 'key-3', value: 'value-3' }), contextData = { 'key-4': 'value-4' }, @@ -210,7 +196,6 @@ describe('pm.variables', function () { ctx.execute(` var assert = require('assert'); - assert.strictEqual(pm.variables.get('vault:key-0'), 'value-0'); assert.strictEqual(pm.variables.get('key-1'), 'value-1'); assert.strictEqual(pm.variables.get('key-2'), 'value-2'); assert.strictEqual(pm.variables.get('key-3'), 'value-3'); @@ -220,7 +205,6 @@ describe('pm.variables', function () { `, { timeout: 200, context: { - vaultSecrets: new sdk.VariableScope(vaultSecretList), globals: new sdk.VariableScope(globalVarList), collectionVariables: new sdk.VariableScope(collectionVarList), environment: new sdk.VariableScope(envVarList), @@ -239,7 +223,6 @@ describe('pm.variables', function () { it('should reinitialize the variables when same sandbox instance is used again', function (done) { ctx.execute(` var assert = require('assert'); - assert.strictEqual(pm.variables.get('vault:key-0'), undefined); assert.strictEqual(pm.variables.get('key-1'), undefined); assert.strictEqual(pm.variables.get('key-2'), undefined); assert.strictEqual(pm.variables.get('key-3'), undefined); @@ -253,7 +236,6 @@ describe('pm.variables', function () { if (err) { return done(err); } expect(execution).to.deep.nested.include({ - 'vaultSecrets.values': [], 'globals.values': [], '_variables.values': [], 'collectionVariables.values': [], diff --git a/test/unit/sandbox-libraries/pm.test.js b/test/unit/sandbox-libraries/pm.test.js index d1c7f0b8..c9687458 100644 --- a/test/unit/sandbox-libraries/pm.test.js +++ b/test/unit/sandbox-libraries/pm.test.js @@ -3,7 +3,6 @@ const CookieStore = require('@postman/tough-cookie').Store; describe('sandbox library - pm api', function () { this.timeout(1000 * 60); var Sandbox = require('../../../'), - sampleContextData = { globals: [{ key: 'var1', @@ -30,17 +29,6 @@ describe('sandbox library - pm api', function () { value: 2.9, type: 'number' }], - vaultSecrets: { - prefix: 'vault:', - values: [{ - key: 'vault:var1', - value: 'one-vault', - type: 'string' - }, { - key: 'vault:var2', - value: 'two-vault', - type: 'string' - }] }, data: { var1: 'one-data' } @@ -277,78 +265,73 @@ describe('sandbox library - pm api', function () { }); describe('vault', function () { - it('should not be a function if vaultSecrets is not present', function (done) { + it('should only have get, set and unset properties', function (done) { context.execute(` var assert = require('assert'); - assert.strictEqual((typeof pm.vault), 'undefined'); - `, done); - }); - - it('should be defined as VariableScope', function (done) { - context.execute(` - var assert = require('assert'), - VariableScope = require('postman-collection').VariableScope; - assert.strictEqual(VariableScope.isVariableScope(pm.vault), true); - `, { context: sampleContextData }, done); - }); - - it('should be a readonly property', function (done) { - context.execute(` - var assert = require('assert'), - _vaultSecrets; - - _vaultSecrets = pm.vault; - pm.vault = []; - - assert.strictEqual(pm.vault, _vaultSecrets, 'property stays unchanged'); - `, { context: sampleContextData }, done); + assert.deepEqual(Object.keys(pm.vault), ['get', 'set', 'unset']); + `, {}, done); }); + it('should send correct events and receive data for pm.vault operations', function (done) { + const executionId = '2', - it('should forward vaultSecrets forwarded during execution', function (done) { - context.execute(` - var assert = require('assert'); - assert.strictEqual(pm.vault.get('var1'), 'one-vault'); - assert.strictEqual(pm.vault.get('var2'), 'two-vault'); - `, { context: sampleContextData }, done); - }); + getErrorEventHandler = function (callback) { + // errors from the execute callback are catched here as well + // so, call mocha `done` callback with an error + // @todo this is not supposed to happen, fix this + return function () { + callback(new Error('Assertion Error')); + }; + }, + executionError = sinon.spy(getErrorEventHandler(done)); - it('pm.vault.toObject must return a pojo', function (done) { + context.on('execution.error', executionError); + // eslint-disable-next-line no-unused-vars + context.on('execution.vault.' + executionId, (eventId, _cmd, ..._args) => { + context.dispatch(`execution.vault.${executionId}`, eventId, null, 'value2'); + }); context.execute(` var assert = require('assert'); + const val = await pm.vault.get('key1'); + assert.equal(val, "value2"); + `, { + id: executionId + }, function (err) { + if (err) { + return done(err); + } - assert.strictEqual(_.isPlainObject(pm.vault.toObject()), true); - assert.deepEqual(pm.vault.toObject(), { - 'vault:var1': 'one-vault', - 'vault:var2': 'two-vault' - }); - `, { context: sampleContextData }, done); + done(); + }); }); - it('pm.variables.toObject must contain vaultSecrets', function (done) { - context.execute(` - var assert = require('assert'); + it('should throw error if pm.vault. promise rejects', function (done) { + const executionId = '2', + executionError = sinon.spy(); - assert.strictEqual(_.isPlainObject(pm.variables.toObject()), true); - assert.deepEqual(pm.variables.toObject(), { - 'vault:var1': 'one-vault', - 'vault:var2': 'two-vault', - 'var1': 'one-data', - 'var2': 2.5 - }); - `, { context: sampleContextData }, done); - }); - it('should propagate updated vault secrets from inside sandbox', function (done) { + context.on('execution.error', (...args) => { + executionError(args); + }); + // eslint-disable-next-line no-unused-vars + context.on('execution.vault.' + executionId, (eventId, _cmd, ..._args) => { + context.dispatch(`execution.vault.${executionId}`, eventId, new Error('Vault access denied')); + }); context.execute(` var assert = require('assert'); - - pm.vault.set('var1', 'one-one-vault'); - assert.strictEqual(pm.vault.get('var1'), 'one-one-vault'); - `, { context: sampleContextData }, function (err, exec) { - expect(err).to.be.null; - expect(exec).to.be.ok; - expect(exec).to.deep.nested.include({ 'vaultSecrets.values': [ - { type: 'string', value: 'one-one-vault', key: 'vault:var1' }, - { type: 'string', value: 'two-vault', key: 'vault:var2' } - ] }); + const val = await pm.vault.get('key1'); + assert.equal(val, "value2"); + `, { + id: executionId + }, function () { + expect(executionError.calledOnce).to.be.true; + expect(executionError.firstCall.args[0]).to.eql([ + { + execution: '2' + }, + { + message: 'Vault access denied', + name: 'Error', + type: 'Error' + } + ]); done(); }); }); diff --git a/test/unit/vault.test.js b/test/unit/vault.test.js new file mode 100644 index 00000000..84a9d585 --- /dev/null +++ b/test/unit/vault.test.js @@ -0,0 +1,166 @@ +const { VaultExternal, Vault } = require('../../lib/sandbox/vault'); + +describe('vault', function () { + describe('Vault', function () { + it('should set up vault', function () { + const bridge = { + on: sinon.spy() + }, + timers = {}, + vault = new Vault('', bridge, timers); + + expect(vault._event).to.eql('execution.vault.'); + }); + it('should close connection on calling dispose()', function () { + const bridge = { + on: sinon.spy(), + off: sinon.spy() + }, + timers = {}, + vault = new Vault('', bridge, timers); + + vault.dispose(); + + expect(bridge.off.calledWith('execution.vault.')).to.be.true; + }); + it('should call bridge dispath on calling exec', async function () { + const bridge = { + on: sinon.spy(), + off: sinon.spy(), + dispatch: sinon.spy() + }, + timers = { + setEvent: (fn) => { return fn(); } + }, + vault = new Vault('', bridge, timers); + + await vault.exec('', ''); + + expect(bridge.dispatch.called).to.be.true; + }); + it('should return value on calling exec', async function () { + const bridge = { + on: sinon.spy(), + off: sinon.spy(), + dispatch: () => { return 0; } + }, + timers = { + setEvent: (fn) => { return fn(null, ''); } + }, + vault = new Vault('', bridge, timers), + + res = await vault.exec('', ''); + + expect(res).to.eql(''); + }); + it('should trigger handler to return value', async function () { + let callHandler, promise, resolve; + + promise = new Promise((res) => { + resolve = res; + }); + + const bridge = { + on: (event, handler) => { + callHandler = () => { return handler(); }; + }, + off: sinon.spy(), + dispatch: () => { return 0; } + }, + timers = { + // setEvent: (fn) => { return fn(null, ''); } + setEvent: async (fn) => { + await promise; + + return fn(null, ''); + }, + clearEvent: () => { + resolve(''); + } + }, + vault = new Vault('', bridge, timers); + + vault._dispatch = callHandler; + + // eslint-disable-next-line one-var + const res = await vault.exec('', ''); + + expect(res).to.eql(''); + }); + it('should handle thrown error', async function () { + const bridge = { + on: sinon.spy(), + off: sinon.spy(), + dispatch: () => { return 0; } + }, + timers = { + setEvent: (fn) => { return fn(new Error('Failed')); } + }, + vault = new Vault('', bridge, timers); + + let errorMsg; + + try { + await vault.exec('', ''); + } + catch (err) { + errorMsg = err.message; + } + + expect(errorMsg).to.eql('Failed'); + }); + it('should handle error', async function () { + const bridge = { + on: sinon.spy(), + off: sinon.spy(), + dispatch: () => { return 0; } + }, + timers = { + setEvent: (fn) => { return fn('Failed'); } + }, + vault = new Vault('', bridge, timers); + + let errorMsg; + + try { + await vault.exec('', ''); + } + catch (err) { + errorMsg = err.message; + } + + expect(errorMsg).to.eql('Failed'); + }); + }); + + describe('VaultExternal', function () { + it('VaultExternal#get', function () { + const vaultFn = sinon.spy(), + + vault = VaultExternal(vaultFn); + + vault.get(''); + + expect(vaultFn.calledWith('get', '')).to.be.true; + }); + it('VaultExternal#set', function () { + const vaultFn = sinon.spy(), + + vault = VaultExternal(vaultFn); + + vault.set('', ''); + + expect(vaultFn.calledWith('set', '', '')).to.be.true; + }); + + it('VaultExternal#unset', function () { + const vaultFn = sinon.spy(), + + vault = VaultExternal(vaultFn); + + vault.unset(''); + + expect(vaultFn.calledWith('unset', '')).to.be.true; + }); + }); +});