From ef65526bd6a6d6408b45e0e6e2f24a1a3285610a Mon Sep 17 00:00:00 2001 From: Pranav Joglekar Date: Mon, 29 Jul 2024 20:25:30 +0530 Subject: [PATCH] Added support for `prefix` in VariableScope (#1364) --- CHANGELOG.yaml | 1 + lib/collection/variable-scope.js | 25 +++++++--- test/unit/variable-scope.test.js | 85 ++++++++++++++++++++++++++++++++ types/index.d.ts | 2 + 4 files changed, 105 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index b7181b012..9b69907c6 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -3,6 +3,7 @@ unreleased: - GH-1366 Fixed a bug where $randomAvatarImage was returning an invalid URL chores: - GH-1362 Updated `Request~size` to handle `downloadedBytes` property + - GH-1364 Added support for `prefix` in VariableScope 4.4.0: date: 2024-02-28 diff --git a/lib/collection/variable-scope.js b/lib/collection/variable-scope.js index bab70895c..a87e6e3fd 100644 --- a/lib/collection/variable-scope.js +++ b/lib/collection/variable-scope.js @@ -26,6 +26,7 @@ var _ = require('../util').lodash, * @typedef VariableScope.definition * @property {String} [id] ID of the scope * @property {String} [name] A name of the scope + * @property {String} [prefix] A prefix to be used for variable names in this scope * @property {Array.} [values] A list of variables defined in an array in form of `{name:String, * value:String}` * @@ -111,6 +112,10 @@ _.inherit(( if (mutations) { this.mutations = new MutationTracker(mutations); } + + if (definition && definition.prefix) { + this.prefix = definition.prefix; + } }), Property); /** @@ -176,7 +181,8 @@ _.assign(VariableScope.prototype, /** @lends VariableScope.prototype */ { * false otherwise */ has: function (key) { - var variable = this.values.oneNormalizedVariable(key), + const _key = (this.prefix || '') + key; + var variable = this.values.oneNormalizedVariable(_key), i, ii; @@ -184,7 +190,7 @@ _.assign(VariableScope.prototype, /** @lends VariableScope.prototype */ { // we search all the layers and return the first occurrence. if ((!variable || variable.disabled === true) && this._layers) { for (i = 0, ii = this._layers.length; i < ii; i++) { - variable = this._layers[i].oneNormalizedVariable(key); + variable = this._layers[i].oneNormalizedVariable(_key); if (variable && variable.disabled !== true) { break; } } } @@ -199,14 +205,15 @@ _.assign(VariableScope.prototype, /** @lends VariableScope.prototype */ { * @returns {*} The value of the specified variable across scopes. */ get: function (key) { - var variable = this.values.oneNormalizedVariable(key), + const _key = (this.prefix || '') + key; + var variable = this.values.oneNormalizedVariable(_key), i, ii; // if a variable does not exist in local scope, we search all the layers and return the first occurrence. if ((!variable || variable.disabled === true) && this._layers) { for (i = 0, ii = this._layers.length; i < ii; i++) { - variable = this._layers[i].oneNormalizedVariable(key); + variable = this._layers[i].oneNormalizedVariable(_key); if (variable && variable.disabled !== true) { break; } } } @@ -222,10 +229,11 @@ _.assign(VariableScope.prototype, /** @lends VariableScope.prototype */ { * @param {Variable.types} [type] - Optionally, the value of the variable can be set to a type */ set: function (key, value, type) { - var variable = this.values.oneNormalizedVariable(key), + const _key = (this.prefix || '') + key; + var variable = this.values.oneNormalizedVariable(_key), // create an object that will be used as setter - update = { key, value }; + update = { key: _key, value: value }; _.isString(type) && (update.type = type); @@ -248,11 +256,12 @@ _.assign(VariableScope.prototype, /** @lends VariableScope.prototype */ { * @param {String} key - */ unset: function (key) { + const _key = (this.prefix || '') + key; var lastDisabledVariable; this.values.remove(function (variable) { // bail out if variable name didn't match - if (variable.key !== key) { + if (variable.key !== _key) { return false; } @@ -269,7 +278,7 @@ _.assign(VariableScope.prototype, /** @lends VariableScope.prototype */ { // restore the reference with the last disabled variable if (lastDisabledVariable) { - this.values.reference[key] = lastDisabledVariable; + this.values.reference[_key] = lastDisabledVariable; } // track the change if mutation tracking is enabled diff --git a/test/unit/variable-scope.test.js b/test/unit/variable-scope.test.js index 394f89532..aee0f53f6 100644 --- a/test/unit/variable-scope.test.js +++ b/test/unit/variable-scope.test.js @@ -325,6 +325,17 @@ describe('VariableScope', function () { expect(scope.get('random')).to.be.undefined; }); + it('should get variables with prefix', function () { + var scope = new VariableScope({ + prefix: 'vault:', + values: [ + { key: 'vault:var-1', value: 'var-1-value' }, + { key: 'vault:var-2', value: 'var-2-value' } + ] }); + + expect(scope.get('var-2')).to.equal('var-2-value'); + }); + describe('multi layer search', function () { it('should get from parent scope', function () { var scope = new VariableScope([ @@ -506,6 +517,19 @@ describe('VariableScope', function () { scope.set('var-4', 3.142, 'boolean'); expect(scope.get('var-4')).to.be.true; }); + + it('should correctly update an existing value with prefix', function () { + var scope = new VariableScope({ + prefix: 'vault:', + values: [{ + key: 'vault:var-1', + value: 'var-1-value' + }] + }); + + scope.set('var-1', 'new-var-1-value'); + expect(scope.get('var-1')).to.equal('new-var-1-value'); + }); }); describe('unset', function () { @@ -607,6 +631,24 @@ describe('VariableScope', function () { // check reference list expect(scope.values.reference).to.have.property('var-2'); }); + + it('should correctly remove an existing variable with prefix', function () { + var scope = new VariableScope({ + prefix: 'vault:', + values: [{ + key: 'vault:var-1', + value: 'var-1-value' + }, { + key: 'vault:var-2', + value: 'var-2-value' + }] + }); + + scope.unset('var-1'); + + expect(scope.values.count()).to.equal(1); + expect(scope.get('var-1')).to.be.undefined; + }); }); describe('clear', function () { @@ -1233,6 +1275,20 @@ describe('VariableScope', function () { expect(scope.has('alpha')).to.be.true; }); + + it('should find variable from current scope with prefix', function () { + var scope = new VariableScope({ + prefix: 'vault:', + values: [ + { key: 'vault:alpha', value: 'foo' }, + { key: 'vault:gamma', value: 'baz', disabled: true } + ] + }); + + expect(scope.has('alpha')).to.be.true; + expect(scope.has('gamma')).to.be.false; + expect(scope.has('random')).to.be.false; + }); }); describe('disabled variable', function () { @@ -1379,6 +1435,35 @@ describe('VariableScope', function () { expect(scope1.values).to.eql(scope2.values); }); + it('should be capable of being replayed with prefix', function () { + var initialState = { + prefix: 'vault:', + values: [{ + key: 'foo', + value: 'foo' + }, { + key: 'bar', + value: 'bar' + }] + }, + scope1 = new VariableScope(initialState), + scope2 = new VariableScope(initialState); + + scope1.enableTracking(); + + // add a new key + scope1.set('baz', 'baz'); + // update a key + scope1.set('foo', 'foo updated'); + // remove a key + scope1.unset('bar'); + + // replay mutations on a different object + scope1.mutations.applyOn(scope2); + + expect(scope1.values).to.eql(scope2.values); + }); + it('should be serialized', function () { var scope = new VariableScope(), serialized, diff --git a/types/index.d.ts b/types/index.d.ts index 9a881d4f3..a680117da 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -2333,12 +2333,14 @@ declare module "postman-collection" { * } * @property [id] - ID of the scope * @property [name] - A name of the scope + * @property [prefix] - A prefix to be used for variable names in this scope * @property [values] - A list of variables defined in an array in form of `{name:String, * value:String}` */ type definition = { id?: string; name?: string; + prefix?: string; values?: Variable.definition[]; }; }