Skip to content

Commit

Permalink
Navegg UserID Submodule: conform with pub storage configuration (#12032)
Browse files Browse the repository at this point in the history
* dev/ simple solution

* dev: working script and working tests

* dev/ final adjustments

* dev: minor-changes

* hotfix/ importing only the necessary functions
  • Loading branch information
p-ribeiro authored Aug 5, 2024
1 parent 7f15127 commit b8659d4
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 89 deletions.
120 changes: 62 additions & 58 deletions modules/naveggIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
*/
import { isStr, isPlainObject, logError } from '../src/utils.js';
import { submodule } from '../src/hook.js';
import { ajax } from '../src/ajax.js';
import {getStorageManager} from '../src/storageManager.js';
import {MODULE_TYPE_UID} from '../src/activities/modules.js';
import { ajaxBuilder } from '../src/ajax.js';
import { getStorageManager } from '../src/storageManager.js';
import { MODULE_TYPE_UID } from '../src/activities/modules.js';

/**
* @typedef {import('../modules/userId/index.js').Submodule} Submodule
Expand All @@ -19,61 +19,72 @@ const MODULE_NAME = 'naveggId';
const OLD_NAVEGG_ID = 'nid';
const NAVEGG_ID = 'nvggid';
const BASE_URL = 'https://id.navegg.com/uid/';
const DEFAULT_EXPIRE = 8 * 24 * 3600 * 1000;
const INVALID_EXPIRE = 3600 * 1000;

export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME});

function getNaveggIdFromApi() {
const callbacks = {
success: response => {
if (response) {
try {
const responseObj = JSON.parse(response);
writeCookie(NAVEGG_ID, responseObj[NAVEGG_ID]);
} catch (error) {
logError(error);
function getIdFromAPI() {
const resp = function (callback) {
ajaxBuilder()(
BASE_URL,
response => {
if (response) {
let responseObj;
try {
responseObj = JSON.parse(response);
} catch (error) {
logError(error);
const fallbackValue = getNaveggIdFromLocalStorage() || getOldCookie();
callback(fallbackValue);
}

if (responseObj && responseObj[NAVEGG_ID]) {
callback(responseObj[NAVEGG_ID]);
} else {
const fallbackValue = getNaveggIdFromLocalStorage() || getOldCookie();
callback(fallbackValue);
}
}
}
},
error: error => {
logError('Navegg ID fetch encountered an error', error);
}
},
error => {
logError('Navegg ID fetch encountered an error', error);
const fallbackValue = getNaveggIdFromLocalStorage() || getOldCookie();
callback(fallbackValue);
},
{method: 'GET', withCredentials: false});
};
ajax(BASE_URL, callbacks, undefined, { method: 'GET', withCredentials: false });
}

function writeCookie(key, value) {
try {
if (storage.cookiesAreEnabled) {
let expTime = new Date();
const expires = value ? DEFAULT_EXPIRE : INVALID_EXPIRE;
expTime.setTime(expTime.getTime() + expires);
storage.setCookie(key, value, expTime.toUTCString(), 'none');
}
} catch (e) {
logError(e);
}
return resp;
}

function readnaveggIdFromLocalStorage() {
return storage.localStorageIsEnabled ? storage.getDataFromLocalStorage(NAVEGG_ID) : null;
/**
* @returns {string | null}
*/
function readNvgIdFromCookie() {
return storage.cookiesAreEnabled ? (storage.findSimilarCookies('nvg') ? storage.findSimilarCookies('nvg')[0] : null) : null;
}

function readnaveggIDFromCookie() {
return storage.cookiesAreEnabled ? storage.getCookie(NAVEGG_ID) : null;
/**
* @returns {string | null}
*/
function readNavIdFromCookie() {
return storage.cookiesAreEnabled() ? (storage.findSimilarCookies('nav') ? storage.findSimilarCookies('nav')[0] : null) : null;
}

function readoldnaveggIDFromCookie() {
return storage.cookiesAreEnabled ? storage.getCookie(OLD_NAVEGG_ID) : null;
/**
* @returns {string | null}
*/
function readOldNaveggIdFromCookie() {
return storage.cookiesAreEnabled() ? storage.getCookie(OLD_NAVEGG_ID) : null;
}

function readnvgIDFromCookie() {
return storage.cookiesAreEnabled ? (storage.findSimilarCookies('nvg') ? storage.findSimilarCookies('nvg')[0] : null) : null;
/**
* @returns {string | null}
*/
function getOldCookie() {
const oldCookie = readOldNaveggIdFromCookie() || readNvgIdFromCookie() || readNavIdFromCookie();
return oldCookie;
}

function readnavIDFromCookie() {
return storage.cookiesAreEnabled ? (storage.findSimilarCookies('nav') ? storage.findSimilarCookies('nav')[0] : null) : null;
/**
* @returns {string | null}
*/
function getNaveggIdFromLocalStorage() {
return storage.localStorageIsEnabled() ? storage.getDataFromLocalStorage(NAVEGG_ID) : null;
}

/** @type {Submodule} */
Expand All @@ -95,23 +106,16 @@ export const naveggIdSubmodule = {
'naveggId': naveggIdVal.split('|')[0]
} : undefined;
},

/**
* performs action to obtain id and return a value in the callback's response argument
* @function
* @param {SubmoduleConfig} config
* @return {{id: string | undefined } | undefined}
*/
getId() {
const naveggIdString = readnaveggIdFromLocalStorage() || readnaveggIDFromCookie() || getNaveggIdFromApi() || readoldnaveggIDFromCookie() || readnvgIDFromCookie() || readnavIDFromCookie();

if (typeof naveggIdString == 'string' && naveggIdString) {
try {
return { id: naveggIdString };
} catch (error) {
logError(error);
}
}
return undefined;
getId(config, consentData) {
const resp = getIdFromAPI()
return {callback: resp}
},
eids: {
'naveggId': {
Expand Down
8 changes: 8 additions & 0 deletions modules/naveggIdSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ pbjs.setConfig({
userSync: {
userIds: [{
name: 'naveggId',
storage: {
name : 'nvggid',
type : 'cookie&html5',
expires: 8
}
}]
}
});
Expand All @@ -20,3 +25,6 @@ The below parameters apply only to the naveggID integration.
| Param under usersync.userIds[] | Scope | Type | Description | Example |
| --- | --- | --- | --- | --- |
| name | Required | String | ID of the module - `"naveggId"` | `"naveggId"` |
| storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"nvggid"` |
| storage.type | Required | String | Must be "`cookie`", "`html5`" or "`cookie&html5`". This is where the results of the user ID will be stored. | `"cookie&html5"` |
| storage.expires | Required | Integer | How long (in days) the user ID information will be stored. | `8` |
172 changes: 141 additions & 31 deletions test/spec/modules/naveggIdSystem_spec.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,155 @@
import { naveggIdSubmodule, storage } from 'modules/naveggIdSystem.js';
import { naveggIdSubmodule, storage, getIdFromAPI } from 'modules/naveggIdSystem.js';
import { server } from 'test/mocks/xhr.js';
import * as ajaxLib from 'src/ajax.js';

describe('naveggId', function () {
let sandbox;
beforeEach(() => {
sandbox = sinon.sandbox.create();
sandbox.stub(storage, 'getDataFromLocalStorage');
const NAVEGGID_CONFIG_COOKIE_HTML5 = {
storage: {
name: 'nvggid',
type: 'cookie&html5',
expires: 8
}
}

const MOCK_RESPONSE = {
nvggid: 'test_nvggid'
}

const MOCK_RESPONSE_NULL = {
nvggid: null
}

function mockResponse(responseText, isSuccess = true) {
return function(url, callbacks) {
if (isSuccess) {
callbacks.success(responseText)
} else {
callbacks.error(new Error('Mock Error'))
}
}
}

function deleteAllCookies() {
document.cookie.split(';').forEach(cookie => {
const eqPos = cookie.indexOf('=');
const name = eqPos > -1 ? cookie.substring(0, eqPos) : cookie;
document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT';
});
}

function setLocalStorage() {
storage.setDataInLocalStorage('nvggid', 'localstorage_value');
}

describe('getId', function () {
let ajaxStub, ajaxBuilderStub;

beforeEach(function() {
ajaxStub = sinon.stub();
ajaxBuilderStub = sinon.stub(ajaxLib, 'ajaxBuilder').returns(ajaxStub);
});

afterEach(function() {
ajaxBuilderStub.restore();
deleteAllCookies();
storage.removeDataFromLocalStorage('nvggid');
});

it('should get the value from the existing localstorage', function() {
setLocalStorage();

const callback = sinon.spy();
const apiCallback = naveggIdSubmodule.getId(NAVEGGID_CONFIG_COOKIE_HTML5).callback;

ajaxStub.callsFake((url, successCallbacks, errorCallback, options) => {
if (successCallbacks && typeof successCallbacks === 'function') {
successCallbacks(JSON.stringify(MOCK_RESPONSE_NULL));
}
});
apiCallback(callback)

expect(callback.calledOnce).to.be.true;
expect(callback.calledWith('localstorage_value')).to.be.true;
});
afterEach(() => {
sandbox.restore();

it('should get the value from a nid cookie', function() {
storage.setCookie('nid', 'old_nid_cookie', storage.expires)

const callback = sinon.spy();
const apiCallback = naveggIdSubmodule.getId(NAVEGGID_CONFIG_COOKIE_HTML5).callback;

ajaxStub.callsFake((url, successCallbacks, errorCallback, options) => {
if (successCallbacks && typeof successCallbacks === 'function') {
successCallbacks(JSON.stringify(MOCK_RESPONSE_NULL));
}
});
apiCallback(callback)

expect(callback.calledOnce).to.be.true;
expect(callback.calledWith('old_nid_cookie')).to.be.true;
});

it('should NOT find navegg id', function () {
let id = naveggIdSubmodule.getId();
it('should get the value from a nav cookie', function() {
storage.setCookie('navId', 'old_nav_cookie', storage.expires)

const callback = sinon.spy();
const apiCallback = naveggIdSubmodule.getId(NAVEGGID_CONFIG_COOKIE_HTML5).callback;

expect(id).to.be.undefined;
ajaxStub.callsFake((url, successCallbacks, errorCallback, options) => {
if (successCallbacks && typeof successCallbacks === 'function') {
successCallbacks(JSON.stringify(MOCK_RESPONSE_NULL));
}
});
apiCallback(callback)

expect(callback.calledOnce).to.be.true;
expect(callback.calledWith('old_nav_cookie')).to.be.true;
});

it('getId() should return "test-nid" id from cookie OLD_NAVEGG_ID', function() {
sinon.stub(storage, 'getCookie').withArgs('nid').returns('test-nid');
let id = naveggIdSubmodule.getId();
expect(id).to.be.deep.equal({id: 'test-nid'})
})
it('should get the value from an old nvg cookie', function() {
storage.setCookie('nvgid', 'old_nvg_cookie', storage.expires)

const callback = sinon.spy();
const apiCallback = naveggIdSubmodule.getId(NAVEGGID_CONFIG_COOKIE_HTML5).callback;

ajaxStub.callsFake((url, successCallbacks, errorCallback, options) => {
if (successCallbacks && typeof successCallbacks === 'function') {
successCallbacks(JSON.stringify(MOCK_RESPONSE_NULL));
}
});
apiCallback(callback)

it('getId() should return "test-nvggid" id from local storage NAVEGG_ID', function() {
storage.getDataFromLocalStorage.callsFake(() => 'test-ninvggidd')
expect(callback.calledOnce).to.be.true;
expect(callback.calledWith('old_nvg_cookie')).to.be.true;
});

let id = naveggIdSubmodule.getId();
expect(id).to.be.deep.equal({id: 'test-ninvggidd'})
})
it('should return correct value from API response', function(done) {
const callback = sinon.spy();
const apiCallback = naveggIdSubmodule.getId(NAVEGGID_CONFIG_COOKIE_HTML5).callback;

it('getId() should return "test-nvggid" id from local storage NAV0', function() {
storage.getDataFromLocalStorage.callsFake(() => 'nvgid-nav0')
ajaxStub.callsFake((url, successCallbacks, errorCallback, options) => {
if (successCallbacks && typeof successCallbacks === 'function') {
successCallbacks(JSON.stringify(MOCK_RESPONSE));
}
});
apiCallback(callback)

let id = naveggIdSubmodule.getId();
expect(id).to.be.deep.equal({id: 'nvgid-nav0'})
})
expect(callback.calledOnce).to.be.true;
expect(callback.calledWith('test_nvggid')).to.be.true;
done();
});

it('getId() should return "test-nvggid" id from local storage NVG0', function() {
storage.getDataFromLocalStorage.callsFake(() => 'nvgid-nvg0')
it('should return no value from API response', function(done) {
const callback = sinon.spy();
const apiCallback = naveggIdSubmodule.getId(NAVEGGID_CONFIG_COOKIE_HTML5).callback;

let id = naveggIdSubmodule.getId();
expect(id).to.be.deep.equal({id: 'nvgid-nvg0'})
})
ajaxStub.callsFake((url, successCallbacks, errorCallback, options) => {
if (successCallbacks && typeof successCallbacks === 'function') {
successCallbacks(JSON.stringify(MOCK_RESPONSE_NULL));
}
});
apiCallback(callback)
expect(callback.calledOnce).to.be.true;
expect(callback.calledWith(undefined)).to.be.true;
done();
});
});

0 comments on commit b8659d4

Please sign in to comment.