Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UserID module: better initialization logic; new global function #8201

Merged
merged 7 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
348 changes: 203 additions & 145 deletions modules/userId/index.js

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions test/helpers/consentData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {gdprDataHandler} from 'src/adapterManager.js';

export function mockGdprConsent(sandbox, getConsentData = () => null) {
sandbox.stub(gdprDataHandler, 'promise').get(() => Promise.resolve(getConsentData()));
sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(getConsentData)
}
33 changes: 22 additions & 11 deletions test/spec/modules/eplanningBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { expect } from 'chai';
import { spec, storage } from 'modules/eplanningBidAdapter.js';
import { newBidder } from 'src/adapters/bidderFactory.js';
import { config } from 'src/config.js';
import { init } from 'modules/userId/index.js';
import {init, getIds} from 'modules/userId/index.js';
import * as utils from 'src/utils.js';
import {hook} from '../../../src/hook.js';
import {getGlobal} from '../../../src/prebidGlobal.js';

describe('E-Planning Adapter', function () {
const adapter = newBidder('spec');
Expand Down Expand Up @@ -305,6 +307,10 @@ describe('E-Planning Adapter', function () {
uspConsent: 'consentCcpa'
};

before(() => {
hook.ready();
});

describe('inherited functions', function () {
it('exists and is a function', function () {
expect(adapter.callBids).to.exist.and.to.be.a('function');
Expand Down Expand Up @@ -954,17 +960,22 @@ describe('E-Planning Adapter', function () {
});
});
describe('Send eids', function() {
let sandbox;
beforeEach(() => {
sandbox = sinon.sandbox.create();
// TODO: bid adapters should look at request data, not call getGlobal().getUserIds
sandbox.stub(getGlobal(), 'getUserIds').callsFake(() => ({
pubcid: 'c29cb2ae-769d-42f6-891a-f53cadee823d',
tdid: 'D6885E90-2A7A-4E0F-87CB-7734ED1B99A3',
id5id: { uid: 'ID5-ZHMOL_IfFSt7_lVYX8rBZc6GH3XMWyPQOBUfr4bm0g!', ext: { linkType: 1 } }
}))
});

afterEach(() => {
sandbox.restore();
})

it('should add eids to the request', function() {
init(config);
config.setConfig({
userSync: {
userIds: [
{ name: 'id5Id', value: { 'id5id': { uid: 'ID5-ZHMOL_IfFSt7_lVYX8rBZc6GH3XMWyPQOBUfr4bm0g!', ext: { linkType: 1 } } } },
{ name: 'pubCommonId', value: {'pubcid': 'c29cb2ae-769d-42f6-891a-f53cadee823d'} },
{ name: 'unifiedId', value: {'tdid': 'D6885E90-2A7A-4E0F-87CB-7734ED1B99A3'} }
]
}
});
let bidRequests = [validBidView];
const expected_id5id = encodeURIComponent(JSON.stringify({ uid: 'ID5-ZHMOL_IfFSt7_lVYX8rBZc6GH3XMWyPQOBUfr4bm0g!', ext: { linkType: 1 } }));
const request = spec.buildRequests(bidRequests, bidderRequest);
Expand Down
101 changes: 57 additions & 44 deletions test/spec/modules/id5IdSystem_spec.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import {
id5IdSubmodule,
ID5_STORAGE_NAME,
ID5_PRIVACY_STORAGE_NAME,
getFromLocalStorage,
storeInLocalStorage,
expDaysStr,
nbCacheName,
getFromLocalStorage,
getNbFromCache,
ID5_PRIVACY_STORAGE_NAME,
ID5_STORAGE_NAME,
id5IdSubmodule,
nbCacheName,
storeInLocalStorage,
storeNbInCache,
isInControlGroup
} from 'modules/id5IdSystem.js';
import { init, requestBidsHook, setSubmoduleRegistry, coreStorage } from 'modules/userId/index.js';
import { config } from 'src/config.js';
import { server } from 'test/mocks/xhr.js';
import {coreStorage, init, requestBidsHook, setSubmoduleRegistry} from 'modules/userId/index.js';
import {config} from 'src/config.js';
import {server} from 'test/mocks/xhr.js';
import * as events from 'src/events.js';
import CONSTANTS from 'src/constants.json';
import * as utils from 'src/utils.js';
import 'src/prebid.js';
import {hook} from '../../../src/hook.js';
import {mockGdprConsent} from '../../helpers/consentData.js';

let expect = require('chai').expect;

Expand Down Expand Up @@ -89,6 +91,10 @@ describe('ID5 ID System', function() {
};
}

before(() => {
hook.ready();
});

describe('Check for valid publisher config', function() {
it('should fail with invalid config', function() {
// no config
Expand Down Expand Up @@ -308,8 +314,11 @@ describe('ID5 ID System', function() {

describe('Request Bids Hook', function() {
let adUnits;
let sandbox;

beforeEach(function() {
sandbox = sinon.sandbox.create();
mockGdprConsent(sandbox);
sinon.stub(events, 'getEvents').returns([]);
coreStorage.removeDataFromLocalStorage(ID5_STORAGE_NAME);
coreStorage.removeDataFromLocalStorage(`${ID5_STORAGE_NAME}_last`);
Expand All @@ -321,13 +330,14 @@ describe('ID5 ID System', function() {
coreStorage.removeDataFromLocalStorage(ID5_STORAGE_NAME);
coreStorage.removeDataFromLocalStorage(`${ID5_STORAGE_NAME}_last`);
coreStorage.removeDataFromLocalStorage(ID5_NB_STORAGE_NAME);
sandbox.restore();
});

it('should add stored ID from cache to bids', function (done) {
storeInLocalStorage(ID5_STORAGE_NAME, JSON.stringify(ID5_STORED_OBJ), 1);

setSubmoduleRegistry([id5IdSubmodule]);
init(config);
setSubmoduleRegistry([id5IdSubmodule]);
config.setConfig(getFetchLocalStorageConfig());

requestBidsHook(function () {
Expand All @@ -352,8 +362,8 @@ describe('ID5 ID System', function() {
});

it('should add config value ID to bids', function (done) {
setSubmoduleRegistry([id5IdSubmodule]);
init(config);
setSubmoduleRegistry([id5IdSubmodule]);
config.setConfig(getValueConfig(ID5_STORED_ID));

requestBidsHook(function () {
Expand All @@ -371,32 +381,32 @@ describe('ID5 ID System', function() {
}, { adUnits });
});

it('should set nb=1 in cache when no stored nb value exists and cached ID', function () {
it('should set nb=1 in cache when no stored nb value exists and cached ID', function (done) {
storeInLocalStorage(ID5_STORAGE_NAME, JSON.stringify(ID5_STORED_OBJ), 1);
coreStorage.removeDataFromLocalStorage(ID5_NB_STORAGE_NAME);

setSubmoduleRegistry([id5IdSubmodule]);
init(config);
setSubmoduleRegistry([id5IdSubmodule]);
config.setConfig(getFetchLocalStorageConfig());

let innerAdUnits;
requestBidsHook((adUnitConfig) => { innerAdUnits = adUnitConfig.adUnits }, {adUnits});

expect(getNbFromCache(ID5_TEST_PARTNER_ID)).to.be.eq(1);
requestBidsHook((adUnitConfig) => {
expect(getNbFromCache(ID5_TEST_PARTNER_ID)).to.be.eq(1);
done()
}, {adUnits});
});

it('should increment nb in cache when stored nb value exists and cached ID', function () {
it('should increment nb in cache when stored nb value exists and cached ID', function (done) {
storeInLocalStorage(ID5_STORAGE_NAME, JSON.stringify(ID5_STORED_OBJ), 1);
storeNbInCache(ID5_TEST_PARTNER_ID, 1);

setSubmoduleRegistry([id5IdSubmodule]);
init(config);
setSubmoduleRegistry([id5IdSubmodule]);
config.setConfig(getFetchLocalStorageConfig());

let innerAdUnits;
requestBidsHook((adUnitConfig) => { innerAdUnits = adUnitConfig.adUnits }, {adUnits});

expect(getNbFromCache(ID5_TEST_PARTNER_ID)).to.be.eq(2);
requestBidsHook(() => {
expect(getNbFromCache(ID5_TEST_PARTNER_ID)).to.be.eq(2);
done()
}, {adUnits});
});

it('should call ID5 servers with signature and incremented nb post auction if refresh needed', function () {
Expand All @@ -407,29 +417,32 @@ describe('ID5 ID System', function() {
let id5Config = getFetchLocalStorageConfig();
id5Config.userSync.userIds[0].storage.refreshInSeconds = 2;

setSubmoduleRegistry([id5IdSubmodule]);
init(config);
setSubmoduleRegistry([id5IdSubmodule]);
config.setConfig(id5Config);

let innerAdUnits;
requestBidsHook((adUnitConfig) => { innerAdUnits = adUnitConfig.adUnits }, {adUnits});

expect(getNbFromCache(ID5_TEST_PARTNER_ID)).to.be.eq(2);

expect(server.requests).to.be.empty;
events.emit(CONSTANTS.EVENTS.AUCTION_END, {});

let request = server.requests[0];
let requestBody = JSON.parse(request.requestBody);
expect(request.url).to.contain(ID5_ENDPOINT);
expect(requestBody.s).to.eq(ID5_STORED_SIGNATURE);
expect(requestBody.nbPage).to.eq(2);

const responseHeader = { 'Content-Type': 'application/json' };
request.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));

expect(decodeURIComponent(getFromLocalStorage(ID5_STORAGE_NAME))).to.be.eq(JSON.stringify(ID5_JSON_RESPONSE));
expect(getNbFromCache(ID5_TEST_PARTNER_ID)).to.be.eq(0);
return new Promise((resolve) => {
requestBidsHook(() => {
resolve()
}, {adUnits});
}).then(() => {
expect(getNbFromCache(ID5_TEST_PARTNER_ID)).to.be.eq(2);
expect(server.requests).to.be.empty;
events.emit(CONSTANTS.EVENTS.AUCTION_END, {});
return new Promise((resolve) => setTimeout(resolve))
}).then(() => {
let request = server.requests[0];
let requestBody = JSON.parse(request.requestBody);
expect(request.url).to.contain(ID5_ENDPOINT);
expect(requestBody.s).to.eq(ID5_STORED_SIGNATURE);
expect(requestBody.nbPage).to.eq(2);

const responseHeader = { 'Content-Type': 'application/json' };
request.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));

expect(decodeURIComponent(getFromLocalStorage(ID5_STORAGE_NAME))).to.be.eq(JSON.stringify(ID5_JSON_RESPONSE));
expect(getNbFromCache(ID5_TEST_PARTNER_ID)).to.be.eq(0);
})
});
});

Expand Down
18 changes: 13 additions & 5 deletions test/spec/modules/idImportLibrary_spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import {init} from 'modules/userId/index.js';
import * as utils from 'src/utils.js';
import * as idImportlibrary from 'modules/idImportLibrary.js';

import {getGlobal} from '../../../src/prebidGlobal.js';
import {config} from 'src/config.js';
import {hook} from '../../../src/hook.js';
var expect = require('chai').expect;

const mockMutationObserver = {
Expand All @@ -15,6 +18,11 @@ describe('IdImportLibrary Tests', function () {
let clock;
let fn = sinon.spy();

before(() => {
hook.ready();
init(config);
});

beforeEach(function () {
fakeServer = sinon.fakeServer.create();
sinon.stub(utils, 'logInfo');
Expand Down Expand Up @@ -85,10 +93,10 @@ describe('IdImportLibrary Tests', function () {
let refreshUserIdSpy;
beforeEach(function() {
let sandbox = sinon.createSandbox();
refreshUserIdSpy = sinon.spy(window.$$PREBID_GLOBAL$$, 'refreshUserIds');
refreshUserIdSpy = sinon.stub(getGlobal(), 'refreshUserIds');
clock = sinon.useFakeTimers(1046952000000); // 2003-03-06T12:00:00Z
mutationObserverStub = sinon.stub(window, 'MutationObserver').returns(mockMutationObserver);
userId = sandbox.stub(window.$$PREBID_GLOBAL$$, 'getUserIds').returns({id: {'MOCKID': '1111'}});
userId = sandbox.stub(getGlobal(), 'getUserIds').returns({id: {'MOCKID': '1111'}});
fakeServer.respondWith('POST', 'URL', [200,
{
'Content-Type': 'application/json',
Expand Down Expand Up @@ -230,14 +238,14 @@ describe('IdImportLibrary Tests', function () {
jsonSpy.restore();
mutationObserverStub.restore();
});
it('results with config inputscan without listner with no user ids ', function () {
it('results with config inputscan without listner with no user ids #1', function () {
let config = { 'url': 'testUrl', 'inputscan': true, 'debounce': 0 }
document.body.innerHTML = '<body><input id="userid" value="[email protected]"></body>';
idImportlibrary.setConfig(config);
expect(config.inputscan).to.be.equal(true);
expect(jsonSpy.calledOnce).to.equal(false);
});
it('results with config inputscan without listner with no user ids ', function () {
it('results with config inputscan without listner with no user ids #2', function () {
let config = { 'url': 'testUrl', 'inputscan': true, 'debounce': 0 }
document.body.innerHTML = '<body><input id="userid"></body>';
idImportlibrary.setConfig(config);
Expand Down
10 changes: 9 additions & 1 deletion test/spec/modules/idxIdSystem_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {find} from 'src/polyfill.js';
import { config } from 'src/config.js';
import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js';
import { storage, idxIdSubmodule } from 'modules/idxIdSystem.js';
import {mockGdprConsent} from '../../helpers/consentData.js';

const IDX_COOKIE_NAME = '_idx';
const IDX_DUMMY_VALUE = 'idx value for testing';
Expand Down Expand Up @@ -85,15 +86,22 @@ describe('IDx ID System', () => {

describe('requestBids hook', () => {
let adUnits;
let sandbox;

beforeEach(() => {
sandbox = sinon.sandbox.create();
mockGdprConsent(sandbox);
adUnits = [getAdUnitMock()];
setSubmoduleRegistry([idxIdSubmodule]);
init(config);
setSubmoduleRegistry([idxIdSubmodule]);
config.setConfig(getConfigMock());
getCookieStub.withArgs(IDX_COOKIE_NAME).returns(IDX_COOKIE_STORED);
});

afterEach(() => {
sandbox.restore();
})

it('when a stored IDx exists it is added to bids', (done) => {
requestBidsHook(() => {
adUnits.forEach(unit => {
Expand Down
7 changes: 6 additions & 1 deletion test/spec/modules/parrableIdSystem_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { uspDataHandler } from 'src/adapterManager.js';
import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js';
import { parrableIdSubmodule } from 'modules/parrableIdSystem.js';
import { server } from 'test/mocks/xhr.js';
import {mockGdprConsent} from '../../helpers/consentData.js';

const storage = newStorageManager();

Expand Down Expand Up @@ -639,18 +640,22 @@ describe('Parrable ID System', function() {

describe('userId requestBids hook', function() {
let adUnits;
let sandbox;

beforeEach(function() {
sandbox = sinon.sandbox.create();
mockGdprConsent(sandbox);
adUnits = [getAdUnitMock()];
writeParrableCookie({ eid: P_COOKIE_EID, ibaOptout: true });
setSubmoduleRegistry([parrableIdSubmodule]);
init(config);
setSubmoduleRegistry([parrableIdSubmodule]);
config.setConfig(getConfigMock());
});

afterEach(function() {
removeParrableCookie();
storage.setCookie(P_COOKIE_NAME, '', EXPIRED_COOKIE_DATE);
sandbox.restore();
});

it('when a stored Parrable ID exists it is added to bids', function(done) {
Expand Down
Loading