+
+
+
+ ]]>
+
+
+
ES
+
+
+ `;
+ let serverResponse = {
+ 'body': xmlStr1,
+ }
+ const bidResponses = spec.interpretResponse(serverResponse, bidRequest);
+ expect(bidResponses.length).to.equal(0);
+ })
+ it('It should return a banner ad.', () => {
+ let serverResponse = {
+ 'body': xmlStr,
+ }
+ setCurrentURL('https://www.sports.com');
+ const bidResponses = spec.interpretResponse(serverResponse, bidRequest);
+ expect(bidResponses.length).greaterThan(0);
+ expect(bidResponses[0].mediaType).to.be.equal(BANNER);
+ expect(bidResponses[0].ad).not.to.be.null;
+ })
+ it('It should return a video ad.', () => {
+ let serverResponse = {
+ 'body': xmlStr,
+ }
+ setCurrentURL('https://www.sports.com');
+ bidRequest.bidRequest.mediaTypes = {
+ video: {
+ sizes: [
+ [300, 250],
+ [300, 600]
+ ]
+ }
+ }
+ const bidResponses = spec.interpretResponse(serverResponse, bidRequest);
+ expect(bidResponses.length).greaterThan(0);
+ expect(bidResponses[0].mediaType).to.be.equal(VIDEO);
+ expect(bidResponses[0].vastUrl).not.to.be.null;
+ })
+ });
+});
diff --git a/test/spec/modules/amxBidAdapter_spec.js b/test/spec/modules/amxBidAdapter_spec.js
index 984c443344d..21fa2e2617c 100644
--- a/test/spec/modules/amxBidAdapter_spec.js
+++ b/test/spec/modules/amxBidAdapter_spec.js
@@ -3,6 +3,7 @@ import { spec } from 'modules/amxBidAdapter.js';
import { createEidsArray } from 'modules/userId/eids.js';
import { BANNER, VIDEO } from 'src/mediaTypes.js';
import { config } from 'src/config.js';
+import { server } from 'test/mocks/xhr.js';
import * as utils from 'src/utils.js';
const sampleRequestId = '82c91e127a9b93e';
@@ -11,7 +12,7 @@ const sampleDisplayCRID = '78827819';
// minimal example vast
const sampleVideoAd = (addlImpression) =>
`
-
00:00:15${addlImpression}
+
00:00:15${addlImpression}
`.replace(/\n+/g, '');
const sampleFPD = {
@@ -37,7 +38,7 @@ const sampleBidderRequest = {
},
gppConsent: {
gppString: 'example',
- applicableSections: 'example'
+ applicableSections: 'example',
},
auctionId: null,
@@ -209,10 +210,12 @@ describe('AmxBidAdapter', () => {
describe('getUserSync', () => {
it('Will perform an iframe sync even if there is no server response..', () => {
const syncs = spec.getUserSyncs({ iframeEnabled: true });
- expect(syncs).to.eql([{
- type: 'iframe',
- url: 'https://prebid.a-mo.net/isyn?gdpr_consent=&gdpr=0&us_privacy=&gpp=&gpp_sid='
- }]);
+ expect(syncs).to.eql([
+ {
+ type: 'iframe',
+ url: 'https://prebid.a-mo.net/isyn?gdpr_consent=&gdpr=0&us_privacy=&gpp=&gpp_sid=',
+ },
+ ]);
});
it('will return valid syncs from a server response', () => {
@@ -276,8 +279,13 @@ describe('AmxBidAdapter', () => {
});
it('will attach additional referrer info data', () => {
- const { data } = spec.buildRequests([sampleBidRequestBase], sampleBidderRequest);
- expect(data.ri.r).to.equal(sampleBidderRequest.refererInfo.topmostLocation);
+ const { data } = spec.buildRequests(
+ [sampleBidRequestBase],
+ sampleBidderRequest
+ );
+ expect(data.ri.r).to.equal(
+ sampleBidderRequest.refererInfo.topmostLocation
+ );
expect(data.ri.t).to.equal(sampleBidderRequest.refererInfo.reachedTop);
expect(data.ri.l).to.equal(sampleBidderRequest.refererInfo.numIframes);
expect(data.ri.s).to.equal(sampleBidderRequest.refererInfo.stack);
@@ -315,7 +323,7 @@ describe('AmxBidAdapter', () => {
[sampleBidRequestBase],
sampleBidderRequest
);
- delete data.m; // don't deal with "m" in this test
+ delete data.m; // don't deal with 'm' in this test
expect(data.gs).to.equal(sampleBidderRequest.gdprConsent.gdprApplies);
expect(data.gc).to.equal(sampleBidderRequest.gdprConsent.consentString);
expect(data.usp).to.equal(sampleBidderRequest.uspConsent);
@@ -343,10 +351,8 @@ describe('AmxBidAdapter', () => {
});
it('will attach sync configuration', () => {
- const request = () => spec.buildRequests(
- [sampleBidRequestBase],
- sampleBidderRequest
- );
+ const request = () =>
+ spec.buildRequests([sampleBidRequestBase], sampleBidderRequest);
const setConfig = (filterSettings) =>
config.setConfig({
@@ -355,56 +361,73 @@ describe('AmxBidAdapter', () => {
syncDelay: 2300,
syncEnabled: true,
filterSettings,
- }
+ },
});
const test = (filterSettings) => {
setConfig(filterSettings);
return request().data.sync;
- }
+ };
const base = { d: 2300, l: 2, e: true };
- const tests = [[
- undefined,
- { ...base, t: 0 }
- ], [{
- image: {
- bidders: '*',
- filter: 'include'
- },
- iframe: {
- bidders: '*',
- filter: 'include'
- }
- }, { ...base, t: 3 }], [{
- image: {
- bidders: ['amx'],
- },
- iframe: {
- bidders: '*',
- filter: 'include'
- }
- }, { ...base, t: 3 }], [{
- image: {
- bidders: ['other'],
- },
- iframe: {
- bidders: '*'
- }
- }, { ...base, t: 2 }], [{
- image: {
- bidders: ['amx']
- },
- iframe: {
- bidders: ['amx'],
- filter: 'exclude'
- }
- }, { ...base, t: 1 }]]
+ const tests = [
+ [undefined, { ...base, t: 0 }],
+ [
+ {
+ image: {
+ bidders: '*',
+ filter: 'include',
+ },
+ iframe: {
+ bidders: '*',
+ filter: 'include',
+ },
+ },
+ { ...base, t: 3 },
+ ],
+ [
+ {
+ image: {
+ bidders: ['amx'],
+ },
+ iframe: {
+ bidders: '*',
+ filter: 'include',
+ },
+ },
+ { ...base, t: 3 },
+ ],
+ [
+ {
+ image: {
+ bidders: ['other'],
+ },
+ iframe: {
+ bidders: '*',
+ },
+ },
+ { ...base, t: 2 },
+ ],
+ [
+ {
+ image: {
+ bidders: ['amx'],
+ },
+ iframe: {
+ bidders: ['amx'],
+ filter: 'exclude',
+ },
+ },
+ { ...base, t: 1 },
+ ],
+ ];
for (let i = 0, l = tests.length; i < l; i++) {
const [result, expected] = tests[i];
- expect(test(result), `input: ${JSON.stringify(result)}`).to.deep.equal(expected);
+ expect(test(result), `input: ${JSON.stringify(result)}`).to.deep.equal(
+ expected
+ );
}
});
@@ -497,7 +520,15 @@ describe('AmxBidAdapter', () => {
it('can build a video request', () => {
const { data } = spec.buildRequests(
- [{ ...sampleBidRequestVideo, params: { ...sampleBidRequestVideo.params, adUnitId: 'custom-auid' } }],
+ [
+ {
+ ...sampleBidRequestVideo,
+ params: {
+ ...sampleBidRequestVideo.params,
+ adUnitId: 'custom-auid',
+ },
+ },
+ ],
sampleBidderRequest
);
expect(Object.keys(data.m).length).to.equal(1);
@@ -659,15 +690,49 @@ describe('AmxBidAdapter', () => {
});
it('will log an event for timeout', () => {
- spec.onTimeout({
- bidder: 'example',
- bidId: 'test-bid-id',
- adUnitCode: 'div-gpt-ad',
- timeout: 300,
- auctionId: utils.getUniqueIdentifierStr(),
+ // this will use sendBeacon..
+ spec.onTimeout([
+ {
+ bidder: 'example',
+ bidId: 'test-bid-id',
+ adUnitCode: 'div-gpt-ad',
+ ortb2: {
+ site: {
+ ref: 'https://example.com',
+ },
+ },
+ params: {
+ tagId: 'tag-id',
+ },
+ timeout: 300,
+ auctionId: utils.getUniqueIdentifierStr(),
+ },
+ ]);
+
+ const [request] = server.requests;
+ request.respond(204, {'Content-Type': 'text/html'}, null);
+ expect(request.url).to.equal('https://1x1.a-mo.net/e');
+
+ if (typeof Request !== 'undefined' && 'keepalive' in Request.prototype) {
+ expect(request.fetch.request.keepalive).to.equal(true);
+ }
+
+ const {c: common, e: events} = JSON.parse(request.requestBody)
+ expect(common).to.deep.equal({
+ V: '$prebid.version$',
+ vg: '$$PREBID_GLOBAL$$',
+ U: null,
+ re: 'https://example.com',
});
- expect(firedPixels.length).to.equal(1);
- expect(firedPixels[0]).to.match(/\/hbx\/g_pbto/);
+
+ expect(events.length).to.equal(1);
+ const [event] = events;
+ expect(event.n).to.equal('g_pbto')
+ expect(event.A).to.equal('example');
+ expect(event.mid).to.equal('tag-id');
+ expect(event.cn).to.equal(300);
+ expect(event.bid).to.equal('test-bid-id');
+ expect(event.a).to.equal('div-gpt-ad');
});
it('will log an event for prebid win', () => {
diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js
index 193e8aa64f8..cf6a1704bde 100644
--- a/test/spec/modules/appnexusBidAdapter_spec.js
+++ b/test/spec/modules/appnexusBidAdapter_spec.js
@@ -1204,6 +1204,46 @@ describe('AppNexusAdapter', function () {
expect(payload.privacy.gpp_sid).to.deep.equal([7]);
});
+ it('should add dsa information to the request via bidderRequest.ortb2.regs.ext.dsa', function () {
+ let bidderRequest = {
+ 'bidderCode': 'appnexus',
+ 'auctionId': '1d1a030790a475',
+ 'bidderRequestId': '22edbae2733bf6',
+ 'timeout': 3000,
+ 'ortb2': {
+ 'regs': {
+ 'ext': {
+ 'dsa': {
+ 'dsarequired': 1,
+ 'pubrender': 0,
+ 'datatopub': 1,
+ 'transparency': [{
+ 'domain': 'good-domain',
+ 'dsaparams': [1, 2]
+ }, {
+ 'domain': 'bad-setup',
+ 'dsaparams': ['1', 3]
+ }]
+ }
+ }
+ }
+ }
+ };
+ bidderRequest.bids = bidRequests;
+
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.dsa).to.exist;
+ expect(payload.dsa.dsarequired).to.equal(1);
+ expect(payload.dsa.pubrender).to.equal(0);
+ expect(payload.dsa.datatopub).to.equal(1);
+ expect(payload.dsa.transparency).to.deep.equal([{
+ 'domain': 'good-domain',
+ 'dsaparams': [1, 2]
+ }]);
+ });
+
it('supports sending hybrid mobile app parameters', function () {
let appRequest = Object.assign({},
bidRequests[0],
@@ -1575,6 +1615,15 @@ describe('AppNexusAdapter', function () {
'viewability': {
'config': ''
},
+ 'dsa': {
+ 'behalf': 'test-behalf',
+ 'paid': 'test-paid',
+ 'transparency': [{
+ 'domain': 'good-domain',
+ 'params': [1, 2, 3]
+ }],
+ 'adrender': 1
+ },
'rtb': {
'banner': {
'content': '',
@@ -1623,6 +1672,15 @@ describe('AppNexusAdapter', function () {
'nodes': [{
'bsid': '958'
}]
+ },
+ 'dsa': {
+ 'behalf': 'test-behalf',
+ 'paid': 'test-paid',
+ 'transparency': [{
+ 'domain': 'good-domain',
+ 'params': [1, 2, 3]
+ }],
+ 'adrender': 1
}
}
}
diff --git a/test/spec/modules/asteriobidAnalyticsAdapter_spec.js b/test/spec/modules/asteriobidAnalyticsAdapter_spec.js
new file mode 100644
index 00000000000..9be6c1dedac
--- /dev/null
+++ b/test/spec/modules/asteriobidAnalyticsAdapter_spec.js
@@ -0,0 +1,151 @@
+import asteriobidAnalytics, {storage} from 'modules/asteriobidAnalyticsAdapter.js';
+import {expect} from 'chai';
+import {server} from 'test/mocks/xhr.js';
+import * as utils from 'src/utils.js';
+import {expectEvents} from '../../helpers/analytics.js';
+
+let events = require('src/events');
+let constants = require('src/constants.json');
+
+describe('AsterioBid Analytics Adapter', function () {
+ let bidWonEvent = {
+ 'bidderCode': 'appnexus',
+ 'width': 300,
+ 'height': 250,
+ 'adId': '1ebb82ec35375e',
+ 'mediaType': 'banner',
+ 'cpm': 0.5,
+ 'requestId': '1582271863760569973',
+ 'creative_id': '96846035',
+ 'creativeId': '96846035',
+ 'ttl': 60,
+ 'currency': 'USD',
+ 'netRevenue': true,
+ 'auctionId': '9c7b70b9-b6ab-4439-9e71-b7b382797c18',
+ 'responseTimestamp': 1537521629657,
+ 'requestTimestamp': 1537521629331,
+ 'bidder': 'appnexus',
+ 'adUnitCode': 'div-gpt-ad-1460505748561-0',
+ 'timeToRespond': 326,
+ 'size': '300x250',
+ 'status': 'rendered',
+ 'eventType': 'bidWon',
+ 'ad': 'some ad',
+ 'adUrl': 'ad url'
+ };
+
+ describe('AsterioBid Analytic tests', function () {
+ beforeEach(function () {
+ sinon.stub(events, 'getEvents').returns([]);
+ });
+
+ afterEach(function () {
+ asteriobidAnalytics.disableAnalytics();
+ events.getEvents.restore();
+ });
+
+ it('support custom endpoint', function () {
+ let custom_url = 'custom url';
+ asteriobidAnalytics.enableAnalytics({
+ provider: 'asteriobid',
+ options: {
+ url: custom_url,
+ bundleId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
+ }
+ });
+
+ expect(asteriobidAnalytics.getOptions().url).to.equal(custom_url);
+ });
+
+ it('bid won event', function() {
+ let bundleId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
+ asteriobidAnalytics.enableAnalytics({
+ provider: 'asteriobid',
+ options: {
+ bundleId: bundleId
+ }
+ });
+
+ events.emit(constants.EVENTS.BID_WON, bidWonEvent);
+ asteriobidAnalytics.flush();
+
+ expect(server.requests.length).to.equal(1);
+ expect(server.requests[0].url).to.equal('https://endpt.asteriobid.com/endpoint');
+ expect(server.requests[0].requestBody.substring(0, 2)).to.equal('1:');
+
+ const pmEvents = JSON.parse(server.requests[0].requestBody.substring(2));
+ expect(pmEvents.pageViewId).to.exist;
+ expect(pmEvents.bundleId).to.equal(bundleId);
+ expect(pmEvents.ver).to.equal(1);
+ expect(pmEvents.events.length).to.equal(1);
+ expect(pmEvents.events[0].eventType).to.equal('bidWon');
+ expect(pmEvents.events[0].ad).to.be.undefined;
+ expect(pmEvents.events[0].adUrl).to.be.undefined;
+ });
+
+ it('track event without errors', function () {
+ sinon.spy(asteriobidAnalytics, 'track');
+
+ asteriobidAnalytics.enableAnalytics({
+ provider: 'asteriobid',
+ options: {
+ bundleId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
+ }
+ });
+
+ expectEvents().to.beTrackedBy(asteriobidAnalytics.track);
+ });
+ });
+
+ describe('build utm tag data', function () {
+ let getDataFromLocalStorageStub;
+ this.timeout(4000)
+ beforeEach(function () {
+ getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage');
+ getDataFromLocalStorageStub.withArgs('pm_utm_source').returns('utm_source');
+ getDataFromLocalStorageStub.withArgs('pm_utm_medium').returns('utm_medium');
+ getDataFromLocalStorageStub.withArgs('pm_utm_campaign').returns('utm_camp');
+ getDataFromLocalStorageStub.withArgs('pm_utm_term').returns('');
+ getDataFromLocalStorageStub.withArgs('pm_utm_content').returns('');
+ });
+ afterEach(function () {
+ getDataFromLocalStorageStub.restore();
+ asteriobidAnalytics.disableAnalytics()
+ });
+ it('should build utm data from local storage', function () {
+ asteriobidAnalytics.enableAnalytics({
+ provider: 'asteriobid',
+ options: {
+ bundleId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
+ }
+ });
+
+ const pmEvents = JSON.parse(server.requests[0].requestBody.substring(2));
+
+ expect(pmEvents.utmTags.utm_source).to.equal('utm_source');
+ expect(pmEvents.utmTags.utm_medium).to.equal('utm_medium');
+ expect(pmEvents.utmTags.utm_campaign).to.equal('utm_camp');
+ expect(pmEvents.utmTags.utm_term).to.equal('');
+ expect(pmEvents.utmTags.utm_content).to.equal('');
+ });
+ });
+
+ describe('build page info', function () {
+ afterEach(function () {
+ asteriobidAnalytics.disableAnalytics()
+ });
+ it('should build page info', function () {
+ asteriobidAnalytics.enableAnalytics({
+ provider: 'asteriobid',
+ options: {
+ bundleId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
+ }
+ });
+
+ const pmEvents = JSON.parse(server.requests[0].requestBody.substring(2));
+
+ expect(pmEvents.pageInfo.domain).to.equal(window.location.hostname);
+ expect(pmEvents.pageInfo.referrerDomain).to.equal(utils.parseUrl(document.referrer).hostname);
+ });
+ });
+});
diff --git a/test/spec/modules/beopBidAdapter_spec.js b/test/spec/modules/beopBidAdapter_spec.js
index c77e304e539..663d622e505 100644
--- a/test/spec/modules/beopBidAdapter_spec.js
+++ b/test/spec/modules/beopBidAdapter_spec.js
@@ -312,4 +312,22 @@ describe('BeOp Bid Adapter tests', () => {
expect(payload.kwds).to.include('keywords');
})
})
+
+ describe('Ensure eids are get', function() {
+ let bidRequests = [];
+ afterEach(function () {
+ bidRequests = [];
+ });
+
+ it(`should get eids from bid`, function () {
+ let bid = Object.assign({}, validBid);
+ bid.userIdAsEids = [{source: 'provider.com', uids: [{id: 'someid', atype: 1, ext: {whatever: true}}]}];
+ bidRequests.push(bid);
+
+ const request = spec.buildRequests(bidRequests, {});
+ const payload = JSON.parse(request.data);
+ expect(payload.eids).to.exist;
+ expect(payload.eids[0].source).to.equal('provider.com');
+ });
+ })
});
diff --git a/test/spec/modules/bizzclickBidAdapter_spec.js b/test/spec/modules/bizzclickBidAdapter_spec.js
index f80051b0a50..f8e66caf657 100644
--- a/test/spec/modules/bizzclickBidAdapter_spec.js
+++ b/test/spec/modules/bizzclickBidAdapter_spec.js
@@ -1,6 +1,102 @@
import { expect } from 'chai';
-import { spec } from 'modules/bizzclickBidAdapter.js';
-import {config} from 'src/config.js';
+import { spec } from 'modules/bizzclickBidAdapter';
+import 'modules/priceFloors.js';
+import { newBidder } from 'src/adapters/bidderFactory';
+import { config } from '../../../src/config.js';
+import { syncAddFPDToBidderRequest } from '../../helpers/fpd.js';
+
+// load modules that register ORTB processors
+import 'src/prebid.js';
+import 'modules/currency.js';
+import 'modules/userId/index.js';
+import 'modules/multibid/index.js';
+import 'modules/priceFloors.js';
+import 'modules/consentManagement.js';
+import 'modules/consentManagementUsp.js';
+import 'modules/schain.js';
+
+const SIMPLE_BID_REQUEST = {
+ bidder: 'bizzclick',
+ params: {
+ accountId: 'testAccountId',
+ sourceId: 'testSourceId',
+ host: 'USE',
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [320, 250],
+ [300, 600],
+ ],
+ },
+ },
+ adUnitCode: 'div-gpt-ad-1499748733608-0',
+ transactionId: 'f183e871-fbed-45f0-a427-c8a63c4c01eb',
+ bidId: '33e9500b21129f',
+ bidderRequestId: '2772c1e566670b',
+ auctionId: '192721e36a0239',
+ sizes: [[300, 250], [160, 600]],
+ gdprConsent: {
+ apiVersion: 2,
+ consentString: 'CONSENT',
+ vendorData: { purpose: { consents: { 1: true } } },
+ gdprApplies: true,
+ addtlConsent: '1~1.35.41.101',
+ },
+}
+
+const BANNER_BID_REQUEST = {
+ bidder: 'bizzclick',
+ params: {
+ accountId: 'testAccountId',
+ sourceId: 'testSourceId',
+ host: 'USE',
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250],
+ [300, 600],
+ ],
+ },
+ },
+ adUnitCode: '/adunit-code/test-path',
+ bidId: 'test-bid-id-1',
+ bidderRequestId: 'test-bid-request-1',
+ auctionId: 'test-auction-1',
+ transactionId: 'test-transactionId-1',
+ code: 'banner_example',
+ timeout: 1000,
+}
+
+const VIDEO_BID_REQUEST = {
+ placementCode: '/DfpAccount1/slotVideo',
+ bidId: 'test-bid-id-2',
+ mediaTypes: {
+ video: {
+ playerSize: [400, 300],
+ w: 400,
+ h: 300,
+ minduration: 5,
+ maxduration: 10,
+ startdelay: 0,
+ skip: 1,
+ minbitrate: 200,
+ protocols: [1, 2, 4]
+ }
+ },
+ bidder: 'bizzclick',
+ params: {
+ accountId: '123',
+ sourceId: '123',
+ host: 'USE',
+ },
+ adUnitCode: '/adunit-code/test-path',
+ bidderRequestId: 'test-bid-request-1',
+ auctionId: 'test-auction-1',
+ transactionId: 'test-transactionId-1',
+ timeout: 1000,
+}
const NATIVE_BID_REQUEST = {
code: 'native_example',
@@ -34,386 +130,179 @@ const NATIVE_BID_REQUEST = {
},
bidder: 'bizzclick',
params: {
- placementId: 'hash',
- accountId: 'accountId'
- },
- timeout: 1000
-
-};
-
-const BANNER_BID_REQUEST = {
- code: 'banner_example',
- mediaTypes: {
- banner: {
- sizes: [[300, 250], [300, 600]]
- }
- },
- schain: {
- ver: '1.0',
- complete: 1,
- nodes: [
- {
- asi: 'example.com',
- sid: '164',
- hp: 1
- }
- ]
- },
- bidder: 'bizzclick',
- params: {
- placementId: 'hash',
- accountId: 'accountId'
+ accountId: 'testAccountId',
+ sourceId: 'testSourceId',
+ host: 'USE',
},
+ adUnitCode: '/adunit-code/test-path',
+ bidId: 'test-bid-id-1',
+ bidderRequestId: 'test-bid-request-1',
+ auctionId: 'test-auction-1',
+ transactionId: 'test-transactionId-1',
timeout: 1000,
- gdprConsent: {
- consentString: 'BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA',
- gdprApplies: 1,
- },
uspConsent: 'uspConsent'
-}
+};
-const bidRequest = {
+const bidderRequest = {
refererInfo: {
- referer: 'test.com'
- }
-}
-
-const VIDEO_BID_REQUEST = {
- code: 'video1',
- sizes: [640, 480],
- mediaTypes: { video: {
- minduration: 0,
- maxduration: 999,
- boxingallowed: 1,
- skip: 0,
- mimes: [
- 'application/javascript',
- 'video/mp4'
- ],
- w: 1920,
- h: 1080,
- protocols: [
- 2
- ],
- linearity: 1,
- api: [
- 1,
- 2
- ]
+ page: 'https://publisher.com/home',
+ ref: 'https://referrer'
}
- },
-
- bidder: 'bizzclick',
- params: {
- placementId: 'hash',
- accountId: 'accountId'
- },
- timeout: 1000
-
-}
-
-const BANNER_BID_RESPONSE = {
- id: 'request_id',
- bidid: 'request_imp_id',
- seatbid: [{
- bid: [{
- id: 'bid_id',
- impid: 'request_imp_id',
- price: 5,
- adomain: ['example.com'],
- adm: 'admcode',
- crid: 'crid',
- ext: {
- mediaType: 'banner'
- }
- }],
- }],
-};
-
-const VIDEO_BID_RESPONSE = {
- id: 'request_id',
- bidid: 'request_imp_id',
- seatbid: [{
- bid: [{
- id: 'bid_id',
- impid: 'request_imp_id',
- price: 5,
- adomain: ['example.com'],
- adm: 'admcode',
- crid: 'crid',
- ext: {
- mediaType: 'video',
- vastUrl: 'http://example.vast',
- }
- }],
- }],
};
-let imgData = {
- url: `https://example.com/image`,
- w: 1200,
- h: 627
-};
+const gdprConsent = {
+ apiVersion: 2,
+ consentString: 'CONSENT',
+ vendorData: { purpose: { consents: { 1: true } } },
+ gdprApplies: true,
+ addtlConsent: '1~1.35.41.101',
+}
-const NATIVE_BID_RESPONSE = {
- id: 'request_id',
- bidid: 'request_imp_id',
- seatbid: [{
- bid: [{
- id: 'bid_id',
- impid: 'request_imp_id',
- price: 5,
- adomain: ['example.com'],
- adm: { native:
- {
- assets: [
- {id: 0, title: 'dummyText'},
- {id: 3, image: imgData},
- {
- id: 5,
- data: {value: 'organization.name'}
- }
- ],
- link: {url: 'example.com'},
- imptrackers: ['tracker1.com', 'tracker2.com', 'tracker3.com'],
- jstracker: 'tracker1.com'
- }
- },
- crid: 'crid',
- ext: {
- mediaType: 'native'
- }
- }],
- }],
-};
+describe('bizzclickAdapter', 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('BizzclickAdapter', function() {
- describe('with COPPA', function() {
- beforeEach(function() {
+ describe('with user privacy regulations', function () {
+ it('should send the Coppa "required" flag set to "1" in the request', function () {
sinon.stub(config, 'getConfig')
.withArgs('coppa')
.returns(true);
- });
- afterEach(function() {
+ const serverRequest = spec.buildRequests([SIMPLE_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(serverRequest.data.regs.coppa).to.equal(1);
config.getConfig.restore();
});
- it('should send the Coppa "required" flag set to "1" in the request', function () {
- let serverRequest = spec.buildRequests([BANNER_BID_REQUEST]);
- expect(serverRequest.data[0].regs.coppa).to.equal(1);
+ it('should send the GDPR Consent data in the request', function () {
+ const serverRequest = spec.buildRequests([SIMPLE_BID_REQUEST], syncAddFPDToBidderRequest({ ...bidderRequest, gdprConsent }));
+ expect(serverRequest.data.regs.ext.gdpr).to.exist.and.to.equal(1);
+ expect(serverRequest.data.user.ext.consent).to.equal('CONSENT');
});
- });
- describe('isBidRequestValid', function() {
- it('should return true when required params found', function () {
- expect(spec.isBidRequestValid(NATIVE_BID_REQUEST)).to.equal(true);
- });
-
- it('should return false when required params are not passed', function () {
- let bid = Object.assign({}, NATIVE_BID_REQUEST);
- delete bid.params;
- bid.params = {
- 'IncorrectParam': 0
- };
- expect(spec.isBidRequestValid(bid)).to.equal(false);
+ it('should send the CCPA data in the request', function () {
+ const serverRequest = spec.buildRequests([SIMPLE_BID_REQUEST], syncAddFPDToBidderRequest({...bidderRequest, ...{ uspConsent: '1YYY' }}));
+ expect(serverRequest.data.regs.ext.us_privacy).to.equal('1YYY');
});
});
- describe('build Native Request', function () {
- const request = spec.buildRequests([NATIVE_BID_REQUEST], bidRequest);
-
- it('Creates a ServerRequest object with method, URL and data', function () {
- expect(request).to.exist;
- expect(request.method).to.exist;
- expect(request.url).to.exist;
- expect(request.data).to.exist;
- });
-
- it('sends bid request to our endpoint via POST', function () {
- expect(request.method).to.equal('POST');
- });
-
- it('Returns valid URL', function () {
- expect(request.url).to.equal('https://us-e-node1.bizzclick.com/bid?rtb_seat_id=prebidjs&secret_key=accountId');
+ describe('isBidRequestValid', function () {
+ it('should return true when required params found', function () {
+ expect(spec.isBidRequestValid(BANNER_BID_REQUEST)).to.equal(true);
});
- it('Returns empty data if no valid requests are passed', function () {
- let serverRequest = spec.buildRequests([]);
- expect(serverRequest).to.be.an('array').that.is.empty;
+ it('should return false when accountID/sourceId is missing', function () {
+ let localbid = Object.assign({}, BANNER_BID_REQUEST);
+ delete localbid.params.accountId;
+ delete localbid.params.sourceId;
+ expect(spec.isBidRequestValid(BANNER_BID_REQUEST)).to.equal(false);
});
});
- describe('build Banner Request', function () {
- const request = spec.buildRequests([BANNER_BID_REQUEST]);
-
- it('Creates a ServerRequest object with method, URL and data', function () {
- expect(request).to.exist;
- expect(request.method).to.exist;
- expect(request.url).to.exist;
- expect(request.data).to.exist;
+ describe('build request', function () {
+ it('should return an empty array when no bid requests', function () {
+ const bidRequest = spec.buildRequests([], syncAddFPDToBidderRequest(bidderRequest));
+ expect(bidRequest).to.be.an('array');
+ expect(bidRequest.length).to.equal(0);
});
- it('sends bid request to our endpoint via POST', function () {
+ it('should return a valid bid request object', function () {
+ const request = spec.buildRequests([SIMPLE_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(request).to.not.equal('array');
+ expect(request.data).to.be.an('object');
expect(request.method).to.equal('POST');
+ expect(request.url).to.not.equal('');
+ expect(request.url).to.not.equal(undefined);
+ expect(request.url).to.not.equal(null);
+
+ expect(request.data.site).to.have.property('page');
+ expect(request.data.site).to.have.property('domain');
+ expect(request.data).to.have.property('id');
+ expect(request.data).to.have.property('imp');
+ expect(request.data).to.have.property('device');
});
- it('check consent and ccpa string is set properly', function() {
- expect(request.data[0].regs.ext.gdpr).to.equal(1);
- expect(request.data[0].user.ext.consent).to.equal(BANNER_BID_REQUEST.gdprConsent.consentString);
- expect(request.data[0].regs.ext.us_privacy).to.equal(BANNER_BID_REQUEST.uspConsent);
- })
-
- it('check schain is set properly', function() {
- expect(request.data[0].source.ext.schain.complete).to.equal(1);
- expect(request.data[0].source.ext.schain.ver).to.equal('1.0');
- })
-
- it('Returns valid URL', function () {
- expect(request.url).to.equal('https://us-e-node1.bizzclick.com/bid?rtb_seat_id=prebidjs&secret_key=accountId');
+ it('should return a valid bid BANNER request object', function () {
+ const request = spec.buildRequests([BANNER_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.data.imp[0].banner).to.exist;
+ expect(request.data.imp[0].banner.format[0].w).to.be.an('number');
+ expect(request.data.imp[0].banner.format[0].h).to.be.an('number');
});
- });
- describe('build Video Request', function () {
- const request = spec.buildRequests([VIDEO_BID_REQUEST]);
-
- it('Creates a ServerRequest object with method, URL and data', function () {
- expect(request).to.exist;
- expect(request.method).to.exist;
- expect(request.url).to.exist;
- expect(request.data).to.exist;
- });
+ if (FEATURES.VIDEO) {
+ it('should return a valid bid VIDEO request object', function () {
+ const request = spec.buildRequests([VIDEO_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.data.imp[0].video).to.exist;
+ expect(request.data.imp[0].video.w).to.be.an('number');
+ expect(request.data.imp[0].video.h).to.be.an('number');
+ });
+ }
- it('sends bid request to our endpoint via POST', function () {
- expect(request.method).to.equal('POST');
+ it('should return a valid bid NATIVE request object', function () {
+ const request = spec.buildRequests([NATIVE_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.data.imp[0]).to.be.an('object');
});
+ })
- it('Returns valid URL', function () {
- expect(request.url).to.equal('https://us-e-node1.bizzclick.com/bid?rtb_seat_id=prebidjs&secret_key=accountId');
+ describe('interpretResponse', function () {
+ let bidRequests, bidderRequest;
+ beforeEach(function () {
+ bidRequests = [{
+ 'bidId': '28ffdk2B952532',
+ 'bidder': 'bizzclick',
+ 'userId': {
+ 'freepassId': {
+ 'userIp': '172.21.0.1',
+ 'userId': '123',
+ 'commonId': 'commonIdValue'
+ }
+ },
+ 'adUnitCode': 'adunit-code',
+ 'params': {
+ 'publisherId': 'publisherIdValue'
+ }
+ }];
+ bidderRequest = {};
});
- });
- describe('interpretResponse', function () {
- it('Empty response must return empty array', function() {
+ it('Empty response must return empty array', function () {
const emptyResponse = null;
- let response = spec.interpretResponse(emptyResponse);
+ let response = spec.interpretResponse(emptyResponse, BANNER_BID_REQUEST);
expect(response).to.be.an('array').that.is.empty;
})
it('Should interpret banner response', function () {
- const bannerResponse = {
- body: [BANNER_BID_RESPONSE]
- }
-
- const expectedBidResponse = {
- requestId: BANNER_BID_RESPONSE.id,
- cpm: BANNER_BID_RESPONSE.seatbid[0].bid[0].price,
- width: BANNER_BID_RESPONSE.seatbid[0].bid[0].w,
- height: BANNER_BID_RESPONSE.seatbid[0].bid[0].h,
- ttl: BANNER_BID_RESPONSE.ttl || 1200,
- currency: BANNER_BID_RESPONSE.cur || 'USD',
- netRevenue: true,
- creativeId: BANNER_BID_RESPONSE.seatbid[0].bid[0].crid,
- dealId: BANNER_BID_RESPONSE.seatbid[0].bid[0].dealid,
-
- meta: {advertiserDomains: BANNER_BID_RESPONSE.seatbid[0].bid[0].adomain},
- mediaType: 'banner',
- ad: BANNER_BID_RESPONSE.seatbid[0].bid[0].adm
- }
-
- let bannerResponses = spec.interpretResponse(bannerResponse);
-
- expect(bannerResponses).to.be.an('array').that.is.not.empty;
- let dataItem = bannerResponses[0];
- expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId',
- 'netRevenue', 'currency', 'dealId', 'meta', 'mediaType');
- expect(dataItem.requestId).to.equal(expectedBidResponse.requestId);
- expect(dataItem.cpm).to.equal(expectedBidResponse.cpm);
- expect(dataItem.ad).to.equal(expectedBidResponse.ad);
- expect(dataItem.ttl).to.equal(expectedBidResponse.ttl);
- expect(dataItem.meta.advertiserDomains).to.equal(expectedBidResponse.meta.advertiserDomains);
- expect(dataItem.creativeId).to.equal(expectedBidResponse.creativeId);
- expect(dataItem.netRevenue).to.be.true;
- expect(dataItem.currency).to.equal(expectedBidResponse.currency);
- expect(dataItem.width).to.equal(expectedBidResponse.width);
- expect(dataItem.height).to.equal(expectedBidResponse.height);
- });
-
- it('Should interpret video response', function () {
- const videoResponse = {
- body: [VIDEO_BID_RESPONSE]
- }
-
- const expectedBidResponse = {
- requestId: VIDEO_BID_RESPONSE.id,
- cpm: VIDEO_BID_RESPONSE.seatbid[0].bid[0].price,
- width: VIDEO_BID_RESPONSE.seatbid[0].bid[0].w,
- height: VIDEO_BID_RESPONSE.seatbid[0].bid[0].h,
- ttl: VIDEO_BID_RESPONSE.ttl || 1200,
- currency: VIDEO_BID_RESPONSE.cur || 'USD',
- netRevenue: true,
- creativeId: VIDEO_BID_RESPONSE.seatbid[0].bid[0].crid,
- dealId: VIDEO_BID_RESPONSE.seatbid[0].bid[0].dealid,
- mediaType: 'video',
- vastXml: VIDEO_BID_RESPONSE.seatbid[0].bid[0].adm,
- meta: {advertiserDomains: VIDEO_BID_RESPONSE.seatbid[0].bid[0].adomain},
- vastUrl: VIDEO_BID_RESPONSE.seatbid[0].bid[0].ext.vastUrl
- }
-
- let videoResponses = spec.interpretResponse(videoResponse);
-
- expect(videoResponses).to.be.an('array').that.is.not.empty;
- let dataItem = videoResponses[0];
- expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'vastXml', 'vastUrl', 'ttl', 'creativeId',
- 'netRevenue', 'currency', 'dealId', 'meta', 'mediaType');
- expect(dataItem.requestId).to.equal(expectedBidResponse.requestId);
- expect(dataItem.cpm).to.equal(expectedBidResponse.cpm);
- expect(dataItem.vastXml).to.equal(expectedBidResponse.vastXml)
- expect(dataItem.ttl).to.equal(expectedBidResponse.ttl);
- expect(dataItem.creativeId).to.equal(expectedBidResponse.creativeId);
- expect(dataItem.meta.advertiserDomains).to.equal(expectedBidResponse.meta.advertiserDomains);
- expect(dataItem.netRevenue).to.be.true;
- expect(dataItem.currency).to.equal(expectedBidResponse.currency);
- expect(dataItem.width).to.equal(expectedBidResponse.width);
- expect(dataItem.height).to.equal(expectedBidResponse.height);
- });
-
- it('Should interpret native response', function () {
- const nativeResponse = {
- body: [NATIVE_BID_RESPONSE]
- }
-
- const expectedBidResponse = {
- requestId: NATIVE_BID_RESPONSE.id,
- cpm: NATIVE_BID_RESPONSE.seatbid[0].bid[0].price,
- width: NATIVE_BID_RESPONSE.seatbid[0].bid[0].w,
- height: NATIVE_BID_RESPONSE.seatbid[0].bid[0].h,
- ttl: NATIVE_BID_RESPONSE.ttl || 1200,
- currency: NATIVE_BID_RESPONSE.cur || 'USD',
- netRevenue: true,
- creativeId: NATIVE_BID_RESPONSE.seatbid[0].bid[0].crid,
- dealId: NATIVE_BID_RESPONSE.seatbid[0].bid[0].dealid,
- mediaType: 'native',
- meta: {advertiserDomains: NATIVE_BID_RESPONSE.seatbid[0].bid[0].adomain},
- native: {clickUrl: NATIVE_BID_RESPONSE.seatbid[0].bid[0].adm.native.link.url}
- }
-
- let nativeResponses = spec.interpretResponse(nativeResponse);
-
- expect(nativeResponses).to.be.an('array').that.is.not.empty;
- let dataItem = nativeResponses[0];
- expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'native', 'ttl', 'creativeId',
- 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta');
- expect(dataItem.requestId).to.equal(expectedBidResponse.requestId);
- expect(dataItem.cpm).to.equal(expectedBidResponse.cpm);
- expect(dataItem.meta.advertiserDomains).to.equal(expectedBidResponse.meta.advertiserDomains);
- expect(dataItem.native.clickUrl).to.equal(expectedBidResponse.native.clickUrl)
- expect(dataItem.ttl).to.equal(expectedBidResponse.ttl);
- expect(dataItem.creativeId).to.equal(expectedBidResponse.creativeId);
- expect(dataItem.netRevenue).to.be.true;
- expect(dataItem.currency).to.equal(expectedBidResponse.currency);
- expect(dataItem.width).to.equal(expectedBidResponse.width);
- expect(dataItem.height).to.equal(expectedBidResponse.height);
- });
+ const serverResponse = {
+ body: {
+ 'cur': 'USD',
+ 'seatbid': [{
+ 'bid': [{
+ 'impid': '28ffdk2B952532',
+ 'price': 97,
+ 'adm': '
',
+ 'w': 300,
+ 'h': 250,
+ 'crid': 'creative0'
+ }]
+ }]
+ }
+ };
+ it('should interpret server response', function () {
+ const bidRequest = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest));
+ const bids = spec.interpretResponse(serverResponse, bidRequest);
+ expect(bids).to.be.an('array');
+ const bid = bids[0];
+ expect(bid).to.be.an('object');
+ expect(bid.currency).to.equal('USD');
+ expect(bid.cpm).to.equal(97);
+ expect(bid.ad).to.equal(ad)
+ expect(bid.width).to.equal(300);
+ expect(bid.height).to.equal(250);
+ expect(bid.creativeId).to.equal('creative0');
+ });
+ })
});
-})
+});
diff --git a/test/spec/modules/boldwinBidAdapter_spec.js b/test/spec/modules/boldwinBidAdapter_spec.js
index 52a6ec03757..9a7b16c0914 100644
--- a/test/spec/modules/boldwinBidAdapter_spec.js
+++ b/test/spec/modules/boldwinBidAdapter_spec.js
@@ -314,7 +314,7 @@ describe('BoldwinBidAdapter', function () {
expect(userSync[0].type).to.exist;
expect(userSync[0].url).to.exist;
expect(userSync[0].type).to.be.equal('image');
- expect(userSync[0].url).to.be.equal('https://cs.videowalldirect.com');
+ expect(userSync[0].url).to.be.equal('https://sync.videowalldirect.com');
});
});
});
diff --git a/test/spec/modules/browsiRtdProvider_spec.js b/test/spec/modules/browsiRtdProvider_spec.js
index 75120aa7505..5fcc78f4322 100644
--- a/test/spec/modules/browsiRtdProvider_spec.js
+++ b/test/spec/modules/browsiRtdProvider_spec.js
@@ -89,12 +89,6 @@ describe('browsi Real time data sub module', function () {
expect(browsiRTD.browsiSubmodule.getTargetingData([], null, null, auction)).to.eql({});
});
- it('should return NA if no prediction for ad unit', function () {
- makeSlot({code: 'adMock', divId: 'browsiAd_2'});
- browsiRTD.setData({});
- expect(browsiRTD.browsiSubmodule.getTargetingData(['adMock'], null, null, auction)).to.eql({adMock: {bv: 'NA'}});
- });
-
it('should return prediction from server', function () {
makeSlot({code: 'hasPrediction', divId: 'hasPrediction'});
const data = {
diff --git a/test/spec/modules/consentManagementGpp_spec.js b/test/spec/modules/consentManagementGpp_spec.js
index 99d4f94f502..93a876d0233 100644
--- a/test/spec/modules/consentManagementGpp_spec.js
+++ b/test/spec/modules/consentManagementGpp_spec.js
@@ -290,7 +290,7 @@ describe('consentManagementGpp', function () {
});
it('should not re-use errors', (done) => {
- cmpResult = Promise.reject(new Error());
+ cmpResult = GreedyPromise.reject(new Error());
GPPClient.init(makeCmp).catch(() => {
cmpResult = {signalStatus: 'ready'};
return GPPClient.init(makeCmp).then(([client]) => {
diff --git a/test/spec/modules/contxtfulRtdProvider_spec.js b/test/spec/modules/contxtfulRtdProvider_spec.js
new file mode 100644
index 00000000000..541c0e6e6dd
--- /dev/null
+++ b/test/spec/modules/contxtfulRtdProvider_spec.js
@@ -0,0 +1,200 @@
+import { contxtfulSubmodule } from '../../../modules/contxtfulRtdProvider.js';
+import { expect } from 'chai';
+import { loadExternalScriptStub } from 'test/mocks/adloaderStub.js';
+
+import * as events from '../../../src/events';
+
+const _ = null;
+const VERSION = 'v1';
+const CUSTOMER = 'CUSTOMER';
+const CONTXTFUL_CONNECTOR_ENDPOINT = `https://api.receptivity.io/${VERSION}/prebid/${CUSTOMER}/connector/p.js`;
+const INITIAL_RECEPTIVITY = { ReceptivityState: 'INITIAL_RECEPTIVITY' };
+const INITIAL_RECEPTIVITY_EVENT = new CustomEvent('initialReceptivity', { detail: INITIAL_RECEPTIVITY });
+
+const CONTXTFUL_API = { GetReceptivity: sinon.stub() }
+const RX_ENGINE_IS_READY_EVENT = new CustomEvent('rxEngineIsReady', {detail: CONTXTFUL_API});
+
+function buildInitConfig(version, customer) {
+ return {
+ name: 'contxtful',
+ params: {
+ version,
+ customer,
+ },
+ };
+}
+
+describe('contxtfulRtdProvider', function () {
+ let sandbox = sinon.sandbox.create();
+ let loadExternalScriptTag;
+ let eventsEmitSpy;
+
+ beforeEach(() => {
+ loadExternalScriptTag = document.createElement('script');
+ loadExternalScriptStub.callsFake((_url, _moduleName) => loadExternalScriptTag);
+
+ CONTXTFUL_API.GetReceptivity.reset();
+
+ eventsEmitSpy = sandbox.spy(events, ['emit']);
+ });
+
+ afterEach(function () {
+ delete window.Contxtful;
+ sandbox.restore();
+ });
+
+ describe('extractParameters with invalid configuration', () => {
+ const {
+ params: { customer, version },
+ } = buildInitConfig(VERSION, CUSTOMER);
+ const theories = [
+ [
+ null,
+ 'params.version should be a non-empty string',
+ 'null object for config',
+ ],
+ [
+ {},
+ 'params.version should be a non-empty string',
+ 'empty object for config',
+ ],
+ [
+ { customer },
+ 'params.version should be a non-empty string',
+ 'customer only in config',
+ ],
+ [
+ { version },
+ 'params.customer should be a non-empty string',
+ 'version only in config',
+ ],
+ [
+ { customer, version: '' },
+ 'params.version should be a non-empty string',
+ 'empty string for version',
+ ],
+ [
+ { customer: '', version },
+ 'params.customer should be a non-empty string',
+ 'empty string for customer',
+ ],
+ [
+ { customer: '', version: '' },
+ 'params.version should be a non-empty string',
+ 'empty string for version & customer',
+ ],
+ ];
+
+ theories.forEach(([params, expectedErrorMessage, _description]) => {
+ const config = { name: 'contxtful', params };
+ it('throws the expected error', () => {
+ expect(() => contxtfulSubmodule.extractParameters(config)).to.throw(
+ expectedErrorMessage
+ );
+ });
+ });
+ });
+
+ describe('initialization with invalid config', function () {
+ it('returns false', () => {
+ expect(contxtfulSubmodule.init({})).to.be.false;
+ });
+ });
+
+ describe('initialization with valid config', function () {
+ it('returns true when initializing', () => {
+ const config = buildInitConfig(VERSION, CUSTOMER);
+ expect(contxtfulSubmodule.init(config)).to.be.true;
+ });
+
+ it('loads contxtful module script asynchronously', (done) => {
+ contxtfulSubmodule.init(buildInitConfig(VERSION, CUSTOMER));
+
+ setTimeout(() => {
+ expect(loadExternalScriptStub.calledOnce).to.be.true;
+ expect(loadExternalScriptStub.args[0][0]).to.equal(
+ CONTXTFUL_CONNECTOR_ENDPOINT
+ );
+ done();
+ }, 10);
+ });
+ });
+
+ describe('load external script return falsy', function () {
+ it('returns true when initializing', () => {
+ loadExternalScriptStub.callsFake(() => {});
+ const config = buildInitConfig(VERSION, CUSTOMER);
+ expect(contxtfulSubmodule.init(config)).to.be.true;
+ });
+ });
+
+ describe('rxEngine from external script', function () {
+ it('use rxEngine api to get receptivity', () => {
+ contxtfulSubmodule.init(buildInitConfig(VERSION, CUSTOMER));
+ loadExternalScriptTag.dispatchEvent(RX_ENGINE_IS_READY_EVENT);
+
+ contxtfulSubmodule.getTargetingData(['ad-slot']);
+
+ expect(CONTXTFUL_API.GetReceptivity.calledOnce).to.be.true;
+ });
+ });
+
+ describe('initial receptivity is not dispatched', function () {
+ it('does not initialize receptivity value', () => {
+ contxtfulSubmodule.init(buildInitConfig(VERSION, CUSTOMER));
+
+ let targetingData = contxtfulSubmodule.getTargetingData(['ad-slot']);
+ expect(targetingData).to.deep.equal({});
+ });
+ });
+
+ describe('initial receptivity is invalid', function () {
+ const theories = [
+ [new Event('initialReceptivity'), 'event without details'],
+ [new CustomEvent('initialReceptivity', { }), 'custom event without details'],
+ [new CustomEvent('initialReceptivity', { detail: {} }), 'custom event with invalid details'],
+ [new CustomEvent('initialReceptivity', { detail: { ReceptivityState: '' } }), 'custom event with details without ReceptivityState'],
+ ];
+
+ theories.forEach(([initialReceptivityEvent, _description]) => {
+ it('does not initialize receptivity value', () => {
+ contxtfulSubmodule.init(buildInitConfig(VERSION, CUSTOMER));
+ loadExternalScriptTag.dispatchEvent(initialReceptivityEvent);
+
+ let targetingData = contxtfulSubmodule.getTargetingData(['ad-slot']);
+ expect(targetingData).to.deep.equal({});
+ });
+ })
+ });
+
+ describe('getTargetingData', function () {
+ const theories = [
+ [undefined, {}, 'undefined ad-slots'],
+ [[], {}, 'empty ad-slots'],
+ [
+ ['ad-slot'],
+ { 'ad-slot': { ReceptivityState: 'INITIAL_RECEPTIVITY' } },
+ 'single ad-slot',
+ ],
+ [
+ ['ad-slot-1', 'ad-slot-2'],
+ {
+ 'ad-slot-1': { ReceptivityState: 'INITIAL_RECEPTIVITY' },
+ 'ad-slot-2': { ReceptivityState: 'INITIAL_RECEPTIVITY' },
+ },
+ 'many ad-slots',
+ ],
+ ];
+
+ theories.forEach(([adUnits, expected, _description]) => {
+ it('adds "ReceptivityState" to the adUnits', function () {
+ contxtfulSubmodule.init(buildInitConfig(VERSION, CUSTOMER));
+ loadExternalScriptTag.dispatchEvent(INITIAL_RECEPTIVITY_EVENT);
+
+ expect(contxtfulSubmodule.getTargetingData(adUnits)).to.deep.equal(
+ expected
+ );
+ });
+ });
+ });
+});
diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js
index 59ebefa2d60..73d1978a9d9 100644
--- a/test/spec/modules/conversantBidAdapter_spec.js
+++ b/test/spec/modules/conversantBidAdapter_spec.js
@@ -2,13 +2,20 @@ import {expect} from 'chai';
import {spec, storage} from 'modules/conversantBidAdapter.js';
import * as utils from 'src/utils.js';
import {createEidsArray} from 'modules/userId/eids.js';
-import { config } from '../../../src/config.js';
import {deepAccess} from 'src/utils';
+// load modules that register ORTB processors
+import 'src/prebid.js'
+import 'modules/currency.js';
+import 'modules/userId/index.js'; // handles eids
+import 'modules/priceFloors.js';
+import 'modules/consentManagement.js';
+import 'modules/consentManagementUsp.js';
+import 'modules/schain.js'; // handles schain
+import {hook} from '../../../src/hook.js'
describe('Conversant adapter tests', function() {
const siteId = '108060';
const versionPattern = /^\d+\.\d+\.\d+(.)*$/;
-
const bidRequests = [
// banner with single size
{
@@ -19,13 +26,18 @@ describe('Conversant adapter tests', function() {
tag_id: 'tagid-1',
bidfloor: 0.5
},
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250]],
+ }
+ },
placementCode: 'pcode000',
transactionId: 'tx000',
- sizes: [[300, 250]],
bidId: 'bid000',
bidderRequestId: '117d765b87bed38',
auctionId: 'req000'
},
+
// banner with sizes in mediaTypes.banner.sizes
{
bidder: 'conversant',
@@ -51,9 +63,13 @@ describe('Conversant adapter tests', function() {
position: 2,
tag_id: ''
},
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 600], [160, 600]],
+ }
+ },
placementCode: 'pcode002',
transactionId: 'tx002',
- sizes: [[300, 600], [160, 600]],
bidId: 'bid002',
bidderRequestId: '117d765b87bed38',
auctionId: 'req000'
@@ -77,7 +93,6 @@ describe('Conversant adapter tests', function() {
},
placementCode: 'pcode003',
transactionId: 'tx003',
- sizes: [640, 480],
bidId: 'bid003',
bidderRequestId: '117d765b87bed38',
auctionId: 'req000'
@@ -125,16 +140,15 @@ describe('Conversant adapter tests', function() {
bidderRequestId: '117d765b87bed38',
auctionId: 'req000'
},
- // video with first party data
+ // banner with first party data
{
bidder: 'conversant',
params: {
site_id: siteId
},
mediaTypes: {
- video: {
- context: 'instream',
- mimes: ['video/mp4', 'video/x-flv']
+ banner: {
+ sizes: [[300, 600], [160, 600]],
}
},
ortb2Imp: {
@@ -150,23 +164,6 @@ describe('Conversant adapter tests', function() {
bidId: 'bid006',
bidderRequestId: '117d765b87bed38',
auctionId: 'req000'
- },
- {
- bidder: 'conversant',
- params: {
- site_id: siteId
- },
- mediaTypes: {
- banner: {
- sizes: [[728, 90], [468, 60]],
- pos: 5
- }
- },
- placementCode: 'pcode001',
- transactionId: 'tx001',
- bidId: 'bid007',
- bidderRequestId: '117d765b87bed38',
- auctionId: 'req000'
}
];
@@ -217,7 +214,14 @@ describe('Conversant adapter tests', function() {
}]
}]
},
- headers: {}};
+ headers: {}
+ };
+
+ before(() => {
+ // ortbConverter depends on other modules to be setup to work as expected so run hook.ready to register some
+ // submodules so functions like setOrtbSourceExtSchain and setOrtbUserExtEids are available
+ hook.ready();
+ });
it('Verify basic properties', function() {
expect(spec.code).to.equal('conversant');
@@ -232,12 +236,9 @@ describe('Conversant adapter tests', function() {
expect(spec.isBidRequestValid({})).to.be.false;
expect(spec.isBidRequestValid({params: {}})).to.be.false;
expect(spec.isBidRequestValid({params: {site_id: '123'}})).to.be.true;
- expect(spec.isBidRequestValid(bidRequests[0])).to.be.true;
- expect(spec.isBidRequestValid(bidRequests[1])).to.be.true;
- expect(spec.isBidRequestValid(bidRequests[2])).to.be.true;
- expect(spec.isBidRequestValid(bidRequests[3])).to.be.true;
- expect(spec.isBidRequestValid(bidRequests[4])).to.be.true;
- expect(spec.isBidRequestValid(bidRequests[5])).to.be.true;
+ bidRequests.forEach((bid) => {
+ expect(spec.isBidRequestValid(bid)).to.be.true;
+ });
const simpleVideo = JSON.parse(JSON.stringify(bidRequests[3]));
simpleVideo.params.site_id = 123;
@@ -251,152 +252,171 @@ describe('Conversant adapter tests', function() {
expect(spec.isBidRequestValid(simpleVideo)).to.be.true;
});
- it('Verify buildRequest', function() {
- const page = 'http://test.com?a=b&c=123';
- const bidderRequest = {
- refererInfo: {
- page: page
- },
- ortb2: {
- source: {
- tid: 'tid000'
+ describe('Verify buildRequest', function() {
+ let page, bidderRequest, request, payload;
+ before(() => {
+ page = 'http://test.com?a=b&c=123';
+ // ortbConverter uses the site/device information from the ortb2 object passed in the bidderRequest object
+ bidderRequest = {
+ refererInfo: {
+ page: page
+ },
+ ortb2: {
+ source: {
+ tid: 'tid000'
+ },
+ site: {
+ mobile: 0,
+ page: page,
+ },
+ device: {
+ w: screen.width,
+ h: screen.height,
+ dnt: 0,
+ ua: navigator.userAgent
+ }
}
- }
- };
- const request = spec.buildRequests(bidRequests, bidderRequest);
- expect(request.method).to.equal('POST');
- expect(request.url).to.equal('https://web.hb.ad.cpe.dotomi.com/cvx/client/hb/ortb/25');
- const payload = request.data;
+ };
+ request = spec.buildRequests(bidRequests, bidderRequest);
+ payload = request.data;
+ });
+
+ it('Verify common elements', function() {
+ expect(request.method).to.equal('POST');
+ expect(request.url).to.equal('https://web.hb.ad.cpe.dotomi.com/cvx/client/hb/ortb/25');
+
+ expect(payload).to.have.property('id');
+ expect(payload.source).to.have.property('tid', 'tid000');
+ expect(payload).to.have.property('at', 1);
+ expect(payload).to.have.property('imp');
+ expect(payload.imp).to.be.an('array').with.lengthOf(bidRequests.length);
+
+ expect(payload).to.have.property('site');
+ expect(payload.site).to.have.property('id', siteId);
+ expect(payload.site).to.have.property('mobile').that.is.oneOf([0, 1]);
+
+ expect(payload.site).to.have.property('page', page);
+
+ expect(payload).to.have.property('device');
+ expect(payload.device).to.have.property('w', screen.width);
+ expect(payload.device).to.have.property('h', screen.height);
+ expect(payload.device).to.have.property('dnt').that.is.oneOf([0, 1]);
+ expect(payload.device).to.have.property('ua', navigator.userAgent);
+
+ expect(payload).to.not.have.property('user'); // there should be no user by default
+ expect(payload).to.not.have.property('tmax'); // there should be no user by default
+ });
- expect(payload).to.have.property('id');
- expect(payload.source).to.have.property('tid', 'tid000');
- expect(payload).to.have.property('at', 1);
- expect(payload).to.have.property('imp');
- expect(payload.imp).to.be.an('array').with.lengthOf(8);
-
- expect(payload.imp[0]).to.have.property('id', 'bid000');
- expect(payload.imp[0]).to.have.property('secure', 1);
- expect(payload.imp[0]).to.have.property('bidfloor', 0.5);
- expect(payload.imp[0]).to.have.property('displaymanager', 'Prebid.js');
- expect(payload.imp[0]).to.have.property('displaymanagerver').that.matches(versionPattern);
- expect(payload.imp[0]).to.have.property('tagid', 'tagid-1');
- expect(payload.imp[0]).to.have.property('banner');
- expect(payload.imp[0].banner).to.have.property('pos', 1);
- expect(payload.imp[0].banner).to.have.property('format');
- expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}]);
- expect(payload.imp[0]).to.not.have.property('video');
-
- expect(payload.imp[1]).to.have.property('id', 'bid001');
- expect(payload.imp[1]).to.have.property('secure', 1);
- expect(payload.imp[1]).to.have.property('bidfloor', 0);
- expect(payload.imp[1]).to.have.property('displaymanager', 'Prebid.js');
- expect(payload.imp[1]).to.have.property('displaymanagerver').that.matches(versionPattern);
- expect(payload.imp[1]).to.not.have.property('tagid');
- expect(payload.imp[1]).to.have.property('banner');
- expect(payload.imp[1].banner).to.not.have.property('pos');
- expect(payload.imp[1].banner).to.have.property('format');
- expect(payload.imp[1].banner.format).to.deep.equal([{w: 728, h: 90}, {w: 468, h: 60}]);
-
- expect(payload.imp[2]).to.have.property('id', 'bid002');
- expect(payload.imp[2]).to.have.property('secure', 1);
- expect(payload.imp[2]).to.have.property('bidfloor', 0);
- expect(payload.imp[2]).to.have.property('displaymanager', 'Prebid.js');
- expect(payload.imp[2]).to.have.property('displaymanagerver').that.matches(versionPattern);
- expect(payload.imp[2]).to.have.property('banner');
- expect(payload.imp[2].banner).to.have.property('pos', 2);
- expect(payload.imp[2].banner).to.have.property('format');
- expect(payload.imp[2].banner.format).to.deep.equal([{w: 300, h: 600}, {w: 160, h: 600}]);
-
- expect(payload.imp[3]).to.have.property('id', 'bid003');
- expect(payload.imp[3]).to.have.property('secure', 1);
- expect(payload.imp[3]).to.have.property('bidfloor', 0);
- expect(payload.imp[3]).to.have.property('displaymanager', 'Prebid.js');
- expect(payload.imp[3]).to.have.property('displaymanagerver').that.matches(versionPattern);
- expect(payload.imp[3]).to.not.have.property('tagid');
- expect(payload.imp[3]).to.have.property('video');
- expect(payload.imp[3].video).to.have.property('pos', 3);
- expect(payload.imp[3].video).to.have.property('w', 632);
- expect(payload.imp[3].video).to.have.property('h', 499);
- expect(payload.imp[3].video).to.have.property('mimes');
- expect(payload.imp[3].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']);
- expect(payload.imp[3].video).to.have.property('protocols');
- expect(payload.imp[3].video.protocols).to.deep.equal([1, 2]);
- expect(payload.imp[3].video).to.have.property('api');
- expect(payload.imp[3].video.api).to.deep.equal([2]);
- expect(payload.imp[3].video).to.have.property('maxduration', 30);
- expect(payload.imp[3]).to.not.have.property('banner');
-
- expect(payload.imp[4]).to.have.property('id', 'bid004');
- expect(payload.imp[4]).to.have.property('secure', 1);
- expect(payload.imp[4]).to.have.property('bidfloor', 0);
- expect(payload.imp[4]).to.have.property('displaymanager', 'Prebid.js');
- expect(payload.imp[4]).to.have.property('displaymanagerver').that.matches(versionPattern);
- expect(payload.imp[4]).to.not.have.property('tagid');
- expect(payload.imp[4]).to.have.property('video');
- expect(payload.imp[4].video).to.not.have.property('pos');
- expect(payload.imp[4].video).to.have.property('w', 1024);
- expect(payload.imp[4].video).to.have.property('h', 768);
- expect(payload.imp[4].video).to.have.property('mimes');
- expect(payload.imp[4].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']);
- expect(payload.imp[4].video).to.have.property('protocols');
- expect(payload.imp[4].video.protocols).to.deep.equal([1, 2, 3]);
- expect(payload.imp[4].video).to.have.property('api');
- expect(payload.imp[4].video.api).to.deep.equal([2, 3]);
- expect(payload.imp[4].video).to.have.property('maxduration', 30);
- expect(payload.imp[4]).to.not.have.property('banner');
-
- expect(payload.imp[5]).to.have.property('id', 'bid005');
- expect(payload.imp[5]).to.have.property('secure', 1);
- expect(payload.imp[5]).to.have.property('bidfloor', 0);
- expect(payload.imp[5]).to.have.property('displaymanager', 'Prebid.js');
- expect(payload.imp[5]).to.have.property('displaymanagerver').that.matches(versionPattern);
- expect(payload.imp[5]).to.not.have.property('tagid');
- expect(payload.imp[5]).to.have.property('video');
- expect(payload.imp[5].video).to.have.property('pos', 2);
- expect(payload.imp[5].video).to.not.have.property('w');
- expect(payload.imp[5].video).to.not.have.property('h');
- expect(payload.imp[5].video).to.have.property('mimes');
- expect(payload.imp[5].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']);
- expect(payload.imp[5].video).to.not.have.property('protocols');
- expect(payload.imp[5].video).to.not.have.property('api');
- expect(payload.imp[5].video).to.not.have.property('maxduration');
- expect(payload.imp[5]).to.not.have.property('banner');
-
- expect(payload.imp[6]).to.have.property('id', 'bid006');
- expect(payload.imp[6]).to.have.property('video');
- expect(payload.imp[6].video).to.have.property('mimes');
- expect(payload.imp[6].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']);
- expect(payload.imp[6]).to.not.have.property('banner');
- expect(payload.imp[6]).to.have.property('instl');
- expect(payload.imp[6]).to.have.property('ext');
- expect(payload.imp[6].ext).to.have.property('data');
- expect(payload.imp[6].ext.data).to.have.property('pbadslot');
-
- expect(payload.imp[7]).to.have.property('id', 'bid007');
- expect(payload.imp[7]).to.have.property('secure', 1);
- expect(payload.imp[7]).to.have.property('bidfloor', 0);
- expect(payload.imp[7]).to.have.property('displaymanager', 'Prebid.js');
- expect(payload.imp[7]).to.have.property('displaymanagerver').that.matches(versionPattern);
- expect(payload.imp[7]).to.not.have.property('tagid');
- expect(payload.imp[7]).to.have.property('banner');
- expect(payload.imp[7].banner).to.have.property('pos', 5);
- expect(payload.imp[7].banner).to.have.property('format');
- expect(payload.imp[7].banner.format).to.deep.equal([{w: 728, h: 90}, {w: 468, h: 60}]);
-
- expect(payload).to.have.property('site');
- expect(payload.site).to.have.property('id', siteId);
- expect(payload.site).to.have.property('mobile').that.is.oneOf([0, 1]);
-
- expect(payload.site).to.have.property('page', page);
-
- expect(payload).to.have.property('device');
- expect(payload.device).to.have.property('w', screen.width);
- expect(payload.device).to.have.property('h', screen.height);
- expect(payload.device).to.have.property('dnt').that.is.oneOf([0, 1]);
- expect(payload.device).to.have.property('ua', navigator.userAgent);
-
- expect(payload).to.not.have.property('user'); // there should be no user by default
- expect(payload).to.not.have.property('tmax'); // there should be no user by default
+ it('Simple banner', () => {
+ expect(payload.imp[0]).to.have.property('id', 'bid000');
+ expect(payload.imp[0]).to.have.property('secure', 1);
+ expect(payload.imp[0]).to.have.property('bidfloor', 0.5);
+ expect(payload.imp[0]).to.have.property('displaymanager', 'Prebid.js');
+ expect(payload.imp[0]).to.have.property('displaymanagerver').that.matches(versionPattern);
+ expect(payload.imp[0]).to.have.property('tagid', 'tagid-1');
+ expect(payload.imp[0]).to.have.property('banner');
+ expect(payload.imp[0].banner).to.have.property('pos', 1);
+ expect(payload.imp[0].banner).to.have.property('format');
+ expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}]);
+ expect(payload.imp[0]).to.not.have.property('video');
+ });
+
+ it('Banner multiple sizes', () => {
+ expect(payload.imp[1]).to.have.property('id', 'bid001');
+ expect(payload.imp[1]).to.have.property('secure', 1);
+ expect(payload.imp[1]).to.have.property('bidfloor', 0);
+ expect(payload.imp[1]).to.have.property('displaymanager', 'Prebid.js');
+ expect(payload.imp[1]).to.have.property('displaymanagerver').that.matches(versionPattern);
+ expect(payload.imp[1]).to.not.have.property('tagid');
+ expect(payload.imp[1]).to.have.property('banner');
+ expect(payload.imp[1].banner).to.not.have.property('pos');
+ expect(payload.imp[1].banner).to.have.property('format');
+ expect(payload.imp[1].banner.format).to.deep.equal([{w: 728, h: 90}, {w: 468, h: 60}]);
+ });
+
+ it('Banner with tagid and position', () => {
+ expect(payload.imp[2]).to.have.property('id', 'bid002');
+ expect(payload.imp[2]).to.have.property('secure', 1);
+ expect(payload.imp[2]).to.have.property('bidfloor', 0);
+ expect(payload.imp[2]).to.have.property('displaymanager', 'Prebid.js');
+ expect(payload.imp[2]).to.have.property('displaymanagerver').that.matches(versionPattern);
+ expect(payload.imp[2]).to.have.property('banner');
+ expect(payload.imp[2].banner).to.have.property('pos', 2);
+ expect(payload.imp[2].banner).to.have.property('format');
+ expect(payload.imp[2].banner.format).to.deep.equal([{w: 300, h: 600}, {w: 160, h: 600}]);
+ });
+
+ if (FEATURES.VIDEO) {
+ it('Simple video', () => {
+ expect(payload.imp[3]).to.have.property('id', 'bid003');
+ expect(payload.imp[3]).to.have.property('secure', 1);
+ expect(payload.imp[3]).to.have.property('bidfloor', 0);
+ expect(payload.imp[3]).to.have.property('displaymanager', 'Prebid.js');
+ expect(payload.imp[3]).to.have.property('displaymanagerver').that.matches(versionPattern);
+ expect(payload.imp[3]).to.not.have.property('tagid');
+ expect(payload.imp[3]).to.have.property('video');
+ expect(payload.imp[3].video).to.have.property('pos', 3);
+ expect(payload.imp[3].video).to.have.property('w', 632);
+ expect(payload.imp[3].video).to.have.property('h', 499);
+ expect(payload.imp[3].video).to.have.property('mimes');
+ expect(payload.imp[3].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']);
+ expect(payload.imp[3].video).to.have.property('protocols');
+ expect(payload.imp[3].video.protocols).to.deep.equal([1, 2]);
+ expect(payload.imp[3].video).to.have.property('api');
+ expect(payload.imp[3].video.api).to.deep.equal([2]);
+ expect(payload.imp[3].video).to.have.property('maxduration', 30);
+ expect(payload.imp[3]).to.not.have.property('banner');
+ });
+
+ it('Video with playerSize', () => {
+ expect(payload.imp[4]).to.have.property('id', 'bid004');
+ expect(payload.imp[4]).to.have.property('secure', 1);
+ expect(payload.imp[4]).to.have.property('bidfloor', 0);
+ expect(payload.imp[4]).to.have.property('displaymanager', 'Prebid.js');
+ expect(payload.imp[4]).to.have.property('displaymanagerver').that.matches(versionPattern);
+ expect(payload.imp[4]).to.not.have.property('tagid');
+ expect(payload.imp[4]).to.have.property('video');
+ expect(payload.imp[4].video).to.not.have.property('pos');
+ expect(payload.imp[4].video).to.have.property('w', 1024);
+ expect(payload.imp[4].video).to.have.property('h', 768);
+ expect(payload.imp[4].video).to.have.property('mimes');
+ expect(payload.imp[4].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']);
+ expect(payload.imp[4].video).to.have.property('protocols');
+ expect(payload.imp[4].video.protocols).to.deep.equal([1, 2, 3]);
+ expect(payload.imp[4].video).to.have.property('api');
+ expect(payload.imp[4].video.api).to.deep.equal([1, 2, 3]);
+ expect(payload.imp[4].video).to.have.property('maxduration', 30);
+ });
+
+ it('Video without sizes', () => {
+ expect(payload.imp[5]).to.have.property('id', 'bid005');
+ expect(payload.imp[5]).to.have.property('secure', 1);
+ expect(payload.imp[5]).to.have.property('bidfloor', 0);
+ expect(payload.imp[5]).to.have.property('displaymanager', 'Prebid.js');
+ expect(payload.imp[5]).to.have.property('displaymanagerver').that.matches(versionPattern);
+ expect(payload.imp[5]).to.not.have.property('tagid');
+ expect(payload.imp[5]).to.have.property('video');
+ expect(payload.imp[5].video).to.have.property('pos', 2);
+ expect(payload.imp[5].video).to.not.have.property('w');
+ expect(payload.imp[5].video).to.not.have.property('h');
+ expect(payload.imp[5].video).to.have.property('mimes');
+ expect(payload.imp[5].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']);
+ expect(payload.imp[5].video).to.not.have.property('protocols');
+ expect(payload.imp[5].video).to.not.have.property('api');
+ expect(payload.imp[5].video).to.not.have.property('maxduration');
+ expect(payload.imp[5]).to.not.have.property('banner');
+ });
+ }
+
+ it('With FPD', () => {
+ expect(payload.imp[6]).to.have.property('id', 'bid006');
+ expect(payload.imp[6]).to.have.property('banner');
+ expect(payload.imp[6]).to.not.have.property('video');
+ expect(payload.imp[6]).to.have.property('instl');
+ expect(payload.imp[6]).to.have.property('ext');
+ expect(payload.imp[6].ext).to.have.property('data');
+ expect(payload.imp[6].ext.data).to.have.property('pbadslot');
+ });
});
it('Verify timeout', () => {
@@ -440,59 +460,62 @@ describe('Conversant adapter tests', function() {
expect(request.url).to.equal(testUrl);
});
- it('Verify interpretResponse', function() {
- const request = spec.buildRequests(bidRequests, {});
- const response = spec.interpretResponse(bidResponses, request);
- expect(response).to.be.an('array').with.lengthOf(4);
-
- let bid = response[0];
- expect(bid).to.have.property('requestId', 'bid000');
- expect(bid).to.have.property('currency', 'USD');
- expect(bid).to.have.property('cpm', 0.99);
- expect(bid).to.have.property('creativeId', '1000');
- expect(bid).to.have.property('width', 300);
- expect(bid).to.have.property('height', 250);
- expect(bid.meta.advertiserDomains).to.deep.equal(['https://example.com']);
- expect(bid).to.have.property('ad', 'markup000

');
- expect(bid).to.have.property('ttl', 300);
- expect(bid).to.have.property('netRevenue', true);
+ describe('Verify interpretResponse', function() {
+ let bid, request, response;
+
+ before(() => {
+ request = spec.buildRequests(bidRequests, {});
+ response = spec.interpretResponse(bidResponses, request).bids;
+ });
+
+ it('Banner', function() {
+ expect(response).to.be.an('array').with.lengthOf(4);
+ bid = response[0];
+ expect(bid).to.have.property('requestId', 'bid000');
+ expect(bid).to.have.property('cpm', 0.99);
+ expect(bid).to.have.property('creativeId', '1000');
+ expect(bid).to.have.property('width', 300);
+ expect(bid).to.have.property('height', 250);
+ expect(bid.meta.advertiserDomains).to.deep.equal(['https://example.com']);
+ expect(bid).to.have.property('ad', 'markup000

');
+ expect(bid).to.have.property('ttl', 300);
+ expect(bid).to.have.property('netRevenue', true);
+ });
// There is no bid001 because cpm is $0
- bid = response[1];
- expect(bid).to.have.property('requestId', 'bid002');
- expect(bid).to.have.property('currency', 'USD');
- expect(bid).to.have.property('cpm', 2.99);
- expect(bid).to.have.property('creativeId', '1002');
- expect(bid).to.have.property('width', 300);
- expect(bid).to.have.property('height', 600);
- expect(bid).to.have.property('ad', 'markup002

');
- expect(bid).to.have.property('ttl', 300);
- expect(bid).to.have.property('netRevenue', true);
-
- bid = response[2];
- expect(bid).to.have.property('requestId', 'bid003');
- expect(bid).to.have.property('currency', 'USD');
- expect(bid).to.have.property('cpm', 3.99);
- expect(bid).to.have.property('creativeId', '1003');
- expect(bid).to.have.property('width', 632);
- expect(bid).to.have.property('height', 499);
- expect(bid).to.have.property('vastUrl', 'markup003');
- expect(bid).to.have.property('mediaType', 'video');
- expect(bid).to.have.property('ttl', 300);
- expect(bid).to.have.property('netRevenue', true);
-
- bid = response[3];
- expect(bid).to.have.property('vastXml', '
');
- });
+ it('Banner multiple sizes', function() {
+ bid = response[1];
+ expect(bid).to.have.property('requestId', 'bid002');
+ expect(bid).to.have.property('cpm', 2.99);
+ expect(bid).to.have.property('creativeId', '1002');
+ expect(bid).to.have.property('width', 300);
+ expect(bid).to.have.property('height', 600);
+ expect(bid).to.have.property('ad', 'markup002

');
+ expect(bid).to.have.property('ttl', 300);
+ expect(bid).to.have.property('netRevenue', true);
+ });
+
+ if (FEATURES.VIDEO) {
+ it('Video', function () {
+ bid = response[2];
+ expect(bid).to.have.property('requestId', 'bid003');
+ expect(bid).to.have.property('cpm', 3.99);
+ expect(bid).to.have.property('creativeId', '1003');
+ expect(bid).to.have.property('playerWidth', 632);
+ expect(bid).to.have.property('playerHeight', 499);
+ expect(bid).to.have.property('vastUrl', 'notify003');
+ expect(bid).to.have.property('vastXml', 'markup003');
+ expect(bid).to.have.property('mediaType', 'video');
+ expect(bid).to.have.property('ttl', 300);
+ expect(bid).to.have.property('netRevenue', true);
+ });
- it('Verify handling of bad responses', function() {
- let response = spec.interpretResponse({}, {});
- expect(response).to.be.an('array').with.lengthOf(0);
- response = spec.interpretResponse({id: '123'}, {});
- expect(response).to.be.an('array').with.lengthOf(0);
- response = spec.interpretResponse({id: '123', seatbid: []}, {});
- expect(response).to.be.an('array').with.lengthOf(0);
+ it('Empty Video', function() {
+ bid = response[3];
+ expect(bid).to.have.property('vastXml', '
');
+ });
+ }
});
it('Verify publisher commond id support', function() {
@@ -524,79 +547,23 @@ describe('Conversant adapter tests', function() {
expect(payload).to.not.have.nested.property('user.ext.eids');
});
- it('Verify GDPR bid request', function() {
- // add gdpr info
- const bidderRequest = {
- gdprConsent: {
- consentString: 'BOJObISOJObISAABAAENAA4AAAAAoAAA',
- gdprApplies: true
- }
- };
-
- const payload = spec.buildRequests(bidRequests, bidderRequest).data;
- expect(payload).to.have.deep.nested.property('user.ext.consent', 'BOJObISOJObISAABAAENAA4AAAAAoAAA');
- expect(payload).to.have.deep.nested.property('regs.ext.gdpr', 1);
- });
-
- it('Verify GDPR bid request without gdprApplies', function() {
- // add gdpr info
- const bidderRequest = {
- gdprConsent: {
- consentString: ''
- }
- };
-
- const payload = spec.buildRequests(bidRequests, bidderRequest).data;
- expect(payload).to.have.deep.nested.property('user.ext.consent', '');
- expect(payload).to.not.have.deep.nested.property('regs.ext.gdpr');
- });
-
- describe('CCPA', function() {
- it('should have us_privacy', function() {
- const bidderRequest = {
- uspConsent: '1NYN'
- };
-
- const payload = spec.buildRequests(bidRequests, bidderRequest).data;
- expect(payload).to.have.deep.nested.property('regs.ext.us_privacy', '1NYN');
- expect(payload).to.not.have.deep.nested.property('regs.ext.gdpr');
- });
-
- it('should have no us_privacy', function() {
- const payload = spec.buildRequests(bidRequests, {}).data;
- expect(payload).to.not.have.deep.nested.property('regs.ext.us_privacy');
- });
-
- it('should have both gdpr and us_privacy', function() {
- const bidderRequest = {
- gdprConsent: {
- consentString: 'BOJObISOJObISAABAAENAA4AAAAAoAAA',
- gdprApplies: true
- },
- uspConsent: '1NYN'
- };
-
- const payload = spec.buildRequests(bidRequests, bidderRequest).data;
- expect(payload).to.have.deep.nested.property('user.ext.consent', 'BOJObISOJObISAABAAENAA4AAAAAoAAA');
- expect(payload).to.have.deep.nested.property('regs.ext.gdpr', 1);
- expect(payload).to.have.deep.nested.property('regs.ext.us_privacy', '1NYN');
- });
- });
-
describe('Extended ID', function() {
it('Verify unifiedid and liveramp', function() {
// clone bidRequests
let requests = utils.deepClone(bidRequests);
+ const uid = {pubcid: '112233', idl_env: '334455'};
+ const eidArray = [{'source': 'pubcid.org', 'uids': [{'id': '112233', 'atype': 1}]}, {'source': 'liveramp.com', 'uids': [{'id': '334455', 'atype': 3}]}];
+
// add pubcid to every entry
requests.forEach((unit) => {
- Object.assign(unit, {userId: {pubcid: '112233', tdid: '223344', idl_env: '334455'}});
- Object.assign(unit, {userIdAsEids: createEidsArray(unit.userId)});
+ Object.assign(unit, {userId: uid});
+ Object.assign(unit, {userIdAsEids: eidArray});
});
// construct http post payload
const payload = spec.buildRequests(requests, {}).data;
expect(payload).to.have.deep.nested.property('user.ext.eids', [
- {source: 'adserver.org', uids: [{id: '223344', atype: 1, ext: {rtiPartner: 'TDID'}}]},
+ {source: 'pubcid.org', uids: [{id: '112233', atype: 1}]},
{source: 'liveramp.com', uids: [{id: '334455', atype: 3}]}
]);
});
diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js
index 97b80ce95db..ce07c6e49bc 100755
--- a/test/spec/modules/criteoBidAdapter_spec.js
+++ b/test/spec/modules/criteoBidAdapter_spec.js
@@ -364,93 +364,6 @@ describe('The Criteo bidding adapter', function () {
});
it('should return false when given an invalid video bid request', function () {
- expect(spec.isBidRequestValid({
- bidder: 'criteo',
- mediaTypes: {
- video: {
- mimes: ['video/mpeg'],
- playerSize: [640, 480],
- protocols: [5, 6],
- maxduration: 30,
- api: [1, 2]
- }
- },
- params: {
- networkId: 456,
- video: {
- skip: 1,
- placement: 1,
- playbackmethod: 1
- }
- },
- })).to.equal(false);
-
- expect(spec.isBidRequestValid({
- bidder: 'criteo',
- mediaTypes: {
- video: {
- context: 'instream',
- mimes: ['video/mpeg'],
- playerSize: [640, 480],
- protocols: [5, 6],
- maxduration: 30,
- api: [1, 2]
- }
- },
- params: {
- networkId: 456,
- video: {
- skip: 1,
- placement: 2,
- playbackmethod: 1
- }
- },
- })).to.equal(false);
-
- expect(spec.isBidRequestValid({
- bidder: 'criteo',
- mediaTypes: {
- video: {
- context: 'outstream',
- mimes: ['video/mpeg'],
- playerSize: [640, 480],
- protocols: [5, 6],
- maxduration: 30,
- api: [1, 2]
- }
- },
- params: {
- networkId: 456,
- video: {
- skip: 1,
- placement: 1,
- playbackmethod: 1
- }
- },
- })).to.equal(false);
-
- expect(spec.isBidRequestValid({
- bidder: 'criteo',
- mediaTypes: {
- video: {
- context: 'adpod',
- mimes: ['video/mpeg'],
- playerSize: [640, 480],
- protocols: [5, 6],
- maxduration: 30,
- api: [1, 2]
- }
- },
- params: {
- networkId: 456,
- video: {
- skip: 1,
- placement: 1,
- playbackmethod: 1
- }
- },
- })).to.equal(false);
-
expect(spec.isBidRequestValid({
bidder: 'criteo',
mediaTypes: {
@@ -1122,6 +1035,30 @@ describe('The Criteo bidding adapter', function () {
expect(request.data.user.uspIab).to.equal('1YNY');
});
+ it('should properly build a request with site and app ortb fields', function () {
+ const bidRequests = [];
+ let app = {
+ publisher: {
+ id: 'appPublisherId'
+ }
+ };
+ let site = {
+ publisher: {
+ id: 'sitePublisherId'
+ }
+ };
+ const bidderRequest = {
+ ortb2: {
+ app: app,
+ site: site
+ }
+ };
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+
+ expect(request.data.app).to.equal(app);
+ expect(request.data.site).to.equal(site);
+ });
+
it('should properly build a request with device sua field', function () {
const sua = {}
const bidRequests = [
@@ -1173,7 +1110,7 @@ describe('The Criteo bidding adapter', function () {
const ortb2 = {
regs: {
gpp: 'gpp_consent_string',
- gpp_sid: [0, 1, 2]
+ gpp_sid: [0, 1, 2],
}
};
@@ -1183,6 +1120,48 @@ describe('The Criteo bidding adapter', function () {
expect(request.data.regs.gpp_sid).to.deep.equal([0, 1, 2]);
});
+ it('should properly build a request with dsa object', function () {
+ const bidRequests = [
+ {
+ bidder: 'criteo',
+ adUnitCode: 'bid-123',
+ transactionId: 'transaction-123',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90]]
+ }
+ },
+ params: {
+ zoneId: 123,
+ },
+ },
+ ];
+ let dsa = {
+ required: 3,
+ pubrender: 0,
+ datatopub: 2,
+ transparency: [{
+ domain: 'platform1domain.com',
+ params: [1]
+ }, {
+ domain: 'SSP2domain.com',
+ params: [1, 2]
+ }]
+ };
+ const ortb2 = {
+ regs: {
+ ext: {
+ dsa: dsa
+ }
+ }
+ };
+
+ const request = spec.buildRequests(bidRequests, { ...bidderRequest, ortb2 });
+ expect(request.data.regs).to.not.be.null;
+ expect(request.data.regs.ext).to.not.be.null;
+ expect(request.data.regs.ext.dsa).to.deep.equal(dsa);
+ });
+
it('should properly build a request with schain object', function () {
const expectedSchain = {
someProperty: 'someValue'
@@ -1969,6 +1948,22 @@ describe('The Criteo bidding adapter', function () {
const request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.slots[0].ext).to.not.have.property('ae');
});
+
+ it('should properly transmit device.ext.cdep if available', function () {
+ const bidderRequest = {
+ ortb2: {
+ device: {
+ ext: {
+ cdep: 'cookieDeprecationLabel'
+ }
+ }
+ }
+ };
+ const bidRequests = [];
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ const ortbRequest = request.data;
+ expect(ortbRequest.device.ext.cdep).to.equal('cookieDeprecationLabel');
+ });
});
describe('interpretResponse', function () {
@@ -2026,6 +2021,48 @@ describe('The Criteo bidding adapter', function () {
expect(bids[0].meta.networkName).to.equal('Criteo');
});
+ it('should properly parse a bid response with dsa', function () {
+ const response = {
+ body: {
+ slots: [{
+ impid: 'test-requestId',
+ cpm: 1.23,
+ creative: 'test-ad',
+ creativecode: 'test-crId',
+ width: 728,
+ height: 90,
+ deal: 'myDealCode',
+ adomain: ['criteo.com'],
+ ext: {
+ dsa: {
+ adrender: 1
+ },
+ meta: {
+ networkName: 'Criteo'
+ }
+ }
+ }],
+ },
+ };
+ const request = {
+ bidRequests: [{
+ adUnitCode: 'test-requestId',
+ bidId: 'test-bidId',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90]]
+ }
+ },
+ params: {
+ networkId: 456,
+ }
+ }]
+ };
+ const bids = spec.interpretResponse(response, request);
+ expect(bids).to.have.lengthOf(1);
+ expect(bids[0].meta.adrender).to.equal(1);
+ });
+
it('should properly parse a bid response with a networkId with twin ad unit banner win', function () {
const response = {
body: {
@@ -2517,12 +2554,30 @@ describe('The Criteo bidding adapter', function () {
foo: 'baz',
},
}]
+ }, {
+ impid: 'test-bidId-2',
+ igbuyer: [{
+ origin: 'https://first-buyer-domain.com',
+ buyerdata: {
+ foo: 'bar',
+ },
+ }, {
+ origin: 'https://second-buyer-domain.com',
+ buyerdata: {
+ foo: 'baz',
+ },
+ }]
}],
seller: 'https://seller-domain.com',
sellerTimeout: 500,
sellerSignals: {
foo: 'bar',
},
+ sellerSignalsPerImp: {
+ 'test-bidId': {
+ foo2: 'bar2',
+ }
+ },
},
},
};
@@ -2549,15 +2604,54 @@ describe('The Criteo bidding adapter', function () {
bidFloorCur: 'EUR'
}
},
+ {
+ bidId: 'test-bidId-2',
+ bidder: 'criteo',
+ adUnitCode: 'bid-123',
+ transactionId: 'transaction-123',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90]]
+ }
+ },
+ params: {
+ bidFloor: 1,
+ bidFloorCur: 'EUR'
+ }
+ },
];
const request = spec.buildRequests(bidRequests, bidderRequest);
const interpretedResponse = spec.interpretResponse(response, request);
expect(interpretedResponse).to.have.property('bids');
expect(interpretedResponse).to.have.property('fledgeAuctionConfigs');
expect(interpretedResponse.bids).to.have.lengthOf(0);
- expect(interpretedResponse.fledgeAuctionConfigs).to.have.lengthOf(1);
+ expect(interpretedResponse.fledgeAuctionConfigs).to.have.lengthOf(2);
expect(interpretedResponse.fledgeAuctionConfigs[0]).to.deep.equal({
bidId: 'test-bidId',
+ config: {
+ auctionSignals: {},
+ decisionLogicUrl: 'https://grid-mercury.criteo.com/fledge/decision',
+ interestGroupBuyers: ['https://first-buyer-domain.com', 'https://second-buyer-domain.com'],
+ perBuyerSignals: {
+ 'https://first-buyer-domain.com': {
+ foo: 'bar',
+ },
+ 'https://second-buyer-domain.com': {
+ foo: 'baz'
+ },
+ },
+ seller: 'https://seller-domain.com',
+ sellerTimeout: 500,
+ sellerSignals: {
+ foo: 'bar',
+ foo2: 'bar2',
+ floor: 1,
+ sellerCurrency: 'EUR',
+ },
+ },
+ });
+ expect(interpretedResponse.fledgeAuctionConfigs[1]).to.deep.equal({
+ bidId: 'test-bidId-2',
config: {
auctionSignals: {},
decisionLogicUrl: 'https://grid-mercury.criteo.com/fledge/decision',
diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js
index 623194cbee9..fa44b7daa7a 100644
--- a/test/spec/modules/currency_spec.js
+++ b/test/spec/modules/currency_spec.js
@@ -259,6 +259,19 @@ describe('currency', function () {
expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000');
});
+ it('does not block auctions if rates do not need to be fetched', () => {
+ sandbox.stub(responseReady, 'resolve');
+ setConfig({
+ adServerCurrency: 'USD',
+ rates: {
+ USD: {
+ JPY: 100
+ }
+ }
+ });
+ sinon.assert.called(responseReady.resolve);
+ })
+
it('uses rates specified in json when provided and consider boosted bid', function () {
setConfig({
adServerCurrency: 'USD',
diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js
index 4c12e9fa211..39713c2b51a 100644
--- a/test/spec/modules/dfpAdServerVideo_spec.js
+++ b/test/spec/modules/dfpAdServerVideo_spec.js
@@ -1,43 +1,61 @@
-import { expect } from 'chai';
+import {expect} from 'chai';
import parse from 'url-parse';
-import {buildDfpVideoUrl, buildAdpodVideoUrl, dep} from 'modules/dfpAdServerVideo.js';
-import adUnit from 'test/fixtures/video/adUnit.json';
+import {buildAdpodVideoUrl, buildDfpVideoUrl, dep} from 'modules/dfpAdServerVideo.js';
+import AD_UNIT from 'test/fixtures/video/adUnit.json';
import * as utils from 'src/utils.js';
-import { config } from 'src/config.js';
-import { targeting } from 'src/targeting.js';
-import { auctionManager } from 'src/auctionManager.js';
-import { gdprDataHandler, uspDataHandler } from 'src/adapterManager.js';
+import {deepClone} from 'src/utils.js';
+import {config} from 'src/config.js';
+import {targeting} from 'src/targeting.js';
+import {auctionManager} from 'src/auctionManager.js';
+import {gdprDataHandler, uspDataHandler} from 'src/adapterManager.js';
import * as adpod from 'modules/adpod.js';
-import { server } from 'test/mocks/xhr.js';
+import {server} from 'test/mocks/xhr.js';
import * as adServer from 'src/adserver.js';
-import {deepClone} from 'src/utils.js';
import {hook} from '../../../src/hook.js';
-import {getRefererInfo} from '../../../src/refererDetection.js';
-
-const bid = {
- videoCacheKey: 'abc',
- adserverTargeting: {
- hb_uuid: 'abc',
- hb_cache_id: 'abc',
- },
-};
+import {stubAuctionIndex} from '../../helpers/indexStub.js';
+import {AuctionIndex} from '../../../src/auctionIndex.js';
describe('The DFP video support module', function () {
before(() => {
hook.ready();
});
- let sandbox;
+ let sandbox, bid, adUnit;
beforeEach(() => {
sandbox = sinon.sandbox.create();
+ bid = {
+ videoCacheKey: 'abc',
+ adserverTargeting: {
+ hb_uuid: 'abc',
+ hb_cache_id: 'abc',
+ },
+ };
+ adUnit = deepClone(AD_UNIT);
});
afterEach(() => {
sandbox.restore();
});
+ function getURL(options) {
+ return parse(buildDfpVideoUrl(Object.assign({
+ adUnit: adUnit,
+ bid: bid,
+ params: {
+ 'iu': 'my/adUnit'
+ }
+ }, options)))
+ }
+ function getQueryParams(options) {
+ return utils.parseQS(getURL(options).query);
+ }
+
+ function getCustomParams(options) {
+ return utils.parseQS('?' + decodeURIComponent(getQueryParams(options).cust_params));
+ }
+
Object.entries({
params: {
params: {
@@ -51,37 +69,25 @@ describe('The DFP video support module', function () {
describe(`when using ${t}`, () => {
it('should use page location as default for description_url', () => {
sandbox.stub(dep, 'ri').callsFake(() => ({page: 'example.com'}));
-
- const url = parse(buildDfpVideoUrl(Object.assign({
- adUnit: adUnit,
- bid: bid,
- }, options)));
- const prm = utils.parseQS(url.query);
+ const prm = getQueryParams(options);
expect(prm.description_url).to.eql('example.com');
});
it('should use a URI encoded page location as default for description_url', () => {
sandbox.stub(dep, 'ri').callsFake(() => ({page: 'https://example.com?iu=/99999999/news&cust_params=current_hour%3D12%26newscat%3Dtravel&pbjs_debug=true'}));
- const url = parse(buildDfpVideoUrl(Object.assign({
- adUnit: adUnit,
- bid: bid,
- }, options)));
- const prm = utils.parseQS(url.query);
+ const prm = getQueryParams(options);
expect(prm.description_url).to.eql('https%3A%2F%2Fexample.com%3Fiu%3D%2F99999999%2Fnews%26cust_params%3Dcurrent_hour%253D12%2526newscat%253Dtravel%26pbjs_debug%3Dtrue');
});
});
})
it('should make a legal request URL when given the required params', function () {
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bid,
+ const url = getURL({
params: {
'iu': 'my/adUnit',
'description_url': 'someUrl.com',
}
- }));
-
+ })
expect(url.protocol).to.equal('https:');
expect(url.host).to.equal('securepubads.g.doubleclick.net');
@@ -98,15 +104,10 @@ describe('The DFP video support module', function () {
});
it('can take an adserver url as a parameter', function () {
- const bidCopy = utils.deepClone(bid);
- bidCopy.vastUrl = 'vastUrl.example';
-
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bidCopy,
+ bid.vastUrl = 'vastUrl.example';
+ const url = getURL({
url: 'https://video.adserver.example/',
- }));
-
+ })
expect(url.host).to.equal('video.adserver.example');
});
@@ -120,161 +121,64 @@ describe('The DFP video support module', function () {
});
it('overwrites url params when both url and params object are given', function () {
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bid,
+ const params = getQueryParams({
url: 'https://video.adserver.example/ads?sz=640x480&iu=/123/aduniturl&impl=s',
params: { iu: 'my/adUnit' }
- }));
+ });
- const queryObject = utils.parseQS(url.query);
- expect(queryObject.iu).to.equal('my/adUnit');
+ expect(params.iu).to.equal('my/adUnit');
});
it('should override param defaults with user-provided ones', function () {
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bid,
+ const params = getQueryParams({
params: {
- 'iu': 'my/adUnit',
'output': 'vast',
}
- }));
-
- expect(utils.parseQS(url.query)).to.have.property('output', 'vast');
+ });
+ expect(params.output).to.equal('vast');
});
it('should include the cache key and adserver targeting in cust_params', function () {
- const bidCopy = utils.deepClone(bid);
- bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, {
+ bid.adserverTargeting = Object.assign(bid.adserverTargeting, {
hb_adid: 'ad_id',
});
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bidCopy,
- params: {
- 'iu': 'my/adUnit'
- }
- }));
- const queryObject = utils.parseQS(url.query);
- const customParams = utils.parseQS('?' + decodeURIComponent(queryObject.cust_params));
+ const customParams = getCustomParams()
expect(customParams).to.have.property('hb_adid', 'ad_id');
expect(customParams).to.have.property('hb_uuid', bid.videoCacheKey);
expect(customParams).to.have.property('hb_cache_id', bid.videoCacheKey);
});
- it('should include the us_privacy key when USP Consent is available', function () {
- let uspDataHandlerStub = sinon.stub(uspDataHandler, 'getConsentData');
- uspDataHandlerStub.returns('1YYY');
-
- const bidCopy = utils.deepClone(bid);
- bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, {
- hb_adid: 'ad_id',
- });
-
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bidCopy,
- params: {
- 'iu': 'my/adUnit'
- }
- }));
- const queryObject = utils.parseQS(url.query);
- expect(queryObject.us_privacy).to.equal('1YYY');
- uspDataHandlerStub.restore();
- });
-
- it('should not include the us_privacy key when USP Consent is not available', function () {
- const bidCopy = utils.deepClone(bid);
- bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, {
- hb_adid: 'ad_id',
- });
-
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bidCopy,
- params: {
- 'iu': 'my/adUnit'
- }
- }));
- const queryObject = utils.parseQS(url.query);
- expect(queryObject.us_privacy).to.equal(undefined);
- });
-
it('should include the GDPR keys when GDPR Consent is available', function () {
- let gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData');
- gdprDataHandlerStub.returns({
+ sandbox.stub(gdprDataHandler, 'getConsentData').returns({
gdprApplies: true,
consentString: 'consent',
addtlConsent: 'moreConsent'
});
-
- const bidCopy = utils.deepClone(bid);
- bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, {
- hb_adid: 'ad_id',
- });
-
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bidCopy,
- params: {
- 'iu': 'my/adUnit'
- }
- }));
- const queryObject = utils.parseQS(url.query);
+ const queryObject = getQueryParams();
expect(queryObject.gdpr).to.equal('1');
expect(queryObject.gdpr_consent).to.equal('consent');
expect(queryObject.addtl_consent).to.equal('moreConsent');
- gdprDataHandlerStub.restore();
});
it('should not include the GDPR keys when GDPR Consent is not available', function () {
- const bidCopy = utils.deepClone(bid);
- bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, {
- hb_adid: 'ad_id',
- });
-
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bidCopy,
- params: {
- 'iu': 'my/adUnit'
- }
- }));
- const queryObject = utils.parseQS(url.query);
+ const queryObject = getQueryParams()
expect(queryObject.gdpr).to.equal(undefined);
expect(queryObject.gdpr_consent).to.equal(undefined);
expect(queryObject.addtl_consent).to.equal(undefined);
});
it('should only include the GDPR keys for GDPR Consent fields with values', function () {
- let gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData');
- gdprDataHandlerStub.returns({
+ sandbox.stub(gdprDataHandler, 'getConsentData').returns({
gdprApplies: true,
consentString: 'consent',
});
-
- const bidCopy = utils.deepClone(bid);
- bidCopy.adserverTargeting = Object.assign(bidCopy.adserverTargeting, {
- hb_adid: 'ad_id',
- });
-
- const url = parse(buildDfpVideoUrl({
- adUnit: adUnit,
- bid: bidCopy,
- params: {
- 'iu': 'my/adUnit'
- }
- }));
- const queryObject = utils.parseQS(url.query);
+ const queryObject = getQueryParams()
expect(queryObject.gdpr).to.equal('1');
expect(queryObject.gdpr_consent).to.equal('consent');
expect(queryObject.addtl_consent).to.equal(undefined);
- gdprDataHandlerStub.restore();
});
-
describe('GAM PPID', () => {
let ppid;
let getPPIDStub;
@@ -290,29 +194,283 @@ describe('The DFP video support module', function () {
'url': {url: 'https://video.adserver.mock/', params: {'iu': 'mock/unit'}}
}).forEach(([t, opts]) => {
describe(`when using ${t}`, () => {
- function buildUrlAndGetParams() {
- const url = parse(buildDfpVideoUrl(Object.assign({
- adUnit: adUnit,
- bid: deepClone(bid),
- }, opts)));
- return utils.parseQS(url.query);
- }
-
it('should be included if available', () => {
ppid = 'mockPPID';
- const q = buildUrlAndGetParams();
+ const q = getQueryParams(opts);
expect(q.ppid).to.equal('mockPPID');
});
it('should not be included if not available', () => {
ppid = undefined;
- const q = buildUrlAndGetParams();
+ const q = getQueryParams(opts);
expect(q.hasOwnProperty('ppid')).to.be.false;
})
})
})
})
+ describe('ORTB video parameters', () => {
+ Object.entries({
+ plcmt: [
+ {
+ video: {
+ plcmt: 1
+ },
+ expected: '1'
+ }
+ ],
+ min_ad_duration: [
+ {
+ video: {
+ minduration: 123
+ },
+ expected: '123000'
+ }
+ ],
+ max_ad_duration: [
+ {
+ video: {
+ maxduration: 321
+ },
+ expected: '321000'
+ }
+ ],
+ vpos: [
+ {
+ video: {
+ startdelay: 0
+ },
+ expected: 'preroll'
+ },
+ {
+ video: {
+ startdelay: -1
+ },
+ expected: 'midroll'
+ },
+ {
+ video: {
+ startdelay: -2
+ },
+ expected: 'postroll'
+ },
+ {
+ video: {
+ startdelay: 10
+ },
+ expected: 'midroll'
+ }
+ ],
+ vconp: [
+ {
+ video: {
+ playbackmethod: [7]
+ },
+ expected: '2'
+ },
+ {
+ video: {
+ playbackmethod: [7, 1]
+ },
+ expected: undefined
+ }
+ ],
+ vpa: [
+ {
+ video: {
+ playbackmethod: [1, 2, 4, 5, 6, 7]
+ },
+ expected: 'auto'
+ },
+ {
+ video: {
+ playbackmethod: [3, 7],
+ },
+ expected: 'click'
+ },
+ {
+ video: {
+ playbackmethod: [1, 3],
+ },
+ expected: undefined
+ }
+ ],
+ vpmute: [
+ {
+ video: {
+ playbackmethod: [1, 3, 4, 5, 7]
+ },
+ expected: '0'
+ },
+ {
+ video: {
+ playbackmethod: [2, 6, 7],
+ },
+ expected: '1'
+ },
+ {
+ video: {
+ playbackmethod: [1, 2]
+ },
+ expected: undefined
+ }
+ ]
+ }).forEach(([param, cases]) => {
+ describe(param, () => {
+ cases.forEach(({video, expected}) => {
+ describe(`when mediaTypes.video has ${JSON.stringify(video)}`, () => {
+ it(`fills in ${param} = ${expected}`, () => {
+ Object.assign(adUnit.mediaTypes.video, video);
+ expect(getQueryParams()[param]).to.eql(expected);
+ });
+ it(`does not override pub-provided params.${param}`, () => {
+ Object.assign(adUnit.mediaTypes.video, video);
+ expect(getQueryParams({
+ params: {
+ [param]: 'OG'
+ }
+ })[param]).to.eql('OG');
+ });
+ it('does not fill if param has no value', () => {
+ expect(getQueryParams().hasOwnProperty(param)).to.be.false;
+ })
+ })
+ })
+ })
+ })
+ });
+
+ describe('ppsj', () => {
+ let ortb2;
+ beforeEach(() => {
+ ortb2 = null;
+ })
+
+ function getSignals() {
+ const ppsj = JSON.parse(atob(getQueryParams().ppsj));
+ return Object.fromEntries(ppsj.PublisherProvidedTaxonomySignals.map(sig => [sig.taxonomy, sig.values]));
+ }
+
+ Object.entries({
+ 'FPD from bid request'() {
+ bid.requestId = 'req-id';
+ sandbox.stub(auctionManager, 'index').get(() => stubAuctionIndex({
+ bidRequests: [
+ {
+ bidId: 'req-id',
+ ortb2
+ }
+ ]
+ }));
+ },
+ 'global FPD from auction'() {
+ bid.auctionId = 'auid';
+ sandbox.stub(auctionManager, 'index').get(() => new AuctionIndex(() => [{
+ getAuctionId: () => 'auid',
+ getFPD: () => ({
+ global: ortb2
+ })
+ }]));
+ }
+ }).forEach(([t, setup]) => {
+ describe(`using ${t}`, () => {
+ beforeEach(setup);
+ it('does not fill if there\'s no segments in segtax 4 or 6', () => {
+ ortb2 = {
+ site: {
+ content: {
+ data: [
+ {
+ segment: [
+ {id: '1'},
+ {id: '2'}
+ ]
+ },
+ ]
+ }
+ },
+ user: {
+ data: [
+ {
+ ext: {
+ segtax: 1,
+ },
+ segment: [
+ {id: '3'}
+ ]
+ }
+ ]
+ }
+ }
+ expect(getQueryParams().ppsj).to.not.exist;
+ });
+
+ const SEGMENTS = [
+ {
+ ext: {
+ segtax: 4,
+ },
+ segment: [
+ {id: '4-1'},
+ {id: '4-2'}
+ ]
+ },
+ {
+ ext: {
+ segtax: 4,
+ },
+ segment: [
+ {id: '4-2'},
+ {id: '4-3'}
+ ]
+ },
+ {
+ ext: {
+ segtax: 6,
+ },
+ segment: [
+ {id: '6-1'},
+ {id: '6-2'}
+ ]
+ },
+ {
+ ext: {
+ segtax: 6,
+ },
+ segment: [
+ {id: '6-2'},
+ {id: '6-3'}
+ ]
+ },
+ ]
+
+ it('collects user.data segments with segtax = 4 into IAB_AUDIENCE_1_1', () => {
+ ortb2 = {
+ user: {
+ data: SEGMENTS
+ }
+ }
+ expect(getSignals()).to.eql({
+ IAB_AUDIENCE_1_1: ['4-1', '4-2', '4-3']
+ })
+ })
+
+ it('collects site.content.data segments with segtax = 6 into IAB_CONTENT_2_2', () => {
+ ortb2 = {
+ site: {
+ content: {
+ data: SEGMENTS
+ }
+ }
+ }
+ expect(getSignals()).to.eql({
+ IAB_CONTENT_2_2: ['6-1', '6-2', '6-3']
+ })
+ })
+ })
+ })
+ })
+
describe('special targeting unit test', function () {
const allTargetingData = {
'hb_format': 'video',
@@ -639,7 +797,6 @@ describe('The DFP video support module', function () {
expect(queryParams).to.have.property('unviewed_position_start', '1');
expect(queryParams).to.have.property('url');
expect(queryParams).to.have.property('cust_params');
- expect(queryParams).to.have.property('us_privacy', '1YYY');
expect(queryParams).to.have.property('gdpr', '1');
expect(queryParams).to.have.property('gdpr_consent', 'consent');
expect(queryParams).to.have.property('addtl_consent', 'moreConsent');
diff --git a/test/spec/modules/discoveryBidAdapter_spec.js b/test/spec/modules/discoveryBidAdapter_spec.js
index 8957f8bbd40..961ccb33c4f 100644
--- a/test/spec/modules/discoveryBidAdapter_spec.js
+++ b/test/spec/modules/discoveryBidAdapter_spec.js
@@ -1,5 +1,17 @@
import { expect } from 'chai';
-import { spec } from 'modules/discoveryBidAdapter.js';
+import {
+ spec,
+ getPmgUID,
+ storage,
+ getPageTitle,
+ getPageDescription,
+ getPageKeywords,
+ getConnectionDownLink,
+ THIRD_PARTY_COOKIE_ORIGIN,
+ COOKIE_KEY_MGUID,
+ getCurrentTimeToUTCString
+} from 'modules/discoveryBidAdapter.js';
+import * as utils from 'src/utils.js';
describe('discovery:BidAdapterTests', function () {
let bidRequestData = {
@@ -79,6 +91,77 @@ describe('discovery:BidAdapterTests', function () {
};
let request = [];
+ let bidRequestDataNoParams = {
+ bidderCode: 'discovery',
+ auctionId: 'ff66e39e-4075-4d18-9854-56fde9b879ac',
+ bidderRequestId: '4fec04e87ad785',
+ bids: [
+ {
+ bidder: 'discovery',
+ params: {
+ referrer: 'https://discovery.popin.cc',
+ },
+ refererInfo: {
+ page: 'https://discovery.popin.cc',
+ stack: [
+ 'a.com',
+ 'b.com'
+ ]
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250]],
+ pos: 'left',
+ },
+ },
+ ortb2: {
+ user: {
+ ext: {
+ data: {
+ CxSegments: []
+ }
+ }
+ },
+ site: {
+ domain: 'discovery.popin.cc',
+ publisher: {
+ domain: 'discovery.popin.cc'
+ },
+ page: 'https://discovery.popin.cc',
+ cat: ['IAB-19', 'IAB-20'],
+ },
+ },
+ ortb2Imp: {
+ ext: {
+ gpid: 'adslot_gpid',
+ tid: 'tid_01',
+ data: {
+ browsi: {
+ browsiViewability: 'NA',
+ },
+ adserver: {
+ name: 'adserver_name',
+ adslot: 'adslot_name',
+ },
+ keywords: ['travel', 'sport'],
+ pbadslot: '202309999'
+ }
+ }
+ },
+ adUnitCode: 'regular_iframe',
+ transactionId: 'd163f9e2-7ecd-4c2c-a3bd-28ceb52a60ee',
+ sizes: [[300, 250]],
+ bidId: '276092a19e05eb',
+ bidderRequestId: '1fadae168708b',
+ auctionId: 'ff66e39e-4075-4d18-9854-56fde9b879ac',
+ src: 'client',
+ bidRequestsCount: 1,
+ bidderRequestsCount: 1,
+ bidderWinsCount: 0,
+ },
+ ],
+ };
+
it('discovery:validate_pub_params', function () {
expect(
spec.isBidRequestValid({
@@ -92,12 +175,62 @@ describe('discovery:BidAdapterTests', function () {
).to.equal(true);
});
+ it('isBidRequestValid:no_params', function () {
+ expect(
+ spec.isBidRequestValid({
+ bidder: 'discovery',
+ params: {},
+ })
+ ).to.equal(true);
+ });
+
it('discovery:validate_generated_params', function () {
request = spec.buildRequests(bidRequestData.bids, bidRequestData);
let req_data = JSON.parse(request.data);
expect(req_data.imp).to.have.lengthOf(1);
});
+ describe('discovery: buildRequests', function() {
+ describe('getPmgUID function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+ sandbox.stub(storage, 'getCookie');
+ sandbox.stub(storage, 'setCookie');
+ sandbox.stub(utils, 'generateUUID').returns('new-uuid');
+ sandbox.stub(storage, 'cookiesAreEnabled');
+ })
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should generate new UUID and set cookie if not exists', () => {
+ storage.cookiesAreEnabled.callsFake(() => true);
+ storage.getCookie.callsFake(() => null);
+ const uid = getPmgUID();
+ expect(uid).to.equal('new-uuid');
+ expect(storage.setCookie.calledOnce).to.be.true;
+ });
+
+ it('should return existing UUID from cookie', () => {
+ storage.cookiesAreEnabled.callsFake(() => true);
+ storage.getCookie.callsFake(() => 'existing-uuid');
+ const uid = getPmgUID();
+ expect(uid).to.equal('existing-uuid');
+ expect(storage.setCookie.called).to.be.false;
+ });
+
+ it('should not set new UUID when cookies are not enabled', () => {
+ storage.cookiesAreEnabled.callsFake(() => false);
+ storage.getCookie.callsFake(() => null);
+ getPmgUID();
+ expect(storage.setCookie.calledOnce).to.be.false;
+ });
+ })
+ });
+
it('discovery:validate_response_params', function () {
let tempAdm = '
'
tempAdm += '%3Cscr';
@@ -137,4 +270,324 @@ describe('discovery:BidAdapterTests', function () {
expect(bid.height).to.equal(250);
expect(bid.currency).to.equal('USD');
});
+
+ describe('discovery: getUserSyncs', function() {
+ const COOKY_SYNC_IFRAME_URL = 'https://asset.popin.cc/js/cookieSync.html';
+ const IFRAME_ENABLED = {
+ iframeEnabled: true,
+ pixelEnabled: false,
+ };
+ const IFRAME_DISABLED = {
+ iframeEnabled: false,
+ pixelEnabled: false,
+ };
+ const GDPR_CONSENT = {
+ consentString: 'gdprConsentString',
+ gdprApplies: true
+ };
+ const USP_CONSENT = {
+ consentString: 'uspConsentString'
+ }
+
+ let syncParamUrl = `dm=${encodeURIComponent(location.origin || `https://${location.host}`)}`;
+ syncParamUrl += '&gdpr=1&gdpr_consent=gdprConsentString&ccpa_consent=uspConsentString';
+ const expectedIframeSyncs = [
+ {
+ type: 'iframe',
+ url: `${COOKY_SYNC_IFRAME_URL}?${syncParamUrl}`
+ }
+ ];
+
+ it('should return nothing if iframe is disabled', () => {
+ const userSyncs = spec.getUserSyncs(IFRAME_DISABLED, undefined, GDPR_CONSENT, USP_CONSENT, undefined);
+ expect(userSyncs).to.be.undefined;
+ });
+
+ it('should do userSyncs if iframe is enabled', () => {
+ const userSyncs = spec.getUserSyncs(IFRAME_ENABLED, undefined, GDPR_CONSENT, USP_CONSENT, undefined);
+ expect(userSyncs).to.deep.equal(expectedIframeSyncs);
+ });
+ });
+});
+
+describe('discovery Bid Adapter Tests', function () {
+ describe('buildRequests', () => {
+ describe('getPageTitle function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should return the top document title if available', function() {
+ const fakeTopDocument = {
+ title: 'Top Document Title',
+ querySelector: () => ({ content: 'Top Document Title test' })
+ };
+ const fakeTopWindow = {
+ document: fakeTopDocument
+ };
+ const result = getPageTitle({ top: fakeTopWindow });
+ expect(result).to.equal('Top Document Title');
+ });
+
+ it('should return the content of top og:title meta tag if title is empty', function() {
+ const ogTitleContent = 'Top OG Title Content';
+ const fakeTopWindow = {
+ document: {
+ title: '',
+ querySelector: sandbox.stub().withArgs('meta[property="og:title"]').returns({ content: ogTitleContent })
+ }
+ };
+
+ const result = getPageTitle({ top: fakeTopWindow });
+ expect(result).to.equal(ogTitleContent);
+ });
+
+ it('should return the document title if no og:title meta tag is present', function() {
+ document.title = 'Test Page Title';
+ sandbox.stub(document, 'querySelector').withArgs('meta[property="og:title"]').returns(null);
+
+ const result = getPageTitle({ top: undefined });
+ expect(result).to.equal('Test Page Title');
+ });
+
+ it('should return the content of og:title meta tag if present', function() {
+ document.title = '';
+ const ogTitleContent = 'Top OG Title Content';
+ sandbox.stub(document, 'querySelector').withArgs('meta[property="og:title"]').returns({ content: ogTitleContent });
+ const result = getPageTitle({ top: undefined });
+ expect(result).to.equal(ogTitleContent);
+ });
+
+ it('should return an empty string if no title or og:title meta tag is found', function() {
+ document.title = '';
+ sandbox.stub(document, 'querySelector').withArgs('meta[property="og:title"]').returns(null);
+ const result = getPageTitle({ top: undefined });
+ expect(result).to.equal('');
+ });
+
+ it('should handle exceptions when accessing top.document and fallback to current document', function() {
+ const fakeWindow = {
+ get top() {
+ throw new Error('Access denied');
+ }
+ };
+ const ogTitleContent = 'Current OG Title Content';
+ document.title = 'Current Document Title';
+ sandbox.stub(document, 'querySelector').withArgs('meta[property="og:title"]').returns({ content: ogTitleContent });
+ const result = getPageTitle(fakeWindow);
+ expect(result).to.equal('Current Document Title');
+ });
+ });
+
+ describe('getPageDescription function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should return the top document description if available', function() {
+ const descriptionContent = 'Top Document Description';
+ const fakeTopDocument = {
+ querySelector: sandbox.stub().withArgs('meta[name="description"]').returns({ content: descriptionContent })
+ };
+ const fakeTopWindow = { document: fakeTopDocument };
+ const result = getPageDescription({ top: fakeTopWindow });
+ expect(result).to.equal(descriptionContent);
+ });
+
+ it('should return the top document og:description if description is not present', function() {
+ const ogDescriptionContent = 'Top OG Description';
+ const fakeTopDocument = {
+ querySelector: sandbox.stub().withArgs('meta[property="og:description"]').returns({ content: ogDescriptionContent })
+ };
+ const fakeTopWindow = { document: fakeTopDocument };
+ const result = getPageDescription({ top: fakeTopWindow });
+ expect(result).to.equal(ogDescriptionContent);
+ });
+
+ it('should return the current document description if top document is not accessible', function() {
+ const descriptionContent = 'Current Document Description';
+ sandbox.stub(document, 'querySelector')
+ .withArgs('meta[name="description"]').returns({ content: descriptionContent })
+ const fakeWindow = {
+ get top() {
+ throw new Error('Access denied');
+ }
+ };
+ const result = getPageDescription(fakeWindow);
+ expect(result).to.equal(descriptionContent);
+ });
+
+ it('should return the current document og:description if description is not present and top document is not accessible', function() {
+ const ogDescriptionContent = 'Current OG Description';
+ sandbox.stub(document, 'querySelector')
+ .withArgs('meta[property="og:description"]').returns({ content: ogDescriptionContent });
+
+ const fakeWindow = {
+ get top() {
+ throw new Error('Access denied');
+ }
+ };
+ const result = getPageDescription(fakeWindow);
+ expect(result).to.equal(ogDescriptionContent);
+ });
+ });
+
+ describe('getPageKeywords function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should return the top document keywords if available', function() {
+ const keywordsContent = 'keyword1, keyword2, keyword3';
+ const fakeTopDocument = {
+ querySelector: sandbox.stub()
+ .withArgs('meta[name="keywords"]').returns({ content: keywordsContent })
+ };
+ const fakeTopWindow = { document: fakeTopDocument };
+
+ const result = getPageKeywords({ top: fakeTopWindow });
+ expect(result).to.equal(keywordsContent);
+ });
+
+ it('should return the current document keywords if top document is not accessible', function() {
+ const keywordsContent = 'keyword1, keyword2, keyword3';
+ sandbox.stub(document, 'querySelector')
+ .withArgs('meta[name="keywords"]').returns({ content: keywordsContent });
+
+ // æ¨ĄæéĄļåąįĒåŖčŽŋéŽåŧ常
+ const fakeWindow = {
+ get top() {
+ throw new Error('Access denied');
+ }
+ };
+
+ const result = getPageKeywords(fakeWindow);
+ expect(result).to.equal(keywordsContent);
+ });
+
+ it('should return an empty string if no keywords meta tag is found', function() {
+ sandbox.stub(document, 'querySelector').withArgs('meta[name="keywords"]').returns(null);
+
+ const result = getPageKeywords();
+ expect(result).to.equal('');
+ });
+ });
+ describe('getConnectionDownLink function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should return the downlink value as a string if available', function() {
+ const downlinkValue = 2.5;
+ const fakeNavigator = {
+ connection: {
+ downlink: downlinkValue
+ }
+ };
+
+ const result = getConnectionDownLink({ navigator: fakeNavigator });
+ expect(result).to.equal(downlinkValue.toString());
+ });
+
+ it('should return undefined if downlink is not available', function() {
+ const fakeNavigator = {
+ connection: {}
+ };
+
+ const result = getConnectionDownLink({ navigator: fakeNavigator });
+ expect(result).to.be.undefined;
+ });
+
+ it('should return undefined if connection is not available', function() {
+ const fakeNavigator = {};
+
+ const result = getConnectionDownLink({ navigator: fakeNavigator });
+ expect(result).to.be.undefined;
+ });
+
+ it('should handle cases where navigator is not defined', function() {
+ const result = getConnectionDownLink({});
+ expect(result).to.be.undefined;
+ });
+ });
+
+ describe('getUserSyncs with message event listener', function() {
+ function messageHandler(event) {
+ if (!event.data || event.origin !== THIRD_PARTY_COOKIE_ORIGIN) {
+ return;
+ }
+
+ window.removeEventListener('message', messageHandler, true);
+ event.stopImmediatePropagation();
+
+ const response = event.data;
+ if (!response.optout && response.mguid) {
+ storage.setCookie(COOKIE_KEY_MGUID, response.mguid, getCurrentTimeToUTCString());
+ }
+ }
+
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ sandbox.stub(storage, 'setCookie');
+ sandbox.stub(window, 'removeEventListener');
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should set a cookie when a valid message is received', () => {
+ const fakeEvent = {
+ data: { optout: '', mguid: '12345' },
+ origin: THIRD_PARTY_COOKIE_ORIGIN,
+ stopImmediatePropagation: sinon.spy()
+ };
+
+ messageHandler(fakeEvent);
+
+ expect(fakeEvent.stopImmediatePropagation.calledOnce).to.be.true;
+ expect(window.removeEventListener.calledWith('message', messageHandler, true)).to.be.true;
+ expect(storage.setCookie.calledWith(COOKIE_KEY_MGUID, '12345', sinon.match.string)).to.be.true;
+ });
+ it('should not do anything when an invalid message is received', () => {
+ const fakeEvent = {
+ data: null,
+ origin: 'http://invalid-origin.com',
+ stopImmediatePropagation: sinon.spy()
+ };
+
+ messageHandler(fakeEvent);
+
+ expect(fakeEvent.stopImmediatePropagation.notCalled).to.be.true;
+ expect(window.removeEventListener.notCalled).to.be.true;
+ expect(storage.setCookie.notCalled).to.be.true;
+ });
+ });
+ });
});
diff --git a/test/spec/modules/dsaControl_spec.js b/test/spec/modules/dsaControl_spec.js
new file mode 100644
index 00000000000..0d7c52b5efd
--- /dev/null
+++ b/test/spec/modules/dsaControl_spec.js
@@ -0,0 +1,113 @@
+import {addBidResponseHook, setMetaDsa, reset} from '../../../modules/dsaControl.js';
+import CONSTANTS from 'src/constants.json';
+import {auctionManager} from '../../../src/auctionManager.js';
+import {AuctionIndex} from '../../../src/auctionIndex.js';
+
+describe('DSA transparency', () => {
+ let sandbox;
+ beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+ });
+ afterEach(() => {
+ sandbox.restore();
+ reset();
+ });
+
+ describe('addBidResponseHook', () => {
+ const auctionId = 'auction-id';
+ let bid, auction, fpd, next, reject;
+ beforeEach(() => {
+ next = sinon.stub();
+ reject = sinon.stub();
+ fpd = {};
+ bid = {
+ auctionId
+ }
+ auction = {
+ getAuctionId: () => auctionId,
+ getFPD: () => ({global: fpd})
+ }
+ sandbox.stub(auctionManager, 'index').get(() => new AuctionIndex(() => [auction]));
+ });
+
+ function expectRejection(reason) {
+ addBidResponseHook(next, 'adUnit', bid, reject);
+ sinon.assert.calledWith(reject, reason);
+ sinon.assert.notCalled(next);
+ }
+
+ function expectAcceptance() {
+ addBidResponseHook(next, 'adUnit', bid, reject);
+ sinon.assert.notCalled(reject);
+ sinon.assert.calledWith(next, 'adUnit', bid, reject);
+ }
+
+ [2, 3].forEach(required => {
+ describe(`when regs.ext.dsa.dsarequired is ${required} (required)`, () => {
+ beforeEach(() => {
+ fpd = {
+ regs: {ext: {dsa: {dsarequired: required}}}
+ };
+ });
+
+ it('should reject bids that have no meta.dsa', () => {
+ expectRejection(CONSTANTS.REJECTION_REASON.DSA_REQUIRED);
+ });
+
+ it('should accept bids that do', () => {
+ bid.meta = {dsa: {}};
+ expectAcceptance();
+ });
+
+ describe('and pubrender = 0 (rendering by publisher not supported)', () => {
+ beforeEach(() => {
+ fpd.regs.ext.dsa.pubrender = 0;
+ });
+
+ it('should reject bids with adrender = 0 (advertiser will not render)', () => {
+ bid.meta = {dsa: {adrender: 0}};
+ expectRejection(CONSTANTS.REJECTION_REASON.DSA_MISMATCH);
+ });
+
+ it('should accept bids with adrender = 1 (advertiser will render)', () => {
+ bid.meta = {dsa: {adrender: 1}};
+ expectAcceptance();
+ });
+ });
+ describe('and pubrender = 2 (publisher will render)', () => {
+ beforeEach(() => {
+ fpd.regs.ext.dsa.pubrender = 2;
+ });
+
+ it('should reject bids with adrender = 1 (advertiser will render)', () => {
+ bid.meta = {dsa: {adrender: 1}};
+ expectRejection(CONSTANTS.REJECTION_REASON.DSA_MISMATCH);
+ });
+
+ it('should accept bids with adrender = 0 (advertiser will not render)', () => {
+ bid.meta = {dsa: {adrender: 0}};
+ expectAcceptance();
+ })
+ })
+ });
+ });
+ [undefined, 'garbage', 0, 1].forEach(required => {
+ describe(`when regs.ext.dsa.dsarequired is ${required}`, () => {
+ beforeEach(() => {
+ if (required != null) {
+ fpd = {
+ regs: {ext: {dsa: {dsarequired: required}}}
+ }
+ }
+ });
+
+ it('should accept bids regardless of their meta.dsa', () => {
+ addBidResponseHook(next, 'adUnit', bid, reject);
+ sinon.assert.notCalled(reject);
+ sinon.assert.calledWith(next, 'adUnit', bid, reject);
+ })
+ })
+ })
+ it('should accept bids regardless of dsa when "required" any other value')
+ });
+});
diff --git a/test/spec/modules/dsp_genieeBidAdapter_spec.js b/test/spec/modules/dsp_genieeBidAdapter_spec.js
new file mode 100644
index 00000000000..94ec1011fbf
--- /dev/null
+++ b/test/spec/modules/dsp_genieeBidAdapter_spec.js
@@ -0,0 +1,173 @@
+import { expect } from 'chai';
+import { spec } from 'modules/dsp_genieeBidAdapter.js';
+import { config } from 'src/config';
+
+describe('Geniee adapter tests', () => {
+ const validBidderRequest = {
+ code: 'sample_request',
+ bids: [{
+ bidId: 'bid-id',
+ bidder: 'dsp_geniee',
+ params: {
+ test: 1
+ }
+ }],
+ gdprConsent: {
+ gdprApplies: false
+ },
+ uspConsent: '1YNY'
+ };
+
+ describe('isBidRequestValid function test', () => {
+ it('valid', () => {
+ expect(spec.isBidRequestValid(validBidderRequest.bids[0])).equal(true);
+ });
+ });
+ describe('buildRequests function test', () => {
+ it('auction', () => {
+ const request = spec.buildRequests(validBidderRequest.bids, validBidderRequest);
+ const auction_id = request.data.id;
+ expect(request).deep.equal({
+ method: 'POST',
+ url: 'https://rt.gsspat.jp/prebid_auction',
+ data: {
+ at: 1,
+ id: auction_id,
+ imp: [
+ {
+ ext: {
+ test: 1
+ },
+ id: 'bid-id'
+ }
+ ],
+ test: 1
+ },
+ });
+ });
+ it('uncomfortable (gdpr)', () => {
+ validBidderRequest.gdprConsent.gdprApplies = true;
+ const request = spec.buildRequests(validBidderRequest.bids, validBidderRequest);
+ expect(request).deep.equal({
+ method: 'GET',
+ url: 'https://rt.gsspat.jp/prebid_uncomfortable',
+ });
+ validBidderRequest.gdprConsent.gdprApplies = false;
+ });
+ it('uncomfortable (usp)', () => {
+ validBidderRequest.uspConsent = '1YYY';
+ const request = spec.buildRequests(validBidderRequest.bids, validBidderRequest);
+ expect(request).deep.equal({
+ method: 'GET',
+ url: 'https://rt.gsspat.jp/prebid_uncomfortable',
+ });
+ validBidderRequest.uspConsent = '1YNY';
+ });
+ it('uncomfortable (coppa)', () => {
+ config.setConfig({ coppa: true });
+ const request = spec.buildRequests(validBidderRequest.bids, validBidderRequest);
+ expect(request).deep.equal({
+ method: 'GET',
+ url: 'https://rt.gsspat.jp/prebid_uncomfortable',
+ });
+ config.resetConfig();
+ });
+ it('uncomfortable (currency)', () => {
+ config.setConfig({ currency: { adServerCurrency: 'TWD' } });
+ const request = spec.buildRequests(validBidderRequest.bids, validBidderRequest);
+ expect(request).deep.equal({
+ method: 'GET',
+ url: 'https://rt.gsspat.jp/prebid_uncomfortable',
+ });
+ config.resetConfig();
+ });
+ });
+ describe('interpretResponse function test', () => {
+ it('sample bid', () => {
+ const request = spec.buildRequests(validBidderRequest.bids, validBidderRequest);
+ const auction_id = request.data.id;
+ const adm = "\n";
+ const serverResponse = {
+ body: {
+ id: auction_id,
+ cur: 'JPY',
+ seatbid: [{
+ bid: [{
+ id: '7b77235d599e06d289e58ddfa9390443e22d7071',
+ impid: 'bid-id',
+ price: 0.6666000000000001,
+ adid: '8405715',
+ adm: adm,
+ adomain: ['geniee.co.jp'],
+ iurl: 'http://img.gsspat.jp/e/068c8e1eafbf0cb6ac1ee95c36152bd2/04f4bd4e6b71f978d343d84ecede3877.png',
+ cid: '8405715',
+ crid: '1383823',
+ cat: ['IAB1'],
+ w: 300,
+ h: 250,
+ mtype: 1
+ }]
+ }]
+ }
+ };
+ const bids = spec.interpretResponse(serverResponse, request);
+ expect(bids).deep.equal([{
+ ad: adm,
+ cpm: 0.6666000000000001,
+ creativeId: '1383823',
+ creative_id: '1383823',
+ height: 250,
+ width: 300,
+ currency: 'JPY',
+ mediaType: 'banner',
+ meta: {
+ advertiserDomains: ['geniee.co.jp']
+ },
+ netRevenue: true,
+ requestId: 'bid-id',
+ seatBidId: '7b77235d599e06d289e58ddfa9390443e22d7071',
+ ttl: 300
+ }]);
+ });
+ it('no bid', () => {
+ const serverResponse = {};
+ const bids = spec.interpretResponse(serverResponse, validBidderRequest);
+ expect(bids).deep.equal([]);
+ });
+ });
+ describe('getUserSyncs function test', () => {
+ it('sync enabled', () => {
+ const syncOptions = {
+ iframeEnabled: true,
+ pixelEnabled: true
+ };
+ const serverResponses = [];
+ const syncs = spec.getUserSyncs(syncOptions, serverResponses);
+ expect(syncs).deep.equal([{
+ type: 'image',
+ url: 'https://rt.gsspat.jp/prebid_cs'
+ }]);
+ });
+ it('sync disabled (option false)', () => {
+ const syncOptions = {
+ iframeEnabled: false,
+ pixelEnabled: false
+ };
+ const serverResponses = [];
+ const syncs = spec.getUserSyncs(syncOptions, serverResponses);
+ expect(syncs).deep.equal([]);
+ });
+ it('sync disabled (gdpr)', () => {
+ const syncOptions = {
+ iframeEnabled: true,
+ pixelEnabled: true
+ };
+ const serverResponses = [];
+ const gdprConsent = {
+ gdprApplies: true
+ };
+ const syncs = spec.getUserSyncs(syncOptions, serverResponses, gdprConsent);
+ expect(syncs).deep.equal([]);
+ });
+ });
+});
diff --git a/test/spec/modules/dxkultureBidAdapter_spec.js b/test/spec/modules/dxkultureBidAdapter_spec.js
index d3ae8ec5124..a752c81cb6e 100644
--- a/test/spec/modules/dxkultureBidAdapter_spec.js
+++ b/test/spec/modules/dxkultureBidAdapter_spec.js
@@ -281,7 +281,7 @@ describe('dxkultureBidAdapter', function() {
it('should return expected request object', function() {
const bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest);
- expect(bidRequest.url).equal('https://ads.kulture.media/pbjs?pid=publisherId&placementId=123456');
+ expect(bidRequest.url).equal('https://ads.dxkulture.com/pbjs?pid=publisherId&placementId=123456');
expect(bidRequest.method).equal('POST');
});
});
@@ -606,7 +606,14 @@ describe('dxkultureBidAdapter', function() {
});
});
- describe('user sync', function () {
+ describe('getUserSyncs', function () {
+ let bidRequest, bidderResponse;
+ beforeEach(function() {
+ const bidderRequest = getVideoRequest();
+ bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest);
+ bidderResponse = getBidderResponse();
+ });
+
it('handles no parameters', function () {
let opts = spec.getUserSyncs({});
expect(opts).to.be.an('array').that.is.empty;
@@ -617,66 +624,26 @@ describe('dxkultureBidAdapter', function() {
expect(opts).to.be.an('array').that.is.empty;
});
- describe('when gdpr applies', function () {
- let gdprConsent;
- let gdprPixelUrl;
- const consentString = 'gdpr-pixel-consent';
- const gdprApplies = '1';
- beforeEach(() => {
- gdprConsent = {
- consentString,
- gdprApplies: true
- };
-
- gdprPixelUrl = `${SYNC_URL}&gdpr=${gdprApplies}&gdpr_consent=${consentString}`;
- });
+ it('iframe sync enabled should return results', function () {
+ let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [bidderResponse]);
- it('when there is a response, it should have the gdpr query params', () => {
- let [{url}] = spec.getUserSyncs(
- {iframeEnabled: true, pixelEnabled: true},
- [],
- gdprConsent
- );
+ expect(opts.length).to.equal(1);
+ expect(opts[0].type).to.equal('iframe');
+ expect(opts[0].url).to.equal(bidderResponse.body.ext.usersync['sovrn'].syncs[0].url);
+ });
- expect(url).to.have.string(`gdpr_consent=${consentString}`);
- expect(url).to.have.string(`gdpr=${gdprApplies}`);
- });
+ it('pixel sync enabled should return results', function () {
+ let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [bidderResponse]);
- it('should not send signals if no consent object is available', function () {
- let [{url}] = spec.getUserSyncs(
- {iframeEnabled: true, pixelEnabled: true},
- [],
- );
- expect(url).to.not.have.string('gdpr_consent=');
- expect(url).to.not.have.string('gdpr=');
- });
+ expect(opts.length).to.equal(1);
+ expect(opts[0].type).to.equal('image');
+ expect(opts[0].url).to.equal(bidderResponse.body.ext.usersync['appnexus'].syncs[0].url);
});
- describe('when ccpa applies', function () {
- let usPrivacyConsent;
- let uspPixelUrl;
- const privacyString = 'TEST';
- beforeEach(() => {
- usPrivacyConsent = 'TEST';
- uspPixelUrl = `${SYNC_URL}&us_privacy=${privacyString}`
- });
- it('should send the us privacy string, ', () => {
- let [{url}] = spec.getUserSyncs(
- {iframeEnabled: true, pixelEnabled: true},
- [],
- undefined,
- usPrivacyConsent
- );
- expect(url).to.have.string(`us_privacy=${privacyString}`);
- });
+ it('all sync enabled should prioritize iframe', function () {
+ let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, [bidderResponse]);
- it('should not send signals if no consent string is available', function () {
- let [{url}] = spec.getUserSyncs(
- {iframeEnabled: true, pixelEnabled: true},
- [],
- );
- expect(url).to.not.have.string('us_privacy=');
- });
+ expect(opts.length).to.equal(1);
});
});
});
diff --git a/test/spec/modules/eids_spec.js b/test/spec/modules/eids_spec.js
index f2ccdcb3024..25e70f12ced 100644
--- a/test/spec/modules/eids_spec.js
+++ b/test/spec/modules/eids_spec.js
@@ -238,6 +238,39 @@ describe('eids array generation for known sub-modules', function() {
});
});
+ it('sovrn', function() {
+ const userId = {
+ sovrn: {'id': 'sample_id'}
+ };
+ const newEids = createEidsArray(userId);
+ expect(newEids.length).to.equal(1);
+ expect(newEids[0]).to.deep.equal({
+ source: 'liveintent.sovrn.com',
+ uids: [{
+ id: 'sample_id',
+ atype: 3
+ }]
+ });
+ });
+
+ it('sovrn with ext', function() {
+ const userId = {
+ sovrn: {'id': 'sample_id', 'ext': {'provider': 'some.provider.com'}}
+ };
+ const newEids = createEidsArray(userId);
+ expect(newEids.length).to.equal(1);
+ expect(newEids[0]).to.deep.equal({
+ source: 'liveintent.sovrn.com',
+ uids: [{
+ id: 'sample_id',
+ atype: 3,
+ ext: {
+ provider: 'some.provider.com'
+ }
+ }]
+ });
+ });
+
it('magnite', function() {
const userId = {
magnite: {'id': 'sample_id'}
@@ -311,7 +344,7 @@ describe('eids array generation for known sub-modules', function() {
const newEids = createEidsArray(userId);
expect(newEids.length).to.equal(1);
expect(newEids[0]).to.deep.equal({
- source: 'openx.com',
+ source: 'openx.net',
uids: [{
id: 'sample_id',
atype: 3
@@ -326,7 +359,7 @@ describe('eids array generation for known sub-modules', function() {
const newEids = createEidsArray(userId);
expect(newEids.length).to.equal(1);
expect(newEids[0]).to.deep.equal({
- source: 'openx.com',
+ source: 'openx.net',
uids: [{
id: 'sample_id',
atype: 3,
diff --git a/test/spec/modules/euidIdSystem_spec.js b/test/spec/modules/euidIdSystem_spec.js
index 9e4598bb5f5..98770fa80bc 100644
--- a/test/spec/modules/euidIdSystem_spec.js
+++ b/test/spec/modules/euidIdSystem_spec.js
@@ -3,6 +3,7 @@ import {config} from 'src/config.js';
import {euidIdSubmodule} from 'modules/euidIdSystem.js';
import 'modules/consentManagement.js';
import 'src/prebid.js';
+import * as utils from 'src/utils.js';
import {apiHelpers, cookieHelpers, runAuction, setGdprApplies} from './uid2IdSystem_helpers.js';
import {hook} from 'src/hook.js';
import {uninstall as uninstallGdprEnforcement} from 'modules/gdprEnforcement.js';
@@ -22,13 +23,18 @@ const auctionDelayMs = 10;
const makeEuidIdentityContainer = (token) => ({euid: {id: token}});
const useLocalStorage = true;
+
const makePrebidConfig = (params = null, extraSettings = {}, debug = false) => ({
userSync: { auctionDelay: auctionDelayMs, userIds: [{name: 'euid', params: {storage: useLocalStorage ? 'localStorage' : 'cookie', ...params}, ...extraSettings}] }, debug
});
+const cstgConfigParams = { serverPublicKey: 'UID2-X-L-24B8a/eLYBmRkXA9yPgRZt+ouKbXewG2OPs23+ov3JC8mtYJBCx6AxGwJ4MlwUcguebhdDp2CvzsCgS9ogwwGA==', subscriptionId: 'subscription-id' }
+const clientSideGeneratedToken = 'client-side-generated-advertising-token';
+
const apiUrl = 'https://prod.euid.eu/v2/token/refresh';
+const cstgApiUrl = 'https://prod.euid.eu/v2/token/client-generate';
const headers = { 'Content-Type': 'application/json' };
-const makeSuccessResponseBody = () => btoa(JSON.stringify({ status: 'success', body: { ...apiHelpers.makeTokenResponse(initialToken), advertising_token: refreshedToken } }));
+const makeSuccessResponseBody = (token) => btoa(JSON.stringify({ status: 'success', body: { ...apiHelpers.makeTokenResponse(initialToken), advertising_token: token } }));
const expectToken = (bid, token) => expect(bid?.userId ?? {}).to.deep.include(makeEuidIdentityContainer(token));
const expectNoIdentity = (bid) => expect(bid).to.not.haveOwnProperty('userId');
@@ -36,6 +42,7 @@ describe('EUID module', function() {
let suiteSandbox, restoreSubtleToUndefined = false;
const configureEuidResponse = (httpStatus, response) => server.respondWith('POST', apiUrl, (xhr) => xhr.respond(httpStatus, headers, response));
+ const configureEuidCstgResponse = (httpStatus, response) => server.respondWith('POST', cstgApiUrl, (xhr) => xhr.respond(httpStatus, headers, response));
before(function() {
uninstallGdprEnforcement();
@@ -43,10 +50,18 @@ describe('EUID module', function() {
suiteSandbox = sinon.sandbox.create();
if (typeof window.crypto.subtle === 'undefined') {
restoreSubtleToUndefined = true;
- window.crypto.subtle = { importKey: () => {}, decrypt: () => {} };
+ window.crypto.subtle = { importKey: () => {}, digest: () => {}, decrypt: () => {}, deriveKey: () => {}, encrypt: () => {}, generateKey: () => {}, exportKey: () => {} };
}
suiteSandbox.stub(window.crypto.subtle, 'importKey').callsFake(() => Promise.resolve());
+ suiteSandbox.stub(window.crypto.subtle, 'digest').callsFake(() => Promise.resolve('hashed_value'));
suiteSandbox.stub(window.crypto.subtle, 'decrypt').callsFake((settings, key, data) => Promise.resolve(new Uint8Array([...settings.iv, ...data])));
+ suiteSandbox.stub(window.crypto.subtle, 'deriveKey').callsFake(() => Promise.resolve());
+ suiteSandbox.stub(window.crypto.subtle, 'exportKey').callsFake(() => Promise.resolve());
+ suiteSandbox.stub(window.crypto.subtle, 'encrypt').callsFake(() => Promise.resolve(new ArrayBuffer()));
+ suiteSandbox.stub(window.crypto.subtle, 'generateKey').callsFake(() => Promise.resolve({
+ privateKey: {},
+ publicKey: {}
+ }));
});
after(function() {
suiteSandbox.restore();
@@ -113,10 +128,23 @@ describe('EUID module', function() {
it('When an expired token is provided and the API responds in time, the refreshed token is provided to the auction.', async function() {
setGdprApplies(true);
const euidToken = apiHelpers.makeTokenResponse(initialToken, true, true);
- configureEuidResponse(200, makeSuccessResponseBody());
+ configureEuidResponse(200, makeSuccessResponseBody(refreshedToken));
config.setConfig(makePrebidConfig({euidToken}));
apiHelpers.respondAfterDelay(1, server);
const bid = await runAuction();
expectToken(bid, refreshedToken);
});
+
+ if (FEATURES.UID2_CSTG) {
+ it('Should use client side generated EUID token in the auction.', async function() {
+ setGdprApplies(true);
+ const euidToken = apiHelpers.makeTokenResponse(initialToken, true, true);
+ configureEuidCstgResponse(200, makeSuccessResponseBody(clientSideGeneratedToken));
+ config.setConfig(makePrebidConfig({ euidToken, ...cstgConfigParams, email: 'test@test.com' }));
+ apiHelpers.respondAfterDelay(1, server);
+
+ const bid = await runAuction();
+ expectToken(bid, clientSideGeneratedToken);
+ });
+ }
});
diff --git a/test/spec/modules/gdprEnforcement_spec.js b/test/spec/modules/gdprEnforcement_spec.js
index 2880b2fac5d..295b14dd796 100644
--- a/test/spec/modules/gdprEnforcement_spec.js
+++ b/test/spec/modules/gdprEnforcement_spec.js
@@ -26,7 +26,7 @@ import * as events from 'src/events.js';
import 'modules/appnexusBidAdapter.js'; // some tests expect this to be in the adapter registry
import 'src/prebid.js';
import {hook} from '../../../src/hook.js';
-import {GDPR_GVLIDS, VENDORLESS_GVLID} from '../../../src/consentHandler.js';
+import {GDPR_GVLIDS, VENDORLESS_GVLID, FIRST_PARTY_GVLID} from '../../../src/consentHandler.js';
import {validateStorageEnforcement} from '../../../src/storageManager.js';
import {activityParams} from '../../../src/activities/activityParams.js';
@@ -789,6 +789,21 @@ describe('gdpr enforcement', function () {
})
})
+ it('if validateRules is passed FIRST_PARTY_GVLID, it will use publisher.consents', () => {
+ const rule = createGdprRule();
+ const consentData = {
+ 'vendorData': {
+ 'publisher': {
+ 'consents': {
+ '1': true
+ }
+ },
+ },
+ };
+ const result = validateRules(rule, consentData, 'cdep', FIRST_PARTY_GVLID);
+ expect(result).to.equal(true);
+ });
+
describe('validateRules', function () {
Object.entries({
'1 (which does not consider LI)': [1, 'storage', false],
diff --git a/test/spec/modules/genericAnalyticsAdapter_spec.js b/test/spec/modules/genericAnalyticsAdapter_spec.js
index a5a6074c425..79874f5d756 100644
--- a/test/spec/modules/genericAnalyticsAdapter_spec.js
+++ b/test/spec/modules/genericAnalyticsAdapter_spec.js
@@ -75,7 +75,7 @@ describe('Generic analytics', () => {
options: {
url: 'mock',
events: {
- bidResponse: null
+ mockEvent: null
}
}
});
diff --git a/test/spec/modules/geoedgeRtdProvider_spec.js b/test/spec/modules/geoedgeRtdProvider_spec.js
index 96da2e3dbd7..211a3efa3c6 100644
--- a/test/spec/modules/geoedgeRtdProvider_spec.js
+++ b/test/spec/modules/geoedgeRtdProvider_spec.js
@@ -1,17 +1,21 @@
import * as utils from '../../../src/utils.js';
import {loadExternalScript} from '../../../src/adloader.js';
-import {
+import * as geoedgeRtdModule from '../../../modules/geoedgeRtdProvider.js';
+import {server} from '../../../test/mocks/xhr.js';
+import * as events from '../../../src/events.js';
+import CONSTANTS from '../../../src/constants.json';
+
+let {
geoedgeSubmodule,
getClientUrl,
getInPageUrl,
htmlPlaceholder,
setWrapper,
- wrapper,
- WRAPPER_URL
-} from '../../../modules/geoedgeRtdProvider.js';
-import {server} from '../../../test/mocks/xhr.js';
-import * as events from '../../../src/events.js';
-import CONSTANTS from '../../../src/constants.json';
+ getMacros,
+ WRAPPER_URL,
+ preloadClient,
+ markAsLoaded
+} = geoedgeRtdModule;
let key = '123123123';
function makeConfig(gpt) {
@@ -64,13 +68,11 @@ describe('Geoedge RTD module', function () {
});
});
describe('init', function () {
- let insertElementStub;
-
before(function () {
- insertElementStub = sinon.stub(utils, 'insertElement');
+ sinon.spy(geoedgeRtdModule, 'preloadClient');
});
after(function () {
- utils.insertElement.restore();
+ geoedgeRtdModule.preloadClient.restore();
});
it('should return false when missing params or key', function () {
let missingParams = geoedgeSubmodule.init({});
@@ -86,14 +88,13 @@ describe('Geoedge RTD module', function () {
let isWrapperRequest = request && request.url && request.url && request.url === WRAPPER_URL;
expect(isWrapperRequest).to.equal(true);
});
- it('should preload the client', function () {
- let isLinkPreloadAsScript = arg => arg.tagName === 'LINK' && arg.rel === 'preload' && arg.as === 'script' && arg.href === getClientUrl(key);
- expect(insertElementStub.calledWith(sinon.match(isLinkPreloadAsScript))).to.equal(true);
+ it('should call preloadClient', function () {
+ expect(preloadClient.called);
});
it('should emit billable events with applicable winning bids', function (done) {
let counter = 0;
events.on(CONSTANTS.EVENTS.BILLABLE_EVENT, function (event) {
- if (event.vendor === 'geoedge' && event.type === 'impression') {
+ if (event.vendor === geoedgeSubmodule.name && event.type === 'impression') {
counter += 1;
}
expect(counter).to.equal(1);
@@ -103,7 +104,7 @@ describe('Geoedge RTD module', function () {
});
it('should load the in page code when gpt params is true', function () {
geoedgeSubmodule.init(makeConfig(true));
- let isInPageUrl = arg => arg == getInPageUrl(key);
+ let isInPageUrl = arg => arg === getInPageUrl(key);
expect(loadExternalScript.calledWith(sinon.match(isInPageUrl))).to.equal(true);
});
it('should set the window.grumi config object when gpt params is true', function () {
@@ -111,10 +112,36 @@ describe('Geoedge RTD module', function () {
expect(hasGrumiObj && window.grumi.key === key && window.grumi.fromPrebid).to.equal(true);
});
});
+ describe('preloadClient', function () {
+ let iframe;
+ preloadClient(key);
+ let loadExternalScriptCall = loadExternalScript.getCall(0);
+ it('should create an invisible iframe and insert it to the DOM', function () {
+ iframe = document.getElementById('grumiFrame');
+ expect(iframe && iframe.style.display === 'none');
+ });
+ it('should assign params object to the iframe\'s window', function () {
+ let grumi = iframe.contentWindow.grumi;
+ expect(grumi.key).to.equal(key);
+ });
+ it('should preload the client into the iframe', function () {
+ let isClientUrl = arg => arg === getClientUrl(key);
+ expect(loadExternalScriptCall.calledWithMatch(isClientUrl)).to.equal(true);
+ });
+ });
describe('setWrapper', function () {
it('should set the wrapper', function () {
setWrapper(mockWrapper);
- expect(wrapper).to.equal(mockWrapper);
+ expect(geoedgeRtdModule.wrapper).to.equal(mockWrapper);
+ });
+ });
+ describe('getMacros', function () {
+ it('return a dictionary of macros replaced with values from bid object', function () {
+ let bid = mockBid('testBidder');
+ let dict = getMacros(bid, key);
+ let hasCpm = dict['%_hbCpm!'] === bid.cpm;
+ let hasCurrency = dict['%_hbCurrency!'] === bid.currency;
+ expect(hasCpm && hasCurrency);
});
});
describe('onBidResponseEvent', function () {
diff --git a/test/spec/modules/greenbidsAnalyticsAdapter_spec.js b/test/spec/modules/greenbidsAnalyticsAdapter_spec.js
index 3cfdc9b9749..30361ca5661 100644
--- a/test/spec/modules/greenbidsAnalyticsAdapter_spec.js
+++ b/test/spec/modules/greenbidsAnalyticsAdapter_spec.js
@@ -1,8 +1,11 @@
import {
- greenbidsAnalyticsAdapter, parseBidderCode,
+ greenbidsAnalyticsAdapter,
+ isSampled,
ANALYTICS_VERSION, BIDDER_STATUS
} from 'modules/greenbidsAnalyticsAdapter.js';
-
+import {
+ generateUUID,
+} from '../../../src/utils.js';
import {expect} from 'chai';
import sinon from 'sinon';
@@ -13,11 +16,42 @@ const pbuid = 'pbuid-AA778D8A796AEA7A0843E2BBEB677766';
const auctionId = 'b0b39610-b941-4659-a87c-de9f62d3e13e';
describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
+ describe('enableAnalytics and config parser', function () {
+ const configOptions = {
+ pbuid: pbuid,
+ greenbidsSampling: 1,
+ };
+ beforeEach(function () {
+ greenbidsAnalyticsAdapter.enableAnalytics({
+ provider: 'greenbidsAnalytics',
+ options: configOptions
+ });
+ });
+
+ afterEach(function () {
+ greenbidsAnalyticsAdapter.disableAnalytics();
+ });
+
+ it('should parse config correctly with optional values', function () {
+ expect(greenbidsAnalyticsAdapter.getAnalyticsOptions().options).to.deep.equal(configOptions);
+ expect(greenbidsAnalyticsAdapter.getAnalyticsOptions().pbuid).to.equal(configOptions.pbuid);
+ });
+
+ it('should not enable Analytics when pbuid is missing', function () {
+ const configOptions = {
+ options: {
+ }
+ };
+ const validConfig = greenbidsAnalyticsAdapter.initConfig(configOptions);
+ expect(validConfig).to.equal(false);
+ });
+ });
+
describe('event tracking and message cache manager', function () {
beforeEach(function () {
const configOptions = {
pbuid: pbuid,
- sampling: 0,
+ greenbidsSampling: 1,
};
greenbidsAnalyticsAdapter.enableAnalytics({
@@ -30,43 +64,6 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
greenbidsAnalyticsAdapter.disableAnalytics();
});
- describe('#parseBidderCode()', function() {
- it('should get lower case bidder code from bidderCode field value', function() {
- const receivedBids = [
- {
- auctionId: auctionId,
- adUnitCode: 'adunit_1',
- bidder: 'greenbids',
- bidderCode: 'GREENBIDS',
- requestId: 'a1b2c3d4',
- timeToRespond: 72,
- cpm: 0.1,
- currency: 'USD',
- ad: 'fake ad1'
- },
- ];
- const result = parseBidderCode(receivedBids[0]);
- expect(result).to.equal('greenbids');
- });
- it('should get lower case bidder code from bidder field value as bidderCode field is missing', function() {
- const receivedBids = [
- {
- auctionId: auctionId,
- adUnitCode: 'adunit_1',
- bidder: 'greenbids',
- bidderCode: '',
- requestId: 'a1b2c3d4',
- timeToRespond: 72,
- cpm: 0.1,
- currency: 'USD',
- ad: 'fake ad1'
- },
- ];
- const result = parseBidderCode(receivedBids[0]);
- expect(result).to.equal('greenbids');
- });
- });
-
describe('#getCachedAuction()', function() {
const existing = {timeoutBids: [{}]};
greenbidsAnalyticsAdapter.cachedAuctions['test_auction_id'] = existing;
@@ -146,7 +143,7 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
auctionId: auctionId,
pbuid: pbuid,
referrer: window.location.href,
- sampling: 0,
+ sampling: 1,
prebid: '$prebid.version$',
});
}
@@ -260,7 +257,9 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
noBids: noBids
};
+ sinon.stub(greenbidsAnalyticsAdapter, 'getCachedAuction').returns({timeoutBids: timeoutBids});
const result = greenbidsAnalyticsAdapter.createBidMessage(args, timeoutBids);
+ greenbidsAnalyticsAdapter.getCachedAuction.restore();
assertHavingRequiredMessageFields(result);
expect(result).to.deep.include({
@@ -330,7 +329,7 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
timeout: 3000,
auctionEnd: 1234567990,
bidsReceived: receivedBids,
- noBids: noBids
+ noBids: noBids,
}];
greenbidsAnalyticsAdapter.handleBidTimeout(args);
@@ -353,7 +352,7 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
describe('greenbids Analytics Adapter track handler ', function () {
const configOptions = {
pbuid: pbuid,
- sampling: 1,
+ greenbidsSampling: 1,
};
beforeEach(function () {
@@ -369,50 +368,52 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
events.getEvents.restore();
});
+ it('should call handleAuctionInit as AUCTION_INIT trigger event', function() {
+ sinon.spy(greenbidsAnalyticsAdapter, 'handleAuctionInit');
+ events.emit(constants.EVENTS.AUCTION_INIT, {auctionId: 'auctionId'});
+ sinon.assert.callCount(greenbidsAnalyticsAdapter.handleAuctionInit, 1);
+ greenbidsAnalyticsAdapter.handleAuctionInit.restore();
+ });
+
it('should call handleBidTimeout as BID_TIMEOUT trigger event', function() {
sinon.spy(greenbidsAnalyticsAdapter, 'handleBidTimeout');
- events.emit(constants.EVENTS.BID_TIMEOUT, {});
+ events.emit(constants.EVENTS.BID_TIMEOUT, {auctionId: 'auctionId'});
sinon.assert.callCount(greenbidsAnalyticsAdapter.handleBidTimeout, 1);
greenbidsAnalyticsAdapter.handleBidTimeout.restore();
});
it('should call handleAuctionEnd as AUCTION_END trigger event', function() {
sinon.spy(greenbidsAnalyticsAdapter, 'handleAuctionEnd');
- events.emit(constants.EVENTS.AUCTION_END, {});
+ events.emit(constants.EVENTS.AUCTION_END, {auctionId: 'auctionId'});
sinon.assert.callCount(greenbidsAnalyticsAdapter.handleAuctionEnd, 1);
greenbidsAnalyticsAdapter.handleAuctionEnd.restore();
});
- });
-
- describe('enableAnalytics and config parser', function () {
- const configOptions = {
- pbuid: pbuid,
- sampling: 0,
- };
- beforeEach(function () {
- greenbidsAnalyticsAdapter.enableAnalytics({
- provider: 'greenbidsAnalytics',
- options: configOptions
+ it('should call handleBillable as BILLABLE_EVENT trigger event', function() {
+ sinon.spy(greenbidsAnalyticsAdapter, 'handleBillable');
+ events.emit(constants.EVENTS.BILLABLE_EVENT, {
+ type: 'auction',
+ billingId: generateUUID(),
+ auctionId: 'auctionId',
+ vendor: 'greenbidsRtdProvider'
});
+ sinon.assert.callCount(greenbidsAnalyticsAdapter.handleBillable, 1);
+ greenbidsAnalyticsAdapter.handleBillable.restore();
});
+ });
- afterEach(function () {
- greenbidsAnalyticsAdapter.disableAnalytics();
+ describe('isSampled', function() {
+ it('should return true for invalid sampling rates', function() {
+ expect(isSampled('ce1f3692-632c-4cfd-9e40-0c2ad625ec56', -1)).to.be.true;
+ expect(isSampled('ce1f3692-632c-4cfd-9e40-0c2ad625ec56', 1.2)).to.be.true;
});
- it('should parse config correctly with optional values', function () {
- expect(greenbidsAnalyticsAdapter.getAnalyticsOptions().options).to.deep.equal(configOptions);
- expect(greenbidsAnalyticsAdapter.getAnalyticsOptions().pbuid).to.equal(configOptions.pbuid);
+ it('should return determinist falsevalue for valid sampling rate given the predifined id and rate', function() {
+ expect(isSampled('ce1f3692-632c-4cfd-9e40-0c2ad625ec56', 0.0001)).to.be.false;
});
- it('should not enable Analytics when pbuid is missing', function () {
- const configOptions = {
- options: {
- }
- };
- const validConfig = greenbidsAnalyticsAdapter.initConfig(configOptions);
- expect(validConfig).to.equal(false);
+ it('should return determinist true value for valid sampling rate given the predifined id and rate', function() {
+ expect(isSampled('ce1f3692-632c-4cfd-9e40-0c2ad625ec56', 0.9999)).to.be.true;
});
});
});
diff --git a/test/spec/modules/greenbidsRtdProvider_spec.js b/test/spec/modules/greenbidsRtdProvider_spec.js
index cd93e9013c0..d0083d4dc7a 100644
--- a/test/spec/modules/greenbidsRtdProvider_spec.js
+++ b/test/spec/modules/greenbidsRtdProvider_spec.js
@@ -6,7 +6,9 @@ import {
import {
greenbidsSubmodule
} from 'modules/greenbidsRtdProvider.js';
-import {server} from '../../mocks/xhr.js';
+import { server } from '../../mocks/xhr.js';
+import * as events from '../../../src/events.js';
+import CONSTANTS from '../../../src/constants.json';
describe('greenbidsRtdProvider', () => {
const endPoint = 't.greenbids.ai';
@@ -39,14 +41,36 @@ describe('greenbidsRtdProvider', () => {
}]
};
- const SAMPLE_RESPONSE_ADUNITS = [
+ const SAMPLE_RESPONSE_ADUNITS_NOT_EXPLORED = [
{
code: 'adUnit1',
bidders: {
'appnexus': true,
'rubicon': false,
'ix': true
- }
+ },
+ isExploration: false
+ },
+ {
+ code: 'adUnit2',
+ bidders: {
+ 'appnexus': false,
+ 'rubicon': true,
+ 'openx': true
+ },
+ isExploration: false
+
+ }];
+
+ const SAMPLE_RESPONSE_ADUNITS_EXPLORED = [
+ {
+ code: 'adUnit1',
+ bidders: {
+ 'appnexus': true,
+ 'rubicon': false,
+ 'ix': true
+ },
+ isExploration: true
},
{
code: 'adUnit2',
@@ -54,7 +78,9 @@ describe('greenbidsRtdProvider', () => {
'appnexus': false,
'rubicon': true,
'openx': true
- }
+ },
+ isExploration: true
+
}];
describe('init', () => {
@@ -70,22 +96,37 @@ describe('greenbidsRtdProvider', () => {
});
describe('updateAdUnitsBasedOnResponse', () => {
- it('should update ad units based on response', () => {
+ it('should update ad units based on response if not exploring', () => {
const adUnits = JSON.parse(JSON.stringify(SAMPLE_REQUEST_BIDS_CONFIG_OBJ.adUnits));
- greenbidsSubmodule.updateAdUnitsBasedOnResponse(adUnits, SAMPLE_RESPONSE_ADUNITS);
+ greenbidsSubmodule.updateAdUnitsBasedOnResponse(adUnits, SAMPLE_RESPONSE_ADUNITS_NOT_EXPLORED);
expect(adUnits[0].bids).to.have.length(2);
expect(adUnits[1].bids).to.have.length(2);
});
+
+ it('should not update ad units based on response if exploring', () => {
+ const adUnits = JSON.parse(JSON.stringify(SAMPLE_REQUEST_BIDS_CONFIG_OBJ.adUnits));
+ greenbidsSubmodule.updateAdUnitsBasedOnResponse(adUnits, SAMPLE_RESPONSE_ADUNITS_EXPLORED);
+
+ expect(adUnits[0].bids).to.have.length(3);
+ expect(adUnits[1].bids).to.have.length(3);
+ expect(adUnits[0].ortb2Imp.ext.greenbids.greenbidsId).to.be.a.string;
+ expect(adUnits[1].ortb2Imp.ext.greenbids.greenbidsId).to.be.a.string;
+ expect(adUnits[0].ortb2Imp.ext.greenbids.greenbidsId).to.equal(adUnits[0].ortb2Imp.ext.greenbids.greenbidsId);
+ expect(adUnits[0].ortb2Imp.ext.greenbids.keptInAuction).to.deep.equal(SAMPLE_RESPONSE_ADUNITS_EXPLORED[0].bidders);
+ expect(adUnits[1].ortb2Imp.ext.greenbids.keptInAuction).to.deep.equal(SAMPLE_RESPONSE_ADUNITS_EXPLORED[1].bidders);
+ expect(adUnits[0].ortb2Imp.ext.greenbids.isExploration).to.equal(SAMPLE_RESPONSE_ADUNITS_EXPLORED[0].isExploration);
+ expect(adUnits[1].ortb2Imp.ext.greenbids.isExploration).to.equal(SAMPLE_RESPONSE_ADUNITS_EXPLORED[1].isExploration);
+ });
});
describe('findMatchingAdUnit', () => {
it('should find matching ad unit by code', () => {
- const matchingAdUnit = greenbidsSubmodule.findMatchingAdUnit(SAMPLE_RESPONSE_ADUNITS, 'adUnit1');
- expect(matchingAdUnit).to.deep.equal(SAMPLE_RESPONSE_ADUNITS[0]);
+ const matchingAdUnit = greenbidsSubmodule.findMatchingAdUnit(SAMPLE_RESPONSE_ADUNITS_NOT_EXPLORED, 'adUnit1');
+ expect(matchingAdUnit).to.deep.equal(SAMPLE_RESPONSE_ADUNITS_NOT_EXPLORED[0]);
});
it('should return undefined if no matching ad unit is found', () => {
- const matchingAdUnit = greenbidsSubmodule.findMatchingAdUnit(SAMPLE_RESPONSE_ADUNITS, 'nonexistent');
+ const matchingAdUnit = greenbidsSubmodule.findMatchingAdUnit(SAMPLE_RESPONSE_ADUNITS_NOT_EXPLORED, 'nonexistent');
expect(matchingAdUnit).to.be.undefined;
});
});
@@ -93,7 +134,7 @@ describe('greenbidsRtdProvider', () => {
describe('removeFalseBidders', () => {
it('should remove bidders with false value', () => {
const adUnit = JSON.parse(JSON.stringify(SAMPLE_REQUEST_BIDS_CONFIG_OBJ.adUnits[0]));
- const matchingAdUnit = SAMPLE_RESPONSE_ADUNITS[0];
+ const matchingAdUnit = SAMPLE_RESPONSE_ADUNITS_NOT_EXPLORED[0];
greenbidsSubmodule.removeFalseBidders(adUnit, matchingAdUnit);
expect(adUnit.bids).to.have.length(2);
expect(adUnit.bids.map((bid) => bid.bidder)).to.not.include('rubicon');
@@ -125,14 +166,15 @@ describe('greenbidsRtdProvider', () => {
setTimeout(() => {
server.requests[0].respond(
200,
- {'Content-Type': 'application/json'},
- JSON.stringify(SAMPLE_RESPONSE_ADUNITS)
+ { 'Content-Type': 'application/json' },
+ JSON.stringify(SAMPLE_RESPONSE_ADUNITS_NOT_EXPLORED)
);
}, 50);
setTimeout(() => {
const requestUrl = new URL(server.requests[0].url);
expect(requestUrl.host).to.be.eq(endPoint);
+ expect(requestBids.greenbidsId).to.be.a.string;
expect(requestBids.adUnits[0].bids).to.have.length(2);
expect(requestBids.adUnits[0].bids.map((bid) => bid.bidder)).to.not.include('rubicon');
expect(requestBids.adUnits[0].bids.map((bid) => bid.bidder)).to.include('ix');
@@ -157,8 +199,8 @@ describe('greenbidsRtdProvider', () => {
setTimeout(() => {
server.requests[0].respond(
200,
- {'Content-Type': 'application/json'},
- JSON.stringify(SAMPLE_RESPONSE_ADUNITS)
+ { 'Content-Type': 'application/json' },
+ JSON.stringify(SAMPLE_RESPONSE_ADUNITS_NOT_EXPLORED)
);
done();
}, 300);
@@ -166,6 +208,7 @@ describe('greenbidsRtdProvider', () => {
setTimeout(() => {
const requestUrl = new URL(server.requests[0].url);
expect(requestUrl.host).to.be.eq(endPoint);
+ expect(requestBids.greenbidsId).to.be.a.string;
expect(requestBids.adUnits[0].bids).to.have.length(3);
expect(requestBids.adUnits[1].bids).to.have.length(3);
expect(callback.calledOnce).to.be.true;
@@ -183,14 +226,15 @@ describe('greenbidsRtdProvider', () => {
setTimeout(() => {
server.requests[0].respond(
500,
- {'Content-Type': 'application/json'},
- JSON.stringify({'failure': 'fail'})
+ { 'Content-Type': 'application/json' },
+ JSON.stringify({ 'failure': 'fail' })
);
}, 50);
setTimeout(() => {
const requestUrl = new URL(server.requests[0].url);
expect(requestUrl.host).to.be.eq(endPoint);
+ expect(requestBids.greenbidsId).to.be.a.string;
expect(requestBids.adUnits[0].bids).to.have.length(3);
expect(requestBids.adUnits[1].bids).to.have.length(3);
expect(callback.calledOnce).to.be.true;
@@ -198,4 +242,116 @@ describe('greenbidsRtdProvider', () => {
}, 60);
});
});
+
+ describe('stripAdUnits', function () {
+ it('should strip all properties except bidder from each bid in adUnits', function () {
+ const adUnits =
+ [
+ {
+ bids: [
+ { bidder: 'bidder1', otherProp: 'value1' },
+ { bidder: 'bidder2', otherProp: 'value2' }
+ ],
+ mediaTypes: { 'banner': { prop: 'value3' } }
+ }
+ ];
+ const expectedOutput = [
+ {
+ bids: [
+ { bidder: 'bidder1' },
+ { bidder: 'bidder2' }
+ ],
+ mediaTypes: { 'banner': { prop: 'value3' } }
+ }
+ ];
+
+ // Perform the test
+ const output = greenbidsSubmodule.stripAdUnits(adUnits);
+ expect(output).to.deep.equal(expectedOutput);
+ });
+
+ it('should strip all properties except bidder from each bid in adUnits but keep ortb2Imp', function () {
+ const adUnits =
+ [
+ {
+ bids: [
+ { bidder: 'bidder1', otherProp: 'value1' },
+ { bidder: 'bidder2', otherProp: 'value2' }
+ ],
+ mediaTypes: { 'banner': { prop: 'value3' } },
+ ortb2Imp: {
+ ext: {
+ greenbids: {
+ greenbidsId: 'test'
+ }
+ }
+ }
+ }
+ ];
+ const expectedOutput = [
+ {
+ bids: [
+ { bidder: 'bidder1' },
+ { bidder: 'bidder2' }
+ ],
+ mediaTypes: { 'banner': { prop: 'value3' } },
+ ortb2Imp: {
+ ext: {
+ greenbids: {
+ greenbidsId: 'test'
+ }
+ }
+ }
+ }
+ ];
+
+ // Perform the test
+ const output = greenbidsSubmodule.stripAdUnits(adUnits);
+ expect(output).to.deep.equal(expectedOutput);
+ });
+ });
+
+ describe('onAuctionInitEvent', function () {
+ it('should not emit billable event if greenbids hasn\'t set the adunit.ext value', function () {
+ sinon.spy(events, 'emit');
+ greenbidsSubmodule.onAuctionInitEvent({
+ auctionId: 'test',
+ adUnits: [
+ {
+ bids: [
+ { bidder: 'bidder1', otherProp: 'value1' },
+ { bidder: 'bidder2', otherProp: 'value2' }
+ ],
+ mediaTypes: { 'banner': { prop: 'value3' } },
+ }
+ ]
+ });
+ sinon.assert.callCount(events.emit, 0);
+ events.emit.restore();
+ });
+
+ it('should emit billable event if greenbids has set the adunit.ext value', function (done) {
+ let counter = 0;
+ events.on(CONSTANTS.EVENTS.BILLABLE_EVENT, function (event) {
+ if (event.vendor === 'greenbidsRtdProvider' && event.type === 'auction') {
+ counter += 1;
+ }
+ expect(counter).to.equal(1);
+ done();
+ });
+ greenbidsSubmodule.onAuctionInitEvent({
+ auctionId: 'test',
+ adUnits: [
+ {
+ bids: [
+ { bidder: 'bidder1', otherProp: 'value1' },
+ { bidder: 'bidder2', otherProp: 'value2' }
+ ],
+ mediaTypes: { 'banner': { prop: 'value3' } },
+ ortb2Imp: { ext: { greenbids: { greenbidsId: 'b0b39610-b941-4659-a87c-de9f62d3e13e' } } }
+ }
+ ]
+ });
+ });
+ });
});
diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js
index b12083236a2..abaa4b37fcd 100644
--- a/test/spec/modules/gridBidAdapter_spec.js
+++ b/test/spec/modules/gridBidAdapter_spec.js
@@ -1352,7 +1352,7 @@ describe('TheMediaGrid Adapter', function () {
it('complicated case', function () {
const fullResponse = [
- {'bid': [{'impid': '2164be6358b9', 'adid': '32_52_7543', 'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300, dealid: 11}], 'seat': '1'},
+ {'bid': [{'impid': '2164be6358b9', 'adid': '32_52_7543', 'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300, dealid: 11, 'ext': {'dsa': {'adrender': 1}}}], 'seat': '1'},
{'bid': [{'impid': '4e111f1b66e4', 'adid': '32_54_4535', 'price': 0.5, 'adm': '
test content 2
', 'auid': 2, 'h': 600, 'w': 300, dealid: 12}], 'seat': '1'},
{'bid': [{'impid': '26d6f897b516', 'adid': '32_53_75467', 'price': 0.15, 'adm': '
test content 3
', 'auid': 1, 'h': 90, 'w': 728}], 'seat': '1'},
{'bid': [{'impid': '326bde7fbf69', 'adid': '32_54_12342', 'price': 0.15, 'adm': '
test content 4
', 'auid': 1, 'h': 600, 'w': 300}], 'seat': '1'},
@@ -1430,6 +1430,7 @@ describe('TheMediaGrid Adapter', function () {
'netRevenue': true,
'ttl': 360,
'meta': {
+ adrender: 1,
advertiserDomains: []
},
},
@@ -1559,37 +1560,9 @@ describe('TheMediaGrid Adapter', function () {
});
it('should send right request on onDataDeletionRequest call', function() {
- spec.onDataDeletionRequest([{
- bids: [
- {
- bidder: 'grid',
- params: {
- uid: 1
- }
- },
- {
- bidder: 'grid',
- params: {
- uid: 2
- }
- },
- {
- bidder: 'another',
- params: {
- uid: 3
- }
- },
- {
- bidder: 'gridNM',
- params: {
- uid: 4
- }
- }
- ],
- }]);
+ spec.onDataDeletionRequest([{}]);
expect(ajaxStub.calledOnce).to.equal(true);
- expect(ajaxStub.firstCall.args[0]).to.equal('https://media.grid.bidswitch.net/uspapi_delete');
- expect(ajaxStub.firstCall.args[2]).to.equal('{"uids":[1,2,4]}');
+ expect(ajaxStub.firstCall.args[0]).to.equal('https://media.grid.bidswitch.net/uspapi_delete_c2s');
});
});
diff --git a/test/spec/modules/growthCodeIdSystem_spec.js b/test/spec/modules/growthCodeIdSystem_spec.js
index 97083047d4e..e3848dc4844 100644
--- a/test/spec/modules/growthCodeIdSystem_spec.js
+++ b/test/spec/modules/growthCodeIdSystem_spec.js
@@ -6,9 +6,12 @@ import {expect} from 'chai';
import {getStorageManager} from '../../../src/storageManager.js';
import {MODULE_TYPE_UID} from '../../../src/activities/modules.js';
-const GCID_EXPIRY = 45;
const MODULE_NAME = 'growthCodeId';
-const SHAREDID = 'fe9c5c89-7d56-4666-976d-e07e73b3b664';
+const EIDS = '[{"source":"domain.com","uids":[{"id":"8212212191539393121","ext":{"stype":"ppuid"}}]}]';
+const GCID = 'e06e9e5a-273c-46f8-aace-6f62cf13ea71'
+
+const GCID_EID = '{"id": [{"source": "growthcode.io", "uids": [{"atype": 3,"id": "e06e9e5a-273c-46f8-aace-6f62cf13ea71"}]}]}'
+const GCID_EID_EID = '{"id": [{"source": "growthcode.io", "uids": [{"atype": 3,"id": "e06e9e5a-273c-46f8-aace-6f62cf13ea71"}]},{"source": "domain.com", "uids": [{"id": "8212212191539393121", "ext": {"stype":"ppuid"}}]}]}'
const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME });
@@ -23,11 +26,8 @@ describe('growthCodeIdSystem', () => {
beforeEach(function () {
logErrorStub = sinon.stub(utils, 'logError');
- storage.setDataInLocalStorage('_sharedid', SHAREDID);
- const expiresStr = (new Date(Date.now() + (GCID_EXPIRY * (60 * 60 * 24 * 1000)))).toUTCString();
- if (storage.cookiesAreEnabled()) {
- storage.setCookie('_sharedid', SHAREDID, expiresStr, 'LAX');
- }
+ storage.setDataInLocalStorage('gcid', GCID, null);
+ storage.setDataInLocalStorage('customerEids', EIDS, null);
});
afterEach(function () {
@@ -40,45 +40,33 @@ describe('growthCodeIdSystem', () => {
});
});
- it('should NOT call the growthcode id endpoint if gdpr applies but consent string is missing', function () {
- let submoduleCallback = growthCodeIdSubmodule.getId(getIdParams, { gdprApplies: true }, undefined);
- expect(submoduleCallback).to.be.undefined;
- });
-
- it('should log an error if pid configParam was not passed when getId', function () {
- growthCodeIdSubmodule.getId();
- expect(logErrorStub.callCount).to.be.equal(1);
+ it('test return of GCID', function () {
+ let ids;
+ ids = growthCodeIdSubmodule.getId();
+ expect(ids).to.deep.equal(JSON.parse(GCID_EID));
});
- it('should log an error if sharedId (LocalStore) is not setup correctly', function () {
- growthCodeIdSubmodule.getId({params: {
- pid: 'TEST01',
- publisher_id: '_sharedid_bad',
- publisher_id_storage: 'html5',
+ it('test return of the GCID and an additional EID', function () {
+ let ids;
+ ids = growthCodeIdSubmodule.getId({params: {
+ customerEids: 'customerEids',
}});
- expect(logErrorStub.callCount).to.be.equal(1);
+ expect(ids).to.deep.equal(JSON.parse(GCID_EID_EID));
});
- it('should log an error if sharedId (LocalStore) is not setup correctly', function () {
- growthCodeIdSubmodule.getId({params: {
- pid: 'TEST01',
- publisher_id: '_sharedid_bad',
- publisher_id_storage: 'cookie',
+ it('test return of the GCID and an additional EID (bad Local Store name)', function () {
+ let ids;
+ ids = growthCodeIdSubmodule.getId({params: {
+ customerEids: 'customerEidsBad',
}});
- expect(logErrorStub.callCount).to.be.equal(1);
+ expect(ids).to.deep.equal(JSON.parse(GCID_EID));
});
- it('should call the growthcode id endpoint', function () {
- let callBackSpy = sinon.spy();
- let submoduleCallback = growthCodeIdSubmodule.getId(getIdParams).callback;
- submoduleCallback(callBackSpy);
- let request = server.requests[0];
- expect(request.url.substr(0, 85)).to.be.eq('https://p2.gcprivacy.com/v1/pb?pid=TEST01&uid=' + SHAREDID + '&u=');
- request.respond(
- 200,
- {},
- JSON.stringify({})
- );
- expect(callBackSpy.calledOnce).to.be.true;
+ it('test decode function)', function () {
+ let ids;
+ ids = growthCodeIdSubmodule.decode(GCID, {params: {
+ customerEids: 'customerEids',
+ }});
+ expect(ids).to.deep.equal(JSON.parse('{"growthCodeId":"' + GCID + '"}'));
});
})
diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js
index f541a69abe8..52cfd0294e7 100644
--- a/test/spec/modules/gumgumBidAdapter_spec.js
+++ b/test/spec/modules/gumgumBidAdapter_spec.js
@@ -297,6 +297,14 @@ describe('gumgumAdapter', function () {
expect(bidRequest.data.gpid).to.equal(pbadslot);
});
+ it('should set the global placement id (gpid) if media type is video', function () {
+ const pbadslot = 'cde456'
+ const req = { ...bidRequests[0], ortb2Imp: { ext: { data: { pbadslot } } }, params: zoneParam, mediaTypes: vidMediaTypes }
+ const bidRequest = spec.buildRequests([req])[0];
+ expect(bidRequest.data).to.have.property('gpid');
+ expect(bidRequest.data.gpid).to.equal(pbadslot);
+ });
+
it('should set the bid floor if getFloor module is not present but static bid floor is defined', function () {
const req = { ...bidRequests[0], params: { bidfloor: 42 } }
const bidRequest = spec.buildRequests([req])[0];
@@ -872,6 +880,19 @@ describe('gumgumAdapter', function () {
expect(result.height = expectedSize[1]);
})
+ it('request size that matches response size for in-slot', function () {
+ const request = { ...bidRequest };
+ const body = { ...serverResponse };
+ const expectedSize = [[ 320, 50 ], [300, 600], [300, 250]];
+ let result;
+ request.pi = 3;
+ body.ad.width = 300;
+ body.ad.height = 600;
+ result = spec.interpretResponse({ body }, request)[0];
+ expect(result.width = expectedSize[1][0]);
+ expect(result.height = expectedSize[1][1]);
+ })
+
it('defaults to use bidRequest sizes', function () {
const { ad, jcsi, pag, thms, meta } = serverResponse
const noAdSizes = { ...ad }
diff --git a/test/spec/modules/hadronIdSystem_spec.js b/test/spec/modules/hadronIdSystem_spec.js
index cc0118d4659..85c8cc11c9e 100644
--- a/test/spec/modules/hadronIdSystem_spec.js
+++ b/test/spec/modules/hadronIdSystem_spec.js
@@ -22,7 +22,7 @@ describe('HadronIdSystem', function () {
const callback = hadronIdSubmodule.getId(config).callback;
callback(callbackSpy);
const request = server.requests[0];
- expect(request.url).to.eq(`https://id.hadron.ad.gt/api/v1/pbhid?partner_id=0&_it=prebid`);
+ expect(request.url).to.match(/^https:\/\/id\.hadron\.ad\.gt\/api\/v1\/pbhid/);
request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ hadronId: 'testHadronId1' }));
expect(callbackSpy.lastCall.lastArg).to.deep.equal({ id: { hadronId: 'testHadronId1' } });
});
@@ -47,7 +47,7 @@ describe('HadronIdSystem', function () {
const callback = hadronIdSubmodule.getId(config).callback;
callback(callbackSpy);
const request = server.requests[0];
- expect(request.url).to.eq('https://hadronid.publync.com/?partner_id=0&_it=prebid');
+ expect(request.url).to.match(/^https:\/\/hadronid\.publync\.com\//);
request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ hadronId: 'testHadronId1' }));
expect(callbackSpy.lastCall.lastArg).to.deep.equal({ id: { hadronId: 'testHadronId1' } });
});
diff --git a/test/spec/modules/id5IdSystem_spec.js b/test/spec/modules/id5IdSystem_spec.js
index 56b23ba9634..ecce98d0b8d 100644
--- a/test/spec/modules/id5IdSystem_spec.js
+++ b/test/spec/modules/id5IdSystem_spec.js
@@ -1,26 +1,18 @@
-import {
- expDaysStr,
- getFromLocalStorage,
- getNbFromCache,
- ID5_PRIVACY_STORAGE_NAME,
- ID5_STORAGE_NAME,
- id5IdSubmodule,
- nbCacheName,
- storage,
- storeInLocalStorage,
- storeNbInCache,
-} from 'modules/id5IdSystem.js';
-import {coreStorage, getConsentHash, init, requestBidsHook, setSubmoduleRegistry} from 'modules/userId/index.js';
-import {config} from 'src/config.js';
-import * as events from 'src/events.js';
-import CONSTANTS from 'src/constants.json';
-import * as utils from 'src/utils.js';
-import {uspDataHandler} from 'src/adapterManager.js';
-import 'src/prebid.js';
+import * as id5System from '../../../modules/id5IdSystem.js';
+import {coreStorage, getConsentHash, init, requestBidsHook, setSubmoduleRegistry} from '../../../modules/userId/index.js';
+import {config} from '../../../src/config.js';
+import * as events from '../../../src/events.js';
+import CONSTANTS from '../../../src/constants.json';
+import * as utils from '../../../src/utils.js';
+import {uspDataHandler, gppDataHandler} from '../../../src/adapterManager.js';
+import '../../../src/prebid.js';
import {hook} from '../../../src/hook.js';
import {mockGdprConsent} from '../../helpers/consentData.js';
import {server} from '../../mocks/xhr.js';
import {expect} from 'chai';
+import { GreedyPromise } from '../../../src/utils/promise.js';
+
+const IdFetchFlow = id5System.IdFetchFlow;
describe('ID5 ID System', function () {
const ID5_MODULE_NAME = 'id5Id';
@@ -35,7 +27,6 @@ describe('ID5 ID System', function () {
url: ID5_ENDPOINT
}
};
- const ID5_NB_STORAGE_NAME = nbCacheName(ID5_TEST_PARTNER_ID);
const ID5_STORED_ID = 'storedid5id';
const ID5_STORED_SIGNATURE = '123456';
const ID5_STORED_LINK_TYPE = 1;
@@ -74,11 +65,11 @@ describe('ID5 ID System', function () {
'Content-Type': 'application/json'
}
- function getId5FetchConfig(storageName = ID5_STORAGE_NAME, storageType = 'html5') {
+ function getId5FetchConfig(partner = ID5_TEST_PARTNER_ID, storageName = id5System.ID5_STORAGE_NAME, storageType = 'html5') {
return {
name: ID5_MODULE_NAME,
params: {
- partner: ID5_TEST_PARTNER_ID
+ partner
},
storage: {
name: storageName,
@@ -109,7 +100,7 @@ describe('ID5 ID System', function () {
}
function getFetchLocalStorageConfig() {
- return getUserSyncConfig([getId5FetchConfig(ID5_STORAGE_NAME, 'html5')]);
+ return getUserSyncConfig([getId5FetchConfig()]);
}
function getValueConfig(value) {
@@ -126,67 +117,66 @@ describe('ID5 ID System', function () {
}
function callSubmoduleGetId(config, consentData, cacheIdObj) {
- return new Promise((resolve) => {
- id5IdSubmodule.getId(config, consentData, cacheIdObj).callback((response) => {
- resolve(response)
- })
+ return new GreedyPromise((resolve) => {
+ id5System.id5IdSubmodule.getId(config, consentData, cacheIdObj).callback((response) => {
+ resolve(response);
+ });
});
}
class XhrServerMock {
+ currentRequestIdx = 0;
+ server;
+
constructor(server) {
- this.currentRequestIdx = 0
- this.server = server
+ this.currentRequestIdx = 0;
+ this.server = server;
}
- expectFirstRequest() {
- return this.#expectRequest(0);
+ async expectFirstRequest() {
+ return this.#waitOnRequest(0);
}
- expectNextRequest() {
- return this.#expectRequest(++this.currentRequestIdx)
+ async expectNextRequest() {
+ return this.#waitOnRequest(++this.currentRequestIdx);
}
- expectConfigRequest() {
- return this.expectFirstRequest()
- .then(configRequest => {
- expect(configRequest.url).is.eq(ID5_API_CONFIG_URL);
- expect(configRequest.method).is.eq('POST');
- return configRequest;
- })
+ async expectConfigRequest() {
+ const configRequest = await this.expectFirstRequest();
+ expect(configRequest.url).is.eq(ID5_API_CONFIG_URL);
+ expect(configRequest.method).is.eq('POST');
+ return configRequest;
}
- respondWithConfigAndExpectNext(configRequest, config = ID5_API_CONFIG) {
+ async respondWithConfigAndExpectNext(configRequest, config = ID5_API_CONFIG) {
configRequest.respond(200, HEADERS_CONTENT_TYPE_JSON, JSON.stringify(config));
- return this.expectNextRequest()
+ return this.expectNextRequest();
}
- expectFetchRequest() {
- return this.expectConfigRequest()
- .then(configRequest => {
- return this.respondWithConfigAndExpectNext(configRequest, ID5_API_CONFIG);
- }).then(request => {
- expect(request.url).is.eq(ID5_API_CONFIG.fetchCall.url);
- expect(request.method).is.eq('POST');
- return request;
- })
+ async expectFetchRequest() {
+ const configRequest = await this.expectFirstRequest();
+ const fetchRequest = await this.respondWithConfigAndExpectNext(configRequest);
+ expect(fetchRequest.method).is.eq('POST');
+ expect(fetchRequest.url).is.eq(ID5_API_CONFIG.fetchCall.url);
+ return fetchRequest;
}
- #expectRequest(index) {
- let server = this.server
- return new Promise(function (resolve) {
- (function waitForCondition() {
- if (server.requests && server.requests.length > index) return resolve(server.requests[index]);
- setTimeout(waitForCondition, 30);
- })();
- })
- .then(request => {
- return request
- });
+ async #waitOnRequest(index) {
+ const server = this.server
+ return new GreedyPromise((resolve) => {
+ const waitForCondition = () => {
+ if (server.requests && server.requests.length > index) {
+ resolve(server.requests[index]);
+ } else {
+ setTimeout(waitForCondition, 30);
+ }
+ };
+ waitForCondition();
+ });
}
hasReceivedAnyRequest() {
- let requests = this.server.requests;
+ const requests = this.server.requests;
return requests && requests.length > 0;
}
}
@@ -198,29 +188,29 @@ describe('ID5 ID System', function () {
describe('Check for valid publisher config', function () {
it('should fail with invalid config', function () {
// no config
- expect(id5IdSubmodule.getId()).is.eq(undefined);
- expect(id5IdSubmodule.getId({})).is.eq(undefined);
-
- // valid params, invalid storage
- expect(id5IdSubmodule.getId({ params: { partner: 123 } })).to.be.eq(undefined);
- expect(id5IdSubmodule.getId({ params: { partner: 123 }, storage: {} })).to.be.eq(undefined);
- expect(id5IdSubmodule.getId({ params: { partner: 123 }, storage: { name: '' } })).to.be.eq(undefined);
- expect(id5IdSubmodule.getId({ params: { partner: 123 }, storage: { type: '' } })).to.be.eq(undefined);
-
- // valid storage, invalid params
- expect(id5IdSubmodule.getId({ storage: { name: 'name', type: 'html5', }, })).to.be.eq(undefined);
- expect(id5IdSubmodule.getId({ storage: { name: 'name', type: 'html5', }, params: { } })).to.be.eq(undefined);
- expect(id5IdSubmodule.getId({ storage: { name: 'name', type: 'html5', }, params: { partner: 'abc' } })).to.be.eq(undefined);
+ expect(id5System.id5IdSubmodule.getId()).is.eq(undefined);
+ expect(id5System.id5IdSubmodule.getId({})).is.eq(undefined);
+
+ // valid params, invalid id5System.storage
+ expect(id5System.id5IdSubmodule.getId({ params: { partner: 123 } })).to.be.eq(undefined);
+ expect(id5System.id5IdSubmodule.getId({ params: { partner: 123 }, storage: {} })).to.be.eq(undefined);
+ expect(id5System.id5IdSubmodule.getId({ params: { partner: 123 }, storage: { name: '' } })).to.be.eq(undefined);
+ expect(id5System.id5IdSubmodule.getId({ params: { partner: 123 }, storage: { type: '' } })).to.be.eq(undefined);
+
+ // valid id5System.storage, invalid params
+ expect(id5System.id5IdSubmodule.getId({ storage: { name: 'name', type: 'html5', }, })).to.be.eq(undefined);
+ expect(id5System.id5IdSubmodule.getId({ storage: { name: 'name', type: 'html5', }, params: { } })).to.be.eq(undefined);
+ expect(id5System.id5IdSubmodule.getId({ storage: { name: 'name', type: 'html5', }, params: { partner: 'abc' } })).to.be.eq(undefined);
});
- it('should warn with non-recommended storage params', function () {
- let logWarnStub = sinon.stub(utils, 'logWarn');
+ it('should warn with non-recommended id5System.storage params', function () {
+ const logWarnStub = sinon.stub(utils, 'logWarn');
- id5IdSubmodule.getId({ storage: { name: 'name', type: 'html5', }, params: { partner: 123 } });
+ id5System.id5IdSubmodule.getId({ storage: { name: 'name', type: 'html5', }, params: { partner: 123 } });
expect(logWarnStub.calledOnce).to.be.true;
logWarnStub.restore();
- id5IdSubmodule.getId({ storage: { name: ID5_STORAGE_NAME, type: 'cookie', }, params: { partner: 123 } });
+ id5System.id5IdSubmodule.getId({ storage: { name: id5System.ID5_STORAGE_NAME, type: 'cookie', }, params: { partner: 123 } });
expect(logWarnStub.calledOnce).to.be.true;
logWarnStub.restore();
});
@@ -240,152 +230,150 @@ describe('ID5 ID System', function () {
dataConsentVals.forEach(function([purposeConsent, vendorConsent, caseName]) {
it('should fail with invalid consent because of ' + caseName, function() {
- let dataConsent = {
+ const dataConsent = {
gdprApplies: true,
consentString: 'consentString',
vendorData: {
purposeConsent, vendorConsent
}
}
- expect(id5IdSubmodule.getId(config)).is.eq(undefined);
- expect(id5IdSubmodule.getId(config, dataConsent)).is.eq(undefined);
+ expect(id5System.id5IdSubmodule.getId(config)).is.eq(undefined);
+ expect(id5System.id5IdSubmodule.getId(config, dataConsent)).is.eq(undefined);
- let cacheIdObject = 'cacheIdObject';
- expect(id5IdSubmodule.extendId(config)).is.eq(undefined);
- expect(id5IdSubmodule.extendId(config, dataConsent, cacheIdObject)).is.eq(cacheIdObject);
+ const cacheIdObject = 'cacheIdObject';
+ expect(id5System.id5IdSubmodule.extendId(config)).is.eq(undefined);
+ expect(id5System.id5IdSubmodule.extendId(config, dataConsent, cacheIdObject)).is.eq(cacheIdObject);
});
});
});
describe('Xhr Requests from getId()', function () {
const responseHeader = HEADERS_CONTENT_TYPE_JSON
+ let gppStub
beforeEach(function () {
});
afterEach(function () {
uspDataHandler.reset()
+ gppStub?.restore()
});
- it('should call the ID5 server and handle a valid response', function () {
- let xhrServerMock = new XhrServerMock(server)
- let config = getId5FetchConfig();
- let submoduleResponse = callSubmoduleGetId(config, undefined, undefined);
+ it('should call the ID5 server and handle a valid response', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const config = getId5FetchConfig();
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(fetchRequest.url).to.contain(ID5_ENDPOINT);
- expect(fetchRequest.withCredentials).is.true;
- expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
- expect(requestBody.o).is.eq('pbjs');
- expect(requestBody.pd).is.undefined;
- expect(requestBody.s).is.undefined;
- expect(requestBody.provider).is.undefined
- expect(requestBody.v).is.eq('$prebid.version$');
- expect(requestBody.gdpr).is.eq(0);
- expect(requestBody.gdpr_consent).is.undefined;
- expect(requestBody.us_privacy).is.undefined;
- expect(requestBody.storage).is.deep.eq(config.storage)
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(config, undefined, undefined);
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
- .then(submoduleResponse => {
- expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
- });
+ const fetchRequest = await xhrServerMock.expectFetchRequest()
+
+ expect(fetchRequest.url).to.contain(ID5_ENDPOINT);
+ expect(fetchRequest.withCredentials).is.true;
+
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
+ expect(requestBody.o).is.eq('pbjs');
+ expect(requestBody.pd).is.undefined;
+ expect(requestBody.s).is.undefined;
+ expect(requestBody.provider).is.undefined
+ expect(requestBody.v).is.eq('$prebid.version$');
+ expect(requestBody.gdpr).is.eq(0);
+ expect(requestBody.gdpr_consent).is.undefined;
+ expect(requestBody.us_privacy).is.undefined;
+ expect(requestBody.storage).is.deep.eq(config.storage)
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+
+ const submoduleResponse = await submoduleResponsePromise;
+ expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
});
- it('should call the ID5 server with gdpr data ', function () {
- let xhrServerMock = new XhrServerMock(server)
- let consentData = {
+ it('should call the ID5 server with gdpr data ', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const consentData = {
gdprApplies: true,
consentString: 'consentString',
vendorData: ALLOWED_ID5_VENDOR_DATA
}
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), consentData, undefined);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), consentData, undefined);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
- expect(requestBody.gdpr).to.eq(1);
- expect(requestBody.gdpr_consent).is.eq(consentData.consentString);
+ const fetchRequest = await xhrServerMock.expectFetchRequest()
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
+ expect(requestBody.gdpr).to.eq(1);
+ expect(requestBody.gdpr_consent).is.eq(consentData.consentString);
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
- .then(submoduleResponse => {
- expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
- });
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+
+ const submoduleResponse = await submoduleResponsePromise;
+ expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
});
- it('should call the ID5 server without gdpr data when gdpr not applies ', function () {
- let xhrServerMock = new XhrServerMock(server)
- let consentData = {
+ it('should call the ID5 server without gdpr data when gdpr not applies ', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const consentData = {
gdprApplies: false,
consentString: 'consentString'
}
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), consentData, undefined);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), consentData, undefined);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.gdpr).to.eq(0);
- expect(requestBody.gdpr_consent).is.undefined
+ const fetchRequest = await xhrServerMock.expectFetchRequest()
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.gdpr).to.eq(0);
+ expect(requestBody.gdpr_consent).is.undefined
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
- .then(submoduleResponse => {
- expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
- });
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+
+ const submoduleResponse = await submoduleResponsePromise;
+ expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
});
- it('should call the ID5 server with us privacy consent', function () {
- let usPrivacyString = '1YN-';
+ it('should call the ID5 server with us privacy consent', async function () {
+ const usPrivacyString = '1YN-';
uspDataHandler.setConsentData(usPrivacyString)
- let xhrServerMock = new XhrServerMock(server)
- let consentData = {
+ const xhrServerMock = new XhrServerMock(server)
+ const consentData = {
gdprApplies: true,
consentString: 'consentString',
vendorData: ALLOWED_ID5_VENDOR_DATA
}
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), consentData, undefined);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), consentData, undefined);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
- expect(requestBody.us_privacy).to.eq(usPrivacyString);
+ const fetchRequest = await xhrServerMock.expectFetchRequest()
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
+ expect(requestBody.us_privacy).to.eq(usPrivacyString);
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
- .then(submoduleResponse => {
- expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
- });
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+
+ const submoduleResponse = await submoduleResponsePromise;
+ expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
});
- it('should call the ID5 server with no signature field when no stored object', function () {
- let xhrServerMock = new XhrServerMock(server)
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), undefined, undefined);
+ it('should call the ID5 server with no signature field when no stored object', async function () {
+ const xhrServerMock = new XhrServerMock(server)
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.s).is.undefined;
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), undefined, undefined);
+
+ const fetchRequest = await xhrServerMock.expectFetchRequest()
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.s).is.undefined;
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server for config with submodule config object', function () {
- let xhrServerMock = new XhrServerMock(server)
- let id5FetchConfig = getId5FetchConfig();
+ it('should call the ID5 server for config with submodule config object', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const id5FetchConfig = getId5FetchConfig();
id5FetchConfig.params.extraParam = {
x: 'X',
y: {
@@ -393,340 +381,410 @@ describe('ID5 ID System', function () {
b: '3'
}
}
- let submoduleResponse = callSubmoduleGetId(id5FetchConfig, undefined, undefined);
- return xhrServerMock.expectConfigRequest()
- .then(configRequest => {
- let requestBody = JSON.parse(configRequest.requestBody)
- expect(requestBody).is.deep.eq(id5FetchConfig)
- return xhrServerMock.respondWithConfigAndExpectNext(configRequest)
- })
- .then(fetchRequest => {
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(id5FetchConfig, undefined, undefined);
+
+ const configRequest = await xhrServerMock.expectConfigRequest();
+ const requestBody = JSON.parse(configRequest.requestBody);
+ expect(requestBody).is.deep.eq(id5FetchConfig)
+
+ const fetchRequest = await xhrServerMock.respondWithConfigAndExpectNext(configRequest)
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server for config with partner id being a string', function () {
- let xhrServerMock = new XhrServerMock(server)
- let id5FetchConfig = getId5FetchConfig();
+ it('should call the ID5 server for config with partner id being a string', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const id5FetchConfig = getId5FetchConfig();
id5FetchConfig.params.partner = '173';
- let submoduleResponse = callSubmoduleGetId(id5FetchConfig, undefined, undefined);
- return xhrServerMock.expectConfigRequest()
- .then(configRequest => {
- let requestBody = JSON.parse(configRequest.requestBody)
- expect(requestBody.params.partner).is.eq(173)
- return xhrServerMock.respondWithConfigAndExpectNext(configRequest)
- })
- .then(fetchRequest => {
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(id5FetchConfig, undefined, undefined);
+
+ const configRequest = await xhrServerMock.expectConfigRequest();
+ const requestBody = JSON.parse(configRequest.requestBody)
+ expect(requestBody.params.partner).is.eq(173)
+
+ const fetchRequest = await xhrServerMock.respondWithConfigAndExpectNext(configRequest)
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server for config with overridden url', function () {
- let xhrServerMock = new XhrServerMock(server)
- let id5FetchConfig = getId5FetchConfig();
+ it('should call the ID5 server for config with overridden url', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const id5FetchConfig = getId5FetchConfig();
id5FetchConfig.params.configUrl = 'http://localhost/x/y/z'
- let submoduleResponse = callSubmoduleGetId(id5FetchConfig, undefined, undefined);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(id5FetchConfig, undefined, undefined);
- return xhrServerMock.expectFirstRequest()
- .then(configRequest => {
- expect(configRequest.url).is.eq('http://localhost/x/y/z')
- return xhrServerMock.respondWithConfigAndExpectNext(configRequest)
- })
- .then(fetchRequest => {
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
+ const configRequest = await xhrServerMock.expectFirstRequest();
+ expect(configRequest.url).is.eq('http://localhost/x/y/z');
+
+ const fetchRequest = await xhrServerMock.respondWithConfigAndExpectNext(configRequest)
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server with additional data when provided', function () {
- let xhrServerMock = new XhrServerMock(server)
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), undefined, undefined);
-
- return xhrServerMock.expectConfigRequest()
- .then(configRequest => {
- return xhrServerMock.respondWithConfigAndExpectNext(configRequest, {
- fetchCall: {
- url: ID5_ENDPOINT,
- overrides: {
- arg1: '123',
- arg2: {
- x: '1',
- y: 2
- }
- }
+ it('should call the ID5 server with additional data when provided', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), undefined, undefined);
+
+ const configRequest = await xhrServerMock.expectConfigRequest();
+ const fetchRequest = await xhrServerMock.respondWithConfigAndExpectNext(configRequest, {
+ fetchCall: {
+ url: ID5_ENDPOINT,
+ overrides: {
+ arg1: '123',
+ arg2: {
+ x: '1',
+ y: 2
}
- });
- })
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
- expect(requestBody.o).is.eq('pbjs');
- expect(requestBody.v).is.eq('$prebid.version$');
- expect(requestBody.arg1).is.eq('123')
- expect(requestBody.arg2).is.deep.eq({
- x: '1',
- y: 2
- })
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
+ }
+ }
+ });
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
+ expect(requestBody.o).is.eq('pbjs');
+ expect(requestBody.v).is.eq('$prebid.version$');
+ expect(requestBody.arg1).is.eq('123')
+ expect(requestBody.arg2).is.deep.eq({
+ x: '1',
+ y: 2
+ })
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server with extensions', function () {
- let xhrServerMock = new XhrServerMock(server)
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), undefined, undefined);
-
- return xhrServerMock.expectConfigRequest()
- .then(configRequest => {
- return xhrServerMock.respondWithConfigAndExpectNext(configRequest, {
- fetchCall: {
- url: ID5_ENDPOINT
- },
- extensionsCall: {
- url: ID5_EXTENSIONS_ENDPOINT,
- method: 'GET'
- }
- });
- })
- .then(extensionsRequest => {
- expect(extensionsRequest.url).is.eq(ID5_EXTENSIONS_ENDPOINT)
- expect(extensionsRequest.method).is.eq('GET')
- extensionsRequest.respond(200, responseHeader, JSON.stringify({
- lb: 'ex'
- }))
- return xhrServerMock.expectNextRequest();
- })
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
- expect(requestBody.o).is.eq('pbjs');
- expect(requestBody.v).is.eq('$prebid.version$');
- expect(requestBody.extensions).is.deep.eq({
- lb: 'ex'
- })
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
+ it('should call the ID5 server with extensions', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), undefined, undefined);
+
+ const configRequest = await xhrServerMock.expectConfigRequest();
+ const extensionsRequest = await xhrServerMock.respondWithConfigAndExpectNext(configRequest, {
+ fetchCall: {
+ url: ID5_ENDPOINT
+ },
+ extensionsCall: {
+ url: ID5_EXTENSIONS_ENDPOINT,
+ method: 'GET'
+ }
+ });
+ expect(extensionsRequest.url).is.eq(ID5_EXTENSIONS_ENDPOINT)
+ expect(extensionsRequest.method).is.eq('GET')
+
+ extensionsRequest.respond(200, responseHeader, JSON.stringify({
+ lb: 'ex'
+ }));
+ const fetchRequest = await xhrServerMock.expectNextRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
+ expect(requestBody.o).is.eq('pbjs');
+ expect(requestBody.v).is.eq('$prebid.version$');
+ expect(requestBody.extensions).is.deep.eq({
+ lb: 'ex'
+ })
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server with extensions fetched with POST', function () {
- let xhrServerMock = new XhrServerMock(server)
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), undefined, undefined);
-
- return xhrServerMock.expectConfigRequest()
- .then(configRequest => {
- return xhrServerMock.respondWithConfigAndExpectNext(configRequest, {
- fetchCall: {
- url: ID5_ENDPOINT
- },
- extensionsCall: {
- url: ID5_EXTENSIONS_ENDPOINT,
- method: 'POST',
- body: {
- x: '1',
- y: 2
- }
- }
- });
- })
- .then(extensionsRequest => {
- expect(extensionsRequest.url).is.eq(ID5_EXTENSIONS_ENDPOINT)
- expect(extensionsRequest.method).is.eq('POST')
- let requestBody = JSON.parse(extensionsRequest.requestBody)
- expect(requestBody).is.deep.eq({
+ it('should call the ID5 server with extensions fetched using method POST', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), undefined, undefined);
+
+ const configRequest = await xhrServerMock.expectConfigRequest();
+ const extensionsRequest = await xhrServerMock.respondWithConfigAndExpectNext(configRequest, {
+ fetchCall: {
+ url: ID5_ENDPOINT
+ },
+ extensionsCall: {
+ url: ID5_EXTENSIONS_ENDPOINT,
+ method: 'POST',
+ body: {
x: '1',
y: 2
- })
- extensionsRequest.respond(200, responseHeader, JSON.stringify({
- lb: 'post',
- }))
- return xhrServerMock.expectNextRequest();
- })
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
- expect(requestBody.o).is.eq('pbjs');
- expect(requestBody.v).is.eq('$prebid.version$');
- expect(requestBody.extensions).is.deep.eq({
- lb: 'post'
- })
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
+ }
+ }
+ });
+ expect(extensionsRequest.url).is.eq(ID5_EXTENSIONS_ENDPOINT)
+ expect(extensionsRequest.method).is.eq('POST')
+ const extRequestBody = JSON.parse(extensionsRequest.requestBody)
+ expect(extRequestBody).is.deep.eq({
+ x: '1',
+ y: 2
+ })
+ extensionsRequest.respond(200, responseHeader, JSON.stringify({
+ lb: 'post',
+ }));
+
+ const fetchRequest = await xhrServerMock.expectNextRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.partner).is.eq(ID5_TEST_PARTNER_ID);
+ expect(requestBody.o).is.eq('pbjs');
+ expect(requestBody.v).is.eq('$prebid.version$');
+ expect(requestBody.extensions).is.deep.eq({
+ lb: 'post'
+ });
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server with signature field from stored object', function () {
- let xhrServerMock = new XhrServerMock(server)
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
+ it('should call the ID5 server with signature field from stored object', async function () {
+ const xhrServerMock = new XhrServerMock(server)
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.s).is.eq(ID5_STORED_SIGNATURE);
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
+
+ const fetchRequest = await xhrServerMock.expectFetchRequest()
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.s).is.eq(ID5_STORED_SIGNATURE);
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server with pd field when pd config is set', function () {
- let xhrServerMock = new XhrServerMock(server)
+ it('should call the ID5 server with pd field when pd config is set', async function () {
+ const xhrServerMock = new XhrServerMock(server)
const pubData = 'b50ca08271795a8e7e4012813f23d505193d75c0f2e2bb99baa63aa822f66ed3';
- let id5Config = getId5FetchConfig();
+ const id5Config = getId5FetchConfig();
id5Config.params.pd = pubData;
- let submoduleResponse = callSubmoduleGetId(id5Config, undefined, ID5_STORED_OBJ);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(id5Config, undefined, undefined);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.pd).is.eq(pubData);
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse;
- })
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.pd).is.eq(pubData);
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server with no pd field when pd config is not set', function () {
- let xhrServerMock = new XhrServerMock(server)
- let id5Config = getId5FetchConfig();
+ it('should call the ID5 server with no pd field when pd config is not set', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const id5Config = getId5FetchConfig();
id5Config.params.pd = undefined;
- let submoduleResponse = callSubmoduleGetId(id5Config, undefined, ID5_STORED_OBJ);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(id5Config, undefined, ID5_STORED_OBJ);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.pd).is.undefined;
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse;
- })
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.pd).is.undefined;
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server with nb=1 when no stored value exists and reset after', function () {
- let xhrServerMock = new XhrServerMock(server)
- coreStorage.removeDataFromLocalStorage(ID5_NB_STORAGE_NAME);
+ it('should call the ID5 server with nb=1 when no stored value exists and reset after', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const TEST_PARTNER_ID = 189;
+ coreStorage.removeDataFromLocalStorage(id5System.nbCacheName(TEST_PARTNER_ID));
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.nbPage).is.eq(1);
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
- .then(() => {
- expect(getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(0);
- })
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.nbPage).is.eq(1);
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
+
+ expect(id5System.getNbFromCache(TEST_PARTNER_ID)).is.eq(0);
});
- it('should call the ID5 server with incremented nb when stored value exists and reset after', function () {
- let xhrServerMock = new XhrServerMock(server)
- storeNbInCache(ID5_TEST_PARTNER_ID, 1);
+ it('should call the ID5 server with incremented nb when stored value exists and reset after', async function () {
+ const xhrServerMock = new XhrServerMock(server);
+ const TEST_PARTNER_ID = 189;
+ const config = getId5FetchConfig(TEST_PARTNER_ID);
+ id5System.storeNbInCache(TEST_PARTNER_ID, 1);
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(config, undefined, ID5_STORED_OBJ);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.nbPage).is.eq(2);
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
- .then(() => {
- expect(getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(0);
- })
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.nbPage).is.eq(2);
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
+
+ expect(id5System.getNbFromCache(TEST_PARTNER_ID)).is.eq(0);
});
- it('should call the ID5 server with ab_testing object when abTesting is turned on', function () {
- let xhrServerMock = new XhrServerMock(server)
- let id5Config = getId5FetchConfig();
+ it('should call the ID5 server with ab_testing object when abTesting is turned on', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const id5Config = getId5FetchConfig();
id5Config.params.abTesting = {enabled: true, controlGroupPct: 0.234}
- let submoduleResponse = callSubmoduleGetId(id5Config, undefined, ID5_STORED_OBJ);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(id5Config, undefined, ID5_STORED_OBJ);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.ab_testing.enabled).is.eq(true);
- expect(requestBody.ab_testing.control_group_pct).is.eq(0.234);
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse;
- });
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.ab_testing.enabled).is.eq(true);
+ expect(requestBody.ab_testing.control_group_pct).is.eq(0.234);
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server without ab_testing object when abTesting is turned off', function () {
- let xhrServerMock = new XhrServerMock(server)
- let id5Config = getId5FetchConfig();
+ it('should call the ID5 server without ab_testing object when abTesting is turned off', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const id5Config = getId5FetchConfig();
id5Config.params.abTesting = {enabled: false, controlGroupPct: 0.55}
- let submoduleResponse = callSubmoduleGetId(id5Config, undefined, ID5_STORED_OBJ);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(id5Config, undefined, ID5_STORED_OBJ);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.ab_testing).is.undefined;
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- });
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.ab_testing).is.undefined;
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should call the ID5 server without ab_testing when when abTesting is not set', function () {
- let xhrServerMock = new XhrServerMock(server)
- let id5Config = getId5FetchConfig();
+ it('should call the ID5 server without ab_testing when when abTesting is not set', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+ const id5Config = getId5FetchConfig();
- let submoduleResponse = callSubmoduleGetId(id5Config, undefined, ID5_STORED_OBJ);
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(id5Config, undefined, ID5_STORED_OBJ);
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.ab_testing).is.undefined;
- fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- });
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.ab_testing).is.undefined;
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+ await submoduleResponsePromise;
});
- it('should store the privacy object from the ID5 server response', function () {
- let xhrServerMock = new XhrServerMock(server)
- let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
+ it('should store the privacy object from the ID5 server response', async function () {
+ const xhrServerMock = new XhrServerMock(server)
+
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
const privacy = {
jurisdiction: 'gdpr',
id5_consent: true
};
- return xhrServerMock.expectFetchRequest()
- .then(request => {
- let responseObject = utils.deepClone(ID5_JSON_RESPONSE);
- responseObject.privacy = privacy;
- request.respond(200, responseHeader, JSON.stringify(responseObject));
- return submoduleResponse
- })
- .then(() => {
- expect(getFromLocalStorage(ID5_PRIVACY_STORAGE_NAME)).is.eq(JSON.stringify(privacy));
- coreStorage.removeDataFromLocalStorage(ID5_PRIVACY_STORAGE_NAME);
- })
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const responseObject = utils.deepClone(ID5_JSON_RESPONSE);
+ responseObject.privacy = privacy;
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(responseObject));
+ await submoduleResponsePromise;
+
+ expect(id5System.getFromLocalStorage(id5System.ID5_PRIVACY_STORAGE_NAME)).is.eq(JSON.stringify(privacy));
+ coreStorage.removeDataFromLocalStorage(id5System.ID5_PRIVACY_STORAGE_NAME);
+ });
+
+ it('should not store a privacy object if not part of ID5 server response', async function () {
+ const xhrServerMock = new XhrServerMock(server);
+ coreStorage.removeDataFromLocalStorage(id5System.ID5_PRIVACY_STORAGE_NAME);
+
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
+
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const responseObject = utils.deepClone(ID5_JSON_RESPONSE);
+ responseObject.privacy = undefined;
+
+ fetchRequest.respond(200, responseHeader, JSON.stringify(responseObject));
+ await submoduleResponsePromise;
+
+ expect(id5System.getFromLocalStorage(id5System.ID5_PRIVACY_STORAGE_NAME)).is.null;
+ });
+
+ describe('with successful external module call', function() {
+ const MOCK_RESPONSE = {
+ ...ID5_JSON_RESPONSE,
+ universal_uid: 'my_mock_reponse'
+ };
+ let mockId5ExternalModule;
+
+ beforeEach(() => {
+ window.id5Prebid = {
+ integration: {
+ fetchId5Id: function() {}
+ }
+ };
+ mockId5ExternalModule = sinon.stub(window.id5Prebid.integration, 'fetchId5Id')
+ .resolves(MOCK_RESPONSE);
+ });
+
+ this.afterEach(() => {
+ mockId5ExternalModule.restore();
+ delete window.id5Prebid;
+ });
+
+ it('should retrieve the response from the external module interface', async function() {
+ const xhrServerMock = new XhrServerMock(server);
+ const config = getId5FetchConfig();
+ config.params.externalModuleUrl = 'https://test-me.test';
+
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(config, undefined, undefined);
+
+ const configRequest = await xhrServerMock.expectConfigRequest();
+ configRequest.respond(200, HEADERS_CONTENT_TYPE_JSON, JSON.stringify(ID5_API_CONFIG));
+
+ const submoduleResponse = await submoduleResponsePromise;
+ expect(submoduleResponse).to.deep.equal(MOCK_RESPONSE);
+ expect(mockId5ExternalModule.calledOnce);
+ });
});
- it('should not store a privacy object if not part of ID5 server response', function () {
+ describe('with failing external module loading', function() {
+ it('should fallback to regular logic if external module fails to load', async function() {
+ const xhrServerMock = new XhrServerMock(server);
+ const config = getId5FetchConfig();
+ config.params.externalModuleUrl = 'https://test-me.test'; // Fails by loading this fake URL
+
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(config, undefined, undefined);
+
+ // Still we have a server-side request triggered as fallback
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
+
+ const submoduleResponse = await submoduleResponsePromise;
+ expect(submoduleResponse).to.deep.equal(ID5_JSON_RESPONSE);
+ });
+ });
+
+ it('should pass gpp_string and gpp_sid to ID5 server', function () {
let xhrServerMock = new XhrServerMock(server)
- coreStorage.removeDataFromLocalStorage(ID5_PRIVACY_STORAGE_NAME);
+ gppStub = sinon.stub(gppDataHandler, 'getConsentData');
+ gppStub.returns({
+ ready: true,
+ gppString: 'GPP_STRING',
+ applicableSections: [2]
+ });
let submoduleResponse = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
return xhrServerMock.expectFetchRequest()
- .then(request => {
- let responseObject = utils.deepClone(ID5_JSON_RESPONSE);
- responseObject.privacy = undefined;
- request.respond(200, responseHeader, JSON.stringify(responseObject));
+ .then(fetchRequest => {
+ let requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.gpp_string).is.equal('GPP_STRING');
+ expect(requestBody.gpp_sid).contains(2);
+ fetchRequest.respond(200, responseHeader, JSON.stringify(ID5_JSON_RESPONSE));
return submoduleResponse
- })
- .then(() => {
- expect(getFromLocalStorage(ID5_PRIVACY_STORAGE_NAME)).is.null;
});
});
@@ -734,14 +792,14 @@ describe('ID5 ID System', function () {
let sandbox;
beforeEach(() => {
sandbox = sinon.sandbox.create();
- sandbox.stub(storage, 'getCookie');
+ sandbox.stub(id5System.storage, 'getCookie');
});
afterEach(() => {
sandbox.restore();
});
it('should not throw if malformed JSON is forced into cookies', () => {
- storage.getCookie.callsFake(() => ' Not JSON ');
- id5IdSubmodule.getId(getId5FetchConfig());
+ id5System.storage.getCookie.callsFake(() => ' Not JSON ');
+ id5System.id5IdSubmodule.getId(getId5FetchConfig());
});
})
});
@@ -750,7 +808,7 @@ describe('ID5 ID System', function () {
let sandbox;
beforeEach(() => {
sandbox = sinon.sandbox.create();
- sandbox.stub(storage, 'localStorageIsEnabled');
+ sandbox.stub(id5System.storage, 'localStorageIsEnabled');
});
afterEach(() => {
sandbox.restore();
@@ -758,26 +816,23 @@ describe('ID5 ID System', function () {
[
[true, 1],
[false, 0]
- ].forEach(function ([isEnabled, expectedValue]) {
- it(`should check localStorage availability and log in request. Available=${isEnabled}`, () => {
- let xhrServerMock = new XhrServerMock(server)
- let config = getId5FetchConfig();
- let submoduleResponse = callSubmoduleGetId(config, undefined, undefined);
- storage.localStorageIsEnabled.callsFake(() => isEnabled)
-
- return xhrServerMock.expectFetchRequest()
- .then(fetchRequest => {
- let requestBody = JSON.parse(fetchRequest.requestBody);
- expect(requestBody.localStorage).is.eq(expectedValue);
-
- fetchRequest.respond(200, HEADERS_CONTENT_TYPE_JSON, JSON.stringify(ID5_JSON_RESPONSE));
- return submoduleResponse
- })
- .then(submoduleResponse => {
- expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
- });
- })
- })
+ ].forEach(([isEnabled, expectedValue]) => {
+ it(`should check localStorage availability and log in request. Available=${isEnabled}`, async function() {
+ const xhrServerMock = new XhrServerMock(server)
+ id5System.storage.localStorageIsEnabled.callsFake(() => isEnabled)
+
+ // Trigger the fetch but we await on it later
+ const submoduleResponsePromise = callSubmoduleGetId(getId5FetchConfig(), undefined, ID5_STORED_OBJ);
+
+ const fetchRequest = await xhrServerMock.expectFetchRequest();
+ const requestBody = JSON.parse(fetchRequest.requestBody);
+ expect(requestBody.localStorage).is.eq(expectedValue);
+
+ fetchRequest.respond(200, HEADERS_CONTENT_TYPE_JSON, JSON.stringify(ID5_JSON_RESPONSE));
+ const submoduleResponse = await submoduleResponsePromise;
+ expect(submoduleResponse).is.deep.equal(ID5_JSON_RESPONSE);
+ });
+ });
});
describe('Request Bids Hook', function () {
@@ -788,26 +843,26 @@ describe('ID5 ID System', function () {
sandbox = sinon.sandbox.create();
mockGdprConsent(sandbox);
sinon.stub(events, 'getEvents').returns([]);
- coreStorage.removeDataFromLocalStorage(ID5_STORAGE_NAME);
- coreStorage.removeDataFromLocalStorage(`${ID5_STORAGE_NAME}_last`);
- coreStorage.removeDataFromLocalStorage(ID5_NB_STORAGE_NAME);
- coreStorage.setDataInLocalStorage(ID5_STORAGE_NAME + '_cst', getConsentHash())
+ coreStorage.removeDataFromLocalStorage(id5System.ID5_STORAGE_NAME);
+ coreStorage.removeDataFromLocalStorage(`${id5System.ID5_STORAGE_NAME}_last`);
+ coreStorage.removeDataFromLocalStorage(id5System.nbCacheName(ID5_TEST_PARTNER_ID));
+ coreStorage.setDataInLocalStorage(id5System.ID5_STORAGE_NAME + '_cst', getConsentHash())
adUnits = [getAdUnitMock()];
});
afterEach(function () {
events.getEvents.restore();
- coreStorage.removeDataFromLocalStorage(ID5_STORAGE_NAME);
- coreStorage.removeDataFromLocalStorage(`${ID5_STORAGE_NAME}_last`);
- coreStorage.removeDataFromLocalStorage(ID5_NB_STORAGE_NAME);
- coreStorage.removeDataFromLocalStorage(ID5_STORAGE_NAME + '_cst')
+ coreStorage.removeDataFromLocalStorage(id5System.ID5_STORAGE_NAME);
+ coreStorage.removeDataFromLocalStorage(`${id5System.ID5_STORAGE_NAME}_last`);
+ coreStorage.removeDataFromLocalStorage(id5System.nbCacheName(ID5_TEST_PARTNER_ID));
+ coreStorage.removeDataFromLocalStorage(id5System.ID5_STORAGE_NAME + '_cst')
sandbox.restore();
});
it('should add stored ID from cache to bids', function (done) {
- storeInLocalStorage(ID5_STORAGE_NAME, JSON.stringify(ID5_STORED_OBJ), 1);
+ id5System.storeInLocalStorage(id5System.ID5_STORAGE_NAME, JSON.stringify(ID5_STORED_OBJ), 1);
init(config);
- setSubmoduleRegistry([id5IdSubmodule]);
+ setSubmoduleRegistry([id5System.id5IdSubmodule]);
config.setConfig(getFetchLocalStorageConfig());
requestBidsHook(function () {
@@ -833,7 +888,7 @@ describe('ID5 ID System', function () {
it('should add config value ID to bids', function (done) {
init(config);
- setSubmoduleRegistry([id5IdSubmodule]);
+ setSubmoduleRegistry([id5System.id5IdSubmodule]);
config.setConfig(getValueConfig(ID5_STORED_ID));
requestBidsHook(function () {
@@ -852,44 +907,44 @@ describe('ID5 ID System', 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);
+ id5System.storeInLocalStorage(id5System.ID5_STORAGE_NAME, JSON.stringify(ID5_STORED_OBJ), 1);
+ coreStorage.removeDataFromLocalStorage(id5System.nbCacheName(ID5_TEST_PARTNER_ID));
init(config);
- setSubmoduleRegistry([id5IdSubmodule]);
+ setSubmoduleRegistry([id5System.id5IdSubmodule]);
config.setConfig(getFetchLocalStorageConfig());
requestBidsHook((adUnitConfig) => {
- expect(getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(1);
+ expect(id5System.getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(1);
done()
}, {adUnits});
});
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);
+ id5System.storeInLocalStorage(id5System.ID5_STORAGE_NAME, JSON.stringify(ID5_STORED_OBJ), 1);
+ id5System.storeNbInCache(ID5_TEST_PARTNER_ID, 1);
init(config);
- setSubmoduleRegistry([id5IdSubmodule]);
+ setSubmoduleRegistry([id5System.id5IdSubmodule]);
config.setConfig(getFetchLocalStorageConfig());
requestBidsHook(() => {
- expect(getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(2);
+ expect(id5System.getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(2);
done()
}, {adUnits});
});
it('should call ID5 servers with signature and incremented nb post auction if refresh needed', function () {
- let xhrServerMock = new XhrServerMock(server)
- let initialLocalStorageValue = JSON.stringify(ID5_STORED_OBJ);
- storeInLocalStorage(ID5_STORAGE_NAME, initialLocalStorageValue, 1);
- storeInLocalStorage(`${ID5_STORAGE_NAME}_last`, expDaysStr(-1), 1);
+ const xhrServerMock = new XhrServerMock(server)
+ const initialLocalStorageValue = JSON.stringify(ID5_STORED_OBJ);
+ id5System.storeInLocalStorage(id5System.ID5_STORAGE_NAME, initialLocalStorageValue, 1);
+ id5System.storeInLocalStorage(`${id5System.ID5_STORAGE_NAME}_last`, id5System.expDaysStr(-1), 1);
- storeNbInCache(ID5_TEST_PARTNER_ID, 1);
+ id5System.storeNbInCache(ID5_TEST_PARTNER_ID, 1);
let id5Config = getFetchLocalStorageConfig();
id5Config.userSync.userIds[0].storage.refreshInSeconds = 2;
init(config);
- setSubmoduleRegistry([id5IdSubmodule]);
+ setSubmoduleRegistry([id5System.id5IdSubmodule]);
config.setConfig(id5Config);
return new Promise((resolve) => {
@@ -899,23 +954,23 @@ describe('ID5 ID System', function () {
}).then(() => {
expect(xhrServerMock.hasReceivedAnyRequest()).is.false;
events.emit(CONSTANTS.EVENTS.AUCTION_END, {});
- return xhrServerMock.expectFetchRequest()
+ return xhrServerMock.expectFetchRequest();
}).then(request => {
- let requestBody = JSON.parse(request.requestBody);
+ const requestBody = JSON.parse(request.requestBody);
expect(requestBody.s).is.eq(ID5_STORED_SIGNATURE);
expect(requestBody.nbPage).is.eq(2);
- expect(getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(2);
+ expect(id5System.getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(0);
request.respond(200, HEADERS_CONTENT_TYPE_JSON, JSON.stringify(ID5_JSON_RESPONSE));
return new Promise(function (resolve) {
(function waitForCondition() {
- if (getFromLocalStorage(ID5_STORAGE_NAME) !== initialLocalStorageValue) return resolve();
+ if (id5System.getFromLocalStorage(id5System.ID5_STORAGE_NAME) !== initialLocalStorageValue) return resolve();
setTimeout(waitForCondition, 30);
})();
})
}).then(() => {
- expect(decodeURIComponent(getFromLocalStorage(ID5_STORAGE_NAME))).is.eq(JSON.stringify(ID5_JSON_RESPONSE));
- expect(getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(0);
+ expect(decodeURIComponent(id5System.getFromLocalStorage(id5System.ID5_STORAGE_NAME))).is.eq(JSON.stringify(ID5_JSON_RESPONSE));
+ expect(id5System.getNbFromCache(ID5_TEST_PARTNER_ID)).is.eq(0);
})
});
});
@@ -924,10 +979,10 @@ describe('ID5 ID System', function () {
const expectedDecodedObject = {id5id: {uid: ID5_STORED_ID, ext: {linkType: ID5_STORED_LINK_TYPE}}};
it('should properly decode from a stored object', function () {
- expect(id5IdSubmodule.decode(ID5_STORED_OBJ, getId5FetchConfig())).is.deep.equal(expectedDecodedObject);
+ expect(id5System.id5IdSubmodule.decode(ID5_STORED_OBJ, getId5FetchConfig())).is.deep.equal(expectedDecodedObject);
});
it('should return undefined if passed a string', function () {
- expect(id5IdSubmodule.decode('somestring', getId5FetchConfig())).is.eq(undefined);
+ expect(id5System.id5IdSubmodule.decode('somestring', getId5FetchConfig())).is.eq(undefined);
});
});
@@ -970,13 +1025,13 @@ describe('ID5 ID System', function () {
});
it('should not set abTestingControlGroup extension when A/B testing is off', function () {
- let decoded = id5IdSubmodule.decode(storedObject, testConfig);
+ const decoded = id5System.id5IdSubmodule.decode(storedObject, testConfig);
expect(decoded).is.deep.equal(expectedDecodedObjectWithIdAbOff);
});
it('should set abTestingControlGroup to false when A/B testing is on but in normal group', function () {
storedObject.ab_testing = {result: 'normal'};
- let decoded = id5IdSubmodule.decode(storedObject, testConfig);
+ const decoded = id5System.id5IdSubmodule.decode(storedObject, testConfig);
expect(decoded).is.deep.equal(expectedDecodedObjectWithIdAbOn);
});
@@ -986,13 +1041,13 @@ describe('ID5 ID System', function () {
storedObject.ext = {
'linkType': 0
};
- let decoded = id5IdSubmodule.decode(storedObject, testConfig);
+ const decoded = id5System.id5IdSubmodule.decode(storedObject, testConfig);
expect(decoded).is.deep.equal(expectedDecodedObjectWithoutIdAbOn);
});
it('should log A/B testing errors', function () {
storedObject.ab_testing = {result: 'error'};
- let decoded = id5IdSubmodule.decode(storedObject, testConfig);
+ const decoded = id5System.id5IdSubmodule.decode(storedObject, testConfig);
expect(decoded).is.deep.equal(expectedDecodedObjectWithIdAbOff);
sinon.assert.calledOnce(logErrorSpy);
});
diff --git a/test/spec/modules/identityLinkIdSystem_spec.js b/test/spec/modules/identityLinkIdSystem_spec.js
index a273f26b28b..66d5a3edd00 100644
--- a/test/spec/modules/identityLinkIdSystem_spec.js
+++ b/test/spec/modules/identityLinkIdSystem_spec.js
@@ -3,6 +3,7 @@ import * as utils from 'src/utils.js';
import {server} from 'test/mocks/xhr.js';
import {getCoreStorageManager} from '../../../src/storageManager.js';
import {stub} from 'sinon';
+import { gppDataHandler } from '../../../src/adapterManager.js';
const storage = getCoreStorageManager();
@@ -20,6 +21,7 @@ function setTestEnvelopeCookie () {
describe('IdentityLinkId tests', function () {
let logErrorStub;
+ let gppConsentDataStub;
beforeEach(function () {
defaultConfigParams = { params: {pid: pid} };
@@ -73,16 +75,19 @@ describe('IdentityLinkId tests', function () {
expect(submoduleCallback).to.be.undefined;
});
- it('should call the LiveRamp envelope endpoint with IAB consent string v1', function () {
+ it('should call the LiveRamp envelope endpoint with IAB consent string v2', function () {
let callBackSpy = sinon.spy();
let consentData = {
gdprApplies: true,
- consentString: 'BOkIpDSOkIpDSADABAENCc-AAAApOAFAAMAAsAMIAcAA_g'
+ consentString: 'CO4VThZO4VTiuADABBENAzCgAP_AAEOAAAAAAwwAgAEABhAAgAgAAA.YAAAAAAAAAA',
+ vendorData: {
+ tcfPolicyVersion: 2
+ }
};
let submoduleCallback = identityLinkSubmodule.getId(defaultConfigParams, consentData).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq('https://api.rlcdn.com/api/identity/envelope?pid=14&ct=1&cv=BOkIpDSOkIpDSADABAENCc-AAAApOAFAAMAAsAMIAcAA_g');
+ expect(request.url).to.be.eq('https://api.rlcdn.com/api/identity/envelope?pid=14&ct=4&cv=CO4VThZO4VTiuADABBENAzCgAP_AAEOAAAAAAwwAgAEABhAAgAgAAA.YAAAAAAAAAA');
request.respond(
200,
responseHeader,
@@ -91,25 +96,46 @@ describe('IdentityLinkId tests', function () {
expect(callBackSpy.calledOnce).to.be.true;
});
- it('should call the LiveRamp envelope endpoint with IAB consent string v2', function () {
+ it('should call the LiveRamp envelope endpoint with GPP consent string', function() {
+ gppConsentDataStub = sinon.stub(gppDataHandler, 'getConsentData');
+ gppConsentDataStub.returns({
+ ready: true,
+ gppString: 'DBABLA~BVVqAAAACqA.QA',
+ applicableSections: [7]
+ });
let callBackSpy = sinon.spy();
- let consentData = {
- gdprApplies: true,
- consentString: 'CO4VThZO4VTiuADABBENAzCgAP_AAEOAAAAAAwwAgAEABhAAgAgAAA.YAAAAAAAAAA',
- vendorData: {
- tcfPolicyVersion: 2
- }
- };
- let submoduleCallback = identityLinkSubmodule.getId(defaultConfigParams, consentData).callback;
+ let submoduleCallback = identityLinkSubmodule.getId(defaultConfigParams).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq('https://api.rlcdn.com/api/identity/envelope?pid=14&ct=4&cv=CO4VThZO4VTiuADABBENAzCgAP_AAEOAAAAAAwwAgAEABhAAgAgAAA.YAAAAAAAAAA');
+ expect(request.url).to.be.eq('https://api.rlcdn.com/api/identity/envelope?pid=14&gpp=DBABLA~BVVqAAAACqA.QA&gpp_sid=7');
+ request.respond(
+ 200,
+ responseHeader,
+ JSON.stringify({})
+ );
+ expect(callBackSpy.calledOnce).to.be.true;
+ gppConsentDataStub.restore();
+ });
+
+ it('should call the LiveRamp envelope endpoint without GPP consent string if consent string is not provided', function () {
+ gppConsentDataStub = sinon.stub(gppDataHandler, 'getConsentData');
+ gppConsentDataStub.returns({
+ ready: true,
+ gppString: '',
+ applicableSections: [7]
+ });
+ let callBackSpy = sinon.spy();
+ let submoduleCallback = identityLinkSubmodule.getId(defaultConfigParams).callback;
+ submoduleCallback(callBackSpy);
+ let request = server.requests[0];
+ expect(request.url).to.be.eq('https://api.rlcdn.com/api/identity/envelope?pid=14');
request.respond(
200,
responseHeader,
JSON.stringify({})
);
expect(callBackSpy.calledOnce).to.be.true;
+ gppConsentDataStub.restore();
});
it('should not throw Uncaught TypeError when envelope endpoint returns empty response', function () {
diff --git a/test/spec/modules/impactifyBidAdapter_spec.js b/test/spec/modules/impactifyBidAdapter_spec.js
index adf968d610d..d9bf4becb22 100644
--- a/test/spec/modules/impactifyBidAdapter_spec.js
+++ b/test/spec/modules/impactifyBidAdapter_spec.js
@@ -36,7 +36,7 @@ describe('ImpactifyAdapter', function () {
localStorageIsEnabledStub = sandbox.stub(STORAGE, 'localStorageIsEnabled');
});
- afterEach(function() {
+ afterEach(function () {
$$PREBID_GLOBAL$$.bidderSettings = {};
document.body.appendChild.restore();
sandbox.restore();
@@ -57,7 +57,6 @@ describe('ImpactifyAdapter', function () {
params: {
appId: 'example.com',
format: 'display',
- size: '728x90',
style: 'static'
}
}
@@ -282,7 +281,7 @@ describe('ImpactifyAdapter', function () {
};
it('should pass bidfloor', function () {
- videoBidRequests[0].getFloor = function() {
+ videoBidRequests[0].getFloor = function () {
return {
currency: 'USD',
floor: 1.23,
@@ -342,7 +341,7 @@ describe('ImpactifyAdapter', function () {
h: 1,
hash: 'test',
expiry: 166192938,
- meta: {'advertiserDomains': ['testdomain.com']},
+ meta: { 'advertiserDomains': ['testdomain.com'] },
ext: {
prebid: {
'type': 'video'
@@ -418,7 +417,7 @@ describe('ImpactifyAdapter', function () {
height: 1,
hash: 'test',
expiry: 166192938,
- meta: {'advertiserDomains': ['testdomain.com']},
+ meta: { 'advertiserDomains': ['testdomain.com'] },
ttl: 300,
creativeId: '97517771'
}
@@ -480,7 +479,7 @@ describe('ImpactifyAdapter', function () {
h: 1,
hash: 'test',
expiry: 166192938,
- meta: {'advertiserDomains': ['testdomain.com']},
+ meta: { 'advertiserDomains': ['testdomain.com'] },
ext: {
prebid: {
'type': 'video'
@@ -536,8 +535,8 @@ describe('ImpactifyAdapter', function () {
const result = spec.getUserSyncs('bad', [], gdprData);
expect(result).to.be.empty;
});
- it('should append the various values if they exist', function() {
- const result = spec.getUserSyncs({iframeEnabled: true}, validResponse, gdprData);
+ it('should append the various values if they exist', function () {
+ const result = spec.getUserSyncs({ iframeEnabled: true }, validResponse, gdprData);
expect(result[0].url).to.include('gdpr=1');
expect(result[0].url).to.include('gdpr_consent=BOh7mtYOh7mtYAcABBENCU-AAAAncgPIXJiiAoao0PxBFkgCAC8ACIAAQAQQAAIAAAIAAAhBGAAAQAQAEQgAAAAAAABAAAAAAAAAAAAAAACAAAAAAAACgAAAAABAAAAQAAAAAAA');
});
diff --git a/test/spec/modules/innityBidAdapter_spec.js b/test/spec/modules/innityBidAdapter_spec.js
index 192ab4911ee..820f535ba72 100644
--- a/test/spec/modules/innityBidAdapter_spec.js
+++ b/test/spec/modules/innityBidAdapter_spec.js
@@ -120,5 +120,11 @@ describe('innityAdapterTest', () => {
expect(result[0].meta.advertiserDomains.length).to.equal(0);
expect(result[0].meta.advertiserDomains).to.deep.equal([]);
});
+
+ it('result with no bids', () => {
+ bidResponse.body = {};
+ const result = spec.interpretResponse(bidResponse, bidRequest);
+ expect(result).to.deep.equal([]);
+ });
});
});
diff --git a/test/spec/modules/insticatorBidAdapter_spec.js b/test/spec/modules/insticatorBidAdapter_spec.js
index e24bcb3b455..149983552f8 100644
--- a/test/spec/modules/insticatorBidAdapter_spec.js
+++ b/test/spec/modules/insticatorBidAdapter_spec.js
@@ -179,6 +179,143 @@ describe('InsticatorBidAdapter', function () {
}
})).to.be.false;
});
+
+ it('should return false if video plcmt is not a number', () => {
+ expect(spec.isBidRequestValid({
+ ...bidRequest,
+ ...{
+ mediaTypes: {
+ video: {
+ mimes: [
+ 'video/mp4',
+ 'video/mpeg',
+ ],
+ w: 250,
+ h: 300,
+ plcmt: 'NaN',
+ },
+ }
+ }
+ })).to.be.false;
+ });
+
+ it('should return true if playerSize is present instead of w and h', () => {
+ expect(spec.isBidRequestValid({
+ ...bidRequest,
+ ...{
+ mediaTypes: {
+ video: {
+ mimes: [
+ 'video/mp4',
+ 'video/mpeg',
+ ],
+ playerSize: [250, 300],
+ placement: 1,
+ },
+ }
+ }
+ })).to.be.true;
+ });
+
+ it('should return true if optional video fields are valid', () => {
+ expect(spec.isBidRequestValid({
+ ...bidRequest,
+ ...{
+ mediaTypes: {
+ video: {
+ mimes: [
+ 'video/mp4',
+ 'video/mpeg',
+ ],
+ playerSize: [250, 300],
+ placement: 1,
+ startdelay: 1,
+ skip: 1,
+ skipmin: 1,
+ skipafter: 1,
+ minduration: 1,
+ maxduration: 1,
+ api: [1, 2],
+ protocols: [2],
+ battr: [1, 2],
+ playbackmethod: [1, 2],
+ playbackend: 1,
+ delivery: [1, 2],
+ pos: 1,
+ },
+ }
+ }
+ })).to.be.true;
+ });
+
+ it('should return false if optional video fields are not valid', () => {
+ expect(spec.isBidRequestValid({
+ ...bidRequest,
+ ...{
+ mediaTypes: {
+ video: {
+ mimes: [
+ 'video/mp4',
+ 'video/mpeg',
+ ],
+ playerSize: [250, 300],
+ placement: 1,
+ startdelay: 'NaN',
+ },
+ }
+ }
+ })).to.be.false;
+ });
+
+ it('should return false if video min duration > max duration', () => {
+ expect(spec.isBidRequestValid({
+ ...bidRequest,
+ ...{
+ mediaTypes: {
+ video: {
+ mimes: [
+ 'video/mp4',
+ 'video/mpeg',
+ ],
+ playerSize: [250, 300],
+ placement: 1,
+ minduration: 5,
+ maxduration: 4,
+ },
+ }
+ }
+ })).to.be.false;
+ });
+
+ it('should return true when video bidder params override bidRequest video params', () => {
+ expect(spec.isBidRequestValid({
+ ...bidRequest,
+ ...{
+ mediaTypes: {
+ video: {
+ mimes: [
+ 'video/mp4',
+ 'video/mpeg',
+ ],
+ playerSize: [250, 300],
+ placement: 1,
+ },
+ }
+ },
+ params: {
+ ...bidRequest.params,
+ video: {
+ mimes: [
+ 'video/mp4',
+ 'video/mpeg',
+ 'video/x-flv',
+ 'video/webm',
+ ],
+ placement: 2,
+ },
+ }
+ })).to.be.true;
+ });
});
describe('buildRequests', function () {
@@ -355,6 +492,40 @@ describe('InsticatorBidAdapter', function () {
it('should return empty array if no valid requests are passed', function () {
expect(spec.buildRequests([], bidderRequest)).to.be.an('array').that.have.lengthOf(0);
});
+
+ it('should have bidder params override bidRequest mediatypes', function () {
+ const tempBiddRequest = {
+ ...bidRequest,
+ params: {
+ ...bidRequest.params,
+ video: {
+ mimes: [
+ 'video/mp4',
+ 'video/mpeg',
+ 'video/x-flv',
+ 'video/webm',
+ 'video/ogg',
+ ],
+ plcmt: 4,
+ w: 640,
+ h: 480,
+ }
+ }
+ }
+ const requests = spec.buildRequests([tempBiddRequest], bidderRequest);
+ const data = JSON.parse(requests[0].data);
+ expect(data.imp[0].video.mimes).to.deep.equal([
+ 'video/mp4',
+ 'video/mpeg',
+ 'video/x-flv',
+ 'video/webm',
+ 'video/ogg',
+ ])
+ expect(data.imp[0].video.placement).to.equal(2);
+ expect(data.imp[0].video.plcmt).to.equal(4);
+ expect(data.imp[0].video.w).to.equal(640);
+ expect(data.imp[0].video.h).to.equal(480);
+ });
});
describe('interpretResponse', function () {
@@ -570,4 +741,87 @@ describe('InsticatorBidAdapter', function () {
expect(spec.getUserSyncs({}, [response])).to.have.length(0);
})
});
+
+ describe('Response with video Instream', function () {
+ const bidRequestVid = {
+ method: 'POST',
+ url: 'https://ex.ingage.tech/v1/openrtb',
+ options: {
+ contentType: 'application/json',
+ withCredentials: true,
+ },
+ data: '',
+ bidderRequest: {
+ bidderRequestId: '22edbae2733bf6',
+ auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2',
+ timeout: 300,
+ bids: [
+ {
+ bidder: 'insticator',
+ params: {
+ adUnitId: '1a2b3c4d5e6f1a2b3c4d'
+ },
+ adUnitCode: 'adunit-code-1',
+ mediaTypes: {
+ video: {
+ mimes: [
+ 'video/mp4',
+ 'video/mpeg',
+ ],
+ playerSize: [[250, 300]],
+ placement: 2,
+ plcmt: 2,
+ }
+ },
+ bidId: 'bid1',
+ }
+ ]
+ }
+ };
+
+ const bidResponseVid = {
+ body: {
+ id: '22edbae2733bf6',
+ bidid: 'foo9876',
+ cur: 'USD',
+ seatbid: [
+ {
+ seat: 'some-dsp',
+ bid: [
+ {
+ ad: '
',
+ impid: 'bid1',
+ crid: 'crid1',
+ price: 0.5,
+ w: 300,
+ h: 250,
+ adm: '
',
+ exp: 60,
+ adomain: ['test1.com'],
+ ext: {
+ meta: {
+ test: 1
+ }
+ },
+ }
+ ],
+ },
+ ]
+ }
+ };
+ const bidRequestWithVideo = utils.deepClone(bidRequestVid);
+
+ it('should have related properties for video Instream', function() {
+ const serverResponseWithInstream = utils.deepClone(bidResponseVid);
+ serverResponseWithInstream.body.seatbid[0].bid[0].vastXml = '
';
+ serverResponseWithInstream.body.seatbid[0].bid[0].mediaType = 'video';
+ const bidResponse = spec.interpretResponse(serverResponseWithInstream, bidRequestWithVideo)[0];
+ expect(bidResponse).to.have.any.keys('mediaType', 'vastXml', 'vastUrl');
+ expect(bidResponse).to.have.property('mediaType', 'video');
+ expect(bidResponse.width).to.equal(300);
+ expect(bidResponse.height).to.equal(250);
+ expect(bidResponse).to.have.property('vastXml', '
');
+ expect(bidResponse.vastUrl).to.match(/^data:text\/xml;charset=utf-8;base64,[\w+/=]+$/)
+ });
+ })
});
diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js
index 7ee6b464996..056255c7738 100644
--- a/test/spec/modules/invibesBidAdapter_spec.js
+++ b/test/spec/modules/invibesBidAdapter_spec.js
@@ -44,6 +44,78 @@ describe('invibesBidAdapter:', function () {
}
];
+ let bidRequestsWithDuplicatedplacementId = [
+ {
+ bidId: 'b1',
+ bidder: BIDDER_CODE,
+ bidderRequestId: 'r1',
+ params: {
+ placementId: PLACEMENT_ID,
+ disableUserSyncs: false
+
+ },
+ adUnitCode: 'test-div1',
+ auctionId: 'a1',
+ sizes: [
+ [300, 250],
+ [400, 300],
+ [125, 125]
+ ],
+ transactionId: 't1'
+ }, {
+ bidId: 'b2',
+ bidder: BIDDER_CODE,
+ bidderRequestId: 'r2',
+ params: {
+ placementId: PLACEMENT_ID,
+ disableUserSyncs: false
+ },
+ adUnitCode: 'test-div2',
+ auctionId: 'a2',
+ sizes: [
+ [300, 250],
+ [400, 300]
+ ],
+ transactionId: 't2'
+ }
+ ];
+
+ let bidRequestsWithUniquePlacementId = [
+ {
+ bidId: 'b1',
+ bidder: BIDDER_CODE,
+ bidderRequestId: 'r1',
+ params: {
+ placementId: 'PLACEMENT_ID_1',
+ disableUserSyncs: false
+
+ },
+ adUnitCode: 'test-div1',
+ auctionId: 'a1',
+ sizes: [
+ [300, 250],
+ [400, 300],
+ [125, 125]
+ ],
+ transactionId: 't1'
+ }, {
+ bidId: 'b2',
+ bidder: BIDDER_CODE,
+ bidderRequestId: 'r2',
+ params: {
+ placementId: 'PLACEMENT_ID_2',
+ disableUserSyncs: false
+ },
+ adUnitCode: 'test-div2',
+ auctionId: 'a2',
+ sizes: [
+ [300, 250],
+ [400, 300]
+ ],
+ transactionId: 't2'
+ }
+ ];
+
let bidRequestsWithUserId = [
{
bidId: 'b1',
@@ -185,17 +257,44 @@ describe('invibesBidAdapter:', function () {
expect(request.data.preventPageViewEvent).to.be.false;
});
+ it('sends isPlacementRefresh as false when the placement ids are used for the first time', function () {
+ let request = spec.buildRequests(bidRequestsWithUniquePlacementId, bidderRequestWithPageInfo);
+ expect(request.data.isPlacementRefresh).to.be.false;
+ });
+
it('sends preventPageViewEvent as true on 2nd call', function () {
let request = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
expect(request.data.preventPageViewEvent).to.be.true;
});
+ it('sends isPlacementRefresh as true on multi requests on the same placement id', function () {
+ let request = spec.buildRequests(bidRequestsWithDuplicatedplacementId, bidderRequestWithPageInfo);
+ expect(request.data.isPlacementRefresh).to.be.true;
+ });
+
+ it('sends isInfiniteScrollPage as false initially', function () {
+ let request = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
+ expect(request.data.isInfiniteScrollPage).to.be.false;
+ });
+
+ it('sends isPlacementRefresh as true on multi requests multiple calls with the same placement id from second call', function () {
+ let request = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
+ expect(request.data.isInfiniteScrollPage).to.be.false;
+ let duplicatedRequest = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
+ expect(duplicatedRequest.data.isPlacementRefresh).to.be.true;
+ });
+
it('sends bid request to ENDPOINT via GET', function () {
const request = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
expect(request.url).to.equal(ENDPOINT);
expect(request.method).to.equal('GET');
});
+ it('generates a visitId of length 32', function () {
+ spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
+ expect(top.window.invibes.visitId.length).to.equal(32);
+ });
+
it('sends bid request to custom endpoint via GET', function () {
const request = spec.buildRequests([{
bidId: 'b1',
diff --git a/test/spec/modules/iqxBidAdapter_spec.js b/test/spec/modules/iqxBidAdapter_spec.js
new file mode 100644
index 00000000000..f5e680c8e0b
--- /dev/null
+++ b/test/spec/modules/iqxBidAdapter_spec.js
@@ -0,0 +1,455 @@
+import {expect} from 'chai';
+import {config} from 'src/config.js';
+import {spec, getBidFloor} from 'modules/iqxBidAdapter.js';
+import {deepClone} from 'src/utils';
+
+const ENDPOINT = 'https://pbjs.iqzonertb.live';
+
+const defaultRequest = {
+ adUnitCode: 'test',
+ bidId: '1',
+ requestId: 'qwerty',
+ ortb2: {
+ source: {
+ tid: 'auctionId'
+ }
+ },
+ ortb2Imp: {
+ ext: {
+ tid: 'tr1',
+ }
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250],
+ [300, 200]
+ ]
+ }
+ },
+ bidder: 'iqx',
+ params: {
+ env: 'iqx',
+ pid: '40',
+ ext: {}
+ },
+ bidRequestsCount: 1
+};
+
+const defaultRequestVideo = deepClone(defaultRequest);
+defaultRequestVideo.mediaTypes = {
+ video: {
+ playerSize: [640, 480],
+ context: 'instream',
+ skipppable: true
+ }
+};
+describe('iqxBidAdapter', () => {
+ describe('isBidRequestValid', function () {
+ it('should return false when request params is missing', function () {
+ const invalidRequest = deepClone(defaultRequest);
+ delete invalidRequest.params;
+ expect(spec.isBidRequestValid(invalidRequest)).to.equal(false);
+ });
+
+ it('should return false when required env param is missing', function () {
+ const invalidRequest = deepClone(defaultRequest);
+ delete invalidRequest.params.env;
+ expect(spec.isBidRequestValid(invalidRequest)).to.equal(false);
+ });
+
+ it('should return false when required pid param is missing', function () {
+ const invalidRequest = deepClone(defaultRequest);
+ delete invalidRequest.params.pid;
+ expect(spec.isBidRequestValid(invalidRequest)).to.equal(false);
+ });
+
+ it('should return false when video.playerSize is missing', function () {
+ const invalidRequest = deepClone(defaultRequestVideo);
+ delete invalidRequest.mediaTypes.video.playerSize;
+ expect(spec.isBidRequestValid(invalidRequest)).to.equal(false);
+ });
+
+ it('should return true when required params found', function () {
+ expect(spec.isBidRequestValid(defaultRequest)).to.equal(true);
+ });
+ });
+
+ describe('buildRequests', function () {
+ beforeEach(function () {
+ config.resetConfig();
+ });
+
+ it('should send request with correct structure', function () {
+ const request = spec.buildRequests([defaultRequest], {});
+ expect(request.method).to.equal('POST');
+ expect(request.url).to.equal(ENDPOINT + '/bid');
+ expect(request.options).to.have.property('contentType').and.to.equal('application/json');
+ expect(request).to.have.property('data');
+ });
+
+ it('should build basic request structure', function () {
+ const request = JSON.parse(spec.buildRequests([defaultRequest], {}).data)[0];
+ expect(request).to.have.property('bidId').and.to.equal(defaultRequest.bidId);
+ expect(request).to.have.property('auctionId').and.to.equal(defaultRequest.ortb2.source.tid);
+ expect(request).to.have.property('transactionId').and.to.equal(defaultRequest.ortb2Imp.ext.tid);
+ expect(request).to.have.property('tz').and.to.equal(new Date().getTimezoneOffset());
+ expect(request).to.have.property('bc').and.to.equal(1);
+ expect(request).to.have.property('floor').and.to.equal(null);
+ expect(request).to.have.property('banner').and.to.deep.equal({sizes: [[300, 250], [300, 200]]});
+ expect(request).to.have.property('gdprApplies').and.to.equal(0);
+ expect(request).to.have.property('consentString').and.to.equal('');
+ expect(request).to.have.property('userEids').and.to.deep.equal([]);
+ expect(request).to.have.property('usPrivacy').and.to.equal('');
+ expect(request).to.have.property('coppa').and.to.equal(0);
+ expect(request).to.have.property('sizes').and.to.deep.equal(['300x250', '300x200']);
+ expect(request).to.have.property('ext').and.to.deep.equal({});
+ expect(request).to.have.property('env').and.to.deep.equal({
+ env: 'iqx',
+ pid: '40'
+ });
+ expect(request).to.have.property('device').and.to.deep.equal({
+ ua: navigator.userAgent,
+ lang: navigator.language
+ });
+ });
+
+ it('should build request with schain', function () {
+ const schainRequest = deepClone(defaultRequest);
+ schainRequest.schain = {
+ validation: 'strict',
+ config: {
+ ver: '1.0'
+ }
+ };
+ const request = JSON.parse(spec.buildRequests([schainRequest], {}).data)[0];
+ expect(request).to.have.property('schain').and.to.deep.equal({
+ validation: 'strict',
+ config: {
+ ver: '1.0'
+ }
+ });
+ });
+
+ it('should build request with location', function () {
+ const bidderRequest = {
+ refererInfo: {
+ page: 'page',
+ location: 'location',
+ domain: 'domain',
+ ref: 'ref',
+ isAmp: false
+ }
+ };
+ const request = JSON.parse(spec.buildRequests([defaultRequest], bidderRequest).data)[0];
+ expect(request).to.have.property('location');
+ const location = request.location;
+ expect(location).to.have.property('page').and.to.equal('page');
+ expect(location).to.have.property('location').and.to.equal('location');
+ expect(location).to.have.property('domain').and.to.equal('domain');
+ expect(location).to.have.property('ref').and.to.equal('ref');
+ expect(location).to.have.property('isAmp').and.to.equal(false);
+ });
+
+ it('should build request with ortb2 info', function () {
+ const ortb2Request = deepClone(defaultRequest);
+ ortb2Request.ortb2 = {
+ site: {
+ name: 'name'
+ }
+ };
+ const request = JSON.parse(spec.buildRequests([ortb2Request], {}).data)[0];
+ expect(request).to.have.property('ortb2').and.to.deep.equal({
+ site: {
+ name: 'name'
+ }
+ });
+ });
+
+ it('should build request with ortb2Imp info', function () {
+ const ortb2ImpRequest = deepClone(defaultRequest);
+ ortb2ImpRequest.ortb2Imp = {
+ ext: {
+ data: {
+ pbadslot: 'home1',
+ adUnitSpecificAttribute: '1'
+ }
+ }
+ };
+ const request = JSON.parse(spec.buildRequests([ortb2ImpRequest], {}).data)[0];
+ expect(request).to.have.property('ortb2Imp').and.to.deep.equal({
+ ext: {
+ data: {
+ pbadslot: 'home1',
+ adUnitSpecificAttribute: '1'
+ }
+ }
+ });
+ });
+
+ it('should build request with valid bidfloor', function () {
+ const bfRequest = deepClone(defaultRequest);
+ bfRequest.getFloor = () => ({floor: 5, currency: 'USD'});
+ const request = JSON.parse(spec.buildRequests([bfRequest], {}).data)[0];
+ expect(request).to.have.property('floor').and.to.equal(5);
+ });
+
+ it('should build request with gdpr consent data if applies', function () {
+ const bidderRequest = {
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: 'qwerty'
+ }
+ };
+ const request = JSON.parse(spec.buildRequests([defaultRequest], bidderRequest).data)[0];
+ expect(request).to.have.property('gdprApplies').and.equals(1);
+ expect(request).to.have.property('consentString').and.equals('qwerty');
+ });
+
+ it('should build request with usp consent data if applies', function () {
+ const bidderRequest = {
+ uspConsent: '1YA-'
+ };
+ const request = JSON.parse(spec.buildRequests([defaultRequest], bidderRequest).data)[0];
+ expect(request).to.have.property('usPrivacy').and.equals('1YA-');
+ });
+
+ it('should build request with coppa 1', function () {
+ config.setConfig({
+ coppa: true
+ });
+ const request = JSON.parse(spec.buildRequests([defaultRequest], {}).data)[0];
+ expect(request).to.have.property('coppa').and.equals(1);
+ });
+
+ it('should build request with extended ids', function () {
+ const idRequest = deepClone(defaultRequest);
+ idRequest.userIdAsEids = [
+ {source: 'adserver.org', uids: [{id: 'TTD_ID_FROM_USER_ID_MODULE', atype: 1, ext: {rtiPartner: 'TDID'}}]},
+ {source: 'pubcid.org', uids: [{id: 'pubCommonId_FROM_USER_ID_MODULE', atype: 1}]}
+ ];
+ const request = JSON.parse(spec.buildRequests([idRequest], {}).data)[0];
+ expect(request).to.have.property('userEids').and.deep.equal(idRequest.userIdAsEids);
+ });
+
+ it('should build request with video', function () {
+ const request = JSON.parse(spec.buildRequests([defaultRequestVideo], {}).data)[0];
+ expect(request).to.have.property('video').and.to.deep.equal({
+ playerSize: [640, 480],
+ context: 'instream',
+ skipppable: true
+ });
+ expect(request).to.have.property('sizes').and.to.deep.equal(['640x480']);
+ });
+ });
+
+ describe('interpretResponse', function () {
+ it('should return empty bids', function () {
+ const serverResponse = {
+ body: {
+ data: null
+ }
+ };
+
+ const invalidResponse = spec.interpretResponse(serverResponse, {});
+ expect(invalidResponse).to.be.an('array').that.is.empty;
+ });
+
+ it('should interpret valid response', function () {
+ const serverResponse = {
+ body: {
+ data: [{
+ requestId: 'qwerty',
+ cpm: 1,
+ currency: 'USD',
+ width: 300,
+ height: 250,
+ ttl: 600,
+ meta: {
+ advertiserDomains: ['iqx']
+ },
+ ext: {
+ pixels: [
+ ['iframe', 'surl1'],
+ ['image', 'surl2'],
+ ]
+ }
+ }]
+ }
+ };
+
+ const validResponse = spec.interpretResponse(serverResponse, {bidderRequest: defaultRequest});
+ const bid = validResponse[0];
+ expect(validResponse).to.be.an('array').that.is.not.empty;
+ expect(bid.requestId).to.equal('qwerty');
+ expect(bid.cpm).to.equal(1);
+ expect(bid.currency).to.equal('USD');
+ expect(bid.width).to.equal(300);
+ expect(bid.height).to.equal(250);
+ expect(bid.ttl).to.equal(600);
+ expect(bid.meta).to.deep.equal({advertiserDomains: ['iqx']});
+ });
+
+ it('should interpret valid banner response', function () {
+ const serverResponse = {
+ body: {
+ data: [{
+ requestId: 'qwerty',
+ cpm: 1,
+ currency: 'USD',
+ width: 300,
+ height: 250,
+ ttl: 600,
+ mediaType: 'banner',
+ creativeId: 'xe-demo-banner',
+ ad: 'ad',
+ meta: {}
+ }]
+ }
+ };
+
+ const validResponseBanner = spec.interpretResponse(serverResponse, {bidderRequest: defaultRequest});
+ const bid = validResponseBanner[0];
+ expect(validResponseBanner).to.be.an('array').that.is.not.empty;
+ expect(bid.mediaType).to.equal('banner');
+ expect(bid.creativeId).to.equal('xe-demo-banner');
+ expect(bid.ad).to.equal('ad');
+ });
+
+ it('should interpret valid video response', function () {
+ const serverResponse = {
+ body: {
+ data: [{
+ requestId: 'qwerty',
+ cpm: 1,
+ currency: 'USD',
+ width: 600,
+ height: 480,
+ ttl: 600,
+ mediaType: 'video',
+ creativeId: 'xe-demo-video',
+ ad: 'vast-xml',
+ meta: {}
+ }]
+ }
+ };
+
+ const validResponseBanner = spec.interpretResponse(serverResponse, {bidderRequest: defaultRequestVideo});
+ const bid = validResponseBanner[0];
+ expect(validResponseBanner).to.be.an('array').that.is.not.empty;
+ expect(bid.mediaType).to.equal('video');
+ expect(bid.creativeId).to.equal('xe-demo-video');
+ expect(bid.ad).to.equal('vast-xml');
+ });
+ });
+
+ describe('getUserSyncs', function () {
+ it('shoukd handle no params', function () {
+ const opts = spec.getUserSyncs({}, []);
+ expect(opts).to.be.an('array').that.is.empty;
+ });
+
+ it('should return empty if sync is not allowed', function () {
+ const opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false});
+ expect(opts).to.be.an('array').that.is.empty;
+ });
+
+ it('should allow iframe sync', function () {
+ const opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [{
+ body: {
+ data: [{
+ requestId: 'qwerty',
+ ext: {
+ pixels: [
+ ['iframe', 'surl1?a=b'],
+ ['image', 'surl2?a=b'],
+ ]
+ }
+ }]
+ }
+ }]);
+ expect(opts.length).to.equal(1);
+ expect(opts[0].type).to.equal('iframe');
+ expect(opts[0].url).to.equal('surl1?a=b&us_privacy=&gdpr=0&gdpr_consent=');
+ });
+
+ it('should allow pixel sync', function () {
+ const opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [{
+ body: {
+ data: [{
+ requestId: 'qwerty',
+ ext: {
+ pixels: [
+ ['iframe', 'surl1?a=b'],
+ ['image', 'surl2?a=b'],
+ ]
+ }
+ }]
+ }
+ }]);
+ expect(opts.length).to.equal(1);
+ expect(opts[0].type).to.equal('image');
+ expect(opts[0].url).to.equal('surl2?a=b&us_privacy=&gdpr=0&gdpr_consent=');
+ });
+
+ it('should allow pixel sync and parse consent params', function () {
+ const opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [{
+ body: {
+ data: [{
+ requestId: 'qwerty',
+ ext: {
+ pixels: [
+ ['iframe', 'surl1?a=b'],
+ ['image', 'surl2?a=b'],
+ ]
+ }
+ }]
+ }
+ }], {
+ gdprApplies: 1,
+ consentString: '1YA-'
+ });
+ expect(opts.length).to.equal(1);
+ expect(opts[0].type).to.equal('image');
+ expect(opts[0].url).to.equal('surl2?a=b&us_privacy=&gdpr=1&gdpr_consent=1YA-');
+ });
+ });
+
+ describe('getBidFloor', function () {
+ it('should return null when getFloor is not a function', () => {
+ const bid = {getFloor: 2};
+ const result = getBidFloor(bid);
+ expect(result).to.be.null;
+ });
+
+ it('should return null when getFloor doesnt return an object', () => {
+ const bid = {getFloor: () => 2};
+ const result = getBidFloor(bid);
+ expect(result).to.be.null;
+ });
+
+ it('should return null when floor is not a number', () => {
+ const bid = {
+ getFloor: () => ({floor: 'string', currency: 'USD'})
+ };
+ const result = getBidFloor(bid);
+ expect(result).to.be.null;
+ });
+
+ it('should return null when currency is not USD', () => {
+ const bid = {
+ getFloor: () => ({floor: 5, currency: 'EUR'})
+ };
+ const result = getBidFloor(bid);
+ expect(result).to.be.null;
+ });
+
+ it('should return floor value when everything is correct', () => {
+ const bid = {
+ getFloor: () => ({floor: 5, currency: 'USD'})
+ };
+ const result = getBidFloor(bid);
+ expect(result).to.equal(5);
+ });
+ });
+})
diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js
index 500f2239e55..7655868ffc3 100644
--- a/test/spec/modules/ixBidAdapter_spec.js
+++ b/test/spec/modules/ixBidAdapter_spec.js
@@ -625,6 +625,45 @@ describe('IndexexchangeAdapter', function () {
]
};
+ const DEFAULT_BANNER_BID_RESPONSE_WITH_DSA = {
+ cur: 'USD',
+ id: '11a22b33c44d',
+ seatbid: [
+ {
+ bid: [
+ {
+ crid: '12345',
+ adomain: ['www.abc.com'],
+ adid: '14851455',
+ impid: '1a2b3c4d',
+ cid: '3051266',
+ price: 100,
+ w: 300,
+ h: 250,
+ id: '1',
+ ext: {
+ dspid: 50,
+ pricelevel: '_100',
+ advbrandid: 303325,
+ advbrand: 'OECTA',
+ dsa: {
+ behalf: 'Advertiser',
+ paid: 'Advertiser',
+ transparency: [{
+ domain: 'dsp1domain.com',
+ dsaparams: [1, 2]
+ }],
+ 'adrender': 1
+ }
+ },
+ adm: '
'
+ }
+ ],
+ seat: '3970'
+ }
+ ]
+ };
+
const DEFAULT_BANNER_BID_RESPONSE_WITHOUT_ADOMAIN = {
cur: 'USD',
id: '11a22b33c44d',
@@ -919,6 +958,23 @@ describe('IndexexchangeAdapter', function () {
const extractPayload = function (bidRequest) { return bidRequest.data }
+ const generateEid = function (numEid) {
+ const eids = [];
+
+ for (let i = 1; i <= numEid; i++) {
+ const newEid = {
+ source: `eid_source_${i}.com`,
+ uids: [{
+ id: `uid_id_${i}`,
+ }]
+ };
+
+ eids.push(newEid);
+ }
+
+ return eids;
+ }
+
describe('inherited functions', function () {
it('should exists and is a function', function () {
const adapter = newBidder(spec);
@@ -1485,6 +1541,17 @@ describe('IndexexchangeAdapter', function () {
describe('buildRequestsUserId', function () {
let validIdentityResponse;
let validUserIdPayload;
+ const serverResponse = {
+ body: {
+ ext: {
+ pbjs_allow_all_eids: {
+ test: {
+ activated: false
+ }
+ }
+ }
+ }
+ };
beforeEach(function () {
window.headertag = {};
@@ -1495,6 +1562,12 @@ describe('IndexexchangeAdapter', function () {
afterEach(function () {
delete window.headertag;
+ serverResponse.body.ext.features = {
+ pbjs_allow_all_eids: {
+ activated: false
+ }
+ };
+ validIdentityResponse = {}
});
it('IX adapter reads supported user modules from Prebid and adds it to Video', function () {
@@ -1506,6 +1579,91 @@ describe('IndexexchangeAdapter', function () {
expect(payload.user.eids).to.have.deep.members(DEFAULT_USERID_PAYLOAD);
});
+ it('IX adapter filters eids from prebid past the maximum eid limit', function () {
+ serverResponse.body.ext.features = {
+ pbjs_allow_all_eids: {
+ activated: true
+ }
+ };
+ FEATURE_TOGGLES.setFeatureToggles(serverResponse);
+ const cloneValidBid = utils.deepClone(DEFAULT_VIDEO_VALID_BID);
+ let eid_sent_from_prebid = generateEid(55);
+ cloneValidBid[0].userIdAsEids = utils.deepClone(eid_sent_from_prebid);
+ const request = spec.buildRequests(cloneValidBid, DEFAULT_OPTION)[0];
+ const payload = extractPayload(request);
+ expect(payload.user.eids).to.have.lengthOf(50);
+ let eid_accepted = eid_sent_from_prebid.slice(0, 50);
+ expect(payload.user.eids).to.have.deep.members(eid_accepted);
+ expect(payload.ext.ixdiag.eidLength).to.equal(55);
+ });
+
+ it('IX adapter filters eids from IXL past the maximum eid limit', function () {
+ validIdentityResponse = {
+ MerkleIp: {
+ responsePending: false,
+ data: {
+ source: 'merkle.com',
+ uids: [{
+ id: '1234-5678-9012-3456',
+ ext: {
+ keyID: '1234-5678',
+ enc: 1
+ }
+ }]
+ }
+ },
+ LiveIntentIp: {
+ responsePending: false,
+ data: {
+ source: 'liveintent.com',
+ uids: [{
+ id: '1234-5678-9012-3456',
+ ext: {
+ keyID: '1234-5678',
+ rtiPartner: 'LDID',
+ enc: 1
+ }
+ }]
+ }
+ }
+ };
+ serverResponse.body.ext.features = {
+ pbjs_allow_all_eids: {
+ activated: true
+ }
+ };
+ FEATURE_TOGGLES.setFeatureToggles(serverResponse);
+ const cloneValidBid = utils.deepClone(DEFAULT_VIDEO_VALID_BID);
+ let eid_sent_from_prebid = generateEid(49);
+ cloneValidBid[0].userIdAsEids = utils.deepClone(eid_sent_from_prebid);
+ const request = spec.buildRequests(cloneValidBid, DEFAULT_OPTION)[0];
+ const payload = extractPayload(request);
+ expect(payload.user.eids).to.have.lengthOf(50);
+ eid_sent_from_prebid.push({
+ source: 'merkle.com',
+ uids: [{
+ id: '1234-5678-9012-3456',
+ ext: {
+ keyID: '1234-5678',
+ enc: 1
+ }
+ }]
+ })
+ expect(payload.user.eids).to.have.deep.members(eid_sent_from_prebid);
+ expect(payload.ext.ixdiag.eidLength).to.equal(49);
+ });
+
+ it('All incoming eids are from unsupported source with feature toggle off', function () {
+ FEATURE_TOGGLES.setFeatureToggles(serverResponse);
+ const cloneValidBid = utils.deepClone(DEFAULT_VIDEO_VALID_BID);
+ let eid_sent_from_prebid = generateEid(20);
+ cloneValidBid[0].userIdAsEids = utils.deepClone(eid_sent_from_prebid);
+ const request = spec.buildRequests(cloneValidBid, DEFAULT_OPTION)[0];
+ const payload = extractPayload(request);
+ expect(payload.user.eids).to.be.undefined
+ expect(payload.ext.ixdiag.eidLength).to.equal(20);
+ });
+
it('We continue to send in IXL identity info and Prebid takes precedence over IXL', function () {
validIdentityResponse = {
AdserverOrgIp: {
@@ -1784,6 +1942,72 @@ describe('IndexexchangeAdapter', function () {
expect(r.user.testProperty).to.be.undefined;
});
+ it('should set dsa field when defined', function () {
+ const dsa = {
+ dsarequired: 3,
+ pubrender: 0,
+ datatopub: 2,
+ transparency: [{
+ domain: 'domain.com',
+ dsaparams: [1]
+ }]
+ }
+ const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: {
+ ext: {
+ dsa: deepClone(dsa)
+ }
+ }
+ }})[0];
+ const r = extractPayload(request);
+
+ expect(r.regs.ext.dsa.dsarequired).to.equal(dsa.dsarequired);
+ expect(r.regs.ext.dsa.pubrender).to.equal(dsa.pubrender);
+ expect(r.regs.ext.dsa.datatopub).to.equal(dsa.datatopub);
+ expect(r.regs.ext.dsa.transparency).to.be.an('array');
+ expect(r.regs.ext.dsa.transparency).to.have.deep.members(dsa.transparency);
+ });
+ it('should not set dsa fields when fields arent appropriately defined', function () {
+ const dsa = {
+ dsarequired: '3',
+ pubrender: '0',
+ datatopub: '2',
+ transparency: 20
+ }
+ const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: {
+ ext: {
+ dsa: deepClone(dsa)
+ }
+ }
+ }})[0];
+ const r = extractPayload(request);
+
+ expect(r.regs).to.be.undefined;
+ });
+ it('should not set dsa transparency when fields arent appropriately defined', function () {
+ const dsa = {
+ transparency: [{
+ domain: 3,
+ dsaparams: [1]
+ },
+ {
+ domain: 'domain.com',
+ dsaparams: 'params'
+ },
+ {
+ domain: 'domain.com',
+ dsaparams: ['1']
+ }]
+ }
+ const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: {
+ ext: {
+ dsa: deepClone(dsa)
+ }
+ }
+ }})[0];
+ const r = extractPayload(request);
+
+ expect(r.regs).to.be.undefined;
+ });
it('should set gpp and gpp_sid field when defined', function () {
const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: {gpp: 'gpp', gpp_sid: [1]}} })[0];
const r = extractPayload(request);
@@ -1792,7 +2016,7 @@ describe('IndexexchangeAdapter', function () {
expect(r.regs.gpp_sid).to.be.an('array');
expect(r.regs.gpp_sid).to.include(1);
});
- it('should not set gpp and gpp_sid field when not defined', function () {
+ it('should not set gpp, gpp_sid and dsa field when not defined', function () {
const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: {}} })[0];
const r = extractPayload(request);
@@ -3410,6 +3634,40 @@ describe('IndexexchangeAdapter', function () {
expect(result[0]).to.deep.equal(expectedParse[0]);
});
+ it('should get correct bid response for banner ad with dsa signals', function () {
+ const expectedParse = [
+ {
+ requestId: '1a2b3c4d',
+ cpm: 1,
+ creativeId: '12345',
+ width: 300,
+ height: 250,
+ mediaType: 'banner',
+ ad: '
',
+ currency: 'USD',
+ ttl: 300,
+ netRevenue: true,
+ meta: {
+ networkId: 50,
+ brandId: 303325,
+ brandName: 'OECTA',
+ advertiserDomains: ['www.abc.com'],
+ dsa: {
+ behalf: 'Advertiser',
+ paid: 'Advertiser',
+ transparency: [{
+ domain: 'dsp1domain.com',
+ dsaparams: [1, 2]
+ }],
+ 'adrender': 1
+ }
+ }
+ }
+ ];
+ const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE_WITH_DSA }, bannerBidderRequest);
+ expect(result[0]).to.deep.equal(expectedParse[0]);
+ });
+
it('should get correct bid response for banner ad with missing adomain', function () {
const expectedParse = [
{
diff --git a/test/spec/modules/liveIntentIdMinimalSystem_spec.js b/test/spec/modules/liveIntentIdMinimalSystem_spec.js
index ed78d8f6e40..ad21d7b6763 100644
--- a/test/spec/modules/liveIntentIdMinimalSystem_spec.js
+++ b/test/spec/modules/liveIntentIdMinimalSystem_spec.js
@@ -73,7 +73,7 @@ describe('LiveIntentMinimalId', function() {
expect(callBackSpy.calledOnce).to.be.true;
});
- it('should call the Identity Exchange endpoint with the privided distributorId', function() {
+ it('should call the Identity Exchange endpoint with the provided distributorId', function() {
getCookieStub.returns(null);
let callBackSpy = sinon.spy();
let submoduleCallback = liveIntentIdSubmodule.getId({ params: { fireEventDelay: 1, distributorId: 'did-1111' } }).callback;
@@ -87,7 +87,7 @@ describe('LiveIntentMinimalId', function() {
expect(callBackSpy.calledOnceWith({})).to.be.true;
});
- it('should call the Identity Exchange endpoint without the privided distributorId when appId is provided', function() {
+ it('should call the Identity Exchange endpoint without the provided distributorId when appId is provided', function() {
getCookieStub.returns(null);
let callBackSpy = sinon.spy();
let submoduleCallback = liveIntentIdSubmodule.getId({ params: { fireEventDelay: 1, distributorId: 'did-1111', liCollectConfig: { appId: 'a-0001' } } }).callback;
@@ -261,6 +261,11 @@ describe('LiveIntentMinimalId', function() {
expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'medianet': 'bar'}, 'medianet': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
});
+ it('should decode a sovrn id to a seperate object when present', function() {
+ const result = liveIntentIdSubmodule.decode({ nonId: 'foo', sovrn: 'bar' });
+ expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'sovrn': 'bar'}, 'sovrn': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
+ });
+
it('should decode a magnite id to a seperate object when present', function() {
const result = liveIntentIdSubmodule.decode({ nonId: 'foo', magnite: 'bar' });
expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'magnite': 'bar'}, 'magnite': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
diff --git a/test/spec/modules/liveIntentIdSystem_spec.js b/test/spec/modules/liveIntentIdSystem_spec.js
index 9f57a5aa405..3af598c5d4e 100644
--- a/test/spec/modules/liveIntentIdSystem_spec.js
+++ b/test/spec/modules/liveIntentIdSystem_spec.js
@@ -94,6 +94,16 @@ describe('LiveIntentId', function() {
}, 200);
});
+ it('should initialize LiveConnect and forward the prebid version when decode and emit an event', function(done) {
+ liveIntentIdSubmodule.decode({}, { params: {
+ ...defaultConfigParams
+ }});
+ setTimeout(() => {
+ expect(server.requests[0].url).to.contain('tv=$prebid.version$')
+ done();
+ }, 200);
+ });
+
it('should initialize LiveConnect with the config params when decode and emit an event', function (done) {
liveIntentIdSubmodule.decode({}, { params: {
...defaultConfigParams.params,
@@ -186,7 +196,7 @@ describe('LiveIntentId', function() {
let submoduleCallback = liveIntentIdSubmodule.getId({ params: {...defaultConfigParams.params, ...{'url': 'https://dummy.liveintent.com/idex'}} }).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq('https://dummy.liveintent.com/idex/prebid/89899?resolve=nonId');
+ expect(request.url).to.be.eq('https://dummy.liveintent.com/idex/prebid/89899?cd=.localhost&resolve=nonId');
request.respond(
204,
responseHeader
@@ -194,13 +204,13 @@ describe('LiveIntentId', function() {
expect(callBackSpy.calledOnceWith({})).to.be.true;
});
- it('should call the Identity Exchange endpoint with the privided distributorId', function() {
+ it('should call the Identity Exchange endpoint with the provided distributorId', function() {
getCookieStub.returns(null);
let callBackSpy = sinon.spy();
let submoduleCallback = liveIntentIdSubmodule.getId({ params: { fireEventDelay: 1, distributorId: 'did-1111' } }).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq('https://idx.liadm.com/idex/did-1111/any?did=did-1111&resolve=nonId');
+ expect(request.url).to.be.eq('https://idx.liadm.com/idex/did-1111/any?did=did-1111&cd=.localhost&resolve=nonId');
request.respond(
204,
responseHeader
@@ -208,13 +218,13 @@ describe('LiveIntentId', function() {
expect(callBackSpy.calledOnceWith({})).to.be.true;
});
- it('should call the Identity Exchange endpoint without the privided distributorId when appId is provided', function() {
+ it('should call the Identity Exchange endpoint without the provided distributorId when appId is provided', function() {
getCookieStub.returns(null);
let callBackSpy = sinon.spy();
let submoduleCallback = liveIntentIdSubmodule.getId({ params: { fireEventDelay: 1, distributorId: 'did-1111', liCollectConfig: { appId: 'a-0001' } } }).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/any?resolve=nonId');
+ expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/any?cd=.localhost&resolve=nonId');
request.respond(
204,
responseHeader
@@ -234,7 +244,7 @@ describe('LiveIntentId', function() {
} }).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq('https://dummy.liveintent.com/idex/rubicon/89899?resolve=nonId');
+ expect(request.url).to.be.eq('https://dummy.liveintent.com/idex/rubicon/89899?cd=.localhost&resolve=nonId');
request.respond(
200,
responseHeader,
@@ -249,7 +259,7 @@ describe('LiveIntentId', function() {
let submoduleCallback = liveIntentIdSubmodule.getId(defaultConfigParams).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/89899?resolve=nonId');
+ expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/89899?cd=.localhost&resolve=nonId');
request.respond(
200,
responseHeader,
@@ -264,7 +274,7 @@ describe('LiveIntentId', function() {
let submoduleCallback = liveIntentIdSubmodule.getId(defaultConfigParams).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/89899?resolve=nonId');
+ expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/89899?cd=.localhost&resolve=nonId');
request.respond(
503,
responseHeader,
@@ -281,7 +291,7 @@ describe('LiveIntentId', function() {
let submoduleCallback = liveIntentIdSubmodule.getId(defaultConfigParams).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?duid=${oldCookie}&resolve=nonId`);
+ expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?duid=${oldCookie}&cd=.localhost&resolve=nonId`);
request.respond(
200,
responseHeader,
@@ -304,7 +314,7 @@ describe('LiveIntentId', function() {
let submoduleCallback = liveIntentIdSubmodule.getId(configParams).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?duid=${oldCookie}&_thirdPC=third-pc&resolve=nonId`);
+ expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?duid=${oldCookie}&cd=.localhost&_thirdPC=third-pc&resolve=nonId`);
request.respond(
200,
responseHeader,
@@ -326,7 +336,7 @@ describe('LiveIntentId', function() {
let submoduleCallback = liveIntentIdSubmodule.getId(configParams).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/89899?_thirdPC=%7B%22key%22%3A%22value%22%7D&resolve=nonId');
+ expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/89899?cd=.localhost&_thirdPC=%7B%22key%22%3A%22value%22%7D&resolve=nonId');
request.respond(
200,
responseHeader,
@@ -359,7 +369,7 @@ describe('LiveIntentId', function() {
} }).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?resolve=nonId&resolve=foo`);
+ expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?cd=.localhost&resolve=nonId&resolve=foo`);
request.respond(
200,
responseHeader,
@@ -368,7 +378,7 @@ describe('LiveIntentId', function() {
expect(callBackSpy.calledOnce).to.be.true;
});
- it('should decode a uid2 to a seperate object when present', function() {
+ it('should decode a uid2 to a separate object when present', function() {
const result = liveIntentIdSubmodule.decode({ nonId: 'foo', uid2: 'bar' });
expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'uid2': 'bar'}, 'uid2': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
});
@@ -378,32 +388,37 @@ describe('LiveIntentId', function() {
expect(result).to.eql({'uid2': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
});
- it('should decode a bidswitch id to a seperate object when present', function() {
+ it('should decode a bidswitch id to a separate object when present', function() {
const result = liveIntentIdSubmodule.decode({ nonId: 'foo', bidswitch: 'bar' });
expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'bidswitch': 'bar'}, 'bidswitch': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
});
- it('should decode a medianet id to a seperate object when present', function() {
+ it('should decode a medianet id to a separate object when present', function() {
const result = liveIntentIdSubmodule.decode({ nonId: 'foo', medianet: 'bar' });
expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'medianet': 'bar'}, 'medianet': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
});
- it('should decode a magnite id to a seperate object when present', function() {
+ it('should decode a sovrn id to a separate object when present', function() {
+ const result = liveIntentIdSubmodule.decode({ nonId: 'foo', sovrn: 'bar' });
+ expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'sovrn': 'bar'}, 'sovrn': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
+ });
+
+ it('should decode a magnite id to a separate object when present', function() {
const result = liveIntentIdSubmodule.decode({ nonId: 'foo', magnite: 'bar' });
expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'magnite': 'bar'}, 'magnite': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
});
- it('should decode an index id to a seperate object when present', function() {
+ it('should decode an index id to a separate object when present', function() {
const result = liveIntentIdSubmodule.decode({ nonId: 'foo', index: 'bar' });
expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'index': 'bar'}, 'index': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
});
- it('should decode an openx id to a seperate object when present', function () {
+ it('should decode an openx id to a separate object when present', function () {
const result = liveIntentIdSubmodule.decode({ nonId: 'foo', openx: 'bar' });
expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'openx': 'bar'}, 'openx': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
});
- it('should decode an pubmatic id to a seperate object when present', function() {
+ it('should decode an pubmatic id to a separate object when present', function() {
const result = liveIntentIdSubmodule.decode({ nonId: 'foo', pubmatic: 'bar' });
expect(result).to.eql({'lipb': {'lipbid': 'foo', 'nonId': 'foo', 'pubmatic': 'bar'}, 'pubmatic': {'id': 'bar', 'ext': {'provider': 'liveintent.com'}}});
});
@@ -416,7 +431,7 @@ describe('LiveIntentId', function() {
} }).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?resolve=uid2`);
+ expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?cd=.localhost&resolve=uid2`);
request.respond(
200,
responseHeader,
diff --git a/test/spec/modules/livewrappedBidAdapter_spec.js b/test/spec/modules/livewrappedBidAdapter_spec.js
index 52eaf8d7d76..5ab00859d81 100644
--- a/test/spec/modules/livewrappedBidAdapter_spec.js
+++ b/test/spec/modules/livewrappedBidAdapter_spec.js
@@ -38,10 +38,9 @@ describe('Livewrapped adapter tests', function () {
auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C',
ortb2Imp: {
ext: {
- tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
}
},
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
}
],
start: 1472239426002,
@@ -120,8 +119,49 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
- formats: [{width: 980, height: 240}, {width: 980, height: 120}]
+ formats: [{width: 980, height: 240}, {width: 980, height: 120}],
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ }
+ }]
+ };
+
+ expect(data).to.deep.equal(expectedQuery);
+ });
+
+ it('should send ortb2Imp', function() {
+ sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
+ sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);
+ let ortb2ImpRequest = clone(bidderRequest);
+ ortb2ImpRequest.bids[0].ortb2Imp.ext.data = {key: 'value'};
+ let result = spec.buildRequests(ortb2ImpRequest.bids, ortb2ImpRequest);
+ let data = JSON.parse(result.data);
+
+ expect(result.url).to.equal('https://lwadm.com/ad');
+
+ let expectedQuery = {
+ auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C',
+ publisherId: '26947112-2289-405D-88C1-A7340C57E63E',
+ userId: 'user id',
+ url: 'https://www.domain.com',
+ seats: {'dsp': ['seat 1']},
+ version: '1.4',
+ width: 100,
+ height: 100,
+ cookieSupport: true,
+ adRequests: [{
+ adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
+ callerAdUnitId: 'panorama_d_1',
+ bidId: '2ffb201a808da7',
+ formats: [{width: 980, height: 240}, {width: 980, height: 120}],
+ rtbData: {
+ ext: {
+ data: {key: 'value'},
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ }
}]
};
@@ -157,12 +197,20 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}, {
callerAdUnitId: 'box_d_1',
bidId: '3ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 300, height: 250}]
}]
};
@@ -194,7 +242,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'caller id 1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -225,7 +277,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -256,7 +312,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -289,7 +349,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -322,7 +386,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -352,7 +420,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}],
options: {keyvalues: [{key: 'key', value: 'value'}]}
}]
@@ -384,7 +456,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -414,7 +490,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}],
native: {'nativedata': 'content parsed serverside only'}
}]
@@ -445,7 +525,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}],
native: {'nativedata': 'content parsed serverside only'},
banner: true
@@ -477,7 +561,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}],
video: {'videodata': 'content parsed serverside only'}
}]
@@ -525,7 +613,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -555,7 +647,11 @@ describe('Livewrapped adapter tests', function () {
adRequests: [{
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 728, height: 90}]
}]
};
@@ -592,7 +688,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -627,7 +727,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -660,7 +764,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -700,7 +808,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -730,7 +842,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -760,7 +876,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -810,7 +930,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -842,7 +966,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -876,7 +1004,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -910,7 +1042,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -946,7 +1082,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -982,7 +1122,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -1018,7 +1162,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};
@@ -1063,7 +1211,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}],
flr: 10
}]
@@ -1101,7 +1253,11 @@ describe('Livewrapped adapter tests', function () {
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
- transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
+ rtbData: {
+ ext: {
+ tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D'
+ },
+ },
formats: [{width: 980, height: 240}, {width: 980, height: 120}],
flr: 10
}]
diff --git a/test/spec/modules/mediagoBidAdapter_spec.js b/test/spec/modules/mediagoBidAdapter_spec.js
index 5eb362893e3..6e58217b3d3 100644
--- a/test/spec/modules/mediagoBidAdapter_spec.js
+++ b/test/spec/modules/mediagoBidAdapter_spec.js
@@ -1,5 +1,17 @@
import { expect } from 'chai';
-import { spec } from 'modules/mediagoBidAdapter.js';
+import {
+ spec,
+ getPmgUID,
+ storage,
+ getPageTitle,
+ getPageDescription,
+ getPageKeywords,
+ getConnectionDownLink,
+ THIRD_PARTY_COOKIE_ORIGIN,
+ COOKIE_KEY_MGUID,
+ getCurrentTimeToUTCString
+} from 'modules/mediagoBidAdapter.js';
+import * as utils from 'src/utils.js';
describe('mediago:BidAdapterTests', function () {
let bidRequestData = {
@@ -23,29 +35,37 @@ describe('mediago:BidAdapterTests', function () {
tid: 'tid_01',
data: {
browsi: {
- browsiViewability: 'NA',
+ browsiViewability: 'NA'
},
adserver: {
name: 'adserver_name',
- adslot: 'adslot_name',
+ adslot: 'adslot_name'
},
- },
- },
- },
+ pbadslot: '/12345/my-gpt-tag-0'
+ }
+ }
+ }
},
mediaTypes: {
banner: {
sizes: [[300, 250]],
- pos: 'left',
- },
+ pos: 'left'
+ }
},
ortb2: {
- user: {
- ext: {
- data: {
- },
+ site: {
+ cat: ['IAB2'],
+ keywords: 'power tools, drills, tools=industrial',
+ content: {
+ keywords: 'video, source=streaming'
},
+
},
+ user: {
+ ext: {
+ data: {}
+ }
+ }
},
adUnitCode: 'regular_iframe',
transactionId: '7b26fdae-96e6-4c35-a18b-218dda11397d',
@@ -56,9 +76,83 @@ describe('mediago:BidAdapterTests', function () {
src: 'client',
bidRequestsCount: 1,
bidderRequestsCount: 1,
- bidderWinsCount: 0,
- },
+ bidderWinsCount: 0
+ }
],
+ gdprConsent: {
+ consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==',
+ gdprApplies: true,
+ apiVersion: 2,
+ vendorData: {
+ purpose: {
+ consents: {
+ 1: false
+ }
+ }
+ }
+ },
+ userId: {
+ tdid: 'sample-userid',
+ uid2: { id: 'sample-uid2-value' },
+ criteoId: 'sample-criteo-userid',
+ netId: 'sample-netId-userid',
+ idl_env: 'sample-idl-userid',
+ pubProvidedId: [
+ {
+ source: 'puburl.com',
+ uids: [
+ {
+ id: 'pubid2',
+ atype: 1,
+ ext: {
+ stype: 'ppuid'
+ }
+ }
+ ]
+ },
+ {
+ source: 'puburl2.com',
+ uids: [
+ {
+ id: 'pubid2'
+ },
+ {
+ id: 'pubid2-123'
+ }
+ ]
+ }
+ ]
+ },
+ userIdAsEids: [
+ {
+ source: 'adserver.org',
+ uids: [{ id: 'sample-userid' }]
+ },
+ {
+ source: 'criteo.com',
+ uids: [{ id: 'sample-criteo-userid' }]
+ },
+ {
+ source: 'netid.de',
+ uids: [{ id: 'sample-netId-userid' }]
+ },
+ {
+ source: 'liveramp.com',
+ uids: [{ id: 'sample-idl-userid' }]
+ },
+ {
+ source: 'uidapi.com',
+ uids: [{ id: 'sample-uid2-value' }]
+ },
+ {
+ source: 'puburl.com',
+ uids: [{ id: 'pubid1' }]
+ },
+ {
+ source: 'puburl2.com',
+ uids: [{ id: 'pubid2' }, { id: 'pubid2-123' }]
+ }
+ ]
};
let request = [];
@@ -67,8 +161,8 @@ describe('mediago:BidAdapterTests', function () {
spec.isBidRequestValid({
bidder: 'mediago',
params: {
- token: ['85a6b01e41ac36d49744fad726e3655d'],
- },
+ token: ['85a6b01e41ac36d49744fad726e3655d']
+ }
})
).to.equal(true);
});
@@ -79,11 +173,54 @@ describe('mediago:BidAdapterTests', function () {
expect(req_data.imp).to.have.lengthOf(1);
});
+ describe('mediago: buildRequests', function() {
+ describe('getPmgUID function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+ sandbox.stub(storage, 'getCookie');
+ sandbox.stub(storage, 'setCookie');
+ sandbox.stub(utils, 'generateUUID').returns('new-uuid');
+ sandbox.stub(storage, 'cookiesAreEnabled');
+ })
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should generate new UUID and set cookie if not exists', () => {
+ storage.cookiesAreEnabled.callsFake(() => true);
+ storage.getCookie.callsFake(() => null);
+ const uid = getPmgUID();
+ expect(uid).to.equal('new-uuid');
+ expect(storage.setCookie.calledOnce).to.be.true;
+ });
+
+ it('should return existing UUID from cookie', () => {
+ storage.cookiesAreEnabled.callsFake(() => true);
+ storage.getCookie.callsFake(() => 'existing-uuid');
+ const uid = getPmgUID();
+ expect(uid).to.equal('existing-uuid');
+ expect(storage.setCookie.called).to.be.false;
+ });
+
+ it('should not set new UUID when cookies are not enabled', () => {
+ storage.cookiesAreEnabled.callsFake(() => false);
+ storage.getCookie.callsFake(() => null);
+ getPmgUID();
+ expect(storage.setCookie.calledOnce).to.be.false;
+ });
+ })
+ });
+
it('mediago:validate_response_params', function () {
- let adm = "
";
+ let adm =
+ '
';
let temp = '%3Cscr';
temp += 'ipt%3E';
- temp += '!function()%7B%22use%20strict%22%3Bfunction%20f(t)%7Breturn(f%3D%22function%22%3D%3Dtypeof%20Symbol%26%26%22symbol%22%3D%3Dtypeof%20Symbol.iterator%3Ffunction(t)%7Breturn%20typeof%20t%7D%3Afunction(t)%7Breturn%20t%26%26%22function%22%3D%3Dtypeof%20Symbol%26%26t.constructor%3D%3D%3DSymbol%26%26t!%3D%3DSymbol.prototype%3F%22symbol%22%3Atypeof%20t%7D)(t)%7Dfunction%20l(t)%7Bvar%20e%3D0%3Carguments.length%26%26void%200!%3D%3Dt%3Ft%3A%7B%7D%3Btry%7Be.random_t%3D(new%20Date).getTime()%2Cg(function(t)%7Bvar%20e%3D1%3Carguments.length%26%26void%200!%3D%3Darguments%5B1%5D%3Farguments%5B1%5D%3A%22%22%3Bif(%22object%22!%3D%3Df(t))return%20e%3Bvar%20n%3Dfunction(t)%7Bfor(var%20e%2Cn%3D%5B%5D%2Co%3D0%2Ci%3DObject.keys(t)%3Bo%3Ci.length%3Bo%2B%2B)e%3Di%5Bo%5D%2Cn.push(%22%22.concat(e%2C%22%3D%22).concat(t%5Be%5D))%3Breturn%20n%7D(t).join(%22%26%22)%2Co%3De.indexOf(%22%23%22)%2Ci%3De%2Ct%3D%22%22%3Breturn-1!%3D%3Do%26%26(i%3De.slice(0%2Co)%2Ct%3De.slice(o))%2Cn%26%26(i%26%26-1!%3D%3Di.indexOf(%22%3F%22)%3Fi%2B%3D%22%26%22%2Bn%3Ai%2B%3D%22%3F%22%2Bn)%2Ci%2Bt%7D(e%2C%22https%3A%2F%2Ftrace.mediago.io%2Fapi%2Flog%2Ftrack%22))%7Dcatch(t)%7B%7D%7Dfunction%20g(t%2Ce%2Cn)%7B(t%3Dt%3Ft.split(%22%3B%3B%3B%22)%3A%5B%5D).map(function(t)%7Btry%7B0%3C%3Dt.indexOf(%22%2Fapi%2Fbidder%2Ftrack%22)%26%26n%26%26(t%2B%3D%22%26inIframe%3D%22.concat(!(!self.frameElement%7C%7C%22IFRAME%22!%3Dself.frameElement.tagName)%7C%7Cwindow.frames.length!%3Dparent.frames.length%7C%7Cself!%3Dtop)%2Ct%2B%3D%22%26pos_x%3D%22.concat(n.left%2C%22%26pos_y%3D%22).concat(n.top%2C%22%26page_w%3D%22).concat(n.page_width%2C%22%26page_h%3D%22).concat(n.page_height))%7Dcatch(t)%7Bl(%7Btn%3As%2Cwinloss%3A1%2Cfe%3A2%2Cpos_err_c%3A1002%2Cpos_err_m%3At.toString()%7D)%7Dvar%20e%3Dnew%20Image%3Be.src%3Dt%2Ce.style.display%3D%22none%22%2Ce.style.visibility%3D%22hidden%22%2Ce.width%3D0%2Ce.height%3D0%2Cdocument.body.appendChild(e)%7D)%7Dvar%20d%3D%5B%22https%3A%2F%2Ftrace.mediago.io%2Fapi%2Fbidder%2Ftrack%3Ftn%3D39934c2bda4debbe4c680be1dd02f5d3%26price%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26evt%3D101%26rid%3D6e28cfaf115a354ea1ad8e1304d6d7b8%26campaignid%3D1339145%26impid%3D44-300x250-1%26offerid%3D24054386%26test%3D0%26time%3D1660789795%26cp%3DjZDh1xu6_QqJLlKVtCkiHIP_TER6gL9jeTrlHCBoxOM%26acid%3D599%26trackingid%3D99afea272c2b0e8626489674ddb7a0bb%26uid%3Da865b9ae-fa9e-4c09-8204-2db99ac7c8f7%26bm%3D2%26la%3Den%26cn%3Dus%26cid%3D3998296%26info%3DSi3oM-qfCbw2iZRYs01BkUWyH6c5CQWHrA8CQLE0VHcXAcf4ljY9dyLzQ4vAlTWd6-j_ou4ySor3e70Ll7wlKiiauQKaUkZqNoTizHm73C4FK8DYJSTP3VkhJV8RzrYk%26sid%3D128__110__1__12__28__38__163__96__58__24__47__99%26sp%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26scp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26acu%3DUSD%26scu%3DUSD%26sgcp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26gprice%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26gcp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26ah%3D%26de%3Dwjh.popin.cc%26iv%3D0%22%2C%22%24%7BITRACKER2%7D%22%2C%22%24%7BITRACKER3%7D%22%2C%22%24%7BITRACKER4%7D%22%2C%22%24%7BITRACKER5%7D%22%2C%22%24%7BITRACKER6%7D%22%5D%2Cp%3D%5B%22https%3A%2F%2Ftrace.mediago.io%2Fapi%2Fbidder%2Ftrack%3Ftn%3D39934c2bda4debbe4c680be1dd02f5d3%26price%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26evt%3D104%26rid%3D6e28cfaf115a354ea1ad8e1304d6d7b8%26campaignid%3D1339145%26impid%3D44-300x250-1%26offerid%3D24054386%26test%3D0%26time%3D1660789795%26cp%3DjZDh1xu6_QqJLlKVtCkiHIP_TER6gL9jeTrlHCBoxOM%26acid%3D599%26trackingid%3D99afea272c2b0e8626489674ddb7a0bb%26uid%3Da865b9ae-fa9e-4c09-8204-2db99ac7c8f7%26sid%3D128__110__1__12__28__38__163__96__58__24__47__99%26format%3D%26crid%3Dff32b6f9b3bbc45c00b78b6674a2952e%26bm%3D2%26la%3Den%26cn%3Dus%26cid%3D3998296%26info%3DSi3oM-qfCbw2iZRYs01BkUWyH6c5CQWHrA8CQLE0VHcXAcf4ljY9dyLzQ4vAlTWd6-j_ou4ySor3e70Ll7wlKiiauQKaUkZqNoTizHm73C4FK8DYJSTP3VkhJV8RzrYk%26sp%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26scp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26acu%3DUSD%26scu%3DUSD%26sgcp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26gprice%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26gcp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26ah%3D%26de%3Dwjh.popin.cc%26iv%3D0%22%2C%22%24%7BVTRACKER2%7D%22%2C%22%24%7BVTRACKER3%7D%22%2C%22%24%7BVTRACKER4%7D%22%2C%22%24%7BVTRACKER5%7D%22%2C%22%24%7BVTRACKER6%7D%22%5D%2Cs%3D%22f9f2b1ef23fe2759c2cad0953029a94b%22%2Cn%3Ddocument.getElementById(%22mgcontainer-99afea272c2b0e8626489674ddb7a0bb%22)%3Bn%26%26function()%7Bvar%20a%3Dn.getElementsByClassName(%22mediago-placement-track%22)%3Bif(a%26%26a.length)%7Bvar%20t%2Ce%3Dfunction(t)%7Bvar%20e%2Cn%2Co%2Ci%2Cc%2Cr%3B%22object%22%3D%3D%3Df(r%3Da%5Bt%5D)%26%26(e%3Dfunction(t)%7Btry%7Bvar%20e%3Dt.getBoundingClientRect()%2Cn%3De%26%26e.top%7C%7C-1%2Co%3De%26%26e.left%7C%7C-1%2Ci%3Ddocument.body.scrollWidth%7C%7C-1%2Ce%3Ddocument.body.scrollHeight%7C%7C-1%3Breturn%7Btop%3An.toFixed(0)%2Cleft%3Ao.toFixed(0)%2Cpage_width%3Ai%2Cpage_height%3Ae%7D%7Dcatch(o)%7Breturn%20l(%7Btn%3As%2Cwinloss%3A1%2Cfe%3A2%2Cpos_err_c%3A1001%2Cpos_err_m%3Ao.toString()%7D)%2C%7Btop%3A%22-1%22%2Cleft%3A%22-1%22%2Cpage_width%3A%22-1%22%2Cpage_height%3A%22-1%22%7D%7D%7D(r)%2C(n%3Dd%5Bt%5D)%26%26g(n%2C0%2Ce)%2Co%3Dp%5Bt%5D%2Ci%3D!1%2C(c%3Dfunction()%7BsetTimeout(function()%7Bvar%20t%2Ce%3B!i%26%26(t%3Dr%2Ce%3Dwindow.innerHeight%7C%7Cdocument.documentElement.clientHeight%7C%7Cdocument.body.clientHeight%2C(t.getBoundingClientRect()%26%26t.getBoundingClientRect().top)%3C%3De-.75*(t.offsetHeight%7C%7Ct.clientHeight))%3F(i%3D!0%2Co%26%26g(o))%3Ac()%7D%2C500)%7D)())%7D%3Bfor(t%20in%20a)e(t)%7D%7D()%7D()';
+ temp +=
+ '!function()%7B%22use%20strict%22%3Bfunction%20f(t)%7Breturn(f%3D%22function%22%3D%3Dtypeof%20Symbol%26%26%22symbol%22%3D%3Dtypeof%20Symbol.iterator%3Ffunction(t)%7Breturn%20typeof%20t%7D%3Afunction(t)%7Breturn%20t%26%26%22function%22%3D%3Dtypeof%20Symbol%26%26t.constructor%3D%3D%3DSymbol%26%26t!%3D%3DSymbol.prototype%3F%22symbol%22%3Atypeof%20t%7D)(t)%7Dfunction%20l(t)%7Bvar%20e%3D0%3Carguments.length%26%26void%200!%3D%3Dt%3Ft%3A%7B%7D%3Btry%7Be.random_t%3D(new%20Date).getTime()%2Cg(function(t)%7Bvar%20e%3D1%3Carguments.length%26%26void%200!%3D%3Darguments%5B1%5D%3Farguments%5B1%5D%3A%22%22%3Bif(%22object%22!%3D%3Df(t))return%20e%3Bvar%20n%3Dfunction(t)%7Bfor(var%20e%2Cn%3D%5B%5D%2Co%3D0%2Ci%3DObject.keys(t)%3Bo%3Ci.length%3Bo%2B%2B)e%3Di%5Bo%5D%2Cn.push(%22%22.concat(e%2C%22%3D%22).concat(t%5Be%5D))%3Breturn%20n%7D(t).join(%22%26%22)%2Co%3De.indexOf(%22%23%22)%2Ci%3De%2Ct%3D%22%22%3Breturn-1!%3D%3Do%26%26(i%3De.slice(0%2Co)%2Ct%3De.slice(o))%2Cn%26%26(i%26%26-1!%3D%3Di.indexOf(%22%3F%22)%3Fi%2B%3D%22%26%22%2Bn%3Ai%2B%3D%22%3F%22%2Bn)%2Ci%2Bt%7D(e%2C%22https%3A%2F%2Ftrace.mediago.io%2Fapi%2Flog%2Ftrack%22))%7Dcatch(t)%7B%7D%7Dfunction%20g(t%2Ce%2Cn)%7B(t%3Dt%3Ft.split(%22%3B%3B%3B%22)%3A%5B%5D).map(function(t)%7Btry%7B0%3C%3Dt.indexOf(%22%2Fapi%2Fbidder%2Ftrack%22)%26%26n%26%26(t%2B%3D%22%26inIframe%3D%22.concat(!(!self.frameElement%7C%7C%22IFRAME%22!%3Dself.frameElement.tagName)%7C%7Cwindow.frames.length!%3Dparent.frames.length%7C%7Cself!%3Dtop)%2Ct%2B%3D%22%26pos_x%3D%22.concat(n.left%2C%22%26pos_y%3D%22).concat(n.top%2C%22%26page_w%3D%22).concat(n.page_width%2C%22%26page_h%3D%22).concat(n.page_height))%7Dcatch(t)%7Bl(%7Btn%3As%2Cwinloss%3A1%2Cfe%3A2%2Cpos_err_c%3A1002%2Cpos_err_m%3At.toString()%7D)%7Dvar%20e%3Dnew%20Image%3Be.src%3Dt%2Ce.style.display%3D%22none%22%2Ce.style.visibility%3D%22hidden%22%2Ce.width%3D0%2Ce.height%3D0%2Cdocument.body.appendChild(e)%7D)%7Dvar%20d%3D%5B%22https%3A%2F%2Ftrace.mediago.io%2Fapi%2Fbidder%2Ftrack%3Ftn%3D39934c2bda4debbe4c680be1dd02f5d3%26price%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26evt%3D101%26rid%3D6e28cfaf115a354ea1ad8e1304d6d7b8%26campaignid%3D1339145%26impid%3D44-300x250-1%26offerid%3D24054386%26test%3D0%26time%3D1660789795%26cp%3DjZDh1xu6_QqJLlKVtCkiHIP_TER6gL9jeTrlHCBoxOM%26acid%3D599%26trackingid%3D99afea272c2b0e8626489674ddb7a0bb%26uid%3Da865b9ae-fa9e-4c09-8204-2db99ac7c8f7%26bm%3D2%26la%3Den%26cn%3Dus%26cid%3D3998296%26info%3DSi3oM-qfCbw2iZRYs01BkUWyH6c5CQWHrA8CQLE0VHcXAcf4ljY9dyLzQ4vAlTWd6-j_ou4ySor3e70Ll7wlKiiauQKaUkZqNoTizHm73C4FK8DYJSTP3VkhJV8RzrYk%26sid%3D128__110__1__12__28__38__163__96__58__24__47__99%26sp%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26scp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26acu%3DUSD%26scu%3DUSD%26sgcp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26gprice%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26gcp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26ah%3D%26de%3Dwjh.popin.cc%26iv%3D0%22%2C%22%24%7BITRACKER2%7D%22%2C%22%24%7BITRACKER3%7D%22%2C%22%24%7BITRACKER4%7D%22%2C%22%24%7BITRACKER5%7D%22%2C%22%24%7BITRACKER6%7D%22%5D%2Cp%3D%5B%22https%3A%2F%2Ftrace.mediago.io%2Fapi%2Fbidder%2Ftrack%3Ftn%3D39934c2bda4debbe4c680be1dd02f5d3%26price%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26evt%3D104%26rid%3D6e28cfaf115a354ea1ad8e1304d6d7b8%26campaignid%3D1339145%26impid%3D44-300x250-1%26offerid%3D24054386%26test%3D0%26time%3D1660789795%26cp%3DjZDh1xu6_QqJLlKVtCkiHIP_TER6gL9jeTrlHCBoxOM%26acid%3D599%26trackingid%3D99afea272c2b0e8626489674ddb7a0bb%26uid%3Da865b9ae-fa9e-4c09-8204-2db99ac7c8f7%26sid%3D128__110__1__12__28__38__163__96__58__24__47__99%26format%3D%26crid%3Dff32b6f9b3bbc45c00b78b6674a2952e%26bm%3D2%26la%3Den%26cn%3Dus%26cid%3D3998296%26info%3DSi3oM-qfCbw2iZRYs01BkUWyH6c5CQWHrA8CQLE0VHcXAcf4ljY9dyLzQ4vAlTWd6-j_ou4ySor3e70Ll7wlKiiauQKaUkZqNoTizHm73C4FK8DYJSTP3VkhJV8RzrYk%26sp%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26scp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26acu%3DUSD%26scu%3DUSD%26sgcp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26gprice%3DdjUJcggeuWWfbm28q4WXHdgMFkO28DrGw49FnubQ0Bk%26gcp%3DzK0DRYY1UV-syqSpmcMYBpOebtoQJV9ZEJT0JFqbTQg%26ah%3D%26de%3Dwjh.popin.cc%26iv%3D0%22%2C%22%24%7BVTRACKER2%7D%22%2C%22%24%7BVTRACKER3%7D%22%2C%22%24%7BVTRACKER4%7D%22%2C%22%24%7BVTRACKER5%7D%22%2C%22%24%7BVTRACKER6%7D%22%5D%2Cs%3D%22f9f2b1ef23fe2759c2cad0953029a94b%22%2Cn%3Ddocument.getElementById(%22mgcontainer-99afea272c2b0e8626489674ddb7a0bb%22)%3Bn%26%26function()%7Bvar%20a%3Dn.getElementsByClassName(%22mediago-placement-track%22)%3Bif(a%26%26a.length)%7Bvar%20t%2Ce%3Dfunction(t)%7Bvar%20e%2Cn%2Co%2Ci%2Cc%2Cr%3B%22object%22%3D%3D%3Df(r%3Da%5Bt%5D)%26%26(e%3Dfunction(t)%7Btry%7Bvar%20e%3Dt.getBoundingClientRect()%2Cn%3De%26%26e.top%7C%7C-1%2Co%3De%26%26e.left%7C%7C-1%2Ci%3Ddocument.body.scrollWidth%7C%7C-1%2Ce%3Ddocument.body.scrollHeight%7C%7C-1%3Breturn%7Btop%3An.toFixed(0)%2Cleft%3Ao.toFixed(0)%2Cpage_width%3Ai%2Cpage_height%3Ae%7D%7Dcatch(o)%7Breturn%20l(%7Btn%3As%2Cwinloss%3A1%2Cfe%3A2%2Cpos_err_c%3A1001%2Cpos_err_m%3Ao.toString()%7D)%2C%7Btop%3A%22-1%22%2Cleft%3A%22-1%22%2Cpage_width%3A%22-1%22%2Cpage_height%3A%22-1%22%7D%7D%7D(r)%2C(n%3Dd%5Bt%5D)%26%26g(n%2C0%2Ce)%2Co%3Dp%5Bt%5D%2Ci%3D!1%2C(c%3Dfunction()%7BsetTimeout(function()%7Bvar%20t%2Ce%3B!i%26%26(t%3Dr%2Ce%3Dwindow.innerHeight%7C%7Cdocument.documentElement.clientHeight%7C%7Cdocument.body.clientHeight%2C(t.getBoundingClientRect()%26%26t.getBoundingClientRect().top)%3C%3De-.75*(t.offsetHeight%7C%7Ct.clientHeight))%3F(i%3D!0%2Co%26%26g(o))%3Ac()%7D%2C500)%7D)())%7D%3Bfor(t%20in%20a)e(t)%7D%7D()%7D()';
temp += '%3B%3C%2Fscri';
temp += 'pt%3E';
adm += decodeURIComponent(temp);
@@ -101,13 +238,13 @@ describe('mediago:BidAdapterTests', function () {
cid: '1339145',
crid: 'ff32b6f9b3bbc45c00b78b6674a2952e',
w: 300,
- h: 250,
- },
- ],
- },
+ h: 250
+ }
+ ]
+ }
],
- cur: 'USD',
- },
+ cur: 'USD'
+ }
};
let bids = spec.interpretResponse(serverResponse);
@@ -123,4 +260,324 @@ describe('mediago:BidAdapterTests', function () {
expect(bid.height).to.equal(250);
expect(bid.currency).to.equal('USD');
});
+
+ describe('mediago: getUserSyncs', function() {
+ const COOKY_SYNC_IFRAME_URL = 'https://cdn.mediago.io/js/cookieSync.html';
+ const IFRAME_ENABLED = {
+ iframeEnabled: true,
+ pixelEnabled: false,
+ };
+ const IFRAME_DISABLED = {
+ iframeEnabled: false,
+ pixelEnabled: false,
+ };
+ const GDPR_CONSENT = {
+ consentString: 'gdprConsentString',
+ gdprApplies: true
+ };
+ const USP_CONSENT = {
+ consentString: 'uspConsentString'
+ }
+
+ let syncParamUrl = `dm=${encodeURIComponent(location.origin || `https://${location.host}`)}`;
+ syncParamUrl += '&gdpr=1&gdpr_consent=gdprConsentString&ccpa_consent=uspConsentString';
+ const expectedIframeSyncs = [
+ {
+ type: 'iframe',
+ url: `${COOKY_SYNC_IFRAME_URL}?${syncParamUrl}`
+ }
+ ];
+
+ it('should return nothing if iframe is disabled', () => {
+ const userSyncs = spec.getUserSyncs(IFRAME_DISABLED, undefined, GDPR_CONSENT, USP_CONSENT, undefined);
+ expect(userSyncs).to.be.undefined;
+ });
+
+ it('should do userSyncs if iframe is enabled', () => {
+ const userSyncs = spec.getUserSyncs(IFRAME_ENABLED, undefined, GDPR_CONSENT, USP_CONSENT, undefined);
+ expect(userSyncs).to.deep.equal(expectedIframeSyncs);
+ });
+ });
+});
+
+describe('mediago Bid Adapter Tests', function () {
+ describe('buildRequests', () => {
+ describe('getPageTitle function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should return the top document title if available', function() {
+ const fakeTopDocument = {
+ title: 'Top Document Title',
+ querySelector: () => ({ content: 'Top Document Title test' })
+ };
+ const fakeTopWindow = {
+ document: fakeTopDocument
+ };
+ const result = getPageTitle({ top: fakeTopWindow });
+ expect(result).to.equal('Top Document Title');
+ });
+
+ it('should return the content of top og:title meta tag if title is empty', function() {
+ const ogTitleContent = 'Top OG Title Content';
+ const fakeTopWindow = {
+ document: {
+ title: '',
+ querySelector: sandbox.stub().withArgs('meta[property="og:title"]').returns({ content: ogTitleContent })
+ }
+ };
+
+ const result = getPageTitle({ top: fakeTopWindow });
+ expect(result).to.equal(ogTitleContent);
+ });
+
+ it('should return the document title if no og:title meta tag is present', function() {
+ document.title = 'Test Page Title';
+ sandbox.stub(document, 'querySelector').withArgs('meta[property="og:title"]').returns(null);
+
+ const result = getPageTitle({ top: undefined });
+ expect(result).to.equal('Test Page Title');
+ });
+
+ it('should return the content of og:title meta tag if present', function() {
+ document.title = '';
+ const ogTitleContent = 'Top OG Title Content';
+ sandbox.stub(document, 'querySelector').withArgs('meta[property="og:title"]').returns({ content: ogTitleContent });
+ const result = getPageTitle({ top: undefined });
+ expect(result).to.equal(ogTitleContent);
+ });
+
+ it('should return an empty string if no title or og:title meta tag is found', function() {
+ document.title = '';
+ sandbox.stub(document, 'querySelector').withArgs('meta[property="og:title"]').returns(null);
+ const result = getPageTitle({ top: undefined });
+ expect(result).to.equal('');
+ });
+
+ it('should handle exceptions when accessing top.document and fallback to current document', function() {
+ const fakeWindow = {
+ get top() {
+ throw new Error('Access denied');
+ }
+ };
+ const ogTitleContent = 'Current OG Title Content';
+ document.title = 'Current Document Title';
+ sandbox.stub(document, 'querySelector').withArgs('meta[property="og:title"]').returns({ content: ogTitleContent });
+ const result = getPageTitle(fakeWindow);
+ expect(result).to.equal('Current Document Title');
+ });
+ });
+
+ describe('getPageDescription function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should return the top document description if available', function() {
+ const descriptionContent = 'Top Document Description';
+ const fakeTopDocument = {
+ querySelector: sandbox.stub().withArgs('meta[name="description"]').returns({ content: descriptionContent })
+ };
+ const fakeTopWindow = { document: fakeTopDocument };
+ const result = getPageDescription({ top: fakeTopWindow });
+ expect(result).to.equal(descriptionContent);
+ });
+
+ it('should return the top document og:description if description is not present', function() {
+ const ogDescriptionContent = 'Top OG Description';
+ const fakeTopDocument = {
+ querySelector: sandbox.stub().withArgs('meta[property="og:description"]').returns({ content: ogDescriptionContent })
+ };
+ const fakeTopWindow = { document: fakeTopDocument };
+ const result = getPageDescription({ top: fakeTopWindow });
+ expect(result).to.equal(ogDescriptionContent);
+ });
+
+ it('should return the current document description if top document is not accessible', function() {
+ const descriptionContent = 'Current Document Description';
+ sandbox.stub(document, 'querySelector')
+ .withArgs('meta[name="description"]').returns({ content: descriptionContent })
+ const fakeWindow = {
+ get top() {
+ throw new Error('Access denied');
+ }
+ };
+ const result = getPageDescription(fakeWindow);
+ expect(result).to.equal(descriptionContent);
+ });
+
+ it('should return the current document og:description if description is not present and top document is not accessible', function() {
+ const ogDescriptionContent = 'Current OG Description';
+ sandbox.stub(document, 'querySelector')
+ .withArgs('meta[property="og:description"]').returns({ content: ogDescriptionContent });
+
+ const fakeWindow = {
+ get top() {
+ throw new Error('Access denied');
+ }
+ };
+ const result = getPageDescription(fakeWindow);
+ expect(result).to.equal(ogDescriptionContent);
+ });
+ });
+
+ describe('getPageKeywords function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should return the top document keywords if available', function() {
+ const keywordsContent = 'keyword1, keyword2, keyword3';
+ const fakeTopDocument = {
+ querySelector: sandbox.stub()
+ .withArgs('meta[name="keywords"]').returns({ content: keywordsContent })
+ };
+ const fakeTopWindow = { document: fakeTopDocument };
+
+ const result = getPageKeywords({ top: fakeTopWindow });
+ expect(result).to.equal(keywordsContent);
+ });
+
+ it('should return the current document keywords if top document is not accessible', function() {
+ const keywordsContent = 'keyword1, keyword2, keyword3';
+ sandbox.stub(document, 'querySelector')
+ .withArgs('meta[name="keywords"]').returns({ content: keywordsContent });
+
+ // æ¨ĄæéĄļåąįĒåŖčŽŋéŽåŧ常
+ const fakeWindow = {
+ get top() {
+ throw new Error('Access denied');
+ }
+ };
+
+ const result = getPageKeywords(fakeWindow);
+ expect(result).to.equal(keywordsContent);
+ });
+
+ it('should return an empty string if no keywords meta tag is found', function() {
+ sandbox.stub(document, 'querySelector').withArgs('meta[name="keywords"]').returns(null);
+
+ const result = getPageKeywords();
+ expect(result).to.equal('');
+ });
+ });
+ describe('getConnectionDownLink function', function() {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should return the downlink value as a string if available', function() {
+ const downlinkValue = 2.5;
+ const fakeNavigator = {
+ connection: {
+ downlink: downlinkValue
+ }
+ };
+
+ const result = getConnectionDownLink({ navigator: fakeNavigator });
+ expect(result).to.equal(downlinkValue.toString());
+ });
+
+ it('should return undefined if downlink is not available', function() {
+ const fakeNavigator = {
+ connection: {}
+ };
+
+ const result = getConnectionDownLink({ navigator: fakeNavigator });
+ expect(result).to.be.undefined;
+ });
+
+ it('should return undefined if connection is not available', function() {
+ const fakeNavigator = {};
+
+ const result = getConnectionDownLink({ navigator: fakeNavigator });
+ expect(result).to.be.undefined;
+ });
+
+ it('should handle cases where navigator is not defined', function() {
+ const result = getConnectionDownLink({});
+ expect(result).to.be.undefined;
+ });
+ });
+
+ describe('getUserSyncs with message event listener', function() {
+ function messageHandler(event) {
+ if (!event.data || event.origin !== THIRD_PARTY_COOKIE_ORIGIN) {
+ return;
+ }
+
+ window.removeEventListener('message', messageHandler, true);
+ event.stopImmediatePropagation();
+
+ const response = event.data;
+ if (!response.optout && response.mguid) {
+ storage.setCookie(COOKIE_KEY_MGUID, response.mguid, getCurrentTimeToUTCString());
+ }
+ }
+
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.createSandbox();
+ sandbox.stub(storage, 'setCookie');
+ sandbox.stub(window, 'removeEventListener');
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ it('should set a cookie when a valid message is received', () => {
+ const fakeEvent = {
+ data: { optout: '', mguid: '12345' },
+ origin: THIRD_PARTY_COOKIE_ORIGIN,
+ stopImmediatePropagation: sinon.spy()
+ };
+
+ messageHandler(fakeEvent);
+
+ expect(fakeEvent.stopImmediatePropagation.calledOnce).to.be.true;
+ expect(window.removeEventListener.calledWith('message', messageHandler, true)).to.be.true;
+ expect(storage.setCookie.calledWith(COOKIE_KEY_MGUID, '12345', sinon.match.string)).to.be.true;
+ });
+ it('should not do anything when an invalid message is received', () => {
+ const fakeEvent = {
+ data: null,
+ origin: 'http://invalid-origin.com',
+ stopImmediatePropagation: sinon.spy()
+ };
+
+ messageHandler(fakeEvent);
+
+ expect(fakeEvent.stopImmediatePropagation.notCalled).to.be.true;
+ expect(window.removeEventListener.notCalled).to.be.true;
+ expect(storage.setCookie.notCalled).to.be.true;
+ });
+ });
+ });
});
diff --git a/test/spec/modules/mediasquareBidAdapter_spec.js b/test/spec/modules/mediasquareBidAdapter_spec.js
index d7984c05967..6082ef65055 100644
--- a/test/spec/modules/mediasquareBidAdapter_spec.js
+++ b/test/spec/modules/mediasquareBidAdapter_spec.js
@@ -102,10 +102,34 @@ describe('MediaSquare bid adapter tests', function () {
'context': 'instream',
'increment': 1.0,
'ova': 'cleared',
+ 'dsa': {
+ 'behalf': 'some-behalf',
+ 'paid': 'some-paid',
+ 'transparency': [{
+ 'domain': 'test.com',
+ 'dsaparams': [1, 2, 3]
+ }],
+ 'adrender': 1
+ }
}],
}};
const DEFAULT_OPTIONS = {
+ ortb2: {
+ regs: {
+ ext: {
+ dsa: {
+ dsarequired: '1',
+ pubrender: '2',
+ datatopub: '3',
+ transparency: [{
+ domain: 'test.com',
+ dsaparams: [1, 2, 3]
+ }]
+ }
+ }
+ }
+ },
gdprConsent: {
gdprApplies: true,
consentString: 'BOzZdA0OzZdA0AGABBENDJ-AAAAvh7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__79__3z3_9pxP78k89r7337Mw_v-_v-b7JCPN_Y3v-8Kg',
@@ -144,6 +168,7 @@ describe('MediaSquare bid adapter tests', function () {
expect(requestContent.codes[0]).to.have.property('mediatypes').exist;
expect(requestContent.codes[0]).to.have.property('floor').exist;
expect(requestContent.codes[0].floor).to.deep.equal({});
+ expect(requestContent).to.have.property('dsa');
const requestfloor = spec.buildRequests(FLOORS_PARAMS, DEFAULT_OPTIONS);
const responsefloor = JSON.parse(requestfloor.data);
expect(responsefloor.codes[0]).to.have.property('floor').exist;
@@ -176,6 +201,7 @@ describe('MediaSquare bid adapter tests', function () {
expect(bid.meta).to.exist;
expect(bid.meta.advertiserDomains).to.exist;
expect(bid.meta.advertiserDomains).to.have.lengthOf(1);
+ expect(bid.meta.dsa).to.exist;
});
it('Verifies match', function () {
const request = spec.buildRequests(DEFAULT_PARAMS, DEFAULT_OPTIONS);
diff --git a/test/spec/modules/mgidXBidAdapter_spec.js b/test/spec/modules/mgidXBidAdapter_spec.js
index 14619e9c0e1..e0b1e1a84e9 100644
--- a/test/spec/modules/mgidXBidAdapter_spec.js
+++ b/test/spec/modules/mgidXBidAdapter_spec.js
@@ -6,7 +6,6 @@ import { config } from '../../../src/config';
import { USERSYNC_DEFAULT_CONFIG } from '../../../src/userSync';
const bidder = 'mgidX'
-const adUrl = 'https://us-east-x.mgid.com/pbjs';
describe('MGIDXBidAdapter', function () {
const bids = [
@@ -19,6 +18,7 @@ describe('MGIDXBidAdapter', function () {
}
},
params: {
+ region: 'eu',
placementId: 'testBanner',
}
},
@@ -56,6 +56,7 @@ describe('MGIDXBidAdapter', function () {
}
},
params: {
+ region: 'eu',
placementId: 'testNative',
}
}
@@ -76,7 +77,10 @@ describe('MGIDXBidAdapter', function () {
const bidderRequest = {
uspConsent: '1---',
- gdprConsent: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
+ gdprConsent: {
+ consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
+ vendorData: {}
+ },
refererInfo: {
referer: 'https://test.com'
}
@@ -105,8 +109,16 @@ describe('MGIDXBidAdapter', function () {
expect(serverRequest.method).to.equal('POST');
});
- it('Returns valid URL', function () {
- expect(serverRequest.url).to.equal(adUrl);
+ it('Returns valid EU URL', function () {
+ bids[0].params.region = 'eu';
+ serverRequest = spec.buildRequests(bids, bidderRequest);
+ expect(serverRequest.url).to.equal('https://eu.mgid.com/pbjs');
+ });
+
+ it('Returns valid EAST URL', function () {
+ bids[0].params.region = 'other';
+ serverRequest = spec.buildRequests(bids, bidderRequest);
+ expect(serverRequest.url).to.equal('https://us-east-x.mgid.com/pbjs');
});
it('Returns general data valid', function () {
@@ -131,7 +143,7 @@ describe('MGIDXBidAdapter', function () {
expect(data.host).to.be.a('string');
expect(data.page).to.be.a('string');
expect(data.coppa).to.be.a('number');
- expect(data.gdpr).to.be.a('string');
+ expect(data.gdpr).to.be.a('object');
expect(data.ccpa).to.be.a('string');
expect(data.tmax).to.be.a('number');
expect(data.placements).to.have.lengthOf(3);
@@ -172,8 +184,10 @@ describe('MGIDXBidAdapter', function () {
serverRequest = spec.buildRequests(bids, bidderRequest);
let data = serverRequest.data;
expect(data.gdpr).to.exist;
- expect(data.gdpr).to.be.a('string');
- expect(data.gdpr).to.equal(bidderRequest.gdprConsent);
+ expect(data.gdpr).to.be.a('object');
+ expect(data.gdpr).to.have.property('consentString');
+ expect(data.gdpr).to.not.have.property('vendorData');
+ expect(data.gdpr.consentString).to.equal(bidderRequest.gdprConsent.consentString);
expect(data.ccpa).to.not.exist;
delete bidderRequest.gdprConsent;
});
@@ -188,12 +202,6 @@ describe('MGIDXBidAdapter', function () {
expect(data.ccpa).to.equal(bidderRequest.uspConsent);
expect(data.gdpr).to.not.exist;
});
-
- it('Returns empty data if no valid requests are passed', function () {
- serverRequest = spec.buildRequests([], bidderRequest);
- let data = serverRequest.data;
- expect(data.placements).to.be.an('array').that.is.empty;
- });
});
describe('interpretResponse', function () {
diff --git a/test/spec/modules/microadBidAdapter_spec.js b/test/spec/modules/microadBidAdapter_spec.js
index bd6d04a6312..9eb36d2fa6c 100644
--- a/test/spec/modules/microadBidAdapter_spec.js
+++ b/test/spec/modules/microadBidAdapter_spec.js
@@ -382,6 +382,196 @@ describe('microadBidAdapter', () => {
})
});
})
+
+ describe('should send gpid', () => {
+ it('from gpid', () => {
+ const bidRequest = Object.assign({}, bidRequestTemplate, {
+ ortb2Imp: {
+ ext: {
+ tid: 'transaction-id',
+ gpid: '1111/2222',
+ data: {
+ pbadslot: '3333/4444'
+ }
+ }
+ }
+ });
+ const requests = spec.buildRequests([bidRequest], bidderRequest)
+ requests.forEach(request => {
+ expect(request.data).to.deep.equal(
+ Object.assign({}, expectedResultTemplate, {
+ cbt: request.data.cbt,
+ gpid: '1111/2222',
+ pbadslot: '3333/4444'
+ })
+ );
+ })
+ })
+
+ it('from pbadslot', () => {
+ const bidRequest = Object.assign({}, bidRequestTemplate, {
+ ortb2Imp: {
+ ext: {
+ tid: 'transaction-id',
+ data: {
+ pbadslot: '3333/4444'
+ }
+ }
+ }
+ });
+ const requests = spec.buildRequests([bidRequest], bidderRequest)
+ requests.forEach(request => {
+ expect(request.data).to.deep.equal(
+ Object.assign({}, expectedResultTemplate, {
+ cbt: request.data.cbt,
+ gpid: '3333/4444',
+ pbadslot: '3333/4444'
+ })
+ );
+ })
+ })
+ })
+
+ const notGettingGpids = {
+ 'they are not existing': bidRequestTemplate,
+ 'they are blank': {
+ ortb2Imp: {
+ ext: {
+ tid: 'transaction-id',
+ gpid: '',
+ data: {
+ pbadslot: ''
+ }
+ }
+ }
+ }
+ }
+
+ Object.entries(notGettingGpids).forEach(([testTitle, param]) => {
+ it(`should not send gpid because ${testTitle}`, () => {
+ const bidRequest = Object.assign({}, bidRequestTemplate, param);
+ const requests = spec.buildRequests([bidRequest], bidderRequest)
+ requests.forEach(request => {
+ expect(request.data).to.deep.equal(
+ Object.assign({}, expectedResultTemplate, {
+ cbt: request.data.cbt,
+ })
+ );
+ expect(request.data.gpid).to.be.undefined;
+ expect(request.data.pbadslot).to.be.undefined;
+ })
+ })
+ })
+
+ it('should send adservname', () => {
+ const bidRequest = Object.assign({}, bidRequestTemplate, {
+ ortb2Imp: {
+ ext: {
+ tid: 'transaction-id',
+ data: {
+ adserver: {
+ name: 'gam'
+ }
+ }
+ }
+ }
+ });
+ const requests = spec.buildRequests([bidRequest], bidderRequest)
+ requests.forEach(request => {
+ expect(request.data).to.deep.equal(
+ Object.assign({}, expectedResultTemplate, {
+ cbt: request.data.cbt,
+ adservname: 'gam'
+ })
+ );
+ })
+ })
+
+ const notGettingAdservnames = {
+ 'it is not existing': bidRequestTemplate,
+ 'it is blank': {
+ ortb2Imp: {
+ ext: {
+ tid: 'transaction-id',
+ data: {
+ adserver: {
+ name: ''
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Object.entries(notGettingAdservnames).forEach(([testTitle, param]) => {
+ it(`should not send adservname because ${testTitle}`, () => {
+ const bidRequest = Object.assign({}, bidRequestTemplate, param);
+ const requests = spec.buildRequests([bidRequest], bidderRequest)
+ requests.forEach(request => {
+ expect(request.data).to.deep.equal(
+ Object.assign({}, expectedResultTemplate, {
+ cbt: request.data.cbt,
+ })
+ );
+ expect(request.data.adservname).to.be.undefined;
+ })
+ })
+ })
+
+ it('should send adservadslot', () => {
+ const bidRequest = Object.assign({}, bidRequestTemplate, {
+ ortb2Imp: {
+ ext: {
+ tid: 'transaction-id',
+ data: {
+ adserver: {
+ adslot: '/1111/home'
+ }
+ }
+ }
+ }
+ });
+ const requests = spec.buildRequests([bidRequest], bidderRequest)
+ requests.forEach(request => {
+ expect(request.data).to.deep.equal(
+ Object.assign({}, expectedResultTemplate, {
+ cbt: request.data.cbt,
+ adservadslot: '/1111/home'
+ })
+ );
+ })
+ })
+
+ const notGettingAdservadslots = {
+ 'it is not existing': bidRequestTemplate,
+ 'it is blank': {
+ ortb2Imp: {
+ ext: {
+ tid: 'transaction-id',
+ data: {
+ adserver: {
+ adslot: ''
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Object.entries(notGettingAdservadslots).forEach(([testTitle, param]) => {
+ it(`should not send adservadslot because ${testTitle}`, () => {
+ const bidRequest = Object.assign({}, bidRequestTemplate, param);
+ const requests = spec.buildRequests([bidRequest], bidderRequest)
+ requests.forEach(request => {
+ expect(request.data).to.deep.equal(
+ Object.assign({}, expectedResultTemplate, {
+ cbt: request.data.cbt,
+ })
+ );
+ expect(request.data.adservadslot).to.be.undefined;
+ })
+ })
+ })
});
describe('interpretResponse', () => {
diff --git a/test/spec/modules/minutemediaBidAdapter_spec.js b/test/spec/modules/minutemediaBidAdapter_spec.js
index 48f694bc79d..d5d6cdc5449 100644
--- a/test/spec/modules/minutemediaBidAdapter_spec.js
+++ b/test/spec/modules/minutemediaBidAdapter_spec.js
@@ -178,6 +178,16 @@ describe('minutemediaAdapter', function () {
expect(request.data.bids[1].mediaType).to.equal(BANNER)
});
+ it('should send the correct currency in bid request', function () {
+ const bid = utils.deepClone(bidRequests[0]);
+ bid.params = {
+ 'currency': 'EUR'
+ };
+ const expectedCurrency = bid.params.currency;
+ const request = spec.buildRequests([bid], bidderRequest);
+ expect(request.data.bids[0].currency).to.equal(expectedCurrency);
+ });
+
it('should respect syncEnabled option', function() {
config.setConfig({
userSync: {
@@ -291,6 +301,22 @@ describe('minutemediaAdapter', function () {
expect(request.data.params).to.have.property('gdpr_consent', 'test-consent-string');
});
+ it('should not send the gpp param if gppConsent is false in the bidRequest', function () {
+ const bidderRequestWithGPP = Object.assign({gppConsent: false}, bidderRequest);
+ const request = spec.buildRequests(bidRequests, bidderRequestWithGPP);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.not.have.property('gpp');
+ expect(request.data.params).to.not.have.property('gpp_sid');
+ });
+
+ it('should send the gpp param if gppConsent is true in the bidRequest', function () {
+ const bidderRequestWithGPP = Object.assign({gppConsent: {gppString: 'test-consent-string', applicableSections: [7]}}, bidderRequest);
+ const request = spec.buildRequests(bidRequests, bidderRequestWithGPP);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.have.property('gpp', 'test-consent-string');
+ expect(request.data.params.gpp_sid[0]).to.be.equal(7);
+ });
+
it('should have schain param if it is available in the bidRequest', () => {
const schain = {
ver: '1.0',
diff --git a/test/spec/modules/missenaBidAdapter_spec.js b/test/spec/modules/missenaBidAdapter_spec.js
index e874aabbc70..ab1fbdcc074 100644
--- a/test/spec/modules/missenaBidAdapter_spec.js
+++ b/test/spec/modules/missenaBidAdapter_spec.js
@@ -1,18 +1,29 @@
import { expect } from 'chai';
-import { spec, _getPlatform } from 'modules/missenaBidAdapter.js';
-import { newBidder } from 'src/adapters/bidderFactory.js';
+import { spec, storage } from 'modules/missenaBidAdapter.js';
import { BANNER } from '../../../src/mediaTypes.js';
+const REFERRER = 'https://referer';
+const REFERRER2 = 'https://referer2';
+const COOKIE_DEPRECATION_LABEL = 'test';
+
describe('Missena Adapter', function () {
- const adapter = newBidder(spec);
+ $$PREBID_GLOBAL$$.bidderSettings = {
+ missena: {
+ storageAllowed: true,
+ },
+ };
const bidId = 'abc';
-
const bid = {
bidder: 'missena',
bidId: bidId,
sizes: [[1, 1]],
mediaTypes: { banner: { sizes: [[1, 1]] } },
+ ortb2: {
+ device: {
+ ext: { cdep: COOKIE_DEPRECATION_LABEL },
+ },
+ },
params: {
apiKey: 'PA-34745704',
placement: 'sticky',
@@ -40,7 +51,20 @@ describe('Missena Adapter', function () {
formats: ['sticky-banner'],
},
};
+ const consentString = 'AAAAAAAAA==';
+ const bidderRequest = {
+ gdprConsent: {
+ consentString: consentString,
+ gdprApplies: true,
+ },
+ refererInfo: {
+ topmostLocation: REFERRER,
+ canonicalUrl: 'https://canonical',
+ },
+ };
+
+ const bids = [bid, bidWithoutFloor];
describe('codes', function () {
it('should return a bidder code of missena', function () {
expect(spec.code).to.equal('missena');
@@ -66,20 +90,12 @@ describe('Missena Adapter', function () {
});
describe('buildRequests', function () {
- const consentString = 'AAAAAAAAA==';
-
- const bidderRequest = {
- gdprConsent: {
- consentString: consentString,
- gdprApplies: true,
- },
- refererInfo: {
- topmostLocation: 'https://referer',
- canonicalUrl: 'https://canonical',
- },
- };
+ let getDataFromLocalStorageStub = sinon.stub(
+ storage,
+ 'getDataFromLocalStorage',
+ );
- const requests = spec.buildRequests([bid, bidWithoutFloor], bidderRequest);
+ const requests = spec.buildRequests(bids, bidderRequest);
const request = requests[0];
const payload = JSON.parse(request.data);
const payloadNoFloor = JSON.parse(requests[1].data);
@@ -105,7 +121,7 @@ describe('Missena Adapter', function () {
});
it('should send referer information to the request', function () {
- expect(payload.referer).to.equal('https://referer');
+ expect(payload.referer).to.equal(REFERRER);
expect(payload.referer_canonical).to.equal('https://canonical');
});
@@ -121,6 +137,70 @@ describe('Missena Adapter', function () {
expect(payloadNoFloor.floor).to.equal(undefined);
expect(payloadNoFloor.floor_currency).to.equal(undefined);
});
+ it('should send the idempotency key', function () {
+ expect(window.msna_ik).to.not.equal(undefined);
+ expect(payload.ik).to.equal(window.msna_ik);
+ });
+
+ getDataFromLocalStorageStub.restore();
+ getDataFromLocalStorageStub = sinon.stub(
+ storage,
+ 'getDataFromLocalStorage',
+ );
+ const localStorageData = {
+ [`missena.missena.capper.remove-bubble.${bid.params.apiKey}`]:
+ JSON.stringify({
+ expiry: new Date().getTime() + 600_000, // 10 min into the future
+ }),
+ };
+ getDataFromLocalStorageStub.callsFake((key) => localStorageData[key]);
+ const cappedRequests = spec.buildRequests(bids, bidderRequest);
+
+ it('should not participate if capped', function () {
+ expect(cappedRequests.length).to.equal(0);
+ });
+
+ const localStorageDataSamePage = {
+ [`missena.missena.capper.remove-bubble.${bid.params.apiKey}`]:
+ JSON.stringify({
+ expiry: new Date().getTime() + 600_000, // 10 min into the future
+ referer: REFERRER,
+ }),
+ };
+
+ getDataFromLocalStorageStub.callsFake(
+ (key) => localStorageDataSamePage[key],
+ );
+ const cappedRequestsSamePage = spec.buildRequests(bids, bidderRequest);
+
+ it('should not participate if capped on same page', function () {
+ expect(cappedRequestsSamePage.length).to.equal(0);
+ });
+
+ const localStorageDataOtherPage = {
+ [`missena.missena.capper.remove-bubble.${bid.params.apiKey}`]:
+ JSON.stringify({
+ expiry: new Date().getTime() + 600_000, // 10 min into the future
+ referer: REFERRER2,
+ }),
+ };
+
+ getDataFromLocalStorageStub.callsFake(
+ (key) => localStorageDataOtherPage[key],
+ );
+ const cappedRequestsOtherPage = spec.buildRequests(bids, bidderRequest);
+
+ it('should participate if capped on a different page', function () {
+ expect(cappedRequestsOtherPage.length).to.equal(2);
+ });
+
+ it('should send the prebid version', function () {
+ expect(payload.version).to.equal('$prebid.version$');
+ });
+
+ it('should send cookie deprecation', function () {
+ expect(payload.cdep).to.equal(COOKIE_DEPRECATION_LABEL);
+ });
});
describe('interpretResponse', function () {
diff --git a/test/spec/modules/mygaruIdSystem_spec.js b/test/spec/modules/mygaruIdSystem_spec.js
new file mode 100644
index 00000000000..2bfb5fdd4af
--- /dev/null
+++ b/test/spec/modules/mygaruIdSystem_spec.js
@@ -0,0 +1,62 @@
+import { mygaruIdSubmodule } from 'modules/mygaruIdSystem.js';
+import { server } from '../../mocks/xhr';
+
+describe('MygaruID module', function () {
+ it('should respond with async callback and get valid id', async () => {
+ const callBackSpy = sinon.spy();
+ const expectedUrl = `https://ident.mygaru.com/v2/id?gdprApplies=0`;
+ const result = mygaruIdSubmodule.getId({});
+
+ expect(result.callback).to.be.an('function');
+ const promise = result.callback(callBackSpy);
+
+ const request = server.requests[0];
+ expect(request.url).to.be.eq(expectedUrl);
+
+ request.respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ JSON.stringify({ iuid: '123' })
+ );
+ await promise;
+
+ expect(callBackSpy.calledOnce).to.be.true;
+ expect(callBackSpy.calledWith({mygaruId: '123'})).to.be.true;
+ });
+ it('should not fail on error', async () => {
+ const callBackSpy = sinon.spy();
+ const expectedUrl = `https://ident.mygaru.com/v2/id?gdprApplies=0`;
+ const result = mygaruIdSubmodule.getId({});
+
+ expect(result.callback).to.be.an('function');
+ const promise = result.callback(callBackSpy);
+
+ const request = server.requests[0];
+ expect(request.url).to.be.eq(expectedUrl);
+
+ request.respond(
+ 500,
+ {},
+ ''
+ );
+ await promise;
+
+ expect(callBackSpy.calledOnce).to.be.true;
+ expect(callBackSpy.calledWith({mygaruId: undefined})).to.be.true;
+ });
+
+ it('should not modify while decoding', () => {
+ const id = '222';
+ const newId = mygaruIdSubmodule.decode(id)
+
+ expect(id).to.eq(newId);
+ })
+ it('should buildUrl with consent data', () => {
+ const result = mygaruIdSubmodule.getId({}, {
+ gdprApplies: true,
+ consentString: 'consentString'
+ });
+
+ expect(result.url).to.eq('https://ident.mygaru.com/v2/id?gdprApplies=1&gdprConsentString=consentString');
+ })
+});
diff --git a/test/spec/modules/nextMillenniumBidAdapter_spec.js b/test/spec/modules/nextMillenniumBidAdapter_spec.js
index 564788c8b56..b9871bbbe71 100644
--- a/test/spec/modules/nextMillenniumBidAdapter_spec.js
+++ b/test/spec/modules/nextMillenniumBidAdapter_spec.js
@@ -1,32 +1,550 @@
import { expect } from 'chai';
-import { spec } from 'modules/nextMillenniumBidAdapter.js';
+import {
+ getImp,
+ replaceUsersyncMacros,
+ setConsentStrings,
+ setOrtb2Parameters,
+ setEids,
+ spec,
+} from 'modules/nextMillenniumBidAdapter.js';
+
+describe('nextMillenniumBidAdapterTests', () => {
+ describe('function getImp', () => {
+ const dataTests = [
+ {
+ title: 'imp - banner',
+ data: {
+ id: '123',
+ bid: {
+ mediaTypes: {banner: {sizes: [[300, 250], [320, 250]]}},
+ adUnitCode: 'test-banner-1',
+ },
+
+ mediaTypes: {
+ banner: {
+ data: {sizes: [[300, 250], [320, 250]]},
+ bidfloorcur: 'EUR',
+ bidfloor: 1.11,
+ },
+ },
+ },
-describe('nextMillenniumBidAdapterTests', function() {
- const bidRequestData = [
- {
- adUnitCode: 'test-div',
- bidId: 'bid1234',
- auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917',
- bidder: 'nextMillennium',
- params: { placement_id: '-1' },
- sizes: [[300, 250]],
- uspConsent: '1---',
- gdprConsent: {
- consentString: 'kjfdniwjnifwenrif3',
- gdprApplies: true
+ expected: {
+ id: 'test-banner-1',
+ bidfloorcur: 'EUR',
+ bidfloor: 1.11,
+ ext: {prebid: {storedrequest: {id: '123'}}},
+ banner: {format: [{w: 300, h: 250}, {w: 320, h: 250}]},
+ },
},
- ortb2: {
- device: {
- w: 1500,
- h: 1000
+
+ {
+ title: 'imp - video',
+ data: {
+ id: '234',
+ bid: {
+ mediaTypes: {video: {playerSize: [400, 300]}},
+ adUnitCode: 'test-video-1',
+ },
+
+ mediaTypes: {
+ video: {
+ data: {playerSize: [400, 300]},
+ bidfloorcur: 'USD',
+ },
+ },
},
- site: {
- domain: 'example.com',
- page: 'http://example.com'
- }
+
+ expected: {
+ id: 'test-video-1',
+ bidfloorcur: 'USD',
+ ext: {prebid: {storedrequest: {id: '234'}}},
+ video: {w: 400, h: 300},
+ },
+ },
+ ];
+
+ for (let {title, data, expected} of dataTests) {
+ it(title, () => {
+ const {bid, id, mediaTypes} = data;
+ const imp = getImp(bid, id, mediaTypes);
+ expect(imp).to.deep.equal(expected);
+ });
+ }
+ });
+
+ describe('function setConsentStrings', () => {
+ const dataTests = [
+ {
+ title: 'full: uspConsent, gdprConsent and gppConsent',
+ data: {
+ postBody: {},
+ bidderRequest: {
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: true},
+ ortb2: {regs: {gpp: 'DSFHFHWEUYVDC', gpp_sid: [8, 9, 10]}},
+ },
+ },
+
+ expected: {
+ user: {ext: {consent: 'kjfdniwjnifwenrif3'}},
+ regs: {
+ gpp: 'DBACNYA~CPXxRfAPXxR',
+ gpp_sid: [7],
+ ext: {gdpr: 1, us_privacy: '1---'},
+ },
+ },
+ },
+
+ {
+ title: 'gdprConsent(false) and ortb2(gpp)',
+ data: {
+ postBody: {},
+ bidderRequest: {
+ gdprConsent: {consentString: 'ewtewbefbawyadexv', gdprApplies: false},
+ ortb2: {regs: {gpp: 'DSFHFHWEUYVDC', gpp_sid: [8, 9, 10]}},
+ },
+ },
+
+ expected: {
+ user: {ext: {consent: 'ewtewbefbawyadexv'}},
+ regs: {
+ gpp: 'DSFHFHWEUYVDC',
+ gpp_sid: [8, 9, 10],
+ ext: {gdpr: 0},
+ },
+ },
+ },
+
+ {
+ title: 'gdprConsent(false)',
+ data: {
+ postBody: {},
+ bidderRequest: {gdprConsent: {gdprApplies: false}},
+ },
+
+ expected: {
+ regs: {ext: {gdpr: 0}},
+ },
+ },
+
+ {
+ title: 'empty',
+ data: {
+ postBody: {},
+ bidderRequest: {},
+ },
+
+ expected: {},
+ },
+ ];
+
+ for (let {title, data, expected} of dataTests) {
+ it(title, () => {
+ const {postBody, bidderRequest} = data;
+ setConsentStrings(postBody, bidderRequest);
+ expect(postBody).to.deep.equal(expected);
+ });
+ }
+ });
+
+ describe('function replaceUsersyncMacros', () => {
+ const dataTests = [
+ {
+ title: 'url with all macroses - consents full: uspConsent, gdprConsent and gppConsent',
+ data: {
+ url: 'https://some.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&type={{.TYPE_PIXEL}}',
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7, 8]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: true},
+ type: 'image',
+ },
+
+ expected: 'https://some.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8&type=image',
+ },
+
+ {
+ title: 'url with some macroses - consents full: uspConsent, gdprConsent and gppConsent',
+ data: {
+ url: 'https://some.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&type={{.TYPE_PIXEL}}',
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7, 8]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: false},
+ type: 'iframe',
+ },
+
+ expected: 'https://some.url?gdpr=0&gdpr_consent=kjfdniwjnifwenrif3&type=iframe',
+ },
+
+ {
+ title: 'url without macroses - consents full: uspConsent, gdprConsent and gppConsent',
+ data: {
+ url: 'https://some.url?param1=value1¶m2=value2',
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7, 8]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: false},
+ type: 'iframe',
+ },
+
+ expected: 'https://some.url?param1=value1¶m2=value2',
+ },
+
+ {
+ title: 'url with all macroses - consents are empty',
+ data: {
+ url: 'https://some.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&type={{.TYPE_PIXEL}}',
+ },
+
+ expected: 'https://some.url?gdpr=0&gdpr_consent=&us_privacy=&gpp=&gpp_sid=&type=',
+ },
+ ];
+
+ for (let {title, data, expected} of dataTests) {
+ it(title, () => {
+ const {url, gdprConsent, uspConsent, gppConsent, type} = data;
+ const newUrl = replaceUsersyncMacros(url, gdprConsent, uspConsent, gppConsent, type);
+ expect(newUrl).to.equal(expected);
+ });
+ }
+ });
+
+ describe('function spec.getUserSyncs', () => {
+ const dataTests = [
+ {
+ title: 'pixels from responses ({iframeEnabled: true, pixelEnabled: true})',
+ data: {
+ syncOptions: {iframeEnabled: true, pixelEnabled: true},
+ responses: [
+ {body: {ext: {sync: {
+ image: [
+ 'https://some.1.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.2.url?us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.3.url?param=1234',
+ ],
+
+ iframe: [
+ 'https://some.4.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.5.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}',
+ ],
+ }}}},
+
+ {body: {ext: {sync: {
+ iframe: [
+ 'https://some.6.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.7.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}',
+ ],
+ }}}},
+
+ {body: {ext: {sync: {
+ image: [
+ 'https://some.8.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ ],
+ }}}},
+ ],
+
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7, 8]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: true},
+ },
+
+ expected: [
+ {type: 'image', url: 'https://some.1.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8'},
+ {type: 'image', url: 'https://some.2.url?us_privacy=1---&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8'},
+ {type: 'image', url: 'https://some.3.url?param=1234'},
+ {type: 'iframe', url: 'https://some.4.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8'},
+ {type: 'iframe', url: 'https://some.5.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---'},
+ {type: 'iframe', url: 'https://some.6.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8'},
+ {type: 'iframe', url: 'https://some.7.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---'},
+ {type: 'image', url: 'https://some.8.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8'},
+ ],
+ },
+
+ {
+ title: 'pixels from responses ({iframeEnabled: true, pixelEnabled: false})',
+ data: {
+ syncOptions: {iframeEnabled: true, pixelEnabled: false},
+ responses: [
+ {body: {ext: {sync: {
+ image: [
+ 'https://some.1.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.2.url?us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.3.url?param=1234',
+ ],
+
+ iframe: [
+ 'https://some.4.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.5.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}',
+ ],
+ }}}},
+ ],
+
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7, 8]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: true},
+ },
+
+ expected: [
+ {type: 'iframe', url: 'https://some.4.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8'},
+ {type: 'iframe', url: 'https://some.5.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---'},
+ ],
+ },
+
+ {
+ title: 'pixels from responses ({iframeEnabled: false, pixelEnabled: true})',
+ data: {
+ syncOptions: {iframeEnabled: false, pixelEnabled: true},
+ responses: [
+ {body: {ext: {sync: {
+ image: [
+ 'https://some.1.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.2.url?us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.3.url?param=1234',
+ ],
+
+ iframe: [
+ 'https://some.4.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}',
+ 'https://some.5.url?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}',
+ ],
+ }}}},
+ ],
+
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7, 8]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: true},
+ },
+
+ expected: [
+ {type: 'image', url: 'https://some.1.url?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8'},
+ {type: 'image', url: 'https://some.2.url?us_privacy=1---&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8'},
+ {type: 'image', url: 'https://some.3.url?param=1234'},
+ ],
+ },
+
+ {
+ title: 'pixels - responses is empty ({iframeEnabled: true, pixelEnabled: true})',
+ data: {
+ syncOptions: {iframeEnabled: true, pixelEnabled: true},
+ responses: [],
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7, 8]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: true},
+ },
+
+ expected: [
+ {type: 'image', url: 'https://cookies.nextmillmedia.com/sync?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8&type=image'},
+ {type: 'iframe', url: 'https://cookies.nextmillmedia.com/sync?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8&type=iframe'},
+ ],
+ },
+
+ {
+ title: 'pixels - responses is empty ({iframeEnabled: true, pixelEnabled: false})',
+ data: {
+ syncOptions: {iframeEnabled: true, pixelEnabled: false},
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7, 8]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: true},
+ },
+
+ expected: [
+ {type: 'iframe', url: 'https://cookies.nextmillmedia.com/sync?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---&gpp=DBACNYA~CPXxRfAPXxR&gpp_sid=7,8&type=iframe'},
+ ],
+ },
+
+ {
+ title: 'pixels - responses is empty ({iframeEnabled: false, pixelEnabled: false})',
+ data: {
+ syncOptions: {iframeEnabled: false, pixelEnabled: false},
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7, 8]},
+ gdprConsent: {consentString: 'kjfdniwjnifwenrif3', gdprApplies: true},
+ },
+
+ expected: [],
+ },
+ ];
+
+ for (let {title, data, expected} of dataTests) {
+ it(title, () => {
+ const {syncOptions, responses, gdprConsent, uspConsent, gppConsent} = data;
+ const pixels = spec.getUserSyncs(syncOptions, responses, gdprConsent, uspConsent, gppConsent);
+ expect(pixels).to.deep.equal(expected);
+ });
+ }
+ });
+
+ describe('function setOrtb2Parameters', () => {
+ const dataTests = [
+ {
+ title: 'site.pagecat, site.content.cat and site.content.language',
+ data: {
+ postBody: {},
+ ortb2: {site: {
+ pagecat: ['IAB2-11', 'IAB2-12', 'IAB2-14'],
+ content: {cat: ['IAB2-11', 'IAB2-12', 'IAB2-14'], language: 'EN'},
+ }},
+ },
+
+ expected: {site: {
+ pagecat: ['IAB2-11', 'IAB2-12', 'IAB2-14'],
+ content: {cat: ['IAB2-11', 'IAB2-12', 'IAB2-14'], language: 'EN'},
+ }},
+ },
+
+ {
+ title: 'site.keywords, site.content.keywords and user.keywords',
+ data: {
+ postBody: {},
+ ortb2: {
+ user: {keywords: 'key7,key8,key9'},
+ site: {
+ keywords: 'key1,key2,key3',
+ content: {keywords: 'key4,key5,key6'},
+ },
+ },
+ },
+
+ expected: {
+ user: {keywords: 'key7,key8,key9'},
+ site: {
+ keywords: 'key1,key2,key3',
+ content: {keywords: 'key4,key5,key6'},
+ },
+ },
+ },
+
+ {
+ title: 'only site.content.language',
+ data: {
+ postBody: {site: {domain: 'some.domain'}},
+ ortb2: {site: {
+ content: {language: 'EN'},
+ }},
+ },
+
+ expected: {site: {
+ domain: 'some.domain',
+ content: {language: 'EN'},
+ }},
+ },
+
+ {
+ title: 'object ortb2 is empty',
+ data: {
+ postBody: {imp: []},
+ },
+
+ expected: {imp: []},
+ },
+ ];
+
+ for (let {title, data, expected} of dataTests) {
+ it(title, () => {
+ const {postBody, ortb2} = data;
+ setOrtb2Parameters(postBody, ortb2);
+ expect(postBody).to.deep.equal(expected);
+ });
+ };
+ });
+
+ describe('function setEids', () => {
+ const dataTests = [
+ {
+ title: 'setEids - userIdAsEids is empty',
+ data: {
+ postBody: {},
+ bid: {
+ userIdAsEids: undefined,
+ },
+ },
+
+ expected: {},
+ },
+
+ {
+ title: 'setEids - userIdAsEids - array is empty',
+ data: {
+ postBody: {},
+ bid: {
+ userIdAsEids: [],
+ },
+ },
+
+ expected: {},
+ },
+
+ {
+ title: 'setEids - userIdAsEids is',
+ data: {
+ postBody: {},
+ bid: {
+ userIdAsEids: [
+ {
+ source: '33across.com',
+ uids: [{id: 'some-random-id-value', atype: 1}],
+ },
+
+ {
+ source: 'utiq.com',
+ uids: [{id: 'some-random-id-value', atype: 1}],
+ },
+ ],
+ },
+ },
+
+ expected: {
+ user: {
+ eids: [
+ {
+ source: '33across.com',
+ uids: [{id: 'some-random-id-value', atype: 1}],
+ },
+
+ {
+ source: 'utiq.com',
+ uids: [{id: 'some-random-id-value', atype: 1}],
+ },
+ ],
+ },
+ },
+ },
+ ];
+
+ for (let { title, data, expected } of dataTests) {
+ it(title, () => {
+ const { postBody, bid } = data;
+ setEids(postBody, bid);
+ expect(postBody).to.deep.equal(expected);
+ });
+ }
+ });
+
+ const bidRequestData = [{
+ adUnitCode: 'test-div',
+ bidId: 'bid1234',
+ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917',
+ bidder: 'nextMillennium',
+ params: { placement_id: '-1' },
+ sizes: [[300, 250]],
+ uspConsent: '1---',
+ gppConsent: {gppString: 'DBACNYA~CPXxRfAPXxR', applicableSections: [7]},
+ gdprConsent: {
+ consentString: 'kjfdniwjnifwenrif3',
+ gdprApplies: true
+ },
+
+ ortb2: {
+ device: {
+ w: 1500,
+ h: 1000
+ },
+
+ site: {
+ domain: 'example.com',
+ page: 'http://example.com'
}
}
- ];
+ }];
const serverResponse = {
body: {
@@ -49,7 +567,7 @@ describe('nextMillenniumBidAdapterTests', function() {
cur: 'USD',
ext: {
sync: {
- image: ['urlA?gdpr={{.GDPR}}'],
+ image: ['urlA?gdpr={{.GDPR}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}'],
iframe: ['urlB'],
}
}
@@ -117,61 +635,6 @@ describe('nextMillenniumBidAdapterTests', function() {
},
];
- it('Request params check with GDPR and USP Consent', function () {
- const request = spec.buildRequests(bidRequestData, bidRequestData[0]);
- expect(JSON.parse(request[0].data).user.ext.consent).to.equal('kjfdniwjnifwenrif3');
- expect(JSON.parse(request[0].data).regs.ext.us_privacy).to.equal('1---');
- expect(JSON.parse(request[0].data).regs.ext.gdpr).to.equal(1);
- });
-
- it('Test getUserSyncs function', function () {
- const syncOptions = {
- 'iframeEnabled': false,
- 'pixelEnabled': true
- }
- let userSync = spec.getUserSyncs(syncOptions, [serverResponse], bidRequestData[0].gdprConsent, bidRequestData[0].uspConsent);
- expect(userSync).to.be.an('array').with.lengthOf(1);
- expect(userSync[0].type).to.equal('image');
- expect(userSync[0].url).to.equal('urlA?gdpr=1');
-
- syncOptions.iframeEnabled = true;
- syncOptions.pixelEnabled = false;
- userSync = spec.getUserSyncs(syncOptions, [serverResponse], bidRequestData[0].gdprConsent, bidRequestData[0].uspConsent);
- expect(userSync).to.be.an('array').with.lengthOf(1);
- expect(userSync[0].type).to.equal('iframe');
- expect(userSync[0].url).to.equal('urlB');
- });
-
- it('Test getUserSyncs with no response', function () {
- const syncOptions = {
- 'iframeEnabled': true,
- 'pixelEnabled': false
- }
- let userSync = spec.getUserSyncs(syncOptions, [], bidRequestData[0].gdprConsent, bidRequestData[0].uspConsent);
- expect(userSync).to.be.an('array')
- expect(userSync[0].type).to.equal('iframe')
- expect(userSync[0].url).to.equal('https://cookies.nextmillmedia.com/sync?gdpr=1&gdpr_consent=kjfdniwjnifwenrif3&us_privacy=1---&type=iframe')
- })
-
- it('Test getUserSyncs function if GDPR is undefined', function () {
- const syncOptions = {
- 'iframeEnabled': false,
- 'pixelEnabled': true
- }
-
- let userSync = spec.getUserSyncs(syncOptions, [serverResponse], undefined, bidRequestData[0].uspConsent);
- expect(userSync).to.be.an('array').with.lengthOf(1);
- expect(userSync[0].type).to.equal('image');
- expect(userSync[0].url).to.equal('urlA?gdpr=0');
- });
-
- it('Request params check without GDPR Consent', function () {
- delete bidRequestData[0].gdprConsent
- const request = spec.buildRequests(bidRequestData, bidRequestData[0]);
- expect(JSON.parse(request[0].data).regs.ext.gdpr).to.be.undefined;
- expect(JSON.parse(request[0].data).regs.ext.us_privacy).to.equal('1---');
- });
-
it('validate_generated_params', function() {
const request = spec.buildRequests(bidRequestData, {bidderRequestId: 'mock-uuid'});
expect(request[0].bidId).to.equal('bid1234');
@@ -190,7 +653,7 @@ describe('nextMillenniumBidAdapterTests', function() {
it('Check if refresh_count param is incremented', function() {
const request = spec.buildRequests(bidRequestData);
- expect(JSON.parse(request[0].data).ext.nextMillennium.refresh_count).to.equal(3);
+ expect(JSON.parse(request[0].data).ext.nextMillennium.refresh_count).to.equal(1);
});
it('Check if domain was added', function() {
diff --git a/test/spec/modules/nobidAnalyticsAdapter_spec.js b/test/spec/modules/nobidAnalyticsAdapter_spec.js
index 742b4c16abb..3da334eea97 100644
--- a/test/spec/modules/nobidAnalyticsAdapter_spec.js
+++ b/test/spec/modules/nobidAnalyticsAdapter_spec.js
@@ -344,7 +344,6 @@ describe('NoBid Prebid Analytic', function () {
bidderRequestId: '7c1940bb285731',
bids: [
{
- bidder: 'nobid',
params: { siteId: SITE_ID },
mediaTypes: { banner: { sizes: [[728, 90]] } },
adUnitCode: 'leaderboard',
@@ -390,19 +389,28 @@ describe('NoBid Prebid Analytic', function () {
const auctionEndRequest = JSON.parse(server.requests[0].requestBody);
expect(auctionEndRequest).to.have.property('auctionId', requestOutgoing.auctionId);
expect(auctionEndRequest.bidderRequests).to.have.length(1);
- expect(auctionEndRequest.bidderRequests[0]).to.have.property('bidderCode', requestOutgoing.bidderRequests[0].bidderCode);
+ expect(auctionEndRequest.bidderRequests[0].bidderCode).to.equal(requestOutgoing.bidderRequests[0].bidderCode);
expect(auctionEndRequest.bidderRequests[0].bids).to.have.length(1);
- expect(auctionEndRequest.bidderRequests[0].bids[0]).to.have.property('bidder', requestOutgoing.bidderRequests[0].bids[0].bidder);
- expect(auctionEndRequest.bidderRequests[0].bids[0]).to.have.property('adUnitCode', requestOutgoing.bidderRequests[0].bids[0].adUnitCode);
- expect(auctionEndRequest.bidderRequests[0].bids[0].params).to.have.property('siteId', requestOutgoing.bidderRequests[0].bids[0].params.siteId);
- expect(auctionEndRequest.bidderRequests[0].refererInfo).to.have.property('topmostLocation', requestOutgoing.bidderRequests[0].refererInfo.topmostLocation);
+ expect(typeof auctionEndRequest.bidderRequests[0].bids[0].bidder).to.equal('undefined');
+ expect(auctionEndRequest.bidderRequests[0].bids[0].adUnitCode).to.equal(requestOutgoing.bidderRequests[0].bids[0].adUnitCode);
+ expect(typeof auctionEndRequest.bidderRequests[0].bids[0].params).to.equal('undefined');
+ expect(typeof auctionEndRequest.bidderRequests[0].bids[0].src).to.equal('undefined');
+ expect(auctionEndRequest.bidderRequests[0].refererInfo.topmostLocation).to.equal(requestOutgoing.bidderRequests[0].refererInfo.topmostLocation);
+ expect(auctionEndRequest.bidsReceived).to.have.length(1);
+ expect(auctionEndRequest.bidsReceived[0].bidderCode).to.equal(requestOutgoing.bidsReceived[0].bidderCode);
+ expect(auctionEndRequest.bidsReceived[0].width).to.equal(requestOutgoing.bidsReceived[0].width);
+ expect(auctionEndRequest.bidsReceived[0].height).to.equal(requestOutgoing.bidsReceived[0].height);
+ expect(auctionEndRequest.bidsReceived[0].mediaType).to.equal(requestOutgoing.bidsReceived[0].mediaType);
+ expect(auctionEndRequest.bidsReceived[0].cpm).to.equal(requestOutgoing.bidsReceived[0].cpm);
+ expect(auctionEndRequest.bidsReceived[0].adUnitCode).to.equal(requestOutgoing.bidsReceived[0].adUnitCode);
+ expect(typeof auctionEndRequest.bidsReceived[0].source).to.equal('undefined');
done();
});
it('Analytics disabled test', function (done) {
let disabled;
- nobidAnalytics.processServerResponse(JSON.stringify({disabled: false}));
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled: 0}));
disabled = nobidAnalytics.isAnalyticsDisabled();
expect(disabled).to.equal(false);
events.emit(constants.EVENTS.AUCTION_END, {auctionId: '1234567890'});
@@ -417,7 +425,7 @@ describe('NoBid Prebid Analytic', function () {
clock.tick(1000);
expect(server.requests).to.have.length(3);
- nobidAnalytics.processServerResponse(JSON.stringify({disabled: true}));
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled: 1}));
disabled = nobidAnalytics.isAnalyticsDisabled();
expect(disabled).to.equal(true);
events.emit(constants.EVENTS.AUCTION_END, {auctionId: '12345678902'});
@@ -425,7 +433,7 @@ describe('NoBid Prebid Analytic', function () {
expect(server.requests).to.have.length(3);
nobidAnalytics.retentionSeconds = 5;
- nobidAnalytics.processServerResponse(JSON.stringify({disabled: true}));
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled: 1}));
clock.tick(1000);
disabled = nobidAnalytics.isAnalyticsDisabled();
expect(disabled).to.equal(true);
@@ -437,6 +445,100 @@ describe('NoBid Prebid Analytic', function () {
});
});
+ describe('Analytics disabled event type test', function () {
+ beforeEach(function () {
+ sinon.stub(events, 'getEvents').returns([]);
+ clock = sinon.useFakeTimers(Date.now());
+ });
+
+ afterEach(function () {
+ events.getEvents.restore();
+ clock.restore();
+ });
+
+ after(function () {
+ nobidAnalytics.disableAnalytics();
+ });
+
+ it('Analytics disabled event type test', function (done) {
+ // Initialize adapter
+ const initOptions = { options: { siteId: SITE_ID } };
+ nobidAnalytics.enableAnalytics(initOptions);
+ adapterManager.enableAnalytics({ provider: 'nobid', options: initOptions });
+
+ let eventType = constants.EVENTS.AUCTION_END;
+ let disabled;
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled: 0}));
+ disabled = nobidAnalytics.isAnalyticsDisabled();
+ expect(disabled).to.equal(false);
+ events.emit(eventType, {auctionId: '1234567890'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(1);
+ events.emit(eventType, {auctionId: '12345678901'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(2);
+
+ server.requests.length = 0;
+ expect(server.requests).to.have.length(0);
+
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled_auctionEnd: 1}));
+ disabled = nobidAnalytics.isAnalyticsDisabled(eventType);
+ expect(disabled).to.equal(true);
+ events.emit(eventType, {auctionId: '1234567890'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(0);
+
+ server.requests.length = 0;
+
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled_auctionEnd: 0}));
+ disabled = nobidAnalytics.isAnalyticsDisabled(eventType);
+ expect(disabled).to.equal(false);
+ events.emit(constants.EVENTS.AUCTION_END, {auctionId: '1234567890'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(1);
+
+ server.requests.length = 0;
+ expect(server.requests).to.have.length(0);
+
+ eventType = constants.EVENTS.BID_WON;
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled_bidWon: 1}));
+ disabled = nobidAnalytics.isAnalyticsDisabled(eventType);
+ expect(disabled).to.equal(true);
+ events.emit(eventType, {bidderCode: 'nobid'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(0);
+
+ server.requests.length = 0;
+ expect(server.requests).to.have.length(0);
+
+ eventType = constants.EVENTS.AUCTION_END;
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled: 1}));
+ disabled = nobidAnalytics.isAnalyticsDisabled(eventType);
+ expect(disabled).to.equal(true);
+ events.emit(eventType, {auctionId: '1234567890'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(0);
+
+ server.requests.length = 0;
+ expect(server.requests).to.have.length(0);
+
+ eventType = constants.EVENTS.AUCTION_END;
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled_auctionEnd: 1, disabled_bidWon: 0}));
+ disabled = nobidAnalytics.isAnalyticsDisabled(eventType);
+ expect(disabled).to.equal(true);
+ events.emit(eventType, {auctionId: '1234567890'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(0);
+ disabled = nobidAnalytics.isAnalyticsDisabled(constants.EVENTS.BID_WON);
+ expect(disabled).to.equal(false);
+ events.emit(constants.EVENTS.BID_WON, {bidderCode: 'nobid'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(1);
+
+ done();
+ });
+ });
+
describe('NoBid Carbonizer', function () {
beforeEach(function () {
sinon.stub(events, 'getEvents').returns([]);
@@ -456,7 +558,8 @@ describe('NoBid Prebid Analytic', function () {
let active = nobidCarbonizer.isActive();
expect(active).to.equal(false);
- active = nobidCarbonizer.isActive(JSON.stringify({carbonizer_active: false}));
+ nobidAnalytics.processServerResponse(JSON.stringify({carbonizer_active: false}));
+ active = nobidCarbonizer.isActive();
expect(active).to.equal(false);
nobidAnalytics.processServerResponse(JSON.stringify({carbonizer_active: true}));
@@ -466,15 +569,15 @@ describe('NoBid Prebid Analytic', function () {
const previousRetention = nobidAnalytics.retentionSeconds;
nobidAnalytics.retentionSeconds = 3;
nobidAnalytics.processServerResponse(JSON.stringify({carbonizer_active: true}));
- const stored = nobidCarbonizer.getStoredLocalData();
- expect(stored).to.contain(`{"carbonizer_active":true,"ts":`);
+ let stored = nobidCarbonizer.getStoredLocalData();
+ expect(stored[nobidAnalytics.ANALYTICS_DATA_NAME]).to.contain(`{"carbonizer_active":true,"ts":`);
clock.tick(5000);
- active = nobidCarbonizer.isActive(adunits, true);
+ active = nobidCarbonizer.isActive();
expect(active).to.equal(false);
nobidAnalytics.retentionSeconds = previousRetention;
nobidAnalytics.processServerResponse(JSON.stringify({carbonizer_active: true}));
- active = nobidCarbonizer.isActive(adunits, true);
+ active = nobidCarbonizer.isActive();
expect(active).to.equal(true);
let adunits = [
@@ -486,6 +589,10 @@ describe('NoBid Prebid Analytic', function () {
}
]
nobidCarbonizer.carbonizeAdunits(adunits, true);
+ stored = nobidCarbonizer.getStoredLocalData();
+ expect(stored[nobidAnalytics.ANALYTICS_DATA_NAME]).to.contain('{"carbonizer_active":true,"ts":');
+ expect(stored[nobidAnalytics.ANALYTICS_OPT_NAME]).to.contain('{"bidder1":1,"bidder2":1}');
+ clock.tick(5000);
expect(adunits[0].bids.length).to.equal(0);
done();
diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js
index 6d43dd2e40e..c3d8a4ee0e1 100644
--- a/test/spec/modules/onetagBidAdapter_spec.js
+++ b/test/spec/modules/onetagBidAdapter_spec.js
@@ -189,7 +189,7 @@ describe('onetag', function () {
});
it('Should contain all keys', function () {
expect(data).to.be.an('object');
- expect(data).to.include.all.keys('location', 'referrer', 'stack', 'numIframes', 'sHeight', 'sWidth', 'docHeight', 'wHeight', 'wWidth', 'oHeight', 'oWidth', 'aWidth', 'aHeight', 'sLeft', 'sTop', 'hLength', 'bids', 'docHidden', 'xOffset', 'yOffset', 'networkConnectionType', 'networkEffectiveConnectionType', 'timing', 'version');
+ expect(data).to.include.all.keys('location', 'referrer', 'stack', 'numIframes', 'sHeight', 'sWidth', 'docHeight', 'wHeight', 'wWidth', 'oHeight', 'oWidth', 'aWidth', 'aHeight', 'sLeft', 'sTop', 'hLength', 'bids', 'docHidden', 'xOffset', 'yOffset', 'networkConnectionType', 'networkEffectiveConnectionType', 'timing', 'version', 'fledgeEnabled');
expect(data.location).to.satisfy(function (value) {
return value === null || typeof value === 'string';
});
@@ -213,6 +213,7 @@ describe('onetag', function () {
expect(data.networkEffectiveConnectionType).to.satisfy(function (value) {
return value === null || typeof value === 'string'
});
+ expect(data.fledgeEnabled).to.be.a('boolean');
expect(data.bids).to.be.an('array');
expect(data.version).to.have.all.keys('prebid', 'adapter');
const bids = data['bids'];
@@ -395,14 +396,90 @@ describe('onetag', function () {
expect(payload.ortb2).to.exist;
expect(payload.ortb2).to.exist.and.to.deep.equal(firtPartyData);
});
+ it('Should send DSA (ortb2 field)', function () {
+ const dsa = {
+ 'regs': {
+ 'ext': {
+ 'dsa': {
+ 'required': 1,
+ 'pubrender': 0,
+ 'datatopub': 1,
+ 'transparency': [{
+ 'domain': 'dsa-domain',
+ 'params': [1, 2]
+ }]
+ }
+ }
+ }
+ };
+ let bidderRequest = {
+ 'bidderCode': 'onetag',
+ 'auctionId': '1d1a030790a475',
+ 'bidderRequestId': '22edbae2733bf6',
+ 'timeout': 3000,
+ 'ortb2': dsa
+ }
+ let serverRequest = spec.buildRequests([bannerBid], bidderRequest);
+ const payload = JSON.parse(serverRequest.data);
+ expect(payload.ortb2).to.exist;
+ expect(payload.ortb2).to.exist.and.to.deep.equal(dsa);
+ });
+ it('Should send FLEDGE eligibility flag when FLEDGE is enabled', function () {
+ let bidderRequest = {
+ 'bidderCode': 'onetag',
+ 'auctionId': '1d1a030790a475',
+ 'bidderRequestId': '22edbae2733bf6',
+ 'timeout': 3000,
+ 'fledgeEnabled': true
+ };
+ let serverRequest = spec.buildRequests([bannerBid], bidderRequest);
+ const payload = JSON.parse(serverRequest.data);
+
+ expect(payload.fledgeEnabled).to.exist;
+ expect(payload.fledgeEnabled).to.exist.and.to.equal(bidderRequest.fledgeEnabled);
+ });
+ it('Should send FLEDGE eligibility flag when FLEDGE is not enabled', function () {
+ let bidderRequest = {
+ 'bidderCode': 'onetag',
+ 'auctionId': '1d1a030790a475',
+ 'bidderRequestId': '22edbae2733bf6',
+ 'timeout': 3000,
+ 'fledgeEnabled': false
+ };
+ let serverRequest = spec.buildRequests([bannerBid], bidderRequest);
+ const payload = JSON.parse(serverRequest.data);
+
+ expect(payload.fledgeEnabled).to.exist;
+ expect(payload.fledgeEnabled).to.exist.and.to.equal(bidderRequest.fledgeEnabled);
+ });
+ it('Should send FLEDGE eligibility flag set to false when fledgeEnabled is not defined', function () {
+ let bidderRequest = {
+ 'bidderCode': 'onetag',
+ 'auctionId': '1d1a030790a475',
+ 'bidderRequestId': '22edbae2733bf6',
+ 'timeout': 3000,
+ };
+ let serverRequest = spec.buildRequests([bannerBid], bidderRequest);
+ const payload = JSON.parse(serverRequest.data);
+
+ expect(payload.fledgeEnabled).to.exist;
+ expect(payload.fledgeEnabled).to.exist.and.to.equal(false);
+ });
});
describe('interpretResponse', function () {
const request = getBannerVideoRequest();
const response = getBannerVideoResponse();
+ const fledgeResponse = getFledgeBannerResponse();
const requestData = JSON.parse(request.data);
it('Returns an array of valid server responses if response object is valid', function () {
const interpretedResponse = spec.interpretResponse(response, request);
+ const fledgeInterpretedResponse = spec.interpretResponse(fledgeResponse, request);
expect(interpretedResponse).to.be.an('array').that.is.not.empty;
+ expect(fledgeInterpretedResponse).to.be.an('object');
+ expect(fledgeInterpretedResponse.bids).to.satisfy(function (value) {
+ return value === null || Array.isArray(value);
+ });
+ expect(fledgeInterpretedResponse.fledgeAuctionConfigs).to.be.an('array').that.is.not.empty;
for (let i = 0; i < interpretedResponse.length; i++) {
let dataItem = interpretedResponse[i];
expect(dataItem).to.include.all.keys('requestId', 'cpm', 'width', 'height', 'ttl', 'creativeId', 'netRevenue', 'currency', 'meta', 'dealId');
@@ -437,6 +514,21 @@ describe('onetag', function () {
const serverResponses = spec.interpretResponse('invalid_response', { data: '{}' });
expect(serverResponses).to.be.an('array').that.is.empty;
});
+ it('Returns meta dsa field if dsa field is present in response', function () {
+ const dsaResponseObj = {
+ 'behalf': 'Advertiser',
+ 'paid': 'Advertiser',
+ 'transparency': {
+ 'domain': 'dsp1domain.com',
+ 'params': [1, 2]
+ },
+ 'adrender': 1
+ };
+ const responseWithDsa = {...response};
+ responseWithDsa.body.bids.forEach(bid => bid.dsa = {...dsaResponseObj});
+ const serverResponse = spec.interpretResponse(responseWithDsa, request);
+ serverResponse.forEach(bid => expect(bid.meta.dsa).to.deep.equals(dsaResponseObj));
+ });
});
describe('getUserSyncs', function () {
const sync_endpoint = 'https://onetag-sys.com/usync/';
@@ -600,6 +692,24 @@ function getBannerVideoResponse() {
};
}
+function getFledgeBannerResponse() {
+ const bannerVideoResponse = getBannerVideoResponse();
+ bannerVideoResponse.body.fledgeAuctionConfigs = [
+ {
+ bidId: 'fledge',
+ config: {
+ seller: 'https://onetag-sys.com',
+ decisionLogicUrl:
+ 'https://onetag-sys.com/paapi/decision_logic.js',
+ interestGroupBuyers: [
+ 'https://onetag-sys.com'
+ ],
+ }
+ }
+ ]
+ return bannerVideoResponse;
+}
+
function getBannerVideoRequest() {
return {
data: JSON.stringify({
diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js
index 1af0fce103d..7c504bca50b 100644
--- a/test/spec/modules/openxBidAdapter_spec.js
+++ b/test/spec/modules/openxBidAdapter_spec.js
@@ -1508,6 +1508,25 @@ describe('OpenxRtbAdapter', function () {
expect(response.fledgeAuctionConfigs.length).to.equal(1);
expect(response.fledgeAuctionConfigs[0].bidId).to.equal('test-bid-id');
});
+
+ it('should inject ortb2Imp in auctionSignals', function () {
+ const auctionConfig = response.fledgeAuctionConfigs[0].config;
+ expect(auctionConfig).to.deep.include({
+ auctionSignals: {
+ ortb2Imp: {
+ id: 'test-bid-id',
+ tagid: '12345678',
+ banner: {
+ topframe: 0,
+ format: bidRequestConfigs[0].mediaTypes.banner.sizes.map(([w, h]) => ({w, h}))
+ },
+ ext: {
+ divid: 'adunit-code',
+ }
+ }
+ }
+ });
+ })
});
});
diff --git a/test/spec/modules/pangleBidAdapter_spec.js b/test/spec/modules/pangleBidAdapter_spec.js
index 94f5a6e4b1d..6d8f9a66bcf 100644
--- a/test/spec/modules/pangleBidAdapter_spec.js
+++ b/test/spec/modules/pangleBidAdapter_spec.js
@@ -1,6 +1,5 @@
import { expect } from 'chai';
import { spec } from 'modules/pangleBidAdapter.js';
-import { logInfo } from '../../../src/utils';
const REQUEST = [{
adUnitCode: 'adUnitCode1',
@@ -84,6 +83,7 @@ const RESPONSE = {
'cat': [],
'w': 300,
'h': 250,
+ 'mtype': 1,
'ext': {
'prebid': {
'type': 'banner'
@@ -186,26 +186,6 @@ describe('pangle bid adapter', function () {
expect(deviceType).to.equal(2);
});
});
-
- // describe('video', function () {
- // it('video config', function() {
- // logInfo(spec.buildRequests(VIDEO_REQUEST, DEFAULT_OPTIONS)[0].data, 'spec.buildRequests(videoConfig, DEFAULT_OPTIONS)[0].data.imp[0]');
- // const request = spec.buildRequests(VIDEO_REQUEST, DEFAULT_OPTIONS)[0];
-
- // expect(request).to.exist.and.to.be.a('object');
- // const payload = request.data;
- // expect(payload).to.exist.and.to.be.a('object');
- // const video = payload.imp[0].video;
- // expect(video).to.exist.and.to.be.a('object');
- // // console.log(video, 'video???')
- // // expect(url).to.equal('https://pangle.pangleglobal.com/api/ad/union/web_js/common/get_ads');
- // // assert.deepEqual(video, {
- // // h: 380,
- // // mimes: ['video/mp4'],
- // // w: 240
- // // })
- // })
- // })
});
describe('Pangle Adapter with video', function() {
@@ -247,6 +227,7 @@ describe('Pangle Adapter with video', function() {
],
'w': 640,
'h': 640,
+ 'mtype': 1,
'ext': {
'pangle': {
'adtype': 8
@@ -293,3 +274,114 @@ describe('Pangle Adapter with video', function() {
});
});
});
+
+describe('pangle multi-format ads', function () {
+ const bidderRequest = {
+ refererInfo: {
+ referer: 'https://example.com'
+ }
+ };
+ const multiRequest = [
+ {
+ bidId: '2820132fe18114',
+ mediaTypes: { banner: { sizes: [[300, 250]] }, video: { context: 'outstream', playerSize: [[300, 250]] } },
+ params: { token: 'test-token' }
+ }
+ ];
+ const videoResponse = {
+ 'headers': null,
+ 'body': {
+ 'id': '233f1693-68d1-470a-ad85-c156c3faaf6f',
+ 'seatbid': [
+ {
+ 'bid': [
+ {
+ 'id': '2820132fe18114',
+ 'impid': '2820132fe18114',
+ 'price': 0.03294,
+ 'nurl': 'https://api16-event-sg2.pangle.io/api/ad/union/openrtb/win/?req_id=233f1693-68d1-470a-ad85-c156c3faaf6fu1450&ttdsp_adx_index=256&rit=980589944&extra=oqveoB%2Bg4%2ByNz9L8wwu%2Fy%2FwKxQsGaKsJHuB4NMK77uqZ9%2FJKpnsVZculJX8%2FxrRBAtaktU1DRN%2Fy6TKAqibCbj%2FM3%2BZ6biAKQG%2BCyt4eIV0KVvri9jCCnaajbkN7YNJWJJw2lW6cJ6Va3SuJG9H7a%2FAJd2PMbhK7fXWhoW72TwgOcKHKBgjM6sNDISBKbWlZyY3L1PhKSX%2FM8LOvL6qahsb%2FDpEObIx24vhQLNWp28XY1L4UqeibuRjam3eCvN7nXoQq74KkJ45QQsTgvV4j6I6EbLOdjOi%2FURhWMDjUD1VCMpqUT%2B6L8ZROgrX9Tp53eJ3bFOczmSTOmDSazKMHa%2B3uZZ7JHcSx32eoY4hfYc99NOJmYBKXNKCmoXyJvS3PCM3PlAz97hKrDMGnVv1wAQ7QGDCbittF0vZwtsRAvvx2mWINNIB3%2FUB2PjhxFsoDA%2BWE2urVZwEdyu%2FJrCznJsMwenXjcbMD5jmUF5vDkkLS%2B7TMDIEawJPJKZ62pK35enrwGxCs6ePXi21rJJkA0bF8tgAdl4mU1illBIVO4kCL%2ByRASskHPjgg%2FcdFe9HP%2Fi8byjAprH%2BhRerN%2FRKFxC3xv8b75x2pb1g7dY%2FTj9IjT0evsBSPVwFNqtKmPId35IcY%2FSXiqPHh%2FrAHZzr5BPsTT19P49SlNMR9UZYTzViX1iJpcCL1UFjuDdrdff%2BhHCviXxo%2FkRmufEF3umHZwxbdDOPAghuZ0DtRCY6S1rnb%2FK9BbpsVKSndOtgfCwMHFwiPmdw1XjEXGc1eOWXY6qfSp90PIfL6WS7Neh3ba2qMv6WxG3HSOBYvrcCqVTsNxk4UdVm3qb1J0CMVByweTMo45usSkCTdvX3JuEB7tVA6%2BrEk57b3XJd5Phf2AN8hon%2F7lmcXE41kwMQuXq89ViwQmW0G247UFWOQx4t1cmBqFiP6qNA%2F%2BunkZDno1pmAsGnTv7Mz9xtpOaIqKl8BKrVQSTopZ9WcUVzdBUutF19mn1f43BvyA9gIEhcDJHOj&win_price=${AUCTION_PRICE}&auction_mwb=${AUCTION_BID_TO_WIN}&use_pb=1',
+ 'lurl': 'https://api16-event-sg2.pangle.io/api/ad/union/openrtb/loss/?req_id=233f1693-68d1-470a-ad85-c156c3faaf6fu1450&ttdsp_adx_index=256&rit=980589944&extra=oqveoB%2Bg4%2ByNz9L8wwu%2Fy%2FwKxQsGaKsJHuB4NMK77uqZ9%2FJKpnsVZculJX8%2FxrRBAtaktU1DRN%2Fy6TKAqibCbj%2FM3%2BZ6biAKQG%2BCyt4eIV0KVvri9jCCnaajbkN7YNJWJJw2lW6cJ6Va3SuJG9H7a%2FAJd2PMbhK7fXWhoW72TwgOcKHKBgjM6sNDISBKbWlZyY3L1PhKSX%2FM8LOvL6qahsb%2FDpEObIx24vhQLNWp28XY1L4UqeibuRjam3eCvN7nXoQq74KkJ45QQsTgvV4j6I6EbLOdjOi%2FURhWMDjUD1VCMpqUT%2B6L8ZROgrX9Tp53eJ3bFOczmSTOmDSazKMHa%2B3uZZ7JHcSx32eoY4hfYc99NOJmYBKXNKCmoXyJvS3PCM3PlAz97hKrDMGnVv1wAQ7QGDCbittF0vZwtsRAvvx2mWINNIB3%2FUB2PjhxFsoDA%2BWE2urVZwEdyu%2FJrCznJsMwenXjcbMD5jmUF5vDkkLS%2B7TMDIEawJPJKZ62pK35enrwGxCs6ePXi21rJJkA0bF8tgAdl4mU1illBIVO4kCL%2ByRASskHPjgg%2FcdFe9HP%2Fi8byjAprH%2BhRerN%2FRKFxC3xv8b75x2pb1g7dY%2FTj9IjT0evsBSPVwFNqtKmPId35IcY%2FSXiqPHh%2FrAHZzr5BPsTT19P49SlNMR9UZYTzViX1iJpcCL1UFjuDdrdff%2BhHCviXxo%2FkRmufEF3umHZwxbdDOPAghuZ0DtRCY6S1rnb%2FK9BbpsVKSndOtgfCwMHFwiPmdw1XjEXGc1eOWXY6qfSp90PIfL6WS7Neh3ba2qMv6WxG3HSOBYvrcCqVTsNxk4UdVm3qb1J0CMVByweTMo45usSkCTdvX3JuEB7tVA6%2BrEk57b3XJd5Phf2AN8hon%2F7lmcXE41kwMQuXq89ViwQmW0G247UFWOQx4t1cmBqFiP6qNA%2F%2BunkZDno1pmAsGnTv7Mz9xtpOaIqKl8BKrVQSTopZ9WcUVzdBUutF19mn1f43BvyA9gIEhcDJHOj&reason=${AUCTION_LOSS}&ad_slot_type=8&auction_mwb=${AUCTION_PRICE}&use_pb=1',
+ 'adm': '
',
+ 'adid': '1780626232977441',
+ 'adomain': [
+ 'swi.esxcmnb.com'
+ ],
+ 'iurl': 'https://p16-ttam-va.ibyteimg.com/origin/ad-site-i18n-sg/202310245d0d598b3ff5993c4f129a8b',
+ 'cid': '1780626232977441',
+ 'crid': '1780626232977441',
+ 'attr': [
+ 4
+ ],
+ 'w': 640,
+ 'h': 640,
+ 'mtype': 2,
+ 'ext': {
+ 'pangle': {
+ 'adtype': 8
+ },
+ 'event_notification_token': {
+ 'payload': '980589944:8:1450:7492'
+ }
+ }
+ }
+ ],
+ 'seat': 'pangle'
+ }
+ ]
+ }
+ };
+ const bannerResponse = {
+ 'headers': null,
+ 'body': {
+ 'id': '233f1693-68d1-470a-ad85-c156c3faaf6f',
+ 'seatbid': [
+ {
+ 'bid': [
+ {
+ 'id': '2820132fe18114',
+ 'impid': '2820132fe18114',
+ 'price': 0.03294,
+ 'nurl': 'https://api16-event-sg2.pangle.io/api/ad/union/openrtb/win/?req_id=233f1693-68d1-470a-ad85-c156c3faaf6fu1450&ttdsp_adx_index=256&rit=980589944&extra=oqveoB%2Bg4%2ByNz9L8wwu%2Fy%2FwKxQsGaKsJHuB4NMK77uqZ9%2FJKpnsVZculJX8%2FxrRBAtaktU1DRN%2Fy6TKAqibCbj%2FM3%2BZ6biAKQG%2BCyt4eIV0KVvri9jCCnaajbkN7YNJWJJw2lW6cJ6Va3SuJG9H7a%2FAJd2PMbhK7fXWhoW72TwgOcKHKBgjM6sNDISBKbWlZyY3L1PhKSX%2FM8LOvL6qahsb%2FDpEObIx24vhQLNWp28XY1L4UqeibuRjam3eCvN7nXoQq74KkJ45QQsTgvV4j6I6EbLOdjOi%2FURhWMDjUD1VCMpqUT%2B6L8ZROgrX9Tp53eJ3bFOczmSTOmDSazKMHa%2B3uZZ7JHcSx32eoY4hfYc99NOJmYBKXNKCmoXyJvS3PCM3PlAz97hKrDMGnVv1wAQ7QGDCbittF0vZwtsRAvvx2mWINNIB3%2FUB2PjhxFsoDA%2BWE2urVZwEdyu%2FJrCznJsMwenXjcbMD5jmUF5vDkkLS%2B7TMDIEawJPJKZ62pK35enrwGxCs6ePXi21rJJkA0bF8tgAdl4mU1illBIVO4kCL%2ByRASskHPjgg%2FcdFe9HP%2Fi8byjAprH%2BhRerN%2FRKFxC3xv8b75x2pb1g7dY%2FTj9IjT0evsBSPVwFNqtKmPId35IcY%2FSXiqPHh%2FrAHZzr5BPsTT19P49SlNMR9UZYTzViX1iJpcCL1UFjuDdrdff%2BhHCviXxo%2FkRmufEF3umHZwxbdDOPAghuZ0DtRCY6S1rnb%2FK9BbpsVKSndOtgfCwMHFwiPmdw1XjEXGc1eOWXY6qfSp90PIfL6WS7Neh3ba2qMv6WxG3HSOBYvrcCqVTsNxk4UdVm3qb1J0CMVByweTMo45usSkCTdvX3JuEB7tVA6%2BrEk57b3XJd5Phf2AN8hon%2F7lmcXE41kwMQuXq89ViwQmW0G247UFWOQx4t1cmBqFiP6qNA%2F%2BunkZDno1pmAsGnTv7Mz9xtpOaIqKl8BKrVQSTopZ9WcUVzdBUutF19mn1f43BvyA9gIEhcDJHOj&win_price=${AUCTION_PRICE}&auction_mwb=${AUCTION_BID_TO_WIN}&use_pb=1',
+ 'lurl': 'https://api16-event-sg2.pangle.io/api/ad/union/openrtb/loss/?req_id=233f1693-68d1-470a-ad85-c156c3faaf6fu1450&ttdsp_adx_index=256&rit=980589944&extra=oqveoB%2Bg4%2ByNz9L8wwu%2Fy%2FwKxQsGaKsJHuB4NMK77uqZ9%2FJKpnsVZculJX8%2FxrRBAtaktU1DRN%2Fy6TKAqibCbj%2FM3%2BZ6biAKQG%2BCyt4eIV0KVvri9jCCnaajbkN7YNJWJJw2lW6cJ6Va3SuJG9H7a%2FAJd2PMbhK7fXWhoW72TwgOcKHKBgjM6sNDISBKbWlZyY3L1PhKSX%2FM8LOvL6qahsb%2FDpEObIx24vhQLNWp28XY1L4UqeibuRjam3eCvN7nXoQq74KkJ45QQsTgvV4j6I6EbLOdjOi%2FURhWMDjUD1VCMpqUT%2B6L8ZROgrX9Tp53eJ3bFOczmSTOmDSazKMHa%2B3uZZ7JHcSx32eoY4hfYc99NOJmYBKXNKCmoXyJvS3PCM3PlAz97hKrDMGnVv1wAQ7QGDCbittF0vZwtsRAvvx2mWINNIB3%2FUB2PjhxFsoDA%2BWE2urVZwEdyu%2FJrCznJsMwenXjcbMD5jmUF5vDkkLS%2B7TMDIEawJPJKZ62pK35enrwGxCs6ePXi21rJJkA0bF8tgAdl4mU1illBIVO4kCL%2ByRASskHPjgg%2FcdFe9HP%2Fi8byjAprH%2BhRerN%2FRKFxC3xv8b75x2pb1g7dY%2FTj9IjT0evsBSPVwFNqtKmPId35IcY%2FSXiqPHh%2FrAHZzr5BPsTT19P49SlNMR9UZYTzViX1iJpcCL1UFjuDdrdff%2BhHCviXxo%2FkRmufEF3umHZwxbdDOPAghuZ0DtRCY6S1rnb%2FK9BbpsVKSndOtgfCwMHFwiPmdw1XjEXGc1eOWXY6qfSp90PIfL6WS7Neh3ba2qMv6WxG3HSOBYvrcCqVTsNxk4UdVm3qb1J0CMVByweTMo45usSkCTdvX3JuEB7tVA6%2BrEk57b3XJd5Phf2AN8hon%2F7lmcXE41kwMQuXq89ViwQmW0G247UFWOQx4t1cmBqFiP6qNA%2F%2BunkZDno1pmAsGnTv7Mz9xtpOaIqKl8BKrVQSTopZ9WcUVzdBUutF19mn1f43BvyA9gIEhcDJHOj&reason=${AUCTION_LOSS}&ad_slot_type=8&auction_mwb=${AUCTION_PRICE}&use_pb=1',
+ 'adm': '
![]()
',
+ 'adid': '1780626232977441',
+ 'adomain': [
+ 'swi.esxcmnb.com'
+ ],
+ 'iurl': 'https://p16-ttam-va.ibyteimg.com/origin/ad-site-i18n-sg/202310245d0d598b3ff5993c4f129a8b',
+ 'cid': '1780626232977441',
+ 'crid': '1780626232977441',
+ 'attr': [
+ 4
+ ],
+ 'w': 640,
+ 'h': 640,
+ 'mtype': 1,
+ 'ext': {
+ 'pangle': {
+ 'adtype': 8
+ },
+ 'event_notification_token': {
+ 'payload': '980589944:8:1450:7492'
+ }
+ }
+ }
+ ],
+ 'seat': 'pangle'
+ }
+ ]
+ }
+ };
+ it('should set mediaType to banner', function() {
+ const request = spec.buildRequests(multiRequest, bidderRequest)[0];
+ const interpretedResponse = spec.interpretResponse(bannerResponse, request);
+ const bid = interpretedResponse[0];
+ expect(bid.mediaType).to.equal('banner');
+ })
+ it('should set mediaType to video', function() {
+ const request = spec.buildRequests(multiRequest, bidderRequest)[0];
+ const interpretedResponse = spec.interpretResponse(videoResponse, request);
+ const bid = interpretedResponse[0];
+ expect(bid.mediaType).to.equal('video');
+ })
+});
diff --git a/test/spec/modules/pgamsspBidAdapter_spec.js b/test/spec/modules/pgamsspBidAdapter_spec.js
index 7e2323d4b81..0766219eda8 100644
--- a/test/spec/modules/pgamsspBidAdapter_spec.js
+++ b/test/spec/modules/pgamsspBidAdapter_spec.js
@@ -145,6 +145,7 @@ describe('PGAMBidAdapter', function () {
expect(placement.schain).to.be.an('object');
expect(placement.bidfloor).to.exist.and.to.equal(0);
expect(placement.type).to.exist.and.to.equal('publisher');
+ expect(placement.eids).to.exist.and.to.be.an('array');
if (placement.adFormat === BANNER) {
expect(placement.sizes).to.be.an('array');
diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js
index 5b591804b95..2bab144dae7 100644
--- a/test/spec/modules/prebidServerBidAdapter_spec.js
+++ b/test/spec/modules/prebidServerBidAdapter_spec.js
@@ -91,6 +91,7 @@ const REQUEST = {
}
},
'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c',
+ 'adUnitId': 'au-id-1',
'bids': [
{
'bid_id': '123',
@@ -2882,6 +2883,32 @@ describe('S2S Adapter', function () {
})
})
+ describe('calls done', () => {
+ let success, error;
+ beforeEach(() => {
+ const mockAjax = function (_, callback) {
+ ({success, error} = callback);
+ }
+ config.setConfig({ s2sConfig: CONFIG });
+ adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, mockAjax);
+ })
+
+ it('passing timedOut = false on succcess', () => {
+ success({});
+ sinon.assert.calledWith(done, false);
+ });
+
+ Object.entries({
+ 'timeouts': true,
+ 'other errors': false
+ }).forEach(([t, timedOut]) => {
+ it(`passing timedOut = ${timedOut} on ${t}`, () => {
+ error('', {timedOut});
+ sinon.assert.calledWith(done, timedOut);
+ })
+ })
+ })
+
// TODO: test dependent on pbjs_api_spec. Needs to be isolated
it('does not call addBidResponse and calls done when ad unit not set', function () {
config.setConfig({ s2sConfig: CONFIG });
diff --git a/test/spec/modules/priceFloors_spec.js b/test/spec/modules/priceFloors_spec.js
index 673a821b497..7ea7722b12a 100644
--- a/test/spec/modules/priceFloors_spec.js
+++ b/test/spec/modules/priceFloors_spec.js
@@ -12,7 +12,7 @@ import {
isFloorsDataValid,
addBidResponseHook,
fieldMatchingFunctions,
- allowedFields, parseFloorData, normalizeDefault, getFloorDataFromAdUnits
+ allowedFields, parseFloorData, normalizeDefault, getFloorDataFromAdUnits, updateAdUnitsForAuction, createFloorsDataForAuction
} from 'modules/priceFloors.js';
import * as events from 'src/events.js';
import * as mockGpt from '../integration/faker/googletag.js';
@@ -116,7 +116,8 @@ describe('the price floors module', function () {
bidder: 'rubicon',
adUnitCode: 'test_div_1',
auctionId: '1234-56-789',
- transactionId: 'tr_test_div_1'
+ transactionId: 'tr_test_div_1',
+ adUnitId: 'tr_test_div_1',
};
function getAdUnitMock(code = 'adUnit-code') {
@@ -618,8 +619,8 @@ describe('the price floors module', function () {
});
});
it('picks the gptSlot from the adUnit and does not call the slotMatching', function () {
- const newBidRequest1 = { ...basicBidRequest, transactionId: 'au1' };
- adUnits = [{code: newBidRequest1.code, transactionId: 'au1'}];
+ const newBidRequest1 = { ...basicBidRequest, adUnitId: 'au1' };
+ adUnits = [{code: newBidRequest1.adUnitCode, adUnitId: 'au1'}];
utils.deepSetValue(adUnits[0], 'ortb2Imp.ext.data.adserver', {
name: 'gam',
adslot: '/12345/news/politics'
@@ -632,8 +633,8 @@ describe('the price floors module', function () {
matchingRule: '/12345/news/politics'
});
- const newBidRequest2 = { ...basicBidRequest, adUnitCode: 'test_div_2', transactionId: 'au2' };
- adUnits = [{code: newBidRequest2.adUnitCode, transactionId: newBidRequest2.transactionId}];
+ const newBidRequest2 = { ...basicBidRequest, adUnitCode: 'test_div_2', adUnitId: 'au2' };
+ adUnits = [{code: newBidRequest2.adUnitCode, adUnitId: newBidRequest2.adUnitId}];
utils.deepSetValue(adUnits[0], 'ortb2Imp.ext.data.adserver', {
name: 'gam',
adslot: '/12345/news/weather'
@@ -648,6 +649,107 @@ describe('the price floors module', function () {
});
});
});
+
+ describe('updateAdUnitsForAuction', function() {
+ let inputFloorData;
+ let adUnits;
+
+ beforeEach(function() {
+ adUnits = [getAdUnitMock()];
+ inputFloorData = utils.deepClone(minFloorConfigLow);
+ inputFloorData.skipRate = 0.5;
+ });
+
+ it('should set the skipRate to the skipRate from the data property before using the skipRate from floorData directly', function() {
+ utils.deepSetValue(inputFloorData, 'data', {
+ skipRate: 0.7
+ });
+ updateAdUnitsForAuction(adUnits, inputFloorData, 'id');
+
+ const skipRate = utils.deepAccess(adUnits, '0.bids.0.floorData.skipRate');
+ expect(skipRate).to.equal(0.7);
+ });
+
+ it('should set the skipRate to the skipRate from floorData directly if it does not exist in the data property of floorData', function() {
+ updateAdUnitsForAuction(adUnits, inputFloorData, 'id');
+
+ const skipRate = utils.deepAccess(adUnits, '0.bids.0.floorData.skipRate');
+ expect(skipRate).to.equal(0.5);
+ });
+
+ it('should set the skipRate in the bid floorData to undefined if both skipRate and skipRate in the data property are undefined', function() {
+ inputFloorData.skipRate = undefined;
+ utils.deepSetValue(inputFloorData, 'data', {
+ skipRate: undefined,
+ });
+ updateAdUnitsForAuction(adUnits, inputFloorData, 'id');
+
+ const skipRate = utils.deepAccess(adUnits, '0.bids.0.floorData.skipRate');
+ expect(skipRate).to.equal(undefined);
+ });
+ });
+
+ describe('createFloorsDataForAuction', function() {
+ let adUnits;
+ let floorConfig;
+
+ beforeEach(function() {
+ adUnits = [getAdUnitMock()];
+ floorConfig = utils.deepClone(basicFloorConfig);
+ });
+
+ it('should return skipRate as 0 if both skipRate and skipRate in the data property are undefined', function() {
+ floorConfig.skipRate = undefined;
+ floorConfig.data.skipRate = undefined;
+ handleSetFloorsConfig(floorConfig);
+
+ const floorData = createFloorsDataForAuction(adUnits, 'id');
+
+ expect(floorData.skipRate).to.equal(0);
+ expect(floorData.skipped).to.equal(false);
+ });
+
+ it('should properly set skipRate if it is available in the data property', function() {
+ // this will force skipped to be true
+ floorConfig.skipRate = 101;
+ floorConfig.data.skipRate = 201;
+ handleSetFloorsConfig(floorConfig);
+
+ const floorData = createFloorsDataForAuction(adUnits, 'id');
+
+ expect(floorData.data.skipRate).to.equal(201);
+ expect(floorData.skipped).to.equal(true);
+ });
+
+ it('should should use the skipRate if its not available in the data property ', function() {
+ // this will force skipped to be true
+ floorConfig.skipRate = 101;
+ handleSetFloorsConfig(floorConfig);
+
+ const floorData = createFloorsDataForAuction(adUnits, 'id');
+
+ expect(floorData.skipRate).to.equal(101);
+ expect(floorData.skipped).to.equal(true);
+ });
+
+ it('should have skippedReason set to "not_found" if there is no valid floor data', function() {
+ floorConfig.data = {}
+ handleSetFloorsConfig(floorConfig);
+
+ const floorData = createFloorsDataForAuction(adUnits, 'id');
+ expect(floorData.skippedReason).to.equal(CONSTANTS.FLOOR_SKIPPED_REASON.NOT_FOUND);
+ });
+
+ it('should have skippedReason set to "random" if there is floor data and skipped is true', function() {
+ // this will force skipped to be true
+ floorConfig.skipRate = 101;
+ handleSetFloorsConfig(floorConfig);
+
+ const floorData = createFloorsDataForAuction(adUnits, 'id');
+ expect(floorData.skippedReason).to.equal(CONSTANTS.FLOOR_SKIPPED_REASON.RANDOM);
+ });
+ });
+
describe('pre-auction tests', function () {
let exposedAdUnits;
const validateBidRequests = (getFloorExpected, FloorDataExpected) => {
@@ -689,6 +791,124 @@ describe('the price floors module', function () {
floorProvider: undefined
});
});
+ it('should not do floor stuff if floors.data is defined by noFloorSignalBidders[]', function() {
+ handleSetFloorsConfig({
+ ...basicFloorConfig,
+ data: {
+ ...basicFloorDataLow,
+ noFloorSignalBidders: ['someBidder', 'someOtherBidder']
+ }});
+ runStandardAuction();
+ validateBidRequests(false, {
+ skipped: false,
+ floorMin: undefined,
+ modelVersion: 'basic model',
+ modelWeight: 10,
+ modelTimestamp: undefined,
+ location: 'setConfig',
+ skipRate: 0,
+ fetchStatus: undefined,
+ floorProvider: undefined,
+ noFloorSignaled: true
+ })
+ });
+ it('should not do floor stuff if floors.enforcement is defined by noFloorSignalBidders[]', function() {
+ handleSetFloorsConfig({ ...basicFloorConfig,
+ enforcement: {
+ enforceJS: true,
+ noFloorSignalBidders: ['someBidder', 'someOtherBidder']
+ },
+ data: basicFloorDataLow
+ });
+ runStandardAuction();
+ validateBidRequests(false, {
+ skipped: false,
+ floorMin: undefined,
+ modelVersion: 'basic model',
+ modelWeight: 10,
+ modelTimestamp: undefined,
+ location: 'setConfig',
+ skipRate: 0,
+ fetchStatus: undefined,
+ floorProvider: undefined,
+ noFloorSignaled: true
+ })
+ });
+ it('should not do floor stuff and use first floors.data.noFloorSignalBidders if its defined betwen enforcement.noFloorSignalBidders', function() {
+ handleSetFloorsConfig({ ...basicFloorConfig,
+ enforcement: {
+ enforceJS: true,
+ noFloorSignalBidders: ['someBidder']
+ },
+ data: {
+ ...basicFloorDataLow,
+ noFloorSignalBidders: ['someBidder', 'someOtherBidder']
+ }
+ });
+ runStandardAuction();
+ validateBidRequests(false, {
+ skipped: false,
+ floorMin: undefined,
+ modelVersion: 'basic model',
+ modelWeight: 10,
+ modelTimestamp: undefined,
+ location: 'setConfig',
+ skipRate: 0,
+ fetchStatus: undefined,
+ floorProvider: undefined,
+ noFloorSignaled: true
+ })
+ });
+ it('it shouldn`t return floor stuff for bidder in the noFloorSignalBidders list', function() {
+ handleSetFloorsConfig({ ...basicFloorConfig,
+ enforcement: {
+ enforceJS: true,
+ },
+ data: {
+ ...basicFloorDataLow,
+ noFloorSignalBidders: ['someBidder']
+ }
+ });
+ runStandardAuction()
+ const bidRequestData = exposedAdUnits[0].bids.find(bid => bid.bidder === 'someBidder');
+ expect(bidRequestData.hasOwnProperty('getFloor')).to.equal(false);
+ sinon.assert.match(bidRequestData.floorData, {
+ skipped: false,
+ floorMin: undefined,
+ modelVersion: 'basic model',
+ modelWeight: 10,
+ modelTimestamp: undefined,
+ location: 'setConfig',
+ skipRate: 0,
+ fetchStatus: undefined,
+ floorProvider: undefined,
+ noFloorSignaled: true
+ });
+ })
+ it('it should return floor stuff if we defined wrong bidder name in data.noFloorSignalBidders', function() {
+ handleSetFloorsConfig({ ...basicFloorConfig,
+ enforcement: {
+ enforceJS: true,
+ },
+ data: {
+ ...basicFloorDataLow,
+ noFloorSignalBidders: ['randomBiider']
+ }
+ });
+ runStandardAuction();
+ validateBidRequests(true, {
+ skipped: false,
+ floorMin: undefined,
+ modelVersion: 'basic model',
+ modelWeight: 10,
+ modelTimestamp: undefined,
+ location: 'setConfig',
+ skipRate: 0,
+ fetchStatus: undefined,
+ floorProvider: undefined,
+ noFloorSignaled: false
+ })
+ });
it('should use adUnit level data if not setConfig or fetch has occured', function () {
handleSetFloorsConfig({
...basicFloorConfig,
@@ -2143,7 +2363,7 @@ describe('the price floors module', function () {
}
const resp = {
- transactionId: req.transactionId,
+ adUnitId: req.adUnitId,
size: [100, 100],
mediaType: 'banner',
}
@@ -2154,7 +2374,7 @@ describe('the price floors module', function () {
adUnits: [
{
code: req.adUnitCode,
- transactionId: req.transactionId,
+ adUnitId: req.adUnitId,
ortb2Imp: {ext: {data: {adserver: {name: 'gam', adslot: 'slot'}}}}
}
]
diff --git a/test/spec/modules/pubmaticAnalyticsAdapter_spec.js b/test/spec/modules/pubmaticAnalyticsAdapter_spec.js
index 7fce08fc24f..c6447905ecd 100755
--- a/test/spec/modules/pubmaticAnalyticsAdapter_spec.js
+++ b/test/spec/modules/pubmaticAnalyticsAdapter_spec.js
@@ -1,4 +1,4 @@
-import pubmaticAnalyticsAdapter, {getMetadata} from 'modules/pubmaticAnalyticsAdapter.js';
+import pubmaticAnalyticsAdapter, { getMetadata } from 'modules/pubmaticAnalyticsAdapter.js';
import adapterManager from 'src/adapterManager.js';
import CONSTANTS from 'src/constants.json';
import { config } from 'src/config.js';
@@ -316,6 +316,208 @@ describe('pubmatic analytics adapter', function () {
expect(utils.logError.called).to.equal(true);
});
+ describe('OW S2S', function() {
+ this.beforeEach(function() {
+ pubmaticAnalyticsAdapter.enableAnalytics({
+ options: {
+ publisherId: 9999,
+ profileId: 1111,
+ profileVersionId: 20
+ }
+ });
+ config.setConfig({
+ s2sConfig: {
+ accountId: '1234',
+ bidders: ['pubmatic'],
+ defaultVendor: 'openwrap',
+ timeout: 500
+ }
+ });
+ });
+
+ this.afterEach(function() {
+ pubmaticAnalyticsAdapter.disableAnalytics();
+ });
+
+ it('Pubmatic Won: No tracker fired', function() {
+ this.timeout(5000)
+
+ sandbox.stub($$PREBID_GLOBAL$$, 'getHighestCpmBids').callsFake((key) => {
+ return [MOCK.BID_RESPONSE[0], MOCK.BID_RESPONSE[1]]
+ });
+
+ config.setConfig({
+ testGroupId: 15
+ });
+
+ events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
+ events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
+ events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]);
+ events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
+ events.emit(AUCTION_END, MOCK.AUCTION_END);
+ events.emit(SET_TARGETING, MOCK.SET_TARGETING);
+ events.emit(BID_WON, MOCK.BID_WON[0]);
+
+ clock.tick(2000 + 1000);
+ expect(requests.length).to.equal(1); // only logger is fired
+ let request = requests[0];
+ expect(request.url).to.equal('https://t.pubmatic.com/wl?pubid=9999');
+ let data = getLoggerJsonFromRequest(request.requestBody);
+ expect(data.pubid).to.equal('9999');
+ expect(data.pid).to.equal('1111');
+ expect(data.pdvid).to.equal('20');
+ });
+
+ it('Non-pubmatic won: logger, tracker fired', function() {
+ const APPNEXUS_BID = Object.assign({}, BID, {
+ 'bidder': 'appnexus',
+ 'adserverTargeting': {
+ 'hb_bidder': 'appnexus',
+ 'hb_adid': '2ecff0db240757',
+ 'hb_pb': 1.20,
+ 'hb_size': '640x480',
+ 'hb_source': 'server'
+ }
+ });
+
+ const MOCK_AUCTION_INIT_APPNEXUS = {
+ 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa',
+ 'timestamp': 1519767010567,
+ 'auctionStatus': 'inProgress',
+ 'adUnits': [ {
+ 'code': '/19968336/header-bid-tag-1',
+ 'sizes': [[640, 480]],
+ 'bids': [ {
+ 'bidder': 'appnexus',
+ 'params': {
+ 'publisherId': '1001'
+ }
+ } ],
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014'
+ }
+ ],
+ 'adUnitCodes': ['/19968336/header-bid-tag-1'],
+ 'bidderRequests': [ {
+ 'bidderCode': 'appnexus',
+ 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa',
+ 'bidderRequestId': '1be65d7958826a',
+ 'bids': [ {
+ 'bidder': 'appnexus',
+ 'params': {
+ 'publisherId': '1001',
+ 'kgpv': 'this-is-a-kgpv'
+ },
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [[640, 480]]
+ }
+ },
+ 'adUnitCode': '/19968336/header-bid-tag-1',
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014',
+ 'sizes': [[640, 480]],
+ 'bidId': '2ecff0db240757',
+ 'bidderRequestId': '1be65d7958826a',
+ 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa',
+ 'src': 'client',
+ 'bidRequestsCount': 1
+ }
+ ],
+ 'timeout': 3000,
+ 'refererInfo': {
+ 'topmostLocation': 'http://www.test.com/page.html', 'reachedTop': true, 'numIframes': 0, 'stack': ['http://www.test.com/page.html']
+ }
+ }
+ ],
+ 'bidsReceived': [],
+ 'winningBids': [],
+ 'timeout': 3000
+ };
+
+ const MOCK_BID_REQUESTED_APPNEXUS = {
+ 'bidder': 'appnexus',
+ 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa',
+ 'bidderRequestId': '1be65d7958826a',
+ 'bids': [
+ {
+ 'bidder': 'appnexus',
+ 'adapterCode': 'appnexus',
+ 'bidderCode': 'appnexus',
+ 'params': {
+ 'publisherId': '1001',
+ 'video': {
+ 'minduration': 30,
+ 'skippable': true
+ }
+ },
+ 'mediaType': 'video',
+ 'adUnitCode': '/19968336/header-bid-tag-0',
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014',
+ 'sizes': [[640, 480]],
+ 'bidId': '2ecff0db240757',
+ 'bidderRequestId': '1be65d7958826a',
+ 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa'
+ }
+ ],
+ 'auctionStart': 1519149536560,
+ 'timeout': 5000,
+ 'start': 1519149562216,
+ 'refererInfo': {
+ 'topmostLocation': 'http://www.test.com/page.html', 'reachedTop': true, 'numIframes': 0, 'stack': ['http://www.test.com/page.html']
+ },
+ 'gdprConsent': {
+ 'consentString': 'here-goes-gdpr-consent-string',
+ 'gdprApplies': true
+ }
+ };
+
+ this.timeout(5000)
+
+ sandbox.stub($$PREBID_GLOBAL$$, 'getHighestCpmBids').callsFake((key) => {
+ return [APPNEXUS_BID]
+ });
+
+ events.emit(AUCTION_INIT, MOCK_AUCTION_INIT_APPNEXUS);
+ events.emit(BID_REQUESTED, MOCK_BID_REQUESTED_APPNEXUS);
+ events.emit(BID_RESPONSE, APPNEXUS_BID);
+ events.emit(BIDDER_DONE, {
+ 'bidderCode': 'appnexus',
+ 'bids': [
+ APPNEXUS_BID,
+ Object.assign({}, APPNEXUS_BID, {
+ 'serverResponseTimeMs': 42,
+ })
+ ]
+ });
+ events.emit(AUCTION_END, MOCK.AUCTION_END);
+ events.emit(SET_TARGETING, {
+ [APPNEXUS_BID.adUnitCode]: APPNEXUS_BID.adserverTargeting,
+ });
+ events.emit(BID_WON, Object.assign({}, APPNEXUS_BID, {
+ 'status': 'rendered'
+ }));
+
+ clock.tick(2000 + 1000);
+ expect(requests.length).to.equal(2); // logger as well as tracker is fired
+ let request = requests[1]; // logger is executed late, trackers execute first
+ expect(request.url).to.equal('https://t.pubmatic.com/wl?pubid=9999');
+ let data = getLoggerJsonFromRequest(request.requestBody);
+ expect(data.pubid).to.equal('9999');
+ expect(data.pid).to.equal('1111');
+ expect(data.pdvid).to.equal('20');
+
+ let firstTracker = requests[0].url;
+ expect(firstTracker.split('?')[0]).to.equal('https://t.pubmatic.com/wt');
+ firstTracker.split('?')[1].split('&').map(e => e.split('=')).forEach(e => data[e[0]] = e[1]);
+ expect(data.pubid).to.equal('9999');
+ expect(decodeURIComponent(data.purl)).to.equal('http://www.test.com/page.html');
+
+ expect(data.s).to.be.an('array');
+ expect(data.s.length).to.equal(1);
+ expect(data.s[0].ps[0].pn).to.equal('appnexus');
+ expect(data.s[0].ps[0].bc).to.equal('appnexus');
+ })
+ });
+
describe('when handling events', function() {
beforeEach(function () {
pubmaticAnalyticsAdapter.enableAnalytics({
@@ -374,10 +576,14 @@ describe('pubmatic analytics adapter', function () {
// slot 1
expect(data.s[0].sn).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].fskp).to.equal(0);
+ expect(data.s[0].sid).not.to.be.undefined;
+ expect(data.s[0].ffs).to.equal(1);
+ expect(data.s[0].fsrc).to.equal(2);
+ expect(data.s[0].fp).to.equal('pubmatic');
expect(data.s[0].sz).to.deep.equal(['640x480']);
expect(data.s[0].ps).to.be.an('array');
- expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
- expect(data.s[0].ps.length).to.equal(1);
+ expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
+ expect(data.s[0].ps.length).to.equal(1);
expect(data.s[0].ps[0].pn).to.equal('pubmatic');
expect(data.s[0].ps[0].bc).to.equal('pubmatic');
expect(data.s[0].ps[0].bidid).to.equal('2ecff0db240757');
@@ -390,8 +596,8 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[0].ps[0].en).to.equal(1.23);
expect(data.s[0].ps[0].di).to.equal('-1');
expect(data.s[0].ps[0].dc).to.equal('');
- expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].l1).to.equal(944);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[0].ps[0].l2).to.equal(0);
expect(data.s[0].ps[0].ss).to.equal(1);
expect(data.s[0].ps[0].t).to.equal(0);
@@ -403,6 +609,10 @@ describe('pubmatic analytics adapter', function () {
// slot 2
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].fskp).to.equal(0);
+ expect(data.s[1].sid).not.to.be.undefined;
+ expect(data.s[1].ffs).to.equal(1);
+ expect(data.s[1].fsrc).to.equal(2);
+ expect(data.s[1].fp).to.equal('pubmatic');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
@@ -421,7 +631,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(0);
@@ -459,7 +669,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.af).to.equal('video');
});
- it('Logger: do not log floor fields when prebids floor shows noData in location property', function() {
+ it('Logger : do not log floor fields when prebids floor shows noData in location property', function() {
const BID_REQUESTED_COPY = utils.deepClone(MOCK.BID_REQUESTED);
BID_REQUESTED_COPY['bids'][1]['floorData']['location'] = 'noData';
@@ -583,9 +793,13 @@ describe('pubmatic analytics adapter', function () {
// slot 1
expect(data.s[0].sn).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].fskp).to.equal(0);
+ expect(data.s[0].sid).not.to.be.undefined;
+ expect(data.s[0].ffs).to.equal(1);
+ expect(data.s[0].fsrc).to.equal(2);
+ expect(data.s[0].fp).to.equal('pubmatic');
expect(data.s[0].sz).to.deep.equal(['640x480']);
expect(data.s[0].ps).to.be.an('array');
- expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
+ expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].ps.length).to.equal(1);
expect(data.s[0].ps[0].pn).to.equal('pubmatic');
expect(data.s[0].ps[0].bc).to.equal('pubmatic');
@@ -659,7 +873,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[0].sz).to.deep.equal(['640x480']);
expect(data.s[0].ps).to.be.an('array');
expect(data.s[0].ps.length).to.equal(1);
- expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
+ expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].ps[0].pn).to.equal('pubmatic');
expect(data.s[0].ps[0].bc).to.equal('pubmatic');
expect(data.s[0].ps[0].bidid).to.equal('2ecff0db240757');
@@ -702,6 +916,13 @@ describe('pubmatic analytics adapter', function () {
expect(data.tgid).to.equal(0);// test group id should be an INT between 0-15 else set to 0
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].fskp).to.equal(0);
+
+ expect(data.s[1].sid).not.to.be.undefined;
+
+ expect(data.s[1].ffs).to.equal(1);
+ expect(data.s[1].fsrc).to.equal(2);
+ expect(data.s[1].fp).to.equal('pubmatic');
+
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
@@ -784,6 +1005,10 @@ describe('pubmatic analytics adapter', function () {
let data = getLoggerJsonFromRequest(request.requestBody);
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].fskp).to.equal(0);
+ expect(data.s[1].sid).not.to.be.undefined;
+ expect(data.s[1].ffs).to.equal(1);
+ expect(data.s[1].fsrc).to.equal(2);
+ expect(data.s[1].fp).to.equal('pubmatic');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
@@ -800,8 +1025,8 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].dc).to.equal('PMP');
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
- expect(data.s[0].ps[0].l1).to.equal(0);
- expect(data.s[0].ps[0].ol1).to.equal(0);
+ expect(data.s[0].ps[0].l1).to.equal(0);
+ expect(data.s[0].ps[0].ol1).to.equal(0);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(1);
@@ -846,6 +1071,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
expect(data.s[1].ps).to.be.an('array');
+ expect(data.s[1].sid).not.to.be.undefined;
expect(data.s[1].ps.length).to.equal(1);
expect(data.s[1].ps[0].pn).to.equal('pubmatic');
expect(data.s[1].ps[0].bc).to.equal('pubmatic');
@@ -861,7 +1087,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(0);
@@ -893,6 +1119,10 @@ describe('pubmatic analytics adapter', function () {
let data = getLoggerJsonFromRequest(request.requestBody);
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].fskp).to.equal(0);
+ expect(data.s[1].sid).not.to.be.undefined;
+ expect(data.s[1].ffs).to.equal(1);
+ expect(data.s[1].fsrc).to.equal(2);
+ expect(data.s[1].fp).to.equal('pubmatic');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
@@ -910,7 +1140,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(0);
@@ -952,6 +1182,7 @@ describe('pubmatic analytics adapter', function () {
let data = getLoggerJsonFromRequest(request.requestBody);
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
+ expect(data.s[1].sid).not.to.be.undefined;
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
expect(data.s[1].ps[0].pn).to.equal('pubmatic');
@@ -968,7 +1199,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(0);
@@ -1006,6 +1237,10 @@ describe('pubmatic analytics adapter', function () {
let data = getLoggerJsonFromRequest(request.requestBody);
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].fskp).to.equal(0);
+ expect(data.s[1].sid).not.to.be.undefined;
+ expect(data.s[1].ffs).to.equal(1);
+ expect(data.s[1].fsrc).to.equal(2);
+ expect(data.s[1].fp).to.equal('pubmatic');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
@@ -1023,7 +1258,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(0);
@@ -1063,6 +1298,7 @@ describe('pubmatic analytics adapter', function () {
let data = getLoggerJsonFromRequest(request.requestBody);
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
+ expect(data.s[1].sid).not.to.be.undefined;
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
expect(data.s[1].ps[0].pn).to.equal('pubmatic');
@@ -1079,7 +1315,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(0);
@@ -1121,7 +1357,11 @@ describe('pubmatic analytics adapter', function () {
// Testing only for rejected bid as other scenarios will be covered under other TCs
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].fskp).to.equal(0);
+ expect(data.s[1].ffs).to.equal(1);
+ expect(data.s[1].fsrc).to.equal(2);
+ expect(data.s[1].fp).to.equal('pubmatic');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
+ expect(data.s[1].sid).not.to.be.undefined;
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
expect(data.s[1].ps[0].pn).to.equal('pubmatic');
@@ -1139,7 +1379,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(0);
@@ -1196,9 +1436,13 @@ describe('pubmatic analytics adapter', function () {
// slot 1
expect(data.s[0].sn).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].fskp).to.equal(0);
+ expect(data.s[0].ffs).to.equal(1);
+ expect(data.s[0].fsrc).to.equal(2);
+ expect(data.s[0].fp).to.equal('pubmatic');
expect(data.s[0].sz).to.deep.equal(['640x480']);
+ expect(data.s[0].sid).not.to.be.undefined;
expect(data.s[0].ps).to.be.an('array');
- expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
+ expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].ps.length).to.equal(1);
expect(data.s[0].ps[0].pn).to.equal('pubmatic');
expect(data.s[0].ps[0].bc).to.equal('pubmatic_alias');
@@ -1213,7 +1457,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[0].ps[0].di).to.equal('-1');
expect(data.s[0].ps[0].dc).to.equal('');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[0].ps[0].l2).to.equal(0);
expect(data.s[0].ps[0].ss).to.equal(0);
expect(data.s[0].ps[0].t).to.equal(0);
@@ -1226,7 +1470,11 @@ describe('pubmatic analytics adapter', function () {
// slot 2
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].fskp).to.equal(0);
+ expect(data.s[1].ffs).to.equal(1);
+ expect(data.s[1].fsrc).to.equal(2);
+ expect(data.s[1].fp).to.equal('pubmatic');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
+ expect(data.s[1].sid).not.to.be.undefined;
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
expect(data.s[1].ps[0].pn).to.equal('pubmatic');
@@ -1243,8 +1491,8 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].dc).to.equal('PMP');
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
- expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].l1).to.equal(944);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(0);
@@ -1318,9 +1566,13 @@ describe('pubmatic analytics adapter', function () {
// slot 1
expect(data.s[0].sn).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].fskp).to.equal(0);
+ expect(data.s[0].ffs).to.equal(1);
+ expect(data.s[0].fsrc).to.equal(2);
+ expect(data.s[0].fp).to.equal('pubmatic');
expect(data.s[0].sz).to.deep.equal(['640x480']);
+ expect(data.s[0].sid).not.to.be.undefined;
expect(data.s[0].ps).to.be.an('array');
- expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
+ expect(data.s[0].au).to.equal('/19968336/header-bid-tag-0');
expect(data.s[0].ps.length).to.equal(1);
expect(data.s[0].ps[0].pn).to.equal('pubmatic');
expect(data.s[0].ps[0].bc).to.equal('groupm');
@@ -1335,7 +1587,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[0].ps[0].di).to.equal('-1');
expect(data.s[0].ps[0].dc).to.equal('');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[0].ps[0].l2).to.equal(0);
expect(data.s[0].ps[0].ss).to.equal(0);
expect(data.s[0].ps[0].t).to.equal(0);
@@ -1348,6 +1600,7 @@ describe('pubmatic analytics adapter', function () {
// slot 2
expect(data.s[1].sn).to.equal('/19968336/header-bid-tag-1');
expect(data.s[1].sz).to.deep.equal(['1000x300', '970x250', '728x90']);
+ expect(data.s[1].sid).not.to.be.undefined;
expect(data.s[1].ps).to.be.an('array');
expect(data.s[1].ps.length).to.equal(1);
expect(data.s[1].ps[0].pn).to.equal('pubmatic');
@@ -1365,7 +1618,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].mi).to.equal('matched-impression');
expect(data.s[1].ps[0].adv).to.equal('example.com');
expect(data.s[0].ps[0].l1).to.equal(944);
- expect(data.s[0].ps[0].ol1).to.equal(3214);
+ expect(data.s[0].ps[0].ol1).to.equal(3214);
expect(data.s[1].ps[0].l2).to.equal(0);
expect(data.s[1].ps[0].ss).to.equal(1);
expect(data.s[1].ps[0].t).to.equal(0);
diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js
index 154a8e1253b..5d59ff99a89 100644
--- a/test/spec/modules/pubmaticBidAdapter_spec.js
+++ b/test/spec/modules/pubmaticBidAdapter_spec.js
@@ -104,6 +104,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '5890',
adSlot: 'Div1@0x0', // ad_id or tagid
+ wiid: 'new-unique-wiid',
video: {
mimes: ['video/mp4', 'video/x-flv'],
skippable: true,
@@ -154,6 +155,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '5890',
adSlot: 'Div1@640x480', // ad_id or tagid
+ wiid: '1234567890',
video: {
mimes: ['video/mp4', 'video/x-flv'],
skippable: true,
@@ -213,6 +215,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '5670',
adSlot: '/43743431/NativeAutomationPrebid@1x1',
+ wiid: 'new-unique-wiid'
},
bidId: '2a5571261281d4',
requestId: 'B68287E1-DC39-4B38-9790-FE4F179739D6',
@@ -278,6 +281,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '5670',
adSlot: '/43743431/NativeAutomationPrebid@1x1',
+ wiid: 'new-unique-wiid'
},
bidId: '2a5571261281d4',
requestId: 'B68287E1-DC39-4B38-9790-FE4F179739D6',
@@ -304,6 +308,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '5670',
adSlot: '/43743431/NativeAutomationPrebid@1x1',
+ wiid: 'new-unique-wiid'
}
}];
@@ -344,6 +349,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '5670',
adSlot: '/43743431/NativeAutomationPrebid@1x1',
+ wiid: 'new-unique-wiid'
}
}];
@@ -502,6 +508,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '301',
adSlot: '/15671365/DMDemo@300x250:0',
+ wiid: 'new-unique-wiid',
video: {
mimes: ['video/mp4', 'video/x-flv'],
skippable: true,
@@ -572,6 +579,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '301',
adSlot: '/15671365/DMDemo@300x250:0',
+ wiid: 'new-unique-wiid',
video: {
mimes: ['video/mp4', 'video/x-flv'],
skippable: true,
@@ -1914,6 +1922,15 @@ describe('PubMatic adapter', function () {
expect(data.user.yob).to.equal(1985);
});
+ it('ortb2.badv should be merged in the request', function() {
+ const ortb2 = {
+ badv: ['example.com']
+ };
+ const request = spec.buildRequests(bidRequests, {ortb2});
+ let data = JSON.parse(request.data);
+ expect(data.badv).to.deep.equal(['example.com']);
+ });
+
describe('ortb2Imp', function() {
describe('ortb2Imp.ext.gpid', function() {
beforeEach(function () {
diff --git a/test/spec/modules/r2b2BidAdapter_spec.js b/test/spec/modules/r2b2BidAdapter_spec.js
new file mode 100644
index 00000000000..b94b400a71d
--- /dev/null
+++ b/test/spec/modules/r2b2BidAdapter_spec.js
@@ -0,0 +1,689 @@
+import {expect} from 'chai';
+import {spec, internal as r2b2, internal} from 'modules/r2b2BidAdapter.js';
+import * as utils from '../../../src/utils';
+import 'modules/schain.js';
+import 'modules/userId/index.js';
+
+function encodePlacementIds (ids) {
+ return btoa(JSON.stringify(ids));
+}
+
+describe('R2B2 adapter', function () {
+ let serverResponse, requestForInterpretResponse;
+ let bidderRequest;
+ let bids = [];
+ let gdprConsent = {
+ gdprApplies: true,
+ consentString: 'consent-string',
+ };
+ let schain = {
+ ver: '1.0',
+ complete: 1,
+ nodes: [{
+ asi: 'example.com',
+ sid: '00001',
+ hp: 1
+ }]
+ };
+ const usPrivacyString = '1YNN';
+ const impId = 'impID';
+ const price = 10.6;
+ const ad = 'adm';
+ const creativeId = 'creativeID';
+ const cid = 41849;
+ const cdid = 595121;
+ const unitCode = 'unitCode';
+ const bidId1 = '1';
+ const bidId2 = '2';
+ const bidId3 = '3';
+ const bidId4 = '4';
+ const bidId5 = '5';
+ const bidWonUrl = 'url1';
+ const setTargetingUrl = 'url2';
+ const bidder = 'r2b2';
+ const foreignBidder = 'differentBidder';
+ const id1 = { pid: 'd/g/p' };
+ const id1Object = { d: 'd', g: 'g', p: 'p', m: 0 };
+ const id2 = { pid: 'd/g/p/1' };
+ const id2Object = { d: 'd', g: 'g', p: 'p', m: 1 };
+ const badId = { pid: 'd/g/' };
+ const bid1 = { bidId: bidId1, bidder, params: [ id1 ] };
+ const bid2 = { bidId: bidId2, bidder, params: [ id2 ] };
+ const bidWithBadSetup = { bidId: bidId3, bidder, params: [ badId ] };
+ const bidForeign1 = { bidId: bidId4, bidder: foreignBidder, params: [ { id: 'abc' } ] };
+ const bidForeign2 = { bidId: bidId5, bidder: foreignBidder, params: [ { id: 'xyz' } ] };
+ const fakeTime = 1234567890;
+ const cacheBusterRegex = /[\?&]cb=([^&]+)/;
+ let bidStub, time;
+
+ beforeEach(function () {
+ bids = [{
+ bidder: 'r2b2',
+ params: {
+ pid: 'example.com/generic/300x250/1'
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250]
+ ]
+ }
+ },
+ adUnitCode: unitCode,
+ transactionId: '29c408b9-65ce-48b1-9167-18a57791f908',
+ sizes: [
+ [300, 250]
+ ],
+ bidId: '20917a54ee9858',
+ bidderRequestId: '15270d403778d',
+ auctionId: '36acef1b-f635-4f57-b693-5cc55ee16346',
+ src: 'client',
+ ortb2: {
+ regs: {
+ ext: {
+ gdpr: 1,
+ us_privacy: '1YYY'
+ }
+ },
+ user: {
+ ext: {
+ consent: 'consent-string'
+ }
+ },
+ site: {},
+ device: {}
+ },
+ schain
+ }, {
+ bidder: 'r2b2',
+ params: {
+ pid: 'example.com/generic/300x600/0'
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 600]
+ ]
+ }
+ },
+ adUnitCode: unitCode,
+ transactionId: '29c408b9-65ce-48b1-9167-18a57791f908',
+ sizes: [
+ [300, 600]
+ ],
+ bidId: '3dd53d30c691fe',
+ bidderRequestId: '15270d403778d',
+ auctionId: '36acef1b-f635-4f57-b693-5cc55ee16346',
+ src: 'client',
+ ortb2: {
+ regs: {
+ ext: {
+ gdpr: 1,
+ us_privacy: '1YYY'
+ }
+ },
+ user: {
+ ext: {
+ consent: 'consent-string'
+ }
+ },
+ site: {},
+ device: {}
+ },
+ schain
+ }];
+ bidderRequest = {
+ bidderCode: 'r2b2',
+ auctionId: '36acef1b-f635-4f57-b693-5cc55ee16346',
+ bidderRequestId: '15270d403778d',
+ bids: bids,
+ ortb2: {
+ regs: {
+ ext: {
+ gdpr: 1,
+ us_privacy: '1YYY'
+ }
+ },
+ user: {
+ ext: {
+ consent: 'consent-string'
+ }
+ },
+ site: {},
+ device: {}
+ },
+ gdprConsent: {
+ consentString: 'consent-string',
+ vendorData: {},
+ gdprApplies: true,
+ apiVersion: 2
+ },
+ uspConsent: '1YYY',
+ };
+ serverResponse = {
+ id: 'a66a6e32-2a7d-4ed3-bb13-6f3c9bdcf6a1',
+ seatbid: [{
+ bid: [{
+ id: '4756cc9e9b504fd0bd39fdd594506545',
+ impid: impId,
+ price: price,
+ adm: ad,
+ crid: creativeId,
+ w: 300,
+ h: 250,
+ ext: {
+ prebid: {
+ meta: {
+ adaptercode: 'r2b2'
+ },
+ type: 'banner'
+ },
+ r2b2: {
+ cdid: cdid,
+ cid: cid,
+ useRenderer: true
+ }
+ }
+ }],
+ seat: 'seat'
+ }]
+ };
+ requestForInterpretResponse = {
+ data: {
+ imp: [
+ {id: impId}
+ ]
+ },
+ bids
+ };
+ });
+
+ describe('isBidRequestValid', function () {
+ let bid = {};
+
+ it('should return false when missing required "pid" param', function () {
+ bid.params = {random: 'param'};
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ bid.params = {d: 'd', g: 'g', p: 'p', m: 1};
+ expect(spec.isBidRequestValid(bid)).to.equal(false)
+ });
+
+ it('should return false when "pid" is malformed', function () {
+ bid.params = {pid: 'pid'};
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ bid.params = {pid: '///'};
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ bid.params = {pid: '/g/p/m'};
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ bid.params = {pid: 'd//p/m'};
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ bid.params = {pid: 'd/g//m'};
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ bid.params = {pid: 'd/p/'};
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ bid.params = {pid: 'd/g/p/m/t'};
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+
+ it('should return true when "pid" is a correct dgpm', function () {
+ bid.params = {pid: 'd/g/p/m'};
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+ it('should return true when type is blank', function () {
+ bid.params = {pid: 'd/g/p/'};
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+ it('should return true when type is missing', function () {
+ bid.params = {pid: 'd/g/p'};
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+ it('should return true when "pid" is a number', function () {
+ bid.params = {pid: 12356};
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+ it('should return true when "pid" is a numeric string', function () {
+ bid.params = {pid: '12356'};
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+ it('should return true for selfpromo unit', function () {
+ bid.params = {pid: 'selfpromo'};
+ expect(spec.isBidRequestValid(bid)).to.equal(true)
+ });
+ });
+
+ describe('buildRequests', function () {
+ beforeEach(function () {
+ r2b2.placementsToSync = [];
+ r2b2.mappedParams = {};
+ });
+
+ it('should set correct request method and url and pass bids', function () {
+ let requests = spec.buildRequests([bids[0]], bidderRequest);
+ expect(requests).to.be.an('array').that.has.lengthOf(1);
+ let request = requests[0]
+ expect(request.method).to.equal('POST');
+ expect(request.url).to.equal('https://hb.r2b2.cz/openrtb2/bid');
+ expect(request.data).to.be.an('object');
+ expect(request.bids).to.deep.equal(bids);
+ });
+
+ it('should pass correct parameters', function () {
+ let requests = spec.buildRequests([bids[0]], bidderRequest);
+ let {data} = requests[0];
+ let {imp, device, site, source, ext, cur, test} = data;
+ expect(imp).to.be.an('array').that.has.lengthOf(1);
+ expect(device).to.be.an('object');
+ expect(site).to.be.an('object');
+ expect(source).to.be.an('object');
+ expect(cur).to.deep.equal(['USD']);
+ expect(ext.version).to.equal('1.0.0');
+ expect(test).to.equal(0);
+ });
+
+ it('should pass correct imp', function () {
+ let requests = spec.buildRequests([bids[0]], bidderRequest);
+ let {data} = requests[0];
+ let {imp} = data;
+ expect(imp).to.be.an('array').that.has.lengthOf(1);
+ expect(imp[0]).to.be.an('object');
+ let bid = imp[0];
+ expect(bid.id).to.equal('20917a54ee9858');
+ expect(bid.banner).to.deep.equal({topframe: 0, format: [{w: 300, h: 250}]});
+ expect(bid.ext).to.be.an('object');
+ expect(bid.ext.r2b2).to.deep.equal({d: 'example.com', g: 'generic', p: '300x250', m: 1});
+ });
+
+ it('should map type correctly', function () {
+ let result, bid;
+ let requestWithId = function(id) {
+ let b = bids[0];
+ b.params.pid = id;
+ let passedBids = [b];
+ bidderRequest.bids = passedBids;
+ return spec.buildRequests(passedBids, bidderRequest);
+ };
+
+ result = requestWithId('example.com/generic/300x250/mobile');
+ bid = result[0].data.imp[0];
+ expect(bid.ext.r2b2.m).to.be.a('number').that.is.equal(1);
+
+ result = requestWithId('example.com/generic/300x250/desktop');
+ bid = result[0].data.imp[0];
+ expect(bid.ext.r2b2.m).to.be.a('number').that.is.equal(0);
+
+ result = requestWithId('example.com/generic/300x250/1');
+ bid = result[0].data.imp[0];
+ expect(bid.ext.r2b2.m).to.be.a('number').that.is.equal(1);
+
+ result = requestWithId('example.com/generic/300x250/0');
+ bid = result[0].data.imp[0];
+ expect(bid.ext.r2b2.m).to.be.a('number').that.is.equal(0);
+
+ result = requestWithId('example.com/generic/300x250/m');
+ bid = result[0].data.imp[0];
+ expect(bid.ext.r2b2.m).to.be.a('number').that.is.equal(1);
+
+ result = requestWithId('example.com/generic/300x250');
+ bid = result[0].data.imp[0];
+ expect(bid.ext.r2b2.m).to.be.a('number').that.is.equal(0);
+ });
+
+ it('should pass correct parameters for test ad', function () {
+ let testAdBid = bids[0];
+ testAdBid.params = {pid: 'selfpromo'};
+ let requests = spec.buildRequests([testAdBid], bidderRequest);
+ let {data} = requests[0];
+ let {imp} = data;
+ expect(imp).to.be.an('array').that.has.lengthOf(1);
+ expect(imp[0]).to.be.an('object');
+ let bid = imp[0];
+ expect(bid.ext).to.be.an('object');
+ expect(bid.ext.r2b2).to.deep.equal({d: 'test', g: 'test', p: 'selfpromo', m: 0, 'selfpromo': 1});
+ });
+
+ it('should pass multiple bids', function () {
+ let requests = spec.buildRequests(bids, bidderRequest);
+ expect(requests).to.be.an('array').that.has.lengthOf(1);
+ let {data} = requests[0];
+ let {imp} = data;
+ expect(imp).to.be.an('array').that.has.lengthOf(bids.length);
+ let bid1 = imp[0];
+ expect(bid1.ext.r2b2).to.deep.equal({d: 'example.com', g: 'generic', p: '300x250', m: 1});
+ let bid2 = imp[1];
+ expect(bid2.ext.r2b2).to.deep.equal({d: 'example.com', g: 'generic', p: '300x600', m: 0});
+ });
+
+ it('should set up internal variables', function () {
+ let requests = spec.buildRequests(bids, bidderRequest);
+ let bid1Id = bids[0].bidId;
+ let bid2Id = bids[1].bidId;
+ expect(r2b2.placementsToSync).to.be.an('array').that.has.lengthOf(2);
+ expect(r2b2.mappedParams).to.have.property(bid1Id);
+ expect(r2b2.mappedParams[bid1Id]).to.deep.equal({d: 'example.com', g: 'generic', p: '300x250', m: 1, pid: 'example.com/generic/300x250/1'});
+ expect(r2b2.mappedParams).to.have.property(bid2Id);
+ expect(r2b2.mappedParams[bid2Id]).to.deep.equal({d: 'example.com', g: 'generic', p: '300x600', m: 0, pid: 'example.com/generic/300x600/0'});
+ });
+
+ it('should pass gdpr properties', function () {
+ let requests = spec.buildRequests(bids, bidderRequest);
+ let {data} = requests[0];
+ let {user, regs} = data;
+ expect(user).to.be.an('object').that.has.property('ext');
+ expect(regs).to.be.an('object').that.has.property('ext');
+ expect(user.ext.consent).to.equal('consent-string');
+ expect(regs.ext.gdpr).to.equal(1);
+ });
+
+ it('should pass us privacy properties', function () {
+ let requests = spec.buildRequests(bids, bidderRequest);
+ let {data} = requests[0];
+ let {regs} = data;
+ expect(regs).to.be.an('object').that.has.property('ext');
+ expect(regs.ext.us_privacy).to.equal('1YYY');
+ });
+
+ it('should pass supply chain', function () {
+ let requests = spec.buildRequests(bids, bidderRequest);
+ let {data} = requests[0];
+ let {source} = data;
+ expect(source).to.be.an('object').that.has.property('ext');
+ expect(source.ext.schain).to.deep.equal({
+ complete: 1,
+ nodes: [
+ {asi: 'example.com', hp: 1, sid: '00001'}
+ ],
+ ver: '1.0'
+ })
+ });
+
+ it('should pass extended ids', function () {
+ let eidsArray = [
+ {
+ source: 'adserver.org',
+ uids: [
+ {
+ atype: 1,
+ ext: {
+ rtiPartner: 'TDID',
+ },
+ id: 'TTD_ID_FROM_USER_ID_MODULE',
+ },
+ ],
+ },
+ {
+ source: 'pubcid.org',
+ uids: [
+ {
+ atype: 1,
+ id: 'pubCommonId_FROM_USER_ID_MODULE',
+ },
+ ],
+ },
+ ];
+ bids[0].userIdAsEids = eidsArray;
+ let requests = spec.buildRequests(bids, bidderRequest);
+ let request = requests[0];
+ let eids = request.data.user.ext.eids;
+
+ expect(eids).to.deep.equal(eidsArray);
+ });
+ });
+
+ describe('interpretResponse', function () {
+ it('should respond with empty response when there are no bids', function () {
+ let result = spec.interpretResponse({ body: {} }, {});
+ expect(result).to.be.an('array').that.has.lengthOf(0);
+ result = spec.interpretResponse({ body: { seatbid: [] } }, {});
+ expect(result).to.be.an('array').that.has.lengthOf(0);
+ result = spec.interpretResponse({ body: { seatbid: [ {} ] } }, {});
+ expect(result).to.be.an('array').that.has.lengthOf(0);
+ result = spec.interpretResponse({ body: { seatbid: [ { bids: [] } ] } }, {});
+ expect(result).to.be.an('array').that.has.lengthOf(0);
+ });
+
+ it('should map params correctly', function () {
+ let result = spec.interpretResponse({ body: serverResponse }, requestForInterpretResponse);
+ expect(result).to.be.an('array').that.has.lengthOf(1);
+ let bid = result[0];
+ expect(bid.requestId).to.equal(impId);
+ expect(bid.cpm).to.equal(price);
+ expect(bid.ad).to.equal(ad);
+ expect(bid.currency).to.equal('USD');
+ expect(bid.mediaType).to.equal('banner');
+ expect(bid.width).to.equal(300);
+ expect(bid.height).to.equal(250);
+ expect(bid.netRevenue).to.equal(true);
+ expect(bid.ttl).to.equal(360);
+ expect(bid.creativeId).to.equal(creativeId);
+ });
+
+ it('should set up renderer on bid', function () {
+ let result = spec.interpretResponse({ body: serverResponse }, requestForInterpretResponse);
+ expect(result).to.be.an('array').that.has.lengthOf(1);
+ let bid = result[0];
+ expect(bid.renderer).to.be.an('object');
+ expect(bid.renderer).to.have.property('render').that.is.a('function');
+ expect(bid.renderer).to.have.property('url').that.is.a('string');
+ });
+
+ it('should map ext params correctly', function() {
+ let dgpm = {something: 'something'};
+ r2b2.mappedParams = {};
+ r2b2.mappedParams[impId] = dgpm;
+ let result = spec.interpretResponse({ body: serverResponse }, requestForInterpretResponse);
+ expect(result).to.be.an('array').that.has.lengthOf(1);
+ let bid = result[0];
+ expect(bid.ext).to.be.an('object');
+ let { ext } = bid;
+ expect(ext.dgpm).to.deep.equal(dgpm);
+ expect(ext.cid).to.equal(cid);
+ expect(ext.cdid).to.equal(cdid);
+ expect(ext.adUnit).to.equal(unitCode);
+ expect(ext.mediaType).to.deep.equal({
+ type: 'banner',
+ settings: {
+ chd: null,
+ width: 300,
+ height: 250,
+ ad: {
+ type: 'content',
+ data: ad
+ }
+ }
+ });
+ });
+
+ it('should handle multiple bids', function() {
+ const impId2 = '123456';
+ const price2 = 12;
+ const ad2 = 'gaeouho';
+ const w2 = 300;
+ const h2 = 600;
+ let b = serverResponse.seatbid[0].bid[0];
+ let b2 = Object.assign({}, b);
+ b2.impid = impId2;
+ b2.price = price2;
+ b2.adm = ad2;
+ b2.w = w2;
+ b2.h = h2;
+ serverResponse.seatbid[0].bid.push(b2);
+ requestForInterpretResponse.data.imp.push({id: impId2});
+ let result = spec.interpretResponse({ body: serverResponse }, requestForInterpretResponse);
+ expect(result).to.be.an('array').that.has.lengthOf(2);
+ let firstBid = result[0];
+ let secondBid = result[1];
+ expect(firstBid.requestId).to.equal(impId);
+ expect(firstBid.ad).to.equal(ad);
+ expect(firstBid.cpm).to.equal(price);
+ expect(firstBid.width).to.equal(300);
+ expect(firstBid.height).to.equal(250);
+ expect(secondBid.requestId).to.equal(impId2);
+ expect(secondBid.ad).to.equal(ad2);
+ expect(secondBid.cpm).to.equal(price2);
+ expect(secondBid.width).to.equal(w2);
+ expect(secondBid.height).to.equal(h2);
+ });
+ });
+
+ describe('getUserSyncs', function() {
+ const syncOptions = {
+ iframeEnabled: true,
+ pixelEnabled: true
+ };
+
+ it('should return an array with a sync for all bids', function() {
+ r2b2.placementsToSync = [id1Object, id2Object];
+ const expectedEncodedIds = encodePlacementIds(r2b2.placementsToSync);
+ const syncs = spec.getUserSyncs(syncOptions);
+ expect(syncs).to.be.an('array').that.has.lengthOf(1);
+ const sync = syncs[0];
+ expect(sync).to.be.an('object');
+ expect(sync.type).to.equal('iframe');
+ expect(sync.url).to.include(`?p=${expectedEncodedIds}`);
+ });
+
+ it('should return the sync and include gdpr and usp parameters in the url', function() {
+ r2b2.placementsToSync = [id1Object, id2Object];
+ const syncs = spec.getUserSyncs(syncOptions, {}, gdprConsent, usPrivacyString);
+ const sync = syncs[0];
+ expect(sync).to.be.an('object');
+ expect(sync.url).to.include(`&gdpr=1`);
+ expect(sync.url).to.include(`&gdpr_consent=${gdprConsent.consentString}`);
+ expect(sync.url).to.include(`&us_privacy=${usPrivacyString}`);
+ });
+ });
+
+ describe('events', function() {
+ beforeEach(function() {
+ time = sinon.useFakeTimers(fakeTime);
+ sinon.stub(utils, 'triggerPixel');
+ r2b2.mappedParams = {};
+ r2b2.mappedParams[bidId1] = id1Object;
+ r2b2.mappedParams[bidId2] = id2Object;
+ bidStub = {
+ adserverTargeting: { hb_bidder: bidder, hb_pb: '10.00', hb_size: '300x300' },
+ cpm: 10,
+ currency: 'USD',
+ ext: {
+ dgpm: { d: 'r2b2.cz', g: 'generic', m: 1, p: '300x300', pid: 'r2b2.cz/generic/300x300/1' }
+ },
+ params: [ { pid: 'r2b2.cz/generic/300x300/1' } ],
+ };
+ });
+ afterEach(function() {
+ utils.triggerPixel.restore();
+ time.restore();
+ });
+
+ describe('onBidWon', function () {
+ it('exists and is a function', () => {
+ expect(spec.onBidWon).to.exist.and.to.be.a('function');
+ });
+ it('should return nothing and trigger a pixel with passed url', function () {
+ bidStub.ext.events = {
+ onBidWon: bidWonUrl,
+ onSetTargeting: setTargetingUrl
+ };
+ const response = spec.onBidWon(bidStub);
+ expect(response).to.be.an('undefined');
+ expect(utils.triggerPixel.called).to.equal(true);
+ expect(utils.triggerPixel.callCount).to.equal(1);
+ expect(utils.triggerPixel.calledWithMatch(bidWonUrl)).to.equal(true);
+ });
+ it('should not trigger a pixel if url is not available', function () {
+ bidStub.ext.events = null;
+ spec.onBidWon(bidStub);
+ expect(utils.triggerPixel.callCount).to.equal(0);
+ bidStub.ext.events = {
+ onBidWon: '',
+ onSetTargeting: '',
+ };
+ spec.onBidWon(bidStub);
+ expect(utils.triggerPixel.callCount).to.equal(0);
+ });
+ });
+
+ describe('onSetTargeting', function () {
+ it('exists and is a function', () => {
+ expect(spec.onSetTargeting).to.exist.and.to.be.a('function');
+ });
+ it('should return nothing and trigger a pixel with passed url', function () {
+ bidStub.ext.events = {
+ onBidWon: bidWonUrl,
+ onSetTargeting: setTargetingUrl
+ };
+ const response = spec.onSetTargeting(bidStub);
+ expect(response).to.be.an('undefined');
+ expect(utils.triggerPixel.called).to.equal(true);
+ expect(utils.triggerPixel.callCount).to.equal(1);
+ expect(utils.triggerPixel.calledWithMatch(setTargetingUrl)).to.equal(true);
+ });
+ it('should not trigger a pixel if url is not available', function () {
+ bidStub.ext.events = null;
+ spec.onSetTargeting(bidStub);
+ expect(utils.triggerPixel.callCount).to.equal(0);
+ bidStub.ext.events = {
+ onBidWon: '',
+ onSetTargeting: '',
+ };
+ spec.onSetTargeting(bidStub);
+ expect(utils.triggerPixel.callCount).to.equal(0);
+ });
+ });
+
+ describe('onTimeout', function () {
+ it('exists and is a function', () => {
+ expect(spec.onTimeout).to.exist.and.to.be.a('function');
+ });
+ it('should return nothing and trigger a pixel', function () {
+ const bids = [bid1, bid2];
+ const response = spec.onTimeout(bids);
+ expect(response).to.be.an('undefined');
+ expect(utils.triggerPixel.callCount).to.equal(1);
+ });
+ it('should not trigger a pixel if no bids available', function () {
+ const bids = [];
+ spec.onTimeout(bids);
+ expect(utils.triggerPixel.callCount).to.equal(0);
+ });
+ it('should trigger a pixel with correct ids and a cache buster', function () {
+ const bids = [bid1, bidForeign1, bidForeign2, bid2, bidWithBadSetup];
+ const expectedIds = [id1Object, id2Object];
+ const expectedEncodedIds = encodePlacementIds(expectedIds);
+ spec.onTimeout(bids);
+ expect(utils.triggerPixel.callCount).to.equal(1);
+ const triggeredUrl = utils.triggerPixel.args[0][0];
+ expect(triggeredUrl).to.include(`p=${expectedEncodedIds}`);
+ expect(triggeredUrl.match(cacheBusterRegex)).to.exist;
+ });
+ });
+
+ describe('onBidderError', function () {
+ it('exists and is a function', () => {
+ expect(spec.onBidderError).to.exist.and.to.be.a('function');
+ });
+ it('should return nothing and trigger a pixel', function () {
+ const bidderRequest = { bids: [bid1, bid2] };
+ const response = spec.onBidderError({ bidderRequest });
+ expect(response).to.be.an('undefined')
+ expect(utils.triggerPixel.callCount).to.equal(1);
+ });
+ it('should not trigger a pixel if no bids available', function () {
+ const bidderRequest = { bids: [] };
+ spec.onBidderError({ bidderRequest });
+ expect(utils.triggerPixel.callCount).to.equal(0);
+ });
+ it('should call triggerEvent with correct ids and a cache buster', function () {
+ const bids = [bid1, bid2, bidWithBadSetup]
+ const bidderRequest = { bids };
+ const expectedIds = [id1Object, id2Object];
+ const expectedEncodedIds = encodePlacementIds(expectedIds);
+ spec.onBidderError({ bidderRequest });
+ expect(utils.triggerPixel.callCount).to.equal(1);
+ const triggeredUrl = utils.triggerPixel.args[0][0];
+ expect(triggeredUrl).to.include(`p=${expectedEncodedIds}`);
+ expect(triggeredUrl.match(cacheBusterRegex)).to.exist;
+ });
+ });
+ });
+});
diff --git a/test/spec/modules/raynRtdProvider_spec.js b/test/spec/modules/raynRtdProvider_spec.js
new file mode 100644
index 00000000000..69ea316e8b5
--- /dev/null
+++ b/test/spec/modules/raynRtdProvider_spec.js
@@ -0,0 +1,308 @@
+import * as raynRTD from 'modules/raynRtdProvider.js';
+import { config } from 'src/config.js';
+import * as utils from 'src/utils.js';
+
+const TEST_CHECKSUM = '-1135402174';
+const TEST_URL = 'http://localhost:9876/context.html';
+const TEST_SEGMENTS = {
+ [TEST_CHECKSUM]: {
+ 7: {
+ 2: ['51', '246', '652', '48', '324']
+ }
+ }
+};
+
+const RTD_CONFIG = {
+ auctionDelay: 250,
+ dataProviders: [
+ {
+ name: 'rayn',
+ waitForIt: true,
+ params: {
+ bidders: [],
+ integration: {
+ iabAudienceCategories: {
+ v1_1: {
+ tier: 6,
+ enabled: true,
+ },
+ },
+ iabContentCategories: {
+ v3_0: {
+ tier: 4,
+ enabled: true,
+ },
+ v2_2: {
+ tier: 4,
+ enabled: true,
+ },
+ },
+ }
+ },
+ },
+ ],
+};
+
+describe('rayn RTD Submodule', function () {
+ let getDataFromLocalStorageStub;
+
+ beforeEach(function () {
+ config.resetConfig();
+ getDataFromLocalStorageStub = sinon.stub(
+ raynRTD.storage,
+ 'getDataFromLocalStorage',
+ );
+ });
+
+ afterEach(function () {
+ getDataFromLocalStorageStub.restore();
+ });
+
+ describe('Initialize module', function () {
+ it('should initialize and return true', function () {
+ expect(raynRTD.raynSubmodule.init(RTD_CONFIG.dataProviders[0])).to.equal(
+ true,
+ );
+ });
+ });
+
+ describe('Generate ortb data object', function () {
+ it('should set empty segment array', function () {
+ expect(raynRTD.generateOrtbDataObject(7, 'invalid', 2).segment).to.be.instanceOf(Array).and.lengthOf(0);
+ });
+
+ it('should set segment array', function () {
+ const expectedSegmentIdsMap = TEST_SEGMENTS[TEST_CHECKSUM][7][2].map((id) => {
+ return { id };
+ });
+ expect(raynRTD.generateOrtbDataObject(7, TEST_SEGMENTS[TEST_CHECKSUM][7], 4)).to.deep.equal({
+ name: raynRTD.SEGMENTS_RESOLVER,
+ ext: {
+ segtax: 7,
+ },
+ segment: expectedSegmentIdsMap,
+ });
+ });
+ });
+
+ describe('Generate checksum', function () {
+ it('should generate checksum', function () {
+ expect(raynRTD.generateChecksum(TEST_URL)).to.equal(TEST_CHECKSUM);
+ });
+ });
+
+ describe('Get segments', function () {
+ it('should get segments from local storage', function () {
+ getDataFromLocalStorageStub
+ .withArgs(raynRTD.RAYN_LOCAL_STORAGE_KEY)
+ .returns(JSON.stringify(TEST_SEGMENTS));
+
+ const segments = raynRTD.readSegments(raynRTD.RAYN_LOCAL_STORAGE_KEY);
+
+ expect(segments).to.deep.equal(TEST_SEGMENTS);
+ });
+
+ it('should return null if unable to read and parse data from local storage', function () {
+ const testString = 'test';
+ getDataFromLocalStorageStub
+ .withArgs(raynRTD.RAYN_LOCAL_STORAGE_KEY)
+ .returns(testString);
+
+ const segments = raynRTD.readSegments(raynRTD.RAYN_LOCAL_STORAGE_KEY);
+
+ expect(segments).to.equal(null);
+ });
+ });
+
+ describe('Set segments as bidder ortb2', function () {
+ it('should set global ortb2 config', function () {
+ const globalOrtb2 = {};
+ const bidders = RTD_CONFIG.dataProviders[0].params.bidders;
+ const integrationConfig = RTD_CONFIG.dataProviders[0].params.integration;
+
+ raynRTD.setSegmentsAsBidderOrtb2({ ortb2Fragments: { global: globalOrtb2 } }, bidders, integrationConfig, TEST_SEGMENTS, TEST_CHECKSUM);
+
+ TEST_SEGMENTS[TEST_CHECKSUM]['7']['2'].forEach((id) => {
+ expect(globalOrtb2.site.content.data[0].segment.find(segment => segment.id === id)).to.exist;
+ })
+ });
+
+ it('should set bidder specific ortb2 config', function () {
+ RTD_CONFIG.dataProviders[0].params.bidders = ['appnexus'];
+
+ const bidderOrtb2 = {};
+ const bidders = RTD_CONFIG.dataProviders[0].params.bidders;
+ const integrationConfig = RTD_CONFIG.dataProviders[0].params.integration;
+
+ raynRTD.setSegmentsAsBidderOrtb2({ ortb2Fragments: { bidder: bidderOrtb2 } }, bidders, integrationConfig, TEST_SEGMENTS, TEST_CHECKSUM);
+
+ bidders.forEach((bidder) => {
+ const ortb2 = bidderOrtb2[bidder];
+ TEST_SEGMENTS[TEST_CHECKSUM]['7']['2'].forEach((id) => {
+ expect(ortb2.site.content.data[0].segment.find(segment => segment.id === id)).to.exist;
+ })
+ });
+ });
+
+ it('should set bidder specific ortb2 config with all segments', function () {
+ TEST_SEGMENTS['4'] = {
+ 3: ['4', '17', '72', '612']
+ };
+ TEST_SEGMENTS[TEST_CHECKSUM]['6'] = {
+ 2: ['71', '313'],
+ 4: ['33', '145', '712']
+ };
+
+ const bidderOrtb2 = {};
+ const bidders = RTD_CONFIG.dataProviders[0].params.bidders;
+ const integrationConfig = RTD_CONFIG.dataProviders[0].params.integration;
+
+ raynRTD.setSegmentsAsBidderOrtb2({ ortb2Fragments: { bidder: bidderOrtb2 } }, bidders, integrationConfig, TEST_SEGMENTS, TEST_CHECKSUM);
+
+ bidders.forEach((bidder) => {
+ const ortb2 = bidderOrtb2[bidder];
+
+ TEST_SEGMENTS[TEST_CHECKSUM]['6']['2'].forEach((id) => {
+ expect(ortb2.site.content.data[0].segment.find(segment => segment.id === id)).to.exist;
+ });
+ TEST_SEGMENTS[TEST_CHECKSUM]['6']['4'].forEach((id) => {
+ expect(ortb2.site.content.data[0].segment.find(segment => segment.id === id)).to.exist;
+ });
+ TEST_SEGMENTS[TEST_CHECKSUM]['7']['2'].forEach((id) => {
+ expect(ortb2.site.content.data[1].segment.find(segment => segment.id === id)).to.exist;
+ });
+ TEST_SEGMENTS['4']['3'].forEach((id) => {
+ expect(ortb2.user.data[0].segment.find(segment => segment.id === id)).to.exist;
+ });
+ });
+ });
+ });
+
+ describe('Alter Bid Requests', function () {
+ it('should update reqBidsConfigObj and execute callback', function () {
+ const callbackSpy = sinon.spy();
+ const logMessageSpy = sinon.spy(utils, 'logMessage');
+
+ getDataFromLocalStorageStub
+ .withArgs(raynRTD.RAYN_LOCAL_STORAGE_KEY)
+ .returns(JSON.stringify(TEST_SEGMENTS));
+
+ const reqBidsConfigObj = { ortb2Fragments: { bidder: {} } };
+
+ raynRTD.raynSubmodule.getBidRequestData(reqBidsConfigObj, callbackSpy, RTD_CONFIG);
+
+ expect(callbackSpy.calledOnce).to.be.true;
+ expect(logMessageSpy.lastCall.lastArg).to.equal(`Segtax data from localStorage: ${JSON.stringify(TEST_SEGMENTS)}`);
+
+ logMessageSpy.restore();
+ });
+
+ it('should update reqBidsConfigObj and execute callback using user segments from localStorage', function () {
+ const callbackSpy = sinon.spy();
+ const logMessageSpy = sinon.spy(utils, 'logMessage');
+ const testSegments = {
+ 4: {
+ 3: ['4', '17', '72', '612']
+ }
+ };
+
+ getDataFromLocalStorageStub
+ .withArgs(raynRTD.RAYN_LOCAL_STORAGE_KEY)
+ .returns(JSON.stringify(testSegments));
+
+ RTD_CONFIG.dataProviders[0].params.integration.iabContentCategories = {
+ v3_0: {
+ enabled: false,
+ },
+ v2_2: {
+ enabled: false,
+ },
+ };
+
+ const reqBidsConfigObj = { ortb2Fragments: { bidder: {} } };
+
+ raynRTD.raynSubmodule.getBidRequestData(reqBidsConfigObj, callbackSpy, RTD_CONFIG.dataProviders[0]);
+
+ expect(callbackSpy.calledOnce).to.be.true;
+ expect(logMessageSpy.lastCall.lastArg).to.equal(`Segtax data from localStorage: ${JSON.stringify(testSegments)}`);
+
+ logMessageSpy.restore();
+ });
+
+ it('should update reqBidsConfigObj and execute callback using segments from raynJS', function () {
+ const callbackSpy = sinon.spy();
+ const logMessageSpy = sinon.spy(utils, 'logMessage');
+
+ getDataFromLocalStorageStub
+ .withArgs(raynRTD.RAYN_LOCAL_STORAGE_KEY)
+ .returns(null);
+
+ const reqBidsConfigObj = { ortb2Fragments: { bidder: {} } };
+
+ raynRTD.raynSubmodule.getBidRequestData(reqBidsConfigObj, callbackSpy, RTD_CONFIG.dataProviders[0]);
+
+ expect(callbackSpy.calledOnce).to.be.true;
+ expect(logMessageSpy.lastCall.lastArg).to.equal(`No segtax data`);
+
+ logMessageSpy.restore();
+ });
+
+ it('should update reqBidsConfigObj and execute callback using audience from localStorage', function (done) {
+ const callbackSpy = sinon.spy();
+ const logMessageSpy = sinon.spy(utils, 'logMessage');
+ const testSegments = {
+ 6: {
+ 4: ['3', '27', '177']
+ }
+ };
+
+ global.window.raynJS = {
+ getSegtax: function () {
+ return Promise.resolve(testSegments);
+ }
+ };
+
+ getDataFromLocalStorageStub
+ .withArgs(raynRTD.RAYN_LOCAL_STORAGE_KEY)
+ .returns(null);
+
+ const reqBidsConfigObj = { ortb2Fragments: { bidder: {} } };
+
+ raynRTD.raynSubmodule.getBidRequestData(reqBidsConfigObj, callbackSpy, RTD_CONFIG.dataProviders[0]);
+
+ setTimeout(() => {
+ expect(callbackSpy.calledOnce).to.be.true;
+ expect(logMessageSpy.lastCall.lastArg).to.equal(`Segtax data from RaynJS: ${JSON.stringify(testSegments)}`);
+ logMessageSpy.restore();
+ done();
+ }, 0)
+ });
+
+ it('should execute callback if log error', function (done) {
+ const callbackSpy = sinon.spy();
+ const logErrorSpy = sinon.spy(utils, 'logError');
+ const rejectError = 'Error';
+
+ global.window.raynJS = {
+ getSegtax: function () {
+ return Promise.reject(rejectError);
+ }
+ };
+
+ getDataFromLocalStorageStub
+ .withArgs(raynRTD.RAYN_LOCAL_STORAGE_KEY)
+ .returns(null);
+
+ const reqBidsConfigObj = { ortb2Fragments: { bidder: {} } };
+
+ raynRTD.raynSubmodule.getBidRequestData(reqBidsConfigObj, callbackSpy, RTD_CONFIG.dataProviders[0]);
+
+ setTimeout(() => {
+ expect(callbackSpy.calledOnce).to.be.true;
+ expect(logErrorSpy.lastCall.lastArg).to.equal(rejectError);
+ logErrorSpy.restore();
+ done();
+ }, 0)
+ });
+ });
+});
diff --git a/test/spec/modules/relaidoBidAdapter_spec.js b/test/spec/modules/relaidoBidAdapter_spec.js
index 7778e9cbf80..f0d019913e8 100644
--- a/test/spec/modules/relaidoBidAdapter_spec.js
+++ b/test/spec/modules/relaidoBidAdapter_spec.js
@@ -239,6 +239,7 @@ describe('RelaidoAdapter', function () {
const request = data.bids[0];
expect(bidRequests.method).to.equal('POST');
expect(bidRequests.url).to.equal('https://api.relaido.jp/bid/v1/sprebid');
+ expect(data.canonical_url).to.equal('https://publisher.com/home');
expect(data.canonical_url_hash).to.equal('e6092f44a0044903ae3764126eedd6187c1d9f04');
expect(data.ref).to.equal(bidderRequest.refererInfo.page);
expect(data.timeout_ms).to.equal(bidderRequest.timeout);
@@ -317,6 +318,23 @@ describe('RelaidoAdapter', function () {
expect(data.bids).to.have.lengthOf(1);
expect(data.imuid).to.equal('i.tjHcK_7fTcqnbrS_YA2vaw');
});
+
+ it('should get userIdAsEids', function () {
+ const userIdAsEids = [
+ {
+ source: 'hogehoge.com',
+ uids: {
+ atype: 1,
+ id: 'hugahuga'
+ }
+ }
+ ]
+ bidRequest.userIdAsEids = userIdAsEids
+ const bidRequests = spec.buildRequests([bidRequest], bidderRequest);
+ const data = JSON.parse(bidRequests.data);
+ expect(data.bids[0].userIdAsEids).to.have.lengthOf(1);
+ expect(data.bids[0].userIdAsEids[0].source).to.equal('hogehoge.com');
+ });
});
describe('spec.interpretResponse', function () {
@@ -325,6 +343,7 @@ describe('RelaidoAdapter', function () {
expect(bidResponses).to.have.lengthOf(1);
const response = bidResponses[0];
expect(response.requestId).to.equal(serverRequest.data.bids[0].bidId);
+ expect(response.placementId).to.equal(serverResponse.body.ads[0].placementId);
expect(response.width).to.equal(serverRequest.data.bids[0].width);
expect(response.height).to.equal(serverRequest.data.bids[0].height);
expect(response.cpm).to.equal(serverResponse.body.ads[0].price);
@@ -343,6 +362,7 @@ describe('RelaidoAdapter', function () {
expect(bidResponses).to.have.lengthOf(1);
const response = bidResponses[0];
expect(response.requestId).to.equal(serverRequest.data.bids[0].bidId);
+ expect(response.placementId).to.equal(serverResponse.body.ads[0].placementId);
expect(response.width).to.equal(serverRequest.data.bids[0].width);
expect(response.height).to.equal(serverRequest.data.bids[0].height);
expect(response.cpm).to.equal(serverResponse.body.ads[0].price);
@@ -360,6 +380,7 @@ describe('RelaidoAdapter', function () {
expect(bidResponses).to.have.lengthOf(1);
const response = bidResponses[0];
expect(response.requestId).to.equal(serverRequest.data.bids[0].bidId);
+ expect(response.placementId).to.equal(serverResponseBanner.body.ads[0].placementId);
expect(response.cpm).to.equal(serverResponseBanner.body.ads[0].price);
expect(response.currency).to.equal(serverResponseBanner.body.ads[0].currency);
expect(response.creativeId).to.equal(serverResponseBanner.body.ads[0].creativeId);
diff --git a/test/spec/modules/richaudienceBidAdapter_spec.js b/test/spec/modules/richaudienceBidAdapter_spec.js
index ea45ff7e0b0..20c60ca328a 100644
--- a/test/spec/modules/richaudienceBidAdapter_spec.js
+++ b/test/spec/modules/richaudienceBidAdapter_spec.js
@@ -4,6 +4,8 @@ import {
spec
} from 'modules/richaudienceBidAdapter.js';
import {config} from 'src/config.js';
+import * as utils from 'src/utils.js';
+import sinon from 'sinon';
describe('Richaudience adapter tests', function () {
var DEFAULT_PARAMS_NEW_SIZES = [{
@@ -64,6 +66,30 @@ describe('Richaudience adapter tests', function () {
user: {}
}];
+ var DEFAULT_PARAMS_VIDEO_TIMEOUT = [{
+ adUnitCode: 'test-div',
+ bidId: '2c7c8e9c900244',
+ mediaTypes: {
+ video: {
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4']
+ }
+ },
+ bidder: 'richaudience',
+ params: [{
+ bidfloor: 0.5,
+ pid: 'ADb1f40rmi',
+ supplyType: 'site'
+ }],
+ timeout: 3000,
+ auctionId: '0cb3144c-d084-4686-b0d6-f5dbe917c563',
+ bidRequestsCount: 1,
+ bidderRequestId: '1858b7382993ca',
+ transactionId: '29df2112-348b-4961-8863-1b33684d95e6',
+ user: {}
+ }]
+
var DEFAULT_PARAMS_VIDEO_IN = [{
adUnitCode: 'test-div',
bidId: '2c7c8e9c900244',
@@ -879,6 +905,24 @@ describe('Richaudience adapter tests', function () {
expect(requestContent).to.have.property('gpid').and.to.equal('/19968336/header-bid-tag-1#example-2');
})
+ describe('onTimeout', function () {
+ beforeEach(function() {
+ sinon.stub(utils, 'triggerPixel');
+ });
+
+ afterEach(function() {
+ utils.triggerPixel.restore();
+ });
+ it('onTimeout exist as a function', () => {
+ expect(spec.onTimeout).to.exist.and.to.be.a('function');
+ });
+ it('should send timeout', function () {
+ spec.onTimeout(DEFAULT_PARAMS_VIDEO_TIMEOUT);
+ expect(utils.triggerPixel.called).to.equal(true);
+ expect(utils.triggerPixel.firstCall.args[0]).to.equal('https://s.richaudience.com/err/?ec=6&ev=3000&pla=ADb1f40rmi&int=PREBID&pltfm=&node=&dm=localhost:9876');
+ });
+ });
+
describe('userSync', function () {
it('Verifies user syncs iframe include', function () {
config.setConfig({
diff --git a/test/spec/modules/riseBidAdapter_spec.js b/test/spec/modules/riseBidAdapter_spec.js
index eed8d74f271..ec9309fd4ae 100644
--- a/test/spec/modules/riseBidAdapter_spec.js
+++ b/test/spec/modules/riseBidAdapter_spec.js
@@ -22,6 +22,12 @@ describe('riseAdapter', function () {
});
});
+ describe('bid adapter', function () {
+ it('should have aliases', function () {
+ expect(spec.aliases).to.be.an('array').that.is.not.empty;
+ });
+ });
+
describe('isBidRequestValid', function () {
const bid = {
'bidder': spec.code,
@@ -53,7 +59,7 @@ describe('riseAdapter', function () {
'adUnitCode': 'adunit-code',
'sizes': [[640, 480]],
'params': {
- 'org': 'jdye8weeyirk00000001'
+ 'org': 'jdye8weeyirk00000001',
},
'bidId': '299ffc8cca0b87',
'loop': 1,
@@ -195,6 +201,16 @@ describe('riseAdapter', function () {
expect(request.data.bids[1].mediaType).to.equal(BANNER)
});
+ it('should send the correct currency in bid request', function () {
+ const bid = utils.deepClone(bidRequests[0]);
+ bid.params = {
+ 'currency': 'EUR'
+ };
+ const expectedCurrency = bid.params.currency;
+ const request = spec.buildRequests([bid], bidderRequest);
+ expect(request.data.bids[0].currency).to.equal(expectedCurrency);
+ });
+
it('should respect syncEnabled option', function() {
config.setConfig({
userSync: {
@@ -308,6 +324,24 @@ describe('riseAdapter', function () {
expect(request.data.params).to.have.property('gdpr_consent', 'test-consent-string');
});
+ it('should not send the gpp param if gppConsent is false in the bidRequest', function () {
+ const bidderRequestWithoutGPP = Object.assign({gppConsent: false}, bidderRequest);
+ const request = spec.buildRequests(bidRequests, bidderRequestWithoutGPP);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.not.have.property('gpp');
+ expect(request.data.params).to.not.have.property('gpp_sid');
+ });
+
+ it('should send the gpp param if gppConsent is true in the bidRequest', function () {
+ const bidderRequestWithGPP = Object.assign({gppConsent: {gppString: 'gpp-consent', applicableSections: [7]}}, bidderRequest);
+ const request = spec.buildRequests(bidRequests, bidderRequestWithGPP);
+ console.log('request.data.params');
+ console.log(request.data.params);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.have.property('gpp', 'gpp-consent');
+ expect(request.data.params.gpp_sid[0]).to.be.equal(7);
+ });
+
it('should have schain param if it is available in the bidRequest', () => {
const schain = {
ver: '1.0',
diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js
index 3f3cbfbb46c..f0e33ce940e 100644
--- a/test/spec/modules/rubiconBidAdapter_spec.js
+++ b/test/spec/modules/rubiconBidAdapter_spec.js
@@ -2381,16 +2381,6 @@ describe('the rubicon adapter', function () {
bidderRequest = createVideoBidderRequest();
delete bidderRequest.bids[0].mediaTypes.video.linearity;
expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false);
-
- // change api to an string, no good
- bidderRequest = createVideoBidderRequest();
- bidderRequest.bids[0].mediaTypes.video.api = 'string';
- expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false);
-
- // delete api, no good
- bidderRequest = createVideoBidderRequest();
- delete bidderRequest.bids[0].mediaTypes.video.api;
- expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false);
});
it('bid request is valid when video context is outstream', function () {
diff --git a/test/spec/modules/seedtagBidAdapter_spec.js b/test/spec/modules/seedtagBidAdapter_spec.js
index fb666e89f73..516c5ec933a 100644
--- a/test/spec/modules/seedtagBidAdapter_spec.js
+++ b/test/spec/modules/seedtagBidAdapter_spec.js
@@ -2,10 +2,24 @@ import { expect } from 'chai';
import { spec, getTimeoutUrl } from 'modules/seedtagBidAdapter.js';
import * as utils from 'src/utils.js';
import { config } from '../../../src/config.js';
+import * as mockGpt from 'test/spec/integration/faker/googletag.js';
const PUBLISHER_ID = '0000-0000-01';
const ADUNIT_ID = '000000';
+const adUnitCode = '/19968336/header-bid-tag-0'
+
+// create a default adunit
+const slot = document.createElement('div');
+slot.id = adUnitCode;
+slot.style.width = '300px'
+slot.style.height = '250px'
+slot.style.position = 'absolute'
+slot.style.top = '10px'
+slot.style.left = '20px'
+
+document.body.appendChild(slot);
+
function getSlotConfigs(mediaTypes, params) {
return {
params: params,
@@ -25,7 +39,7 @@ function getSlotConfigs(mediaTypes, params) {
tid: 'd704d006-0d6e-4a09-ad6c-179e7e758096',
}
},
- adUnitCode: 'adunit-code',
+ adUnitCode: adUnitCode,
};
}
@@ -46,6 +60,13 @@ const createBannerSlotConfig = (placement, mediatypes) => {
};
describe('Seedtag Adapter', function () {
+ beforeEach(function () {
+ mockGpt.reset();
+ });
+
+ afterEach(function () {
+ mockGpt.enable();
+ });
describe('isBidRequestValid method', function () {
describe('returns true', function () {
describe('when banner slot config has all mandatory params', () => {
@@ -277,7 +298,7 @@ describe('Seedtag Adapter', function () {
expect(data.auctionStart).to.be.greaterThanOrEqual(now);
expect(data.ttfb).to.be.greaterThanOrEqual(0);
- expect(data.bidRequests[0].adUnitCode).to.equal('adunit-code');
+ expect(data.bidRequests[0].adUnitCode).to.equal(adUnitCode);
});
describe('GDPR params', function () {
@@ -374,6 +395,35 @@ describe('Seedtag Adapter', function () {
expect(videoBid.sizes[1][1]).to.equal(600);
expect(videoBid.requestCount).to.equal(1);
});
+
+ it('should have geom parameters if slot is available', function() {
+ const request = spec.buildRequests(validBidRequests, bidderRequest);
+ const data = JSON.parse(request.data);
+ const bidRequests = data.bidRequests;
+ const bannerBid = bidRequests[0];
+
+ // on some CI, the DOM is not initialized, so we need to check if the slot is available
+ const slot = document.getElementById(adUnitCode)
+ if (slot) {
+ expect(bannerBid).to.have.property('geom')
+
+ const params = [['width', 300], ['height', 250], ['top', 10], ['left', 20], ['scrollY', 0]]
+ params.forEach(([param, value]) => {
+ expect(bannerBid.geom).to.have.property(param)
+ expect(bannerBid.geom[param]).to.be.a('number')
+ expect(bannerBid.geom[param]).to.be.equal(value)
+ })
+
+ expect(bannerBid.geom).to.have.property('viewport')
+ const viewportParams = ['width', 'height']
+ viewportParams.forEach(param => {
+ expect(bannerBid.geom.viewport).to.have.property(param)
+ expect(bannerBid.geom.viewport[param]).to.be.a('number')
+ })
+ } else {
+ expect(bannerBid).to.not.have.property('geom')
+ }
+ })
});
describe('COPPA param', function () {
diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js
index eb0b45dda11..1bb6f898b81 100644
--- a/test/spec/modules/sharethroughBidAdapter_spec.js
+++ b/test/spec/modules/sharethroughBidAdapter_spec.js
@@ -585,6 +585,64 @@ describe('sharethrough adapter spec', function () {
expect(videoImp.placement).to.equal(4);
});
+
+ it('should not override "placement" value if "plcmt" prop is present', () => {
+ // ASSEMBLE
+ const ARBITRARY_PLACEMENT_VALUE = 99;
+ const ARBITRARY_PLCMT_VALUE = 100;
+
+ bidRequests[1].mediaTypes.video.context = 'instream';
+ bidRequests[1].mediaTypes.video.placement = ARBITRARY_PLACEMENT_VALUE;
+
+ // adding "plcmt" property - this should prevent "placement" prop
+ // from getting overridden to 1
+ bidRequests[1].mediaTypes.video['plcmt'] = ARBITRARY_PLCMT_VALUE;
+
+ // ACT
+ const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1];
+ const videoImp = builtRequest.data.imp[0].video;
+
+ // ASSERT
+ expect(videoImp.placement).to.equal(ARBITRARY_PLACEMENT_VALUE);
+ expect(videoImp.plcmt).to.equal(ARBITRARY_PLCMT_VALUE);
+ });
+ });
+ });
+
+ describe('cookie deprecation', () => {
+ it('should not add cdep if we do not get it in an impression request', () => {
+ const builtRequests = spec.buildRequests(bidRequests, {
+ auctionId: 'new-auction-id',
+ ortb2: {
+ device: {
+ ext: {
+ propThatIsNotCdep: 'value-we-dont-care-about',
+ },
+ },
+ },
+ });
+ const noCdep = builtRequests.every((builtRequest) => {
+ const ourCdepValue = builtRequest.data.device?.ext?.cdep;
+ return ourCdepValue === undefined;
+ });
+ expect(noCdep).to.be.true;
+ });
+
+ it('should add cdep if we DO get it in an impression request', () => {
+ const builtRequests = spec.buildRequests(bidRequests, {
+ auctionId: 'new-auction-id',
+ ortb2: {
+ device: {
+ ext: {
+ cdep: 'cdep-value',
+ },
+ },
+ },
+ });
+ const cdepPresent = builtRequests.every((builtRequest) => {
+ return builtRequest.data.device.ext.cdep === 'cdep-value';
+ });
+ expect(cdepPresent).to.be.true;
});
});
@@ -655,6 +713,22 @@ describe('sharethrough adapter spec', function () {
expect(openRtbReq.regs.ext.gpp_sid).to.equal(firstPartyData.regs.gpp_sid);
});
});
+
+ describe('fledge', () => {
+ it('should attach "ae" as a property to the request if 1) fledge auctions are enabled, and 2) request is display (only supporting display for now)', () => {
+ // ASSEMBLE
+ const EXPECTED_AE_VALUE = 1;
+
+ // ACT
+ bidderRequest['fledgeEnabled'] = true;
+ const builtRequests = spec.buildRequests(bidRequests, bidderRequest);
+ const ACTUAL_AE_VALUE = builtRequests[0].data.imp[0].ext.ae;
+
+ // ASSERT
+ expect(ACTUAL_AE_VALUE).to.equal(EXPECTED_AE_VALUE);
+ expect(builtRequests[1].data.imp[0].ext.ae).to.be.undefined;
+ });
+ });
});
describe('interpretResponse', function () {
diff --git a/test/spec/modules/shinezRtbBidAdapter_spec.js b/test/spec/modules/shinezRtbBidAdapter_spec.js
new file mode 100644
index 00000000000..3965cd69c5f
--- /dev/null
+++ b/test/spec/modules/shinezRtbBidAdapter_spec.js
@@ -0,0 +1,639 @@
+import {expect} from 'chai';
+import {
+ spec as adapter,
+ createDomain,
+ hashCode,
+ extractPID,
+ extractCID,
+ extractSubDomain,
+ getStorageItem,
+ setStorageItem,
+ tryParseJSON,
+ getUniqueDealId,
+} from 'modules/shinezRtbBidAdapter';
+import * as utils from 'src/utils.js';
+import {version} from 'package.json';
+import {useFakeTimers} from 'sinon';
+import {BANNER, VIDEO} from '../../../src/mediaTypes';
+import {config} from '../../../src/config';
+import {deepAccess} from 'src/utils.js';
+
+export const TEST_ID_SYSTEMS = ['britepoolid', 'criteoId', 'id5id', 'idl_env', 'lipb', 'netId', 'parrableId', 'pubcid', 'tdid', 'pubProvidedId', 'digitrustid'];
+
+const SUB_DOMAIN = 'exchange';
+
+const BID = {
+ 'bidId': '2d52001cabd527',
+ 'adUnitCode': 'div-gpt-ad-12345-0',
+ 'params': {
+ 'subDomain': SUB_DOMAIN,
+ 'cId': '59db6b3b4ffaa70004f45cdc',
+ 'pId': '59ac17c192832d0011283fe3',
+ 'bidFloor': 0.1,
+ 'ext': {
+ 'param1': 'loremipsum',
+ 'param2': 'dolorsitamet'
+ }
+ },
+ 'placementCode': 'div-gpt-ad-1460505748561-0',
+ 'sizes': [[300, 250], [300, 600]],
+ 'bidderRequestId': '1fdb5ff1b6eaa7',
+ 'bidRequestsCount': 4,
+ 'bidderRequestsCount': 3,
+ 'bidderWinsCount': 1,
+ 'requestId': 'b0777d85-d061-450e-9bc7-260dd54bbb7a',
+ 'schain': 'a0819c69-005b-41ed-af06-1be1e0aefefc',
+ 'mediaTypes': [BANNER],
+ 'ortb2Imp': {
+ 'ext': {
+ 'gpid': '0123456789',
+ 'tid': '56e184c6-bde9-497b-b9b9-cf47a61381ee'
+ }
+ }
+};
+
+const VIDEO_BID = {
+ 'bidId': '2d52001cabd527',
+ 'adUnitCode': '63550ad1ff6642d368cba59dh5884270560',
+ 'bidderRequestId': '12a8ae9ada9c13',
+ 'bidRequestsCount': 4,
+ 'bidderRequestsCount': 3,
+ 'bidderWinsCount': 1,
+ 'schain': 'a0819c69-005b-41ed-af06-1be1e0aefefc',
+ 'params': {
+ 'subDomain': SUB_DOMAIN,
+ 'cId': '635509f7ff6642d368cb9837',
+ 'pId': '59ac17c192832d0011283fe3',
+ 'bidFloor': 0.1
+ },
+ 'sizes': [[545, 307]],
+ 'mediaTypes': {
+ 'video': {
+ 'playerSize': [[545, 307]],
+ 'context': 'instream',
+ 'mimes': [
+ 'video/mp4',
+ 'application/javascript'
+ ],
+ 'protocols': [2, 3, 5, 6],
+ 'maxduration': 60,
+ 'minduration': 0,
+ 'startdelay': 0,
+ 'linearity': 1,
+ 'api': [2],
+ 'placement': 1
+ }
+ },
+ 'ortb2Imp': {
+ 'ext': {
+ 'gpid': '0123456789',
+ 'tid': '56e184c6-bde9-497b-b9b9-cf47a61381ee'
+ }
+ }
+}
+
+const BIDDER_REQUEST = {
+ 'gdprConsent': {
+ 'consentString': 'consent_string',
+ 'gdprApplies': true
+ },
+ 'gppConsent': {
+ 'gppString': 'gpp_string',
+ 'applicableSections': [7]
+ },
+ 'uspConsent': 'consent_string',
+ 'refererInfo': {
+ 'page': 'https://www.greatsite.com',
+ 'ref': 'https://www.somereferrer.com'
+ },
+ 'ortb2': {
+ 'regs': {
+ 'gpp': 'gpp_string',
+ 'gpp_sid': [7]
+ },
+ 'device': {
+ 'sua': {
+ 'source': 2,
+ 'platform': {
+ 'brand': 'Android',
+ 'version': ['8', '0', '0']
+ },
+ 'browsers': [
+ {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']},
+ {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']},
+ {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']}
+ ],
+ 'mobile': 1,
+ 'model': 'SM-G955U',
+ 'bitness': '64',
+ 'architecture': ''
+ }
+ }
+ }
+};
+
+const SERVER_RESPONSE = {
+ body: {
+ cid: 'testcid123',
+ results: [{
+ 'ad': '
',
+ 'price': 0.8,
+ 'creativeId': '12610997325162499419',
+ 'exp': 30,
+ 'width': 300,
+ 'height': 250,
+ 'advertiserDomains': ['securepubads.g.doubleclick.net'],
+ 'cookies': [{
+ 'src': 'https://sync.com',
+ 'type': 'iframe'
+ }, {
+ 'src': 'https://sync.com',
+ 'type': 'img'
+ }]
+ }]
+ }
+};
+
+const VIDEO_SERVER_RESPONSE = {
+ body: {
+ 'cid': '635509f7ff6642d368cb9837',
+ 'results': [{
+ 'ad': '
',
+ 'advertiserDomains': ['sweetgum.io'],
+ 'exp': 60,
+ 'width': 545,
+ 'height': 307,
+ 'mediaType': 'video',
+ 'creativeId': '12610997325162499419',
+ 'price': 2,
+ 'cookies': []
+ }]
+ }
+};
+
+const REQUEST = {
+ data: {
+ width: 300,
+ height: 250,
+ bidId: '2d52001cabd527'
+ }
+};
+
+function getTopWindowQueryParams() {
+ try {
+ const parsedUrl = utils.parseUrl(window.top.document.URL, {decodeSearchAsString: true});
+ return parsedUrl.search;
+ } catch (e) {
+ return '';
+ }
+}
+
+describe('ShinezRtbBidAdapter', function () {
+ describe('validtae spec', function () {
+ it('exists and is a function', function () {
+ expect(adapter.isBidRequestValid).to.exist.and.to.be.a('function');
+ });
+
+ it('exists and is a function', function () {
+ expect(adapter.buildRequests).to.exist.and.to.be.a('function');
+ });
+
+ it('exists and is a function', function () {
+ expect(adapter.interpretResponse).to.exist.and.to.be.a('function');
+ });
+
+ it('exists and is a function', function () {
+ expect(adapter.getUserSyncs).to.exist.and.to.be.a('function');
+ });
+
+ it('exists and is a string', function () {
+ expect(adapter.code).to.exist.and.to.be.a('string');
+ });
+
+ it('exists and contains media types', function () {
+ expect(adapter.supportedMediaTypes).to.exist.and.to.be.an('array').with.length(2);
+ expect(adapter.supportedMediaTypes).to.contain.members([BANNER, VIDEO]);
+ });
+ });
+
+ describe('validate bid requests', function () {
+ it('should require cId', function () {
+ const isValid = adapter.isBidRequestValid({
+ params: {
+ pId: 'pid'
+ }
+ });
+ expect(isValid).to.be.false;
+ });
+
+ it('should require pId', function () {
+ const isValid = adapter.isBidRequestValid({
+ params: {
+ cId: 'cid'
+ }
+ });
+ expect(isValid).to.be.false;
+ });
+
+ it('should validate correctly', function () {
+ const isValid = adapter.isBidRequestValid({
+ params: {
+ cId: 'cid',
+ pId: 'pid'
+ }
+ });
+ expect(isValid).to.be.true;
+ });
+ });
+
+ describe('build requests', function () {
+ let sandbox;
+ before(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {
+ shinezRtb: {
+ storageAllowed: true
+ }
+ };
+ sandbox = sinon.sandbox.create();
+ sandbox.stub(Date, 'now').returns(1000);
+ });
+
+ it('should build video request', function () {
+ const hashUrl = hashCode(BIDDER_REQUEST.refererInfo.page);
+ config.setConfig({
+ bidderTimeout: 3000,
+ enableTIDs: true
+ });
+ const requests = adapter.buildRequests([VIDEO_BID], BIDDER_REQUEST);
+ expect(requests).to.have.length(1);
+ expect(requests[0]).to.deep.equal({
+ method: 'POST',
+ url: `${createDomain(SUB_DOMAIN)}/prebid/multi/635509f7ff6642d368cb9837`,
+ data: {
+ adUnitCode: '63550ad1ff6642d368cba59dh5884270560',
+ bidFloor: 0.1,
+ bidId: '2d52001cabd527',
+ bidderVersion: adapter.version,
+ bidderRequestId: '12a8ae9ada9c13',
+ cb: 1000,
+ gdpr: 1,
+ gdprConsent: 'consent_string',
+ usPrivacy: 'consent_string',
+ gppString: 'gpp_string',
+ gppSid: [7],
+ transactionId: '56e184c6-bde9-497b-b9b9-cf47a61381ee',
+ prebidVersion: version,
+ bidRequestsCount: 4,
+ bidderRequestsCount: 3,
+ bidderWinsCount: 1,
+ bidderTimeout: 3000,
+ publisherId: '59ac17c192832d0011283fe3',
+ url: 'https%3A%2F%2Fwww.greatsite.com',
+ referrer: 'https://www.somereferrer.com',
+ res: `${window.top.screen.width}x${window.top.screen.height}`,
+ schain: VIDEO_BID.schain,
+ sizes: ['545x307'],
+ sua: {
+ 'source': 2,
+ 'platform': {
+ 'brand': 'Android',
+ 'version': ['8', '0', '0']
+ },
+ 'browsers': [
+ {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']},
+ {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']},
+ {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']}
+ ],
+ 'mobile': 1,
+ 'model': 'SM-G955U',
+ 'bitness': '64',
+ 'architecture': ''
+ },
+ uniqueDealId: `${hashUrl}_${Date.now().toString()}`,
+ uqs: getTopWindowQueryParams(),
+ mediaTypes: {
+ video: {
+ api: [2],
+ context: 'instream',
+ linearity: 1,
+ maxduration: 60,
+ mimes: [
+ 'video/mp4',
+ 'application/javascript'
+ ],
+ minduration: 0,
+ placement: 1,
+ playerSize: [[545, 307]],
+ protocols: [2, 3, 5, 6],
+ startdelay: 0
+ }
+ },
+ gpid: '0123456789'
+ }
+ });
+ });
+
+ it('should build banner request for each size', function () {
+ const hashUrl = hashCode(BIDDER_REQUEST.refererInfo.page);
+ config.setConfig({
+ bidderTimeout: 3000,
+ enableTIDs: true
+ });
+ const requests = adapter.buildRequests([BID], BIDDER_REQUEST);
+ expect(requests).to.have.length(1);
+ expect(requests[0]).to.deep.equal({
+ method: 'POST',
+ url: `${createDomain(SUB_DOMAIN)}/prebid/multi/59db6b3b4ffaa70004f45cdc`,
+ data: {
+ gdprConsent: 'consent_string',
+ gdpr: 1,
+ gppString: 'gpp_string',
+ gppSid: [7],
+ usPrivacy: 'consent_string',
+ bidRequestsCount: 4,
+ bidderRequestsCount: 3,
+ bidderWinsCount: 1,
+ bidderTimeout: 3000,
+ bidderRequestId: '1fdb5ff1b6eaa7',
+ transactionId: '56e184c6-bde9-497b-b9b9-cf47a61381ee',
+ sizes: ['300x250', '300x600'],
+ sua: {
+ 'source': 2,
+ 'platform': {
+ 'brand': 'Android',
+ 'version': ['8', '0', '0']
+ },
+ 'browsers': [
+ {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']},
+ {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']},
+ {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']}
+ ],
+ 'mobile': 1,
+ 'model': 'SM-G955U',
+ 'bitness': '64',
+ 'architecture': ''
+ },
+ url: 'https%3A%2F%2Fwww.greatsite.com',
+ referrer: 'https://www.somereferrer.com',
+ cb: 1000,
+ bidFloor: 0.1,
+ bidId: '2d52001cabd527',
+ adUnitCode: 'div-gpt-ad-12345-0',
+ publisherId: '59ac17c192832d0011283fe3',
+ uniqueDealId: `${hashUrl}_${Date.now().toString()}`,
+ bidderVersion: adapter.version,
+ prebidVersion: version,
+ schain: BID.schain,
+ res: `${window.top.screen.width}x${window.top.screen.height}`,
+ mediaTypes: [BANNER],
+ gpid: '0123456789',
+ uqs: getTopWindowQueryParams(),
+ 'ext.param1': 'loremipsum',
+ 'ext.param2': 'dolorsitamet',
+ }
+ });
+ });
+
+ after(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {};
+ sandbox.restore();
+ });
+ });
+ describe('getUserSyncs', function () {
+ it('should have valid user sync with iframeEnabled', function () {
+ const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]);
+
+ expect(result).to.deep.equal([{
+ type: 'iframe',
+ url: 'https://sync.sweetgum.io/api/sync/iframe/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy='
+ }]);
+ });
+
+ it('should have valid user sync with cid on response', function () {
+ const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]);
+ expect(result).to.deep.equal([{
+ type: 'iframe',
+ url: 'https://sync.sweetgum.io/api/sync/iframe/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy='
+ }]);
+ });
+
+ it('should have valid user sync with pixelEnabled', function () {
+ const result = adapter.getUserSyncs({pixelEnabled: true}, [SERVER_RESPONSE]);
+
+ expect(result).to.deep.equal([{
+ 'url': 'https://sync.sweetgum.io/api/sync/image/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy=',
+ 'type': 'image'
+ }]);
+ })
+ });
+
+ describe('interpret response', function () {
+ it('should return empty array when there is no response', function () {
+ const responses = adapter.interpretResponse(null);
+ expect(responses).to.be.empty;
+ });
+
+ it('should return empty array when there is no ad', function () {
+ const responses = adapter.interpretResponse({price: 1, ad: ''});
+ expect(responses).to.be.empty;
+ });
+
+ it('should return empty array when there is no price', function () {
+ const responses = adapter.interpretResponse({price: null, ad: 'great ad'});
+ expect(responses).to.be.empty;
+ });
+
+ it('should return an array of interpreted banner responses', function () {
+ const responses = adapter.interpretResponse(SERVER_RESPONSE, REQUEST);
+ expect(responses).to.have.length(1);
+ expect(responses[0]).to.deep.equal({
+ requestId: '2d52001cabd527',
+ cpm: 0.8,
+ width: 300,
+ height: 250,
+ creativeId: '12610997325162499419',
+ currency: 'USD',
+ netRevenue: true,
+ ttl: 30,
+ ad: '
',
+ meta: {
+ advertiserDomains: ['securepubads.g.doubleclick.net']
+ }
+ });
+ });
+
+ it('should get meta from response metaData', function () {
+ const serverResponse = utils.deepClone(SERVER_RESPONSE);
+ serverResponse.body.results[0].metaData = {
+ advertiserDomains: ['sweetgum.io'],
+ agencyName: 'Agency Name',
+ };
+ const responses = adapter.interpretResponse(serverResponse, REQUEST);
+ expect(responses[0].meta).to.deep.equal({
+ advertiserDomains: ['sweetgum.io'],
+ agencyName: 'Agency Name'
+ });
+ });
+
+ it('should return an array of interpreted video responses', function () {
+ const responses = adapter.interpretResponse(VIDEO_SERVER_RESPONSE, REQUEST);
+ expect(responses).to.have.length(1);
+ expect(responses[0]).to.deep.equal({
+ requestId: '2d52001cabd527',
+ cpm: 2,
+ width: 545,
+ height: 307,
+ mediaType: 'video',
+ creativeId: '12610997325162499419',
+ currency: 'USD',
+ netRevenue: true,
+ ttl: 60,
+ vastXml: '
',
+ meta: {
+ advertiserDomains: ['sweetgum.io']
+ }
+ });
+ });
+
+ it('should take default TTL', function () {
+ const serverResponse = utils.deepClone(SERVER_RESPONSE);
+ delete serverResponse.body.results[0].exp;
+ const responses = adapter.interpretResponse(serverResponse, REQUEST);
+ expect(responses).to.have.length(1);
+ expect(responses[0].ttl).to.equal(300);
+ });
+ });
+
+ describe('user id system', function () {
+ TEST_ID_SYSTEMS.forEach((idSystemProvider) => {
+ const id = Date.now().toString();
+ const bid = utils.deepClone(BID);
+
+ const userId = (function () {
+ switch (idSystemProvider) {
+ case 'digitrustid':
+ return {data: {id}};
+ case 'lipb':
+ return {lipbid: id};
+ case 'parrableId':
+ return {eid: id};
+ case 'id5id':
+ return {uid: id};
+ default:
+ return id;
+ }
+ })();
+
+ bid.userId = {
+ [idSystemProvider]: userId
+ };
+
+ it(`should include 'uid.${idSystemProvider}' in request params`, function () {
+ const requests = adapter.buildRequests([bid], BIDDER_REQUEST);
+ expect(requests[0].data[`uid.${idSystemProvider}`]).to.equal(id);
+ });
+ });
+ });
+
+ describe('alternate param names extractors', function () {
+ it('should return undefined when param not supported', function () {
+ const cid = extractCID({'c_id': '1'});
+ const pid = extractPID({'p_id': '1'});
+ const subDomain = extractSubDomain({'sub_domain': 'prebid'});
+ expect(cid).to.be.undefined;
+ expect(pid).to.be.undefined;
+ expect(subDomain).to.be.undefined;
+ });
+
+ it('should return value when param supported', function () {
+ const cid = extractCID({'cID': '1'});
+ const pid = extractPID({'Pid': '2'});
+ const subDomain = extractSubDomain({'subDOMAIN': 'prebid'});
+ expect(cid).to.be.equal('1');
+ expect(pid).to.be.equal('2');
+ expect(subDomain).to.be.equal('prebid');
+ });
+ });
+
+ describe('unique deal id', function () {
+ before(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {
+ shinezRtb: {
+ storageAllowed: true
+ }
+ };
+ });
+ after(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {};
+ });
+ const key = 'myKey';
+ let uniqueDealId;
+ beforeEach(() => {
+ uniqueDealId = getUniqueDealId(key, 0);
+ })
+
+ it('should get current unique deal id', function (done) {
+ // waiting some time so `now` will become past
+ setTimeout(() => {
+ const current = getUniqueDealId(key);
+ expect(current).to.be.equal(uniqueDealId);
+ done();
+ }, 200);
+ });
+
+ it('should get new unique deal id on expiration', function (done) {
+ setTimeout(() => {
+ const current = getUniqueDealId(key, 100);
+ expect(current).to.not.be.equal(uniqueDealId);
+ done();
+ }, 200)
+ });
+ });
+
+ describe('storage utils', function () {
+ before(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {
+ shinezRtb: {
+ storageAllowed: true
+ }
+ };
+ });
+ after(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {};
+ });
+ it('should get value from storage with create param', function () {
+ const now = Date.now();
+ const clock = useFakeTimers({
+ shouldAdvanceTime: true,
+ now
+ });
+ setStorageItem('myKey', 2020);
+ const {value, created} = getStorageItem('myKey');
+ expect(created).to.be.equal(now);
+ expect(value).to.be.equal(2020);
+ expect(typeof value).to.be.equal('number');
+ expect(typeof created).to.be.equal('number');
+ clock.restore();
+ });
+
+ it('should get external stored value', function () {
+ const value = 'superman'
+ window.localStorage.setItem('myExternalKey', value);
+ const item = getStorageItem('myExternalKey');
+ expect(item).to.be.equal(value);
+ });
+
+ it('should parse JSON value', function () {
+ const data = JSON.stringify({event: 'send'});
+ const {event} = tryParseJSON(data);
+ expect(event).to.be.equal('send');
+ });
+
+ it('should get original value on parse fail', function () {
+ const value = 21;
+ const parsed = tryParseJSON(value);
+ expect(typeof parsed).to.be.equal('number');
+ expect(parsed).to.be.equal(value);
+ });
+ });
+});
diff --git a/test/spec/modules/silvermobBidAdapter_spec.js b/test/spec/modules/silvermobBidAdapter_spec.js
new file mode 100644
index 00000000000..7d7fbacc04e
--- /dev/null
+++ b/test/spec/modules/silvermobBidAdapter_spec.js
@@ -0,0 +1,301 @@
+import { expect } from 'chai';
+import {spec} from '../../../modules/silvermobBidAdapter.js';
+import 'modules/priceFloors.js';
+import { newBidder } from 'src/adapters/bidderFactory';
+import { config } from '../../../src/config.js';
+import { syncAddFPDToBidderRequest } from '../../helpers/fpd.js';
+
+// load modules that register ORTB processors
+import 'src/prebid.js';
+import 'modules/currency.js';
+import 'modules/userId/index.js';
+import 'modules/multibid/index.js';
+import 'modules/priceFloors.js';
+import 'modules/consentManagement.js';
+import 'modules/consentManagementUsp.js';
+import 'modules/schain.js';
+
+const SIMPLE_BID_REQUEST = {
+ bidder: 'silvermob',
+ params: {
+ zoneid: '0',
+ host: 'us',
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [320, 250],
+ [300, 600],
+ ],
+ },
+ },
+ adUnitCode: 'div-gpt-ad-1499748733608-0',
+ transactionId: 'f183e871-fbed-45f0-a427-c8a63c4c01eb',
+ bidId: '33e9500b21129f',
+ bidderRequestId: '2772c1e566670b',
+ auctionId: '192721e36a0239',
+ sizes: [[300, 250], [160, 600]],
+ gdprConsent: {
+ apiVersion: 2,
+ consentString: 'CONSENT',
+ vendorData: { purpose: { consents: { 1: true } } },
+ gdprApplies: true,
+ addtlConsent: '1~1.35.41.101',
+ },
+}
+
+const BANNER_BID_REQUEST = {
+ bidder: 'silvermob',
+ params: {
+ zoneid: '0',
+ host: 'us',
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250],
+ [300, 600],
+ ],
+ },
+ },
+ adUnitCode: '/adunit-code/test-path',
+ bidId: 'test-bid-id-1',
+ bidderRequestId: 'test-bid-request-1',
+ auctionId: 'test-auction-1',
+ transactionId: 'test-transactionId-1',
+ code: 'banner_example',
+ timeout: 1000,
+}
+
+const VIDEO_BID_REQUEST = {
+ placementCode: '/DfpAccount1/slotVideo',
+ bidId: 'test-bid-id-2',
+ mediaTypes: {
+ video: {
+ playerSize: [400, 300],
+ w: 400,
+ h: 300,
+ minduration: 5,
+ maxduration: 10,
+ startdelay: 0,
+ skip: 1,
+ minbitrate: 200,
+ protocols: [1, 2, 4]
+ }
+ },
+ bidder: 'silvermob',
+ params: {
+ zoneid: '0',
+ host: 'us',
+ },
+ adUnitCode: '/adunit-code/test-path',
+ bidderRequestId: 'test-bid-request-1',
+ auctionId: 'test-auction-1',
+ transactionId: 'test-transactionId-1',
+ timeout: 1000,
+}
+
+const NATIVE_BID_REQUEST = {
+ code: 'native_example',
+ mediaTypes: {
+ native: {
+ title: {
+ required: true,
+ len: 800
+ },
+ image: {
+ required: true,
+ len: 80
+ },
+ sponsoredBy: {
+ required: true
+ },
+ clickUrl: {
+ required: true
+ },
+ privacyLink: {
+ required: false
+ },
+ body: {
+ required: true
+ },
+ icon: {
+ required: true,
+ sizes: [50, 50]
+ }
+ }
+ },
+ bidder: 'silvermob',
+ params: {
+ zoneid: '0',
+ host: 'us',
+ },
+ adUnitCode: '/adunit-code/test-path',
+ bidId: 'test-bid-id-1',
+ bidderRequestId: 'test-bid-request-1',
+ auctionId: 'test-auction-1',
+ transactionId: 'test-transactionId-1',
+ timeout: 1000,
+ uspConsent: 'uspConsent'
+};
+
+const bidderRequest = {
+ refererInfo: {
+ page: 'https://publisher.com/home',
+ ref: 'https://referrer'
+ }
+};
+
+const gdprConsent = {
+ apiVersion: 2,
+ consentString: 'CONSENT',
+ vendorData: { purpose: { consents: { 1: true } } },
+ gdprApplies: true,
+ addtlConsent: '1~1.35.41.101',
+}
+
+describe('silvermobAdapter', 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('with user privacy regulations', function () {
+ it('should send the Coppa "required" flag set to "1" in the request', function () {
+ sinon.stub(config, 'getConfig')
+ .withArgs('coppa')
+ .returns(true);
+ const serverRequest = spec.buildRequests([SIMPLE_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(serverRequest.data.regs.coppa).to.equal(1);
+ config.getConfig.restore();
+ });
+
+ it('should send the GDPR Consent data in the request', function () {
+ const serverRequest = spec.buildRequests([SIMPLE_BID_REQUEST], syncAddFPDToBidderRequest({ ...bidderRequest, gdprConsent }));
+ expect(serverRequest.data.regs.ext.gdpr).to.exist.and.to.equal(1);
+ expect(serverRequest.data.user.ext.consent).to.equal('CONSENT');
+ });
+
+ it('should send the CCPA data in the request', function () {
+ const serverRequest = spec.buildRequests([SIMPLE_BID_REQUEST], syncAddFPDToBidderRequest({...bidderRequest, ...{ uspConsent: '1YYY' }}));
+ expect(serverRequest.data.regs.ext.us_privacy).to.equal('1YYY');
+ });
+ });
+
+ describe('isBidRequestValid', function () {
+ it('should return true when required params found', function () {
+ expect(spec.isBidRequestValid(BANNER_BID_REQUEST)).to.equal(true);
+ });
+
+ it('should return false when zoneid is missing', function () {
+ let localbid = Object.assign({}, BANNER_BID_REQUEST);
+ delete localbid.params.zoneid;
+ expect(spec.isBidRequestValid(BANNER_BID_REQUEST)).to.equal(false);
+ });
+ });
+
+ describe('build request', function () {
+ it('should return an empty array when no bid requests', function () {
+ const bidRequest = spec.buildRequests([], syncAddFPDToBidderRequest(bidderRequest));
+ expect(bidRequest).to.be.an('array');
+ expect(bidRequest.length).to.equal(0);
+ });
+
+ it('should return a valid bid request object', function () {
+ const request = spec.buildRequests([SIMPLE_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(request).to.not.equal('array');
+ expect(request.data).to.be.an('object');
+ expect(request.method).to.equal('POST');
+ expect(request.url).to.equal('https://us.silvermob.com/marketplace/api/dsp/prebidjs/0');
+
+ expect(request.data.site).to.have.property('page');
+ expect(request.data.site).to.have.property('domain');
+ expect(request.data).to.have.property('id');
+ expect(request.data).to.have.property('imp');
+ expect(request.data).to.have.property('device');
+ });
+
+ it('should return a valid bid BANNER request object', function () {
+ const request = spec.buildRequests([BANNER_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.data.imp[0].banner).to.exist;
+ expect(request.data.imp[0].banner.format[0].w).to.be.an('number');
+ expect(request.data.imp[0].banner.format[0].h).to.be.an('number');
+ });
+
+ if (FEATURES.VIDEO) {
+ it('should return a valid bid VIDEO request object', function () {
+ const request = spec.buildRequests([VIDEO_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.data.imp[0].video).to.exist;
+ expect(request.data.imp[0].video.w).to.be.an('number');
+ expect(request.data.imp[0].video.h).to.be.an('number');
+ });
+ }
+
+ it('should return a valid bid NATIVE request object', function () {
+ const request = spec.buildRequests([NATIVE_BID_REQUEST], syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.data.imp[0]).to.be.an('object');
+ });
+ })
+
+ describe('interpretResponse', function () {
+ let bidRequests, bidderRequest;
+ beforeEach(function () {
+ bidRequests = [{
+ 'bidId': '28ffdk2B952532',
+ 'bidder': 'silvermob',
+ 'userId': {
+ 'freepassId': {
+ 'userIp': '172.21.0.1',
+ 'userId': '123',
+ 'commonId': 'commonIdValue'
+ }
+ },
+ 'adUnitCode': 'adunit-code',
+ 'params': {
+ 'publisherId': 'publisherIdValue'
+ }
+ }];
+ bidderRequest = {};
+ });
+
+ it('Empty response must return empty array', function () {
+ const emptyResponse = null;
+ let response = spec.interpretResponse(emptyResponse, BANNER_BID_REQUEST);
+
+ expect(response).to.be.an('array').that.is.empty;
+ })
+
+ it('Should interpret banner response', function () {
+ const serverResponse = {
+ body: {
+ 'cur': 'USD',
+ 'seatbid': [{
+ 'bid': [{
+ 'impid': '28ffdk2B952532',
+ 'price': 97,
+ 'adm': '
',
+ 'w': 300,
+ 'h': 250,
+ 'crid': 'creative0'
+ }]
+ }]
+ }
+ };
+ it('should interpret server response', function () {
+ const bidRequest = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest));
+ const bids = spec.interpretResponse(serverResponse, bidRequest);
+ expect(bids).to.be.an('array');
+ const bid = bids[0];
+ expect(bid).to.be.an('object');
+ expect(bid.currency).to.equal('USD');
+ expect(bid.cpm).to.equal(97);
+ expect(bid.ad).to.equal(ad)
+ expect(bid.width).to.equal(300);
+ expect(bid.height).to.equal(250);
+ expect(bid.creativeId).to.equal('creative0');
+ });
+ })
+ });
+});
diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js
index 9daa6a87826..58b4cd8c0d0 100644
--- a/test/spec/modules/smartadserverBidAdapter_spec.js
+++ b/test/spec/modules/smartadserverBidAdapter_spec.js
@@ -786,7 +786,7 @@ describe('Smart bid adapter tests', function () {
expect(request[0]).to.have.property('method').and.to.equal('POST');
const requestContent = JSON.parse(request[0].data);
expect(requestContent).to.have.property('videoData');
- expect(requestContent.videoData).to.have.property('videoProtocol').and.to.equal(null);
+ expect(requestContent.videoData).not.to.have.property('videoProtocol').eq(true);
expect(requestContent.videoData).to.have.property('adBreak').and.to.equal(2);
});
@@ -833,6 +833,73 @@ describe('Smart bid adapter tests', function () {
expect(requestContent.videoData).to.have.property('videoProtocol').and.to.equal(6);
expect(requestContent.videoData).to.have.property('adBreak').and.to.equal(3);
});
+
+ it('should pass additional parameters', function () {
+ const request = spec.buildRequests([{
+ bidder: 'smartadserver',
+ mediaTypes: {
+ video: {
+ context: 'instream',
+ api: [1, 2, 3],
+ maxbitrate: 50,
+ minbitrate: 20,
+ maxduration: 30,
+ minduration: 5,
+ placement: 3,
+ playbackmethod: [2, 4],
+ playerSize: [[640, 480]],
+ plcmt: 1,
+ skip: 0
+ }
+ },
+ params: {
+ siteId: '123'
+ }
+ }]);
+ const requestContent = JSON.parse(request[0].data);
+
+ expect(requestContent.videoData).to.have.property('iabframeworks').and.to.equal('1,2,3');
+ expect(requestContent.videoData).not.to.have.property('skip');
+ expect(requestContent.videoData).to.have.property('vbrmax').and.to.equal(50);
+ expect(requestContent.videoData).to.have.property('vbrmin').and.to.equal(20);
+ expect(requestContent.videoData).to.have.property('vdmax').and.to.equal(30);
+ expect(requestContent.videoData).to.have.property('vdmin').and.to.equal(5);
+ expect(requestContent.videoData).to.have.property('vplcmt').and.to.equal(1);
+ expect(requestContent.videoData).to.have.property('vpmt').and.to.have.lengthOf(2);
+ expect(requestContent.videoData.vpmt[0]).to.equal(2);
+ expect(requestContent.videoData.vpmt[1]).to.equal(4);
+ expect(requestContent.videoData).to.have.property('vpt').and.to.equal(3);
+ });
+
+ it('should not pass not valuable parameters', function () {
+ const request = spec.buildRequests([{
+ bidder: 'smartadserver',
+ mediaTypes: {
+ video: {
+ context: 'instream',
+ maxbitrate: 20,
+ minbitrate: null,
+ maxduration: 0,
+ playbackmethod: [],
+ playerSize: [[640, 480]],
+ plcmt: 1
+ }
+ },
+ params: {
+ siteId: '123'
+ }
+ }]);
+ const requestContent = JSON.parse(request[0].data);
+
+ expect(requestContent.videoData).not.to.have.property('iabframeworks');
+ expect(requestContent.videoData).to.have.property('vbrmax').and.to.equal(20);
+ expect(requestContent.videoData).not.to.have.property('vbrmin');
+ expect(requestContent.videoData).not.to.have.property('vdmax');
+ expect(requestContent.videoData).not.to.have.property('vdmin');
+ expect(requestContent.videoData).to.have.property('vplcmt').and.to.equal(1);
+ expect(requestContent.videoData).not.to.have.property('vpmt');
+ expect(requestContent.videoData).not.to.have.property('vpt');
+ });
});
});
@@ -1029,7 +1096,7 @@ describe('Smart bid adapter tests', function () {
expect(request[0]).to.have.property('method').and.to.equal('POST');
const requestContent = JSON.parse(request[0].data);
expect(requestContent).to.have.property('videoData');
- expect(requestContent.videoData).to.have.property('videoProtocol').and.to.equal(null);
+ expect(requestContent.videoData).not.to.have.property('videoProtocol').eq(true);
expect(requestContent.videoData).to.have.property('adBreak').and.to.equal(2);
});
@@ -1393,4 +1460,41 @@ describe('Smart bid adapter tests', function () {
expect(requestContent).to.have.property('gpid').and.to.equal(gpid);
});
});
+
+ describe('#getValuableProperty method', function () {
+ it('should return an object when calling with a number value', () => {
+ const obj = spec.getValuableProperty('prop', 3);
+ expect(obj).to.deep.equal({ prop: 3 });
+ });
+
+ it('should return an empty object when calling with a string value', () => {
+ const obj = spec.getValuableProperty('prop', 'str');
+ expect(obj).to.deep.equal({});
+ });
+
+ it('should return an empty object when calling with a number property', () => {
+ const obj = spec.getValuableProperty(7, 'str');
+ expect(obj).to.deep.equal({});
+ });
+
+ it('should return an empty object when calling with a null value', () => {
+ const obj = spec.getValuableProperty('prop', null);
+ expect(obj).to.deep.equal({});
+ });
+
+ it('should return an empty object when calling with an object value', () => {
+ const obj = spec.getValuableProperty('prop', {});
+ expect(obj).to.deep.equal({});
+ });
+
+ it('should return an empty object when calling with a 0 value', () => {
+ const obj = spec.getValuableProperty('prop', 0);
+ expect(obj).to.deep.equal({});
+ });
+
+ it('should return an empty object when calling without the value argument', () => {
+ const obj = spec.getValuableProperty('prop');
+ expect(obj).to.deep.equal({});
+ });
+ });
});
diff --git a/test/spec/modules/smilewantedBidAdapter_spec.js b/test/spec/modules/smilewantedBidAdapter_spec.js
index 22221dbe1ef..99c4034610f 100644
--- a/test/spec/modules/smilewantedBidAdapter_spec.js
+++ b/test/spec/modules/smilewantedBidAdapter_spec.js
@@ -93,7 +93,24 @@ const BID_RESPONSE_DISPLAY = {
const VIDEO_INSTREAM_REQUEST = [{
code: 'video1',
mediaTypes: {
- video: {}
+ video: {
+ context: 'instream',
+ mimes: ['video/mp4'],
+ minduration: 0,
+ maxduration: 120,
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ startdelay: 0,
+ placement: 1,
+ skip: 1,
+ skipafter: 10,
+ minbitrate: 10,
+ maxbitrate: 10,
+ delivery: [1],
+ playbackmethod: [2],
+ api: [1, 2],
+ linearity: 1,
+ playerSize: [640, 480]
+ }
},
sizes: [
[640, 480]
@@ -163,6 +180,99 @@ const BID_RESPONSE_VIDEO_OUTSTREAM = {
}
};
+const NATIVE_REQUEST = [{
+ adUnitCode: 'native_300x250',
+ code: '/19968336/prebid_native_example_1',
+ bidId: '12345',
+ sizes: [
+ [300, 250]
+ ],
+ mediaTypes: {
+ native: {
+ sendTargetingKeys: false,
+ title: {
+ required: true,
+ len: 140
+ },
+ image: {
+ required: true,
+ sizes: [300, 250]
+ },
+ icon: {
+ required: false,
+ sizes: [50, 50]
+ },
+ sponsoredBy: {
+ required: true
+ },
+ body: {
+ required: true
+ },
+ clickUrl: {
+ required: false
+ },
+ privacyLink: {
+ required: false
+ },
+ cta: {
+ required: false
+ },
+ rating: {
+ required: false
+ },
+ likes: {
+ required: false
+ },
+ downloads: {
+ required: false
+ },
+ price: {
+ required: false
+ },
+ salePrice: {
+ required: false
+ },
+ phone: {
+ required: false
+ },
+ address: {
+ required: false
+ },
+ desc2: {
+ required: false
+ },
+ displayUrl: {
+ required: false
+ }
+ }
+ },
+ bidder: 'smilewanted',
+ params: {
+ zoneId: 4,
+ },
+ requestId: 'request_abcd1234',
+ ortb2Imp: {
+ ext: {
+ tid: 'trans_abcd1234',
+ }
+ },
+}];
+
+const BID_RESPONSE_NATIVE = {
+ body: {
+ cpm: 3,
+ width: 300,
+ height: 250,
+ creativeId: 'crea_sw_1',
+ currency: 'EUR',
+ isNetCpm: true,
+ ttl: 300,
+ ad: '{"link":{"url":"https://www.smilewanted.com"},"assets":[{"id":0,"required":1,"title":{"len":50}},{"id":1,"required":1,"img":{"type":3,"w":150,"h":50,"ext":{"aspectratios":["2:1"]}}},{"id":2,"required":0,"img":{"type":1,"w":50,"h":50,"ext":{"aspectratios":["2:1"]}}},{"id":3,"required":1,"data":{"type":1,"value":"Smilewanted sponsor"}},{"id":4,"required":1,"data":{"type":2,"value":"Smilewanted Description"}}]}',
+ cSyncUrl: 'https://csync.smilewanted.com',
+ formatTypeSw: 'native'
+ }
+};
+
// Default params with optional ones
describe('smilewantedBidAdapterTests', function () {
it('SmileWanted - Verify build request', function () {
@@ -195,6 +305,23 @@ describe('smilewantedBidAdapterTests', function () {
expect(requestVideoInstreamContent.sizes[0]).to.have.property('w').and.to.equal(640);
expect(requestVideoInstreamContent.sizes[0]).to.have.property('h').and.to.equal(480);
expect(requestVideoInstreamContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent).to.have.property('videoParams');
+ expect(requestVideoInstreamContent.videoParams).to.have.property('context').and.to.equal('instream').and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('mimes').to.be.an('array').that.include('video/mp4').and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('minduration').and.to.equal(0).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('maxduration').and.to.equal(120).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('protocols').to.be.an('array').that.include.members([1, 2, 3, 4, 5, 6, 7, 8]).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('startdelay').and.to.equal(0).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('placement').and.to.equal(1).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('skip').and.to.equal(1).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('skipafter').and.to.equal(10).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('minbitrate').and.to.equal(10).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('maxbitrate').and.to.equal(10).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('delivery').to.be.an('array').that.include(1).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('playbackmethod').to.be.an('array').that.include(2).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('api').to.be.an('array').that.include.members([1, 2]).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('linearity').and.to.equal(1).and.to.not.be.undefined;
+ expect(requestVideoInstreamContent.videoParams).to.have.property('playerSize').to.be.an('array').that.include.members([640, 480]).and.to.not.be.undefined;
const requestVideoOutstream = spec.buildRequests(VIDEO_OUTSTREAM_REQUEST);
expect(requestVideoOutstream[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com');
@@ -206,6 +333,39 @@ describe('smilewantedBidAdapterTests', function () {
expect(requestVideoOutstreamContent.sizes[0]).to.have.property('w').and.to.equal(640);
expect(requestVideoOutstreamContent.sizes[0]).to.have.property('h').and.to.equal(480);
expect(requestVideoOutstreamContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined;
+
+ const requestNative = spec.buildRequests(NATIVE_REQUEST);
+ expect(requestNative[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com');
+ expect(requestNative[0]).to.have.property('method').and.to.equal('POST');
+ const requestNativeContent = JSON.parse(requestNative[0].data);
+ expect(requestNativeContent).to.have.property('zoneId').and.to.equal(4);
+ expect(requestNativeContent).to.have.property('currencyCode').and.to.equal('EUR');
+ expect(requestNativeContent).to.have.property('sizes');
+ expect(requestNativeContent.sizes[0]).to.have.property('w').and.to.equal(300);
+ expect(requestNativeContent.sizes[0]).to.have.property('h').and.to.equal(250);
+ expect(requestNativeContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined;
+ expect(requestNativeContent).to.have.property('context').and.to.equal('native').and.to.not.be.undefined;
+ expect(requestNativeContent).to.have.property('nativeParams');
+ expect(requestNativeContent.nativeParams.title).to.have.property('required').and.to.equal(true);
+ expect(requestNativeContent.nativeParams.title).to.have.property('len').and.to.equal(140);
+ expect(requestNativeContent.nativeParams.image).to.have.property('required').and.to.equal(true);
+ expect(requestNativeContent.nativeParams.image).to.have.property('sizes').to.be.an('array').that.include.members([300, 250]).and.to.not.be.undefined;
+ expect(requestNativeContent.nativeParams.icon).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.icon).to.have.property('sizes').to.be.an('array').that.include.members([50, 50]).and.to.not.be.undefined;
+ expect(requestNativeContent.nativeParams.sponsoredBy).to.have.property('required').and.to.equal(true);
+ expect(requestNativeContent.nativeParams.body).to.have.property('required').and.to.equal(true);
+ expect(requestNativeContent.nativeParams.clickUrl).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.privacyLink).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.cta).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.rating).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.likes).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.downloads).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.price).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.salePrice).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.phone).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.address).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.desc2).to.have.property('required').and.to.equal(false);
+ expect(requestNativeContent.nativeParams.displayUrl).to.have.property('required').and.to.equal(false);
});
it('SmileWanted - Verify build request with referrer', function () {
@@ -337,7 +497,7 @@ describe('smilewantedBidAdapterTests', function () {
}).to.not.throw();
});
- it('SmileWanted - Verify parse response - Video Oustream', function () {
+ it('SmileWanted - Verify parse response - Video Outstream', function () {
const request = spec.buildRequests(VIDEO_OUTSTREAM_REQUEST);
const bids = spec.interpretResponse(BID_RESPONSE_VIDEO_OUTSTREAM, request[0]);
expect(bids).to.have.lengthOf(1);
@@ -360,6 +520,28 @@ describe('smilewantedBidAdapterTests', function () {
}).to.not.throw();
});
+ it('SmileWanted - Verify parse response - Native', function () {
+ const request = spec.buildRequests(NATIVE_REQUEST);
+ const bids = spec.interpretResponse(BID_RESPONSE_NATIVE, request[0]);
+ expect(bids).to.have.lengthOf(1);
+ const bid = bids[0];
+ expect(bid.cpm).to.equal(3);
+ expect(bid.ad).to.equal('{"link":{"url":"https://www.smilewanted.com"},"assets":[{"id":0,"required":1,"title":{"len":50}},{"id":1,"required":1,"img":{"type":3,"w":150,"h":50,"ext":{"aspectratios":["2:1"]}}},{"id":2,"required":0,"img":{"type":1,"w":50,"h":50,"ext":{"aspectratios":["2:1"]}}},{"id":3,"required":1,"data":{"type":1,"value":"Smilewanted sponsor"}},{"id":4,"required":1,"data":{"type":2,"value":"Smilewanted Description"}}]}');
+ expect(bid.width).to.equal(300);
+ expect(bid.height).to.equal(250);
+ expect(bid.creativeId).to.equal('crea_sw_1');
+ expect(bid.currency).to.equal('EUR');
+ expect(bid.netRevenue).to.equal(true);
+ expect(bid.ttl).to.equal(300);
+ expect(bid.requestId).to.equal(NATIVE_REQUEST[0].bidId);
+
+ expect(function () {
+ spec.interpretResponse(BID_RESPONSE_NATIVE, {
+ data: 'invalid Json'
+ })
+ }).to.not.throw();
+ });
+
it('SmileWanted - Verify bidder code', function () {
expect(spec.code).to.equal('smilewanted');
});
diff --git a/test/spec/modules/snigelBidAdapter_spec.js b/test/spec/modules/snigelBidAdapter_spec.js
index 3ba84228872..828aec9491c 100644
--- a/test/spec/modules/snigelBidAdapter_spec.js
+++ b/test/spec/modules/snigelBidAdapter_spec.js
@@ -2,6 +2,8 @@ import {expect} from 'chai';
import {spec} from 'modules/snigelBidAdapter.js';
import {config} from 'src/config.js';
import {isValid} from 'src/adapters/bidderFactory.js';
+import {registerActivityControl} from 'src/activities/rules.js';
+import {ACTIVITY_ACCESS_DEVICE} from 'src/activities/activities.js';
const BASE_BID_REQUEST = {
adUnitCode: 'top_leaderboard',
@@ -344,5 +346,67 @@ describe('snigelBidAdapter', function () {
expect(sync).to.have.property('url');
expect(sync.url).to.equal(`https://somesyncurl?gdpr=1&gdpr_consent=${DUMMY_GDPR_CONSENT_STRING}`);
});
+
+ it('should omit session ID if no device access', function() {
+ const bidderRequest = makeBidderRequest();
+ const unregisterRule = registerActivityControl(ACTIVITY_ACCESS_DEVICE, 'denyAccess', () => {
+ return {allow: false, reason: 'no consent'};
+ });
+
+ try {
+ const request = spec.buildRequests([], bidderRequest);
+ expect(request).to.have.property('data');
+ const data = JSON.parse(request.data);
+ expect(data.sessionId).to.be.undefined;
+ } finally {
+ unregisterRule();
+ }
+ });
+
+ it('should determine full GDPR consent correctly', function () {
+ const baseBidderRequest = makeBidderRequest({
+ gdprConsent: {
+ gdprApplies: true,
+ vendorData: {
+ purpose: {
+ consents: {1: true, 2: true, 3: true, 4: true, 5: true},
+ },
+ vendor: {
+ consents: {[spec.gvlid]: true},
+ }
+ },
+ }
+ });
+ let request = spec.buildRequests([], baseBidderRequest);
+ expect(request).to.have.property('data');
+ let data = JSON.parse(request.data);
+ expect(data.gdprConsent).to.be.true;
+
+ let bidderRequest = {...baseBidderRequest, ...{gdprConsent: {vendorData: {purpose: {consents: {1: false}}}}}};
+ request = spec.buildRequests([], bidderRequest);
+ expect(request).to.have.property('data');
+ data = JSON.parse(request.data);
+ expect(data.gdprConsent).to.be.false;
+
+ bidderRequest = {...baseBidderRequest, ...{gdprConsent: {vendorData: {vendor: {consents: {[spec.gvlid]: false}}}}}};
+ request = spec.buildRequests([], bidderRequest);
+ expect(request).to.have.property('data');
+ data = JSON.parse(request.data);
+ expect(data.gdprConsent).to.be.false;
+ });
+
+ it('should increment auction counter upon every request', function() {
+ const bidderRequest = makeBidderRequest({});
+
+ let request = spec.buildRequests([], bidderRequest);
+ expect(request).to.have.property('data');
+ let data = JSON.parse(request.data);
+ const previousCounter = data.counter;
+
+ request = spec.buildRequests([], bidderRequest);
+ expect(request).to.have.property('data');
+ data = JSON.parse(request.data);
+ expect(data.counter).to.equal(previousCounter + 1);
+ });
});
});
diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js
index 164aa06d9b7..83db7c0a812 100644
--- a/test/spec/modules/sonobiBidAdapter_spec.js
+++ b/test/spec/modules/sonobiBidAdapter_spec.js
@@ -1,8 +1,8 @@
-import {expect} from 'chai';
-import {_getPlatform, spec} from 'modules/sonobiBidAdapter.js';
-import {newBidder} from 'src/adapters/bidderFactory.js';
-import {userSync} from '../../../src/userSync.js';
-import {config} from 'src/config.js';
+import { expect } from 'chai';
+import { _getPlatform, spec } from 'modules/sonobiBidAdapter.js';
+import { newBidder } from 'src/adapters/bidderFactory.js';
+import { userSync } from '../../../src/userSync.js';
+import { config } from 'src/config.js';
import * as gptUtils from '../../../libraries/gptUtils/gptUtils.js';
describe('SonobiBidAdapter', function () {
@@ -359,7 +359,9 @@ describe('SonobiBidAdapter', function () {
'page': 'https://example.com',
'stack': ['https://example.com']
},
- uspConsent: 'someCCPAString'
+ uspConsent: 'someCCPAString',
+ ortb2: {}
+
};
it('should set fpd if there is any data in ortb2', function () {
@@ -493,6 +495,14 @@ describe('SonobiBidAdapter', function () {
expect(bidRequests.data.hfa).to.equal('hfakey')
})
+ it('should return a properly formatted request with expData and expKey', function () {
+ bidderRequests.ortb2.experianRtidData = 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg==';
+ bidderRequests.ortb2.experianRtidKey = 'sovrn-encryption-key-1';
+ const bidRequests = spec.buildRequests(bidRequest, bidderRequests)
+ expect(bidRequests.data.expData).to.equal('IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg==');
+ expect(bidRequests.data.expKey).to.equal('sovrn-encryption-key-1');
+ })
+
it('should return null if there is nothing to bid on', function () {
const bidRequests = spec.buildRequests([{ params: {} }], bidderRequests)
expect(bidRequests).to.equal(null);
diff --git a/test/spec/modules/sovrnAnalyticsAdapter_spec.js b/test/spec/modules/sovrnAnalyticsAdapter_spec.js
index 68552eb3d8a..973e90abd5a 100644
--- a/test/spec/modules/sovrnAnalyticsAdapter_spec.js
+++ b/test/spec/modules/sovrnAnalyticsAdapter_spec.js
@@ -12,7 +12,7 @@ let constants = require('src/constants.json');
/**
* Emit analytics events
- * @param {array} eventArr - array of objects to define the events that will fire
+ * @param {Array} eventArr - array of objects to define the events that will fire
* @param {object} eventObj - key is eventType, value is event
* @param {string} auctionId - the auction id to attached to the events
*/
diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js
index 032f959e559..f165a6da6d1 100644
--- a/test/spec/modules/sovrnBidAdapter_spec.js
+++ b/test/spec/modules/sovrnBidAdapter_spec.js
@@ -318,6 +318,41 @@ describe('sovrnBidAdapter', function() {
expect(data.regs.ext['us_privacy']).to.equal(bidderRequest.uspConsent)
})
+ it('should not set coppa when coppa is undefined', function () {
+ const bidderRequest = {
+ ...baseBidderRequest,
+ bidderCode: 'sovrn',
+ auctionId: '1d1a030790a475',
+ bidderRequestId: '22edbae2733bf6',
+ timeout: 3000,
+ bids: [baseBidRequest],
+ gdprConsent: {
+ consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==',
+ gdprApplies: true
+ },
+ }
+ const {regs} = JSON.parse(spec.buildRequests([baseBidRequest], bidderRequest).data)
+ expect(regs.coppa).to.be.undefined
+ })
+
+ it('should set coppa to 1 when coppa is provided with value true', function () {
+ const bidderRequest = {
+ ...baseBidderRequest,
+ ortb2: {
+ regs: {
+ coppa: true
+ }
+ },
+ bidderCode: 'sovrn',
+ auctionId: '1d1a030790a475',
+ bidderRequestId: '22edbae2733bf6',
+ timeout: 3000,
+ bids: [baseBidRequest]
+ }
+ const {regs} = JSON.parse(spec.buildRequests([baseBidRequest], bidderRequest).data)
+ expect(regs.coppa).to.equal(1)
+ })
+
it('should send gpp info in OpenRTB 2.6 location when gppConsent defined', function () {
const bidderRequest = {
...baseBidderRequest,
diff --git a/test/spec/modules/sparteoBidAdapter_spec.js b/test/spec/modules/sparteoBidAdapter_spec.js
index e82f23a1d4e..293f7da30a1 100644
--- a/test/spec/modules/sparteoBidAdapter_spec.js
+++ b/test/spec/modules/sparteoBidAdapter_spec.js
@@ -6,13 +6,15 @@ const CURRENCY = 'EUR';
const TTL = 60;
const HTTP_METHOD = 'POST';
const REQUEST_URL = 'https://bid.sparteo.com/auction';
+const USER_SYNC_URL_IFRAME = 'https://sync.sparteo.com/sync/iframe.html?from=prebidjs';
const VALID_BID_BANNER = {
bidder: 'sparteo',
bidId: '1a2b3c4d',
adUnitCode: 'id-1234',
params: {
- networkId: '1234567a-eb1b-1fae-1d23-e1fbaef234cf'
+ networkId: '1234567a-eb1b-1fae-1d23-e1fbaef234cf',
+ formats: ['corner']
},
mediaTypes: {
banner: {
@@ -64,6 +66,14 @@ const VALID_REQUEST_BANNER = {
'w': 1
}],
'topframe': 0
+ },
+ 'ext': {
+ 'sparteo': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf',
+ 'formats': ['corner']
+ }
+ }
}
}],
'site': {
@@ -99,7 +109,12 @@ const VALID_REQUEST_VIDEO = {
'maxduration': 30,
},
'ext': {
- 'pbadslot': 'video'
+ 'pbadslot': 'video',
+ 'sparteo': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf'
+ }
+ }
}
}],
'site': {
@@ -127,6 +142,14 @@ const VALID_REQUEST = {
'w': 1
}],
'topframe': 0
+ },
+ 'ext': {
+ 'sparteo': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf',
+ 'formats': ['corner']
+ }
+ }
}
}, {
'id': '5e6f7g8h',
@@ -144,7 +167,12 @@ const VALID_REQUEST = {
'maxduration': 30,
},
'ext': {
- 'pbadslot': 'video'
+ 'pbadslot': 'video',
+ 'sparteo': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf'
+ }
+ }
}
}],
'site': {
@@ -296,7 +324,12 @@ describe('SparteoAdapter', function () {
'price': 5,
'ext': {
'prebid': {
- 'type': 'video'
+ 'type': 'video',
+ 'cache': {
+ 'vastXml': {
+ 'url': 'https://pbs.tet.com/cache?uuid=1234'
+ }
+ }
}
},
'adm': 'tag',
@@ -341,7 +374,8 @@ describe('SparteoAdapter', function () {
ttl: TTL,
mediaType: 'video',
meta: {},
- vastUrl: 'https://t.bidder.sparteo.com/img',
+ nurl: 'https://t.bidder.sparteo.com/img',
+ vastUrl: 'https://pbs.tet.com/cache?uuid=1234',
vastXml: 'tag'
});
}
@@ -405,4 +439,29 @@ describe('SparteoAdapter', function () {
});
});
});
+
+ describe('getUserSyncs', function() {
+ describe('Check methods succeed', function () {
+ it('should return the sync url', function() {
+ const syncOptions = {
+ 'iframeEnabled': true,
+ 'pixelEnabled': false
+ };
+ const gdprConsent = {
+ gdprApplies: 1,
+ consentString: 'tcfv2'
+ };
+ const uspConsent = {
+ consentString: '1Y---'
+ };
+
+ const syncUrls = [{
+ type: 'iframe',
+ url: USER_SYNC_URL_IFRAME + '&gdpr=1&gdpr_consent=tcfv2&usp_consent=1Y---'
+ }];
+
+ expect(adapter.getUserSyncs(syncOptions, null, gdprConsent, uspConsent)).to.deep.equal(syncUrls);
+ });
+ });
+ });
});
diff --git a/test/spec/modules/stroeerCoreBidAdapter_spec.js b/test/spec/modules/stroeerCoreBidAdapter_spec.js
index 2ed5f80f152..66e0da6ddf8 100644
--- a/test/spec/modules/stroeerCoreBidAdapter_spec.js
+++ b/test/spec/modules/stroeerCoreBidAdapter_spec.js
@@ -844,6 +844,39 @@ describe('stroeerCore bid adapter', function () {
assert.nestedPropertyVal(bid, 'ban.fp.cur', 'EUR');
assert.deepNestedPropertyVal(bid, 'ban.fp.siz', [{w: 160, h: 60, p: 2.7}]);
});
+
+ it('should add the DSA signals', () => {
+ const bidReq = buildBidderRequest();
+ const dsa = {
+ dsarequired: 3,
+ pubrender: 0,
+ datatopub: 2,
+ transparency: [
+ {
+ domain: 'testplatform.com',
+ dsaparams: [1],
+ },
+ {
+ domain: 'testdomain.com',
+ dsaparams: [1, 2]
+ }
+ ]
+ }
+ const ortb2 = {
+ regs: {
+ ext: {
+ dsa
+ }
+ }
+ }
+
+ bidReq.ortb2 = utils.deepClone(ortb2);
+
+ const serverRequestInfo = spec.buildRequests(bidReq.bids, bidReq);
+ const sentOrtb2 = serverRequestInfo.data.ortb2;
+
+ assert.deepEqual(sentOrtb2, ortb2);
+ });
});
});
});
@@ -882,13 +915,32 @@ describe('stroeerCore bid adapter', function () {
assertStandardFieldsOnVideoBid(videoBidResponse, 'bid1', '
video', 800, 250, 4);
})
- it('should add data to meta object', () => {
+ it('should add advertiser domains to meta object', () => {
const response = buildBidderResponse();
response.bids[0] = Object.assign(response.bids[0], {adomain: ['website.org', 'domain.com']});
const result = spec.interpretResponse({body: response});
- assert.deepPropertyVal(result[0], 'meta', {advertiserDomains: ['website.org', 'domain.com']});
- // nothing provided for the second bid
- assert.deepPropertyVal(result[1], 'meta', {advertiserDomains: undefined});
+ assert.deepPropertyVal(result[0].meta, 'advertiserDomains', ['website.org', 'domain.com']);
+ assert.propertyVal(result[1].meta, 'advertiserDomains', undefined);
+ });
+
+ it('should add dsa info to meta object', () => {
+ const dsaResponse = {
+ behalf: 'AdvertiserA',
+ paid: 'AdvertiserB',
+ transparency: [{
+ domain: 'dspexample.com',
+ dsaparams: [1, 2],
+ }],
+ adrender: 1
+ };
+
+ const response = buildBidderResponse();
+ response.bids[0] = Object.assign(response.bids[0], {dsa: utils.deepClone(dsaResponse)});
+
+ const result = spec.interpretResponse({body: response});
+
+ assert.deepPropertyVal(result[0].meta, 'dsa', dsaResponse);
+ assert.propertyVal(result[1].meta, 'dsa', undefined);
});
});
diff --git a/test/spec/modules/stvBidAdapter_spec.js b/test/spec/modules/stvBidAdapter_spec.js
index 41f29cced34..3ef865ed2f1 100644
--- a/test/spec/modules/stvBidAdapter_spec.js
+++ b/test/spec/modules/stvBidAdapter_spec.js
@@ -71,6 +71,24 @@ describe('stvAdapter', function() {
'hp': 1
}
]
+ },
+ 'userId': {
+ 'id5id': {
+ 'uid': '1234',
+ 'ext': {
+ 'linkType': 'abc'
+ }
+ },
+ 'netId': '2345',
+ 'uid2': {
+ 'id': '3456',
+ },
+ 'sharedid': {
+ 'id': '4567',
+ },
+ 'idl_env': '5678',
+ 'criteoId': '6789',
+ 'utiq': '7890',
}
},
{
@@ -84,7 +102,27 @@ describe('stvAdapter', function() {
],
'bidId': '30b31c1838de1e2',
'bidderRequestId': '22edbae2733bf62',
- 'auctionId': '1d1a030790a476'
+ 'auctionId': '1d1a030790a476',
+ 'userId': { // with other utiq variant
+ 'id5id': {
+ 'uid': '1234',
+ 'ext': {
+ 'linkType': 'abc'
+ }
+ },
+ 'netId': '2345',
+ 'uid2': {
+ 'id': '3456',
+ },
+ 'sharedid': {
+ 'id': '4567',
+ },
+ 'idl_env': '5678',
+ 'criteoId': '6789',
+ 'utiq': {
+ 'id': '7890'
+ },
+ }
}, {
'bidder': 'stv',
'params': {
@@ -181,7 +219,7 @@ describe('stvAdapter', function() {
expect(request1.method).to.equal('GET');
expect(request1.url).to.equal(ENDPOINT_URL);
let data = request1.data.replace(/rnd=\d+\&/g, '').replace(/ref=.*\&bid/g, 'bid').replace(/pbver=.*?&/g, 'pbver=test&');
- expect(data).to.equal('_f=html&alternative=prebid_js&_ps=6682&srw=300&srh=250&idt=100&bid_id=30b31c1838de1e1&pbver=test&schain=1.0,0!reseller.com,aaaaa,1,BidRequest4,,,&pfilter%5Bfloorprice%5D=1000000&pfilter%5Bgeo%5D%5Bcountry%5D=DE&gdpr_consent=BOJ%2FP2HOJ%2FP2HABABMAAAAAZ%2BA%3D%3D&gdpr=true&bcat=IAB2%2CIAB4&dvt=desktop&pbcode=testDiv1&media_types%5Bbanner%5D=300x250');
+ expect(data).to.equal('_f=html&alternative=prebid_js&_ps=6682&srw=300&srh=250&idt=100&bid_id=30b31c1838de1e1&pbver=test&schain=1.0,0!reseller.com,aaaaa,1,BidRequest4,,&uids=id5%3A1234,id5_linktype%3Aabc,netid%3A2345,uid2%3A3456,sharedid%3A4567,liverampid%3A5678,criteoid%3A6789,utiq%3A7890&pfilter%5Bfloorprice%5D=1000000&pfilter%5Bgeo%5D%5Bcountry%5D=DE&gdpr_consent=BOJ%2FP2HOJ%2FP2HABABMAAAAAZ%2BA%3D%3D&gdpr=true&bcat=IAB2%2CIAB4&dvt=desktop&pbcode=testDiv1&media_types%5Bbanner%5D=300x250');
});
var request2 = spec.buildRequests([bidRequests[1]], bidderRequest)[0];
@@ -189,7 +227,7 @@ describe('stvAdapter', function() {
expect(request2.method).to.equal('GET');
expect(request2.url).to.equal(ENDPOINT_URL);
let data = request2.data.replace(/rnd=\d+\&/g, '').replace(/ref=.*\&bid/g, 'bid').replace(/pbver=.*?&/g, 'pbver=test&');
- expect(data).to.equal('_f=html&alternative=prebid_js&_ps=101&srw=300&srh=250&idt=100&bid_id=30b31c1838de1e2&pbver=test&gdpr_consent=BOJ%2FP2HOJ%2FP2HABABMAAAAAZ%2BA%3D%3D&gdpr=true&prebidDevMode=1&media_types%5Bbanner%5D=300x250');
+ expect(data).to.equal('_f=html&alternative=prebid_js&_ps=101&srw=300&srh=250&idt=100&bid_id=30b31c1838de1e2&pbver=test&uids=id5%3A1234,id5_linktype%3Aabc,netid%3A2345,uid2%3A3456,sharedid%3A4567,liverampid%3A5678,criteoid%3A6789,utiq%3A7890&gdpr_consent=BOJ%2FP2HOJ%2FP2HABABMAAAAAZ%2BA%3D%3D&gdpr=true&prebidDevMode=1&media_types%5Bbanner%5D=300x250');
});
// Without gdprConsent
diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js
index 16bbb525ee7..dd91c410d08 100644
--- a/test/spec/modules/taboolaBidAdapter_spec.js
+++ b/test/spec/modules/taboolaBidAdapter_spec.js
@@ -1,5 +1,5 @@
import {expect} from 'chai';
-import {spec, internal, END_POINT_URL, userData} from 'modules/taboolaBidAdapter.js';
+import {spec, internal, END_POINT_URL, userData, EVENT_ENDPOINT} from 'modules/taboolaBidAdapter.js';
import {config} from '../../../src/config'
import * as utils from '../../../src/utils'
import {server} from '../../mocks/xhr'
@@ -113,6 +113,50 @@ describe('Taboola Adapter', function () {
});
});
+ describe('onTimeout', function () {
+ it('onTimeout exist as a function', () => {
+ expect(spec.onTimeout).to.exist.and.to.be.a('function');
+ });
+ it('should send timeout', function () {
+ const timeoutData = [{
+ bidder: 'taboola',
+ bidId: 'da43860a-4644-442a-b5e0-93f268cf8d19',
+ params: [{
+ publisherId: 'publisherId'
+ }],
+ adUnitCode: 'adUnit-code',
+ timeout: 3000,
+ auctionId: '12a34b56c'
+ }]
+ spec.onTimeout(timeoutData);
+ expect(server.requests[0].method).to.equal('POST');
+ expect(server.requests[0].url).to.equal(EVENT_ENDPOINT + '/timeout');
+ expect(JSON.parse(server.requests[0].requestBody)).to.deep.equal(timeoutData);
+ });
+ });
+
+ describe('onBidderError', function () {
+ it('onBidderError exist as a function', () => {
+ expect(spec.onBidderError).to.exist.and.to.be.a('function');
+ });
+ it('should send bidder error', function () {
+ const error = {
+ status: 204,
+ statusText: 'No Content'
+ };
+ const bidderRequest = {
+ bidder: 'taboola',
+ params: {
+ publisherId: 'publisherId'
+ }
+ }
+ spec.onBidderError({error, bidderRequest});
+ expect(server.requests[0].method).to.equal('POST');
+ expect(server.requests[0].url).to.equal(EVENT_ENDPOINT + '/bidError');
+ expect(JSON.parse(server.requests[0].requestBody)).to.deep.equal(error, bidderRequest);
+ });
+ });
+
describe('buildRequests', function () {
const defaultBidRequest = {
...createBidRequest(),
@@ -129,10 +173,10 @@ describe('Taboola Adapter', function () {
}
it('should build display request', function () {
+ const res = spec.buildRequests([defaultBidRequest], commonBidderRequest);
const expectedData = {
- id: 'mock-uuid',
'imp': [{
- 'id': 1,
+ 'id': res.data.imp[0].id,
'banner': {
format: [{
w: displayBidRequestParams.sizes[0][0],
@@ -149,6 +193,8 @@ describe('Taboola Adapter', function () {
'bidfloorcur': 'USD',
'ext': {}
}],
+ id: 'mock-uuid',
+ 'test': 0,
'site': {
'id': commonBidRequest.params.publisherId,
'name': commonBidRequest.params.publisherId,
@@ -171,10 +217,8 @@ describe('Taboola Adapter', function () {
'ext': {}
};
- const res = spec.buildRequests([defaultBidRequest], commonBidderRequest);
-
expect(res.url).to.equal(`${END_POINT_URL}?publisher=${commonBidRequest.params.publisherId}`);
- expect(res.data).to.deep.equal(JSON.stringify(expectedData));
+ expect(JSON.stringify(res.data)).to.deep.equal(JSON.stringify(expectedData));
});
it('should pass optional parameters in request', function () {
@@ -189,9 +233,8 @@ describe('Taboola Adapter', function () {
};
const res = spec.buildRequests([bidRequest], commonBidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.imp[0].bidfloor).to.deep.equal(0.25);
- expect(resData.imp[0].bidfloorcur).to.deep.equal('EUR');
+ expect(res.data.imp[0].bidfloor).to.deep.equal(0.25);
+ expect(res.data.imp[0].bidfloorcur).to.deep.equal('EUR');
});
it('should pass bid floor', function () {
@@ -206,9 +249,8 @@ describe('Taboola Adapter', function () {
}
};
const res = spec.buildRequests([bidRequest], commonBidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.imp[0].bidfloor).to.deep.equal(2.7);
- expect(resData.imp[0].bidfloorcur).to.deep.equal('USD');
+ expect(res.data.imp[0].bidfloor).to.deep.equal(2.7);
+ expect(res.data.imp[0].bidfloorcur).to.deep.equal('USD');
});
it('should pass bid floor even if it is a bid floor param', function () {
@@ -228,9 +270,8 @@ describe('Taboola Adapter', function () {
}
};
const res = spec.buildRequests([bidRequest], commonBidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.imp[0].bidfloor).to.deep.equal(2.7);
- expect(resData.imp[0].bidfloorcur).to.deep.equal('USD');
+ expect(res.data.imp[0].bidfloor).to.deep.equal(2.7);
+ expect(res.data.imp[0].bidfloorcur).to.deep.equal('USD');
});
it('should pass impression position', function () {
@@ -244,8 +285,7 @@ describe('Taboola Adapter', function () {
};
const res = spec.buildRequests([bidRequest], commonBidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.imp[0].banner.pos).to.deep.equal(2);
+ expect(res.data.imp[0].banner.pos).to.deep.equal(2);
});
it('should pass gpid if configured', function () {
@@ -261,8 +301,23 @@ describe('Taboola Adapter', function () {
};
const res = spec.buildRequests([bidRequest], commonBidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.imp[0].ext.gpid).to.deep.equal('/homepage/#1');
+ expect(res.data.imp[0].ext.gpid).to.deep.equal('/homepage/#1');
+ });
+
+ it('should pass new parameter to imp ext', function () {
+ const ortb2Imp = {
+ ext: {
+ example: 'example'
+ }
+ }
+ const bidRequest = {
+ ...defaultBidRequest,
+ ortb2Imp: ortb2Imp,
+ params: {...commonBidRequest.params}
+ };
+
+ const res = spec.buildRequests([bidRequest], commonBidderRequest);
+ expect(res.data.imp[0].ext.example).to.deep.equal('example');
});
it('should pass bidder timeout', function () {
@@ -271,8 +326,25 @@ describe('Taboola Adapter', function () {
timeout: 500
}
const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.tmax).to.equal(500);
+ expect(res.data.tmax).to.equal(500);
+ });
+
+ it('should pass bidder tmax as int', function () {
+ const bidderRequest = {
+ ...commonBidderRequest,
+ timeout: '500'
+ }
+ const res = spec.buildRequests([defaultBidRequest], bidderRequest);
+ expect(res.data.tmax).to.equal(500);
+ });
+
+ it('should pass bidder timeout as null', function () {
+ const bidderRequest = {
+ ...commonBidderRequest,
+ timeout: null
+ }
+ const res = spec.buildRequests([defaultBidRequest], bidderRequest);
+ expect(res.data.tmax).to.equal(undefined);
});
describe('first party data', function () {
@@ -286,10 +358,9 @@ describe('Taboola Adapter', function () {
}
}
const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.bcat).to.deep.equal(bidderRequest.ortb2.bcat)
- expect(resData.badv).to.deep.equal(bidderRequest.ortb2.badv)
- expect(resData.wlang).to.deep.equal(bidderRequest.ortb2.wlang)
+ expect(res.data.bcat).to.deep.equal(bidderRequest.ortb2.bcat)
+ expect(res.data.badv).to.deep.equal(bidderRequest.ortb2.badv)
+ expect(res.data.wlang).to.deep.equal(bidderRequest.ortb2.wlang)
});
it('should pass pageType if exists in ortb2', function () {
@@ -304,8 +375,20 @@ describe('Taboola Adapter', function () {
}
}
const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.ext.pageType).to.deep.equal(bidderRequest.ortb2.ext.data.pageType);
+ expect(res.data.ext.pageType).to.deep.equal(bidderRequest.ortb2.ext.data.pageType);
+ });
+
+ it('should pass additional parameter in request', function () {
+ const bidderRequest = {
+ ...commonBidderRequest,
+ ortb2: {
+ ext: {
+ example: 'example'
+ }
+ }
+ }
+ const res = spec.buildRequests([defaultBidRequest], bidderRequest);
+ expect(res.data.ext.example).to.deep.equal(bidderRequest.ortb2.ext.example);
});
});
@@ -322,9 +405,8 @@ describe('Taboola Adapter', function () {
};
const res = spec.buildRequests([defaultBidRequest], bidderRequest)
- const resData = JSON.parse(res.data)
- expect(resData.user.ext.consent).to.equal('consentString')
- expect(resData.regs.ext.gdpr).to.equal(1)
+ expect(res.data.user.ext.consent).to.equal('consentString')
+ expect(res.data.regs.ext.gdpr).to.equal(1)
});
it('should pass GPP consent if exist in ortb2', function () {
@@ -336,9 +418,8 @@ describe('Taboola Adapter', function () {
}
const res = spec.buildRequests([defaultBidRequest], {...commonBidderRequest, ortb2})
- const resData = JSON.parse(res.data)
- expect(resData.regs.ext.gpp).to.equal('testGpp')
- expect(resData.regs.ext.gpp_sid).to.deep.equal([1, 2, 3])
+ expect(res.data.regs.ext.gpp).to.equal('testGpp')
+ expect(res.data.regs.ext.gpp_sid).to.deep.equal([1, 2, 3])
});
it('should pass us privacy consent', function () {
@@ -349,16 +430,14 @@ describe('Taboola Adapter', function () {
uspConsent: 'consentString'
}
const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.regs.ext.us_privacy).to.equal('consentString');
+ expect(res.data.regs.ext.us_privacy).to.equal('consentString');
});
it('should pass coppa consent', function () {
config.setConfig({coppa: true})
const res = spec.buildRequests([defaultBidRequest], commonBidderRequest)
- const resData = JSON.parse(res.data);
- expect(resData.regs.coppa).to.equal(1)
+ expect(res.data.regs.coppa).to.equal(1)
config.resetConfig()
});
@@ -375,8 +454,7 @@ describe('Taboola Adapter', function () {
timeout: 500
}
const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.user.buyeruid).to.equal(51525152);
+ expect(res.data.user.buyeruid).to.equal(51525152);
});
it('should get user id from cookie if local storage isn`t defined', function () {
@@ -390,9 +468,22 @@ describe('Taboola Adapter', function () {
...commonBidderRequest
};
const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- const resData = JSON.parse(res.data);
+ expect(res.data.user.buyeruid).to.equal('12121212');
+ });
+
+ it('should get user id from tgid cookie if local storage isn`t defined', function () {
+ getDataFromLocalStorage.returns(51525152);
+ hasLocalStorage.returns(false);
+ localStorageIsEnabled.returns(false);
+ cookiesAreEnabled.returns(true);
+ getCookie.returns('d966c5be-c49f-4f73-8cd1-37b6b5790653-tuct9f7bf10');
+
+ const bidderRequest = {
+ ...commonBidderRequest
+ };
+ const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- expect(resData.user.buyeruid).to.equal('12121212');
+ expect(res.data.user.buyeruid).to.equal('d966c5be-c49f-4f73-8cd1-37b6b5790653-tuct9f7bf10');
});
it('should get user id from TRC if local storage and cookie isn`t defined', function () {
@@ -408,8 +499,7 @@ describe('Taboola Adapter', function () {
...commonBidderRequest
}
const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.user.buyeruid).to.equal(window.TRC.user_id);
+ expect(res.data.user.buyeruid).to.equal(window.TRC.user_id);
delete window.TRC;
});
@@ -422,8 +512,7 @@ describe('Taboola Adapter', function () {
...commonBidderRequest
}
const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.user.buyeruid).to.equal(0);
+ expect(res.data.user.buyeruid).to.equal(0);
});
it('should set buyeruid to be 0 if it`s a new user', function () {
@@ -431,13 +520,29 @@ describe('Taboola Adapter', function () {
...commonBidderRequest
}
const res = spec.buildRequests([defaultBidRequest], bidderRequest);
- const resData = JSON.parse(res.data);
- expect(resData.user.buyeruid).to.equal(0);
+ expect(res.data.user.buyeruid).to.equal(0);
});
});
})
describe('interpretResponse', function () {
+ const defaultBidRequest = {
+ ...createBidRequest(),
+ ...displayBidRequestParams,
+ };
+ const commonBidderRequest = {
+ bidderRequestId: 'mock-uuid',
+ refererInfo: {
+ page: 'https://example.com/ref',
+ ref: 'https://ref',
+ domain: 'example.com',
+ }
+ };
+ const bidderRequest = {
+ ...commonBidderRequest
+ };
+ const request = spec.buildRequests([defaultBidRequest], bidderRequest);
+
const serverResponse = {
body: {
'id': '49ffg4d58ef9a163a69fhgfghd4fad03621b9e036f24f7_15',
@@ -446,7 +551,7 @@ describe('Taboola Adapter', function () {
'bid': [
{
'id': '0b3dd94348-134b-435f-8db5-6bf5afgfc39e86c',
- 'impid': '1',
+ 'impid': request.data.imp[0].id,
'price': 0.342068,
'adid': '2785119545551083381',
'adm': '\u003chtml\u003e\n\u003chead\u003e\n\u003cmeta charset\u003d"UTF-8"\u003e\n\u003cmeta http-equiv\u003d"Content-Type" content\u003d"text/html; charset\u003dutf-8"/\u003e\u003c/head\u003e\n\u003cbody style\u003d"margin: 0px; overflow:hidden;"\u003e \n\u003cscript type\u003d"text/javascript"\u003e\nwindow.tbl_trc_domain \u003d \u0027us-trc.taboola.com\u0027;\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({article:\u0027auto\u0027});\n!function (e, f, u, i) {\nif (!document.getElementById(i)){\ne.async \u003d 1;\ne.src \u003d u;\ne.id \u003d i;\nf.parentNode.insertBefore(e, f);\n}\n}(document.createElement(\u0027script\u0027),\ndocument.getElementsByTagName(\u0027script\u0027)[0],\n\u0027//cdn.taboola.com/libtrc/wattpad-placement-255/loader.js\u0027,\n\u0027tb_loader_script\u0027);\nif(window.performance \u0026\u0026 typeof window.performance.mark \u003d\u003d \u0027function\u0027)\n{window.performance.mark(\u0027tbl_ic\u0027);}\n\u003c/script\u003e\n\n\u003cdiv id\u003d"taboola-below-article-thumbnails" style\u003d"height: 250px; width: 300px;"\u003e\u003c/div\u003e\n\u003cscript type\u003d"text/javascript"\u003e\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({\nmode: \u0027Rbox_300x250_1x1\u0027,\ncontainer: \u0027taboola-below-article-thumbnails\u0027,\nplacement: \u0027wattpad.com_P18694_S257846_W300_H250_N1_TB\u0027,\ntarget_type: \u0027mix\u0027,\n"rtb-win":{ \nbi:\u002749ff4d58ef9a163a696d4fad03621b9e036f24f7_15\u0027,\ncu:\u0027USD\u0027,\nwp:\u0027${AUCTION_PRICE:BF}\u0027,\nwcb:\u0027~!audex-display-impression!~\u0027,\nrt:\u00271643227025284\u0027,\nrdc:\u0027us.taboolasyndication.com\u0027,\nti:\u00274212\u0027,\nex:\u0027MagniteSCoD\u0027,\nbs:\u0027xapi:257846:lvvSm6Ak7_wE\u0027,\nbp:\u002718694\u0027,\nbd:\u0027wattpad.com\u0027,\nsi:\u00279964\u0027\n} \n,\nrec: {"trc":{"si":"a69c7df43b2334f0aa337c37e2d80c21","sd":"v2_a69c7df43b2334f0aa337c37e2d80c21_3c70f7c7d64a65b15e4a4175c9a2cfa51072f04bMagniteSCoD_1643227025_1643227025_CJS1tQEQ5NdWGPLA0d76xo-9ngEgASgEMCY4iegHQIroB0iB09kDUKPPB1gAYABop-G2i_Hl-eVucAA","ui":"3c70f7c7d64a65b15e4a4175c9a2cfa51072f04bMagniteSCoD","plc":"PHON","wi":"-643136642229425433","cc":"CA","route":"US:US:V","el2r":["bulk-metrics","debug","social","metrics","perf"],"uvpw":"1","pi":"1420260","cpb":"GNO629MGIJz__________wEqGXVzLnRhYm9vbGFzeW5kaWNhdGlvbi5jb20yC3RyYy1zY29kMTI5OIDwmrUMQInoB0iK6AdQgdPZA1ijzwdjCN3__________wEQ3f__________ARgjZGMI3AoQoBAYFmRjCNIDEOAGGAhkYwiWFBCcHBgYZGMI9AUQiwoYC2RjCNkUEPkcGB1kYwj0FBCeHRgfZGorNDlmZjRkNThlZjlhMTYzYTY5NmQ0ZmFkMDM2MjFiOWUwMzZmMjRmN18xNXgCgAHpbIgBrPvTxQE","dcga":{"pubConfigOverride":{"border-color":"black","font-weight":"bold","inherit-title-color":"true","module-name":"cta-lazy-module","enable-call-to-action-creative-component":"true","disable-cta-on-custom-module":"true"}},"tslt":{"p-video-overlay":{"cancel":"ץ××ר","goto":"×ĸ××ר ×××Ŗ"},"read-more":{"DEFAULT_CAPTION":"%D7%A7%D7%A8%D7%90%20%D7%A2%D7%95%D7%93"},"next-up":{"BTN_TEXT":"×קר×××Ē ××Ē××× ×××"},"time-ago":{"now":"×ĸ×׊××","today":"××××","yesterday":"××Ē×××","minutes":"××¤× × {0} ×ק××Ē","hour":"××¤× × ×Š×ĸ×","hours":"××¤× × {0} ׊×ĸ××Ē","days":"××¤× × {0} ××××"},"explore-more":{"TITLE_TEXT":"××׊××× ×קר××","POPUP_TEXT":"×× ×Ē×¤×Ą×¤×Ą× ××××× ××Ē ×קר×× ×ĸ×× ×Ē××× ××ĸ×××, ר××ĸ ××¤× × ×Š×Ē×ĸ×××"}},"evh":"-1964913910","vl":[{"ri":"185db6d274ce94b27caaabd9eed7915b","uip":"wattpad.com_P18694_S257846_W300_H250_N1_TB","ppb":"COIF","estimation_method":"EcpmEstimationMethodType_ESTIMATION","baseline_variant":"false","original_ecpm":"0.4750949889421463","v":[{"thumbnail":"https://cdn.taboola.com/libtrc/static/thumbnails/a2b272be514ca3ebe3f97a4a32a41db5.jpg","all-thumbnails":"https://cdn.taboola.com/libtrc/static/thumbnails/a2b272be514ca3ebe3f97a4a32a41db5.jpg!-#@1600x1000","origin":"default","thumb-size":"1600x1000","title":"Get Roofing Services At Prices You Can Afford In Edmonton","type":"text","published-date":"1641997069","branding-text":"Roofing Services | Search Ads","url":"https://inneth-conded.xyz/9ad2e613-8777-4fe7-9a52-386c88879289?site\u003dwattpad-placement-255\u0026site_id\u003d1420260\u0026title\u003dGet+Roofing+Services+At+Prices+You+Can+Afford+In+Edmonton\u0026platform\u003dSmartphone\u0026campaign_id\u003d15573949\u0026campaign_item_id\u003d3108610633\u0026thumbnail\u003dhttp%3A%2F%2Fcdn.taboola.com%2Flibtrc%2Fstatic%2Fthumbnails%2Fa2b272be514ca3ebe3f97a4a32a41db5.jpg\u0026cpc\u003d{cpc}\u0026click_id\u003dGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1\u0026tblci\u003dGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1#tblciGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1","duration":"0","sig":"328243c4127ff16e3fdcd7270bab908f6f3fc5b4c98d","item-id":"~~V1~~2785119550041083381~~PnBkfBE9JnQxpahv0adkcuIcmMhroRAHXwLZd-7zhunTxvAnL2wqac4MyzR7uD46gj3kUkbS3FhelBtnsiJV6MhkDZRZzzIqDobN6rWmCPA3hYz5D3PLat6nhIftiT1lwdxwdlxkeV_Mfb3eos_TQavImGhxk0e7psNAZxHJ9RKL2w3lppALGgQJoy2o6lkf-pOqODtX1VkgWpEEM4WsVoWOnUTAwdyGd-8yrze8CWNp752y28hl7lleicyO1vByRdbgwlJdnqyroTPEQNNEn1JRxBOSYSWt-Xm3vkPm-G4","uploader":"","is-syndicated":"true","publisher":"search","id":"~~V1~~2785119550041083381~~PnBkfBE9JnQxpahv0adkcuIcmMhroRAHXwLZd-7zhunTxvAnL2wqac4MyzR7uD46gj3kUkbS3FhelBtnsiJV6MhkDZRZzzIqDobN6rWmCPA3hYz5D3PLat6nhIftiT1lwdxwdlxkeV_Mfb3eos_TQavImGhxk0e7psNAZxHJ9RKL2w3lppALGgQJoy2o6lkf-pOqODtX1VkgWpEEM4WsVoWOnUTAwdyGd-8yrze8CWNp752y28hl7lleicyO1vByRdbgwlJdnqyroTPEQNNEn1JRxBOSYSWt-Xm3vkPm-G4","category":"home","views":"0","itp":[{"u":"https://trc.taboola.com/1326786/log/3/unip?en\u003dclickersusa","t":"c"}],"description":""}]}],"cpcud":{"upc":"0.0","upr":"0.0"}}}\n});\n\u003c/script\u003e\n\n\u003cscript type\u003d"text/javascript"\u003e\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({flush: true});\n\u003c/script\u003e\n\n\u003c/body\u003e\n\u003c/html\u003e',
@@ -471,15 +576,6 @@ describe('Taboola Adapter', function () {
}
};
- const request = {
- bids: [
- {
- ...commonBidRequest,
- ...displayBidRequestParams
- }
- ]
- }
-
it('should return empty array if no valid bids', function () {
const res = spec.interpretResponse(serverResponse, [])
expect(res).to.be.an('array').that.is.empty
@@ -513,18 +609,7 @@ describe('Taboola Adapter', function () {
});
it('should interpret multi impression request', function () {
- const multiRequest = {
- bids: [
- {
- ...createBidRequest(),
- ...displayBidRequestParams
- },
- {
- ...createBidRequest(),
- ...displayBidRequestParams
- }
- ]
- }
+ const multiRequest = spec.buildRequests([defaultBidRequest, defaultBidRequest], bidderRequest);
const multiServerResponse = {
body: {
@@ -534,7 +619,7 @@ describe('Taboola Adapter', function () {
'bid': [
{
'id': '0b3dd94348-134b-435f-8db5-6bf5afgfc39e86c',
- 'impid': '2',
+ 'impid': multiRequest.data.imp[0].id,
'price': 0.342068,
'adid': '2785119545551083381',
'adm': 'ADM2',
@@ -551,7 +636,7 @@ describe('Taboola Adapter', function () {
},
{
'id': '0b3dd94348-134b-435f-8db5-6bf5afgfc39e86c',
- 'impid': '1',
+ 'impid': multiRequest.data.imp[1].id,
'price': 0.342068,
'adid': '2785119545551083381',
'adm': 'ADM1',
@@ -582,6 +667,8 @@ describe('Taboola Adapter', function () {
requestId: multiRequest.bids[1].bidId,
cpm: bid.price,
creativeId: bid.crid,
+ creative_id: bid.crid,
+ seatBidId: multiServerResponse.body.seatbid[0].bid[0].id,
ttl: 60,
netRevenue: true,
currency: multiServerResponse.body.cur,
@@ -598,6 +685,8 @@ describe('Taboola Adapter', function () {
requestId: multiRequest.bids[0].bidId,
cpm: bid.price,
creativeId: bid.crid,
+ creative_id: bid.crid,
+ seatBidId: multiServerResponse.body.seatbid[0].bid[1].id,
ttl: 60,
netRevenue: true,
currency: multiServerResponse.body.cur,
@@ -621,8 +710,10 @@ describe('Taboola Adapter', function () {
const expectedRes = [
{
requestId: request.bids[0].bidId,
+ seatBidId: serverResponse.body.seatbid[0].bid[0].id,
cpm: bid.price,
creativeId: bid.crid,
+ creative_id: bid.crid,
ttl: 60,
netRevenue: true,
currency: serverResponse.body.cur,
@@ -648,8 +739,10 @@ describe('Taboola Adapter', function () {
const expectedRes = [
{
requestId: request.bids[0].bidId,
+ seatBidId: serverResponse.body.seatbid[0].bid[0].id,
cpm: bid.price,
creativeId: bid.crid,
+ creative_id: bid.crid,
ttl: 125,
netRevenue: true,
currency: serverResponse.body.cur,
@@ -668,18 +761,7 @@ describe('Taboola Adapter', function () {
});
it('should replace AUCTION_PRICE macro in adm', function () {
- const multiRequest = {
- bids: [
- {
- ...createBidRequest(),
- ...displayBidRequestParams
- },
- {
- ...createBidRequest(),
- ...displayBidRequestParams
- }
- ]
- }
+ const multiRequest = spec.buildRequests([defaultBidRequest, defaultBidRequest], bidderRequest);
const multiServerResponseWithMacro = {
body: {
'id': '49ffg4d58ef9a163a69fhgfghd4fad03621b9e036f24f7_15',
@@ -688,7 +770,7 @@ describe('Taboola Adapter', function () {
'bid': [
{
'id': '0b3dd94348-134b-435f-8db5-6bf5afgfc39e86c',
- 'impid': '2',
+ 'impid': multiRequest.data.imp[0].id,
'price': 0.34,
'adid': '2785119545551083381',
'adm': 'ADM2,\\nwp:\'${AUCTION_PRICE}\'',
@@ -705,7 +787,7 @@ describe('Taboola Adapter', function () {
},
{
'id': '0b3dd94348-134b-435f-8db5-6bf5afgfc39e86c',
- 'impid': '1',
+ 'impid': multiRequest.data.imp[1].id,
'price': 0.35,
'adid': '2785119545551083381',
'adm': 'ADM2,\\nwp:\'${AUCTION_PRICE}\'',
@@ -735,6 +817,8 @@ describe('Taboola Adapter', function () {
requestId: multiRequest.bids[1].bidId,
cpm: multiServerResponseWithMacro.body.seatbid[0].bid[0].price,
creativeId: bid.crid,
+ creative_id: bid.crid,
+ seatBidId: multiServerResponseWithMacro.body.seatbid[0].bid[0].id,
ttl: 60,
netRevenue: true,
currency: multiServerResponseWithMacro.body.cur,
@@ -751,6 +835,8 @@ describe('Taboola Adapter', function () {
requestId: multiRequest.bids[0].bidId,
cpm: multiServerResponseWithMacro.body.seatbid[0].bid[1].price,
creativeId: bid.crid,
+ creative_id: bid.crid,
+ seatBidId: multiServerResponseWithMacro.body.seatbid[0].bid[1].id,
ttl: 60,
netRevenue: true,
currency: multiServerResponseWithMacro.body.cur,
@@ -771,17 +857,28 @@ describe('Taboola Adapter', function () {
describe('getUserSyncs', function () {
const usersyncUrl = 'https://trc.taboola.com/sg/prebidJS/1/cm';
+ const iframeUrl = 'https://cdn.taboola.com/scripts/prebid_iframe_sync.html';
- it('should not return user sync if pixelEnabled is false', function () {
- const res = spec.getUserSyncs({pixelEnabled: false});
+ it('should not return user sync if pixelEnabled is false and iframe disabled', function () {
+ const res = spec.getUserSyncs({pixelEnabled: false, iframeEnabled: false});
expect(res).to.be.an('array').that.is.empty;
});
it('should return user sync if pixelEnabled is true', function () {
- const res = spec.getUserSyncs({pixelEnabled: true});
+ const res = spec.getUserSyncs({pixelEnabled: true, iframeEnabled: false});
expect(res).to.deep.equal([{type: 'image', url: usersyncUrl}]);
});
+ it('should return user sync if iframeEnabled is true', function () {
+ const res = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false});
+ expect(res).to.deep.equal([{type: 'iframe', url: iframeUrl}]);
+ });
+
+ it('should return both user syncs if iframeEnabled is true and pixelEnabled is true', function () {
+ const res = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true});
+ expect(res).to.deep.equal([{type: 'iframe', url: iframeUrl}, {type: 'image', url: usersyncUrl}]);
+ });
+
it('should pass consent tokens values', function() {
expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'GDPR_CONSENT'}, 'USP_CONSENT')).to.deep.equal([{
type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=GDPR_CONSENT&us_privacy=USP_CONSENT`
diff --git a/test/spec/modules/tagorasBidAdapter_spec.js b/test/spec/modules/tagorasBidAdapter_spec.js
new file mode 100644
index 00000000000..7559567dcff
--- /dev/null
+++ b/test/spec/modules/tagorasBidAdapter_spec.js
@@ -0,0 +1,651 @@
+import {expect} from 'chai';
+import {
+ spec as adapter,
+ createDomain,
+ hashCode,
+ extractPID,
+ extractCID,
+ extractSubDomain,
+ getStorageItem,
+ setStorageItem,
+ tryParseJSON,
+ getUniqueDealId,
+} from 'modules/tagorasBidAdapter';
+import * as utils from 'src/utils.js';
+import {version} from 'package.json';
+import {useFakeTimers} from 'sinon';
+import {BANNER, VIDEO} from '../../../src/mediaTypes';
+import {config} from '../../../src/config';
+
+export const TEST_ID_SYSTEMS = ['britepoolid', 'criteoId', 'id5id', 'idl_env', 'lipb', 'netId', 'parrableId', 'pubcid', 'tdid', 'pubProvidedId'];
+
+const SUB_DOMAIN = 'exchange';
+
+const BID = {
+ 'bidId': '2d52001cabd527',
+ 'adUnitCode': 'div-gpt-ad-12345-0',
+ 'params': {
+ 'subDomain': SUB_DOMAIN,
+ 'cId': '59db6b3b4ffaa70004f45cdc',
+ 'pId': '59ac17c192832d0011283fe3',
+ 'bidFloor': 0.1,
+ 'ext': {
+ 'param1': 'loremipsum',
+ 'param2': 'dolorsitamet'
+ }
+ },
+ 'placementCode': 'div-gpt-ad-1460505748561-0',
+ 'sizes': [[300, 250], [300, 600]],
+ 'bidderRequestId': '1fdb5ff1b6eaa7',
+ 'bidRequestsCount': 4,
+ 'bidderRequestsCount': 3,
+ 'bidderWinsCount': 1,
+ 'requestId': 'b0777d85-d061-450e-9bc7-260dd54bbb7a',
+ 'schain': 'a0819c69-005b-41ed-af06-1be1e0aefefc',
+ 'mediaTypes': [BANNER],
+ 'ortb2Imp': {
+ 'ext': {
+ 'gpid': '0123456789',
+ 'tid': 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf'
+ }
+ }
+};
+
+const VIDEO_BID = {
+ 'bidId': '2d52001cabd527',
+ 'adUnitCode': '63550ad1ff6642d368cba59dh5884270560',
+ 'bidderRequestId': '12a8ae9ada9c13',
+ 'transactionId': '56e184c6-bde9-497b-b9b9-cf47a61381ee',
+ 'bidRequestsCount': 4,
+ 'bidderRequestsCount': 3,
+ 'bidderWinsCount': 1,
+ 'schain': 'a0819c69-005b-41ed-af06-1be1e0aefefc',
+ 'params': {
+ 'subDomain': SUB_DOMAIN,
+ 'cId': '635509f7ff6642d368cb9837',
+ 'pId': '59ac17c192832d0011283fe3',
+ 'bidFloor': 0.1
+ },
+ 'sizes': [[545, 307]],
+ 'mediaTypes': {
+ 'video': {
+ 'playerSize': [[545, 307]],
+ 'context': 'instream',
+ 'mimes': [
+ 'video/mp4',
+ 'application/javascript'
+ ],
+ 'protocols': [2, 3, 5, 6],
+ 'maxduration': 60,
+ 'minduration': 0,
+ 'startdelay': 0,
+ 'linearity': 1,
+ 'api': [2],
+ 'placement': 1
+ }
+ },
+ 'ortb2Imp': {
+ 'ext': {
+ 'tid': '56e184c6-bde9-497b-b9b9-cf47a61381ee'
+ }
+ }
+}
+
+const BIDDER_REQUEST = {
+ 'gdprConsent': {
+ 'consentString': 'consent_string',
+ 'gdprApplies': true
+ },
+ 'gppString': 'gpp_string',
+ 'gppSid': [7],
+ 'uspConsent': 'consent_string',
+ 'refererInfo': {
+ 'page': 'https://www.greatsite.com',
+ 'ref': 'https://www.somereferrer.com'
+ },
+ 'ortb2': {
+ 'regs': {
+ 'gpp': 'gpp_string',
+ 'gpp_sid': [7]
+ },
+ 'device': {
+ 'sua': {
+ 'source': 2,
+ 'platform': {
+ 'brand': 'Android',
+ 'version': ['8', '0', '0']
+ },
+ 'browsers': [
+ {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']},
+ {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']},
+ {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']}
+ ],
+ 'mobile': 1,
+ 'model': 'SM-G955U',
+ 'bitness': '64',
+ 'architecture': ''
+ }
+ }
+ }
+};
+
+const SERVER_RESPONSE = {
+ body: {
+ cid: 'testcid123',
+ results: [{
+ 'ad': '
',
+ 'price': 0.8,
+ 'creativeId': '12610997325162499419',
+ 'exp': 30,
+ 'width': 300,
+ 'height': 250,
+ 'advertiserDomains': ['securepubads.g.doubleclick.net'],
+ 'cookies': [{
+ 'src': 'https://sync.com',
+ 'type': 'iframe'
+ }, {
+ 'src': 'https://sync.com',
+ 'type': 'img'
+ }]
+ }]
+ }
+};
+
+const VIDEO_SERVER_RESPONSE = {
+ body: {
+ 'cid': '635509f7ff6642d368cb9837',
+ 'results': [{
+ 'ad': '
',
+ 'advertiserDomains': ['tagoras.io'],
+ 'exp': 60,
+ 'width': 545,
+ 'height': 307,
+ 'mediaType': 'video',
+ 'creativeId': '12610997325162499419',
+ 'price': 2,
+ 'cookies': []
+ }]
+ }
+};
+
+const REQUEST = {
+ data: {
+ width: 300,
+ height: 250,
+ bidId: '2d52001cabd527'
+ }
+};
+
+function getTopWindowQueryParams() {
+ try {
+ const parsedUrl = utils.parseUrl(window.top.document.URL, {decodeSearchAsString: true});
+ return parsedUrl.search;
+ } catch (e) {
+ return '';
+ }
+}
+
+describe('TagorasBidAdapter', function () {
+ describe('validtae spec', function () {
+ it('exists and is a function', function () {
+ expect(adapter.isBidRequestValid).to.exist.and.to.be.a('function');
+ });
+
+ it('exists and is a function', function () {
+ expect(adapter.buildRequests).to.exist.and.to.be.a('function');
+ });
+
+ it('exists and is a function', function () {
+ expect(adapter.interpretResponse).to.exist.and.to.be.a('function');
+ });
+
+ it('exists and is a function', function () {
+ expect(adapter.getUserSyncs).to.exist.and.to.be.a('function');
+ });
+
+ it('exists and is a string', function () {
+ expect(adapter.code).to.exist.and.to.be.a('string');
+ });
+
+ it('exists and contains media types', function () {
+ expect(adapter.supportedMediaTypes).to.exist.and.to.be.an('array').with.length(2);
+ expect(adapter.supportedMediaTypes).to.contain.members([BANNER, VIDEO]);
+ });
+ });
+
+ describe('validate bid requests', function () {
+ it('should require cId', function () {
+ const isValid = adapter.isBidRequestValid({
+ params: {
+ pId: 'pid'
+ }
+ });
+ expect(isValid).to.be.false;
+ });
+
+ it('should require pId', function () {
+ const isValid = adapter.isBidRequestValid({
+ params: {
+ cId: 'cid'
+ }
+ });
+ expect(isValid).to.be.false;
+ });
+
+ it('should validate correctly', function () {
+ const isValid = adapter.isBidRequestValid({
+ params: {
+ cId: 'cid',
+ pId: 'pid'
+ }
+ });
+ expect(isValid).to.be.true;
+ });
+ });
+
+ describe('build requests', function () {
+ let sandbox;
+ before(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {
+ tagoras: {
+ storageAllowed: true
+ }
+ };
+ sandbox = sinon.sandbox.create();
+ sandbox.stub(Date, 'now').returns(1000);
+ });
+
+ it('should build video request', function () {
+ const hashUrl = hashCode(BIDDER_REQUEST.refererInfo.page);
+ config.setConfig({
+ bidderTimeout: 3000
+ });
+ const requests = adapter.buildRequests([VIDEO_BID], BIDDER_REQUEST);
+ expect(requests).to.have.length(1);
+ expect(requests[0]).to.deep.equal({
+ method: 'POST',
+ url: `${createDomain(SUB_DOMAIN)}/prebid/multi/635509f7ff6642d368cb9837`,
+ data: {
+ adUnitCode: '63550ad1ff6642d368cba59dh5884270560',
+ bidFloor: 0.1,
+ bidId: '2d52001cabd527',
+ bidderVersion: adapter.version,
+ bidderRequestId: '12a8ae9ada9c13',
+ cb: 1000,
+ gdpr: 1,
+ gdprConsent: 'consent_string',
+ usPrivacy: 'consent_string',
+ gppString: 'gpp_string',
+ gppSid: [7],
+ prebidVersion: version,
+ transactionId: '56e184c6-bde9-497b-b9b9-cf47a61381ee',
+ bidRequestsCount: 4,
+ bidderRequestsCount: 3,
+ bidderWinsCount: 1,
+ bidderTimeout: 3000,
+ publisherId: '59ac17c192832d0011283fe3',
+ url: 'https%3A%2F%2Fwww.greatsite.com',
+ referrer: 'https://www.somereferrer.com',
+ res: `${window.top.screen.width}x${window.top.screen.height}`,
+ schain: VIDEO_BID.schain,
+ sizes: ['545x307'],
+ sua: {
+ 'source': 2,
+ 'platform': {
+ 'brand': 'Android',
+ 'version': ['8', '0', '0']
+ },
+ 'browsers': [
+ {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']},
+ {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']},
+ {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']}
+ ],
+ 'mobile': 1,
+ 'model': 'SM-G955U',
+ 'bitness': '64',
+ 'architecture': ''
+ },
+ uniqueDealId: `${hashUrl}_${Date.now().toString()}`,
+ uqs: getTopWindowQueryParams(),
+ mediaTypes: {
+ video: {
+ api: [2],
+ context: 'instream',
+ linearity: 1,
+ maxduration: 60,
+ mimes: [
+ 'video/mp4',
+ 'application/javascript'
+ ],
+ minduration: 0,
+ placement: 1,
+ playerSize: [[545, 307]],
+ protocols: [2, 3, 5, 6],
+ startdelay: 0
+ }
+ },
+ gpid: ''
+ }
+ });
+ });
+
+ it('should build banner request for each size', function () {
+ const hashUrl = hashCode(BIDDER_REQUEST.refererInfo.page);
+ config.setConfig({
+ bidderTimeout: 3000
+ });
+ const requests = adapter.buildRequests([BID], BIDDER_REQUEST);
+ expect(requests).to.have.length(1);
+ expect(requests[0]).to.deep.equal({
+ method: 'POST',
+ url: `${createDomain(SUB_DOMAIN)}/prebid/multi/59db6b3b4ffaa70004f45cdc`,
+ data: {
+ gdprConsent: 'consent_string',
+ gdpr: 1,
+ gppString: 'gpp_string',
+ gppSid: [7],
+ usPrivacy: 'consent_string',
+ transactionId: 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf',
+ bidRequestsCount: 4,
+ bidderRequestsCount: 3,
+ bidderWinsCount: 1,
+ bidderTimeout: 3000,
+ bidderRequestId: '1fdb5ff1b6eaa7',
+ sizes: ['300x250', '300x600'],
+ sua: {
+ 'source': 2,
+ 'platform': {
+ 'brand': 'Android',
+ 'version': ['8', '0', '0']
+ },
+ 'browsers': [
+ {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']},
+ {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']},
+ {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']}
+ ],
+ 'mobile': 1,
+ 'model': 'SM-G955U',
+ 'bitness': '64',
+ 'architecture': ''
+ },
+ url: 'https%3A%2F%2Fwww.greatsite.com',
+ referrer: 'https://www.somereferrer.com',
+ cb: 1000,
+ bidFloor: 0.1,
+ bidId: '2d52001cabd527',
+ adUnitCode: 'div-gpt-ad-12345-0',
+ publisherId: '59ac17c192832d0011283fe3',
+ uniqueDealId: `${hashUrl}_${Date.now().toString()}`,
+ bidderVersion: adapter.version,
+ prebidVersion: version,
+ schain: BID.schain,
+ res: `${window.top.screen.width}x${window.top.screen.height}`,
+ mediaTypes: [BANNER],
+ gpid: '0123456789',
+ uqs: getTopWindowQueryParams(),
+ 'ext.param1': 'loremipsum',
+ 'ext.param2': 'dolorsitamet',
+ }
+ });
+ });
+
+ after(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {};
+ sandbox.restore();
+ });
+ });
+ describe('getUserSyncs', function () {
+ it('should have valid user sync with iframeEnabled', function () {
+ const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]);
+
+ expect(result).to.deep.equal([{
+ type: 'iframe',
+ url: 'https://sync.tagoras.io/api/sync/iframe/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy='
+ }]);
+ });
+
+ it('should have valid user sync with cid on response', function () {
+ const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]);
+ expect(result).to.deep.equal([{
+ type: 'iframe',
+ url: 'https://sync.tagoras.io/api/sync/iframe/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy='
+ }]);
+ });
+
+ it('should have valid user sync with pixelEnabled', function () {
+ const result = adapter.getUserSyncs({pixelEnabled: true}, [SERVER_RESPONSE]);
+
+ expect(result).to.deep.equal([{
+ 'url': 'https://sync.tagoras.io/api/sync/image/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy=',
+ 'type': 'image'
+ }]);
+ });
+
+ it('should generate url with consent data', function () {
+ const gdprConsent = {
+ gdprApplies: true,
+ consentString: 'consent_string'
+ };
+ const uspConsent = 'usp_string';
+ const gppConsent = {
+ gppString: 'gpp_string',
+ applicableSections: [7]
+ }
+
+ const result = adapter.getUserSyncs({pixelEnabled: true}, [SERVER_RESPONSE], gdprConsent, uspConsent, gppConsent);
+
+ expect(result).to.deep.equal([{
+ 'url': 'https://sync.tagoras.io/api/sync/image/?cid=testcid123&gdpr=1&gdpr_consent=consent_string&us_privacy=usp_string&gpp=gpp_string&gpp_sid=7',
+ 'type': 'image'
+ }]);
+ });
+ });
+
+ describe('interpret response', function () {
+ it('should return empty array when there is no response', function () {
+ const responses = adapter.interpretResponse(null);
+ expect(responses).to.be.empty;
+ });
+
+ it('should return empty array when there is no ad', function () {
+ const responses = adapter.interpretResponse({price: 1, ad: ''});
+ expect(responses).to.be.empty;
+ });
+
+ it('should return empty array when there is no price', function () {
+ const responses = adapter.interpretResponse({price: null, ad: 'great ad'});
+ expect(responses).to.be.empty;
+ });
+
+ it('should return an array of interpreted banner responses', function () {
+ const responses = adapter.interpretResponse(SERVER_RESPONSE, REQUEST);
+ expect(responses).to.have.length(1);
+ expect(responses[0]).to.deep.equal({
+ requestId: '2d52001cabd527',
+ cpm: 0.8,
+ width: 300,
+ height: 250,
+ creativeId: '12610997325162499419',
+ currency: 'USD',
+ netRevenue: true,
+ ttl: 30,
+ ad: '
',
+ meta: {
+ advertiserDomains: ['securepubads.g.doubleclick.net']
+ }
+ });
+ });
+
+ it('should get meta from response metaData', function () {
+ const serverResponse = utils.deepClone(SERVER_RESPONSE);
+ serverResponse.body.results[0].metaData = {
+ advertiserDomains: ['tagoras.io'],
+ agencyName: 'Agency Name',
+ };
+ const responses = adapter.interpretResponse(serverResponse, REQUEST);
+ expect(responses[0].meta).to.deep.equal({
+ advertiserDomains: ['tagoras.io'],
+ agencyName: 'Agency Name'
+ });
+ });
+
+ it('should return an array of interpreted video responses', function () {
+ const responses = adapter.interpretResponse(VIDEO_SERVER_RESPONSE, REQUEST);
+ expect(responses).to.have.length(1);
+ expect(responses[0]).to.deep.equal({
+ requestId: '2d52001cabd527',
+ cpm: 2,
+ width: 545,
+ height: 307,
+ mediaType: 'video',
+ creativeId: '12610997325162499419',
+ currency: 'USD',
+ netRevenue: true,
+ ttl: 60,
+ vastXml: '
',
+ meta: {
+ advertiserDomains: ['tagoras.io']
+ }
+ });
+ });
+
+ it('should take default TTL', function () {
+ const serverResponse = utils.deepClone(SERVER_RESPONSE);
+ delete serverResponse.body.results[0].exp;
+ const responses = adapter.interpretResponse(serverResponse, REQUEST);
+ expect(responses).to.have.length(1);
+ expect(responses[0].ttl).to.equal(300);
+ });
+ });
+
+ describe('user id system', function () {
+ TEST_ID_SYSTEMS.forEach((idSystemProvider) => {
+ const id = Date.now().toString();
+ const bid = utils.deepClone(BID);
+
+ const userId = (function () {
+ switch (idSystemProvider) {
+ case 'lipb':
+ return {lipbid: id};
+ case 'parrableId':
+ return {eid: id};
+ case 'id5id':
+ return {uid: id};
+ default:
+ return id;
+ }
+ })();
+
+ bid.userId = {
+ [idSystemProvider]: userId
+ };
+
+ it(`should include 'uid.${idSystemProvider}' in request params`, function () {
+ const requests = adapter.buildRequests([bid], BIDDER_REQUEST);
+ expect(requests[0].data[`uid.${idSystemProvider}`]).to.equal(id);
+ });
+ });
+ });
+
+ describe('alternate param names extractors', function () {
+ it('should return undefined when param not supported', function () {
+ const cid = extractCID({'c_id': '1'});
+ const pid = extractPID({'p_id': '1'});
+ const subDomain = extractSubDomain({'sub_domain': 'prebid'});
+ expect(cid).to.be.undefined;
+ expect(pid).to.be.undefined;
+ expect(subDomain).to.be.undefined;
+ });
+
+ it('should return value when param supported', function () {
+ const cid = extractCID({'cID': '1'});
+ const pid = extractPID({'Pid': '2'});
+ const subDomain = extractSubDomain({'subDOMAIN': 'prebid'});
+ expect(cid).to.be.equal('1');
+ expect(pid).to.be.equal('2');
+ expect(subDomain).to.be.equal('prebid');
+ });
+ });
+
+ describe('unique deal id', function () {
+ before(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {
+ tagoras: {
+ storageAllowed: true
+ }
+ };
+ });
+ after(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {};
+ });
+ const key = 'myKey';
+ let uniqueDealId;
+ beforeEach(() => {
+ uniqueDealId = getUniqueDealId(key, 0);
+ })
+
+ it('should get current unique deal id', function (done) {
+ // waiting some time so `now` will become past
+ setTimeout(() => {
+ const current = getUniqueDealId(key);
+ expect(current).to.be.equal(uniqueDealId);
+ done();
+ }, 200);
+ });
+
+ it('should get new unique deal id on expiration', function (done) {
+ setTimeout(() => {
+ const current = getUniqueDealId(key, 100);
+ expect(current).to.not.be.equal(uniqueDealId);
+ done();
+ }, 200)
+ });
+ });
+
+ describe('storage utils', function () {
+ before(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {
+ tagoras: {
+ storageAllowed: true
+ }
+ };
+ });
+ after(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {};
+ });
+ it('should get value from storage with create param', function () {
+ const now = Date.now();
+ const clock = useFakeTimers({
+ shouldAdvanceTime: true,
+ now
+ });
+ setStorageItem('myKey', 2020);
+ const {value, created} = getStorageItem('myKey');
+ expect(created).to.be.equal(now);
+ expect(value).to.be.equal(2020);
+ expect(typeof value).to.be.equal('number');
+ expect(typeof created).to.be.equal('number');
+ clock.restore();
+ });
+
+ it('should get external stored value', function () {
+ const value = 'superman'
+ window.localStorage.setItem('myExternalKey', value);
+ const item = getStorageItem('myExternalKey');
+ expect(item).to.be.equal(value);
+ });
+
+ it('should parse JSON value', function () {
+ const data = JSON.stringify({event: 'send'});
+ const {event} = tryParseJSON(data);
+ expect(event).to.be.equal('send');
+ });
+
+ it('should get original value on parse fail', function () {
+ const value = 21;
+ const parsed = tryParseJSON(value);
+ expect(typeof parsed).to.be.equal('number');
+ expect(parsed).to.be.equal(value);
+ });
+ });
+});
diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js
index b0d5f436e0b..f26081b0cef 100644
--- a/test/spec/modules/teadsBidAdapter_spec.js
+++ b/test/spec/modules/teadsBidAdapter_spec.js
@@ -1,6 +1,7 @@
import {expect} from 'chai';
import {spec, storage} from 'modules/teadsBidAdapter.js';
import {newBidder} from 'src/adapters/bidderFactory.js';
+import { off } from '../../../src/events';
const ENDPOINT = 'https://a.teads.tv/hb/bid-request';
const AD_SCRIPT = '"';
@@ -254,6 +255,63 @@ describe('teadsBidAdapter', () => {
expect(payload.pageReferrer).to.deep.equal(document.referrer);
});
+ it('should add screenOrientation info to payload', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+ const screenOrientation = window.top.screen.orientation?.type
+
+ if (screenOrientation) {
+ expect(payload.screenOrientation).to.exist;
+ expect(payload.screenOrientation).to.deep.equal(screenOrientation);
+ } else expect(payload.screenOrientation).to.not.exist;
+ });
+
+ it('should add historyLength info to payload', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.historyLength).to.exist;
+ expect(payload.historyLength).to.deep.equal(window.top.history.length);
+ });
+
+ it('should add viewportHeight info to payload', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.viewportHeight).to.exist;
+ expect(payload.viewportHeight).to.deep.equal(window.top.visualViewport.height);
+ });
+
+ it('should add viewportWidth info to payload', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.viewportWidth).to.exist;
+ expect(payload.viewportWidth).to.deep.equal(window.top.visualViewport.width);
+ });
+
+ it('should add hardwareConcurrency info to payload', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+ const hardwareConcurrency = window.top.navigator?.hardwareConcurrency
+
+ if (hardwareConcurrency) {
+ expect(payload.hardwareConcurrency).to.exist;
+ expect(payload.hardwareConcurrency).to.deep.equal(hardwareConcurrency);
+ } else expect(payload.hardwareConcurrency).to.not.exist
+ });
+
+ it('should add deviceMemory info to payload', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+ const deviceMemory = window.top.navigator.deviceMemory
+
+ if (deviceMemory) {
+ expect(payload.deviceMemory).to.exist;
+ expect(payload.deviceMemory).to.deep.equal(deviceMemory);
+ } else expect(payload.deviceMemory).to.not.exist;
+ });
+
describe('pageTitle', function () {
it('should add pageTitle info to payload based on document title', function () {
const testText = 'This is a title';
@@ -947,6 +1005,45 @@ describe('teadsBidAdapter', () => {
}
});
}
+
+ it('should add dsa info to payload if available', function () {
+ const bidRequestWithDsa = Object.assign({}, bidderRequestDefault, {
+ ortb2: {
+ regs: {
+ ext: {
+ dsa: {
+ dsarequired: '1',
+ pubrender: '2',
+ datatopub: '3',
+ transparency: [{
+ domain: 'test.com',
+ dsaparams: [1, 2, 3]
+ }]
+ }
+ }
+ }
+ }
+ });
+
+ const requestWithDsa = spec.buildRequests(bidRequests, bidRequestWithDsa);
+ const payload = JSON.parse(requestWithDsa.data);
+
+ expect(payload.dsa).to.exist;
+ expect(payload.dsa).to.deep.equal(
+ {
+ dsarequired: '1',
+ pubrender: '2',
+ datatopub: '3',
+ transparency: [{
+ domain: 'test.com',
+ dsaparams: [1, 2, 3]
+ }]
+ }
+ );
+
+ const defaultRequest = spec.buildRequests(bidRequests, bidderRequestDefault);
+ expect(JSON.parse(defaultRequest.data).dsa).to.not.exist;
+ });
});
describe('interpretResponse', function() {
@@ -973,7 +1070,18 @@ describe('teadsBidAdapter', () => {
'width': 350,
'creativeId': 'fs3ff',
'placementId': 34,
- 'dealId': 'ABC_123'
+ 'dealId': 'ABC_123',
+ 'ext': {
+ 'dsa': {
+ 'behalf': 'some-behalf',
+ 'paid': 'some-paid',
+ 'transparency': [{
+ 'domain': 'test.com',
+ 'dsaparams': [1, 2, 3]
+ }],
+ 'adrender': 1
+ }
+ }
}]
}
};
@@ -999,7 +1107,16 @@ describe('teadsBidAdapter', () => {
'currency': 'USD',
'netRevenue': true,
'meta': {
- advertiserDomains: []
+ advertiserDomains: [],
+ dsa: {
+ behalf: 'some-behalf',
+ paid: 'some-paid',
+ transparency: [{
+ domain: 'test.com',
+ dsaparams: [1, 2, 3]
+ }],
+ adrender: 1
+ }
},
'ttl': 360,
'ad': AD_SCRIPT,
diff --git a/test/spec/modules/theAdxBidAdapter_spec.js b/test/spec/modules/theAdxBidAdapter_spec.js
index 99e5156190c..eb00834421a 100644
--- a/test/spec/modules/theAdxBidAdapter_spec.js
+++ b/test/spec/modules/theAdxBidAdapter_spec.js
@@ -446,6 +446,78 @@ describe('TheAdxAdapter', function () {
expect(processedBid.currency).to.equal(responseCurrency);
});
+ it('returns a valid deal bid response on sucessful banner request with deal', function () {
+ let incomingRequestId = 'XXtestingXX';
+ let responsePrice = 3.14
+
+ let responseCreative = 'sample_creative&{FOR_COVARAGE}';
+
+ let responseCreativeId = '274';
+ let responseCurrency = 'TRY';
+
+ let responseWidth = 300;
+ let responseHeight = 250;
+ let responseTtl = 213;
+ let dealId = 'theadx_deal_id';
+
+ let sampleResponse = {
+ id: '66043f5ca44ecd8f8769093b1615b2d9',
+ seatbid: [{
+ bid: [{
+ id: 'c21bab0e-7668-4d8f-908a-63e094c09197',
+ dealid: 'theadx_deal_id',
+ impid: '1',
+ price: responsePrice,
+ adid: responseCreativeId,
+ crid: responseCreativeId,
+ adm: responseCreative,
+ adomain: [
+ 'www.domain.com'
+ ],
+ cid: '274',
+ attr: [],
+ w: responseWidth,
+ h: responseHeight,
+ ext: {
+ ttl: responseTtl
+ }
+ }],
+ seat: '201',
+ group: 0
+ }],
+ bidid: 'c21bab0e-7668-4d8f-908a-63e094c09197',
+ cur: responseCurrency
+ };
+
+ let sampleRequest = {
+ bidId: incomingRequestId,
+ mediaTypes: {
+ banner: {}
+ },
+ requestId: incomingRequestId,
+ deals: [{id: dealId}]
+ };
+ let serverResponse = {
+ body: sampleResponse
+ }
+ let result = spec.interpretResponse(serverResponse, sampleRequest);
+
+ expect(result.length).to.equal(1);
+
+ let processedBid = result[0];
+
+ // expect(processedBid.requestId).to.equal(incomingRequestId);
+ expect(processedBid.cpm).to.equal(responsePrice);
+ expect(processedBid.width).to.equal(responseWidth);
+ expect(processedBid.height).to.equal(responseHeight);
+ expect(processedBid.ad).to.equal(responseCreative);
+ expect(processedBid.ttl).to.equal(responseTtl);
+ expect(processedBid.creativeId).to.equal(responseCreativeId);
+ expect(processedBid.netRevenue).to.equal(true);
+ expect(processedBid.currency).to.equal(responseCurrency);
+ expect(processedBid.dealId).to.equal(dealId);
+ });
+
it('returns an valid bid response on sucessful video request', function () {
let incomingRequestId = 'XXtesting-275XX';
let responsePrice = 6
diff --git a/test/spec/modules/topicsFpdModule_spec.js b/test/spec/modules/topicsFpdModule_spec.js
index bc7df85db0d..4a79e7f77fd 100644
--- a/test/spec/modules/topicsFpdModule_spec.js
+++ b/test/spec/modules/topicsFpdModule_spec.js
@@ -384,6 +384,22 @@ describe('topics', () => {
});
describe('cross-frame messages', () => {
+ before(() => {
+ config.setConfig({
+ userSync: {
+ topics: {
+ maxTopicCaller: 3,
+ bidders: [
+ {
+ bidder: 'pubmatic',
+ iframeURL: 'https://ads.pubmatic.com/AdServer/js/topics/topics_frame.html'
+ }
+ ],
+ },
+ }
+ });
+ });
+
beforeEach(() => {
// init iframe logic so that the receiveMessage origin check passes
loadTopicsForBidders({
@@ -398,6 +414,10 @@ describe('topics', () => {
});
});
+ after(() => {
+ config.resetConfig();
+ })
+
it('should store segments if receiveMessage event is triggered with segment data', () => {
receiveMessage(evt);
let segments = new Map(safeJSONParse(storage.getDataFromLocalStorage(topicStorageName)));
@@ -421,11 +441,13 @@ describe('handles fetch request for topics api headers', () => {
beforeEach(() => {
stubbedFetch = sinon.stub(window, 'fetch');
+ reset();
});
afterEach(() => {
stubbedFetch.restore();
storage.removeDataFromLocalStorage(topicStorageName);
+ config.resetConfig();
});
it('should make a fetch call when a fetchUrl is present for a selected bidder', () => {
@@ -444,6 +466,7 @@ describe('handles fetch request for topics api headers', () => {
});
stubbedFetch.returns(Promise.resolve(true));
+
loadTopicsForBidders({
browsingTopics: true,
featurePolicy: {
diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js
index 9bec7229450..998e0db6fe8 100644
--- a/test/spec/modules/ucfunnelBidAdapter_spec.js
+++ b/test/spec/modules/ucfunnelBidAdapter_spec.js
@@ -30,7 +30,7 @@ const validBannerBidReq = {
params: {
adid: 'ad-34BBD2AA24B678BBFD4E7B9EE3B872D'
},
- sizes: [[300, 250]],
+ sizes: [[300, 250], [336, 280]],
bidId: '263be71e91dd9d',
auctionId: '9ad1fa8d-2297-4660-a018-b39945054746',
ortb2Imp: {
@@ -180,15 +180,15 @@ describe('ucfunnel Adapter', function () {
expect(data.schain).to.equal('1.0,1!exchange1.com,1234,1,bid-request-1,publisher,publisher.com');
});
- it('must parse bid size from a nested array', function () {
- const width = 640;
- const height = 480;
- const bid = deepClone(validBannerBidReq);
- bid.sizes = [[ width, height ]];
- const requests = spec.buildRequests([ bid ], bidderRequest);
+ it('should support multiple size', function () {
+ const sizes = [[300, 250], [336, 280]];
+ const format = '300,250;336,280';
+ validBannerBidReq.sizes = sizes;
+ const requests = spec.buildRequests([ validBannerBidReq ], bidderRequest);
const data = requests[0].data;
- expect(data.w).to.equal(width);
- expect(data.h).to.equal(height);
+ expect(data.w).to.equal(sizes[0][0]);
+ expect(data.h).to.equal(sizes[0][1]);
+ expect(data.format).to.equal(format);
});
it('should set bidfloor if configured', function() {
diff --git a/test/spec/modules/uid2IdSystem_spec.js b/test/spec/modules/uid2IdSystem_spec.js
index 8e3728704c7..901e0c57e32 100644
--- a/test/spec/modules/uid2IdSystem_spec.js
+++ b/test/spec/modules/uid2IdSystem_spec.js
@@ -476,37 +476,33 @@ describe(`UID2 module`, function () {
})
describe('When the storedToken is expired and can be refreshed ', function() {
- it('it should calls refresh API', function() {
- testApiSuccessAndFailure(async function(apiSucceeds) {
- const refreshedIdentity = apiHelpers.makeTokenResponse(refreshedToken, true, true);
- const moduleCookie = {originalIdentity: makeOriginalIdentity('test@test.com'), latestToken: refreshedIdentity};
- coreStorage.setCookie(moduleCookieName, JSON.stringify(moduleCookie), cookieHelpers.getFutureCookieExpiry());
- config.setConfig(makePrebidConfig({ ...cstgConfigParams, email: 'test@test.com' }));
- apiHelpers.respondAfterDelay(auctionDelayMs / 10, server);
+ testApiSuccessAndFailure(async function(apiSucceeds) {
+ const refreshedIdentity = apiHelpers.makeTokenResponse(refreshedToken, true, true);
+ const moduleCookie = {originalIdentity: makeOriginalIdentity('test@test.com'), latestToken: refreshedIdentity};
+ coreStorage.setCookie(moduleCookieName, JSON.stringify(moduleCookie), cookieHelpers.getFutureCookieExpiry());
+ config.setConfig(makePrebidConfig({ ...cstgConfigParams, email: 'test@test.com' }));
+ apiHelpers.respondAfterDelay(auctionDelayMs / 10, server);
- const bid = await runAuction();
+ const bid = await runAuction();
- if (apiSucceeds) expectToken(bid, refreshedToken);
- else expectNoIdentity(bid);
- }, refreshApiUrl, 'it should use refreshed token in the auction', 'the auction should have no uid2');
- });
+ if (apiSucceeds) expectToken(bid, refreshedToken);
+ else expectNoIdentity(bid);
+ }, refreshApiUrl, 'it should use refreshed token in the auction', 'the auction should have no uid2');
})
describe('When the storedToken is expired for refresh', function() {
- it('it should calls CSTG API and not use the stored token', function() {
- testApiSuccessAndFailure(async function(apiSucceeds) {
- const refreshedIdentity = apiHelpers.makeTokenResponse(refreshedToken, true, true, true);
- const moduleCookie = {originalIdentity: makeOriginalIdentity('test@test.com'), latestToken: refreshedIdentity};
- coreStorage.setCookie(moduleCookieName, JSON.stringify(moduleCookie), cookieHelpers.getFutureCookieExpiry());
- config.setConfig(makePrebidConfig({ ...cstgConfigParams, email: 'test@test.com' }));
- apiHelpers.respondAfterDelay(auctionDelayMs / 10, server);
+ testApiSuccessAndFailure(async function(apiSucceeds) {
+ const refreshedIdentity = apiHelpers.makeTokenResponse(refreshedToken, true, true, true);
+ const moduleCookie = {originalIdentity: makeOriginalIdentity('test@test.com'), latestToken: refreshedIdentity};
+ coreStorage.setCookie(moduleCookieName, JSON.stringify(moduleCookie), cookieHelpers.getFutureCookieExpiry());
+ config.setConfig(makePrebidConfig({ ...cstgConfigParams, email: 'test@test.com' }));
+ apiHelpers.respondAfterDelay(auctionDelayMs / 10, server);
- const bid = await runAuction();
+ const bid = await runAuction();
- if (apiSucceeds) expectToken(bid, clientSideGeneratedToken);
- else expectNoIdentity(bid);
- }, cstgApiUrl, 'it should use generated token in the auction', 'the auction should have no uid2', false, clientSideGeneratedToken);
- });
+ if (apiSucceeds) expectToken(bid, clientSideGeneratedToken);
+ else expectNoIdentity(bid);
+ }, cstgApiUrl, 'it should use generated token in the auction', 'the auction should have no uid2', false, clientSideGeneratedToken);
})
})
diff --git a/test/spec/modules/unicornBidAdapter_spec.js b/test/spec/modules/unicornBidAdapter_spec.js
index 0abb09bfb78..bd9175dac1e 100644
--- a/test/spec/modules/unicornBidAdapter_spec.js
+++ b/test/spec/modules/unicornBidAdapter_spec.js
@@ -1,4 +1,5 @@
import {assert, expect} from 'chai';
+import * as utils from 'src/utils.js';
import {spec} from 'modules/unicornBidAdapter.js';
import * as _ from 'lodash';
@@ -496,6 +497,17 @@ describe('unicornBidAdapterTest', () => {
});
describe('buildBidRequest', () => {
+ const removeUntestableAttrs = data => {
+ delete data['device'];
+ delete data['site']['domain'];
+ delete data['site']['page'];
+ delete data['id'];
+ data['imp'].forEach(imp => {
+ delete imp['id'];
+ })
+ delete data['user']['id'];
+ return data;
+ };
before(function () {
$$PREBID_GLOBAL$$.bidderSettings = {
unicorn: {
@@ -508,17 +520,6 @@ describe('unicornBidAdapterTest', () => {
});
it('buildBidRequest', () => {
const req = spec.buildRequests(validBidRequests, bidderRequest);
- const removeUntestableAttrs = data => {
- delete data['device'];
- delete data['site']['domain'];
- delete data['site']['page'];
- delete data['id'];
- data['imp'].forEach(imp => {
- delete imp['id'];
- })
- delete data['user']['id'];
- return data;
- };
const uid = JSON.parse(req.data)['user']['id'];
const reqData = removeUntestableAttrs(JSON.parse(req.data));
const openRTBRequestData = removeUntestableAttrs(openRTBRequest);
@@ -527,6 +528,28 @@ describe('unicornBidAdapterTest', () => {
const uid2 = JSON.parse(req2.data)['user']['id'];
assert.deepStrictEqual(uid, uid2);
});
+ it('test if contains ID5', () => {
+ let _validBidRequests = utils.deepClone(validBidRequests);
+ _validBidRequests[0].userId = {
+ id5id: {
+ uid: 'id5_XXXXX'
+ }
+ }
+ const req = spec.buildRequests(_validBidRequests, bidderRequest);
+ const reqData = removeUntestableAttrs(JSON.parse(req.data));
+ const openRTBRequestData = removeUntestableAttrs(utils.deepClone(openRTBRequest));
+ openRTBRequestData.user.eids = [
+ {
+ source: 'id5-sync.com',
+ uids: [
+ {
+ id: 'id5_XXXXX'
+ }
+ ]
+ }
+ ]
+ assert.deepStrictEqual(reqData, openRTBRequestData);
+ })
});
describe('interpretResponse', () => {
diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js
index 6d1d8f9949f..abf1a54787d 100644
--- a/test/spec/modules/unrulyBidAdapter_spec.js
+++ b/test/spec/modules/unrulyBidAdapter_spec.js
@@ -42,9 +42,40 @@ describe('UnrulyAdapter', function () {
}
}
- const createExchangeResponse = (...bids) => ({
- body: {bids}
- });
+ function createOutStreamExchangeAuctionConfig() {
+ return {
+ 'seller': 'https://nexxen.tech',
+ 'decisionLogicURL': 'https://nexxen.tech/padecisionlogic',
+ 'interestGroupBuyers': 'https://mydsp.com',
+ 'perBuyerSignals': {
+ 'https://mydsp.com': {
+ 'floor': 'bouttreefiddy'
+ }
+ }
+ }
+ };
+
+ function createExchangeResponse (bidList, auctionConfigs = null) {
+ let bids = [];
+ if (Array.isArray(bidList)) {
+ bids = bidList;
+ } else if (bidList) {
+ bids.push(bidList);
+ }
+
+ if (!auctionConfigs) {
+ return {
+ 'body': {bids}
+ };
+ }
+
+ return {
+ 'body': {
+ bids,
+ auctionConfigs
+ }
+ }
+ };
const inStreamServerResponse = {
'requestId': '262594d5d1f8104',
@@ -486,7 +517,8 @@ describe('UnrulyAdapter', function () {
'bidderRequestId': '12e00d17dff07b'
}
],
- 'invalidBidsCount': 0
+ 'invalidBidsCount': 0,
+ 'prebidVersion': '$prebid.version$'
}
};
@@ -560,7 +592,8 @@ describe('UnrulyAdapter', function () {
'bidderRequestId': '12e00d17dff07b',
}
],
- 'invalidBidsCount': 0
+ 'invalidBidsCount': 0,
+ 'prebidVersion': '$prebid.version$'
}
};
@@ -651,13 +684,235 @@ describe('UnrulyAdapter', function () {
'bidderRequestId': '12e00d17dff07b',
}
],
- 'invalidBidsCount': 0
+ 'invalidBidsCount': 0,
+ 'prebidVersion': '$prebid.version$'
}
};
let result = adapter.buildRequests(mockBidRequests.bids, mockBidRequests);
expect(result[0].data).to.deep.equal(expectedResult);
});
+ describe('Protected Audience Support', function() {
+ it('should return an array with 2 items and enabled protected audience', function () {
+ mockBidRequests = {
+ 'bidderCode': 'unruly',
+ 'fledgeEnabled': true,
+ 'bids': [
+ {
+ 'bidder': 'unruly',
+ 'params': {
+ 'siteId': 233261,
+ },
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'outstream',
+ 'mimes': [
+ 'video/mp4'
+ ],
+ 'playerSize': [
+ [
+ 640,
+ 480
+ ]
+ ]
+ }
+ },
+ 'adUnitCode': 'video2',
+ 'transactionId': 'a89619e3-137d-4cc5-9ed4-58a0b2a0bbc2',
+ 'sizes': [
+ [
+ 640,
+ 480
+ ]
+ ],
+ 'bidId': '27a3ee1626a5c7',
+ 'bidderRequestId': '12e00d17dff07b',
+ 'ortb2Imp': {
+ 'ext': {
+ 'ae': 1
+ }
+ }
+ },
+ {
+ 'bidder': 'unruly',
+ 'params': {
+ 'siteId': 2234554,
+ },
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'outstream',
+ 'mimes': [
+ 'video/mp4'
+ ],
+ 'playerSize': [
+ [
+ 640,
+ 480
+ ]
+ ]
+ }
+ },
+ 'adUnitCode': 'video2',
+ 'transactionId': 'a89619e3-137d-4cc5-9ed4-58a0b2a0bbc2',
+ 'sizes': [
+ [
+ 640,
+ 480
+ ]
+ ],
+ 'bidId': '27a3ee1626a5c7',
+ 'bidderRequestId': '12e00d17dff07b',
+ 'ortb2Imp': {
+ 'ext': {
+ 'ae': 1
+ }
+ }
+ }
+ ]
+ };
+
+ let result = adapter.buildRequests(mockBidRequests.bids, mockBidRequests);
+ expect(typeof result).to.equal('object');
+ expect(result.length).to.equal(2);
+ expect(result[0].data.bidderRequest.bids.length).to.equal(1);
+ expect(result[1].data.bidderRequest.bids.length).to.equal(1);
+ expect(result[0].data.bidderRequest.bids[0].ortb2Imp.ext.ae).to.equal(1);
+ expect(result[1].data.bidderRequest.bids[0].ortb2Imp.ext.ae).to.equal(1);
+ });
+ it('should return an array with 2 items and enabled protected audience on only one unit', function () {
+ mockBidRequests = {
+ 'bidderCode': 'unruly',
+ 'fledgeEnabled': true,
+ 'bids': [
+ {
+ 'bidder': 'unruly',
+ 'params': {
+ 'siteId': 233261,
+ },
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'outstream',
+ 'mimes': [
+ 'video/mp4'
+ ],
+ 'playerSize': [
+ [
+ 640,
+ 480
+ ]
+ ]
+ }
+ },
+ 'adUnitCode': 'video2',
+ 'transactionId': 'a89619e3-137d-4cc5-9ed4-58a0b2a0bbc2',
+ 'sizes': [
+ [
+ 640,
+ 480
+ ]
+ ],
+ 'bidId': '27a3ee1626a5c7',
+ 'bidderRequestId': '12e00d17dff07b',
+ 'ortb2Imp': {
+ 'ext': {
+ 'ae': 1
+ }
+ }
+ },
+ {
+ 'bidder': 'unruly',
+ 'params': {
+ 'siteId': 2234554,
+ },
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'outstream',
+ 'mimes': [
+ 'video/mp4'
+ ],
+ 'playerSize': [
+ [
+ 640,
+ 480
+ ]
+ ]
+ }
+ },
+ 'adUnitCode': 'video2',
+ 'transactionId': 'a89619e3-137d-4cc5-9ed4-58a0b2a0bbc2',
+ 'sizes': [
+ [
+ 640,
+ 480
+ ]
+ ],
+ 'bidId': '27a3ee1626a5c7',
+ 'bidderRequestId': '12e00d17dff07b',
+ 'ortb2Imp': {
+ 'ext': {}
+ }
+ }
+ ]
+ };
+
+ let result = adapter.buildRequests(mockBidRequests.bids, mockBidRequests);
+ expect(typeof result).to.equal('object');
+ expect(result.length).to.equal(2);
+ expect(result[0].data.bidderRequest.bids.length).to.equal(1);
+ expect(result[1].data.bidderRequest.bids.length).to.equal(1);
+ expect(result[0].data.bidderRequest.bids[0].ortb2Imp.ext.ae).to.equal(1);
+ expect(result[1].data.bidderRequest.bids[0].ortb2Imp.ext.ae).to.be.undefined;
+ });
+ it('disables configured protected audience when fledge is not availble', function () {
+ mockBidRequests = {
+ 'bidderCode': 'unruly',
+ 'fledgeEnabled': false,
+ 'bids': [
+ {
+ 'bidder': 'unruly',
+ 'params': {
+ 'siteId': 233261,
+ },
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'outstream',
+ 'mimes': [
+ 'video/mp4'
+ ],
+ 'playerSize': [
+ [
+ 640,
+ 480
+ ]
+ ]
+ }
+ },
+ 'adUnitCode': 'video2',
+ 'transactionId': 'a89619e3-137d-4cc5-9ed4-58a0b2a0bbc2',
+ 'sizes': [
+ [
+ 640,
+ 480
+ ]
+ ],
+ 'bidId': '27a3ee1626a5c7',
+ 'bidderRequestId': '12e00d17dff07b',
+ 'ortb2Imp': {
+ 'ext': {
+ 'ae': 1
+ }
+ }
+ }
+ ]
+ };
+
+ let result = adapter.buildRequests(mockBidRequests.bids, mockBidRequests);
+ expect(typeof result).to.equal('object');
+ expect(result.length).to.equal(1);
+ expect(result[0].data.bidderRequest.bids.length).to.equal(1);
+ expect(result[0].data.bidderRequest.bids[0].ortb2Imp.ext.ae).to.be.undefined;
+ });
+ });
});
describe('interpretResponse', function () {
@@ -705,7 +960,167 @@ describe('UnrulyAdapter', function () {
renderer: fakeRenderer,
mediaType: 'video'
}
- ])
+ ]);
+ });
+
+ it('should return object with an array of bids and an array of auction configs when it receives a successful response from server', function () {
+ let bidId = '27a3ee1626a5c7'
+ const mockExchangeBid = createOutStreamExchangeBid({adUnitCode: 'video1', requestId: 'mockBidId'});
+ const mockExchangeAuctionConfig = {};
+ mockExchangeAuctionConfig[bidId] = createOutStreamExchangeAuctionConfig();
+ const mockServerResponse = createExchangeResponse(mockExchangeBid, mockExchangeAuctionConfig);
+ const originalRequest = {
+ 'data': {
+ 'bidderRequest': {
+ 'bids': [
+ {
+ 'bidder': 'unruly',
+ 'params': {
+ 'siteId': 233261,
+ },
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [
+ [
+ 640,
+ 480
+ ],
+ [
+ 640,
+ 480
+ ],
+ [
+ 300,
+ 250
+ ],
+ [
+ 300,
+ 250
+ ]
+ ]
+ }
+ },
+ 'adUnitCode': 'video2',
+ 'transactionId': 'a89619e3-137d-4cc5-9ed4-58a0b2a0bbc2',
+ 'bidId': bidId,
+ 'bidderRequestId': '12e00d17dff07b',
+ }
+ ]
+ }
+ }
+ };
+
+ expect(adapter.interpretResponse(mockServerResponse, originalRequest)).to.deep.equal({
+ 'bids': [
+ {
+ 'ext': {
+ 'statusCode': 1,
+ 'renderer': {
+ 'id': 'unruly_inarticle',
+ 'config': {
+ 'siteId': 123456,
+ 'targetingUUID': 'xxx-yyy-zzz'
+ },
+ 'url': 'https://video.unrulymedia.com/native/prebid-loader.js'
+ },
+ 'adUnitCode': 'video1'
+ },
+ requestId: 'mockBidId',
+ bidderCode: 'unruly',
+ cpm: 20,
+ width: 323,
+ height: 323,
+ vastUrl: 'https://targeting.unrulymedia.com/in_article?uuid=74544e00-d43b-4f3a-a799-69d22ce979ce&supported_mime_type=application/javascript&supported_mime_type=video/mp4&tj=%7B%22site%22%3A%7B%22lang%22%3A%22en-GB%22%2C%22ref%22%3A%22%22%2C%22page%22%3A%22https%3A%2F%2Fdemo.unrulymedia.com%2FinArticle%2Finarticle_nypost_upbeat%2Ftravel_magazines.html%22%2C%22domain%22%3A%22demo.unrulymedia.com%22%7D%2C%22user%22%3A%7B%22profile%22%3A%7B%22quantcast%22%3A%7B%22segments%22%3A%5B%7B%22id%22%3A%22D%22%7D%2C%7B%22id%22%3A%22T%22%7D%5D%7D%7D%7D%7D&video_width=618&video_height=347',
+ netRevenue: true,
+ creativeId: 'mockBidId',
+ ttl: 360,
+ 'meta': {
+ 'mediaType': 'video',
+ 'videoContext': 'outstream'
+ },
+ currency: 'USD',
+ renderer: fakeRenderer,
+ mediaType: 'video'
+ }
+ ],
+ 'fledgeAuctionConfigs': [{
+ 'bidId': bidId,
+ 'config': {
+ 'seller': 'https://nexxen.tech',
+ 'decisionLogicURL': 'https://nexxen.tech/padecisionlogic',
+ 'interestGroupBuyers': 'https://mydsp.com',
+ 'perBuyerSignals': {
+ 'https://mydsp.com': {
+ 'floor': 'bouttreefiddy'
+ }
+ }
+ }
+ }]
+ });
+ });
+
+ it('should return object with an array of auction configs when it receives a successful response from server without bids', function () {
+ let bidId = '27a3ee1626a5c7';
+ const mockExchangeAuctionConfig = {};
+ mockExchangeAuctionConfig[bidId] = createOutStreamExchangeAuctionConfig();
+ const mockServerResponse = createExchangeResponse(null, mockExchangeAuctionConfig);
+ const originalRequest = {
+ 'data': {
+ 'bidderRequest': {
+ 'bids': [
+ {
+ 'bidder': 'unruly',
+ 'params': {
+ 'siteId': 233261,
+ },
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [
+ [
+ 640,
+ 480
+ ],
+ [
+ 640,
+ 480
+ ],
+ [
+ 300,
+ 250
+ ],
+ [
+ 300,
+ 250
+ ]
+ ]
+ }
+ },
+ 'adUnitCode': 'video2',
+ 'transactionId': 'a89619e3-137d-4cc5-9ed4-58a0b2a0bbc2',
+ 'bidId': bidId,
+ 'bidderRequestId': '12e00d17dff07b'
+ }
+ ]
+ }
+ }
+ };
+
+ expect(adapter.interpretResponse(mockServerResponse, originalRequest)).to.deep.equal({
+ 'bids': [],
+ 'fledgeAuctionConfigs': [{
+ 'bidId': bidId,
+ 'config': {
+ 'seller': 'https://nexxen.tech',
+ 'decisionLogicURL': 'https://nexxen.tech/padecisionlogic',
+ 'interestGroupBuyers': 'https://mydsp.com',
+ 'perBuyerSignals': {
+ 'https://mydsp.com': {
+ 'floor': 'bouttreefiddy'
+ }
+ }
+ }
+ }]
+ });
});
it('should initialize and set the renderer', function () {
@@ -875,7 +1290,7 @@ describe('UnrulyAdapter', function () {
it('should return correct response for multiple bids', function () {
const outStreamServerResponse = createOutStreamExchangeBid({adUnitCode: 'video1', requestId: 'mockBidId'});
- const mockServerResponse = createExchangeResponse(outStreamServerResponse, inStreamServerResponse, bannerServerResponse);
+ const mockServerResponse = createExchangeResponse([outStreamServerResponse, inStreamServerResponse, bannerServerResponse]);
const expectedOutStreamResponse = outStreamServerResponse;
expectedOutStreamResponse.mediaType = 'video';
@@ -890,7 +1305,7 @@ describe('UnrulyAdapter', function () {
it('should return only valid bids', function () {
const {ad, ...bannerServerResponseNoAd} = bannerServerResponse;
- const mockServerResponse = createExchangeResponse(bannerServerResponseNoAd, inStreamServerResponse);
+ const mockServerResponse = createExchangeResponse([bannerServerResponseNoAd, inStreamServerResponse]);
const expectedInStreamResponse = inStreamServerResponse;
expectedInStreamResponse.mediaType = 'video';
diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js
index 17a865796a2..18f49f4943e 100644
--- a/test/spec/modules/userId_spec.js
+++ b/test/spec/modules/userId_spec.js
@@ -448,7 +448,25 @@ describe('User ID', function () {
]
}
])
- })
+ });
+
+ it('when merging with pubCommonId, should not alter its eids', () => {
+ const uid = {
+ pubProvidedId: [
+ {
+ source: 'mock1Source',
+ uids: [
+ {id: 'uid2'}
+ ]
+ }
+ ],
+ mockId1: 'uid1',
+ };
+ const eids = createEidsArray(uid);
+ expect(eids).to.have.length(1);
+ expect(eids[0].uids.map(u => u.id)).to.have.members(['uid1', 'uid2']);
+ expect(uid.pubProvidedId[0].uids).to.eql([{id: 'uid2'}]);
+ });
})
it('pbjs.getUserIds', function (done) {
diff --git a/test/spec/modules/viantOrtbBidAdapter_spec.js b/test/spec/modules/viantOrtbBidAdapter_spec.js
index ef537d50986..73fdb7f3dc8 100644
--- a/test/spec/modules/viantOrtbBidAdapter_spec.js
+++ b/test/spec/modules/viantOrtbBidAdapter_spec.js
@@ -109,6 +109,49 @@ describe('viantOrtbBidAdapter', function () {
});
});
});
+
+ describe('native', function () {
+ describe('and request config uses mediaTypes', () => {
+ function makeBid() {
+ return {
+ 'bidder': 'viant',
+ 'params': {
+ 'unit': '12345678',
+ 'delDomain': 'test-del-domain',
+ 'publisherId': '464',
+ 'placementId': 'some-PlacementId_2'
+ },
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'instream',
+ 'playerSize': [[640, 480]],
+ 'mimes': ['video/mp4'],
+ 'protocols': [1, 2, 3, 4, 5, 6, 7, 8],
+ 'api': [1, 3],
+ 'skip': 1,
+ 'skipafter': 5,
+ 'minduration': 10,
+ 'maxduration': 30
+ }
+ },
+ 'adUnitCode': 'adunit-code',
+ 'bidId': '30b31c1838de1e',
+ 'bidderRequestId': '22edbae2733bf6',
+ 'auctionId': '1d1a030790a475',
+ 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e'
+ }
+ }
+ it('should return true when required params found', function () {
+ expect(spec.isBidRequestValid(makeBid())).to.equal(true);
+ });
+
+ it('should return false when required params are not passed', function () {
+ let nativeBidWithMediaTypes = Object.assign({}, makeBid());
+ nativeBidWithMediaTypes.params = {};
+ expect(spec.isBidRequestValid(nativeBidWithMediaTypes)).to.equal(false);
+ });
+ });
+ });
});
describe('buildRequests-banner', function () {
@@ -172,7 +215,7 @@ describe('viantOrtbBidAdapter', function () {
});
it('sends bid requests to the correct endpoint', function () {
const url = testBuildRequests(baseBannerBidRequests, baseBidderRequest)[0].url;
- expect(url).to.equal('https://bidders-us-east-1.adelphic.net/d/rtb/v25/prebid/bidder_test');
+ expect(url).to.equal('https://bidders-us-east-1.adelphic.net/d/rtb/v25/prebid/bidder');
});
it('sends site', function () {
diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js
index 864f2b8551c..bc5165c8d54 100644
--- a/test/spec/modules/vidazooBidAdapter_spec.js
+++ b/test/spec/modules/vidazooBidAdapter_spec.js
@@ -648,6 +648,14 @@ describe('VidazooBidAdapter', function () {
expect(responses).to.have.length(1);
expect(responses[0].ttl).to.equal(300);
});
+
+ it('should add nurl if exists on response', function () {
+ const serverResponse = utils.deepClone(SERVER_RESPONSE);
+ serverResponse.body.results[0].nurl = 'https://test.com/win-notice?test=123';
+ const responses = adapter.interpretResponse(serverResponse, REQUEST);
+ expect(responses).to.have.length(1);
+ expect(responses[0].nurl).to.equal('https://test.com/win-notice?test=123');
+ });
});
describe('user id system', function () {
@@ -833,4 +841,66 @@ describe('VidazooBidAdapter', function () {
expect(parsed).to.be.equal(value);
});
});
+
+ describe('validate onBidWon', function () {
+ beforeEach(function () {
+ sinon.stub(utils, 'triggerPixel');
+ });
+ afterEach(function () {
+ utils.triggerPixel.restore();
+ });
+
+ it('should call triggerPixel if nurl exists', function () {
+ const bid = {
+ adUnitCode: 'div-gpt-ad-12345-0',
+ adId: '2d52001cabd527',
+ auctionId: '1fdb5ff1b6eaa7',
+ transactionId: 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf',
+ status: 'rendered',
+ timeToRespond: 100,
+ cpm: 0.8,
+ originalCpm: 0.8,
+ creativeId: '12610997325162499419',
+ currency: 'USD',
+ originalCurrency: 'USD',
+ height: 250,
+ mediaType: 'banner',
+ nurl: 'https://test.com/win-notice?test=123',
+ netRevenue: true,
+ requestId: '2d52001cabd527',
+ ttl: 30,
+ width: 300
+ };
+ adapter.onBidWon(bid);
+ expect(utils.triggerPixel.called).to.be.true;
+
+ const url = utils.triggerPixel.args[0];
+
+ expect(url[0]).to.be.equal('https://test.com/win-notice?test=123&adId=2d52001cabd527&creativeId=12610997325162499419&auctionId=1fdb5ff1b6eaa7&transactionId=c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf&adUnitCode=div-gpt-ad-12345-0&cpm=0.8¤cy=USD&originalCpm=0.8&originalCurrency=USD&netRevenue=true&mediaType=banner&timeToRespond=100&status=rendered');
+ });
+
+ it('should not call triggerPixel if nurl does not exist', function () {
+ const bid = {
+ adUnitCode: 'div-gpt-ad-12345-0',
+ adId: '2d52001cabd527',
+ auctionId: '1fdb5ff1b6eaa7',
+ transactionId: 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf',
+ status: 'rendered',
+ timeToRespond: 100,
+ cpm: 0.8,
+ originalCpm: 0.8,
+ creativeId: '12610997325162499419',
+ currency: 'USD',
+ originalCurrency: 'USD',
+ height: 250,
+ mediaType: 'banner',
+ netRevenue: true,
+ requestId: '2d52001cabd527',
+ ttl: 30,
+ width: 300
+ };
+ adapter.onBidWon(bid);
+ expect(utils.triggerPixel.called).to.be.false;
+ });
+ });
});
diff --git a/test/spec/modules/videoModule/pbVideo_spec.js b/test/spec/modules/videoModule/pbVideo_spec.js
index 2e26737da40..1ccd9766eab 100644
--- a/test/spec/modules/videoModule/pbVideo_spec.js
+++ b/test/spec/modules/videoModule/pbVideo_spec.js
@@ -1,3 +1,4 @@
+import 'src/prebid.js';
import { expect } from 'chai';
import { PbVideo } from 'modules/videoModule';
import CONSTANTS from 'src/constants.json';
@@ -26,7 +27,8 @@ function resetTestVars() {
onEvents: sinon.spy(),
getOrtbVideo: () => ortbVideoMock,
getOrtbContent: () => ortbContentMock,
- setAdTagUrl: sinon.spy()
+ setAdTagUrl: sinon.spy(),
+ hasProviderFor: sinon.spy(),
};
getConfigMock = () => {};
requestBidsMock = {
diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js
index 139349ceead..5528705efd7 100755
--- a/test/spec/modules/visxBidAdapter_spec.js
+++ b/test/spec/modules/visxBidAdapter_spec.js
@@ -1257,6 +1257,7 @@ describe('VisxAdapter', function () {
const request = spec.buildRequests(bidRequests);
const pendingUrl = 'https://t.visx.net/track/pending/123123123';
const winUrl = 'https://t.visx.net/track/win/53245341';
+ const runtimeUrl = 'https://t.visx.net/track/status/12345678';
const expectedResponse = [
{
'requestId': '300bfeb0d71a5b',
@@ -1281,7 +1282,8 @@ describe('VisxAdapter', function () {
'ext': {
'events': {
'pending': pendingUrl,
- 'win': winUrl
+ 'win': winUrl,
+ 'runtime': runtimeUrl
},
'targeting': {
'hb_visx_product': 'understitial',
@@ -1298,6 +1300,9 @@ describe('VisxAdapter', function () {
pending: pendingUrl,
win: winUrl,
});
+ utils.deepSetValue(serverResponse.bid[0], 'ext.visx.events', {
+ runtime: runtimeUrl
+ });
const result = spec.interpretResponse({'body': {'seatbid': [serverResponse]}}, request);
expect(result).to.deep.equal(expectedResponse);
});
@@ -1325,6 +1330,39 @@ describe('VisxAdapter', function () {
expect(utils.triggerPixel.calledOnceWith(trackUrl)).to.equal(true);
});
+ it('onBidWon with runtime tracker (0 < timeToRespond <= 5000 )', function () {
+ const trackUrl = 'https://t.visx.net/track/win/123123123';
+ const runtimeUrl = 'https://t.visx.net/track/status/12345678/{STATUS_CODE}';
+ const bid = { auctionId: '1', ext: { events: { win: trackUrl, runtime: runtimeUrl } }, timeToRespond: 100 };
+ spec.onBidWon(bid);
+ expect(utils.triggerPixel.calledTwice).to.equal(true);
+ expect(utils.triggerPixel.calledWith(trackUrl)).to.equal(true);
+ expect(utils.triggerPixel.calledWith(runtimeUrl.replace('{STATUS_CODE}', 999002))).to.equal(true);
+ });
+
+ it('onBidWon with runtime tracker (timeToRespond <= 0 )', function () {
+ const runtimeUrl = 'https://t.visx.net/track/status/12345678/{STATUS_CODE}';
+ const bid = { auctionId: '2', ext: { events: { runtime: runtimeUrl } }, timeToRespond: 0 };
+ spec.onBidWon(bid);
+ expect(utils.triggerPixel.calledOnceWith(runtimeUrl.replace('{STATUS_CODE}', 999000))).to.equal(true);
+ });
+
+ it('onBidWon with runtime tracker (timeToRespond > 5000 )', function () {
+ const runtimeUrl = 'https://t.visx.net/track/status/12345678/{STATUS_CODE}';
+ const bid = { auctionId: '3', ext: { events: { runtime: runtimeUrl } }, timeToRespond: 5001 };
+ spec.onBidWon(bid);
+ expect(utils.triggerPixel.calledOnceWith(runtimeUrl.replace('{STATUS_CODE}', 999100))).to.equal(true);
+ });
+
+ it('onBidWon runtime tracker should be called once per auction', function () {
+ const runtimeUrl = 'https://t.visx.net/track/status/12345678/{STATUS_CODE}';
+ const bid1 = { auctionId: '4', ext: { events: { runtime: runtimeUrl } }, timeToRespond: 100 };
+ spec.onBidWon(bid1);
+ const bid2 = { auctionId: '4', ext: { events: { runtime: runtimeUrl } }, timeToRespond: 200 };
+ spec.onBidWon(bid2);
+ expect(utils.triggerPixel.calledOnceWith(runtimeUrl.replace('{STATUS_CODE}', 999002))).to.equal(true);
+ });
+
it('onTimeout', function () {
const data = [{ timeout: 3000, adUnitCode: 'adunit-code-1', auctionId: '1cbd2feafe5e8b', bidder: 'visx', bidId: '23423', params: [{ uid: '1' }] }];
const expectedData = [{ timeout: 3000, params: [{ uid: 1 }] }];
diff --git a/test/spec/modules/yandexAnalyticsAdapter_spec.js b/test/spec/modules/yandexAnalyticsAdapter_spec.js
new file mode 100644
index 00000000000..ca9b29d13a5
--- /dev/null
+++ b/test/spec/modules/yandexAnalyticsAdapter_spec.js
@@ -0,0 +1,147 @@
+import * as sinon from 'sinon';
+import yandexAnalytics, { EVENTS_TO_TRACK } from 'modules/yandexAnalyticsAdapter.js';
+import * as log from '../../../src/utils.js'
+import * as events from '../../../src/events.js';
+
+describe('Yandex analytics adapter testing', () => {
+ const sandbox = sinon.createSandbox();
+ let clock;
+ let logError;
+ let getEvents;
+ let onEvent;
+ const counterId = 123;
+ const counterWindowKey = 'yaCounter123';
+
+ beforeEach(() => {
+ yandexAnalytics.counters = {};
+ yandexAnalytics.counterInitTimeouts = {};
+ yandexAnalytics.bufferedEvents = [];
+ yandexAnalytics.oneCounterInited = false;
+ clock = sinon.useFakeTimers();
+ logError = sandbox.stub(log, 'logError');
+ sandbox.stub(log, 'logInfo');
+ getEvents = sandbox.stub(events, 'getEvents').returns([]);
+ onEvent = sandbox.stub(events, 'on');
+ sandbox.stub(window.document, 'createElement').callsFake((tag) => {
+ const element = {
+ tag,
+ events: {},
+ attributes: {},
+ addEventListener: (event, cb) => {
+ element.events[event] = cb;
+ },
+ removeEventListener: (event, cb) => {
+ chai.expect(element.events[event]).to.equal(cb);
+ },
+ setAttribute: (attr, val) => {
+ element.attributes[attr] = val;
+ },
+ };
+ return element;
+ });
+ });
+
+ afterEach(() => {
+ window.Ya = null;
+ window[counterWindowKey] = null;
+ sandbox.restore();
+ clock.restore();
+ });
+
+ it('fails if timeout for counter insertion is exceeded', () => {
+ yandexAnalytics.enableAnalytics({
+ options: {
+ counters: [
+ 123,
+ ],
+ },
+ });
+ clock.tick(25001);
+ chai.expect(yandexAnalytics.bufferedEvents).to.deep.equal([]);
+ sinon.assert.calledWith(logError, `Can't find metrika counter after 25 seconds.`);
+ sinon.assert.calledWith(logError, `Aborting yandex analytics provider initialization.`);
+ });
+
+ it('fails if no valid counters provided', () => {
+ yandexAnalytics.enableAnalytics({
+ options: {
+ counters: [
+ 'abc',
+ ],
+ },
+ });
+ sinon.assert.calledWith(logError, 'options.counters contains no valid counter ids');
+ });
+
+ it('subscribes to events if counter is already present', () => {
+ window[counterWindowKey] = {
+ pbjs: sandbox.stub(),
+ };
+
+ getEvents.returns([
+ {
+ eventType: EVENTS_TO_TRACK[0],
+ },
+ {
+ eventType: 'Some_untracked_event',
+ }
+ ]);
+ const eventsToSend = [{
+ event: EVENTS_TO_TRACK[0],
+ data: {
+ eventType: EVENTS_TO_TRACK[0],
+ }
+ }];
+
+ yandexAnalytics.enableAnalytics({
+ options: {
+ counters: [
+ counterId,
+ ],
+ },
+ });
+
+ EVENTS_TO_TRACK.forEach((eventName, i) => {
+ const [event, callback] = onEvent.getCall(i).args;
+ chai.expect(event).to.equal(eventName);
+ callback(i);
+ eventsToSend.push({
+ event: eventName,
+ data: i,
+ });
+ });
+
+ clock.tick(1501);
+
+ const [ sentEvents ] = window[counterWindowKey].pbjs.getCall(0).args;
+ chai.expect(sentEvents).to.deep.equal(eventsToSend);
+ });
+
+ it('waits for counter initialization', () => {
+ window.Ya = {};
+ // Simulatin metrika script initialization
+ yandexAnalytics.enableAnalytics({
+ options: {
+ counters: [
+ counterId,
+ ],
+ },
+ });
+
+ // Sending event
+ const [event, eventCallback] = onEvent.getCall(0).args;
+ eventCallback({});
+
+ const counterPbjsMethod = sandbox.stub();
+ window[`yaCounter${counterId}`] = {
+ pbjs: counterPbjsMethod,
+ };
+ clock.tick(2001);
+
+ const [ sentEvents ] = counterPbjsMethod.getCall(0).args;
+ chai.expect(sentEvents).to.deep.equal([{
+ event,
+ data: {},
+ }]);
+ });
+});
diff --git a/test/spec/modules/yandexBidAdapter_spec.js b/test/spec/modules/yandexBidAdapter_spec.js
index f14e8df6c09..c5f088a2306 100644
--- a/test/spec/modules/yandexBidAdapter_spec.js
+++ b/test/spec/modules/yandexBidAdapter_spec.js
@@ -1,6 +1,6 @@
import { assert, expect } from 'chai';
import { spec, NATIVE_ASSETS } from 'modules/yandexBidAdapter.js';
-import { parseUrl } from 'src/utils.js';
+import * as utils from 'src/utils.js';
import { BANNER, NATIVE } from '../../../src/mediaTypes';
import { config } from '../../../src/config';
@@ -71,7 +71,7 @@ describe('Yandex adapter', function () {
expect(method).to.equal('POST');
- const parsedRequestUrl = parseUrl(url);
+ const parsedRequestUrl = utils.parseUrl(url);
const { search: query } = parsedRequestUrl
expect(parsedRequestUrl.hostname).to.equal('bs.yandex.ru');
@@ -100,25 +100,43 @@ describe('Yandex adapter', function () {
const bannerRequest = getBidRequest();
const requests = spec.buildRequests([bannerRequest], bidderRequest);
const { url } = requests[0];
- const parsedRequestUrl = parseUrl(url);
+ const parsedRequestUrl = utils.parseUrl(url);
const { search: query } = parsedRequestUrl
expect(query['ssp-cur']).to.equal('USD');
});
- it('should send eids if defined', function() {
- const bannerRequest = getBidRequest({
+ it('should send eids and ortb2 user data if defined', function() {
+ const bidRequestExtra = {
userIdAsEids: [{
source: 'sharedid.org',
- uids: [
- {
- id: '01',
- atype: 1
- }
- ]
- }]
- });
+ uids: [{ id: '01', atype: 1 }],
+ }],
+ ortb2: {
+ user: {
+ data: [
+ {
+ ext: { segtax: 600, segclass: '1' },
+ name: 'example.com',
+ segment: [{ id: '243' }],
+ },
+ {
+ ext: { segtax: 600, segclass: '1' },
+ name: 'ads.example.org',
+ segment: [{ id: '243' }],
+ },
+ ],
+ },
+ },
+ };
+ const expected = {
+ ext: {
+ eids: bidRequestExtra.userIdAsEids,
+ },
+ data: bidRequestExtra.ortb2.user.data,
+ };
+ const bannerRequest = getBidRequest(bidRequestExtra);
const requests = spec.buildRequests([bannerRequest], bidderRequest);
expect(requests).to.have.lengthOf(1);
@@ -128,17 +146,7 @@ describe('Yandex adapter', function () {
const { data } = request;
expect(data.user).to.exist;
- expect(data.user).to.deep.equal({
- ext: {
- eids: [{
- source: 'sharedid.org',
- uids: [{
- id: '01',
- atype: 1,
- }],
- }],
- }
- });
+ expect(data.user).to.deep.equal(expected);
});
describe('banner', () => {
@@ -478,6 +486,55 @@ describe('Yandex adapter', function () {
});
});
});
+
+ describe('onBidWon', function() {
+ beforeEach(function() {
+ sinon.stub(utils, 'triggerPixel');
+ });
+ afterEach(function() {
+ utils.triggerPixel.restore();
+ });
+
+ it('Should not trigger pixel if bid does not contain nurl', function() {
+ const result = spec.onBidWon({});
+ expect(utils.triggerPixel.callCount).to.equal(0)
+ })
+
+ it('Should trigger pixel if bid has nurl', function() {
+ const result = spec.onBidWon({
+ nurl: 'https://example.com/some-tracker',
+ timeToRespond: 378,
+ });
+ expect(utils.triggerPixel.callCount).to.equal(1)
+ expect(utils.triggerPixel.getCall(0).args[0]).to.equal('https://example.com/some-tracker?rtt=378')
+ })
+
+ it('Should trigger pixel if bid has nurl with path & params', function() {
+ const result = spec.onBidWon({
+ nurl: 'https://example.com/some-tracker/abcdxyz?param1=1¶m2=2',
+ timeToRespond: 378,
+ });
+ expect(utils.triggerPixel.callCount).to.equal(1)
+ expect(utils.triggerPixel.getCall(0).args[0]).to.equal('https://example.com/some-tracker/abcdxyz?param1=1¶m2=2&rtt=378')
+ })
+
+ it('Should trigger pixel if bid has nurl with path & params and rtt macros', function() {
+ const result = spec.onBidWon({
+ nurl: 'https://example.com/some-tracker/abcdxyz?param1=1¶m2=2&custom-rtt=${RTT}',
+ timeToRespond: 378,
+ });
+ expect(utils.triggerPixel.callCount).to.equal(1)
+ expect(utils.triggerPixel.getCall(0).args[0]).to.equal('https://example.com/some-tracker/abcdxyz?param1=1¶m2=2&custom-rtt=378')
+ })
+
+ it('Should trigger pixel if bid has nurl and there is no timeToRespond param, but has rtt macros in nurl', function() {
+ const result = spec.onBidWon({
+ nurl: 'https://example.com/some-tracker/abcdxyz?param1=1¶m2=2&custom-rtt=${RTT}',
+ });
+ expect(utils.triggerPixel.callCount).to.equal(1)
+ expect(utils.triggerPixel.getCall(0).args[0]).to.equal('https://example.com/some-tracker/abcdxyz?param1=1¶m2=2&custom-rtt=-1')
+ })
+ })
});
function getBidConfig() {
diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js
index 93c231c816b..751dff4fe33 100644
--- a/test/spec/modules/yieldlabBidAdapter_spec.js
+++ b/test/spec/modules/yieldlabBidAdapter_spec.js
@@ -226,6 +226,36 @@ const PVID_RESPONSE = Object.assign({}, VIDEO_RESPONSE, {
pvid: '43513f11-55a0-4a83-94e5-0ebc08f54a2c',
});
+const DIGITAL_SERVICES_ACT_RESPONSE = Object.assign({}, RESPONSE, {
+ dsa: {
+ behalf: 'some-behalf',
+ paid: 'some-paid',
+ transparency: [{
+ domain: 'test.com',
+ dsaparams: [1, 2, 3]
+ }],
+ adrender: 1
+ }
+});
+
+const DIGITAL_SERVICES_ACT_CONFIG = {
+ ortb2: {
+ regs: {
+ ext: {
+ dsa: {
+ dsarequired: '1',
+ pubrender: '2',
+ datatopub: '3',
+ transparency: [{
+ domain: 'test.com',
+ dsaparams: [1, 2, 3]
+ }]
+ },
+ }
+ },
+ }
+}
+
const REQPARAMS = {
json: true,
ts: 1234567890,
@@ -486,6 +516,75 @@ describe('yieldlabBidAdapter', () => {
expect(request.url).to.not.include('sizes');
});
});
+
+ describe('Digital Services Act handling', () => {
+ beforeEach(() => {
+ config.setConfig(DIGITAL_SERVICES_ACT_CONFIG);
+ });
+
+ afterEach(() => {
+ config.resetConfig();
+ });
+
+ it('does pass dsarequired parameter', () => {
+ let request = spec.buildRequests([DEFAULT_REQUEST()], { ...REQPARAMS, ...DIGITAL_SERVICES_ACT_CONFIG });
+ expect(request.url).to.include('dsarequired=1');
+ });
+
+ it('does pass dsapubrender parameter', () => {
+ let request = spec.buildRequests([DEFAULT_REQUEST()], { ...REQPARAMS, ...DIGITAL_SERVICES_ACT_CONFIG });
+ expect(request.url).to.include('dsapubrender=2');
+ });
+
+ it('does pass dsadatatopub parameter', () => {
+ let request = spec.buildRequests([DEFAULT_REQUEST()], { ...REQPARAMS, ...DIGITAL_SERVICES_ACT_CONFIG });
+ expect(request.url).to.include('dsadatatopub=3');
+ });
+
+ it('does pass dsadomain parameter', () => {
+ let request = spec.buildRequests([DEFAULT_REQUEST()], { ...REQPARAMS, ...DIGITAL_SERVICES_ACT_CONFIG });
+ expect(request.url).to.include('dsadomain=test.com');
+ });
+
+ it('does pass encoded dsaparams parameter', () => {
+ let request = spec.buildRequests([DEFAULT_REQUEST()], { ...REQPARAMS, ...DIGITAL_SERVICES_ACT_CONFIG });
+ expect(request.url).to.include('dsaparams=1%2C2%2C3');
+ });
+
+ it('does pass multiple transparencies in dsatransparency param', () => {
+ const DSA_CONFIG_WITH_MULTIPLE_TRANSPARENCIES = {
+ ortb2: {
+ regs: {
+ ext: {
+ dsa: {
+ dsarequired: '1',
+ pubrender: '2',
+ datatopub: '3',
+ transparency: [
+ {
+ domain: 'test.com',
+ dsaparams: [1, 2, 3]
+ },
+ {
+ domain: 'example.com',
+ dsaparams: [4, 5, 6]
+ }
+ ]
+ }
+ }
+ }
+ }
+ };
+
+ config.setConfig(DSA_CONFIG_WITH_MULTIPLE_TRANSPARENCIES);
+
+ let request = spec.buildRequests([DEFAULT_REQUEST()], { ...REQPARAMS, ...DSA_CONFIG_WITH_MULTIPLE_TRANSPARENCIES });
+
+ expect(request.url).to.include('dsatransparency=test.com~1_2_3~~example.com~4_5_6');
+ expect(request.url).to.not.include('dsadomain');
+ expect(request.url).to.not.include('dsaparams');
+ });
+ });
});
describe('interpretResponse', () => {
@@ -676,6 +775,17 @@ describe('yieldlabBidAdapter', () => {
const result = spec.interpretResponse({body: [VIDEO_RESPONSE]}, {validBidRequests: [VIDEO_REQUEST()], queryParams: REQPARAMS_IAB_CONTENT});
expect(result[0].vastUrl).to.include('&iab_content=id%3Afoo_id%2Cepisode%3A99%2Ctitle%3Afoo_title%252Cbar_title%2Cseries%3Afoo_series%2Cseason%3As1%2Cartist%3Afoo%2520bar%2Cgenre%3Abaz%2Cisrc%3ACC-XXX-YY-NNNNN%2Curl%3Ahttp%253A%252F%252Ffoo_url.de%2Ccat%3Acat1%7Ccat2%252Cppp%7Ccat3%257C%257C%257C%252F%252F%2Ccontext%3A7%2Ckeywords%3Ak1%252C%7Ck2..%2Clive%3A0');
});
+
+ it('should get digital services act object in matched bid response', () => {
+ const result = spec.interpretResponse({body: [DIGITAL_SERVICES_ACT_RESPONSE]}, {validBidRequests: [{...DEFAULT_REQUEST(), ...DIGITAL_SERVICES_ACT_CONFIG}], queryParams: REQPARAMS});
+
+ expect(result[0].requestId).to.equal('2d925f27f5079f');
+ expect(result[0].meta.dsa.behalf).to.equal('some-behalf');
+ expect(result[0].meta.dsa.paid).to.equal('some-paid');
+ expect(result[0].meta.dsa.transparency[0].domain).to.equal('test.com');
+ expect(result[0].meta.dsa.transparency[0].dsaparams).to.deep.equal([1, 2, 3]);
+ expect(result[0].meta.dsa.adrender).to.equal(1);
+ });
});
describe('getUserSyncs', () => {
diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js
index a80d0a842b7..43daa9aca41 100644
--- a/test/spec/modules/yieldmoBidAdapter_spec.js
+++ b/test/spec/modules/yieldmoBidAdapter_spec.js
@@ -47,7 +47,7 @@ describe('YieldmoAdapter', function () {
video: {
playerSize: [640, 480],
context: 'instream',
- mimes: ['video/mp4']
+ mimes: ['video/mp4'],
},
},
params: {
@@ -61,11 +61,11 @@ describe('YieldmoAdapter', function () {
api: [2, 3],
skipppable: true,
playbackmethod: [1, 2],
- ...videoParams
- }
+ ...videoParams,
+ },
},
transactionId: '54a58774-7a41-494e-8cbc-fa7b79164f0c',
- ...rootParams
+ ...rootParams,
});
const mockBidderRequest = (params = {}, bids = [mockBannerBid()]) => ({
@@ -394,6 +394,41 @@ describe('YieldmoAdapter', function () {
expect(placementInfo).to.include('"gpid":"/6355419/Travel/Europe/France/Paris"');
});
+ it('should add topics to the banner bid request', function () {
+ const biddata = build([mockBannerBid()], mockBidderRequest({ortb2: { user: {
+ data: [
+ {
+ ext: {
+ segtax: 600,
+ segclass: '2206021246',
+ },
+ segment: ['7', '8', '9'],
+ },
+ ],
+ }}}));
+ expect(biddata[0].data.topics).to.deep.equal({
+ taxonomy: 600,
+ classifier: '2206021246',
+ topics: [7, 8, 9],
+ });
+ });
+
+ it('should send gpc in the banner bid request', function () {
+ const biddata = build(
+ [mockBannerBid()],
+ mockBidderRequest({
+ ortb2: {
+ regs: {
+ ext: {
+ gpc: '1'
+ },
+ },
+ },
+ })
+ );
+ expect(biddata[0].data.gpc).to.equal('1');
+ });
+
it('should add eids to the banner bid request', function () {
const params = {
userIdAsEids: [{
@@ -460,6 +495,16 @@ describe('YieldmoAdapter', function () {
expect(buildVideoBidAndGetVideoParam().minduration).to.deep.equal(['video/mp4']);
});
+ it('should add plcmt value to the imp.video', function () {
+ const videoBid = mockVideoBid({}, {}, { plcmt: 1 });
+ expect(utils.deepAccess(videoBid, 'params.video')['plcmt']).to.equal(1);
+ });
+
+ it('should add start delay if plcmt value is not 1', function () {
+ const videoBid = mockVideoBid({}, {}, { plcmt: 2 });
+ expect(build([videoBid])[0].data.imp[0].video.startdelay).to.equal(0);
+ });
+
it('should override mediaTypes.video.mimes prop if params.video.mimes is present', function () {
utils.deepAccess(videoBid, 'mediaTypes.video')['mimes'] = ['video/mp4'];
utils.deepAccess(videoBid, 'params.video')['mimes'] = ['video/mkv'];
@@ -610,6 +655,51 @@ describe('YieldmoAdapter', function () {
};
expect(buildAndGetData([mockVideoBid({...params})]).user.eids).to.eql(params.fakeUserIdAsEids);
});
+
+ it('should add topics to the bid request', function () {
+ let videoBidder = mockBidderRequest(
+ {
+ ortb2: {
+ user: {
+ data: [
+ {
+ ext: {
+ segtax: 600,
+ segclass: '2206021246',
+ },
+ segment: ['7', '8', '9'],
+ },
+ ],
+ },
+ },
+ },
+ [mockVideoBid()]
+ );
+ let payload = buildAndGetData([mockVideoBid()], 0, videoBidder);
+ expect(payload.topics).to.deep.equal({
+ taxonomy: 600,
+ classifier: '2206021246',
+ topics: [7, 8, 9],
+ });
+ });
+
+ it('should send gpc in the bid request', function () {
+ let videoBidder = mockBidderRequest(
+ {
+ ortb2: {
+ regs: {
+ ext: {
+ gpc: '1',
+ },
+ },
+ },
+ },
+ [mockVideoBid()]
+ );
+ let payload = buildAndGetData([mockVideoBid()], 0, videoBidder);
+ expect(payload.regs.ext.gpc).to.equal('1');
+ });
+
it('should add device info to payload if available', function () {
let videoBidder = mockBidderRequest({ ortb2: {
device: {
diff --git a/test/spec/modules/zeta_global_sspBidAdapter_spec.js b/test/spec/modules/zeta_global_sspBidAdapter_spec.js
index d4fe28eff90..b06a6700ebf 100644
--- a/test/spec/modules/zeta_global_sspBidAdapter_spec.js
+++ b/test/spec/modules/zeta_global_sspBidAdapter_spec.js
@@ -124,7 +124,34 @@ describe('Zeta Ssp Bid Adapter', function () {
uspConsent: 'someCCPAString',
params: params,
userIdAsEids: eids,
- timeout: 500
+ timeout: 500,
+ ortb2: {
+ device: {
+ sua: {
+ mobile: 1,
+ architecture: 'arm',
+ platform: {
+ brand: 'Chrome',
+ version: ['102']
+ }
+ }
+ },
+ user: {
+ data: [
+ {
+ ext: {
+ segtax: 600,
+ segclass: 'classifier_v1'
+ },
+ segment: [
+ { id: '3' },
+ { id: '44' },
+ { id: '59' }
+ ]
+ }
+ ]
+ }
+ }
}];
const bannerWithFewSizesRequest = [{
@@ -606,4 +633,28 @@ describe('Zeta Ssp Bid Adapter', function () {
expect(bidResponse[0].ad).to.eql(zetaResponse.body.seatbid[0].bid[0].adm);
expect(bidResponse[0].vastXml).to.be.undefined;
});
+
+ it('Test provide segments into the request', function () {
+ const request = spec.buildRequests(bannerRequest, bannerRequest[0]);
+ const payload = JSON.parse(request.data);
+ expect(payload.user.data[0].segment.length).to.eql(3);
+ expect(payload.user.data[0].segment[0].id).to.eql('3');
+ expect(payload.user.data[0].segment[1].id).to.eql('44');
+ expect(payload.user.data[0].segment[2].id).to.eql('59');
+ });
+
+ it('Test provide device params', function () {
+ const request = spec.buildRequests(bannerRequest, bannerRequest[0]);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.device.sua.mobile).to.eql(1);
+ expect(payload.device.sua.architecture).to.eql('arm');
+ expect(payload.device.sua.platform.brand).to.eql('Chrome');
+ expect(payload.device.sua.platform.version[0]).to.eql('102');
+
+ expect(payload.device.ua).to.not.be.undefined;
+ expect(payload.device.language).to.not.be.undefined;
+ expect(payload.device.w).to.not.be.undefined;
+ expect(payload.device.h).to.not.be.undefined;
+ });
});
diff --git a/test/spec/modules/zmaticooBidAdapter_spec.js b/test/spec/modules/zmaticooBidAdapter_spec.js
new file mode 100644
index 00000000000..1634340ac6a
--- /dev/null
+++ b/test/spec/modules/zmaticooBidAdapter_spec.js
@@ -0,0 +1,289 @@
+import {checkParamDataType, spec} from '../../../modules/zmaticooBidAdapter.js'
+import {deepClone} from '../../../src/utils';
+
+describe('zMaticoo Bidder Adapter', function () {
+ const bannerRequest = [{
+ bidId: '1234511',
+ auctionId: '223',
+ mediaTypes: {
+ banner: {
+ sizes: [[320, 50]],
+ }
+ },
+ refererInfo: {
+ page: 'testprebid.com'
+ },
+ params: {
+ user: {
+ uid: '12345',
+ buyeruid: '12345'
+ },
+ device: {
+ ip: '111.222.33.44',
+ geo: {
+ country: 'USA'
+ }
+ },
+ pubId: 'prebid-test',
+ test: 1,
+ bidfloor: 1,
+ tagid: 'test'
+ }
+ }];
+ const bannerRequest1 = [{
+ bidId: '1234511',
+ auctionId: '223',
+ mediaTypes: {
+ banner: {
+ sizes: [[320, 50]],
+ }
+ },
+ refererInfo: {
+ page: 'testprebid.com'
+ },
+ params: {
+ user: {
+ uid: '12345',
+ buyeruid: '12345'
+ },
+ device: {
+ ip: '111.222.33.44',
+ geo: {
+ country: 'USA'
+ }
+ },
+ pubId: 'prebid-test',
+ test: 1,
+ tagid: 'test'
+ },
+ gdprConsent: {
+ gdprApplies: 1,
+ consentString: 'consentString'
+ },
+ getFloor: function () {
+ return {
+ currency: 'USD',
+ floor: 0.5,
+ }
+ },
+ }];
+ const videoRequest = [{
+ bidId: '1234511',
+ auctionId: '223',
+ mediaTypes: {
+ video: {
+ playerSize: [480, 320],
+ mimes: ['video/mp4'],
+ context: 'instream',
+ placement: 1,
+ maxduration: 30,
+ minduration: 15,
+ pos: 1,
+ startdelay: 10,
+ protocols: [2, 3],
+ api: [2, 3],
+ playbackmethod: [2, 6],
+ skip: 10,
+ }
+ },
+ refererInfo: {
+ page: 'testprebid.com'
+ },
+ params: {
+ user: {
+ uid: '12345',
+ buyeruid: '12345'
+ },
+ device: {
+ ip: '111.222.33.44',
+ geo: {
+ country: 'USA'
+ }
+ },
+ pubId: 'prebid-test',
+ test: 1,
+ tagid: 'test',
+ bidfloor: 1
+ }
+ }];
+
+ const videoRequest1 = [{
+ bidId: '1234511',
+ auctionId: '223',
+ mediaTypes: {
+ video: {
+ playerSize: [[480, 320]],
+ mimes: ['video/mp4'],
+ context: 'instream',
+ placement: 1,
+ maxduration: 30,
+ minduration: 15,
+ pos: 1,
+ startdelay: 10,
+ protocols: [2, 3],
+ api: [2, 3],
+ playbackmethod: [2, 6],
+ skip: 10,
+ }
+ },
+ params: {
+ user: {
+ uid: '12345',
+ buyeruid: '12345'
+ },
+ device: {
+ ip: '111.222.33.44',
+ geo: {
+ country: 'USA'
+ }
+ },
+ pubId: 'prebid-test',
+ test: 1,
+ tagid: 'test',
+ bidfloor: 1
+ }
+ }];
+
+ describe('isBidRequestValid', function () {
+ it('this is valid bidrequest', function () {
+ const validBid = spec.isBidRequestValid(videoRequest[0]);
+ expect(validBid).to.be.true;
+ });
+ it('missing required bid data {bid}', function () {
+ const invalidBid = spec.isBidRequestValid(null);
+ expect(invalidBid).to.be.false;
+ });
+ it('missing required bid.bidId', function () {
+ const request = deepClone(videoRequest[0])
+ delete request.bidId
+ const invalidBid = spec.isBidRequestValid(request);
+ expect(invalidBid).to.be.false;
+ });
+ it('missing required params.pubId', function () {
+ const request = deepClone(videoRequest[0])
+ delete request.params.pubId
+ const invalidBid = spec.isBidRequestValid(request);
+ expect(invalidBid).to.be.false;
+ });
+ it('missing required device data', function () {
+ const request = deepClone(videoRequest[0])
+ delete request.params.device
+ const invalidBid = spec.isBidRequestValid(request);
+ expect(invalidBid).to.be.false;
+ });
+ })
+ describe('buildRequests', function () {
+ it('Test the banner request processing function', function () {
+ const request = spec.buildRequests(bannerRequest, bannerRequest[0]);
+ expect(request).to.not.be.empty;
+ const payload = request.data;
+ expect(payload).to.not.be.empty;
+ });
+ it('Test the video request processing function', function () {
+ const request = spec.buildRequests(videoRequest, videoRequest[0]);
+ expect(request).to.not.be.empty;
+ const payload = request.data;
+ expect(payload).to.not.be.empty;
+ });
+ it('Test the param', function () {
+ const request = spec.buildRequests(bannerRequest, bannerRequest[0]);
+ const payload = JSON.parse(request.data);
+ expect(payload.imp[0].tagid).to.eql(videoRequest[0].params.tagid);
+ expect(payload.imp[0].bidfloor).to.eql(videoRequest[0].params.bidfloor);
+ });
+ it('Test video object', function () {
+ const request = spec.buildRequests(videoRequest, videoRequest[0]);
+ const payload = JSON.parse(request.data);
+ expect(payload.imp[0].video).to.exist;
+ expect(payload.imp[0].video.minduration).to.eql(videoRequest[0].mediaTypes.video.minduration);
+ expect(payload.imp[0].video.maxduration).to.eql(videoRequest[0].mediaTypes.video.maxduration);
+ expect(payload.imp[0].video.protocols).to.eql(videoRequest[0].mediaTypes.video.protocols);
+ expect(payload.imp[0].video.mimes).to.eql(videoRequest[0].mediaTypes.video.mimes);
+ expect(payload.imp[0].video.w).to.eql(480);
+ expect(payload.imp[0].video.h).to.eql(320);
+ expect(payload.imp[0].banner).to.be.undefined;
+ });
+
+ it('Test video isArray size', function () {
+ const request = spec.buildRequests(videoRequest1, videoRequest1[0]);
+ const payload = JSON.parse(request.data);
+ expect(payload.imp[0].video.w).to.eql(480);
+ expect(payload.imp[0].video.h).to.eql(320);
+ });
+ it('Test banner object', function () {
+ const request = spec.buildRequests(bannerRequest, bannerRequest[0]);
+ const payload = JSON.parse(request.data);
+ expect(payload.imp[0].video).to.be.undefined;
+ expect(payload.imp[0].banner).to.exist;
+ });
+
+ it('Test provide gdpr and ccpa values in payload', function () {
+ const request = spec.buildRequests(bannerRequest1, bannerRequest1[0]);
+ const payload = JSON.parse(request.data);
+ expect(payload.user.ext.consent).to.eql('consentString');
+ expect(payload.regs.ext.gdpr).to.eql(1);
+ });
+
+ it('Test bidfloor is function', function () {
+ const request = spec.buildRequests(bannerRequest1, bannerRequest1[0]);
+ const payload = JSON.parse(request.data);
+ expect(payload.imp[0].bidfloor).to.eql(0.5);
+ });
+ });
+ describe('checkParamDataType tests', function () {
+ it('return the expected datatypes', function () {
+ assert.isString(checkParamDataType('Right string', 'test', 'string'));
+ assert.isBoolean(checkParamDataType('Right bool', true, 'boolean'));
+ assert.isNumber(checkParamDataType('Right number', 10, 'number'));
+ assert.isArray(checkParamDataType('Right array', [10, 11], 'array'));
+ });
+
+ it('return undefined var for wrong datatypes', function () {
+ expect(checkParamDataType('Wrong string', 10, 'string')).to.be.undefined;
+ expect(checkParamDataType('Wrong bool', 10, 'boolean')).to.be.undefined;
+ expect(checkParamDataType('Wrong number', 'one', 'number')).to.be.undefined;
+ expect(checkParamDataType('Wrong array', false, 'array')).to.be.undefined;
+ });
+ })
+ describe('interpretResponse', function () {
+ const responseBody = {
+ id: '12345',
+ seatbid: [
+ {
+ bid: [
+ {
+ id: 'auctionId',
+ impid: 'impId',
+ price: 0.0,
+ adm: 'adMarkup',
+ crid: 'creativeId',
+ adomain: ['test.com'],
+ h: 50,
+ w: 320,
+ ext: {
+ vast_url: '
'
+ }
+ }
+ ]
+ }
+ ],
+ cur: 'USD'
+ };
+ it('Test the response parsing function', function () {
+ const receivedBid = responseBody.seatbid[0].bid[0];
+ const response = {};
+ response.body = responseBody;
+ const bidResponse = spec.interpretResponse(response, null);
+ expect(bidResponse).to.not.be.empty;
+ const bid = bidResponse[0];
+ expect(bid).to.not.be.empty;
+ expect(bid.ad).to.equal(receivedBid.adm);
+ expect(bid.cpm).to.equal(receivedBid.price);
+ expect(bid.height).to.equal(receivedBid.h);
+ expect(bid.width).to.equal(receivedBid.w);
+ expect(bid.requestId).to.equal(receivedBid.impid);
+ expect(bid.vastXml).to.equal(receivedBid.ext.vast_url);
+ expect(bid.meta.advertiserDomains).to.equal(receivedBid.adomain);
+ });
+ });
+});
diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js
index 9cfee6f5cd8..bf1c745d8cc 100644
--- a/test/spec/native_spec.js
+++ b/test/spec/native_spec.js
@@ -19,7 +19,7 @@ const utils = require('src/utils');
const bid = {
adId: '123',
- transactionId: 'au',
+ adUnitId: 'au',
native: {
title: 'Native Creative',
body: 'Cool description great stuff',
@@ -49,7 +49,7 @@ const bid = {
const ortbBid = {
adId: '123',
- transactionId: 'au',
+ adUnitId: 'au',
native: {
ortb: {
assets: [
@@ -106,7 +106,7 @@ const ortbBid = {
const completeNativeBid = {
adId: '123',
- transactionId: 'au',
+ adUnitId: 'au',
native: {
...bid.native,
...ortbBid.native
@@ -157,7 +157,7 @@ const ortbRequest = {
}
const bidWithUndefinedFields = {
- transactionId: 'au',
+ adUnitId: 'au',
native: {
title: 'Native Creative',
body: undefined,
@@ -209,7 +209,7 @@ describe('native.js', function () {
it('sends placeholders for configured assets', function () {
const adUnit = {
- transactionId: 'au',
+ adUnitId: 'au',
nativeParams: {
body: { sendId: true },
clickUrl: { sendId: true },
@@ -246,7 +246,7 @@ describe('native.js', function () {
it('should only include native targeting keys with values', function () {
const adUnit = {
- transactionId: 'au',
+ adUnitId: 'au',
nativeParams: {
body: { sendId: true },
clickUrl: { sendId: true },
@@ -273,7 +273,7 @@ describe('native.js', function () {
it('should only include targeting that has sendTargetingKeys set to true', function () {
const adUnit = {
- transactionId: 'au',
+ adUnitId: 'au',
nativeParams: {
image: {
required: true,
@@ -294,7 +294,7 @@ describe('native.js', function () {
it('should only include targeting if sendTargetingKeys not set to false', function () {
const adUnit = {
- transactionId: 'au',
+ adUnitId: 'au',
nativeParams: {
image: {
required: true,
@@ -347,7 +347,7 @@ describe('native.js', function () {
it('should copy over rendererUrl to bid object and include it in targeting', function () {
const adUnit = {
- transactionId: 'au',
+ adUnitId: 'au',
nativeParams: {
image: {
required: true,
@@ -382,7 +382,7 @@ describe('native.js', function () {
it('should copy over adTemplate to bid object and include it in targeting', function () {
const adUnit = {
- transactionId: 'au',
+ adUnitId: 'au',
nativeParams: {
image: {
required: true,
@@ -724,7 +724,7 @@ describe('validate native openRTB', function () {
describe('validate native', function () {
const adUnit = {
- transactionId: 'test_adunit',
+ adUnitId: 'test_adunit',
mediaTypes: {
native: {
title: {
@@ -749,7 +749,7 @@ describe('validate native', function () {
let validBid = {
adId: 'abc123',
requestId: 'test_bid_id',
- transactionId: 'test_adunit',
+ adUnitId: 'test_adunit',
adUnitCode: '123/prebid_native_adunit',
bidder: 'test_bidder',
native: {
@@ -776,7 +776,7 @@ describe('validate native', function () {
let noIconDimBid = {
adId: 'abc234',
requestId: 'test_bid_id',
- transactionId: 'test_adunit',
+ adUnitId: 'test_adunit',
adUnitCode: '123/prebid_native_adunit',
bidder: 'test_bidder',
native: {
@@ -799,7 +799,7 @@ describe('validate native', function () {
let noImgDimBid = {
adId: 'abc345',
requestId: 'test_bid_id',
- transactionId: 'test_adunit',
+ adUnitId: 'test_adunit',
adUnitCode: '123/prebid_native_adunit',
bidder: 'test_bidder',
native: {
@@ -836,7 +836,7 @@ describe('validate native', function () {
it('should convert from old-style native to OpenRTB request', () => {
const adUnit = {
- transactionId: 'test_adunit',
+ adUnitId: 'test_adunit',
mediaTypes: {
native: {
title: {
@@ -1043,7 +1043,7 @@ describe('validate native', function () {
const validBidRequests = [{
bidId: 'bidId3',
adUnitCode: 'adUnitCode3',
- transactionId: 'transactionId3',
+ adUnitId: 'transactionId3',
mediaTypes: {
banner: {}
},
diff --git a/test/spec/ortbConverter/common_spec.js b/test/spec/ortbConverter/common_spec.js
new file mode 100644
index 00000000000..d2d61e6778c
--- /dev/null
+++ b/test/spec/ortbConverter/common_spec.js
@@ -0,0 +1,29 @@
+import {DEFAULT_PROCESSORS} from '../../../libraries/ortbConverter/processors/default.js';
+import {BID_RESPONSE} from '../../../src/pbjsORTB.js';
+
+describe('common processors', () => {
+ describe('bid response properties', () => {
+ const responseProps = DEFAULT_PROCESSORS[BID_RESPONSE].props.fn;
+ let context;
+
+ beforeEach(() => {
+ context = {
+ ortbResponse: {}
+ }
+ })
+
+ describe('meta.dsa', () => {
+ const MOCK_DSA = {transparency: 'info'};
+ it('is not set if bid has no meta.dsa', () => {
+ const resp = {};
+ responseProps(resp, {}, context);
+ expect(resp.meta?.dsa).to.not.exist;
+ });
+ it('is set to ext.dsa otherwise', () => {
+ const resp = {};
+ responseProps(resp, {ext: {dsa: MOCK_DSA}}, context);
+ expect(resp.meta.dsa).to.eql(MOCK_DSA);
+ })
+ })
+ })
+})
diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js
index 98d841d9c7c..dac70696b4b 100644
--- a/test/spec/unit/core/adapterManager_spec.js
+++ b/test/spec/unit/core/adapterManager_spec.js
@@ -964,25 +964,42 @@ describe('adapterManager tests', function () {
'start': 1462918897460
}];
- it('invokes callBids on the S2S adapter', function () {
- const done = sinon.stub();
- const onTimelyResponse = sinon.stub();
- prebidServerAdapterMock.callBids.callsFake((_1, _2, _3, done) => {
- done();
+ describe('invokes callBids on the S2S adapter', () => {
+ let onTimelyResponse, timedOut, done;
+ beforeEach(() => {
+ done = sinon.stub();
+ onTimelyResponse = sinon.stub();
+ prebidServerAdapterMock.callBids.callsFake((_1, _2, _3, done) => {
+ done(timedOut);
+ });
+ })
+
+ function runTest() {
+ adapterManager.callBids(
+ getAdUnits(),
+ bidRequests,
+ () => {},
+ done,
+ undefined,
+ undefined,
+ onTimelyResponse
+ );
+ sinon.assert.calledTwice(prebidServerAdapterMock.callBids);
+ sinon.assert.calledTwice(done);
+ }
+
+ it('and marks requests as timely if the adapter says timedOut = false', function () {
+ timedOut = false;
+ runTest();
+ bidRequests.forEach(br => sinon.assert.calledWith(onTimelyResponse, br.bidderRequestId));
});
- adapterManager.callBids(
- getAdUnits(),
- bidRequests,
- () => {},
- done,
- undefined,
- undefined,
- onTimelyResponse
- );
- sinon.assert.calledTwice(prebidServerAdapterMock.callBids);
- sinon.assert.calledTwice(done);
- bidRequests.forEach(br => sinon.assert.calledWith(onTimelyResponse, br.bidderRequestId));
- });
+
+ it('and does NOT mark them as timely if it says timedOut = true', () => {
+ timedOut = true;
+ runTest();
+ sinon.assert.notCalled(onTimelyResponse);
+ })
+ })
// Enable this test when prebidServer adapter is made 1.0 compliant
it('invokes callBids with only s2s bids', function () {
diff --git a/test/spec/unit/core/ajax_spec.js b/test/spec/unit/core/ajax_spec.js
index a3a0459b980..dd03ad1a761 100644
--- a/test/spec/unit/core/ajax_spec.js
+++ b/test/spec/unit/core/ajax_spec.js
@@ -232,7 +232,7 @@ describe('attachCallbacks', () => {
};
}
- function expectNullXHR(response) {
+ function expectNullXHR(response, reason) {
return new Promise((resolve, reject) => {
attachCallbacks(Promise.resolve(response), {
success: () => {
@@ -246,7 +246,8 @@ describe('attachCallbacks', () => {
statusText: '',
responseText: '',
response: '',
- responseXML: null
+ responseXML: null,
+ reason
});
expect(xhr.getResponseHeader('any')).to.be.null;
resolve();
@@ -256,9 +257,21 @@ describe('attachCallbacks', () => {
}
it('runs error callback on rejections', () => {
- return expectNullXHR(Promise.reject(new Error()));
+ const err = new Error();
+ return expectNullXHR(Promise.reject(err), err);
});
+ it('sets timedOut = true on fetch timeout', (done) => {
+ const ctl = new AbortController();
+ ctl.abort();
+ attachCallbacks(fetch('/', {signal: ctl.signal}), {
+ error(_, xhr) {
+ expect(xhr.timedOut).to.be.true;
+ done();
+ }
+ });
+ })
+
Object.entries({
'2xx response': {
success: true,
@@ -368,8 +381,9 @@ describe('attachCallbacks', () => {
});
it(`runs error callback if body cannot be retrieved`, () => {
- response.text = () => Promise.reject(new Error());
- return expectNullXHR(response);
+ const err = new Error();
+ response.text = () => Promise.reject(err);
+ return expectNullXHR(response, err);
});
if (success) {
diff --git a/test/spec/unit/core/auctionIndex_spec.js b/test/spec/unit/core/auctionIndex_spec.js
index f00e2cd281f..df29ed1a6cb 100644
--- a/test/spec/unit/core/auctionIndex_spec.js
+++ b/test/spec/unit/core/auctionIndex_spec.js
@@ -38,22 +38,22 @@ describe('auction index', () => {
let adUnits;
beforeEach(() => {
- adUnits = [{transactionId: 'au1'}, {transactionId: 'au2'}];
+ adUnits = [{adUnitId: 'au1'}, {adUnitId: 'au2'}];
auctions = [
mockAuction('a1', [adUnits[0], {}]),
mockAuction('a2', [adUnits[1]])
];
});
- it('should find adUnits by transactionId', () => {
- expect(index.getAdUnit({transactionId: 'au2'})).to.equal(adUnits[1]);
+ it('should find adUnits by adUnitId', () => {
+ expect(index.getAdUnit({adUnitId: 'au2'})).to.equal(adUnits[1]);
});
it('should return undefined if adunit is missing', () => {
- expect(index.getAdUnit({transactionId: 'missing'})).to.be.undefined;
+ expect(index.getAdUnit({adUnitId: 'missing'})).to.be.undefined;
});
- it('should return undefined if no transactionId is provided', () => {
+ it('should return undefined if no adUnitId is provided', () => {
expect(index.getAdUnit({})).to.be.undefined;
});
});
@@ -87,12 +87,12 @@ describe('auction index', () => {
beforeEach(() => {
mediaTypes = [{mockMT: '1'}, {mockMT: '2'}, {mockMT: '3'}, {mockMT: '4'}]
adUnits = [
- {transactionId: 'au1', mediaTypes: mediaTypes[0]},
- {transactionId: 'au2', mediaTypes: mediaTypes[1]}
+ {adUnitId: 'au1', mediaTypes: mediaTypes[0]},
+ {adUnitId: 'au2', mediaTypes: mediaTypes[1]}
]
bidderRequests = [
- {bidderRequestId: 'ber1', bids: [{bidId: 'b1', mediaTypes: mediaTypes[2], transactionId: 'au1'}, {}]},
- {bidderRequestId: 'ber2', bids: [{bidId: 'b2', mediaTypes: mediaTypes[3], transactionId: 'au2'}]}
+ {bidderRequestId: 'ber1', bids: [{bidId: 'b1', mediaTypes: mediaTypes[2], adUnitId: 'au1'}, {}]},
+ {bidderRequestId: 'ber2', bids: [{bidId: 'b2', mediaTypes: mediaTypes[3], adUnitId: 'au2'}]}
]
auctions = [
mockAuction('a1', [adUnits[0]], [bidderRequests[0], {}]),
@@ -100,8 +100,8 @@ describe('auction index', () => {
]
});
- it('should find mediaTypes by transactionId', () => {
- expect(index.getMediaTypes({transactionId: 'au2'})).to.equal(mediaTypes[1]);
+ it('should find mediaTypes by adUnitId', () => {
+ expect(index.getMediaTypes({adUnitId: 'au2'})).to.equal(mediaTypes[1]);
});
it('should find mediaTypes by requestId', () => {
@@ -109,18 +109,18 @@ describe('auction index', () => {
});
it('should give precedence to request.mediaTypes over adUnit.mediaTypes', () => {
- expect(index.getMediaTypes({requestId: 'b2', transactionId: 'au2'})).to.equal(mediaTypes[3]);
+ expect(index.getMediaTypes({requestId: 'b2', adUnitId: 'au2'})).to.equal(mediaTypes[3]);
});
- it('should return undef if requestId and transactionId do not match', () => {
- expect(index.getMediaTypes({requestId: 'b1', transactionId: 'au2'})).to.be.undefined;
+ it('should return undef if requestId and adUnitId do not match', () => {
+ expect(index.getMediaTypes({requestId: 'b1', adUnitId: 'au2'})).to.be.undefined;
});
it('should return undef if no params are provided', () => {
expect(index.getMediaTypes({})).to.be.undefined;
});
- ['requestId', 'transactionId'].forEach(param => {
+ ['requestId', 'adUnitId'].forEach(param => {
it(`should return undef if ${param} is missing`, () => {
expect(index.getMediaTypes({[param]: 'missing'})).to.be.undefined;
});
diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js
index f089059b65a..aba64733f90 100644
--- a/test/spec/unit/core/bidderFactory_spec.js
+++ b/test/spec/unit/core/bidderFactory_spec.js
@@ -38,10 +38,6 @@ const MOCK_BIDS_REQUEST = {
]
}
-function onTimelyResponseStub() {
-
-}
-
before(() => {
hook.ready();
});
@@ -49,6 +45,10 @@ before(() => {
let wrappedCallback = config.callbackWithBidder(CODE);
describe('bidderFactory', () => {
+ let onTimelyResponseStub;
+ beforeEach(() => {
+ onTimelyResponseStub = sinon.stub();
+ })
describe('bidders created by newBidder', function () {
let spec;
let bidder;
@@ -422,7 +422,15 @@ describe('bidderFactory', () => {
});
describe('browsingTopics ajax option', () => {
- let transmitUfpdAllowed, bidder;
+ let transmitUfpdAllowed, bidder, origBS;
+ before(() => {
+ origBS = window.$$PREBID_GLOBAL$$.bidderSettings;
+ })
+
+ after(() => {
+ window.$$PREBID_GLOBAL$$.bidderSettings = origBS;
+ });
+
beforeEach(() => {
activityRules.isActivityAllowed.reset();
activityRules.isActivityAllowed.callsFake((activity) => activity === ACTIVITY_TRANSMIT_UFPD ? transmitUfpdAllowed : true);
@@ -448,49 +456,71 @@ describe('bidderFactory', () => {
});
Object.entries({
- 'allowed': true,
- 'not allowed': false
- }).forEach(([t, allow]) => {
- it(`should be set to ${allow} when transmitUfpd is ${t}`, () => {
- transmitUfpdAllowed = allow;
- spec.buildRequests.returns([
- {
- method: 'GET',
- url: '1',
- },
- {
- method: 'POST',
- url: '2',
- data: {}
- },
- {
- method: 'GET',
- url: '3',
- options: {
- browsingTopics: true
- }
- },
- {
- method: 'POST',
- url: '4',
- data: {},
- options: {
- browsingTopics: true
+ 'omitted': [undefined, true],
+ 'enabled': [true, true],
+ 'disabled': [false, false]
+ }).forEach(([t, [topicsHeader, enabled]]) => {
+ describe(`when bidderSettings.topicsHeader is ${t}`, () => {
+ beforeEach(() => {
+ window.$$PREBID_GLOBAL$$.bidderSettings = {
+ [CODE]: {
+ topicsHeader: topicsHeader
}
}
- ]);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- ['1', '2', '3', '4'].forEach(url => {
- sinon.assert.calledWith(
- ajaxStub,
- url,
- sinon.match.any,
- sinon.match.any,
- sinon.match({browsingTopics: allow})
- );
});
- });
- });
+
+ afterEach(() => {
+ delete window.$$PREBID_GLOBAL$$.bidderSettings[CODE];
+ });
+
+ Object.entries({
+ 'allowed': true,
+ 'not allowed': false
+ }).forEach(([t, allow]) => {
+ const shouldBeSet = allow && enabled;
+
+ it(`should be set to ${shouldBeSet} when transmitUfpd is ${t}`, () => {
+ transmitUfpdAllowed = allow;
+ spec.buildRequests.returns([
+ {
+ method: 'GET',
+ url: '1',
+ },
+ {
+ method: 'POST',
+ url: '2',
+ data: {}
+ },
+ {
+ method: 'GET',
+ url: '3',
+ options: {
+ browsingTopics: true
+ }
+ },
+ {
+ method: 'POST',
+ url: '4',
+ data: {},
+ options: {
+ browsingTopics: true
+ }
+ }
+ ]);
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ ['1', '2', '3', '4'].forEach(url => {
+ sinon.assert.calledWith(
+ ajaxStub,
+ url,
+ sinon.match.any,
+ sinon.match.any,
+ sinon.match({browsingTopics: shouldBeSet})
+ );
+ });
+ });
+ });
+ })
+ })
});
it('should not add bids for each placement code if no requests are given', function () {
@@ -552,6 +582,14 @@ describe('bidderFactory', () => {
utils.logError.restore();
});
+ it('should call onTimelyResponse', () => {
+ const bidder = newBidder(spec);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({method: 'POST', url: 'test', data: {}});
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ sinon.assert.called(onTimelyResponseStub);
+ })
+
it('should call spec.interpretResponse() with the response content', function () {
const bidder = newBidder(spec);
@@ -770,12 +808,13 @@ describe('bidderFactory', () => {
let ajaxStub;
let callBidderErrorStub;
let eventEmitterStub;
- let xhrErrorMock = {
- status: 500,
- statusText: 'Internal Server Error'
- };
+ let xhrErrorMock;
beforeEach(function () {
+ xhrErrorMock = {
+ status: 500,
+ statusText: 'Internal Server Error'
+ };
ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) {
callbacks.error('ajax call failed.', xhrErrorMock);
});
@@ -791,6 +830,20 @@ describe('bidderFactory', () => {
eventEmitterStub.restore();
});
+ Object.entries({
+ 'timeouts': true,
+ 'other errors': false
+ }).forEach(([t, timedOut]) => {
+ it(`should ${timedOut ? 'NOT ' : ''}call onTimelyResponse on ${t}`, () => {
+ Object.assign(xhrErrorMock, {timedOut});
+ const bidder = newBidder(spec);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({method: 'POST', url: 'test', data: {}});
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ sinon.assert[timedOut ? 'notCalled' : 'called'](onTimelyResponseStub);
+ })
+ })
+
it('should not spec.interpretResponse()', function () {
const bidder = newBidder(spec);
@@ -1056,7 +1109,7 @@ describe('bidderFactory', () => {
if (FEATURES.NATIVE) {
it('should add native bids that do have required assets', function () {
adUnits = [{
- transactionId: 'au',
+ adUnitId: 'au',
nativeParams: {
title: {'required': true},
}
@@ -1067,7 +1120,7 @@ describe('bidderFactory', () => {
bidId: '1',
auctionId: 'first-bid-id',
adUnitCode: 'mock/placement',
- transactionId: 'au',
+ adUnitId: 'au',
params: {
param: 5
},
diff --git a/test/spec/unit/core/events_spec.js b/test/spec/unit/core/events_spec.js
index 6551c9f2456..e1451f657b5 100644
--- a/test/spec/unit/core/events_spec.js
+++ b/test/spec/unit/core/events_spec.js
@@ -1,5 +1,6 @@
import {config} from 'src/config.js';
-import {emit, clearEvents, getEvents} from '../../../../src/events.js';
+import {emit, clearEvents, getEvents, on, off} from '../../../../src/events.js';
+import * as utils from '../../../../src/utils.js'
describe('events', () => {
let clock;
@@ -26,5 +27,19 @@ describe('events', () => {
config.setConfig({eventHistoryTTL: 1000});
clock.tick(10000);
expect(getEvents().length).to.eql(1);
- })
+ });
+
+ it('should include the eventString if a callback fails', () => {
+ const logErrorStub = sinon.stub(utils, 'logError');
+ const eventString = 'bidWon';
+ let fn = function() { throw new Error('Test error'); };
+ on(eventString, fn);
+
+ emit(eventString, {});
+
+ sinon.assert.calledWith(logErrorStub, 'Error executing handler:', 'events.js', sinon.match.instanceOf(Error), eventString);
+
+ off(eventString, fn);
+ logErrorStub.restore();
+ });
})
diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js
index 664f7ebb58f..e61171c3a22 100644
--- a/test/spec/unit/pbjs_api_spec.js
+++ b/test/spec/unit/pbjs_api_spec.js
@@ -14,7 +14,7 @@ import { config as configObj } from 'src/config.js';
import * as ajaxLib from 'src/ajax.js';
import * as auctionModule from 'src/auction.js';
import { registerBidder } from 'src/adapters/bidderFactory.js';
-import { _sendAdToCreative } from 'src/secureCreatives.js';
+import {resizeRemoteCreative} from 'src/secureCreatives.js';
import {find} from 'src/polyfill.js';
import * as pbjsModule from 'src/prebid.js';
import {hook} from '../../../src/hook.js';
@@ -556,6 +556,7 @@ describe('Unit: Prebid Module', function () {
'bidderRequestId': '331f3cf3f1d9c8',
'auctionId': '20882439e3238c',
'transactionId': 'trdiv-gpt-ad-1460505748561-0',
+ 'adUnitId': 'audiv-gpt-ad-1460505748561-0',
}
],
'auctionStart': 1505250713622,
@@ -573,6 +574,7 @@ describe('Unit: Prebid Module', function () {
let auctionManagerInstance = newAuctionManager();
targeting = newTargeting(auctionManagerInstance);
let adUnits = [{
+ adUnitId: 'audiv-gpt-ad-1460505748561-0',
transactionId: 'trdiv-gpt-ad-1460505748561-0',
code: 'div-gpt-ad-1460505748561-0',
sizes: [[300, 250], [300, 600]],
@@ -718,6 +720,7 @@ describe('Unit: Prebid Module', function () {
const adUnit = {
transactionId: `tr${code}`,
+ adUnitId: `au${code}`,
code: code,
sizes: [[300, 250], [300, 600]],
bids: [{
@@ -820,6 +823,7 @@ describe('Unit: Prebid Module', function () {
},
'adUnitCode': 'div-gpt-ad-1460505748561-0',
'transactionId': 'trdiv-gpt-ad-1460505748561-0',
+ 'adUnitId': 'audiv-gpt-ad-1460505748561-0',
'sizes': [
[
300,
@@ -1104,7 +1108,7 @@ describe('Unit: Prebid Module', function () {
adUnitCode: config.adUnitCodes[0],
};
- _sendAdToCreative(mockAdObject, sinon.stub());
+ resizeRemoteCreative(mockAdObject);
expect(slots[0].spyGetSlotElementId.called).to.equal(false);
expect(slots[1].spyGetSlotElementId.called).to.equal(true);
@@ -1233,7 +1237,8 @@ describe('Unit: Prebid Module', function () {
}
},
getElementsByTagName: sinon.stub(),
- querySelector: sinon.stub()
+ querySelector: sinon.stub(),
+ createElement: sinon.stub(),
};
elStub = {
@@ -1264,7 +1269,7 @@ describe('Unit: Prebid Module', function () {
it('should require doc and id params', function () {
$$PREBID_GLOBAL$$.renderAd();
- var error = 'Error trying to write ad Id :undefined to the page. Missing adId';
+ var error = 'Error rendering ad (id: undefined): missing adId';
assert.ok(spyLogError.calledWith(error), 'expected param error was logged');
});
@@ -1289,14 +1294,13 @@ describe('Unit: Prebid Module', function () {
adUrl: 'http://server.example.com/ad/ad.js'
});
$$PREBID_GLOBAL$$.renderAd(doc, bidId);
- assert.ok(elStub.insertBefore.called, 'url was written to iframe in doc');
+ sinon.assert.calledWith(doc.createElement, 'iframe');
});
it('should log an error when no ad or url', function () {
pushBidResponseToAuction({});
$$PREBID_GLOBAL$$.renderAd(doc, bidId);
- var error = 'Error trying to write ad. No ad for bid response id: ' + bidId;
- assert.ok(spyLogError.calledWith(error), 'expected error was logged');
+ sinon.assert.called(spyLogError);
});
it('should log an error when not in an iFrame', function () {
@@ -1305,7 +1309,7 @@ describe('Unit: Prebid Module', function () {
});
inIframe = false;
$$PREBID_GLOBAL$$.renderAd(document, bidId);
- const error = 'Error trying to write ad. Ad render call ad id ' + bidId + ' was prevented from writing to the main document.';
+ const error = `Error rendering ad (id: ${bidId}): renderAd was prevented from writing to the main document.`;
assert.ok(spyLogError.calledWith(error), 'expected error was logged');
});
@@ -1326,14 +1330,14 @@ describe('Unit: Prebid Module', function () {
doc.write = sinon.stub().throws(error);
$$PREBID_GLOBAL$$.renderAd(doc, bidId);
- var errorMessage = 'Error trying to write ad Id :' + bidId + ' to the page:' + error.message;
+ var errorMessage = `Error rendering ad (id: ${bidId}): doc write error`
assert.ok(spyLogError.calledWith(errorMessage), 'expected error was logged');
});
it('should log an error when ad not found', function () {
var fakeId = 99;
$$PREBID_GLOBAL$$.renderAd(doc, fakeId);
- var error = 'Error trying to write ad. Cannot find ad by given id : ' + fakeId;
+ var error = `Error rendering ad (id: ${fakeId}): Cannot find ad '${fakeId}'`
assert.ok(spyLogError.calledWith(error), 'expected error was logged');
});
@@ -1345,14 +1349,6 @@ describe('Unit: Prebid Module', function () {
assert.deepEqual($$PREBID_GLOBAL$$.getAllWinningBids()[0], adResponse);
});
- it('should replace ${CLICKTHROUGH} macro in winning bids response', function () {
- pushBidResponseToAuction({
- ad: ""
- });
- $$PREBID_GLOBAL$$.renderAd(doc, bidId, {clickThrough: 'https://someadserverclickurl.com'});
- expect(adResponse).to.have.property('ad').and.to.match(/https:\/\/someadserverclickurl\.com/i);
- });
-
it('fires billing url if present on s2s bid', function () {
const burl = 'http://www.example.com/burl';
pushBidResponseToAuction({
@@ -1540,6 +1536,7 @@ describe('Unit: Prebid Module', function () {
}
},
transactionId: 'mock-tid',
+ adUnitId: 'mock-au',
bids: [
{bidder: BIDDER_CODE, params: {placementId: 'id'}},
]
@@ -1614,6 +1611,7 @@ describe('Unit: Prebid Module', function () {
height: 250,
adUnitCode: bidRequests[0].bids[0].adUnitCode,
transactionId: 'mock-tid',
+ adUnitId: 'mock-au',
adserverTargeting: {
'hb_bidder': BIDDER_CODE,
'hb_adid': bidId,
@@ -1692,7 +1690,8 @@ describe('Unit: Prebid Module', function () {
const bid = {
bidder: 'mock-bidder',
adUnitCode: adUnits[0].code,
- transactionId: adUnits[0].transactionId
+ transactionId: adUnits[0].transactionId,
+ adUnitId: adUnits[0].adUnitId,
}
requestBids({
adUnits,
@@ -1978,6 +1977,102 @@ describe('Unit: Prebid Module', function () {
.and.to.match(/[a-f0-9\-]{36}/i);
});
+ it('should use the same transactionID for ad units with the same code', () => {
+ $$PREBID_GLOBAL$$.requestBids({
+ adUnits: [
+ {
+ code: 'twin',
+ mediaTypes: { banner: { sizes: [] } },
+ bids: []
+ }, {
+ code: 'twin',
+ mediaTypes: { banner: { sizes: [] } },
+ bids: []
+ }
+ ]
+ });
+ const tid = auctionArgs.adUnits[0].transactionId;
+ expect(tid).to.exist;
+ expect(auctionArgs.adUnits[1].transactionId).to.eql(tid);
+ });
+
+ it('should re-use pub-provided transaction ID for ad units with the same code', () => {
+ $$PREBID_GLOBAL$$.requestBids({
+ adUnits: [
+ {
+ code: 'twin',
+ mediaTypes: { banner: { sizes: [] } },
+ bids: [],
+ }, {
+ code: 'twin',
+ mediaTypes: { banner: { sizes: [] } },
+ bids: [],
+ ortb2Imp: {
+ ext: {
+ tid: 'pub-tid'
+ }
+ }
+ }
+ ]
+ });
+ expect(auctionArgs.adUnits.map(au => au.transactionId)).to.eql(['pub-tid', 'pub-tid']);
+ });
+
+ it('should use pub-provided TIDs when they conflict for ad units with the same code', () => {
+ $$PREBID_GLOBAL$$.requestBids({
+ adUnits: [
+ {
+ code: 'twin',
+ mediaTypes: { banner: { sizes: [] } },
+ bids: [],
+ ortb2Imp: {
+ ext: {
+ tid: 't1'
+ }
+ }
+ }, {
+ code: 'twin',
+ mediaTypes: { banner: { sizes: [] } },
+ bids: [],
+ ortb2Imp: {
+ ext: {
+ tid: 't2'
+ }
+ }
+ }
+ ]
+ });
+ expect(auctionArgs.adUnits.map(au => au.transactionId)).to.eql(['t1', 't2']);
+ });
+
+ it('should generate unique adUnitId', () => {
+ $$PREBID_GLOBAL$$.requestBids({
+ adUnits: [
+ {
+ code: 'single',
+ mediaTypes: { banner: { sizes: [] } },
+ bids: []
+ }, {
+ code: 'twin',
+ mediaTypes: { banner: { sizes: [] } },
+ bids: []
+ },
+ {
+ code: 'twin',
+ mediaTypes: { banner: { sizes: [] } },
+ bids: []
+ }
+ ]
+ });
+
+ const ids = new Set();
+ auctionArgs.adUnits.forEach(au => {
+ expect(au.adUnitId).to.exist;
+ ids.add(au.adUnitId);
+ });
+ expect(ids.size).to.eql(3);
+ });
+
describe('transactionId', () => {
let adUnit;
beforeEach(() => {
@@ -2736,6 +2831,13 @@ describe('Unit: Prebid Module', function () {
events.on.restore();
});
+ it('should emit event BID_ACCEPTED when invoked', function () {
+ var callback = sinon.spy();
+ $$PREBID_GLOBAL$$.onEvent('bidAccepted', callback);
+ events.emit(CONSTANTS.EVENTS.BID_ACCEPTED);
+ sinon.assert.calledOnce(callback);
+ });
+
describe('beforeRequestBids', function () {
let bidRequestedHandler;
let beforeRequestBidsHandler;
@@ -3547,7 +3649,7 @@ describe('Unit: Prebid Module', function () {
{
code: 'adUnit-code-1',
mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] } },
- transactionId: '1234567890',
+ adUnitId: '1234567890',
bids: [
{ bidder: 'pubmatic', params: {placementId: '10433394'}, adUnitCode: 'adUnit-code-1' }
]
@@ -3556,15 +3658,15 @@ describe('Unit: Prebid Module', function () {
code: 'adUnit-code-2',
deferBilling: true,
mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] } },
- transactionId: '0987654321',
+ adUnitId: '0987654321',
bids: [
{ bidder: 'pubmatic', params: {placementId: '10433394'}, adUnitCode: 'adUnit-code-2' }
]
}
];
- let winningBid1 = { adapterCode: 'pubmatic', bidder: 'pubmatic', params: {placementId: '10433394'}, adUnitCode: 'adUnit-code-1', transactionId: '1234567890', adId: 'abcdefg' }
- let winningBid2 = { adapterCode: 'pubmatic', bidder: 'pubmatic', params: {placementId: '10433394'}, adUnitCode: 'adUnit-code-2', transactionId: '0987654321' }
+ let winningBid1 = { adapterCode: 'pubmatic', bidder: 'pubmatic', params: {placementId: '10433394'}, adUnitCode: 'adUnit-code-1', adUnitId: '1234567890', adId: 'abcdefg' }
+ let winningBid2 = { adapterCode: 'pubmatic', bidder: 'pubmatic', params: {placementId: '10433394'}, adUnitCode: 'adUnit-code-2', adUnitId: '0987654321' }
let adUnitCodes = ['adUnit-code-1', 'adUnit-code-2'];
let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 2000});
diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js
index 7d5f9af35dd..75813245298 100644
--- a/test/spec/unit/secureCreatives_spec.js
+++ b/test/spec/unit/secureCreatives_spec.js
@@ -1,6 +1,4 @@
-import {
- _sendAdToCreative, getReplier, receiveMessage
-} from 'src/secureCreatives.js';
+import {getReplier, receiveMessage} from 'src/secureCreatives.js';
import * as utils from 'src/utils.js';
import {getAdUnits, getBidRequests, getBidResponses} from 'test/fixtures/fixtures.js';
import {auctionManager} from 'src/auctionManager.js';
@@ -8,14 +6,25 @@ import * as auctionModule from 'src/auction.js';
import * as native from 'src/native.js';
import {fireNativeTrackers, getAllAssetsMessage} from 'src/native.js';
import * as events from 'src/events.js';
-import { config as configObj } from 'src/config.js';
+import {config as configObj} from 'src/config.js';
import 'src/prebid.js';
-import { expect } from 'chai';
+import {expect} from 'chai';
+import {handleRender} from '../../../src/adRendering.js';
var CONSTANTS = require('src/constants.json');
describe('secureCreatives', () => {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
function makeEvent(ev) {
return Object.assign({origin: 'mock-origin', ports: []}, ev)
}
@@ -54,37 +63,75 @@ describe('secureCreatives', () => {
});
});
- describe('_sendAdToCreative', () => {
- beforeEach(function () {
- sinon.stub(utils, 'logError');
- sinon.stub(utils, 'logWarn');
+ describe('handleRender', () => {
+ let bidResponse, renderFn, result;
+ beforeEach(() => {
+ result = null;
+ renderFn = sinon.stub().callsFake((r) => { result = r; });
+ bidResponse = {
+ adId: 123
+ }
});
- afterEach(function () {
- utils.logError.restore();
- utils.logWarn.restore();
+ describe('when the ad has a renderer', () => {
+ let bidResponse;
+ beforeEach(() => {
+ sandbox.stub(events, 'emit');
+ bidResponse = {
+ adId: 'mock-ad-id',
+ renderer: {
+ url: 'some-custom-renderer',
+ render: sinon.stub()
+ }
+ }
+ });
+
+ it('does not invoke renderFn, but the renderer instead', () => {
+ handleRender(renderFn, {bidResponse});
+ sinon.assert.notCalled(renderFn);
+ sinon.assert.called(bidResponse.renderer.render);
+ });
+
+ it('emits AD_RENDER_SUCCEDED', () => {
+ handleRender(renderFn, {bidResponse});
+ sinon.assert.calledWith(events.emit, CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED, sinon.match({
+ bid: bidResponse,
+ adId: bidResponse.adId
+ }));
+ });
+
+ it('emits AD_RENDER_FAILED', () => {
+ const err = new Error('error message');
+ bidResponse.renderer.render.throws(err);
+ handleRender(renderFn, {bidResponse});
+ sinon.assert.calledWith(events.emit, CONSTANTS.EVENTS.AD_RENDER_FAILED, sinon.match({
+ bid: bidResponse,
+ adId: bidResponse.adId,
+ reason: CONSTANTS.AD_RENDER_FAILED_REASON.EXCEPTION,
+ message: err.message
+ }));
+ })
});
- it('should macro replace ${AUCTION_PRICE} with the winning bid for ad and adUrl', () => {
- const oldVal = window.googletag;
- const oldapntag = window.apntag;
- window.apntag = null
- window.googletag = null;
- const mockAdObject = {
- adId: 'someAdId',
- ad: '',
- adUrl: 'http://creative.prebid.org/${AUCTION_PRICE}',
- width: 300,
- height: 250,
- renderer: null,
- cpm: '1.00',
- adUnitCode: 'some_dom_id'
- };
- const reply = sinon.spy();
- _sendAdToCreative(mockAdObject, reply);
- expect(reply.args[0][0].ad).to.equal('');
- expect(reply.args[0][0].adUrl).to.equal('http://creative.prebid.org/1.00');
- window.googletag = oldVal;
- window.apntag = oldapntag;
+
+ ['ad', 'adUrl'].forEach((prop) => {
+ describe(`on ${prop}`, () => {
+ it('replaces AUCTION_PRICE macro', () => {
+ bidResponse[prop] = 'pre${AUCTION_PRICE}post';
+ bidResponse.cpm = 123;
+ handleRender(renderFn, {adId: 123, bidResponse});
+ expect(result[prop]).to.eql('pre123post');
+ });
+ it('replaces CLICKTHROUGH macro', () => {
+ bidResponse[prop] = 'pre${CLICKTHROUGH}post';
+ handleRender(renderFn, {adId: 123, bidResponse, options: {clickUrl: 'clk'}});
+ expect(result[prop]).to.eql('preclkpost');
+ });
+ it('defaults CLICKTHROUGH to empty string', () => {
+ bidResponse[prop] = 'pre${CLICKTHROUGH}post';
+ handleRender(renderFn, {adId: 123, bidResponse});
+ expect(result[prop]).to.eql('prepost');
+ });
+ });
});
});
diff --git a/test/spec/unit/utils/ttlCollection_spec.js b/test/spec/unit/utils/ttlCollection_spec.js
index 29c6c438855..76cfa32d955 100644
--- a/test/spec/unit/utils/ttlCollection_spec.js
+++ b/test/spec/unit/utils/ttlCollection_spec.js
@@ -67,6 +67,33 @@ describe('ttlCollection', () => {
});
});
+ it('should run onExpiry when items are cleared', () => {
+ const i1 = {ttl: 1000, some: 'data'};
+ const i2 = {ttl: 2000, some: 'data'};
+ coll.add(i1);
+ coll.add(i2);
+ const cb = sinon.stub();
+ coll.onExpiry(cb);
+ return waitForPromises().then(() => {
+ clock.tick(500);
+ sinon.assert.notCalled(cb);
+ clock.tick(SLACK + 500);
+ sinon.assert.calledWith(cb, i1);
+ clock.tick(3000);
+ sinon.assert.calledWith(cb, i2);
+ })
+ });
+
+ it('should allow unregistration of onExpiry callbacks', () => {
+ const cb = sinon.stub();
+ coll.add({ttl: 500});
+ coll.onExpiry(cb)();
+ return waitForPromises().then(() => {
+ clock.tick(500 + SLACK);
+ sinon.assert.notCalled(cb);
+ })
+ })
+
it('should not wait too long if a shorter ttl shows up', () => {
coll.add({ttl: 4000});
coll.add({ttl: 1000});
diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js
index 098582c0af6..c84fe124db6 100644
--- a/test/spec/utils_spec.js
+++ b/test/spec/utils_spec.js
@@ -1002,6 +1002,15 @@ describe('Utils', function () {
const obj = {key: 'value'};
expect(deepEqual({outer: obj}, {outer: new Typed(obj)}, {checkTypes: true})).to.be.false;
});
+ it('should work when adding properties to the prototype of Array', () => {
+ after(function () {
+ // eslint-disable-next-line no-extend-native
+ delete Array.prototype.unitTestTempProp;
+ });
+ // eslint-disable-next-line no-extend-native
+ Array.prototype.unitTestTempProp = 'testing';
+ expect(deepEqual([], [])).to.be.true;
+ });
describe('cyrb53Hash', function() {
it('should return the same hash for the same string', function() {
diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js
index c746fdd2afd..fc6e71779cb 100644
--- a/test/spec/videoCache_spec.js
+++ b/test/spec/videoCache_spec.js
@@ -1,10 +1,10 @@
import chai from 'chai';
-import { getCacheUrl, store } from 'src/videoCache.js';
-import { config } from 'src/config.js';
-import { server } from 'test/mocks/xhr.js';
+import {getCacheUrl, store} from 'src/videoCache.js';
+import {config} from 'src/config.js';
+import {server} from 'test/mocks/xhr.js';
import {auctionManager} from '../../src/auctionManager.js';
import {AuctionIndex} from '../../src/auctionIndex.js';
-import { batchingCache } from '../../src/auction.js';
+import {batchingCache} from '../../src/auction.js';
const should = chai.should();
@@ -127,7 +127,7 @@ describe('The video cache', function () {
prebid.org wrapper
-
+
@@ -149,6 +149,20 @@ describe('The video cache', function () {
assertRequestMade({ vastUrl: 'my-mock-url.com', vastImpUrl: 'imptracker.com', ttl: 25 }, expectedValue)
});
+ it('should include multiple vastImpUrl when it\'s an array', function() {
+ const expectedValue = `
+
+
+ prebid.org wrapper
+
+
+
+
+
+ `;
+ assertRequestMade({ vastUrl: 'my-mock-url.com', vastImpUrl: ['https://vasttracking.mydomain.com/vast?cpm=1.2', 'imptracker.com'], ttl: 25, cpm: 1.2 }, expectedValue)
+ });
+
it('should make the expected request when store() is called on an ad with vastXml', function () {
const vastXml = '';
assertRequestMade({ vastXml: vastXml, ttl: 25 }, vastXml);
diff --git a/test/spec/video_spec.js b/test/spec/video_spec.js
index 35d0a4fef24..3252c58c687 100644
--- a/test/spec/video_spec.js
+++ b/test/spec/video_spec.js
@@ -82,10 +82,10 @@ describe('video.js', function () {
const bid = {
adId: '456xyz',
vastUrl: 'http://www.example.com/vastUrl',
- transactionId: 'au'
+ adUnitId: 'au'
};
const adUnits = [{
- transactionId: 'au',
+ adUnitId: 'au',
mediaTypes: {
video: {context: 'instream'}
}
@@ -96,10 +96,10 @@ describe('video.js', function () {
it('catches invalid instream bids', function () {
const bid = {
- transactionId: 'au'
+ adUnitId: 'au'
};
const adUnits = [{
- transactionId: 'au',
+ adUnitId: 'au',
mediaTypes: {
video: {context: 'instream'}
}
@@ -110,26 +110,26 @@ describe('video.js', function () {
it('catches invalid bids when prebid-cache is disabled', function () {
const adUnits = [{
- transactionId: 'au',
+ adUnitId: 'au',
bidder: 'vastOnlyVideoBidder',
mediaTypes: {video: {}},
}];
- const valid = isValidVideoBid({ transactionId: 'au', vastXml: 'vast' }, {index: stubAuctionIndex({adUnits})});
+ const valid = isValidVideoBid({ adUnitId: 'au', vastXml: 'vast' }, {index: stubAuctionIndex({adUnits})});
expect(valid).to.equal(false);
});
it('validates valid outstream bids', function () {
const bid = {
- transactionId: 'au',
+ adUnitId: 'au',
renderer: {
url: 'render.url',
render: () => true,
}
};
const adUnits = [{
- transactionId: 'au',
+ adUnitId: 'au',
mediaTypes: {
video: {context: 'outstream'}
}
@@ -140,10 +140,10 @@ describe('video.js', function () {
it('validates valid outstream bids with a publisher defined renderer', function () {
const bid = {
- transactionId: 'au',
+ adUnitId: 'au',
};
const adUnits = [{
- transactionId: 'au',
+ adUnitId: 'au',
mediaTypes: {
video: {
context: 'outstream',
@@ -160,10 +160,10 @@ describe('video.js', function () {
it('catches invalid outstream bids', function () {
const bid = {
- transactionId: 'au',
+ adUnitId: 'au',
};
const adUnits = [{
- transactionId: 'au',
+ adUnitId: 'au',
mediaTypes: {
video: {context: 'outstream'}
}
diff --git a/wdio.conf.js b/wdio.conf.js
index 3d93f909971..d23fecd0b15 100644
--- a/wdio.conf.js
+++ b/wdio.conf.js
@@ -1,3 +1,5 @@
+const shared = require('./wdio.shared.conf.js');
+
const browsers = Object.fromEntries(
Object.entries(require('./browsers.json'))
.filter(([k, v]) => {
@@ -35,14 +37,7 @@ function getCapabilities() {
}
exports.config = {
- specs: [
- './test/spec/e2e/**/*.spec.js',
- ],
- exclude: [
- // TODO: decipher original intent for "longform" tests
- // they all appear to be almost exact copies
- './test/spec/e2e/longform/**/*'
- ],
+ ...shared.config,
services: [
['browserstack', {
browserstackLocal: true
@@ -53,17 +48,4 @@ exports.config = {
maxInstances: 5, // Do not increase this, since we have only 5 parallel tests in browserstack account
maxInstancesPerCapability: 1,
capabilities: getCapabilities(),
- logLevel: 'info', // put option here: info | trace | debug | warn| error | silent
- bail: 0,
- waitforTimeout: 60000, // Default timeout for all waitFor* commands.
- connectionRetryTimeout: 60000, // Default timeout in milliseconds for request if Selenium Grid doesn't send response
- connectionRetryCount: 3, // Default request retries count
- framework: 'mocha',
- mochaOpts: {
- ui: 'bdd',
- timeout: 60000,
- compilers: ['js:babel-register'],
- },
- // if you see error, update this to spec reporter and logLevel above to get detailed report.
- reporters: ['spec']
}
diff --git a/wdio.local.conf.js b/wdio.local.conf.js
new file mode 100644
index 00000000000..772448472bf
--- /dev/null
+++ b/wdio.local.conf.js
@@ -0,0 +1,13 @@
+const shared = require('./wdio.shared.conf.js');
+
+exports.config = {
+ ...shared.config,
+ capabilities: [
+ {
+ browserName: 'chrome',
+ 'goog:chromeOptions': {
+ args: ['headless', 'disable-gpu'],
+ },
+ },
+ ],
+};
diff --git a/wdio.shared.conf.js b/wdio.shared.conf.js
new file mode 100644
index 00000000000..34e1ee9c675
--- /dev/null
+++ b/wdio.shared.conf.js
@@ -0,0 +1,23 @@
+exports.config = {
+ specs: [
+ './test/spec/e2e/**/*.spec.js',
+ ],
+ exclude: [
+ // TODO: decipher original intent for "longform" tests
+ // they all appear to be almost exact copies
+ './test/spec/e2e/longform/**/*'
+ ],
+ logLevel: 'info', // put option here: info | trace | debug | warn| error | silent
+ bail: 0,
+ waitforTimeout: 60000, // Default timeout for all waitFor* commands.
+ connectionRetryTimeout: 60000, // Default timeout in milliseconds for request if Selenium Grid doesn't send response
+ connectionRetryCount: 3, // Default request retries count
+ framework: 'mocha',
+ mochaOpts: {
+ ui: 'bdd',
+ timeout: 60000,
+ compilers: ['js:babel-register'],
+ },
+ // if you see error, update this to spec reporter and logLevel above to get detailed report.
+ reporters: ['spec']
+}
diff --git a/webpack.creative.js b/webpack.creative.js
new file mode 100644
index 00000000000..7279455e155
--- /dev/null
+++ b/webpack.creative.js
@@ -0,0 +1,19 @@
+const path = require('path');
+
+module.exports = {
+ mode: 'production',
+ resolve: {
+ modules: [
+ path.resolve('.'),
+ 'node_modules'
+ ],
+ },
+ entry: {
+ 'creative': {
+ import: './libraries/creativeRender/crossDomain.js',
+ },
+ },
+ output: {
+ path: path.resolve('./build/creative'),
+ },
+}