', 'ad missing native container');
- expect(bidResponse.ttl).to.equal(600);
- expect(bidResponse.creativeId).to.equal(placementId);
- expect(bidResponse.netRevenue).to.equal(true);
- expect(bidResponse.currency).to.equal('USD');
-
- expect(bidResponse.hb_bidder).to.equal('fan');
- expect(bidResponse.fb_bidid).to.equal('test-bid-id');
- expect(bidResponse.fb_format).to.equal('native');
- expect(bidResponse.fb_placementid).to.equal(placementId);
- });
- });
-});
diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js
index c4f6fe70dd1..3ebebfef1ee 100644
--- a/test/spec/modules/consentManagement_spec.js
+++ b/test/spec/modules/consentManagement_spec.js
@@ -24,9 +24,8 @@ describe('consentManagement', function () {
setConsentConfig({});
expect(userCMP).to.be.equal('iab');
expect(consentTimeout).to.be.equal(10000);
- expect(allowAuction).to.be.true;
expect(gdprScope).to.be.equal(false);
- sinon.assert.callCount(utils.logInfo, 4);
+ sinon.assert.callCount(utils.logInfo, 3);
});
it('should exit consent manager if config is not an object', function () {
@@ -58,7 +57,10 @@ describe('consentManagement', function () {
setConsentConfig(allConfig);
expect(userCMP).to.be.equal('iab');
expect(consentTimeout).to.be.equal(7500);
- expect(allowAuction).to.be.false;
+ expect(allowAuction).to.deep.equal({
+ value: false,
+ definedInConfig: true
+ });
expect(gdprScope).to.be.true;
});
@@ -110,7 +112,10 @@ describe('consentManagement', function () {
expect(userCMP).to.be.equal('iab');
expect(consentTimeout).to.be.equal(3333);
- expect(allowAuction).to.be.equal(false);
+ expect(allowAuction).to.deep.equal({
+ value: false,
+ definedInConfig: true
+ });
expect(gdprScope).to.be.equal(false);
});
});
@@ -164,7 +169,10 @@ describe('consentManagement', function () {
setConsentConfig(staticConfig);
expect(userCMP).to.be.equal('static');
expect(consentTimeout).to.be.equal(0); // should always return without a timeout when config is used
- expect(allowAuction).to.be.false;
+ expect(allowAuction).to.deep.equal({
+ value: false,
+ definedInConfig: true
+ });
expect(staticConsentData).to.be.equal(staticConfig.consentData);
});
@@ -244,7 +252,10 @@ describe('consentManagement', function () {
setConsentConfig(staticConfig);
expect(userCMP).to.be.equal('static');
expect(consentTimeout).to.be.equal(0); // should always return without a timeout when config is used
- expect(allowAuction).to.be.false;
+ expect(allowAuction).to.deep.equal({
+ value: false,
+ definedInConfig: true
+ });
expect(gdprScope).to.be.equal(false);
expect(staticConsentData).to.be.equal(staticConfig.consentData);
});
@@ -423,7 +434,6 @@ describe('consentManagement', function () {
setConsentConfig(goodConfigWithAllowAuction);
requestBidsHook(() => {
let consent = gdprDataHandler.getConsentData();
- sinon.assert.notCalled(utils.logWarn);
sinon.assert.notCalled(utils.logError);
expect(consent.consentString).to.equal(tarConsentString);
expect(consent.gdprApplies).to.be.true;
@@ -626,7 +636,6 @@ describe('consentManagement', function () {
didHookReturn = true;
}, {});
let consent = gdprDataHandler.getConsentData();
- sinon.assert.notCalled(utils.logWarn);
sinon.assert.notCalled(utils.logError);
expect(didHookReturn).to.be.true;
expect(consent.consentString).to.equal(testConsentData.tcString);
@@ -634,7 +643,7 @@ describe('consentManagement', function () {
expect(consent.apiVersion).to.equal(2);
});
- it('throws an error when processCmpData check failed while config had allowAuction set to false', function () {
+ it('throws an error when processCmpData check fails + does not call requestBids callbcack even when allowAuction is true', function () {
let testConsentData = {};
let bidsBackHandlerReturn = false;
@@ -642,7 +651,7 @@ describe('consentManagement', function () {
args[2](testConsentData);
});
- setConsentConfig(goodConfigWithCancelAuction);
+ setConsentConfig(goodConfigWithAllowAuction);
requestBidsHook(() => {
didHookReturn = true;
@@ -650,6 +659,7 @@ describe('consentManagement', function () {
let consent = gdprDataHandler.getConsentData();
sinon.assert.calledOnce(utils.logError);
+ sinon.assert.notCalled(utils.logWarn);
expect(didHookReturn).to.be.false;
expect(bidsBackHandlerReturn).to.be.true;
expect(consent).to.be.null;
@@ -676,34 +686,12 @@ describe('consentManagement', function () {
didHookReturn = true;
}, {});
let consent = gdprDataHandler.getConsentData();
- sinon.assert.notCalled(utils.logWarn);
sinon.assert.notCalled(utils.logError);
expect(didHookReturn).to.be.true;
expect(consent.consentString).to.equal(testConsentData.tcString);
expect(consent.gdprApplies).to.be.true;
expect(consent.apiVersion).to.equal(2);
});
-
- it('throws a warning + stores consentData + calls callback when processCmpData check failed while config had allowAuction set to true', function () {
- let testConsentData = {};
-
- cmpStub = sinon.stub(window, '__tcfapi').callsFake((...args) => {
- args[2](testConsentData);
- });
-
- setConsentConfig(goodConfigWithAllowAuction);
-
- requestBidsHook(() => {
- didHookReturn = true;
- }, {});
- let consent = gdprDataHandler.getConsentData();
-
- sinon.assert.calledOnce(utils.logWarn);
- expect(didHookReturn).to.be.true;
- expect(consent.consentString).to.be.undefined;
- expect(consent.gdprApplies).to.be.false;
- expect(consent.apiVersion).to.equal(2);
- });
});
});
});
diff --git a/test/spec/modules/digitrustIdSystem_spec.js b/test/spec/modules/digitrustIdSystem_spec.js
deleted file mode 100644
index befd6eb75b6..00000000000
--- a/test/spec/modules/digitrustIdSystem_spec.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import {
- digiTrustIdSubmodule,
- surfaceTestHook
-} from 'modules/digiTrustIdSystem.js';
-
-let assert = require('chai').assert;
-let expect = require('chai').expect;
-var testHook = null;
-
-/**
-* A mock implementation of IAB Consent Provider
-*/
-function mockCmp(command, version, callback, parameter) {
- var resultVal;
- if (command == 'ping') {
- resultVal = {
- gdprAppliesGlobally: mockCmp.stubSettings.isGlobal
- };
- callback(resultVal);
- } else if (command == 'getVendorConsents') {
- let cbResult = {
- vendorConsents: []
- }
- cbResult.vendorConsents[version] = mockCmp.stubSettings.consents;
- callback(cbResult);
- }
-}
-
-mockCmp.stubSettings = {
- isGlobal: false,
- consents: true
-};
-
-function setupCmpMock(isGlobal, consents) {
- window.__cmp = mockCmp;
- mockCmp.stubSettings.isGlobal = isGlobal;
- mockCmp.stubSettings.consents = consents;
-}
-
-describe('DigiTrust Id System', function () {
- it('Should create the test hook', function (done) {
- testHook = surfaceTestHook();
- assert.isNotNull(testHook, 'The test hook failed to surface');
- var conf = {
- init: {
- member: 'unit_test',
- site: 'foo'
- },
- callback: function (result) {
- }
- };
- testHook.initDigitrustFacade(conf);
- window.DigiTrust.getUser(conf);
- expect(window.DigiTrust).to.exist;
- expect(window.DigiTrust.isMock).to.be.true;
- done();
- });
-
- it('Should report as client', function (done) {
- delete window.DigiTrust;
- testHook = surfaceTestHook();
-
- var conf = {
- init: {
- member: 'unit_test',
- site: 'foo'
- },
- callback: function (result) {
- expect(window.DigiTrust).to.exist;
- expect(result).to.exist;
- expect(window.DigiTrust.isMock).to.be.true;
- }
- };
- testHook.initDigitrustFacade(conf);
- expect(window.DigiTrust).to.exist;
- expect(window.DigiTrust.isClient).to.be.true;
- done();
- });
-
- it('Should allow consent when given', function (done) {
- testHook = surfaceTestHook();
- setupCmpMock(true, true);
- var handler = function(result) {
- expect(result).to.be.true;
- done();
- }
-
- testHook.gdpr.hasConsent(null, handler);
- });
-
- it('Should consent if does not apply', function (done) {
- testHook = surfaceTestHook();
- setupCmpMock(false, true);
- var handler = function (result) {
- expect(result).to.be.true;
- done();
- }
-
- testHook.gdpr.hasConsent(null, handler);
- });
-
- it('Should not allow consent when not given', function (done) {
- testHook = surfaceTestHook();
- setupCmpMock(true, false);
- var handler = function (result) {
- expect(result).to.be.false;
- done();
- }
-
- testHook.gdpr.hasConsent(null, handler);
- });
- it('Should deny consent if timeout', function (done) {
- window.__cmp = function () { };
- var handler = function (result) {
- expect(result).to.be.false;
- done();
- }
-
- testHook.gdpr.hasConsent({ consentTimeout: 1 }, handler);
- });
- it('Should pass consent test if cmp not present', function (done) {
- delete window.__cmp
- testHook = surfaceTestHook();
- var handler = function (result) {
- expect(result).to.be.true;
- done();
- }
-
- testHook.gdpr.hasConsent(null, handler);
- });
-});
diff --git a/test/spec/modules/eids_spec.js b/test/spec/modules/eids_spec.js
index 1cbc2911ef5..c0b4703b7f4 100644
--- a/test/spec/modules/eids_spec.js
+++ b/test/spec/modules/eids_spec.js
@@ -119,22 +119,6 @@ describe('eids array generation for known sub-modules', function() {
});
});
- it('DigiTrust; getValue call', function() {
- const userId = {
- digitrustid: {
- data: {
- id: 'some-random-id-value'
- }
- }
- };
- const newEids = createEidsArray(userId);
- expect(newEids.length).to.equal(1);
- expect(newEids[0]).to.deep.equal({
- source: 'digitru.st',
- uids: [{id: 'some-random-id-value', atype: 1}]
- });
- });
-
it('criteo', function() {
const userId = {
criteoId: 'some-random-id-value'
diff --git a/test/spec/modules/gdprEnforcement_spec.js b/test/spec/modules/gdprEnforcement_spec.js
index 7f4828267a9..9b02f74f4bb 100644
--- a/test/spec/modules/gdprEnforcement_spec.js
+++ b/test/spec/modules/gdprEnforcement_spec.js
@@ -1,11 +1,13 @@
-import { deviceAccessHook, setEnforcementConfig, userSyncHook, userIdHook } from 'modules/gdprEnforcement.js';
+import { deviceAccessHook, setEnforcementConfig, userSyncHook, userIdHook, makeBidRequestsHook, validateRules, enforcementRules, purpose1Rule, purpose2Rule } from 'modules/gdprEnforcement.js';
import { config } from 'src/config.js';
import adapterManager, { gdprDataHandler } from 'src/adapterManager.js';
import * as utils from 'src/utils.js';
import { validateStorageEnforcement } from 'src/storageManager.js';
import { executeStorageCallbacks } from 'src/prebid.js';
+import events from 'src/events.js';
+import { EVENTS } from 'src/constants.json';
-describe('gdpr enforcement', function() {
+describe('gdpr enforcement', function () {
let nextFnSpy;
let logWarnSpy;
let gdprDataHandlerStub;
@@ -38,7 +40,7 @@ describe('gdpr enforcement', function() {
},
'legitimateInterests': {
'1': false,
- '2': false,
+ '2': true,
'3': false
}
},
@@ -46,7 +48,9 @@ describe('gdpr enforcement', function() {
'consents': {
'1': true,
'2': true,
- '3': false
+ '3': false,
+ '4': true,
+ '5': false
},
'legitimateInterests': {
'1': false,
@@ -81,23 +85,38 @@ describe('gdpr enforcement', function() {
}
};
- after(function() {
- validateStorageEnforcement.getHooks({hook: deviceAccessHook}).remove();
- $$PREBID_GLOBAL$$.requestBids.getHooks({hook: executeStorageCallbacks}).remove();
+ after(function () {
+ validateStorageEnforcement.getHooks({ hook: deviceAccessHook }).remove();
+ $$PREBID_GLOBAL$$.requestBids.getHooks({ hook: executeStorageCallbacks }).remove();
+ adapterManager.makeBidRequests.getHooks({ hook: makeBidRequestsHook }).remove();
})
- describe('deviceAccessHook', function() {
- beforeEach(function() {
+ describe('deviceAccessHook', function () {
+ let adapterManagerStub;
+
+ function getBidderSpec(gvlid) {
+ return {
+ getSpec: () => {
+ return {
+ gvlid
+ }
+ }
+ }
+ }
+
+ beforeEach(function () {
nextFnSpy = sinon.spy();
gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData');
logWarnSpy = sinon.spy(utils, 'logWarn');
+ adapterManagerStub = sinon.stub(adapterManager, 'getBidAdapter');
});
- afterEach(function() {
+ afterEach(function () {
config.resetConfig();
gdprDataHandler.getConsentData.restore();
logWarnSpy.restore();
+ adapterManagerStub.restore();
});
- it('should not allow device access when device access flag is set to false', function() {
+ it('should not allow device access when device access flag is set to false', function () {
config.setConfig({
deviceAccess: false,
consentManagement: {
@@ -118,10 +137,12 @@ describe('gdpr enforcement', function() {
hasEnforcementHook: true,
valid: false
}
- expect(nextFnSpy.calledWith(undefined, result));
+ sinon.assert.calledWith(nextFnSpy, undefined, undefined, result);
});
- it('should only check for consent for vendor exceptions when enforcePurpose and enforceVendor are false', function() {
+ it('should only check for consent for vendor exceptions when enforcePurpose and enforceVendor are false', function () {
+ adapterManagerStub.withArgs('appnexus').returns(getBidderSpec(1));
+ adapterManagerStub.withArgs('rubicon').returns(getBidderSpec(5));
setEnforcementConfig({
gdpr: {
rules: [{
@@ -143,7 +164,9 @@ describe('gdpr enforcement', function() {
expect(logWarnSpy.callCount).to.equal(0);
});
- it('should check consent for all vendors when enforcePurpose and enforceVendor are true', function() {
+ it('should check consent for all vendors when enforcePurpose and enforceVendor are true', function () {
+ adapterManagerStub.withArgs('appnexus').returns(getBidderSpec(1));
+ adapterManagerStub.withArgs('rubicon').returns(getBidderSpec(3));
setEnforcementConfig({
gdpr: {
rules: [{
@@ -164,7 +187,8 @@ describe('gdpr enforcement', function() {
expect(logWarnSpy.callCount).to.equal(1);
});
- it('should allow device access when gdprApplies is false and hasDeviceAccess flag is true', function() {
+ it('should allow device access when gdprApplies is false and hasDeviceAccess flag is true', function () {
+ adapterManagerStub.withArgs('appnexus').returns(getBidderSpec(1));
setEnforcementConfig({
gdpr: {
rules: [{
@@ -187,15 +211,83 @@ describe('gdpr enforcement', function() {
hasEnforcementHook: true,
valid: true
}
- expect(nextFnSpy.calledWith(undefined, result));
+ sinon.assert.calledWith(nextFnSpy, 1, 'appnexus', result);
+ });
+
+ it('should use gvlMapping set by publisher', function() {
+ config.setConfig({
+ 'gvlMapping': {
+ 'appnexus': 4
+ }
+ });
+ setEnforcementConfig({
+ gdpr: {
+ rules: [{
+ purpose: 'storage',
+ enforcePurpose: true,
+ enforceVendor: true,
+ vendorExceptions: []
+ }]
+ }
+ });
+ let consentData = {}
+ consentData.vendorData = staticConfig.consentData.getTCData;
+ consentData.gdprApplies = true;
+ consentData.apiVersion = 2;
+ gdprDataHandlerStub.returns(consentData);
+
+ deviceAccessHook(nextFnSpy, 1, 'appnexus');
+ expect(nextFnSpy.calledOnce).to.equal(true);
+ let result = {
+ hasEnforcementHook: true,
+ valid: true
+ }
+ sinon.assert.calledWith(nextFnSpy, 4, 'appnexus', result);
+ config.resetConfig();
+ });
+
+ it('should use gvl id of alias and not of parent', function() {
+ let curBidderStub = sinon.stub(config, 'getCurrentBidder');
+ curBidderStub.returns('appnexus-alias');
+ adapterManager.aliasBidAdapter('appnexus', 'appnexus-alias');
+ config.setConfig({
+ 'gvlMapping': {
+ 'appnexus-alias': 4
+ }
+ });
+ setEnforcementConfig({
+ gdpr: {
+ rules: [{
+ purpose: 'storage',
+ enforcePurpose: true,
+ enforceVendor: true,
+ vendorExceptions: []
+ }]
+ }
+ });
+ let consentData = {}
+ consentData.vendorData = staticConfig.consentData.getTCData;
+ consentData.gdprApplies = true;
+ consentData.apiVersion = 2;
+ gdprDataHandlerStub.returns(consentData);
+
+ deviceAccessHook(nextFnSpy, 1, 'appnexus');
+ expect(nextFnSpy.calledOnce).to.equal(true);
+ let result = {
+ hasEnforcementHook: true,
+ valid: true
+ }
+ sinon.assert.calledWith(nextFnSpy, 4, 'appnexus', result);
+ config.resetConfig();
+ curBidderStub.restore();
});
});
- describe('userSyncHook', function() {
+ describe('userSyncHook', function () {
let curBidderStub;
let adapterManagerStub;
- beforeEach(function() {
+ beforeEach(function () {
gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData');
logWarnSpy = sinon.spy(utils, 'logWarn');
curBidderStub = sinon.stub(config, 'getCurrentBidder');
@@ -203,7 +295,7 @@ describe('gdpr enforcement', function() {
nextFnSpy = sinon.spy();
});
- afterEach(function() {
+ afterEach(function () {
config.getCurrentBidder.restore();
config.resetConfig();
gdprDataHandler.getConsentData.restore();
@@ -211,7 +303,7 @@ describe('gdpr enforcement', function() {
logWarnSpy.restore();
});
- it('should allow bidder to do user sync if consent is true', function() {
+ it('should allow bidder to do user sync if consent is true', function () {
setEnforcementConfig({
gdpr: {
rules: [{
@@ -230,7 +322,7 @@ describe('gdpr enforcement', function() {
curBidderStub.returns('sampleBidder1');
adapterManagerStub.withArgs('sampleBidder1').returns({
- getSpec: function() {
+ getSpec: function () {
return {
'gvlid': 1
}
@@ -240,7 +332,7 @@ describe('gdpr enforcement', function() {
curBidderStub.returns('sampleBidder2');
adapterManagerStub.withArgs('sampleBidder2').returns({
- getSpec: function() {
+ getSpec: function () {
return {
'gvlid': 3
}
@@ -250,7 +342,7 @@ describe('gdpr enforcement', function() {
expect(nextFnSpy.calledTwice).to.equal(true);
});
- it('should not allow bidder to do user sync if user has denied consent', function() {
+ it('should not allow bidder to do user sync if user has denied consent', function () {
setEnforcementConfig({
gdpr: {
rules: [{
@@ -269,7 +361,7 @@ describe('gdpr enforcement', function() {
curBidderStub.returns('sampleBidder1');
adapterManagerStub.withArgs('sampleBidder1').returns({
- getSpec: function() {
+ getSpec: function () {
return {
'gvlid': 1
}
@@ -279,7 +371,7 @@ describe('gdpr enforcement', function() {
curBidderStub.returns('sampleBidder2');
adapterManagerStub.withArgs('sampleBidder2').returns({
- getSpec: function() {
+ getSpec: function () {
return {
'gvlid': 3
}
@@ -290,7 +382,7 @@ describe('gdpr enforcement', function() {
expect(logWarnSpy.callCount).to.equal(1);
});
- it('should not check vendor consent when enforceVendor is false', function() {
+ it('should not check vendor consent when enforceVendor is false', function () {
setEnforcementConfig({
gdpr: {
rules: [{
@@ -309,7 +401,7 @@ describe('gdpr enforcement', function() {
curBidderStub.returns('sampleBidder1');
adapterManagerStub.withArgs('sampleBidder1').returns({
- getSpec: function() {
+ getSpec: function () {
return {
'gvlid': 1
}
@@ -319,7 +411,7 @@ describe('gdpr enforcement', function() {
curBidderStub.returns('sampleBidder2');
adapterManagerStub.withArgs('sampleBidder2').returns({
- getSpec: function() {
+ getSpec: function () {
return {
'gvlid': 3
}
@@ -331,16 +423,16 @@ describe('gdpr enforcement', function() {
});
});
- describe('userIdHook', function() {
- beforeEach(function() {
+ describe('userIdHook', function () {
+ beforeEach(function () {
logWarnSpy = sinon.spy(utils, 'logWarn');
nextFnSpy = sinon.spy();
});
- afterEach(function() {
+ afterEach(function () {
config.resetConfig();
logWarnSpy.restore();
});
- it('should allow user id module if consent is given', function() {
+ it('should allow user id module if consent is given', function () {
setEnforcementConfig({
gdpr: {
rules: [{
@@ -366,9 +458,10 @@ describe('gdpr enforcement', function() {
const args = nextFnSpy.getCalls()[0].args;
expect(args[1].hasValidated).to.be.true;
expect(nextFnSpy.calledOnce).to.equal(true);
+ sinon.assert.calledWith(nextFnSpy, submodules, { ...consentData, hasValidated: true });
});
- it('should allow userId module if gdpr not in scope', function() {
+ it('should allow userId module if gdpr not in scope', function () {
let submodules = [{
submodule: {
gvlid: 1,
@@ -381,10 +474,10 @@ describe('gdpr enforcement', function() {
const args = nextFnSpy.getCalls()[0].args;
expect(args[1]).to.be.null;
expect(nextFnSpy.calledOnce).to.equal(true);
- expect(nextFnSpy.calledWith(undefined, submodules, consentData));
+ sinon.assert.calledWith(nextFnSpy, submodules, consentData);
});
- it('should not enforce if not apiVersion 2', function() {
+ it('should not allow user id module if user denied consent', function () {
setEnforcementConfig({
gdpr: {
rules: [{
@@ -397,57 +490,479 @@ describe('gdpr enforcement', function() {
});
let consentData = {}
consentData.vendorData = staticConfig.consentData.getTCData;
- consentData.apiVersion = 1;
+ consentData.apiVersion = 2;
consentData.gdprApplies = true;
+
let submodules = [{
submodule: {
gvlid: 1,
name: 'sampleUserId'
}
+ }, {
+ submodule: {
+ gvlid: 3,
+ name: 'sampleUserId1'
+ }
}]
userIdHook(nextFnSpy, submodules, consentData);
- // Should not pass back hasValidated flag since version 1
- const args = nextFnSpy.getCalls()[0].args;
- expect(args[1].hasValidated).to.be.undefined;
- expect(args[0]).to.deep.equal(submodules);
- expect(nextFnSpy.calledOnce).to.equal(true);
+ expect(logWarnSpy.callCount).to.equal(1);
+ let expectedSubmodules = [{
+ submodule: {
+ gvlid: 1,
+ name: 'sampleUserId'
+ }
+ }]
+ sinon.assert.calledWith(nextFnSpy, expectedSubmodules, { ...consentData, hasValidated: true });
+ });
+ });
+
+ describe('makeBidRequestsHook', function () {
+ let sandbox;
+ let adapterManagerStub;
+ let emitEventSpy;
+
+ const MOCK_AD_UNITS = [{
+ code: 'ad-unit-1',
+ mediaTypes: {},
+ bids: [{
+ bidder: 'bidder_1' // has consent
+ }, {
+ bidder: 'bidder_2' // doesn't have consent, but liTransparency is true. Bidder remains active.
+ }]
+ }, {
+ code: 'ad-unit-2',
+ mediaTypes: {},
+ bids: [{
+ bidder: 'bidder_2'
+ }, {
+ bidder: 'bidder_3'
+ }]
+ }];
+
+ beforeEach(function () {
+ sandbox = sinon.createSandbox();
+ gdprDataHandlerStub = sandbox.stub(gdprDataHandler, 'getConsentData');
+ adapterManagerStub = sandbox.stub(adapterManager, 'getBidAdapter');
+ logWarnSpy = sandbox.spy(utils, 'logWarn');
+ nextFnSpy = sandbox.spy();
+ emitEventSpy = sandbox.spy(events, 'emit');
+ });
+ afterEach(function () {
+ config.resetConfig();
+ sandbox.restore();
});
- it('should not allow user id module if user denied consent', function() {
+ it('should block bidder which does not have consent and allow bidder which has consent (liTransparency is established)', function () {
setEnforcementConfig({
gdpr: {
rules: [{
- purpose: 'storage',
- enforcePurpose: false,
+ purpose: 'basicAds',
+ enforcePurpose: true,
enforceVendor: true,
vendorExceptions: []
}]
}
});
- let consentData = {}
+ const consentData = {};
consentData.vendorData = staticConfig.consentData.getTCData;
consentData.apiVersion = 2;
consentData.gdprApplies = true;
- let submodules = [{
- submodule: {
- gvlid: 1,
- name: 'sampleUserId'
+
+ gdprDataHandlerStub.returns(consentData);
+ adapterManagerStub.withArgs('bidder_1').returns({
+ getSpec: function () {
+ return { 'gvlid': 4 }
+ }
+ });
+ adapterManagerStub.withArgs('bidder_2').returns({
+ getSpec: function () {
+ return { 'gvlid': 5 }
+ }
+ });
+ adapterManagerStub.withArgs('bidder_3').returns({
+ getSpec: function () {
+ return { 'gvlid': undefined }
}
+ });
+ makeBidRequestsHook(nextFnSpy, MOCK_AD_UNITS, []);
+
+ // Assertions
+ expect(nextFnSpy.calledOnce).to.equal(true);
+ sinon.assert.calledWith(nextFnSpy, [{
+ code: 'ad-unit-1',
+ mediaTypes: {},
+ bids: [
+ sinon.match({ bidder: 'bidder_1' }),
+ sinon.match({ bidder: 'bidder_2' })
+ ]
}, {
- submodule: {
- gvlid: 3,
- name: 'sampleUserId1'
+ code: 'ad-unit-2',
+ mediaTypes: {},
+ bids: [
+ sinon.match({ bidder: 'bidder_2' }),
+ sinon.match({ bidder: 'bidder_3' }) // should be allowed even though it's doesn't have a gvlId because liTransparency is established.
+ ]
+ }], []);
+ });
+
+ it('should block bidder which does not have consent and allow bidder which has consent (liTransparency is NOT established)', function() {
+ setEnforcementConfig({
+ gdpr: {
+ rules: [{
+ purpose: 'basicAds',
+ enforcePurpose: true,
+ enforceVendor: true,
+ vendorExceptions: ['bidder_3']
+ }]
}
- }]
- userIdHook(nextFnSpy, submodules, consentData);
- expect(logWarnSpy.callCount).to.equal(1);
- let expectedSubmodules = [{
- submodule: {
- gvlid: 1,
- name: 'sampleUserId'
+ });
+ const consentData = {};
+
+ // set li for purpose 2 to false
+ const newConsentData = utils.deepClone(staticConfig);
+ newConsentData.consentData.getTCData.purpose.legitimateInterests['2'] = false;
+
+ consentData.vendorData = newConsentData.consentData.getTCData;
+ consentData.apiVersion = 2;
+ consentData.gdprApplies = true;
+
+ gdprDataHandlerStub.returns(consentData);
+ adapterManagerStub.withArgs('bidder_1').returns({
+ getSpec: function () {
+ return { 'gvlid': 4 }
+ }
+ });
+ adapterManagerStub.withArgs('bidder_2').returns({
+ getSpec: function () {
+ return { 'gvlid': 5 }
+ }
+ });
+ adapterManagerStub.withArgs('bidder_3').returns({
+ getSpec: function () {
+ return { 'gvlid': undefined }
+ }
+ });
+
+ makeBidRequestsHook(nextFnSpy, MOCK_AD_UNITS, []);
+
+ // Assertions
+ expect(nextFnSpy.calledOnce).to.equal(true);
+ sinon.assert.calledWith(nextFnSpy, [{
+ code: 'ad-unit-1',
+ mediaTypes: {},
+ bids: [
+ sinon.match({ bidder: 'bidder_1' }), // 'bidder_2' is not present because it doesn't have vendorConsent
+ ]
+ }, {
+ code: 'ad-unit-2',
+ mediaTypes: {},
+ bids: [
+ sinon.match({ bidder: 'bidder_3' }), // 'bidder_3' is allowed despite gvlId being undefined because it's part of vendorExceptions
+ ]
+ }], []);
+
+ expect(logWarnSpy.calledOnce).to.equal(true);
+ expect(emitEventSpy.calledOnce).to.equal(true);
+ sinon.assert.calledWith(emitEventSpy, EVENTS.BIDDER_BLOCKED, 'bidder_2');
+ });
+
+ it('should skip validation checks if GDPR version is not equal to "2"', function () {
+ setEnforcementConfig({
+ gdpr: {
+ rules: [{
+ purpose: 'storage',
+ enforePurpose: false,
+ enforceVendor: false,
+ vendorExceptions: []
+ }]
+ }
+ });
+
+ const consentData = {};
+ consentData.vendorData = staticConfig.consentData.getTCData;
+ consentData.apiVersion = 1;
+ consentData.gdprApplies = true;
+ gdprDataHandlerStub.returns(consentData);
+
+ makeBidRequestsHook(nextFnSpy, MOCK_AD_UNITS, []);
+
+ // Assertions
+ expect(nextFnSpy.calledOnce).to.equal(true);
+ sinon.assert.calledWith(nextFnSpy, sinon.match.array.deepEquals(MOCK_AD_UNITS), []);
+ expect(emitEventSpy.notCalled).to.equal(true);
+ expect(logWarnSpy.notCalled).to.equal(true);
+ });
+ });
+
+ describe('validateRules', function () {
+ const createGdprRule = (purposeName = 'storage', enforcePurpose = true, enforceVendor = true, vendorExceptions = []) => ({
+ purpose: purposeName,
+ enforcePurpose: enforcePurpose,
+ enforceVendor: enforceVendor,
+ vendorExceptions: vendorExceptions
+ });
+
+ const consentData = {
+ vendorData: staticConfig.consentData.getTCData,
+ apiVersion: 2,
+ gdprApplies: true
+ };
+
+ // Bidder - 'bidderA' has vendorConsent
+ const vendorAllowedModule = 'bidderA';
+ const vendorAllowedGvlId = 1;
+
+ // Bidder = 'bidderB' doesn't have vendorConsent
+ const vendorBlockedModule = 'bidderB';
+ const vendorBlockedGvlId = 3;
+
+ const consentDataWithPurposeConsentFalse = utils.deepClone(consentData);
+ consentDataWithPurposeConsentFalse.vendorData.purpose.consents['1'] = false;
+
+ it('should return true when enforcePurpose=true AND purposeConsent[p]==true AND enforceVendor[p,v]==true AND vendorConsent[v]==true', function () {
+ // 'enforcePurpose' and 'enforceVendor' both are 'true'
+ const gdprRule = createGdprRule('storage', true, true, []);
+
+ // case 1 - Both purpose consent and vendor consent is 'true'. validateRules must return 'true'
+ let isAllowed = validateRules(gdprRule, consentData, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 2 - Purpose consent is 'true' but vendor consent is 'false'. validateRules must return 'false'
+ isAllowed = validateRules(gdprRule, consentData, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(false);
+
+ // case 3 - Purpose consent is 'false' but vendor consent is 'true'. validateRules must return 'false'
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalse, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(false);
+
+ // case 4 - Both purpose consent and vendor consent is 'false'. validateRules must return 'false'
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalse, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(false);
+ });
+
+ it('should return true when enforcePurpose=true AND purposeConsent[p]==true AND enforceVendor[p,v]==false', function () {
+ // 'enforcePurpose' is 'true' and 'enforceVendor' is 'false'
+ const gdprRule = createGdprRule('storage', true, false, []);
+
+ // case 1 - Both purpose consent and vendor consent is 'true'. validateRules must return 'true'
+ let isAllowed = validateRules(gdprRule, consentData, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 2 - Purpose consent is 'true' but vendor consent is 'false'. validateRules must return 'true' because vendorConsent doens't matter
+ isAllowed = validateRules(gdprRule, consentData, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 3 - Purpose consent is 'false' but vendor consent is 'true'. validateRules must return 'false' because vendorConsent doesn't matter
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalse, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(false);
+
+ // case 4 - Both purpose consent and vendor consent is 'false'. validateRules must return 'false' and vendorConsent doesn't matter
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalse, vendorBlockedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(false);
+ });
+
+ it('should return true when enforcePurpose=false AND enforceVendor[p,v]==true AND vendorConsent[v]==true', function () {
+ // 'enforcePurpose' is 'false' and 'enforceVendor' is 'true'
+ const gdprRule = createGdprRule('storage', false, true, []);
+
+ // case 1 - Both purpose consent and vendor consent is 'true'. validateRules must return 'true'
+ let isAllowed = validateRules(gdprRule, consentData, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 2 - Purpose consent is 'true' but vendor consent is 'false'. validateRules must return 'false' because purposeConsent doesn't matter
+ isAllowed = validateRules(gdprRule, consentData, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(false);
+
+ // case 3 - urpose consent is 'false' but vendor consent is 'true'. validateRules must return 'true' because purposeConsent doesn't matter
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalse, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 4 - Both purpose consent and vendor consent is 'false'. validateRules must return 'false' and purposeConsent doesn't matter
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalse, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(false);
+ });
+
+ it('should return true when enforcePurpose=false AND enforceVendor[p,v]==false', function () {
+ // 'enforcePurpose' is 'false' and 'enforceVendor' is 'false'
+ const gdprRule = createGdprRule('storage', false, false, []);
+
+ // case 1 - Both purpose consent and vendor consent is 'true'. validateRules must return 'true', both the consents do not matter.
+ let isAllowed = validateRules(gdprRule, consentData, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 2 - Purpose consent is 'true' but vendor consent is 'false'. validateRules must return 'true', both the consents do not matter.
+ isAllowed = validateRules(gdprRule, consentData, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 3 - urpose consent is 'false' but vendor consent is 'true'. validateRules must return 'true', both the consents do not matter.
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalse, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 4 - Both purpose consent and vendor consent is 'false'. validateRules must return 'true', both the consents do not matter.
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalse, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(true);
+ });
+
+ it('should return true when "vendorExceptions" contains the name of the vendor under test', function () {
+ // 'vendorExceptions' contains 'bidderB' which doesn't have vendor consent.
+ const gdprRule = createGdprRule('storage', false, true, [vendorBlockedModule]);
+
+ /* 'bidderB' gets a free pass since it's included in the 'vendorExceptions' array. validateRules must disregard
+ user's choice for purpose and vendor consent and return 'true' for this bidder(s) */
+ const isAllowed = validateRules(gdprRule, consentData, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(true);
+ });
+
+ describe('Purpose 2 special case', function () {
+ const consentDataWithLIFalse = utils.deepClone(consentData);
+ consentDataWithLIFalse.vendorData.purpose.legitimateInterests['2'] = false;
+
+ const consentDataWithPurposeConsentFalse = utils.deepClone(consentData);
+ consentDataWithPurposeConsentFalse.vendorData.purpose.consents['2'] = false;
+
+ const consentDataWithPurposeConsentFalseAndLIFalse = utils.deepClone(consentData);
+ consentDataWithPurposeConsentFalseAndLIFalse.vendorData.purpose.legitimateInterests['2'] = false;
+ consentDataWithPurposeConsentFalseAndLIFalse.vendorData.purpose.consents['2'] = false;
+
+ it('should return true when (enforcePurpose=true AND purposeConsent[p]===true AND enforceVendor[p.v]===true AND vendorConsent[v]===true) OR (purposesLITransparency[p]===true)', function () {
+ // both 'enforcePurpose' and 'enforceVendor' is 'true'
+ const gdprRule = createGdprRule('basicAds', true, true, []);
+
+ // case 1 - Both purpose consent and vendor consent is 'true', but legitimateInterests for purpose 2 is 'false'. validateRules must return 'true'.
+ let isAllowed = validateRules(gdprRule, consentDataWithLIFalse, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 2 - Purpose consent is 'true' but vendor consent is 'false', but legitimateInterests for purpose 2 is 'true'. validateRules must return 'true'.
+ isAllowed = validateRules(gdprRule, consentData, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 3 - Purpose consent is 'true' and vendor consent is 'true', as well as legitimateInterests for purpose 2 is 'true'. validateRules must return 'true'.
+ isAllowed = validateRules(gdprRule, consentData, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 4 - Purpose consent is 'true' and vendor consent is 'false', and legitimateInterests for purpose 2 is 'false'. validateRules must return 'false'.
+ isAllowed = validateRules(gdprRule, consentDataWithLIFalse, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(false);
+ });
+
+ it('should return true when (enforcePurpose=true AND purposeConsent[p]===true AND enforceVendor[p.v]===false) OR (purposesLITransparency[p]===true)', function () {
+ // 'enforcePurpose' is 'true' and 'enforceVendor' is 'false'
+ const gdprRule = createGdprRule('basicAds', true, false, []);
+
+ // case 1 - Purpose consent is 'true', vendor consent doesn't matter and legitimateInterests for purpose 2 is 'true'. validateRules must return 'true'.
+ let isAllowed = validateRules(gdprRule, consentData, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 2 - Purpose consent is 'false', vendor consent doesn't matter and legitimateInterests for purpose 2 is 'true'. validateRules must return 'true'.
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalse, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 3 - Purpose consent is 'false', vendor consent doesn't matter and legitimateInterests for purpose 2 is 'false'. validateRules must return 'false'.
+ isAllowed = validateRules(gdprRule, consentDataWithPurposeConsentFalseAndLIFalse, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(false);
+ });
+
+ it('should return true when (enforcePurpose=false AND enforceVendor[p,v]===true AND vendorConsent[v]===true) OR (purposesLITransparency[p]===true)', function () {
+ // 'enforcePurpose' is 'false' and 'enforceVendor' is 'true'
+ const gdprRule = createGdprRule('basicAds', false, true, []);
+
+ // case - 1 Vendor consent is 'true', purpose consent doesn't matter and legitimateInterests for purpose 2 is 'true'. validateRules must return 'true'.
+ let isAllowed = validateRules(gdprRule, consentData, vendorAllowedModule, vendorAllowedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 2 - Vendor consent is 'false', purpose consent doesn't matter and legitimateInterests for purpose 2 is 'true'. validateRules must return 'true'.
+ isAllowed = validateRules(gdprRule, consentData, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(true);
+
+ // case 3 - Vendor consent is 'false', purpose consent doesn't matter and legitimateInterests for purpose 2 is 'false'. validateRules must return 'false'.
+ isAllowed = validateRules(gdprRule, consentDataWithLIFalse, vendorBlockedModule, vendorBlockedGvlId);
+ expect(isAllowed).to.equal(false);
+ });
+ });
+ })
+
+ describe('setEnforcementConfig', function () {
+ let sandbox;
+ const DEFAULT_RULES = [{
+ purpose: 'storage',
+ enforcePurpose: true,
+ enforceVendor: true,
+ vendorExceptions: []
+ }, {
+ purpose: 'basicAds',
+ enforcePurpose: true,
+ enforceVendor: true,
+ vendorExceptions: []
+ }];
+ beforeEach(function () {
+ sandbox = sinon.createSandbox();
+ logWarnSpy = sandbox.spy(utils, 'logWarn');
+ });
+ afterEach(function () {
+ config.resetConfig();
+ sandbox.restore();
+ });
+
+ it('should enforce TCF2 Purpose1 and Purpose 2 if no "rules" found in the config', function () {
+ setEnforcementConfig({
+ gdpr: {
+ cmpApi: 'iab',
+ allowAuctionWithoutConsent: true,
+ timeout: 5000
+ }
+ });
+
+ expect(logWarnSpy.calledOnce).to.equal(true);
+ expect(enforcementRules).to.deep.equal(DEFAULT_RULES);
+ });
+
+ it('should enforce TCF2 Purpose 2 also if only Purpose 1 is defined in "rules"', function () {
+ const purpose1RuleDefinedInConfig = {
+ purpose: 'storage',
+ enforcePurpose: false,
+ enforceVendor: true,
+ vendorExceptions: ['bidderA']
+ }
+ setEnforcementConfig({
+ gdpr: {
+ rules: [purpose1RuleDefinedInConfig]
+ }
+ });
+
+ expect(purpose1Rule).to.deep.equal(purpose1RuleDefinedInConfig);
+ expect(purpose2Rule).to.deep.equal(DEFAULT_RULES[1]);
+ });
+
+ it('should enforce TCF2 Purpose 1 also if only Purpose 2 is defined in "rules"', function () {
+ const purpose2RuleDefinedInConfig = {
+ purpose: 'basicAds',
+ enforcePurpose: false,
+ enforceVendor: true,
+ vendorExceptions: ['bidderA']
+ }
+ setEnforcementConfig({
+ gdpr: {
+ rules: [purpose2RuleDefinedInConfig]
}
+ });
+
+ expect(purpose1Rule).to.deep.equal(DEFAULT_RULES[0]);
+ expect(purpose2Rule).to.deep.equal(purpose2RuleDefinedInConfig);
+ });
+
+ it('should use the "rules" defined in config if a definition found', function() {
+ const rules = [{
+ purpose: 'storage',
+ enforcePurpose: false,
+ enforceVendor: false
+ }, {
+ purpose: 'basicAds',
+ enforcePurpose: false,
+ enforceVendor: false
}]
- expect(nextFnSpy.calledWith(undefined, expectedSubmodules, consentData));
+ setEnforcementConfig({gdpr: { rules }});
+
+ expect(enforcementRules).to.deep.equal(rules);
});
});
});
diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js
index b2b8885a2f8..63b04077f4e 100644
--- a/test/spec/modules/ixBidAdapter_spec.js
+++ b/test/spec/modules/ixBidAdapter_spec.js
@@ -110,6 +110,35 @@ describe('IndexexchangeAdapter', function () {
]
};
+ const DEFAULT_BANNER_BID_RESPONSE_WITHOUT_ADOMAIN = {
+ cur: 'USD',
+ id: '11a22b33c44d',
+ seatbid: [
+ {
+ bid: [
+ {
+ crid: '12345',
+ adid: '14851455',
+ impid: '1a2b3c4d',
+ cid: '3051266',
+ price: 100,
+ w: 300,
+ h: 250,
+ id: '1',
+ ext: {
+ dspid: 50,
+ pricelevel: '_100',
+ advbrandid: 303325,
+ advbrand: 'OECTA'
+ },
+ adm: ''
+ }
+ ],
+ seat: '3970'
+ }
+ ]
+ };
+
const DEFAULT_VIDEO_BID_RESPONSE = {
cur: 'USD',
id: '1aa2bb3cc4de',
@@ -1102,7 +1131,8 @@ describe('IndexexchangeAdapter', function () {
meta: {
networkId: 50,
brandId: 303325,
- brandName: 'OECTA'
+ brandName: 'OECTA',
+ advertiserDomains: ['www.abc.com']
}
}
];
@@ -1110,6 +1140,31 @@ describe('IndexexchangeAdapter', function () {
expect(result[0]).to.deep.equal(expectedParse[0]);
});
+ it('should get correct bid response for banner ad with missing adomain', function () {
+ const expectedParse = [
+ {
+ requestId: '1a2b3c4d',
+ cpm: 1,
+ creativeId: '12345',
+ width: 300,
+ height: 250,
+ mediaType: 'banner',
+ ad: '
',
+ currency: 'USD',
+ ttl: 300,
+ netRevenue: true,
+ dealId: undefined,
+ meta: {
+ networkId: 50,
+ brandId: 303325,
+ brandName: 'OECTA'
+ }
+ }
+ ];
+ const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE_WITHOUT_ADOMAIN }, { data: DEFAULT_BIDDER_REQUEST_DATA });
+ expect(result[0]).to.deep.equal(expectedParse[0]);
+ });
+
it('should set creativeId to default value if not provided', function () {
const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE);
delete bidResponse.seatbid[0].bid[0].crid;
@@ -1129,7 +1184,8 @@ describe('IndexexchangeAdapter', function () {
meta: {
networkId: 50,
brandId: 303325,
- brandName: 'OECTA'
+ brandName: 'OECTA',
+ advertiserDomains: ['www.abc.com']
}
}
];
@@ -1155,7 +1211,8 @@ describe('IndexexchangeAdapter', function () {
meta: {
networkId: 50,
brandId: 303325,
- brandName: 'OECTA'
+ brandName: 'OECTA',
+ advertiserDomains: ['www.abc.com']
}
}
];
@@ -1182,7 +1239,8 @@ describe('IndexexchangeAdapter', function () {
meta: {
networkId: 50,
brandId: 303325,
- brandName: 'OECTA'
+ brandName: 'OECTA',
+ advertiserDomains: ['www.abc.com']
}
}
];
@@ -1207,7 +1265,8 @@ describe('IndexexchangeAdapter', function () {
meta: {
networkId: 51,
brandId: 303326,
- brandName: 'OECTB'
+ brandName: 'OECTB',
+ advertiserDomains: ['www.abcd.com']
}
}
];
diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js
index 294ada6f988..58e607ebb89 100644
--- a/test/spec/modules/prebidServerBidAdapter_spec.js
+++ b/test/spec/modules/prebidServerBidAdapter_spec.js
@@ -712,40 +712,6 @@ describe('S2S Adapter', function () {
});
});
- it('adds digitrust id is present and user is not optout', function () {
- let ortb2Config = utils.deepClone(CONFIG);
- ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction';
-
- let consentConfig = { s2sConfig: ortb2Config };
- config.setConfig(consentConfig);
-
- let digiTrustObj = {
- privacy: {
- optout: false
- },
- id: 'testId',
- keyv: 'testKeyV'
- };
-
- let digiTrustBidRequest = utils.deepClone(BID_REQUESTS);
- digiTrustBidRequest[0].bids[0].userId = { digitrustid: { data: digiTrustObj } };
-
- adapter.callBids(REQUEST, digiTrustBidRequest, addBidResponse, done, ajax);
- let requestBid = JSON.parse(server.requests[0].requestBody);
-
- expect(requestBid.user.ext.digitrust).to.deep.equal({
- id: digiTrustObj.id,
- keyv: digiTrustObj.keyv
- });
-
- digiTrustObj.privacy.optout = true;
-
- adapter.callBids(REQUEST, digiTrustBidRequest, addBidResponse, done, ajax);
- requestBid = JSON.parse(server.requests[1].requestBody);
-
- expect(requestBid.user && request.user.ext && requestBid.user.ext.digitrust).to.not.exist;
- });
-
it('adds device and app objects to request', function () {
const _config = {
s2sConfig: CONFIG,
diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js
index abc440ac8ea..1e8ab8f9faf 100644
--- a/test/spec/modules/pubmaticBidAdapter_spec.js
+++ b/test/spec/modules/pubmaticBidAdapter_spec.js
@@ -2302,6 +2302,7 @@ describe('PubMatic adapter', function () {
expect(response[0].adserverTargeting.hb_buyid_pubmatic).to.equal('BUYER-ID-987');
expect(response[0].meta.buyerId).to.equal(976);
expect(response[0].meta.clickUrl).to.equal('blackrock.com');
+ expect(response[0].meta.advertiserDomains[0]).to.equal('blackrock.com');
expect(response[0].referrer).to.include(data.site.ref);
expect(response[0].ad).to.equal(bidResponses.body.seatbid[0].bid[0].adm);
expect(response[0].pm_seat).to.equal(bidResponses.body.seatbid[0].seat);
@@ -2325,6 +2326,7 @@ describe('PubMatic adapter', function () {
expect(response[1].adserverTargeting.hb_buyid_pubmatic).to.equal('BUYER-ID-789');
expect(response[1].meta.buyerId).to.equal(832);
expect(response[1].meta.clickUrl).to.equal('hivehome.com');
+ expect(response[1].meta.advertiserDomains[0]).to.equal('hivehome.com');
expect(response[1].referrer).to.include(data.site.ref);
expect(response[1].ad).to.equal(bidResponses.body.seatbid[1].bid[0].adm);
expect(response[1].pm_seat).to.equal(bidResponses.body.seatbid[1].seat || null);
diff --git a/test/spec/modules/quantumBidAdapter_spec.js b/test/spec/modules/quantumBidAdapter_spec.js
deleted file mode 100644
index c03d74ea52e..00000000000
--- a/test/spec/modules/quantumBidAdapter_spec.js
+++ /dev/null
@@ -1,325 +0,0 @@
-import { expect } from 'chai'
-import { spec } from 'modules/quantumBidAdapter.js'
-import { newBidder } from 'src/adapters/bidderFactory.js'
-
-const ENDPOINT = 'https://s.sspqns.com/hb'
-const REQUEST = {
- 'bidder': 'quantum',
- 'sizes': [[300, 250]],
- 'renderMode': 'banner',
- 'params': {
- placementId: 21546
- }
-}
-
-const NATIVE_REQUEST = {
- 'bidder': 'quantum',
- 'mediaType': 'native',
- 'sizes': [[0, 0]],
- 'params': {
- placementId: 21546
- }
-}
-
-const serverResponse = {
- 'price': 0.3,
- 'debug': [
- ''
- ],
- 'is_fallback': false,
- 'nurl': 'https://s.sspqns.com/imp/KpQ1WNMHV-9a3HqWL_0JnujJFGo1Hnx9RS3FT_Yy8jW-Z6t_PJYmP2otidJsxE3qcY2EozzcBjRzGM7HEQcxVnjOzq0Th1cxb6A5bSp5BizTwY5SRaxx_0PgF6--8LqaF4LMUgMmhfF5k3gOOzzK6gKdavia4_w3LJ1CRWkMEwABr8bPzeovy1y4MOZsOXv7vXjPGMKJSTgphuZR57fL4u4ZFF4XY70K_TaH5bfXHMRAzE0Q38tfpTvbdFV_u2g-FoF0gjzKjiS88VnetT-Jo3qtrMphWzr52jsg5tH3L7hbymUOm1YkuJP9xrXLoZNVgC5sTMYolKLMSu6dqhS2FXcdfaGAcHweaaAAwJq-pB7DuiVcdnZQphUymhIia_KG2AYweWp6TYEpJbJjf2BcLpm_-KGw4gLh6L3DtEvUZwXZe-JpUJ4/',
- 'native': {
- 'link': {
- 'url': 'https://s.sspqns.com/click/KpQ1WNMHV-9a3HqWL_0JnujJFGo1Hnx9RS3FT_Yy8jW-Z6t_PJYmP2otidJsxE3qcY2EozzcBjRzGM7HEQcxVnjOzq0Th1cxb6A5bSp5BizTwY5SRaxx_0PgF6--8LqaF4LMUgMmhfF5k3gOOzzK6gKdavia4_w3LJ1CRWkMEwABr8bPzeovy1y4MOZsOXv7vXjPGMKJSTgphuZR57fL4u4ZFF4XY70K_TaH5bfXHMRAzE0Q38tfpTvbdFV_u2g-FoF0gjzKjiS88VnetT-Jo3qtrMphWzr52jsg5tH3L7hbymUOm1YkuJP9xrXLoZNVgC5sTMYolKLMSu6dqhS2FXcdfaGAcHweaaAAwJq-pB7DuiVcdnZQphUymhIia_KG2AYweWp6TYEpJbJjf2BcLpm_-KGw4gLh6L3DtEvUZwXZe-JpUJ4///',
- 'clicktrackers': ['https://elasticad.net']
- },
- 'assets': [
- {
- 'id': 1,
- 'title': {
- 'text': 'ad.SSP.1x1'
- },
- 'required': 1
- },
- {
- 'id': 2,
- 'img': {
- 'w': 15,
- 'h': 15,
- 'url': 'https://files.ssp.theadtech.com.s3.amazonaws.com/media/image/sxjermpz/scalecrop-15x15'
- }
- },
- {
- 'id': 3,
- 'data': {
- 'value': 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum is simply dummy text of the printing and typesetting industry.'
- },
- 'required': 1
- },
- {
- 'id': 4,
- 'img': {
- 'w': 500,
- 'h': 500,
- 'url': 'https://files.ssp.theadtech.com.s3.amazonaws.com/media/image/sxjermpz/scalecrop-500x500'
- }
- },
- {
- 'id': 6,
- 'video': {
- 'vasttag': 'https://elasticad.net/vast.xml'
- }
- },
- {
- 'id': 2001,
- 'data': {
- 'value': 'https://elasticad.net'
- }
- },
- {
- 'id': 2002,
- 'data': {
- 'value': 'vast'
- }
- },
- {
- 'id': 2007,
- 'data': {
- 'value': 'click'
- }
- },
- {
- 'id': 10,
- 'data': {
- 'value': 'ad.SSP.1x1 sponsor'
- }
- },
- {
- 'id': 2003,
- 'data': {
- 'value': 'https://elasticad.net'
- }
- },
- {
- 'id': 2004,
- 'data': {
- 'value': 'prism'
- }
- },
- {
- 'id': 2005,
- 'data': {
- 'value': '/home'
- }
- },
- {
- 'id': 2006,
- 'data': {
- 'value': 'https://elasticad.net/vast.xml'
- }
- },
- {
- 'id': 2022,
- 'data': {
- 'value': 'Lorem ipsum....'
- }
- }
- ],
- 'imptrackers': [],
- 'ver': '1.1'
- },
- 'sync': [
- 'https://match.adsrvr.org/track/cmb/generic?ttd_pid=s6e8ued&ttd_tpi=1'
- ]
-}
-
-const nativeServerResponse = {
- 'price': 0.3,
- 'debug': [
- ''
- ],
- 'is_fallback': false,
- 'nurl': 'https://s.sspqns.com/imp/KpQ1WNMHV-9a3HqWL_0JnujJFGo1Hnx9RS3FT_Yy8jW-Z6t_PJYmP2otidJsxE3qcY2EozzcBjRzGM7HEQcxVnjOzq0Th1cxb6A5bSp5BizTwY5SRaxx_0PgF6--8LqaF4LMUgMmhfF5k3gOOzzK6gKdavia4_w3LJ1CRWkMEwABr8bPzeovy1y4MOZsOXv7vXjPGMKJSTgphuZR57fL4u4ZFF4XY70K_TaH5bfXHMRAzE0Q38tfpTvbdFV_u2g-FoF0gjzKjiS88VnetT-Jo3qtrMphWzr52jsg5tH3L7hbymUOm1YkuJP9xrXLoZNVgC5sTMYolKLMSu6dqhS2FXcdfaGAcHweaaAAwJq-pB7DuiVcdnZQphUymhIia_KG2AYweWp6TYEpJbJjf2BcLpm_-KGw4gLh6L3DtEvUZwXZe-JpUJ4/',
- 'native': {
- 'link': {
- 'url': 'https://s.sspqns.com/click/KpQ1WNMHV-9a3HqWL_0JnujJFGo1Hnx9RS3FT_Yy8jW-Z6t_PJYmP2otidJsxE3qcY2EozzcBjRzGM7HEQcxVnjOzq0Th1cxb6A5bSp5BizTwY5SRaxx_0PgF6--8LqaF4LMUgMmhfF5k3gOOzzK6gKdavia4_w3LJ1CRWkMEwABr8bPzeovy1y4MOZsOXv7vXjPGMKJSTgphuZR57fL4u4ZFF4XY70K_TaH5bfXHMRAzE0Q38tfpTvbdFV_u2g-FoF0gjzKjiS88VnetT-Jo3qtrMphWzr52jsg5tH3L7hbymUOm1YkuJP9xrXLoZNVgC5sTMYolKLMSu6dqhS2FXcdfaGAcHweaaAAwJq-pB7DuiVcdnZQphUymhIia_KG2AYweWp6TYEpJbJjf2BcLpm_-KGw4gLh6L3DtEvUZwXZe-JpUJ4///'
- },
- 'assets': [
- {
- 'id': 1,
- 'title': {
- 'text': 'ad.SSP.1x1'
- },
- 'required': 1
- },
- {
- 'id': 2,
- 'img': {
- 'w': 15,
- 'h': 15,
- 'url': 'https://files.ssp.theadtech.com.s3.amazonaws.com/media/image/sxjermpz/scalecrop-15x15'
- }
- },
- {
- 'id': 3,
- 'data': {
- 'value': 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum is simply dummy text of the printing and typesetting industry.'
- },
- 'required': 1
- },
- {
- 'id': 4,
- 'img': {
- 'w': 500,
- 'h': 500,
- 'url': 'https://files.ssp.theadtech.com.s3.amazonaws.com/media/image/sxjermpz/scalecrop-500x500'
- }
- },
- {
- 'id': 2007,
- 'data': {
- 'value': 'click'
- }
- },
- {
- 'id': 10,
- 'data': {
- 'value': 'ad.SSP.1x1 sponsor'
- }
- },
-
- {
- 'id': 2003,
- 'data': {
- 'value': 'https://elasticad.net'
- }
- }
- ],
- 'imptrackers': [],
- 'ver': '1.1'
- },
- 'sync': [
- 'https://match.adsrvr.org/track/cmb/generic?ttd_pid=s6e8ued&ttd_tpi=1'
- ]
-}
-
-describe('quantumBidAdapter', function () {
- const adapter = newBidder(spec)
-
- describe('inherited functions', function () {
- it('exists and is a function', function () {
- expect(adapter.callBids).to.exist.and.to.be.a('function')
- })
- })
-
- describe('isBidRequestValid', function () {
- it('should return true when required params found', function () {
- expect(spec.isBidRequestValid(REQUEST)).to.equal(true)
- })
-
- it('should return false when required params are not passed', function () {
- let bid = Object.assign({}, REQUEST)
- delete bid.params
- expect(spec.isBidRequestValid(bid)).to.equal(false)
- })
- })
-
- describe('buildRequests', function () {
- let bidRequests = [REQUEST]
-
- const request = spec.buildRequests(bidRequests, {})
-
- it('sends bid request to ENDPOINT via GET', function () {
- expect(request[0].method).to.equal('GET')
- })
- })
-
- describe('GDPR conformity', function () {
- const bidRequests = [{
- 'bidder': 'quantum',
- 'mediaType': 'native',
- 'params': {
- placementId: 21546
- },
- adUnitCode: 'aaa',
- transactionId: '2b8389fe-615c-482d-9f1a-376fb8f7d6b0',
- sizes: [[0, 0]],
- bidId: '1abgs362e0x48a8',
- bidderRequestId: '70deaff71c281d',
- auctionId: '5c66da22-426a-4bac-b153-77360bef5337'
- }];
-
- const bidderRequest = {
- gdprConsent: {
- consentString: 'awefasdfwefasdfasd',
- gdprApplies: true
- }
- };
-
- it('should transmit correct data', function () {
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- expect(requests.length).to.equal(1);
- expect(requests[0].data.quantx_gdpr).to.equal(1);
- expect(requests[0].data.quantx_user_consent_string).to.equal('awefasdfwefasdfasd');
- });
- });
-
- describe('GDPR absence conformity', function () {
- const bidRequests = [{
- 'bidder': 'quantum',
- 'mediaType': 'native',
- 'params': {
- placementId: 21546
- },
- adUnitCode: 'aaa',
- transactionId: '2b8389fe-615c-482d-9f1a-376fb8f7d6b0',
- sizes: [[0, 0]],
- bidId: '1abgs362e0x48a8',
- bidderRequestId: '70deaff71c281d',
- auctionId: '5c66da22-426a-4bac-b153-77360bef5337'
- }];
-
- const bidderRequest = {
- gdprConsent: undefined
- };
-
- it('should transmit correct data', function () {
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- expect(requests.length).to.equal(1);
- expect(requests[0].data.quantx_gdpr).to.be.undefined;
- expect(requests[0].data.quantx_user_consent_string).to.be.undefined;
- });
- });
-
- describe('interpretResponse', function () {
- let bidderRequest = {
- bidderCode: 'bidderCode',
- bids: []
- }
-
- it('handles native request : should get correct bid response', function () {
- const result = spec.interpretResponse({body: nativeServerResponse}, NATIVE_REQUEST)
- expect(result[0]).to.have.property('cpm').equal(0.3)
- expect(result[0]).to.have.property('width').to.be.below(2)
- expect(result[0]).to.have.property('height').to.be.below(2)
- expect(result[0]).to.have.property('mediaType').equal('native')
- expect(result[0]).to.have.property('native')
- })
-
- it('should get correct bid response', function () {
- const result = spec.interpretResponse({body: serverResponse}, REQUEST)
- expect(result[0]).to.have.property('cpm').equal(0.3)
- expect(result[0]).to.have.property('width').equal(300)
- expect(result[0]).to.have.property('height').equal(250)
- expect(result[0]).to.have.property('mediaType').equal('banner')
- expect(result[0]).to.have.property('ad')
- })
-
- it('handles nobid responses', function () {
- const nobidServerResponse = {bids: []}
- const nobidResult = spec.interpretResponse({body: nobidServerResponse}, bidderRequest)
- // console.log(nobidResult)
- expect(nobidResult.length).to.equal(0)
- })
- })
-})
diff --git a/test/spec/modules/spotxBidAdapter_spec.js b/test/spec/modules/spotxBidAdapter_spec.js
index 78d17f35c69..94cc335fd8e 100644
--- a/test/spec/modules/spotxBidAdapter_spec.js
+++ b/test/spec/modules/spotxBidAdapter_spec.js
@@ -381,6 +381,7 @@ describe('the spotx adapter', function () {
impid: 123,
cur: 'USD',
price: 12,
+ adomain: ['abc.com'],
crid: 321,
w: 400,
h: 300,
@@ -392,6 +393,7 @@ describe('the spotx adapter', function () {
impid: 124,
cur: 'USD',
price: 13,
+ adomain: ['def.com'],
w: 200,
h: 100,
ext: {
@@ -409,6 +411,7 @@ describe('the spotx adapter', function () {
expect(responses).to.be.an('array').with.length(2);
expect(responses[0].cache_key).to.equal('cache123');
expect(responses[0].channel_id).to.equal(12345);
+ expect(responses[0].meta.advertiserDomains[0]).to.equal('abc.com');
expect(responses[0].cpm).to.equal(12);
expect(responses[0].creativeId).to.equal(321);
expect(responses[0].currency).to.equal('USD');
@@ -423,6 +426,7 @@ describe('the spotx adapter', function () {
expect(responses[1].cache_key).to.equal('cache124');
expect(responses[1].channel_id).to.equal(12345);
expect(responses[1].cpm).to.equal(13);
+ expect(responses[1].meta.advertiserDomains[0]).to.equal('def.com');
expect(responses[1].creativeId).to.equal('');
expect(responses[1].currency).to.equal('USD');
expect(responses[1].height).to.equal(100);
diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js
index 9e4098d7854..25649115cc1 100644
--- a/test/spec/modules/telariaBidAdapter_spec.js
+++ b/test/spec/modules/telariaBidAdapter_spec.js
@@ -236,7 +236,7 @@ describe('TelariaAdapter', () => {
it('should get correct bid response', () => {
let expectedResponseKeys = ['bidderCode', 'width', 'height', 'statusMessage', 'adId', 'mediaType', 'source',
'getStatusCode', 'getSize', 'requestId', 'cpm', 'creativeId', 'vastXml',
- 'vastUrl', 'currency', 'netRevenue', 'ttl', 'ad'];
+ 'vastUrl', 'currency', 'netRevenue', 'ttl', 'ad', 'meta'];
let bidRequest = spec.buildRequests(stub, BIDDER_REQUEST)[0];
bidRequest.bidId = '1234';
diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js
index d038074cb10..a0b7d68bcce 100644
--- a/test/spec/modules/userId_spec.js
+++ b/test/spec/modules/userId_spec.js
@@ -5,7 +5,8 @@ import {
requestBidsHook,
setSubmoduleRegistry,
syncDelay,
- coreStorage
+ coreStorage,
+ setStoredValue
} from 'modules/userId/index.js';
import {createEidsArray} from 'modules/userId/eids.js';
import {config} from 'src/config.js';
@@ -660,7 +661,7 @@ describe('User ID', function() {
it('does not delay auction if there are no ids to fetch', function() {
coreStorage.getCookie.withArgs('MOCKID').returns('123456778');
config.setConfig({
- usersync: {
+ userSync: {
auctionDelay: 33,
syncDelay: 77,
userIds: [{
@@ -1443,4 +1444,45 @@ describe('User ID', function() {
expect(server.requests[0].url).to.equal('https://match.adsrvr.org/track/rid?ttd_pid=rubicon&fmt=json');
});
});
+
+ describe('Set cookie behavior', function() {
+ let coreStorageSpy;
+ beforeEach(function() {
+ coreStorageSpy = sinon.spy(coreStorage, 'setCookie');
+ });
+ afterEach(function() {
+ coreStorageSpy.restore();
+ });
+ it('should allow submodules to override the domain', function () {
+ const submodule = {
+ submodule: {
+ domainOverride: function() {
+ return 'foo.com'
+ }
+ },
+ config: {
+ storage: {
+ type: 'cookie'
+ }
+ }
+ }
+ setStoredValue(submodule, 'bar');
+ expect(coreStorage.setCookie.getCall(0).args[4]).to.equal('foo.com');
+ });
+
+ it('should pass null for domain if submodule does not override the domain', function () {
+ const submodule = {
+ submodule: {
+
+ },
+ config: {
+ storage: {
+ type: 'cookie'
+ }
+ }
+ }
+ setStoredValue(submodule, 'bar');
+ expect(coreStorage.setCookie.getCall(0).args[4]).to.equal(null);
+ });
+ });
});
diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js
index cab0655a29d..692cf9a6475 100644
--- a/test/spec/unit/core/bidderFactory_spec.js
+++ b/test/spec/unit/core/bidderFactory_spec.js
@@ -401,8 +401,12 @@ describe('bidders created by newBidder', function () {
adUnitCode: 'mock/placement',
currency: 'USD',
netRevenue: true,
- ttl: 300
+ ttl: 300,
+ bidderCode: 'sampleBidder',
+ sampleBidder: {advertiserId: '12345', networkId: '111222'}
};
+ const bidderRequest = Object.assign({}, MOCK_BIDS_REQUEST);
+ bidderRequest.bids[0].bidder = 'sampleBidder';
spec.isBidRequestValid.returns(true);
spec.buildRequests.returns({
method: 'POST',
@@ -413,7 +417,7 @@ describe('bidders created by newBidder', function () {
spec.interpretResponse.returns(bid);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ bidder.callBids(bidderRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
expect(addBidResponseStub.calledOnce).to.equal(true);
expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
@@ -423,6 +427,8 @@ describe('bidders created by newBidder', function () {
expect(bidObject.originalCurrency).to.equal(bid.currency);
expect(doneStub.calledOnce).to.equal(true);
expect(logErrorSpy.callCount).to.equal(0);
+ expect(bidObject.meta).to.exist;
+ expect(bidObject.meta).to.deep.equal({advertiserId: '12345', networkId: '111222'});
});
it('should call spec.getUserSyncs() with the response', function () {
@@ -645,6 +651,28 @@ describe('registerBidder', function () {
expect(registerBidAdapterStub.secondCall.args[1]).to.equal('foo')
expect(registerBidAdapterStub.thirdCall.args[1]).to.equal('bar')
});
+
+ it('should register alias with their gvlid', function() {
+ const aliases = [
+ {
+ code: 'foo',
+ gvlid: 1
+ },
+ {
+ code: 'bar',
+ gvlid: 2
+ },
+ {
+ code: 'baz'
+ }
+ ]
+ const thisSpec = Object.assign(newEmptySpec(), { aliases: aliases });
+ registerBidder(thisSpec);
+
+ expect(registerBidAdapterStub.getCall(1).args[0].getSpec().gvlid).to.equal(1);
+ expect(registerBidAdapterStub.getCall(2).args[0].getSpec().gvlid).to.equal(2);
+ expect(registerBidAdapterStub.getCall(3).args[0].getSpec().gvlid).to.equal(undefined);
+ })
})
describe('validate bid response: ', function () {