From eddc1defcc76047c5ba863e32697ba3eedd9baff Mon Sep 17 00:00:00 2001 From: Jagadeesh Karicherla Date: Thu, 5 Oct 2023 10:35:27 -0700 Subject: [PATCH 1/4] feat(core): add setrequestmetadata public method Add setrequestmetadata public method --- src/0_queue.js | 2 +- src/1_utils.js | 20 ++++++++++++++++ src/2_storage.js | 11 ++++----- src/3_api.js | 5 +++- src/6_branch.js | 36 +++++++++++++++++++++++++++- test/6_branch_new.js | 56 ++++++++++++++++++++++++++++++++++++++++---- test/branch-deps.js | 2 +- 7 files changed, 117 insertions(+), 15 deletions(-) diff --git a/src/0_queue.js b/src/0_queue.js index 7f24cd86..2eddd10a 100644 --- a/src/0_queue.js +++ b/src/0_queue.js @@ -7,7 +7,7 @@ goog.provide('task_queue'); /** * @returns {function(function(function()))} */ -var task_queue = function() { +task_queue = function() { var queue = []; var next = function() { if (queue.length) { diff --git a/src/1_utils.js b/src/1_utils.js index 544885ca..7bf06680 100644 --- a/src/1_utils.js +++ b/src/1_utils.js @@ -1320,3 +1320,23 @@ utils.removeTrailingDotZeros = function(versionNumber) { } return versionNumber; }; + +/** + * @param {Object} obj + * A utility function to deep copy objects + */ +utils.deepCopy = function(obj) { + var ret = {}; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + var val = obj[key]; + if (typeof val === 'object' && val !== null) { + ret[key] = utils.deepCopy(val); + } + else { + ret[key] = val; + } + } + } + return ret; +}; diff --git a/src/2_storage.js b/src/2_storage.js index 8652101d..8679713b 100644 --- a/src/2_storage.js +++ b/src/2_storage.js @@ -17,13 +17,12 @@ var BRANCH_KEY_PREFIX = 'BRANCH_WEBSDK_KEY'; /** @typedef {undefined|{get:function(string, boolean=), set:function(string, (string|boolean), boolean=), * remove:function(string), clear:function(), isEnabled:function()}} */ -var storage; /** * @class BranchStorage * @constructor */ -var BranchStorage = function(storageMethods) { +storage.BranchStorage = function(storageMethods) { for (var i = 0; i < storageMethods.length; i++) { var storageMethod = this[storageMethods[i]]; storageMethod = (typeof storageMethod === 'function') ? storageMethod() : storageMethod; @@ -150,12 +149,12 @@ var webStorage = function(perm) { }; /** @type {storage} */ -BranchStorage.prototype['local'] = function() { +storage.BranchStorage.prototype['local'] = function() { return webStorage(true); }; /** @type {storage} */ -BranchStorage.prototype['session'] = function() { +storage.BranchStorage.prototype['session'] = function() { return webStorage(false); }; @@ -214,12 +213,12 @@ var cookies = function() { }; }; -BranchStorage.prototype['cookie'] = function() { +storage.BranchStorage.prototype['cookie'] = function() { return cookies(); }; /** @type {storage} */ -BranchStorage.prototype['pojo'] = { +storage.BranchStorage.prototype['pojo'] = { getAll: function() { return this._store; }, diff --git a/src/3_api.js b/src/3_api.js index c30e5aac..e49f0176 100644 --- a/src/3_api.js +++ b/src/3_api.js @@ -14,7 +14,7 @@ * @class Server * @constructor */ - var Server = function() { }; + Server = function() { }; Server.prototype._jsonp_callback_index = 0; @@ -131,6 +131,9 @@ // to .setBranchViewData() call so the logic above won't work utils.merge(d, data); } + if (data.hasOwnProperty("branch_requestMetadata") && data["branch_requestMetadata"] && !(resource.endpoint === '/v1/pageview' || resource.endpoint === '/v1/dismiss')) { + d['metadata'] = utils.deepcopy(data["branch_requestMetadata"]); + } if (resource.method === 'POST') { try { diff --git a/src/6_branch.js b/src/6_branch.js index 70bdce17..7d5b7da9 100644 --- a/src/6_branch.js +++ b/src/6_branch.js @@ -129,7 +129,7 @@ Branch = function() { var storageMethods = [ 'session', 'cookie', 'pojo' ]; - this._storage = /** @type {storage} */ (new BranchStorage(storageMethods)); + this._storage = /** @type {storage} */ (new storage.BranchStorage(storageMethods)); // jshint ignore:line this._server = new Server(); @@ -139,6 +139,7 @@ Branch = function() { this._listeners = [ ]; this.sdk = sdk + config.version; + this.requestMetadata = {}; this.init_state = init_states.NO_INIT; this.init_state_fail_code = init_state_fail_codes.NO_FAILURE; @@ -203,7 +204,17 @@ Branch.prototype._api = function(resource, obj, callback) { if (utils.userPreferences.trackingDisabled) { obj['tracking_disabled'] = utils.userPreferences.trackingDisabled; } + if (this.requestMetadata) { + for (var metadata_key in this.requestMetadata) { + if (this.requestMetadata.hasOwnProperty(metadata_key)) { + if (!obj["branch_requestMetadata"]) { + obj["branch_requestMetadata"] = {}; + } + obj["branch_requestMetadata"][metadata_key] = this.requestMetadata[metadata_key]; + } + } + } return this._server.request(resource, obj, this._storage, function(err, data) { callback(err, data); }); @@ -1926,3 +1937,26 @@ Branch.prototype['setAPIResponseCallback'] = wrap(callback_params.NO_CALLBACK, f Branch.prototype.referringLink = function(withExtendedJourneysAssist) { return this._referringLink(withExtendedJourneysAssist); }; + +/*** + * @function Branch.setRequestMetaData + * @param {String} key - Request metadata key + * @param {String} value - Request metadata value + * Sets request metadata + */ +Branch.prototype.setRequestMetaData = function(key, value) { + try { + if ((typeof(key) === 'undefined' || key === null || key.length === 0) || (typeof value === "undefined")) { + return; + } + + if (this.requestMetadata.hasOwnProperty(key) && value === null) { + delete this.requestMetadata[key]; + } + + this.requestMetadata = utils.addPropertyIfNotNull(this.requestMetadata, key, value); + } + catch (e) { + console.log("An error occured while setting request metadata", e); + } +}; diff --git a/test/6_branch_new.js b/test/6_branch_new.js index 589e548b..528e69fc 100644 --- a/test/6_branch_new.js +++ b/test/6_branch_new.js @@ -3,18 +3,64 @@ var sinon = require('sinon'); goog.require('Branch'); +goog.require('utils'); describe('Branch - new', function() { - var branch; - beforeEach(function() { - branch = sinon.createStubInstance(Branch); - }); + var branch_instance = new Branch(); + var assert = testUtils.unplanned(); afterEach(function() { sinon.restore(); }); describe('referringLink', function() { it('test method exists', function() { - sinon.assert.match(typeof branch.referringLink, "function"); + sinon.assert.match(typeof branch_instance.referringLink, "function"); + }); + }); + describe('setRequestMetaData', function() { + var addPropertyIfNotNullSpy; + beforeEach(function() { + addPropertyIfNotNullSpy = sinon.spy(utils, 'addPropertyIfNotNull'); + }); + it('test method exists', function() { + sinon.assert.match(typeof branch_instance.setRequestMetaData, "function"); + }); + it('should set metadata for a valid key and value', function() { + var key = 'validKey'; + var value = 'validValue'; + var requestMetadata = { + }; + var result = branch_instance.setRequestMetaData.call({ requestMetadata: requestMetadata }, key, value); + assert.strictEqual(result, undefined); + sinon.assert.calledOnce(addPropertyIfNotNullSpy); + assert.deepEqual(requestMetadata, { "validKey": "validValue" }); + }); + + it('should delete metadata for a key when value is null', function() { + var requestMetadata = { "keyToDelete": "value" }; + branch_instance.setRequestMetaData.call({ requestMetadata: requestMetadata }, "keyToDelete", null); + assert.deepEqual(requestMetadata, {}); + }); + + it('should not modify metadata for an invalid key or undefined value', function() { + var invalidKey = null; + var undefinedValue; + var requestMetadata = { "key": "value" }; + + var result1 = branch_instance.setRequestMetaData.call({ requestMetadata: requestMetadata }, invalidKey, 'validValue'); + var result2 = branch_instance.setRequestMetaData.call({ requestMetadata: requestMetadata }, 'validKey', undefinedValue); + assert.strictEqual(result1, undefined); + assert.strictEqual(result2, undefined); + sinon.assert.notCalled(addPropertyIfNotNullSpy); + assert.deepEqual(requestMetadata, { "key": "value" }); }); }); + describe('setRequestMetaData - exceptions', function() { + it('should throw exception', function() { + var logSpy = sinon.spy(console, 'log'); + sinon.stub(utils, 'addPropertyIfNotNull').throws(new Error("fake error")); + branch_instance.setRequestMetaData.call({ requestMetadata: {} }, "validKey", 'validValue'); + assert(logSpy.calledWith("An error occured while setting request metadata")); + }); + + }); }); diff --git a/test/branch-deps.js b/test/branch-deps.js index a4f38eef..a490af46 100644 --- a/test/branch-deps.js +++ b/test/branch-deps.js @@ -22,7 +22,7 @@ goog.addDependency('../../../../test/1_utils.js', [], ['utils']); goog.addDependency('../../../../test/2_storage.js', [], ['storage']); goog.addDependency('../../../../test/3_api.js', [], ['Server', 'config', 'resources', 'safejson', 'storage', 'utils']); goog.addDependency('../../../../test/6_branch.js', [], ['Branch', 'banner_html', 'banner_utils', 'config', 'goog.json', 'resources', 'safejson', 'session', 'storage', 'utils']); -goog.addDependency('../../../../test/6_branch_new.js', [], ['Branch']); +goog.addDependency('../../../../test/6_branch_new.js', [], ['Branch', 'utils'], {'lang': 'es5'}); goog.addDependency('../../../../test/7_integration.js', [], ['config', 'goog.json']); goog.addDependency('../../../../test/blob-banner.js', [], []); goog.addDependency('../../../../test/blob-interstitial.js', [], []); From 7a48f79efc682908e1b332014f2112f87fb6cad3 Mon Sep 17 00:00:00 2001 From: Jagadeesh Karicherla Date: Thu, 5 Oct 2023 10:51:36 -0700 Subject: [PATCH 2/4] test(core): remove test for exceptions to generate mocha test report remove test for exceptions to generate mocha test report --- test/6_branch_new.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/6_branch_new.js b/test/6_branch_new.js index 528e69fc..6b21c638 100644 --- a/test/6_branch_new.js +++ b/test/6_branch_new.js @@ -54,6 +54,7 @@ describe('Branch - new', function() { assert.deepEqual(requestMetadata, { "key": "value" }); }); }); + /* describe('setRequestMetaData - exceptions', function() { it('should throw exception', function() { var logSpy = sinon.spy(console, 'log'); @@ -63,4 +64,5 @@ describe('Branch - new', function() { }); }); + */ }); From dc208b38e7b636026c4015ee000a84c8659a0c9f Mon Sep 17 00:00:00 2001 From: Jagadeesh Karicherla Date: Fri, 6 Oct 2023 08:51:44 -0700 Subject: [PATCH 3/4] fix(core): change log info to error when setRequestmetadata fails change log info to error when setRequestmetadata fails --- src/6_branch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/6_branch.js b/src/6_branch.js index 7d5b7da9..5456466d 100644 --- a/src/6_branch.js +++ b/src/6_branch.js @@ -1957,6 +1957,6 @@ Branch.prototype.setRequestMetaData = function(key, value) { this.requestMetadata = utils.addPropertyIfNotNull(this.requestMetadata, key, value); } catch (e) { - console.log("An error occured while setting request metadata", e); + console.error("An error occured while setting request metadata", e); } }; From 86a521f1e53799e47794ccee41aee7dfc7b48b9c Mon Sep 17 00:00:00 2001 From: Jagadeesh Karicherla Date: Fri, 8 Dec 2023 01:06:49 -0800 Subject: [PATCH 4/4] fix(core): fix issue with metadata value not stringified fix issue with metadata value not stringified --- src/1_utils.js | 19 ------------------- src/3_api.js | 2 +- src/6_branch.js | 2 +- test/branch-deps.js | 2 +- 4 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/1_utils.js b/src/1_utils.js index 7bf06680..c8fd5de1 100644 --- a/src/1_utils.js +++ b/src/1_utils.js @@ -1321,22 +1321,3 @@ utils.removeTrailingDotZeros = function(versionNumber) { return versionNumber; }; -/** - * @param {Object} obj - * A utility function to deep copy objects - */ -utils.deepCopy = function(obj) { - var ret = {}; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - var val = obj[key]; - if (typeof val === 'object' && val !== null) { - ret[key] = utils.deepCopy(val); - } - else { - ret[key] = val; - } - } - } - return ret; -}; diff --git a/src/3_api.js b/src/3_api.js index e49f0176..92523136 100644 --- a/src/3_api.js +++ b/src/3_api.js @@ -132,7 +132,7 @@ utils.merge(d, data); } if (data.hasOwnProperty("branch_requestMetadata") && data["branch_requestMetadata"] && !(resource.endpoint === '/v1/pageview' || resource.endpoint === '/v1/dismiss')) { - d['metadata'] = utils.deepcopy(data["branch_requestMetadata"]); + d['metadata'] = safejson.stringify(data["branch_requestMetadata"]); } if (resource.method === 'POST') { diff --git a/src/6_branch.js b/src/6_branch.js index 5456466d..19239114 100644 --- a/src/6_branch.js +++ b/src/6_branch.js @@ -1942,7 +1942,7 @@ Branch.prototype['setAPIResponseCallback'] = wrap(callback_params.NO_CALLBACK, f * @function Branch.setRequestMetaData * @param {String} key - Request metadata key * @param {String} value - Request metadata value - * Sets request metadata + * Sets request metadata that gets passed along with all the API calls except v1/pageview */ Branch.prototype.setRequestMetaData = function(key, value) { try { diff --git a/test/branch-deps.js b/test/branch-deps.js index a490af46..df778814 100644 --- a/test/branch-deps.js +++ b/test/branch-deps.js @@ -22,7 +22,7 @@ goog.addDependency('../../../../test/1_utils.js', [], ['utils']); goog.addDependency('../../../../test/2_storage.js', [], ['storage']); goog.addDependency('../../../../test/3_api.js', [], ['Server', 'config', 'resources', 'safejson', 'storage', 'utils']); goog.addDependency('../../../../test/6_branch.js', [], ['Branch', 'banner_html', 'banner_utils', 'config', 'goog.json', 'resources', 'safejson', 'session', 'storage', 'utils']); -goog.addDependency('../../../../test/6_branch_new.js', [], ['Branch', 'utils'], {'lang': 'es5'}); +goog.addDependency('../../../../test/6_branch_new.js', [], ['Branch', 'utils']); goog.addDependency('../../../../test/7_integration.js', [], ['config', 'goog.json']); goog.addDependency('../../../../test/blob-banner.js', [], []); goog.addDependency('../../../../test/blob-interstitial.js', [], []);