"
+ const mockServerResponse = {
+ body: [
+ {
+ requestId: '23a3d87fb6bde9',
+ cpm: 1.61,
+ currency: 'USD',
+ width: '336',
+ height: '280',
+ creativeId: '46271',
+ netRevenue: 'false',
+ ad: MOCK_AD_DOM,
+ meta: {
+ advertiserDomains: [''],
+ },
+ ttl: 360,
+ },
+ {
+ requestId: '3ce3efc40c890b',
+ cpm: 1.61,
+ currency: 'USD',
+ width: '336',
+ height: '280',
+ creativeId: '46271',
+ netRevenue: 'false',
+ ad: MOCK_AD_DOM,
+ meta: {
+ advertiserDomains: [''],
+ },
+ ttl: 360,
+ },
+ ],
+ };
+
+ const exceptServerResponse = [
+ {
+ requestId: '23a3d87fb6bde9',
+ cpm: 1.61,
+ currency: 'USD',
+ width: '336',
+ height: '280',
+ creativeId: '46271',
+ netRevenue: 'false',
+ ad: MOCK_AD_DOM,
+ meta: {
+ advertiserDomains: [''],
+ },
+ ttl: 360,
+ },
+ {
+ requestId: '3ce3efc40c890b',
+ cpm: 1.61,
+ currency: 'USD',
+ width: '336',
+ height: '280',
+ creativeId: '46271',
+ netRevenue: 'false',
+ ad: MOCK_AD_DOM,
+ meta: {
+ advertiserDomains: [''],
+ },
+ ttl: 360,
+ },
+ ]
+
+ const bidResponses = spec.interpretResponse(mockServerResponse);
+
+ expect(bidResponses).to.eql(exceptServerResponse);
+ });
+ });
+});
diff --git a/test/spec/modules/adagioAnalyticsAdapter_spec.js b/test/spec/modules/adagioAnalyticsAdapter_spec.js
index 581f3cb1b87..5ffd7b0b685 100644
--- a/test/spec/modules/adagioAnalyticsAdapter_spec.js
+++ b/test/spec/modules/adagioAnalyticsAdapter_spec.js
@@ -1,12 +1,14 @@
import adagioAnalyticsAdapter from 'modules/adagioAnalyticsAdapter.js';
import { expect } from 'chai';
import * as utils from 'src/utils.js';
+import { getGlobal } from 'src/prebidGlobal.js';
+import { server } from 'test/mocks/xhr.js';
let adapterManager = require('src/adapterManager').default;
let events = require('src/events');
let constants = require('src/constants.json');
-describe('adagio analytics adapter', () => {
+describe('adagio analytics adapter - adagio.js', () => {
let sandbox;
let adagioQueuePushSpy;
@@ -174,3 +176,658 @@ describe('adagio analytics adapter', () => {
});
});
});
+
+const AUCTION_ID = '25c6d7f5-699a-4bfc-87c9-996f915341fa';
+const AUCTION_ID_ADAGIO = '6fc53663-bde5-427b-ab63-baa9ed296f47'
+const AUCTION_ID_CACHE = 'b43d24a0-13d4-406d-8176-3181402bafc4';
+const AUCTION_ID_CACHE_ADAGIO = 'a9cae98f-efb5-477e-9259-27350044f8db';
+
+const BID_ADAGIO = Object.assign({}, BID_ADAGIO, {
+ bidder: 'adagio',
+ auctionId: AUCTION_ID,
+ adUnitCode: '/19968336/header-bid-tag-1',
+ bidId: '3bd4ebb1c900e2',
+ partnerImpId: 'partnerImpressionID-2',
+ adId: 'fake_ad_id_2',
+ requestId: '3bd4ebb1c900e2',
+ width: 728,
+ height: 90,
+ mediaType: 'banner',
+ cpm: 1.42,
+ currency: 'USD',
+ originalCpm: 1.42,
+ originalCurrency: 'USD',
+ dealId: 'the-deal-id',
+ dealChannel: 'PMP',
+ mi: 'matched-impression',
+ seatBidId: 'aaaa-bbbb-cccc-dddd',
+ adserverTargeting: {
+ 'hb_bidder': 'another',
+ 'hb_adid': '3bd4ebb1c900e2',
+ 'hb_pb': '1.500',
+ 'hb_size': '728x90',
+ 'hb_source': 'server'
+ },
+ meta: {
+ advertiserDomains: ['example.com']
+ },
+ pba: {
+ sid: '42',
+ e_pba_test: true
+ }
+});
+
+const BID_ANOTHER = Object.assign({}, BID_ANOTHER, {
+ bidder: 'another',
+ auctionId: AUCTION_ID,
+ adUnitCode: '/19968336/header-bid-tag-1',
+ bidId: '3bd4ebb1c900e2',
+ partnerImpId: 'partnerImpressionID-2',
+ adId: 'fake_ad_id_2',
+ requestId: '3bd4ebb1c900e2',
+ width: 728,
+ height: 90,
+ mediaType: 'banner',
+ cpm: 1.71,
+ currency: 'EUR',
+ originalCpm: 1.62,
+ originalCurrency: 'GBP',
+ dealId: 'the-deal-id',
+ dealChannel: 'PMP',
+ mi: 'matched-impression',
+ seatBidId: 'aaaa-bbbb-cccc-dddd',
+ adserverTargeting: {
+ 'hb_bidder': 'another',
+ 'hb_adid': '3bd4ebb1c900e2',
+ 'hb_pb': '1.500',
+ 'hb_size': '728x90',
+ 'hb_source': 'server'
+ },
+ meta: {
+ advertiserDomains: ['example.com']
+ }
+});
+
+const BID_CACHED = Object.assign({}, BID_ADAGIO, {
+ auctionId: AUCTION_ID_CACHE,
+ latestTargetedAuctionId: BID_ADAGIO.auctionId,
+});
+
+const PARAMS_ADG = {
+ organizationId: '1001',
+ site: 'test-com',
+ pageviewId: 'a68e6d70-213b-496c-be0a-c468ff387106',
+ environment: 'desktop',
+ pagetype: 'article',
+ placement: 'pave_top',
+ testName: 'test',
+ testVersion: 'version',
+};
+
+const AUCTION_INIT_ANOTHER = {
+ 'auctionId': AUCTION_ID,
+ 'timestamp': 1519767010567,
+ 'auctionStatus': 'inProgress',
+ 'adUnits': [ {
+ 'code': '/19968336/header-bid-tag-1',
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [
+ [
+ 640,
+ 480
+ ],
+ [
+ 640,
+ 100
+ ]
+ ]
+ }
+ },
+ 'sizes': [[640, 480]],
+ 'bids': [ {
+ 'bidder': 'another',
+ 'params': {
+ 'publisherId': '1001'
+ },
+ }, {
+ 'bidder': 'nobid',
+ 'params': {
+ 'publisherId': '1002'
+ },
+ }, {
+ 'bidder': 'adagio',
+ 'params': {
+ ...PARAMS_ADG
+ },
+ }, ],
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014'
+ }, {
+ 'code': '/19968336/footer-bid-tag-1',
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [
+ [
+ 640,
+ 480
+ ]
+ ]
+ }
+ },
+ 'sizes': [[640, 480]],
+ 'bids': [ {
+ 'bidder': 'another',
+ 'params': {
+ 'publisherId': '1001'
+ },
+ } ],
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014'
+ } ],
+ 'adUnitCodes': ['/19968336/header-bid-tag-1', '/19968336/footer-bid-tag-1'],
+ 'bidderRequests': [ {
+ 'bidderCode': 'another',
+ 'auctionId': AUCTION_ID,
+ 'bidderRequestId': '1be65d7958826a',
+ 'bids': [ {
+ 'bidder': 'another',
+ 'params': {
+ 'publisherId': '1001',
+ },
+ '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': AUCTION_ID,
+ 'src': 'client',
+ 'bidRequestsCount': 1
+ }, {
+ 'bidder': 'another',
+ 'params': {
+ 'publisherId': '1001'
+ },
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [[640, 480]]
+ }
+ },
+ 'adUnitCode': '/19968336/footer-bid-tag-1',
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014',
+ 'sizes': [[640, 480]],
+ 'bidId': '2ecff0db240757',
+ 'bidderRequestId': '1be65d7958826a',
+ 'auctionId': AUCTION_ID,
+ 'src': 'client',
+ 'bidRequestsCount': 1
+ }, {
+ 'bidder': 'nobid',
+ 'params': {
+ 'publisherId': '1001'
+ },
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [[640, 480]]
+ }
+ },
+ 'adUnitCode': '/19968336/footer-bid-tag-1',
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014',
+ 'sizes': [[640, 480]],
+ 'bidId': '2ecff0db240757',
+ 'bidderRequestId': '1be65d7958826a',
+ 'auctionId': AUCTION_ID,
+ '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']
+ }
+ }, {
+ 'bidderCode': 'adagio',
+ 'auctionId': AUCTION_ID,
+ 'bidderRequestId': '1be65d7958826a',
+ 'bids': [ {
+ 'bidder': 'adagio',
+ 'params': {
+ ...PARAMS_ADG,
+ adagioAuctionId: AUCTION_ID_ADAGIO
+ },
+ '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': AUCTION_ID,
+ '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 AUCTION_INIT_CACHE = {
+ 'auctionId': AUCTION_ID_CACHE,
+ 'timestamp': 1519767010567,
+ 'auctionStatus': 'inProgress',
+ 'adUnits': [ {
+ 'code': '/19968336/header-bid-tag-1',
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [
+ [
+ 640,
+ 480
+ ],
+ [
+ 640,
+ 100
+ ]
+ ]
+ }
+ },
+ 'sizes': [[640, 480]],
+ 'bids': [ {
+ 'bidder': 'another',
+ 'params': {
+ 'publisherId': '1001'
+ },
+ }, {
+ 'bidder': 'adagio',
+ 'params': {
+ ...PARAMS_ADG
+ },
+ }, ],
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014'
+ }, {
+ 'code': '/19968336/footer-bid-tag-1',
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [
+ [
+ 640,
+ 480
+ ]
+ ]
+ }
+ },
+ 'sizes': [[640, 480]],
+ 'bids': [ {
+ 'bidder': 'another',
+ 'params': {
+ 'publisherId': '1001'
+ },
+ } ],
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014'
+ } ],
+ 'adUnitCodes': ['/19968336/header-bid-tag-1', '/19968336/footer-bid-tag-1'],
+ 'bidderRequests': [ {
+ 'bidderCode': 'another',
+ 'auctionId': AUCTION_ID_CACHE,
+ 'bidderRequestId': '1be65d7958826a',
+ 'bids': [ {
+ 'bidder': 'another',
+ 'params': {
+ 'publisherId': '1001',
+ },
+ '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': AUCTION_ID_CACHE,
+ 'src': 'client',
+ 'bidRequestsCount': 1
+ }, {
+ 'bidder': 'another',
+ 'params': {
+ 'publisherId': '1001'
+ },
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [[640, 480]]
+ }
+ },
+ 'adUnitCode': '/19968336/footer-bid-tag-1',
+ 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014',
+ 'sizes': [[640, 480]],
+ 'bidId': '2ecff0db240757',
+ 'bidderRequestId': '1be65d7958826a',
+ 'auctionId': AUCTION_ID_CACHE,
+ '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']
+ }
+ }, {
+ 'bidderCode': 'adagio',
+ 'auctionId': AUCTION_ID_CACHE,
+ 'bidderRequestId': '1be65d7958826a',
+ 'bids': [ {
+ 'bidder': 'adagio',
+ 'params': {
+ ...PARAMS_ADG,
+ adagioAuctionId: AUCTION_ID_CACHE_ADAGIO
+ },
+ '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': AUCTION_ID_CACHE,
+ '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 AUCTION_END_ANOTHER = Object.assign({}, AUCTION_INIT_ANOTHER, {
+ bidsReceived: [BID_ANOTHER, BID_ADAGIO]
+});
+
+const AUCTION_END_ANOTHER_NOBID = Object.assign({}, AUCTION_INIT_ANOTHER, {
+ bidsReceived: []
+});
+
+const MOCK = {
+ SET_TARGETING: {
+ [BID_ADAGIO.adUnitCode]: BID_ADAGIO.adserverTargeting,
+ [BID_ANOTHER.adUnitCode]: BID_ANOTHER.adserverTargeting
+ },
+ AUCTION_INIT: {
+ another: AUCTION_INIT_ANOTHER,
+ bidcached: AUCTION_INIT_CACHE
+ },
+ BID_RESPONSE: {
+ adagio: BID_ADAGIO,
+ another: BID_ANOTHER
+ },
+ AUCTION_END: {
+ another: AUCTION_END_ANOTHER,
+ another_nobid: AUCTION_END_ANOTHER_NOBID
+ },
+ BID_WON: {
+ adagio: Object.assign({}, BID_ADAGIO, {
+ 'status': 'rendered'
+ }),
+ another: Object.assign({}, BID_ANOTHER, {
+ 'status': 'rendered'
+ }),
+ bidcached: Object.assign({}, BID_CACHED, {
+ 'status': 'rendered'
+ }),
+ },
+ AD_RENDER_SUCCEEDED: {
+ another: {
+ ad: '
ad
',
+ adId: 'fake_ad_id_2',
+ bid: BID_ANOTHER
+ },
+ bidcached: {
+ ad: '
ad
',
+ adId: 'fake_ad_id_2',
+ bid: BID_CACHED
+ }
+ },
+ AD_RENDER_FAILED: {
+ bidcached: {
+ adId: 'fake_ad_id_2',
+ bid: BID_CACHED
+ }
+ }
+};
+
+describe('adagio analytics adapter', () => {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+
+ sandbox.stub(events, 'getEvents').returns([]);
+
+ adapterManager.registerAnalyticsAdapter({
+ code: 'adagio',
+ adapter: adagioAnalyticsAdapter
+ });
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ describe('track', () => {
+ beforeEach(() => {
+ adapterManager.enableAnalytics({
+ provider: 'adagio'
+ });
+ });
+
+ afterEach(() => {
+ adagioAnalyticsAdapter.disableAnalytics();
+ });
+
+ it('builds and sends auction data', () => {
+ getGlobal().convertCurrency = (cpm, from, to) => {
+ const convKeys = {
+ 'GBP-EUR': 0.7,
+ 'EUR-GBP': 1.3,
+ 'USD-EUR': 0.8,
+ 'EUR-USD': 1.2,
+ 'USD-GBP': 0.6,
+ 'GBP-USD': 1.6,
+ };
+ return cpm * (convKeys[`${from}-${to}`] || 1);
+ };
+
+ events.emit(constants.EVENTS.AUCTION_INIT, MOCK.AUCTION_INIT.another);
+ events.emit(constants.EVENTS.BID_RESPONSE, MOCK.BID_RESPONSE.adagio);
+ events.emit(constants.EVENTS.BID_RESPONSE, MOCK.BID_RESPONSE.another);
+ events.emit(constants.EVENTS.AUCTION_END, MOCK.AUCTION_END.another);
+ events.emit(constants.EVENTS.BID_WON, MOCK.BID_WON.another);
+ events.emit(constants.EVENTS.AD_RENDER_SUCCEEDED, MOCK.AD_RENDER_SUCCEEDED.another);
+
+ expect(server.requests.length).to.equal(3, 'requests count');
+ {
+ const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[0].url);
+ expect(protocol).to.equal('https');
+ expect(hostname).to.equal('c.4dex.io');
+ expect(pathname).to.equal('/pba.gif');
+ expect(search.v).to.equal('1');
+ expect(search.pbjsv).to.equal('$prebid.version$');
+ expect(search.auct_id).to.equal(AUCTION_ID_ADAGIO);
+ expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
+ expect(search.org_id).to.equal('1001');
+ expect(search.site).to.equal('test-com');
+ expect(search.pv_id).to.equal('a68e6d70-213b-496c-be0a-c468ff387106');
+ expect(search.url_dmn).to.equal(window.location.hostname);
+ expect(search.pgtyp).to.equal('article');
+ expect(search.plcmt).to.equal('pave_top');
+ expect(search.mts).to.equal('ban');
+ expect(search.ban_szs).to.equal('640x100,640x480');
+ expect(search.bdrs).to.equal('adagio,another,nobid');
+ expect(search.adg_mts).to.equal('ban');
+ }
+
+ {
+ const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[1].url);
+ expect(protocol).to.equal('https');
+ expect(hostname).to.equal('c.4dex.io');
+ expect(pathname).to.equal('/pba.gif');
+ expect(search.v).to.equal('2');
+ expect(search.e_sid).to.equal('42');
+ expect(search.e_pba_test).to.equal('true');
+ expect(search.bdrs_bid).to.equal('1,1,0');
+ }
+
+ {
+ const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[2].url);
+ expect(protocol).to.equal('https');
+ expect(hostname).to.equal('c.4dex.io');
+ expect(pathname).to.equal('/pba.gif');
+ expect(search.v).to.equal('3');
+ expect(search.auct_id).to.equal(AUCTION_ID_ADAGIO);
+ expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
+ expect(search.win_bdr).to.equal('another');
+ expect(search.win_mt).to.equal('ban');
+ expect(search.win_ban_sz).to.equal('728x90');
+ expect(search.win_cpm).to.equal('1.71');
+ expect(search.cur).to.equal('EUR');
+ expect(search.cur_rate).to.equal('1.2');
+ expect(search.og_cpm).to.equal('1.62');
+ expect(search.og_cur).to.equal('GBP');
+ expect(search.og_cur_rate).to.equal('1.6');
+ }
+ });
+
+ it('builds and sends auction data with a cached bid win', () => {
+ getGlobal().convertCurrency = (cpm, from, to) => {
+ const convKeys = {
+ 'GBP-EUR': 0.7,
+ 'EUR-GBP': 1.3,
+ 'USD-EUR': 0.8,
+ 'EUR-USD': 1.2,
+ 'USD-GBP': 0.6,
+ 'GBP-USD': 1.6,
+ };
+ return cpm * (convKeys[`${from}-${to}`] || 1);
+ };
+
+ events.emit(constants.EVENTS.AUCTION_INIT, MOCK.AUCTION_INIT.bidcached);
+ events.emit(constants.EVENTS.AUCTION_INIT, MOCK.AUCTION_INIT.another);
+ events.emit(constants.EVENTS.BID_RESPONSE, MOCK.BID_RESPONSE.adagio);
+ events.emit(constants.EVENTS.BID_RESPONSE, MOCK.BID_RESPONSE.another);
+ events.emit(constants.EVENTS.AUCTION_END, MOCK.AUCTION_END.another_nobid);
+ events.emit(constants.EVENTS.BID_WON, MOCK.BID_WON.bidcached);
+ events.emit(constants.EVENTS.AD_RENDER_FAILED, MOCK.AD_RENDER_FAILED.bidcached);
+
+ expect(server.requests.length).to.equal(5, 'requests count');
+ {
+ const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[0].url);
+ expect(protocol).to.equal('https');
+ expect(hostname).to.equal('c.4dex.io');
+ expect(pathname).to.equal('/pba.gif');
+ expect(search.v).to.equal('1');
+ expect(search.pbjsv).to.equal('$prebid.version$');
+ expect(search.auct_id).to.equal(AUCTION_ID_CACHE_ADAGIO);
+ expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
+ expect(search.org_id).to.equal('1001');
+ expect(search.site).to.equal('test-com');
+ expect(search.pv_id).to.equal('a68e6d70-213b-496c-be0a-c468ff387106');
+ expect(search.url_dmn).to.equal(window.location.hostname);
+ expect(search.pgtyp).to.equal('article');
+ expect(search.plcmt).to.equal('pave_top');
+ expect(search.mts).to.equal('ban');
+ expect(search.ban_szs).to.equal('640x100,640x480');
+ expect(search.bdrs).to.equal('adagio,another');
+ expect(search.adg_mts).to.equal('ban');
+ expect(search.t_n).to.equal('test');
+ expect(search.t_v).to.equal('version');
+ }
+
+ {
+ const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[1].url);
+ expect(protocol).to.equal('https');
+ expect(hostname).to.equal('c.4dex.io');
+ expect(pathname).to.equal('/pba.gif');
+ expect(search.v).to.equal('1');
+ expect(search.pbjsv).to.equal('$prebid.version$');
+ expect(search.auct_id).to.equal(AUCTION_ID_ADAGIO);
+ expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
+ expect(search.org_id).to.equal('1001');
+ expect(search.site).to.equal('test-com');
+ expect(search.pv_id).to.equal('a68e6d70-213b-496c-be0a-c468ff387106');
+ expect(search.url_dmn).to.equal(window.location.hostname);
+ expect(search.pgtyp).to.equal('article');
+ expect(search.plcmt).to.equal('pave_top');
+ expect(search.mts).to.equal('ban');
+ expect(search.ban_szs).to.equal('640x100,640x480');
+ expect(search.bdrs).to.equal('adagio,another,nobid');
+ expect(search.adg_mts).to.equal('ban');
+ }
+
+ {
+ const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[2].url);
+ expect(protocol).to.equal('https');
+ expect(hostname).to.equal('c.4dex.io');
+ expect(pathname).to.equal('/pba.gif');
+ expect(search.v).to.equal('2');
+ expect(search.e_sid).to.equal('42');
+ expect(search.e_pba_test).to.equal('true');
+ expect(search.bdrs_bid).to.equal('0,0,0');
+ }
+
+ {
+ const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[3].url);
+ expect(protocol).to.equal('https');
+ expect(hostname).to.equal('c.4dex.io');
+ expect(pathname).to.equal('/pba.gif');
+ expect(search.v).to.equal('3');
+ expect(search.auct_id).to.equal(AUCTION_ID_ADAGIO);
+ expect(search.auct_id_c).to.equal(AUCTION_ID_CACHE_ADAGIO);
+ expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
+ expect(search.win_bdr).to.equal('adagio');
+ expect(search.win_mt).to.equal('ban');
+ expect(search.win_ban_sz).to.equal('728x90');
+ expect(search.win_cpm).to.equal('1.42');
+ expect(search.cur).to.equal('USD');
+ expect(search.cur_rate).to.equal('1');
+ expect(search.og_cpm).to.equal('1.42');
+ expect(search.og_cur).to.equal('USD');
+ expect(search.og_cur_rate).to.equal('1');
+ expect(search.rndr).to.not.exist;
+ }
+
+ {
+ const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[4].url);
+ expect(protocol).to.equal('https');
+ expect(hostname).to.equal('c.4dex.io');
+ expect(pathname).to.equal('/pba.gif');
+ expect(search.v).to.equal('4');
+ expect(search.auct_id).to.equal(AUCTION_ID_ADAGIO);
+ expect(search.auct_id_c).to.equal(AUCTION_ID_CACHE_ADAGIO);
+ expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
+ expect(search.rndr).to.equal('0');
+ }
+ });
+ });
+});
diff --git a/test/spec/modules/adagioBidAdapter_spec.js b/test/spec/modules/adagioBidAdapter_spec.js
index 1f734a6a7fc..744f3c69e83 100644
--- a/test/spec/modules/adagioBidAdapter_spec.js
+++ b/test/spec/modules/adagioBidAdapter_spec.js
@@ -861,11 +861,6 @@ describe('Adagio bid adapter', () => {
}
const requests = spec.buildRequests([bid01], bidderRequest);
- expect(requests[0].data.adUnits[0].floors.length).to.equal(3);
- expect(requests[0].data.adUnits[0].floors[0]).to.deep.equal({f: 1, mt: 'banner', s: '300x250'});
- expect(requests[0].data.adUnits[0].floors[1]).to.deep.equal({f: 1, mt: 'banner', s: '300x600'});
- expect(requests[0].data.adUnits[0].floors[2]).to.deep.equal({f: 1, mt: 'video', s: '600x480'});
-
expect(requests[0].data.adUnits[0].mediaTypes.banner.sizes.length).to.equal(2);
expect(requests[0].data.adUnits[0].mediaTypes.banner.bannerSizes[0]).to.deep.equal({size: [300, 250], floor: 1});
expect(requests[0].data.adUnits[0].mediaTypes.banner.bannerSizes[1]).to.deep.equal({size: [300, 600], floor: 1});
@@ -890,10 +885,6 @@ describe('Adagio bid adapter', () => {
}
const requests = spec.buildRequests([bid01], bidderRequest);
- expect(requests[0].data.adUnits[0].floors.length).to.equal(2);
- expect(requests[0].data.adUnits[0].floors[0]).to.deep.equal({f: 1, mt: 'video'});
- expect(requests[0].data.adUnits[0].floors[1]).to.deep.equal({f: 1, mt: 'native'});
-
expect(requests[0].data.adUnits[0].mediaTypes.video.floor).to.equal(1);
expect(requests[0].data.adUnits[0].mediaTypes.native.floor).to.equal(1);
});
@@ -913,8 +904,6 @@ describe('Adagio bid adapter', () => {
}
const requests = spec.buildRequests([bid01], bidderRequest);
- expect(requests[0].data.adUnits[0].floors.length).to.equal(1);
- expect(requests[0].data.adUnits[0].floors[0]).to.deep.equal({mt: 'video'});
expect(requests[0].data.adUnits[0].mediaTypes.video.floor).to.be.undefined;
});
});
@@ -958,6 +947,34 @@ describe('Adagio bid adapter', () => {
expect(requests[0].data.usIfr).to.equal(false);
});
});
+
+ describe('with GPID', function () {
+ const gpid = '/12345/my-gpt-tag-0';
+
+ it('should add preferred gpid to the request', function () {
+ const bid01 = new BidRequestBuilder().withParams().build();
+ bid01.ortb2Imp = {
+ ext: {
+ gpid: gpid
+ }
+ };
+ const bidderRequest = new BidderRequestBuilder().build();
+ const requests = spec.buildRequests([bid01], bidderRequest);
+ expect(requests[0].data.adUnits[0].gpid).to.exist.and.equal(gpid);
+ });
+
+ it('should add backup gpid to the request', function () {
+ const bid01 = new BidRequestBuilder().withParams().build();
+ bid01.ortb2Imp = {
+ ext: {
+ data: { pbadslot: gpid }
+ }
+ };
+ const bidderRequest = new BidderRequestBuilder().build();
+ const requests = spec.buildRequests([bid01], bidderRequest);
+ expect(requests[0].data.adUnits[0].gpid).to.exist.and.equal(gpid);
+ });
+ });
});
describe('interpretResponse()', function() {
diff --git a/test/spec/modules/adfusionBidAdapter_spec.js b/test/spec/modules/adfusionBidAdapter_spec.js
new file mode 100644
index 00000000000..638831c33f3
--- /dev/null
+++ b/test/spec/modules/adfusionBidAdapter_spec.js
@@ -0,0 +1,97 @@
+import { expect } from 'chai';
+import { spec } from 'modules/adfusionBidAdapter';
+import 'modules/priceFloors.js';
+import { newBidder } from 'src/adapters/bidderFactory';
+
+describe('adfusionBidAdapter', function () {
+ const adapter = newBidder(spec);
+ describe('inherited functions', function () {
+ it('exists and is a function', function () {
+ expect(adapter.callBids).to.exist.and.to.be.a('function');
+ });
+ });
+
+ describe('isBidRequestValid', function () {
+ const bid = {
+ bidder: 'adfusion',
+ params: {
+ accountId: 1234,
+ },
+ adUnitCode: '/adunit-code/test-path',
+ bidId: 'test-bid-id-1',
+ bidderRequestId: 'test-bid-request-1',
+ auctionId: 'test-auction-1',
+ transactionId: 'test-transactionId-1',
+ };
+
+ it('should return true when required params found', function () {
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+
+ it('should return false when params.accountID is missing', function () {
+ let localbid = Object.assign({}, bid);
+ delete localbid.params.accountId;
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ });
+
+ describe('buildRequests', function () {
+ let bidRequests, bidderRequest;
+ beforeEach(function () {
+ bidRequests = [
+ {
+ bidder: 'adfusion',
+ params: {
+ accountId: 1234,
+ },
+ 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',
+ },
+ {
+ bidder: 'adfusion',
+ params: {
+ accountId: 1234,
+ },
+ adUnitCode: 'adunit-code',
+ mediaTypes: {
+ video: {
+ playerSize: [640, 480],
+ },
+ },
+ bidId: 'test-bid-id-2',
+ bidderRequestId: 'test-bid-request-2',
+ auctionId: 'test-auction-2',
+ transactionId: 'test-transactionId-2',
+ },
+ ];
+ bidderRequest = { refererInfo: {} };
+ });
+
+ it('should return an empty array when no bid requests', function () {
+ const bidRequest = spec.buildRequests([], 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(bidRequests, bidderRequest);
+ expect(request).to.be.an('array');
+ expect(request[0].data).to.be.an('object');
+ expect(request[0].method).to.equal('POST');
+ expect(request[0].url).to.not.equal('');
+ expect(request[0].url).to.not.equal(undefined);
+ expect(request[0].url).to.not.equal(null);
+ });
+ });
+});
diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js
index 90200a801c5..ade34478c20 100644
--- a/test/spec/modules/adkernelBidAdapter_spec.js
+++ b/test/spec/modules/adkernelBidAdapter_spec.js
@@ -15,11 +15,13 @@ describe('Adkernel adapter', function () {
auctionId: 'auc-001',
mediaTypes: {
banner: {
- sizes: [[300, 250], [300, 200]]
+ sizes: [[300, 250], [300, 200]],
+ pos: 1
}
},
ortb2Imp: {
- battr: [6, 7, 9]
+ battr: [6, 7, 9],
+ pos: 2
}
}, bid2_zone2 = {
bidder: 'adkernel',
@@ -103,7 +105,11 @@ describe('Adkernel adapter', function () {
video: {
context: 'instream',
playerSize: [[640, 480]],
- api: [1, 2]
+ api: [1, 2],
+ placement: 1,
+ plcmt: 1,
+ skip: 1,
+ pos: 1
}
},
adUnitCode: 'ad-unit-1'
@@ -244,6 +250,31 @@ describe('Adkernel adapter', function () {
}],
bidid: 'pTuOlf5KHUo',
cur: 'EUR'
+ },
+ multiformat_response = {
+ id: '47ce4badcf7482',
+ seatbid: [{
+ bid: [{
+ id: 'sZSYq5zYMxo_0',
+ impid: 'Bid_01b__mf',
+ crid: '100_003',
+ price: 0.00145,
+ adid: '158801',
+ adm: '',
+ nurl: 'https://rtb.com/win?i=sZSYq5zYMxo_0&f=nurl',
+ cid: '16855'
+ }, {
+ id: 'sZSYq5zYMxo_1',
+ impid: 'Bid_01v__mf',
+ crid: '100_003',
+ price: 0.25,
+ adid: '158801',
+ nurl: 'https://rtb.com/win?i=sZSYq5zYMxo_1&f=nurl',
+ cid: '16855'
+ }]
+ }],
+ bidid: 'pTuOlf5KHUo',
+ cur: 'USD'
};
var sandbox;
@@ -346,6 +377,11 @@ describe('Adkernel adapter', function () {
expect(bidRequest.imp[0].banner.battr).to.be.eql([6, 7, 9]);
});
+ it('should respect mediatypes attributes over FPD', function() {
+ expect(bidRequest.imp[0].banner).to.have.property('pos');
+ expect(bidRequest.imp[0].banner.pos).to.be.eql(1);
+ });
+
it('shouldn\'t contain gdpr nor ccpa information for default request', function () {
let [_, bidRequests] = buildRequest([bid1_zone1]);
expect(bidRequests[0]).to.not.have.property('regs');
@@ -438,24 +474,40 @@ describe('Adkernel adapter', function () {
});
it('should have openrtb video impression parameters', function() {
- expect(bidRequests[0].imp[0].video).to.have.property('api');
- expect(bidRequests[0].imp[0].video.api).to.be.eql([1, 2]);
+ let video = bidRequests[0].imp[0].video;
+ expect(video).to.have.property('api');
+ expect(video.api).to.be.eql([1, 2]);
+ expect(video.placement).to.be.eql(1);
+ expect(video.plcmt).to.be.eql(1);
+ expect(video.skip).to.be.eql(1);
+ expect(video.pos).to.be.eql(1);
});
});
describe('multiformat request building', function () {
- let _, bidRequests;
+ let pbRequests, bidRequests;
before(function () {
- [_, bidRequests] = buildRequest([bid_multiformat]);
+ [pbRequests, bidRequests] = buildRequest([bid_multiformat]);
});
it('should contain single request', function () {
expect(bidRequests).to.have.length(1);
- expect(bidRequests[0].imp).to.have.length(1);
});
- it('should contain banner-only impression', function () {
- expect(bidRequests[0].imp).to.have.length(1);
+ it('should contain both impression', function () {
+ expect(bidRequests[0].imp).to.have.length(2);
expect(bidRequests[0].imp[0]).to.have.property('banner');
- expect(bidRequests[0].imp[0]).to.not.have.property('video');
+ expect(bidRequests[0].imp[1]).to.have.property('video');
+ // check that splitted imps do not share same impid
+ expect(bidRequests[0].imp[0].id).to.be.not.eql('Bid_01');
+ expect(bidRequests[0].imp[1].id).to.be.not.eql('Bid_01');
+ expect(bidRequests[0].imp[1].id).to.be.not.eql(bidRequests[0].imp[0].id);
+ });
+ it('x', function() {
+ let bids = spec.interpretResponse({body: multiformat_response}, pbRequests[0]);
+ expect(bids).to.have.length(2);
+ expect(bids[0].requestId).to.be.eql('Bid_01');
+ expect(bids[0].mediaType).to.be.eql('banner');
+ expect(bids[1].requestId).to.be.eql('Bid_01');
+ expect(bids[1].mediaType).to.be.eql('video');
});
});
diff --git a/test/spec/modules/admaticBidAdapter_spec.js b/test/spec/modules/admaticBidAdapter_spec.js
index 8c9969e4d46..b4d84634962 100644
--- a/test/spec/modules/admaticBidAdapter_spec.js
+++ b/test/spec/modules/admaticBidAdapter_spec.js
@@ -1,12 +1,553 @@
-import {expect} from 'chai';
-import {spec, storage} from 'modules/admaticBidAdapter.js';
-import {newBidder} from 'src/adapters/bidderFactory.js';
-import {getStorageManager} from 'src/storageManager';
+import { expect } from 'chai';
+import { spec } from 'modules/admaticBidAdapter.js';
+import { newBidder } from 'src/adapters/bidderFactory.js';
+import { config } from 'src/config.js';
const ENDPOINT = 'https://layer.serve.admatic.com.tr/pb';
describe('admaticBidAdapter', () => {
const adapter = newBidder(spec);
+ let validRequest = [ {
+ 'refererInfo': {
+ 'page': 'https://www.admatic.com.tr',
+ 'domain': 'https://www.admatic.com.tr',
+ },
+ 'bidder': 'admatic',
+ 'params': {
+ 'networkId': 10433394,
+ 'host': 'layer.serve.admatic.com.tr'
+ },
+ 'ortb2Imp': { 'ext': { 'instl': 1 } },
+ 'ortb2': { 'badv': ['admatic.com.tr'] },
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [[300, 250], [728, 90]]
+ },
+ 'native': {
+ },
+ 'video': {
+ }
+ },
+ getFloor: inputParams => {
+ if (inputParams.mediaType === BANNER && inputParams.size[0] === 300 && inputParams.size[1] === 250) {
+ return {
+ currency: 'USD',
+ floor: 1.0
+ };
+ } else if (inputParams.mediaType === BANNER && inputParams.size[0] === 728 && inputParams.size[1] === 90) {
+ return {
+ currency: 'USD',
+ floor: 2.0
+ };
+ } else if (inputParams.mediaType === VIDEO) {
+ return {
+ currency: 'USD',
+ floor: 1.0
+ };
+ } else if (inputParams.mediaType === NATIVE) {
+ return {
+ currency: 'USD',
+ floor: 1.0
+ };
+ } else {
+ return {}
+ }
+ },
+ 'schain': {
+ 'ver': '1.0',
+ 'complete': 1,
+ 'nodes': [
+ {
+ 'asi': 'pixad.com.tr',
+ 'sid': 'px-pub-3000856707',
+ 'hp': 1
+ }
+ ]
+ },
+ 'at': 1,
+ 'tmax': 1000,
+ 'user': {
+ 'ext': {
+ 'eids': [
+ {
+ 'source': 'id5-sync.com',
+ 'uids': [
+ {
+ 'id': '0',
+ 'atype': 1,
+ 'ext': {
+ 'linkType': 0,
+ 'pba': 'wMh3sAXcnhDq7CfSa6ji1g=='
+ }
+ }
+ ]
+ },
+ {
+ 'source': 'pubcid.org',
+ 'uids': [
+ {
+ 'id': '5a49273f-a424-454b-b478-169c3551aa72',
+ 'atype': 1
+ }
+ ]
+ }
+ ]
+ }
+ },
+ 'ortb': {
+ 'badv': [],
+ 'bcat': [],
+ 'site': {
+ 'page': 'http://localhost:8888/admatic.html',
+ 'ref': 'http://localhost:8888',
+ 'publisher': {
+ 'name': 'localhost'
+ }
+ },
+ 'device': {
+ 'ua': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
+ }
+ },
+ 'site': {
+ 'page': 'http://localhost:8888/admatic.html',
+ 'ref': 'http://localhost:8888',
+ 'publisher': {
+ 'name': 'localhost',
+ 'publisherId': 12321312
+ }
+ },
+ 'imp': [
+ {
+ 'size': [
+ {
+ 'w': 300,
+ 'h': 250
+ },
+ {
+ 'w': 728,
+ 'h': 90
+ }
+ ],
+ 'mediatype': {},
+ 'type': 'banner',
+ 'id': '2205da7a81846b',
+ 'floors': {
+ 'banner': {
+ '300x250': { 'currency': 'USD', 'floor': 1 },
+ '728x90': { 'currency': 'USD', 'floor': 2 }
+ }
+ }
+ },
+ {
+ 'size': [
+ {
+ 'w': 338,
+ 'h': 280
+ }
+ ],
+ 'type': 'video',
+ 'mediatype': {
+ 'context': 'instream',
+ 'mimes': [
+ 'video/mp4'
+ ],
+ 'maxduration': 240,
+ 'api': [
+ 1,
+ 2
+ ],
+ 'playerSize': [
+ [
+ 338,
+ 280
+ ]
+ ],
+ 'protocols': [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8
+ ],
+ 'skip': 1,
+ 'playbackmethod': [
+ 2
+ ],
+ 'linearity': 1,
+ 'placement': 2
+ },
+ 'floors': {
+ 'video': {
+ '338x280': { 'currency': 'USD', 'floor': 1 }
+ }
+ },
+ 'id': '45e86fc7ce7fc93'
+ },
+ {
+ 'size': [
+ {
+ 'w': 1,
+ 'h': 1
+ }
+ ],
+ 'type': 'native',
+ 'mediatype': {
+ 'title': {
+ 'required': true,
+ 'len': 120
+ },
+ 'image': {
+ 'required': true
+ },
+ 'icon': {
+ 'required': false,
+ 'sizes': [
+ 640,
+ 480
+ ]
+ },
+ 'sponsoredBy': {
+ 'required': false
+ },
+ 'body': {
+ 'required': false
+ },
+ 'clickUrl': {
+ 'required': false
+ },
+ 'displayUrl': {
+ 'required': false
+ }
+ },
+ 'ext': {
+ 'instl': 0,
+ 'gpid': 'native-INS_b1b1269f-9570-fe3c-9bf4-f187827ec94a',
+ 'data': {
+ 'pbadslot': 'native-INS_b1b1269f-9570-fe3c-9bf4-f187827ec94a'
+ }
+ },
+ 'floors': {
+ 'native': {
+ '*': { 'currency': 'USD', 'floor': 1 }
+ }
+ },
+ 'id': '16e0c8982318f91'
+ }
+ ],
+ 'ext': {
+ 'cur': 'USD',
+ 'bidder': 'admatic'
+ }
+ } ];
+ let bidderRequest = {
+ 'refererInfo': {
+ 'page': 'https://www.admatic.com.tr',
+ 'domain': 'https://www.admatic.com.tr',
+ },
+ 'bidder': 'admatic',
+ 'params': {
+ 'networkId': 10433394,
+ 'host': 'layer.serve.admatic.com.tr'
+ },
+ 'ortb2Imp': { 'ext': { 'instl': 1 } },
+ 'ortb2': { 'badv': ['admatic.com.tr'] },
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [[300, 250], [728, 90]]
+ },
+ 'native': {
+ },
+ 'video': {
+ 'playerSize': [
+ 336,
+ 280
+ ]
+ }
+ },
+ 'userId': {
+ 'id5id': {
+ 'uid': '0',
+ 'ext': {
+ 'linkType': 0,
+ 'pba': 'wMh3sAXcnhDq7CfSa6ji1g=='
+ }
+ },
+ 'pubcid': '5a49273f-a424-454b-b478-169c3551aa72'
+ },
+ 'userIdAsEids': [
+ {
+ 'source': 'id5-sync.com',
+ 'uids': [
+ {
+ 'id': '0',
+ 'atype': 1,
+ 'ext': {
+ 'linkType': 0,
+ 'pba': 'wMh3sAXcnhDq7CfSa6ji1g=='
+ }
+ }
+ ]
+ },
+ {
+ 'source': 'pubcid.org',
+ 'uids': [
+ {
+ 'id': '5a49273f-a424-454b-b478-169c3551aa72',
+ 'atype': 1
+ }
+ ]
+ }
+ ],
+ getFloor: inputParams => {
+ if (inputParams.mediaType === BANNER && inputParams.size[0] === 300 && inputParams.size[1] === 250) {
+ return {
+ currency: 'USD',
+ floor: 1.0
+ };
+ } else if (inputParams.mediaType === BANNER && inputParams.size[0] === 728 && inputParams.size[1] === 90) {
+ return {
+ currency: 'USD',
+ floor: 2.0
+ };
+ } else if (inputParams.mediaType === VIDEO) {
+ return {
+ currency: 'USD',
+ floor: 1.0
+ };
+ } else if (inputParams.mediaType === NATIVE) {
+ return {
+ currency: 'USD',
+ floor: 1.0
+ };
+ } else {
+ return {}
+ }
+ },
+ 'schain': {
+ 'ver': '1.0',
+ 'complete': 1,
+ 'nodes': [
+ {
+ 'asi': 'pixad.com.tr',
+ 'sid': 'px-pub-3000856707',
+ 'hp': 1
+ }
+ ]
+ },
+ 'at': 1,
+ 'tmax': 1000,
+ 'user': {
+ 'ext': {
+ 'eids': [
+ {
+ 'source': 'id5-sync.com',
+ 'uids': [
+ {
+ 'id': '0',
+ 'atype': 1,
+ 'ext': {
+ 'linkType': 0,
+ 'pba': 'wMh3sAXcnhDq7CfSa6ji1g=='
+ }
+ }
+ ]
+ },
+ {
+ 'source': 'pubcid.org',
+ 'uids': [
+ {
+ 'id': '5a49273f-a424-454b-b478-169c3551aa72',
+ 'atype': 1
+ }
+ ]
+ }
+ ]
+ }
+ },
+ 'ortb': {
+ 'source': {},
+ 'site': {
+ 'domain': 'localhost:8888',
+ 'publisher': {
+ 'domain': 'localhost:8888'
+ },
+ 'page': 'http://localhost:8888/',
+ 'name': 'http://localhost:8888'
+ },
+ 'badv': [],
+ 'bcat': [],
+ 'device': {
+ 'w': 896,
+ 'h': 979,
+ 'dnt': 0,
+ 'ua': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
+ 'language': 'tr',
+ 'sua': {
+ 'source': 1,
+ 'platform': {
+ 'brand': 'macOS'
+ },
+ 'browsers': [
+ {
+ 'brand': 'Google Chrome',
+ 'version': [
+ '119'
+ ]
+ },
+ {
+ 'brand': 'Chromium',
+ 'version': [
+ '119'
+ ]
+ },
+ {
+ 'brand': 'Not?A_Brand',
+ 'version': [
+ '24'
+ ]
+ }
+ ],
+ 'mobile': 0
+ }
+ }
+ },
+ 'site': {
+ 'page': 'http://localhost:8888/admatic.html',
+ 'ref': 'http://localhost:8888',
+ 'publisher': {
+ 'name': 'localhost',
+ 'publisherId': 12321312
+ }
+ },
+ 'imp': [
+ {
+ 'size': [
+ {
+ 'w': 300,
+ 'h': 250
+ },
+ {
+ 'w': 728,
+ 'h': 90
+ }
+ ],
+ 'id': '2205da7a81846b',
+ 'mediatype': {},
+ 'type': 'banner',
+ 'floors': {
+ 'banner': {
+ '300x250': { 'currency': 'USD', 'floor': 1 },
+ '728x90': { 'currency': 'USD', 'floor': 2 }
+ }
+ }
+ },
+ {
+ 'size': [
+ {
+ 'w': 338,
+ 'h': 280
+ }
+ ],
+ 'type': 'video',
+ 'mediatype': {
+ 'context': 'instream',
+ 'mimes': [
+ 'video/mp4'
+ ],
+ 'maxduration': 240,
+ 'api': [
+ 1,
+ 2
+ ],
+ 'playerSize': [
+ [
+ 338,
+ 280
+ ]
+ ],
+ 'protocols': [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8
+ ],
+ 'skip': 1,
+ 'playbackmethod': [
+ 2
+ ],
+ 'linearity': 1,
+ 'placement': 2
+ },
+ 'floors': {
+ 'video': {
+ '338x280': { 'currency': 'USD', 'floor': 1 }
+ }
+ },
+ 'id': '45e86fc7ce7fc93'
+ },
+ {
+ 'size': [
+ {
+ 'w': 1,
+ 'h': 1
+ }
+ ],
+ 'type': 'native',
+ 'mediatype': {
+ 'title': {
+ 'required': true,
+ 'len': 120
+ },
+ 'image': {
+ 'required': true
+ },
+ 'icon': {
+ 'required': false,
+ 'sizes': [
+ 640,
+ 480
+ ]
+ },
+ 'sponsoredBy': {
+ 'required': false
+ },
+ 'body': {
+ 'required': false
+ },
+ 'clickUrl': {
+ 'required': false
+ },
+ 'displayUrl': {
+ 'required': false
+ }
+ },
+ 'ext': {
+ 'instl': 0,
+ 'gpid': 'native-INS_b1b1269f-9570-fe3c-9bf4-f187827ec94a',
+ 'data': {
+ 'pbadslot': 'native-INS_b1b1269f-9570-fe3c-9bf4-f187827ec94a'
+ }
+ },
+ 'floors': {
+ 'native': {
+ '*': { 'currency': 'USD', 'floor': 1 }
+ }
+ },
+ 'id': '16e0c8982318f91'
+ }
+ ],
+ 'ext': {
+ 'cur': 'USD',
+ 'bidder': 'admatic'
+ }
+ };
describe('inherited functions', () => {
it('exists and is a function', () => {
@@ -16,6 +557,10 @@ describe('admaticBidAdapter', () => {
describe('isBidRequestValid', function() {
let bid = {
+ 'refererInfo': {
+ 'page': 'https://www.admatic.com.tr',
+ 'domain': 'https://www.admatic.com.tr',
+ },
'bidder': 'admatic',
'params': {
'networkId': 10433394,
@@ -47,255 +592,147 @@ describe('admaticBidAdapter', () => {
describe('buildRequests', function () {
it('sends bid request to ENDPOINT via POST', function () {
- let validRequest = [ {
- 'bidder': 'admatic',
- 'params': {
- 'networkId': 10433394,
- 'host': 'layer.serve.admatic.com.tr'
- },
- 'ortb2Imp': { 'ext': { 'instl': 1 } },
- 'ortb2': { 'badv': ['admatic.com.tr'] },
- 'mediaTypes': {
- 'banner': {
- 'sizes': [[300, 250], [728, 90]]
- }
- },
- getFloor: inputParams => {
- if (inputParams.mediaType === BANNER && inputParams.size[0] === 300 && inputParams.size[1] === 250) {
- return {
- currency: 'USD',
- floor: 1.0
- };
- } else if (inputParams.mediaType === BANNER && inputParams.size[0] === 728 && inputParams.size[1] === 90) {
- return {
- currency: 'USD',
- floor: 2.0
- };
- } else {
- return {}
- }
- },
- 'user': {
- 'ua': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
- },
- 'blacklist': [],
- 'site': {
- 'page': 'http://localhost:8888/admatic.html',
- 'ref': 'http://localhost:8888',
- 'publisher': {
- 'name': 'localhost',
- 'publisherId': 12321312
+ const request = spec.buildRequests(validRequest, bidderRequest);
+ expect(request.url).to.equal(ENDPOINT);
+ expect(request.method).to.equal('POST');
+ });
+
+ it('should not populate GDPR if for non-EEA users', function () {
+ let bidRequest = Object.assign([], validRequest);
+ const request = spec.buildRequests(
+ bidRequest,
+ Object.assign({}, bidderRequest, {
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='
}
- },
- 'imp': [
- {
- 'size': [
- {
- 'w': 300,
- 'h': 250
- },
- {
- 'w': 728,
- 'h': 90
- }
- ],
- 'mediatype': {},
- 'type': 'banner',
- 'id': '2205da7a81846b',
- 'floors': {
- 'banner': {
- '300x250': { 'currency': 'USD', 'floor': 1 },
- '728x90': { 'currency': 'USD', 'floor': 2 }
- }
- }
- },
- {
- 'size': [
- {
- 'w': 338,
- 'h': 280
- }
- ],
- 'type': 'video',
- 'mediatype': {
- 'context': 'instream',
- 'mimes': [
- 'video/mp4'
- ],
- 'maxduration': 240,
- 'api': [
- 1,
- 2
- ],
- 'playerSize': [
- [
- 338,
- 280
- ]
- ],
- 'protocols': [
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8
- ],
- 'skip': 1,
- 'playbackmethod': [
- 2
- ],
- 'linearity': 1,
- 'placement': 2
- },
- 'id': '45e86fc7ce7fc93'
+ })
+ );
+ expect(request.data.regs.ext.gdpr).to.equal(1);
+ expect(request.data.regs.ext.consent).to.equal('BOJ8RZsOJ8RZsABAB8AAAAAZ-A');
+ });
+
+ it('should populate GDPR and empty consent string if available for EEA users without consent string but with consent', function () {
+ let bidRequest = Object.assign([], validRequest);
+ const request = spec.buildRequests(
+ bidRequest,
+ Object.assign({}, bidderRequest, {
+ gdprConsent: {
+ gdprApplies: true
}
- ],
- 'ext': {
- 'cur': 'USD',
- 'bidder': 'admatic'
+ })
+ );
+ expect(request.data.regs.ext.gdpr).to.equal(1);
+ expect(request.data.regs.ext.consent).to.equal('');
+ });
+
+ it('should properly build a request when coppa flag is true', function () {
+ let bidRequest = Object.assign([], validRequest);
+ const request = spec.buildRequests(
+ bidRequest,
+ Object.assign({}, bidderRequest, {
+ coppa: true
+ })
+ );
+ expect(request.data.regs.ext.coppa).to.not.be.undefined;
+ expect(request.data.regs.ext.coppa).to.equal(1);
+ });
+
+ it('should properly build a request with gpp consent field', function () {
+ let bidRequest = Object.assign([], validRequest);
+ const ortb2 = {
+ regs: {
+ gpp: 'gpp_consent_string',
+ gpp_sid: [0, 1, 2]
}
- } ];
- let bidderRequest = {
- 'bidder': 'admatic',
- 'params': {
- 'networkId': 10433394,
- 'host': 'layer.serve.admatic.com.tr'
- },
- 'ortb2Imp': { 'ext': { 'instl': 1 } },
- 'ortb2': { 'badv': ['admatic.com.tr'] },
- 'mediaTypes': {
- 'banner': {
- 'sizes': [[300, 250], [728, 90]]
- }
- },
- getFloor: inputParams => {
- if (inputParams.mediaType === BANNER && inputParams.size[0] === 300 && inputParams.size[1] === 250) {
- return {
- currency: 'USD',
- floor: 1.0
- };
- } else if (inputParams.mediaType === BANNER && inputParams.size[0] === 728 && inputParams.size[1] === 90) {
- return {
- currency: 'USD',
- floor: 2.0
- };
- } else {
- return {}
- }
- },
- 'user': {
- 'ua': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
- },
- 'blacklist': [],
- 'site': {
- 'page': 'http://localhost:8888/admatic.html',
- 'ref': 'http://localhost:8888',
- 'publisher': {
- 'name': 'localhost',
- 'publisherId': 12321312
- }
- },
- 'imp': [
- {
- 'size': [
- {
- 'w': 300,
- 'h': 250
- },
- {
- 'w': 728,
- 'h': 90
- }
- ],
- 'id': '2205da7a81846b',
- 'mediatype': {},
- 'type': 'banner',
- 'floors': {
- 'banner': {
- '300x250': { 'currency': 'USD', 'floor': 1 },
- '728x90': { 'currency': 'USD', 'floor': 2 }
- }
+ };
+ const request = spec.buildRequests(bidRequest, { ...bidderRequest, ortb2 });
+ expect(request.data.regs.ext.gpp).to.equal('gpp_consent_string');
+ expect(request.data.regs.ext.gpp_sid).to.deep.equal([0, 1, 2]);
+ });
+
+ it('should properly build a request with ccpa consent field', function () {
+ let bidRequest = Object.assign([], validRequest);
+ const request = spec.buildRequests(
+ bidRequest,
+ Object.assign({}, bidderRequest, {
+ uspConsent: '1---'
+ })
+ );
+ expect(request.data.regs.ext.uspIab).to.not.be.null;
+ expect(request.data.regs.ext.uspIab).to.equal('1---');
+ });
+
+ it('should properly forward eids', function () {
+ const bidRequests = [
+ {
+ bidder: 'admatic',
+ adUnitCode: 'bid-123',
+ transactionId: 'transaction-123',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90]]
}
},
- {
- 'size': [
- {
- 'w': 338,
- 'h': 280
- }
- ],
- 'type': 'video',
- 'mediatype': {
- 'context': 'instream',
- 'mimes': [
- 'video/mp4'
- ],
- 'maxduration': 240,
- 'api': [
- 1,
- 2
- ],
- 'playerSize': [
- [
- 338,
- 280
- ]
- ],
- 'protocols': [
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8
- ],
- 'skip': 1,
- 'playbackmethod': [
- 2
- ],
- 'linearity': 1,
- 'placement': 2
- },
- 'id': '45e86fc7ce7fc93'
- }
- ],
- 'ext': {
- 'cur': 'USD',
- 'bidder': 'admatic'
+ userIdAsEids: [
+ {
+ source: 'admatic.com.tr',
+ uids: [{
+ id: 'abc',
+ atype: 1
+ }]
+ }
+ ],
+ params: {}
+ },
+ ];
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ const ortbRequest = request.data;
+ expect(ortbRequest.user.ext.eids).to.deep.equal([
+ {
+ source: 'admatic.com.tr',
+ uids: [{
+ id: 'abc',
+ atype: 1
+ }]
}
- };
- const request = spec.buildRequests(validRequest, bidderRequest);
- expect(request.url).to.equal(ENDPOINT);
- expect(request.method).to.equal('POST');
+ ]);
});
it('should properly build a banner request with floors', function () {
- let bidRequests = [
+ const request = spec.buildRequests(validRequest, bidderRequest);
+ request.data.imp[0].floors = {
+ 'banner': {
+ '300x250': { 'currency': 'USD', 'floor': 1 },
+ '728x90': { 'currency': 'USD', 'floor': 2 }
+ }
+ };
+ });
+
+ it('should properly build a video request with several player sizes with floors', function () {
+ const bidRequests = [
{
'bidder': 'admatic',
- 'params': {
- 'networkId': 10433394,
- 'host': 'layer.serve.admatic.com.tr'
- },
+ 'adUnitCode': 'bid-123',
+ 'transactionId': 'transaction-123',
'mediaTypes': {
- 'banner': {
- 'sizes': [[300, 250], [728, 90]]
+ 'video': {
+ 'playerSize': [[300, 250], [728, 90]]
}
},
'ortb2Imp': { 'ext': { 'instl': 1 } },
'ortb2': { 'badv': ['admatic.com.tr'] },
+ 'params': {
+ 'networkId': 10433394,
+ 'host': 'layer.serve.admatic.com.tr'
+ },
getFloor: inputParams => {
- if (inputParams.mediaType === BANNER && inputParams.size[0] === 300 && inputParams.size[1] === 250) {
+ if (inputParams.mediaType === VIDEO && inputParams.size[0] === 300 && inputParams.size[1] === 250) {
return {
currency: 'USD',
floor: 1.0
};
- } else if (inputParams.mediaType === BANNER && inputParams.size[0] === 728 && inputParams.size[1] === 90) {
+ } else if (inputParams.mediaType === VIDEO && inputParams.size[0] === 728 && inputParams.size[1] === 90) {
return {
currency: 'USD',
floor: 2.0
@@ -306,33 +743,50 @@ describe('admaticBidAdapter', () => {
}
},
];
- let bidderRequest = {
- 'bidder': 'admatic',
- 'params': {
- 'networkId': 10433394,
- 'host': 'layer.serve.admatic.com.tr'
- },
- 'ortb2Imp': { 'ext': { 'instl': 1 } },
- 'ortb2': { 'badv': ['admatic.com.tr'] },
- 'adUnitCode': 'adunit-code',
- 'sizes': [[300, 250], [728, 90]],
- 'bidId': '30b31c1838de1e',
- 'bidderRequestId': '22edbae2733bf6',
- 'auctionId': '1d1a030790a475',
- 'creativeId': 'er2ee',
- 'mediaTypes': {
- 'banner': {
- 'sizes': [[300, 250], [728, 90]]
- }
+ const bidderRequest = {
+ 'refererInfo': {
+ 'page': 'https://www.admatic.com.tr',
+ 'domain': 'https://www.admatic.com.tr',
}
};
const request = spec.buildRequests(bidRequests, bidderRequest);
- request.data.imp[0].floors = {
- 'banner': {
- '300x250': { 'currency': 'USD', 'floor': 1 },
- '728x90': { 'currency': 'USD', 'floor': 2 }
+ });
+
+ it('should properly build a native request with floors', function () {
+ const bidRequests = [
+ {
+ 'bidder': 'admatic',
+ 'adUnitCode': 'bid-123',
+ 'transactionId': 'transaction-123',
+ 'mediaTypes': {
+ 'native': {
+ }
+ },
+ 'ortb2Imp': { 'ext': { 'instl': 1 } },
+ 'ortb2': { 'badv': ['admatic.com.tr'] },
+ 'params': {
+ 'networkId': 10433394,
+ 'host': 'layer.serve.admatic.com.tr'
+ },
+ getFloor: inputParams => {
+ if (inputParams.mediaType === NATIVE) {
+ return {
+ currency: 'USD',
+ floor: 1.0
+ };
+ } else {
+ return {}
+ }
+ }
+ },
+ ];
+ const bidderRequest = {
+ 'refererInfo': {
+ 'page': 'https://www.admatic.com.tr',
+ 'domain': 'https://www.admatic.com.tr',
}
};
+ const request = spec.buildRequests(bidRequests, bidderRequest);
});
});
@@ -348,6 +802,7 @@ describe('admaticBidAdapter', () => {
'price': 0.01,
'type': 'banner',
'bidder': 'admatic',
+ 'mime_type': 'iframe',
'adomain': ['admatic.com.tr'],
'party_tag': '
',
'iurl': 'https://www.admatic.com.tr'
@@ -359,6 +814,7 @@ describe('admaticBidAdapter', () => {
'height': 250,
'price': 0.01,
'type': 'video',
+ 'mime_type': 'iframe',
'bidder': 'admatic',
'adomain': ['admatic.com.tr'],
'party_tag': '
',
@@ -371,10 +827,24 @@ describe('admaticBidAdapter', () => {
'height': 250,
'price': 0.01,
'type': 'video',
+ 'mime_type': 'iframe',
'bidder': 'admatic',
'adomain': ['admatic.com.tr'],
'party_tag': 'https://www.admatic.com.tr',
'iurl': 'https://www.admatic.com.tr'
+ },
+ {
+ 'id': 4,
+ 'creative_id': '3742',
+ 'width': 1,
+ 'height': 1,
+ 'price': 0.01,
+ 'type': 'native',
+ 'mime_type': 'iframe',
+ 'bidder': 'admatic',
+ 'adomain': ['admatic.com.tr'],
+ 'party_tag': '{"native":{"ver":"1.1","assets":[{"id":1,"title":{"text":"title"}},{"id":4,"data":{"value":"body"}},{"id":5,"data":{"value":"sponsored"}},{"id":6,"data":{"value":"cta"}},{"id":2,"img":{"url":"https://www.admatic.com.tr","w":1200,"h":628}},{"id":3,"img":{"url":"https://www.admatic.com.tr","w":640,"h":480}}],"link":{"url":"https://www.admatic.com.tr"},"imptrackers":["https://www.admatic.com.tr"]}}',
+ 'iurl': 'https://www.admatic.com.tr'
}
],
'queryId': 'cdnbh24rlv0hhkpfpln0',
@@ -393,6 +863,7 @@ describe('admaticBidAdapter', () => {
ad: '
',
creativeId: '374',
meta: {
+ model: 'iframe',
advertiserDomains: ['admatic.com.tr']
},
ttl: 60,
@@ -410,6 +881,7 @@ describe('admaticBidAdapter', () => {
vastXml: '
',
creativeId: '3741',
meta: {
+ model: 'iframe',
advertiserDomains: ['admatic.com.tr']
},
ttl: 60,
@@ -427,6 +899,41 @@ describe('admaticBidAdapter', () => {
vastXml: 'https://www.admatic.com.tr',
creativeId: '3741',
meta: {
+ model: 'iframe',
+ advertiserDomains: ['admatic.com.tr']
+ },
+ ttl: 60,
+ bidder: 'admatic'
+ },
+ {
+ requestId: 4,
+ cpm: 0.01,
+ width: 1,
+ height: 1,
+ currency: 'TRY',
+ mediaType: 'native',
+ netRevenue: true,
+ native: {
+ 'clickUrl': 'https://www.admatic.com.tr',
+ 'impressionTrackers': ['https://www.admatic.com.tr'],
+ 'title': 'title',
+ 'body': 'body',
+ 'sponsoredBy': 'sponsored',
+ 'cta': 'cta',
+ 'image': {
+ 'url': 'https://www.admatic.com.tr',
+ 'width': 1200,
+ 'height': 628
+ },
+ 'icon': {
+ 'url': 'https://www.admatic.com.tr',
+ 'width': 640,
+ 'height': 480
+ }
+ },
+ creativeId: '3742',
+ meta: {
+ model: 'iframe',
advertiserDomains: ['admatic.com.tr']
},
ttl: 60,
diff --git a/test/spec/modules/admixerBidAdapter_spec.js b/test/spec/modules/admixerBidAdapter_spec.js
index 8cf433460b7..85538efc957 100644
--- a/test/spec/modules/admixerBidAdapter_spec.js
+++ b/test/spec/modules/admixerBidAdapter_spec.js
@@ -4,11 +4,12 @@ import {newBidder} from 'src/adapters/bidderFactory.js';
import {config} from '../../../src/config.js';
const BIDDER_CODE = 'admixer';
-const BIDDER_CODE_ADX = 'admixeradx';
+const WL_BIDDER_CODE = 'admixerwl'
const ENDPOINT_URL = 'https://inv-nets.admixer.net/prebid.1.2.aspx';
const ENDPOINT_URL_CUSTOM = 'https://custom.admixer.net/prebid.aspx';
-const ENDPOINT_URL_ADX = 'https://inv-nets.admixer.net/adxprebid.1.2.aspx';
const ZONE_ID = '2eb6bd58-865c-47ce-af7f-a918108c3fd2';
+const CLIENT_ID = 5124;
+const ENDPOINT_ID = 81264;
describe('AdmixerAdapter', function () {
const adapter = newBidder(spec);
@@ -36,9 +37,28 @@ describe('AdmixerAdapter', function () {
auctionId: '1d1a030790a475',
};
+ let wlBid = {
+ bidder: WL_BIDDER_CODE,
+ params: {
+ clientId: CLIENT_ID,
+ endpointId: ENDPOINT_ID,
+ },
+ adUnitCode: 'adunit-code',
+ sizes: [
+ [300, 250],
+ [300, 600],
+ ],
+ bidId: '30b31c1838de1e',
+ bidderRequestId: '22edbae2733bf6',
+ auctionId: '1d1a030790a475',
+ };
+
it('should return true when required params found', function () {
expect(spec.isBidRequestValid(bid)).to.equal(true);
});
+ it('should return true when params required by WL found', function () {
+ expect(spec.isBidRequestValid(wlBid)).to.equal(true);
+ });
it('should return false when required params are not passed', function () {
let bid = Object.assign({}, bid);
@@ -48,6 +68,14 @@ describe('AdmixerAdapter', function () {
};
expect(spec.isBidRequestValid(bid)).to.equal(false);
});
+ it('should return false when params required by WL are not passed', function () {
+ let wlBid = Object.assign({}, wlBid);
+ delete wlBid.params;
+ wlBid.params = {
+ clientId: 0,
+ };
+ expect(spec.isBidRequestValid(wlBid)).to.equal(false);
+ });
});
describe('buildRequests', function () {
@@ -105,7 +133,10 @@ describe('AdmixerAdapter', function () {
validRequest: [
{
bidder: bidder,
- params: {
+ params: bidder === 'admixerwl' ? {
+ clientId: CLIENT_ID,
+ endpointId: ENDPOINT_ID
+ } : {
zone: ZONE_ID,
},
adUnitCode: 'adunit-code',
@@ -168,6 +199,12 @@ describe('AdmixerAdapter', function () {
expect(request.url).to.equal('https://inv-nets.admixer.net/adxprebid.1.2.aspx');
expect(request.method).to.equal('POST');
});
+ it('build request for admixerwl', function () {
+ const requestParams = requestParamsFor('admixerwl');
+ const request = spec.buildRequests(requestParams.validRequest, requestParams.bidderRequest);
+ expect(request.url).to.equal(`https://inv-nets-adxwl.admixer.com/adxwlprebid.aspx?client=${CLIENT_ID}`);
+ expect(request.method).to.equal('POST');
+ });
});
describe('checkFloorGetting', function () {
diff --git a/test/spec/modules/adnuntiusBidAdapter_spec.js b/test/spec/modules/adnuntiusBidAdapter_spec.js
index 4ddbaaa2e2a..e109ca1829c 100644
--- a/test/spec/modules/adnuntiusBidAdapter_spec.js
+++ b/test/spec/modules/adnuntiusBidAdapter_spec.js
@@ -10,9 +10,10 @@ import {getGlobal} from '../../../src/prebidGlobal';
describe('adnuntiusBidAdapter', function() {
const URL = 'https://ads.adnuntius.delivery/i?tzo=';
const EURO_URL = 'https://europe.delivery.adnuntius.com/i?tzo=';
- const GVLID = 855;
const usi = utils.generateUUID()
- const meta = [{key: 'usi', value: usi}]
+
+ const meta = [{key: 'valueless'}, {value: 'keyless'}, {key: 'voidAuIds'}, {key: 'voidAuIds', value: [{auId: '11118b6bc', exp: misc.getUnixTimestamp()}, {exp: misc.getUnixTimestamp(1)}]}, {key: 'valid', value: 'also-valid', exp: misc.getUnixTimestamp(1)}, {key: 'expired', value: 'fwefew', exp: misc.getUnixTimestamp()}, {key: 'usi', value: 'should be skipped because timestamp', exp: misc.getUnixTimestamp()}, {key: 'usi', value: usi, exp: misc.getUnixTimestamp(100)}, {key: 'usi', value: 'should be skipped because timestamp', exp: misc.getUnixTimestamp()}]
+ let storage;
before(() => {
getGlobal().bidderSettings = {
@@ -20,8 +21,11 @@ describe('adnuntiusBidAdapter', function() {
storageAllowed: true
}
};
- const storage = getStorageManager({bidderCode: 'adnuntius'})
- storage.setDataInLocalStorage('adn.metaData', JSON.stringify(meta))
+ storage = getStorageManager({bidderCode: 'adnuntius'});
+ });
+
+ beforeEach(() => {
+ storage.setDataInLocalStorage('adn.metaData', JSON.stringify(meta));
});
after(() => {
@@ -38,7 +42,7 @@ describe('adnuntiusBidAdapter', function() {
const ENDPOINT_URL_VIDEO = `${ENDPOINT_URL_BASE}&userId=${usi}&tt=vast4`;
const ENDPOINT_URL_NOCOOKIE = `${ENDPOINT_URL_BASE}&userId=${usi}&noCookies=true`;
const ENDPOINT_URL_SEGMENTS = `${ENDPOINT_URL_BASE}&segments=segment1,segment2,segment3&userId=${usi}`;
- const ENDPOINT_URL_CONSENT = `${EURO_URL}${tzo}&format=json&consentString=consentString&userId=${usi}`;
+ const ENDPOINT_URL_CONSENT = `${EURO_URL}${tzo}&format=json&consentString=consentString&gdpr=1&userId=${usi}`;
const adapter = newBidder(spec);
const bidderRequests = [
@@ -47,6 +51,7 @@ describe('adnuntiusBidAdapter', function() {
bidder: 'adnuntius',
params: {
auId: '000000000008b6bc',
+ targetId: '123',
network: 'adnuntius',
maxDeals: 1
},
@@ -99,7 +104,10 @@ describe('adnuntiusBidAdapter', function() {
const videoBidRequest = {
bid: videoBidderRequest,
- bidder: 'adnuntius'
+ bidder: 'adnuntius',
+ params: {
+ bidType: 'justsomestuff-error-handling'
+ }
}
const deals = [
@@ -456,7 +464,78 @@ describe('adnuntiusBidAdapter', function() {
expect(request[0]).to.have.property('url');
expect(request[0].url).to.equal(ENDPOINT_URL);
expect(request[0]).to.have.property('data');
- expect(request[0].data).to.equal('{"adUnits":[{"auId":"000000000008b6bc","targetId":"adn-000000000008b6bc","maxDeals":1,"dimensions":[[640,480],[600,400]]},{"auId":"0000000000000551","targetId":"adn-0000000000000551","maxDeals":0,"dimensions":[[1640,1480],[1600,1400]]}],"metaData":{"usi":"' + usi + '"}}');
+ expect(request[0].data).to.equal('{"adUnits":[{"auId":"000000000008b6bc","targetId":"123","maxDeals":1,"dimensions":[[640,480],[600,400]]},{"auId":"0000000000000551","targetId":"adn-0000000000000551","dimensions":[[1640,1480],[1600,1400]]}],"metaData":{"valid":"also-valid"}}');
+ });
+
+ it('Test requests with no local storage', function() {
+ storage.setDataInLocalStorage('adn.metaData', JSON.stringify([{}]));
+ const request = spec.buildRequests(bidderRequests, {});
+ expect(request.length).to.equal(1);
+ expect(request[0]).to.have.property('bid');
+ const bid = request[0].bid[0]
+ expect(bid).to.have.property('bidId');
+ expect(request[0]).to.have.property('url');
+ expect(request[0].url).to.equal(ENDPOINT_URL_BASE);
+ expect(request[0]).to.have.property('data');
+ expect(request[0].data).to.equal('{"adUnits":[{"auId":"000000000008b6bc","targetId":"123","maxDeals":1,"dimensions":[[640,480],[600,400]]},{"auId":"0000000000000551","targetId":"adn-0000000000000551","dimensions":[[1640,1480],[1600,1400]]}]}');
+
+ localStorage.removeItem('adn.metaData');
+ const request2 = spec.buildRequests(bidderRequests, {});
+ expect(request2.length).to.equal(1);
+ expect(request2[0]).to.have.property('url');
+ expect(request2[0].url).to.equal(ENDPOINT_URL_BASE);
+ });
+
+ it('Test request changes for voided au ids', function() {
+ storage.setDataInLocalStorage('adn.metaData', JSON.stringify([{key: 'voidAuIds', value: [{auId: '11118b6bc', exp: misc.getUnixTimestamp(1)}, {auId: '0000000000000023', exp: misc.getUnixTimestamp(1)}]}]));
+ const bRequests = bidderRequests.concat([{
+ bidId: 'adn-11118b6bc',
+ bidder: 'adnuntius',
+ params: {
+ auId: '11118b6bc',
+ network: 'adnuntius',
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [[1640, 1480], [1600, 1400]],
+ }
+ },
+ }]);
+ bRequests.push({
+ bidId: 'adn-23',
+ bidder: 'adnuntius',
+ params: {
+ auId: '23',
+ network: 'adnuntius',
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [[1640, 1480], [1600, 1400]],
+ }
+ },
+ });
+ bRequests.push({
+ bidId: 'adn-13',
+ bidder: 'adnuntius',
+ params: {
+ auId: '13',
+ network: 'adnuntius',
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [[164, 140], [10, 1400]],
+ }
+ },
+ });
+ const request = spec.buildRequests(bRequests, {});
+ expect(request.length).to.equal(1);
+ expect(request[0]).to.have.property('bid');
+ const bid = request[0].bid[0]
+ expect(bid).to.have.property('bidId');
+ expect(request[0]).to.have.property('url');
+ expect(request[0].url).to.equal(ENDPOINT_URL_BASE);
+ expect(request[0]).to.have.property('data');
+ expect(request[0].data).to.equal('{"adUnits":[{"auId":"000000000008b6bc","targetId":"123","maxDeals":1,"dimensions":[[640,480],[600,400]]},{"auId":"0000000000000551","targetId":"adn-0000000000000551","dimensions":[[1640,1480],[1600,1400]]},{"auId":"13","targetId":"adn-13","dimensions":[[164,140],[10,1400]]}]}');
});
it('Test Video requests', function() {
@@ -474,7 +553,7 @@ describe('adnuntiusBidAdapter', function() {
user: {
data: [{
name: 'adnuntius',
- segment: [{id: 'segment1'}, {id: 'segment2'}]
+ segment: [{id: 'segment1'}, {id: 'segment2'}, {invalidSegment: 'invalid'}, {id: 123}, {id: ['3332']}]
},
{
name: 'other',
@@ -657,7 +736,7 @@ describe('adnuntiusBidAdapter', function() {
expect(bidderRequests[0].params.maxDeals).to.equal(1);
expect(data.adUnits[0].maxDeals).to.equal(bidderRequests[0].params.maxDeals);
expect(bidderRequests[1].params).to.not.have.property('maxBids');
- expect(data.adUnits[1].maxDeals).to.equal(0);
+ expect(data.adUnits[1].maxDeals).to.equal(undefined);
});
it('Should allow a maximum of 5 deals.', function() {
config.setBidderConfig({
@@ -703,7 +782,7 @@ describe('adnuntiusBidAdapter', function() {
expect(request[0]).to.have.property('data');
const data = JSON.parse(request[0].data);
expect(data.adUnits.length).to.equal(1);
- expect(data.adUnits[0].maxDeals).to.equal(0);
+ expect(data.adUnits[0].maxDeals).to.equal(undefined);
});
it('Should set max deals using bidder config.', function() {
config.setBidderConfig({
@@ -749,12 +828,20 @@ describe('adnuntiusBidAdapter', function() {
describe('interpretResponse', function() {
it('should return valid response when passed valid server response', function() {
- const interpretedResponse = spec.interpretResponse(serverResponse, singleBidRequest);
+ config.setBidderConfig({
+ bidders: ['adnuntius'],
+ config: {
+ bidType: 'netBid',
+ maxDeals: 1
+ }
+ });
+
+ const interpretedResponse = config.runWithBidder('adnuntius', () => spec.interpretResponse(serverResponse, singleBidRequest));
expect(interpretedResponse).to.have.lengthOf(2);
const deal = serverResponse.body.adUnits[0].deals[0];
expect(interpretedResponse[0].bidderCode).to.equal('adnuntius');
- expect(interpretedResponse[0].cpm).to.equal(deal.bid.amount * 1000);
+ expect(interpretedResponse[0].cpm).to.equal(deal.netBid.amount * 1000);
expect(interpretedResponse[0].width).to.equal(Number(deal.creativeWidth));
expect(interpretedResponse[0].height).to.equal(Number(deal.creativeHeight));
expect(interpretedResponse[0].creativeId).to.equal(deal.creativeId);
@@ -770,7 +857,7 @@ describe('adnuntiusBidAdapter', function() {
const ad = serverResponse.body.adUnits[0].ads[0];
expect(interpretedResponse[1].bidderCode).to.equal('adnuntius');
- expect(interpretedResponse[1].cpm).to.equal(ad.bid.amount * 1000);
+ expect(interpretedResponse[1].cpm).to.equal(ad.netBid.amount * 1000);
expect(interpretedResponse[1].width).to.equal(Number(ad.creativeWidth));
expect(interpretedResponse[1].height).to.equal(Number(ad.creativeHeight));
expect(interpretedResponse[1].creativeId).to.equal(ad.creativeId);
@@ -783,6 +870,33 @@ describe('adnuntiusBidAdapter', function() {
expect(interpretedResponse[1].ttl).to.equal(360);
expect(interpretedResponse[1].dealId).to.equal('not-in-deal-array-here');
expect(interpretedResponse[1].dealCount).to.equal(0);
+
+ const results = JSON.parse(storage.getDataFromLocalStorage('adn.metaData'));
+ const usiEntry = results.find(entry => entry.key === 'usi');
+ expect(usiEntry.key).to.equal('usi');
+ expect(usiEntry.value).to.equal('from-api-server dude');
+ expect(usiEntry.exp).to.be.greaterThan(misc.getUnixTimestamp(90));
+
+ const voidAuIdsEntry = results.find(entry => entry.key === 'voidAuIds');
+ expect(voidAuIdsEntry.key).to.equal('voidAuIds');
+ expect(voidAuIdsEntry.exp).to.equal(undefined);
+ expect(voidAuIdsEntry.value[0].auId).to.equal('00000000000abcde');
+ expect(voidAuIdsEntry.value[0].exp).to.be.greaterThan(misc.getUnixTimestamp());
+ expect(voidAuIdsEntry.value[0].exp).to.be.lessThan(misc.getUnixTimestamp(2));
+ expect(voidAuIdsEntry.value[1].auId).to.equal('00000000000fffff');
+ expect(voidAuIdsEntry.value[1].exp).to.be.greaterThan(misc.getUnixTimestamp());
+ expect(voidAuIdsEntry.value[1].exp).to.be.lessThan(misc.getUnixTimestamp(2));
+
+ const validEntry = results.find(entry => entry.key === 'valid');
+ expect(validEntry.key).to.equal('valid');
+ expect(validEntry.value).to.equal('also-valid');
+ expect(validEntry.exp).to.be.greaterThan(misc.getUnixTimestamp());
+ expect(validEntry.exp).to.be.lessThan(misc.getUnixTimestamp(2));
+
+ const randomApiEntry = results.find(entry => entry.key === 'randomApiKey');
+ expect(randomApiEntry.key).to.equal('randomApiKey');
+ expect(randomApiEntry.value).to.equal('randomApiValue');
+ expect(randomApiEntry.exp).to.be.greaterThan(misc.getUnixTimestamp(90));
});
it('should not process valid response when passed alt bidder that is an adndeal', function() {
@@ -795,6 +909,7 @@ describe('adnuntiusBidAdapter', function() {
]
};
serverResponse.body.adUnits[0].deals = [];
+ delete serverResponse.body.metaData.voidAuIds; // test response with no voidAuIds
const interpretedResponse = spec.interpretResponse(serverResponse, altBidder);
expect(interpretedResponse).to.have.lengthOf(0);
@@ -808,6 +923,9 @@ describe('adnuntiusBidAdapter', function() {
{
bidder: 'adn-alt',
bidId: 'adn-0000000000000551',
+ params: {
+ bidType: 'netBid'
+ }
}
]
};
@@ -818,7 +936,7 @@ describe('adnuntiusBidAdapter', function() {
const ad = serverResponse.body.adUnits[0].ads[0];
expect(interpretedResponse[0].bidderCode).to.equal('adn-alt');
- expect(interpretedResponse[0].cpm).to.equal(ad.bid.amount * 1000);
+ expect(interpretedResponse[0].cpm).to.equal(ad.netBid.amount * 1000);
expect(interpretedResponse[0].width).to.equal(Number(ad.creativeWidth));
expect(interpretedResponse[0].height).to.equal(Number(ad.creativeHeight));
expect(interpretedResponse[0].creativeId).to.equal(ad.creativeId);
diff --git a/test/spec/modules/adpod_spec.js b/test/spec/modules/adpod_spec.js
index a6164f919ef..14e530c1a9b 100644
--- a/test/spec/modules/adpod_spec.js
+++ b/test/spec/modules/adpod_spec.js
@@ -47,7 +47,6 @@ describe('adpod.js', function () {
addBidToAuctionStub = sinon.stub(auction, 'addBidToAuction').callsFake(function (auctionInstance, bid) {
auctionBids.push(bid);
});
- doCallbacksIfTimedoutStub = sinon.stub(auction, 'doCallbacksIfTimedout');
clock = sinon.useFakeTimers();
config.setConfig({
cache: {
@@ -61,7 +60,6 @@ describe('adpod.js', function () {
logWarnStub.restore();
logInfoStub.restore();
addBidToAuctionStub.restore();
- doCallbacksIfTimedoutStub.restore();
clock.restore();
config.resetConfig();
auctionBids = [];
@@ -633,7 +631,6 @@ describe('adpod.js', function () {
callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT);
callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT);
- expect(doCallbacksIfTimedoutStub.calledTwice).to.equal(true);
expect(logWarnStub.calledOnce).to.equal(true);
expect(auctionBids.length).to.equal(0);
});
diff --git a/test/spec/modules/adstirBidAdapter_spec.js b/test/spec/modules/adstirBidAdapter_spec.js
new file mode 100644
index 00000000000..290a6822f69
--- /dev/null
+++ b/test/spec/modules/adstirBidAdapter_spec.js
@@ -0,0 +1,412 @@
+import { expect } from 'chai';
+import { spec } from '../../../modules/adstirBidAdapter.js';
+import * as utils from 'src/utils.js';
+import { config } from 'src/config.js';
+
+describe('AdstirAdapter', function () {
+ describe('isBidRequestValid', function () {
+ it('should return true if appId is non-empty string and adSpaceNo is integer', function () {
+ const bid = {
+ params: {
+ appId: 'MEDIA-XXXXXX',
+ adSpaceNo: 6,
+ }
+ }
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+ it('should return false if appId is non-empty string, but adSpaceNo is not integer', function () {
+ const bid = {
+ params: {
+ appId: 'MEDIA-XXXXXX',
+ adSpaceNo: 'a',
+ }
+ }
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ it('should return false if appId is non-empty string, but adSpaceNo is null', function () {
+ const bid = {
+ params: {
+ appId: 'MEDIA-XXXXXX',
+ adSpaceNo: null,
+ }
+ }
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ it('should return false if appId is non-empty string, but adSpaceNo is undefined', function () {
+ const bid = {
+ params: {
+ appId: 'MEDIA-XXXXXX'
+ }
+ }
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ it('should return false if adSpaceNo is integer, but appId is empty string', function () {
+ const bid = {
+ params: {
+ appId: '',
+ adSpaceNo: 6,
+ }
+ }
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ it('should return false if adSpaceNo is integer, but appId is not string', function () {
+ const bid = {
+ params: {
+ appId: 123,
+ adSpaceNo: 6,
+ }
+ }
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ it('should return false if adSpaceNo is integer, but appId is null', function () {
+ const bid = {
+ params: {
+ appId: null,
+ adSpaceNo: 6,
+ }
+ }
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ it('should return false if adSpaceNo is integer, but appId is undefined', function () {
+ const bid = {
+ params: {
+ adSpaceNo: 6,
+ }
+ }
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ it('should return false if params is empty', function () {
+ const bid = {
+ params: {}
+ }
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ });
+
+ describe('buildRequests', function () {
+ const validBidRequests = [
+ {
+ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917',
+ bidder: 'adstir',
+ bidId: 'bidid1111',
+ params: {
+ appId: 'MEDIA-XXXXXX',
+ adSpaceNo: 1,
+ },
+ transactionId: 'transactionid-1111',
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250],
+ [336, 280],
+ ],
+ }
+ },
+ sizes: [
+ [300, 250],
+ [336, 280],
+ ],
+ },
+ {
+ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917',
+ bidder: 'adstir',
+ bidId: 'bidid2222',
+ params: {
+ appId: 'MEDIA-XXXXXX',
+ adSpaceNo: 2,
+ },
+ transactionId: 'transactionid-2222',
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [320, 50],
+ [320, 100],
+ ],
+ }
+ },
+ sizes: [
+ [320, 50],
+ [320, 100],
+ ],
+ },
+ ];
+
+ const bidderRequest = {
+ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917',
+ refererInfo: {
+ page: 'https://ad-stir.com/contact',
+ topmostLocation: 'https://ad-stir.com/contact',
+ reachedTop: true,
+ ref: 'https://test.example/q=adstir',
+ isAmp: false,
+ numIframes: 0,
+ stack: [
+ 'https://ad-stir.com/contact',
+ ],
+ },
+ };
+
+ it('one entry in validBidRequests corresponds to one server request object.', function () {
+ const requests = spec.buildRequests(validBidRequests, bidderRequest);
+ expect(requests.length).to.equal(validBidRequests.length);
+ requests.forEach(function (r, i) {
+ expect(r.method).to.equal('POST');
+ expect(r.url).to.equal('https://ad.ad-stir.com/prebid');
+ const d = JSON.parse(r.data);
+ expect(d.auctionId).to.equal('b06c5141-fe8f-4cdf-9d7d-54415490a917');
+
+ const v = validBidRequests[i];
+ expect(d.appId).to.equal(v.params.appId);
+ expect(d.adSpaceNo).to.equal(v.params.adSpaceNo);
+ expect(d.bidId).to.equal(v.bidId);
+ expect(d.transactionId).to.equal(v.transactionId);
+ expect(d.mediaTypes).to.deep.equal(v.mediaTypes);
+ expect(d.sizes).to.deep.equal(v.sizes);
+ expect(d.ref.page).to.equal(bidderRequest.refererInfo.page);
+ expect(d.ref.tloc).to.equal(bidderRequest.refererInfo.topmostLocation);
+ expect(d.ref.referrer).to.equal(bidderRequest.refererInfo.ref);
+ expect(d.sua).to.equal(null);
+ expect(d.gdpr).to.equal(false);
+ expect(d.usp).to.equal(false);
+ expect(d.schain).to.equal(null);
+ expect(d.eids).to.deep.equal([]);
+ });
+ });
+
+ it('ref.page, ref.tloc and ref.referrer correspond to refererInfo', function () {
+ const [ request ] = spec.buildRequests([validBidRequests[0]], {
+ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917',
+ refererInfo: {
+ page: null,
+ topmostLocation: 'https://adserver.example/iframe1.html',
+ reachedTop: false,
+ ref: null,
+ isAmp: false,
+ numIframes: 2,
+ stack: [
+ null,
+ 'https://adserver.example/iframe1.html',
+ 'https://adserver.example/iframe2.html'
+ ],
+ },
+ });
+
+ const { ref } = JSON.parse(request.data);
+ expect(ref.page).to.equal(null);
+ expect(ref.tloc).to.equal('https://adserver.example/iframe1.html');
+ expect(ref.referrer).to.equal(null);
+ });
+
+ it('when config.pageUrl is not set, ref.topurl equals to refererInfo.reachedTop', function () {
+ let bidderRequestClone = utils.deepClone(bidderRequest);
+ [true, false].forEach(function (reachedTop) {
+ bidderRequestClone.refererInfo.reachedTop = reachedTop;
+ const requests = spec.buildRequests(validBidRequests, bidderRequestClone);
+ const d = JSON.parse(requests[0].data);
+ expect(d.ref.topurl).to.equal(reachedTop);
+ });
+ });
+
+ describe('when config.pageUrl is set, ref.topurl is always false', function () {
+ before(function () {
+ config.setConfig({ pageUrl: 'https://ad-stir.com/register' });
+ });
+ after(function () {
+ config.resetConfig();
+ });
+
+ it('ref.topurl should be false', function () {
+ let bidderRequestClone = utils.deepClone(bidderRequest);
+ [true, false].forEach(function (reachedTop) {
+ bidderRequestClone.refererInfo.reachedTop = reachedTop;
+ const requests = spec.buildRequests(validBidRequests, bidderRequestClone);
+ const d = JSON.parse(requests[0].data);
+ expect(d.ref.topurl).to.equal(false);
+ });
+ });
+ });
+
+ it('gdprConsent.gdprApplies is sent', function () {
+ let bidderRequestClone = utils.deepClone(bidderRequest);
+ [true, false].forEach(function (gdprApplies) {
+ bidderRequestClone.gdprConsent = { gdprApplies };
+ const requests = spec.buildRequests(validBidRequests, bidderRequestClone);
+ const d = JSON.parse(requests[0].data);
+ expect(d.gdpr).to.equal(gdprApplies);
+ });
+ });
+
+ it('includes in the request parameters whether CCPA applies', function () {
+ let bidderRequestClone = utils.deepClone(bidderRequest);
+ const cases = [
+ { uspConsent: '1---', expected: false },
+ { uspConsent: '1YYY', expected: true },
+ { uspConsent: '1YNN', expected: true },
+ { uspConsent: '1NYN', expected: true },
+ { uspConsent: '1-Y-', expected: true },
+ ];
+ cases.forEach(function ({ uspConsent, expected }) {
+ bidderRequestClone.uspConsent = uspConsent;
+ const requests = spec.buildRequests(validBidRequests, bidderRequestClone);
+ const d = JSON.parse(requests[0].data);
+ expect(d.usp).to.equal(expected);
+ });
+ });
+
+ it('should add schain if available', function() {
+ const schain = {
+ 'ver': '1.0',
+ 'complete': 1,
+ 'nodes': [
+ {
+ 'asi': 'exchange1.example',
+ 'sid': '1234!abcd',
+ 'hp': 1,
+ 'rid': 'bid-request-1',
+ 'name': 'publisher, Inc.',
+ 'domain': 'publisher.example'
+ },
+ {
+ 'asi': 'exchange2.example',
+ 'sid': 'abcd',
+ 'hp': 1,
+ 'rid': 'bid-request-2',
+ 'name': 'intermediary',
+ 'domain': 'intermediary.example'
+ }
+ ]
+ };
+ const serializedSchain = '1.0,1!exchange1.example,1234%21abcd,1,bid-request-1,publisher%2C%20Inc.,publisher.example!exchange2.example,abcd,1,bid-request-2,intermediary,intermediary.example';
+
+ const [ request ] = spec.buildRequests([utils.mergeDeep(utils.deepClone(validBidRequests[0]), { schain })], bidderRequest);
+ const d = JSON.parse(request.data);
+ expect(d.schain).to.deep.equal(serializedSchain);
+ });
+
+ it('should add schain even if some nodes params are blank', function() {
+ const schain = {
+ 'ver': '1.0',
+ 'complete': 1,
+ 'nodes': [
+ {
+ 'asi': 'exchange1.example',
+ 'sid': '1234!abcd',
+ 'hp': 1,
+ },
+ {
+ },
+ {
+ 'asi': 'exchange2.example',
+ 'sid': 'abcd',
+ 'hp': 1,
+ },
+ ]
+ };
+ const serializedSchain = '1.0,1!exchange1.example,1234%21abcd,1,,,!,,,,,!exchange2.example,abcd,1,,,';
+
+ const [ request ] = spec.buildRequests([utils.mergeDeep(utils.deepClone(validBidRequests[0]), { schain })], bidderRequest);
+ const d = JSON.parse(request.data);
+ expect(d.schain).to.deep.equal(serializedSchain);
+ });
+
+ it('should add UA client hints to payload if available', function () {
+ const sua = {
+ browsers: [
+ {
+ brand: 'Not?A_Brand',
+ version: [
+ '8',
+ '0',
+ '0',
+ '0'
+ ]
+ },
+ {
+ version: [
+ '108',
+ '0',
+ '5359',
+ '40'
+ ]
+ },
+ {
+ brand: 'Google Chrome',
+ version: [
+ '108',
+ '0',
+ '5359',
+ '40'
+ ]
+ }
+ ],
+ platform: {
+ brand: 'Android',
+ version: [
+ '11'
+ ]
+ },
+ mobile: 1,
+ architecture: '',
+ bitness: '64',
+ model: 'Pixel 5',
+ source: 2
+ }
+
+ const validBidRequestsClone = utils.deepClone(validBidRequests);
+ validBidRequestsClone[0] = utils.mergeDeep(validBidRequestsClone[0], {
+ ortb2: {
+ device: { sua },
+ }
+ });
+
+ const requests = spec.buildRequests(validBidRequestsClone, bidderRequest);
+ requests.forEach(function (r) {
+ const d = JSON.parse(r.data);
+ expect(d.sua).to.deep.equal(sua);
+ });
+ });
+ });
+
+ describe('interpretResponse', function () {
+ it('return empty array when no content', function () {
+ const bids = spec.interpretResponse({ body: '' });
+ expect(bids).to.deep.equal([]);
+ });
+ it('return empty array when seatbid empty', function () {
+ const bids = spec.interpretResponse({ body: { seatbid: [] } });
+ expect(bids).to.deep.equal([]);
+ });
+ it('return valid bids when serverResponse is valid', function () {
+ const serverResponse = {
+ 'body': {
+ 'seatbid': [
+ {
+ 'bid': {
+ 'ad': '
test response
',
+ 'cpm': 5250,
+ 'creativeId': '5_1234ABCD',
+ 'currency': 'JPY',
+ 'height': 250,
+ 'meta': {
+ 'advertiserDomains': [
+ 'adv.example'
+ ],
+ 'mediaType': 'banner',
+ 'networkId': 5
+ },
+ 'netRevenue': true,
+ 'requestId': '22a9457aed98a4',
+ 'transactionId': 'f18c078e-4d2a-4ecb-a886-2a0c52187213',
+ 'ttl': 60,
+ 'width': 300,
+ }
+ }
+ ]
+ },
+ 'headers': {}
+ };
+ const bids = spec.interpretResponse(serverResponse);
+ expect(bids[0]).to.deep.equal(serverResponse.body.seatbid[0].bid);
+ });
+ });
+});
diff --git a/test/spec/modules/adtelligentBidAdapter_spec.js b/test/spec/modules/adtelligentBidAdapter_spec.js
index e40828e6852..0acbaa06f5b 100644
--- a/test/spec/modules/adtelligentBidAdapter_spec.js
+++ b/test/spec/modules/adtelligentBidAdapter_spec.js
@@ -11,18 +11,13 @@ const EXPECTED_ENDPOINTS = [
'https://ghb.adtelligent.com/v2/auction/'
];
const aliasEP = {
- 'appaloosa': 'https://ghb.hb.appaloosa.media/v2/auction/',
- 'appaloosa_publisherSuffix': 'https://ghb.hb.appaloosa.media/v2/auction/',
- 'onefiftytwomedia': 'https://ghb.ads.152media.com/v2/auction/',
- 'navelix': 'https://ghb.hb.navelix.com/v2/auction/',
- 'bidsxchange': 'https://ghb.hbd.bidsxchange.com/v2/auction/',
+ 'janet_publisherSuffix': 'https://ghb.bidder.jmgads.com/v2/auction/',
'streamkey': 'https://ghb.hb.streamkey.net/v2/auction/',
'janet': 'https://ghb.bidder.jmgads.com/v2/auction/',
- 'pgam': 'https://ghb.pgamssp.com/v2/auction/',
'ocm': 'https://ghb.cenarius.orangeclickmedia.com/v2/auction/',
- 'vidcrunchllc': 'https://ghb.platform.vidcrunch.com/v2/auction/',
'9dotsmedia': 'https://ghb.platform.audiodots.com/v2/auction/',
'copper6': 'https://ghb.app.copper6.com/v2/auction/',
+ 'indicue': 'https://ghb.console.indicue.com/v2/auction/',
};
const DEFAULT_ADATPER_REQ = { bidderCode: 'adtelligent' };
diff --git a/test/spec/modules/adxcgBidAdapter_spec.js b/test/spec/modules/adxcgBidAdapter_spec.js
index 65c7584b428..e07e3a6e5d4 100644
--- a/test/spec/modules/adxcgBidAdapter_spec.js
+++ b/test/spec/modules/adxcgBidAdapter_spec.js
@@ -1,835 +1,19 @@
// jshint esversion: 6, es3: false, node: true
-import {assert} from 'chai';
-import {spec} from 'modules/adxcgBidAdapter.js';
-import {config} from 'src/config.js';
-import {createEidsArray} from 'modules/userId/eids.js';
+import { assert } from 'chai';
+import { spec } from 'modules/adxcgBidAdapter.js';
+import { config } from 'src/config.js';
+import { createEidsArray } from 'modules/userId/eids.js';
+/* eslint dot-notation:0, quote-props:0 */
+import { expect } from 'chai';
+
+import { syncAddFPDToBidderRequest } from '../../helpers/fpd.js';
+import { deepClone } from '../../../src/utils';
+
const utils = require('src/utils');
describe('Adxcg adapter', function () {
let bids = [];
- describe('isBidRequestValid', function () {
- let bid = {
- 'bidder': 'adxcg',
- 'params': {
- 'adzoneid': '19910113'
- }
- };
-
- it('should return true when required params found', function () {
- assert(spec.isBidRequestValid(bid));
-
- bid.params = {
- adzoneid: 4332,
- };
- assert(spec.isBidRequestValid(bid));
- });
-
- it('should return false when required params are missing', function () {
- bid.params = {};
- assert.isFalse(spec.isBidRequestValid(bid));
-
- bid.params = {
- mname: 'some-placement'
- };
- assert.isFalse(spec.isBidRequestValid(bid));
-
- bid.params = {
- inv: 1234
- };
- assert.isFalse(spec.isBidRequestValid(bid));
- });
- });
-
- describe('buildRequests', function () {
- beforeEach(function () {
- config.resetConfig();
- });
- it('should send request with correct structure', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {
- adzoneid: '19910113'
- }
- }];
- let request = spec.buildRequests(validBidRequests, {refererInfo: {page: 'page', domain: 'localhost'}});
-
- assert.equal(request.method, 'POST');
- assert.equal(request.url, 'https://pbc.adxcg.net/rtb/ortb/pbc?adExchangeId=1');
- assert.deepEqual(request.options, {contentType: 'application/json'});
- assert.ok(request.data);
- });
-
- describe('user privacy', function () {
- it('should send GDPR Consent data to exchange if gdprApplies', function () {
- let validBidRequests = [{bidId: 'bidId', params: {test: 1}}];
- let bidderRequest = {
- gdprConsent: {gdprApplies: true, consentString: 'consentDataString'},
- refererInfo: {referer: 'page'}
- };
- let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
-
- assert.equal(request.user.ext.consent, bidderRequest.gdprConsent.consentString);
- assert.equal(request.regs.ext.gdpr, bidderRequest.gdprConsent.gdprApplies);
- assert.equal(typeof request.regs.ext.gdpr, 'number');
- });
-
- it('should send gdpr as number', function () {
- let validBidRequests = [{bidId: 'bidId', params: {test: 1}}];
- let bidderRequest = {
- gdprConsent: {gdprApplies: true, consentString: 'consentDataString'},
- refererInfo: {referer: 'page'}
- };
- let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
-
- assert.equal(typeof request.regs.ext.gdpr, 'number');
- assert.equal(request.regs.ext.gdpr, 1);
- });
-
- it('should send CCPA Consent data to exchange', function () {
- let validBidRequests = [{bidId: 'bidId', params: {test: 1}}];
- let bidderRequest = {uspConsent: '1YA-', refererInfo: {referer: 'page'}};
- let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
-
- assert.equal(request.regs.ext.us_privacy, '1YA-');
-
- bidderRequest = {
- uspConsent: '1YA-',
- gdprConsent: {gdprApplies: true, consentString: 'consentDataString'},
- refererInfo: {referer: 'page'}
- };
- request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
-
- assert.equal(request.regs.ext.us_privacy, '1YA-');
- assert.equal(request.user.ext.consent, 'consentDataString');
- assert.equal(request.regs.ext.gdpr, 1);
- });
-
- it('should not send GDPR Consent data to adxcg if gdprApplies is undefined', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {siteId: 'siteId'}
- }];
- let bidderRequest = {
- gdprConsent: {gdprApplies: false, consentString: 'consentDataString'},
- refererInfo: {referer: 'page'}
- };
- let request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
-
- assert.equal(request.user.ext.consent, 'consentDataString');
- assert.equal(request.regs.ext.gdpr, 0);
-
- bidderRequest = {gdprConsent: {consentString: 'consentDataString'}, refererInfo: {referer: 'page'}};
- request = JSON.parse(spec.buildRequests(validBidRequests, bidderRequest).data);
-
- assert.equal(request.user, undefined);
- assert.equal(request.regs, undefined);
- });
- it('should send default GDPR Consent data to exchange', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {siteId: 'siteId'}
- }];
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
-
- assert.equal(request.user, undefined);
- assert.equal(request.regs, undefined);
- });
- });
-
- it('should add test and is_debug to request, if test is set in parameters', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {test: 1}
- }];
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
-
- assert.ok(request.is_debug);
- assert.equal(request.test, 1);
- });
-
- it('should have default request structure', function () {
- let keys = 'site,geo,device,source,ext,imp'.split(',');
- let validBidRequests = [{
- bidId: 'bidId',
- params: {siteId: 'siteId'}
- }];
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
- let data = Object.keys(request);
-
- assert.deepEqual(keys, data);
- });
-
- it('should set request keys correct values', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {siteId: 'siteId'},
- }];
- let request = JSON.parse(spec.buildRequests(validBidRequests, {
- refererInfo: {referer: 'page'},
- ortb2: {source: {tid: 'tid'}}
- }).data);
-
- assert.equal(request.source.tid, 'tid');
- assert.equal(request.source.fd, 1);
- });
-
- it('should send info about device', function () {
- config.setConfig({
- device: {w: 100, h: 100}
- });
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: '1000'}
- }];
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {page: 'page', domain: 'localhost'}}).data);
-
- assert.equal(request.device.ua, navigator.userAgent);
- assert.equal(request.device.w, 100);
- assert.equal(request.device.h, 100);
- });
-
- it('should send app info', function () {
- config.setConfig({
- app: {id: 'appid'},
- });
- const ortb2 = {app: {name: 'appname'}}
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: '1000'},
- ortb2
- }];
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}, ortb2}).data);
-
- assert.equal(request.app.id, 'appid');
- assert.equal(request.app.name, 'appname');
- assert.equal(request.site, undefined);
- });
-
- it('should send info about the site', function () {
- config.setConfig({
- site: {
- id: '123123',
- publisher: {
- domain: 'publisher.domain.com'
- }
- },
- });
- const ortb2 = {
- site: {
- publisher: {
- id: 4441,
- name: 'publisher\'s name'
- }
- }
- };
-
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: '1000'},
- ortb2
- }];
- let refererInfo = {page: 'page', domain: 'localhost'};
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo, ortb2}).data);
-
- assert.deepEqual(request.site, {
- domain: 'localhost',
- id: '123123',
- page: refererInfo.page,
- publisher: {
- domain: 'publisher.domain.com',
- id: 4441,
- name: 'publisher\'s name'
- }
- });
- });
-
- it('should pass extended ids', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {},
- userIdAsEids: createEidsArray({
- tdid: 'TTD_ID_FROM_USER_ID_MODULE',
- pubcid: 'pubCommonId_FROM_USER_ID_MODULE'
- })
- }];
-
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
- assert.deepEqual(request.user.ext.eids, [
- {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}]}
- ]);
- });
-
- it('should send currency if defined', function () {
- config.setConfig({currency: {adServerCurrency: 'EUR'}});
- let validBidRequests = [{params: {}}];
- let refererInfo = {referer: 'page'};
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo}).data);
-
- assert.deepEqual(request.cur, ['EUR']);
- });
-
- it('should pass supply chain object', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {},
- schain: {
- validation: 'strict',
- config: {
- ver: '1.0'
- }
- }
- }];
-
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
- assert.deepEqual(request.source.ext.schain, {
- validation: 'strict',
- config: {
- ver: '1.0'
- }
- });
- });
-
- describe('bids', function () {
- it('should add more than one bid to the request', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {siteId: 'siteId'}
- }, {
- bidId: 'bidId2',
- params: {siteId: 'siteId'}
- }];
- let request = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data);
-
- assert.equal(request.imp.length, 2);
- });
- it('should add incrementing values of id', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: '1000'},
- mediaTypes: {video: {}}
- }, {
- bidId: 'bidId2',
- params: {adzoneid: '1000'},
- mediaTypes: {video: {}}
- }, {
- bidId: 'bidId3',
- params: {adzoneid: '1000'},
- mediaTypes: {video: {}}
- }];
- let imps = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp;
-
- for (let i = 0; i < 3; i++) {
- assert.equal(imps[i].id, i + 1);
- }
- });
-
- it('should add adzoneid', function () {
- let validBidRequests = [{bidId: 'bidId', params: {adzoneid: 1000}, mediaTypes: {video: {}}},
- {bidId: 'bidId2', params: {adzoneid: 1001}, mediaTypes: {video: {}}},
- {bidId: 'bidId3', params: {adzoneid: 1002}, mediaTypes: {video: {}}}];
- let imps = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp;
- for (let i = 0; i < 3; i++) {
- assert.equal(imps[i].tagid, validBidRequests[i].params.adzoneid);
- }
- });
-
- describe('price floors', function () {
- it('should not add if floors module not configured', function () {
- const validBidRequests = [{bidId: 'bidId', params: {adzoneid: 1000}, mediaTypes: {video: {}}}];
- let imp = getRequestImps(validBidRequests)[0];
-
- assert.equal(imp.bidfloor, undefined);
- assert.equal(imp.bidfloorcur, undefined);
- });
-
- it('should not add if floor price not defined', function () {
- const validBidRequests = [getBidWithFloor()];
- let imp = getRequestImps(validBidRequests)[0];
-
- assert.equal(imp.bidfloor, undefined);
- assert.equal(imp.bidfloorcur, 'USD');
- });
-
- it('should request floor price in adserver currency', function () {
- config.setConfig({currency: {adServerCurrency: 'DKK'}});
- const validBidRequests = [getBidWithFloor()];
- let imp = getRequestImps(validBidRequests)[0];
-
- assert.equal(imp.bidfloor, undefined);
- assert.equal(imp.bidfloorcur, 'DKK');
- });
-
- it('should add correct floor values', function () {
- const expectedFloors = [1, 1.3, 0.5];
- const validBidRequests = expectedFloors.map(getBidWithFloor);
- let imps = getRequestImps(validBidRequests);
-
- expectedFloors.forEach((floor, index) => {
- assert.equal(imps[index].bidfloor, floor);
- assert.equal(imps[index].bidfloorcur, 'USD');
- });
- });
-
- function getBidWithFloor(floor) {
- return {
- params: {adzoneid: 1},
- mediaTypes: {video: {}},
- getFloor: ({currency}) => {
- return {
- currency: currency,
- floor
- };
- }
- };
- }
- });
-
- describe('multiple media types', function () {
- it('should use all configured media types for bidding', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- mediaTypes: {
- banner: {
- sizes: [[100, 100], [200, 300]]
- },
- video: {}
- }
- }, {
- bidId: 'bidId1',
- params: {adzoneid: 1000},
- mediaTypes: {
- video: {},
- native: {}
- }
- }, {
- bidId: 'bidId2',
- params: {adzoneid: 1000},
- nativeParams: {
- title: {required: true, len: 140}
- },
- mediaTypes: {
- banner: {
- sizes: [[100, 100], [200, 300]]
- },
- native: {},
- video: {}
- }
- }];
- let [first, second, third] = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp;
-
- assert.ok(first.banner);
- assert.ok(first.video);
- assert.equal(first.native, undefined);
-
- assert.ok(second.video);
- assert.equal(second.banner, undefined);
- assert.equal(second.native, undefined);
-
- assert.ok(third.native);
- assert.ok(third.video);
- assert.ok(third.banner);
- });
- });
-
- describe('banner', function () {
- it('should convert sizes to openrtb format', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- mediaTypes: {
- banner: {
- sizes: [[100, 100], [200, 300]]
- }
- }
- }];
- let {banner} = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0];
- assert.deepEqual(banner, {
- format: [{w: 100, h: 100}, {w: 200, h: 300}]
- });
- });
- });
-
- describe('video', function () {
- it('should pass video mediatype config', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- mediaTypes: {
- video: {
- playerSize: [640, 480],
- context: 'outstream',
- mimes: ['video/mp4']
- }
- }
- }];
- let {video} = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0];
- assert.deepEqual(video, {
- playerSize: [640, 480],
- context: 'outstream',
- mimes: ['video/mp4']
- });
- });
- });
-
- describe('native', function () {
- describe('assets', function () {
- it('should set correct asset id', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- nativeParams: {
- title: {required: true, len: 140},
- image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
- body: {len: 140}
- }
- }];
- let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
- let assets = JSON.parse(nativeRequest).assets;
-
- assert.equal(assets[0].id, 0);
- assert.equal(assets[1].id, 3);
- assert.equal(assets[2].id, 4);
- });
- it('should add required key if it is necessary', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- nativeParams: {
- title: {required: true, len: 140},
- image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
- body: {len: 140},
- sponsoredBy: {required: true, len: 140}
- }
- }];
-
- let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
- let assets = JSON.parse(nativeRequest).assets;
-
- assert.equal(assets[0].required, 1);
- assert.ok(!assets[1].required);
- assert.ok(!assets[2].required);
- assert.equal(assets[3].required, 1);
- });
-
- it('should map img and data assets', function () {
- let validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- nativeParams: {
- title: {required: true, len: 140},
- image: {required: true, sizes: [150, 50]},
- icon: {required: false, sizes: [50, 50]},
- body: {required: false, len: 140},
- sponsoredBy: {required: true},
- cta: {required: false},
- clickUrl: {required: false}
- }
- }];
-
- let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
- let assets = JSON.parse(nativeRequest).assets;
- assert.ok(assets[0].title);
- assert.equal(assets[0].title.len, 140);
- assert.deepEqual(assets[1].img, {type: 3, w: 150, h: 50});
- assert.deepEqual(assets[2].img, {type: 1, w: 50, h: 50});
- assert.deepEqual(assets[3].data, {type: 2, len: 140});
- assert.deepEqual(assets[4].data, {type: 1});
- assert.deepEqual(assets[5].data, {type: 12});
- assert.ok(!assets[6]);
- });
-
- describe('icon/image sizing', function () {
- it('should flatten sizes and utilise first pair', function () {
- const validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- nativeParams: {
- image: {
- sizes: [[200, 300], [100, 200]]
- },
- }
- }];
-
- let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
- let assets = JSON.parse(nativeRequest).assets;
- assert.ok(assets[0].img);
- assert.equal(assets[0].img.w, 200);
- assert.equal(assets[0].img.h, 300);
- });
- });
-
- it('should utilise aspect_ratios', function () {
- const validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- nativeParams: {
- image: {
- aspect_ratios: [{
- min_width: 100,
- ratio_height: 3,
- ratio_width: 1
- }]
- },
- icon: {
- aspect_ratios: [{
- min_width: 10,
- ratio_height: 5,
- ratio_width: 2
- }]
- }
- }
- }];
-
- let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
- let assets = JSON.parse(nativeRequest).assets;
- assert.ok(assets[0].img);
- assert.equal(assets[0].img.wmin, 100);
- assert.equal(assets[0].img.hmin, 300);
-
- assert.ok(assets[1].img);
- assert.equal(assets[1].img.wmin, 10);
- assert.equal(assets[1].img.hmin, 25);
- });
-
- it('should not throw error if aspect_ratios config is not defined', function () {
- const validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- nativeParams: {
- image: {
- aspect_ratios: []
- },
- icon: {
- aspect_ratios: []
- }
- }
- }];
-
- assert.doesNotThrow(() => spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}));
- });
- });
-
- it('should expect any dimensions if min_width not passed', function () {
- const validBidRequests = [{
- bidId: 'bidId',
- params: {adzoneid: 1000},
- nativeParams: {
- image: {
- aspect_ratios: [{
- ratio_height: 3,
- ratio_width: 1
- }]
- }
- }
- }];
-
- let nativeRequest = JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp[0].native.request;
- let assets = JSON.parse(nativeRequest).assets;
- assert.ok(assets[0].img);
- assert.equal(assets[0].img.wmin, 0);
- assert.equal(assets[0].img.hmin, 0);
- assert.ok(!assets[1]);
- });
- });
- });
-
- function getRequestImps(validBidRequests) {
- return JSON.parse(spec.buildRequests(validBidRequests, {refererInfo: {referer: 'page'}}).data).imp;
- }
- });
-
- describe('interpretResponse', function () {
- it('should return if no body in response', function () {
- let serverResponse = {};
- let bidRequest = {};
-
- assert.ok(!spec.interpretResponse(serverResponse, bidRequest));
- });
- it('should return more than one bids', function () {
- let serverResponse = {
- body: {
- seatbid: [{
- bid: [{
- impid: '1',
- native: {ver: '1.1', link: {url: 'link'}, assets: [{id: 1, title: {text: 'Asset title text'}}]}
- }]
- }, {
- bid: [{
- impid: '2',
- native: {ver: '1.1', link: {url: 'link'}, assets: [{id: 1, data: {value: 'Asset title text'}}]}
- }]
- }]
- }
- };
- let bidRequest = {
- data: {},
- bids: [
- {
- bidId: 'bidId1',
- params: {adzoneid: 1000},
- nativeParams: {
- title: {required: true, len: 140},
- image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
- body: {len: 140}
- }
- },
- {
- bidId: 'bidId2',
- params: {adzoneid: 1000},
- nativeParams: {
- title: {required: true, len: 140},
- image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
- body: {len: 140}
- }
- }
- ]
- };
-
- bids = spec.interpretResponse(serverResponse, bidRequest);
- assert.equal(spec.interpretResponse(serverResponse, bidRequest).length, 2);
- });
-
- it('should set correct values to bid', function () {
- let nativeExample1 = {
- assets: [],
- link: {url: 'link'},
- imptrackers: ['imptrackers url1', 'imptrackers url2']
- }
-
- let serverResponse = {
- body: {
- id: null,
- bidid: null,
- seatbid: [{
- bid: [
- {
- impid: '1',
- price: 93.1231,
- crid: '12312312',
- adm: JSON.stringify(nativeExample1),
- dealid: 'deal-id',
- adomain: ['demo.com'],
- ext: {
- crType: 'native',
- advertiser_id: 'adv1',
- advertiser_name: 'advname',
- agency_name: 'agname',
- mediaType: 'native'
- }
- }
- ]
- }],
- cur: 'EUR'
- }
- };
- let bidRequest = {
- data: {},
- bids: [
- {
- bidId: 'bidId1',
- params: {adzoneid: 1000},
- nativeParams: {
- title: {required: true, len: 140},
- image: {required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif']},
- body: {len: 140}
- }
- }
- ]
- };
-
- const bids = spec.interpretResponse(serverResponse, bidRequest);
- const bid = serverResponse.body.seatbid[0].bid[0];
- assert.deepEqual(bids[0].requestId, bidRequest.bids[0].bidId);
- assert.deepEqual(bids[0].cpm, bid.price);
- assert.deepEqual(bids[0].creativeId, bid.crid);
- assert.deepEqual(bids[0].ttl, 300);
- assert.deepEqual(bids[0].netRevenue, false);
- assert.deepEqual(bids[0].currency, serverResponse.body.cur);
- assert.deepEqual(bids[0].mediaType, 'native');
- assert.deepEqual(bids[0].meta.mediaType, 'native');
- assert.deepEqual(bids[0].meta.advertiserDomains, ['demo.com']);
-
- assert.deepEqual(bids[0].meta.advertiserName, 'advname');
- assert.deepEqual(bids[0].meta.agencyName, 'agname');
-
- assert.deepEqual(bids[0].dealId, 'deal-id');
- });
-
- it('should return empty when there is no bids in response', function () {
- const serverResponse = {
- body: {
- id: null,
- bidid: null,
- seatbid: [{bid: []}],
- cur: 'EUR'
- }
- };
- let bidRequest = {
- data: {},
- bids: [{bidId: 'bidId1'}]
- };
- const result = spec.interpretResponse(serverResponse, bidRequest)[0];
- assert.ok(!result);
- });
-
- describe('banner', function () {
- it('should set ad content on response', function () {
- let serverResponse = {
- body: {
- seatbid: [{
- bid: [{impid: '1', adm: '
', ext: {crType: 'banner'}}]
- }]
- }
- };
- let bidRequest = {
- data: {},
- bids: [
- {
- bidId: 'bidId1',
- params: {adzoneid: 1000}
- }
- ]
- };
-
- bids = spec.interpretResponse(serverResponse, bidRequest);
- assert.equal(bids.length, 1);
- assert.equal(bids[0].ad, '');
- assert.equal(bids[0].mediaType, 'banner');
- assert.equal(bids[0].meta.mediaType, 'banner');
- });
- });
-
- describe('video', function () {
- it('should set vastXml on response', function () {
- let serverResponse = {
- body: {
- seatbid: [{
- bid: [{impid: '1', adm: '', ext: {crType: 'video'}}]
- }]
- }
- };
- let bidRequest = {
- data: {},
- bids: [
- {
- bidId: 'bidId1',
- params: {adzoneid: 1000}
- }
- ]
- };
-
- bids = spec.interpretResponse(serverResponse, bidRequest);
- assert.equal(bids.length, 1);
- assert.equal(bids[0].vastXml, '');
- assert.equal(bids[0].mediaType, 'video');
- assert.equal(bids[0].meta.mediaType, 'video');
- });
- });
- });
-
describe('getUserSyncs', function () {
const usersyncUrl = 'https://usersync-url.com';
beforeEach(() => {
@@ -846,55 +30,55 @@ describe('Adxcg adapter', function () {
})
it('should return user sync if pixel enabled with adxcg config', function () {
- const ret = spec.getUserSyncs({pixelEnabled: true})
- expect(ret).to.deep.equal([{type: 'image', url: usersyncUrl}])
+ const ret = spec.getUserSyncs({ pixelEnabled: true })
+ expect(ret).to.deep.equal([{ type: 'image', url: usersyncUrl }])
})
it('should not return user sync if pixel disabled', function () {
- const ret = spec.getUserSyncs({pixelEnabled: false})
+ const ret = spec.getUserSyncs({ pixelEnabled: false })
expect(ret).to.be.an('array').that.is.empty
})
it('should not return user sync if url is not set', function () {
config.resetConfig()
- const ret = spec.getUserSyncs({pixelEnabled: true})
+ const ret = spec.getUserSyncs({ pixelEnabled: true })
expect(ret).to.be.an('array').that.is.empty
})
- it('should pass GDPR consent', function() {
- expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, undefined)).to.deep.equal([{
+ it('should pass GDPR consent', function () {
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { gdprApplies: true, consentString: 'foo' }, undefined)).to.deep.equal([{
type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=foo`
}]);
- expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: false, consentString: 'foo'}, undefined)).to.deep.equal([{
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { gdprApplies: false, consentString: 'foo' }, undefined)).to.deep.equal([{
type: 'image', url: `${usersyncUrl}?gdpr=0&gdpr_consent=foo`
}]);
- expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: undefined}, undefined)).to.deep.equal([{
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { gdprApplies: true, consentString: undefined }, undefined)).to.deep.equal([{
type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=`
}]);
});
- it('should pass US consent', function() {
+ it('should pass US consent', function () {
expect(spec.getUserSyncs({ pixelEnabled: true }, {}, undefined, '1NYN')).to.deep.equal([{
type: 'image', url: `${usersyncUrl}?us_privacy=1NYN`
}]);
});
- it('should pass GDPR and US consent', function() {
- expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {gdprApplies: true, consentString: 'foo'}, '1NYN')).to.deep.equal([{
+ it('should pass GDPR and US consent', function () {
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { gdprApplies: true, consentString: 'foo' }, '1NYN')).to.deep.equal([{
type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=foo&us_privacy=1NYN`
}]);
});
});
- describe('onBidWon', function() {
- beforeEach(function() {
+ describe('onBidWon', function () {
+ beforeEach(function () {
sinon.stub(utils, 'triggerPixel');
});
- afterEach(function() {
+ afterEach(function () {
utils.triggerPixel.restore();
});
- it('Should trigger pixel if bid nurl', function() {
+ it('Should trigger pixel if bid nurl', function () {
const bid = {
nurl: 'http://example.com/win/${AUCTION_PRICE}',
cpm: 2.1,
@@ -904,4 +88,510 @@ describe('Adxcg adapter', function () {
expect(utils.triggerPixel.callCount).to.equal(1)
})
})
+
+ it('should return just to have at least 1 karma test ok', function () {
+ assert(true);
+ });
+});
+
+describe('adxcg v8 oRtbConverter Adapter Tests', function () {
+ const slotConfigs = [{
+ placementCode: '/DfpAccount1/slot1',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90], [160, 600]]
+ }
+ },
+ bidId: 'bid12345',
+ params: {
+ cp: 'p10000',
+ ct: 't10000',
+ cf: '300x250',
+ adzoneid: '77'
+ }
+ }, {
+ placementCode: '/DfpAccount2/slot2',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90]]
+ }
+ },
+ bidId: 'bid23456',
+ params: {
+ cp: 'p10000',
+ ct: 't20000',
+ cf: '728x90',
+ adzoneid: '77'
+ }
+ }];
+ const nativeOrtbRequest = {
+ assets: [{
+ id: 1,
+ required: 1,
+ img: {
+ type: 3,
+ w: 150,
+ h: 50,
+ }
+ },
+ {
+ id: 2,
+ required: 1,
+ title: {
+ len: 80
+ }
+ },
+ {
+ id: 3,
+ required: 0,
+ data: {
+ type: 1
+ }
+ }]
+ };
+ const nativeSlotConfig = [{
+ placementCode: '/DfpAccount1/slot3',
+ bidId: 'bid12345',
+ mediaTypes: {
+ native: {
+ sendTargetingKeys: false,
+ ortb: nativeOrtbRequest
+ }
+ },
+ nativeOrtbRequest,
+ params: {
+ cp: 'p10000',
+ ct: 't10000',
+ adzoneid: '77'
+ }
+ }];
+ const videoSlotConfig = [{
+ placementCode: '/DfpAccount1/slotVideo',
+ bidId: 'bid12345',
+ mediaTypes: {
+ video: {
+ playerSize: [400, 300],
+ w: 400,
+ h: 300,
+ minduration: 5,
+ maxduration: 10,
+ startdelay: 0,
+ skip: 1,
+ minbitrate: 200,
+ protocols: [1, 2, 4]
+ }
+ },
+ params: {
+ cp: 'p10000',
+ ct: 't10000',
+ adzoneid: '77'
+ }
+ }];
+ const additionalParamsConfig = [{
+ placementCode: '/DfpAccount1/slot1',
+ mediaTypes: {
+ banner: {
+ sizes: [[1, 1]]
+ }
+ },
+ bidId: 'bid12345',
+ params: {
+ cp: 'p10000',
+ ct: 't10000',
+ cf: '1x1',
+ adzoneid: '77',
+ extra_key1: 'extra_val1',
+ extra_key2: 12345,
+ extra_key3: {
+ key1: 'val1',
+ key2: 23456,
+ },
+ extra_key4: [1, 2, 3]
+ }
+ }];
+
+ const schainParamsSlotConfig = [{
+ placementCode: '/DfpAccount1/slot1',
+ mediaTypes: {
+ banner: {
+ sizes: [[1, 1]]
+ }
+ },
+ bidId: 'bid12345',
+ params: {
+ cp: 'p10000',
+ ct: 't10000',
+ cf: '1x1',
+ adzoneid: '77',
+ bcat: ['IAB-1', 'IAB-20'],
+ battr: [1, 2, 3],
+ bidfloor: 1.5,
+ badv: ['cocacola.com', 'lays.com']
+ },
+ schain: {
+ 'ver': '1.0',
+ 'complete': 1,
+ 'nodes': [
+ {
+ 'asi': 'exchange1.com',
+ 'sid': '1234',
+ 'hp': 1,
+ 'rid': 'bid-request-1',
+ 'name': 'publisher',
+ 'domain': 'publisher.com'
+ }
+ ]
+ },
+ }];
+
+ const bidderRequest = {
+ refererInfo: {
+ page: 'https://publisher.com/home',
+ ref: 'https://referrer'
+ }
+ };
+
+ it('Verify build request', function () {
+ const request = spec.buildRequests(slotConfigs, syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.url).to.equal('https://pbc.adxcg.net/rtb/ortb/pbc?adExchangeId=1');
+ expect(request.method).to.equal('POST');
+ const ortbRequest = request.data;
+ // site object
+ expect(ortbRequest.site).to.not.equal(null);
+ expect(ortbRequest.site.publisher).to.not.equal(null);
+ // expect(ortbRequest.site.publisher.id).to.equal('p10000');
+ expect(ortbRequest.site.page).to.equal('https://publisher.com/home');
+ expect(ortbRequest.imp).to.have.lengthOf(2);
+ // device object
+ expect(ortbRequest.device).to.not.equal(null);
+ expect(ortbRequest.device.ua).to.equal(navigator.userAgent);
+ // slot 1
+ // expect(ortbRequest.imp[0].tagid).to.equal('t10000');
+ expect(ortbRequest.imp[0].banner).to.not.equal(null);
+ expect(ortbRequest.imp[0].banner.format).to.deep.eq([{ 'w': 728, 'h': 90 }, { 'w': 160, 'h': 600 }]);
+ // slot 2
+ // expect(ortbRequest.imp[1].tagid).to.equal('t20000');
+ expect(ortbRequest.imp[1].banner).to.not.equal(null);
+ expect(ortbRequest.imp[1].banner.format).to.deep.eq([{ 'w': 728, 'h': 90 }]);
+ });
+
+ it('Verify parse response', function () {
+ const request = spec.buildRequests(slotConfigs, syncAddFPDToBidderRequest(bidderRequest));
+ const ortbRequest = request.data;
+ const ortbResponse = {
+ seatbid: [{
+ bid: [{
+ impid: ortbRequest.imp[0].id,
+ price: 1.25,
+ adm: 'This is an Ad',
+ crid: 'Creative#123',
+ mtype: 1,
+ w: 300,
+ h: 250,
+ exp: 20,
+ adomain: ['advertiser.com']
+ }]
+ }]
+ };
+ const bids = spec.interpretResponse({ body: ortbResponse }, request);
+ expect(bids).to.have.lengthOf(1);
+ // verify first bid
+ const bid = bids[0];
+ expect(bid.cpm).to.equal(1.25);
+ expect(bid.ad).to.equal('This is an Ad');
+ expect(bid.width).to.equal(300);
+ expect(bid.height).to.equal(250);
+ expect(bid.creative_id).to.equal('Creative#123');
+ expect(bid.creativeId).to.equal('Creative#123');
+ expect(bid.netRevenue).to.equal(true);
+ expect(bid.currency).to.equal('EUR');
+ expect(bid.ttl).to.equal(20);
+ expect(bid.meta).to.not.be.null;
+ expect(bid.meta.advertiserDomains).to.eql(['advertiser.com']);
+ });
+
+ it('Verify full passback', function () {
+ const request = spec.buildRequests(slotConfigs, bidderRequest);
+ const bids = spec.interpretResponse({ body: null }, request)
+ expect(bids).to.have.lengthOf(0);
+ });
+
+ if (FEATURES.NATIVE) {
+ it('Verify Native request', function () {
+ const request = spec.buildRequests(nativeSlotConfig, syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.url).to.equal('https://pbc.adxcg.net/rtb/ortb/pbc?adExchangeId=1');
+ expect(request.method).to.equal('POST');
+ const ortbRequest = request.data;
+ // native impression
+ expect(ortbRequest.imp[0].tagid).to.equal('77');
+ expect(ortbRequest.imp[0].banner).to.be.undefined;
+ const nativePart = ortbRequest.imp[0]['native'];
+ expect(nativePart).to.not.equal(null);
+ expect(nativePart.request).to.not.equal(null);
+ // native request assets
+ const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request);
+ expect(nativeRequest).to.not.equal(null);
+ expect(nativeRequest.assets).to.have.lengthOf(3);
+ // image asset
+ expect(nativeRequest.assets[0].id).to.equal(1);
+ expect(nativeRequest.assets[0].required).to.equal(1);
+ expect(nativeRequest.assets[0].title).to.be.undefined;
+ expect(nativeRequest.assets[0].img).to.not.equal(null);
+ expect(nativeRequest.assets[0].img.w).to.equal(150);
+ expect(nativeRequest.assets[0].img.h).to.equal(50);
+ expect(nativeRequest.assets[0].img.type).to.equal(3);
+ // title asset
+ expect(nativeRequest.assets[1].id).to.equal(2);
+ expect(nativeRequest.assets[1].required).to.equal(1);
+ expect(nativeRequest.assets[1].title).to.not.equal(null);
+ expect(nativeRequest.assets[1].title.len).to.equal(80);
+ // data asset
+ expect(nativeRequest.assets[2].id).to.equal(3);
+ expect(nativeRequest.assets[2].required).to.equal(0);
+ expect(nativeRequest.assets[2].title).to.be.undefined;
+ expect(nativeRequest.assets[2].data).to.not.equal(null);
+ expect(nativeRequest.assets[2].data.type).to.equal(1);
+ });
+
+ it('Verify Native response', function () {
+ const request = spec.buildRequests(nativeSlotConfig, syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.url).to.equal('https://pbc.adxcg.net/rtb/ortb/pbc?adExchangeId=1');
+ expect(request.method).to.equal('POST');
+ const ortbRequest = request.data;
+ const nativeResponse = {
+ assets: [
+ { id: 1, img: { type: 3, url: 'https://images.cdn.brand.com/123' } },
+ { id: 2, title: { text: 'Ad Title' } },
+ { id: 3, data: { type: 1, value: 'Sponsored By: Brand' } }
+ ],
+ link: { url: 'https://brand.clickme.com/' },
+ imptrackers: ['https://imp1.trackme.com/', 'https://imp1.contextweb.com/']
+
+ };
+ const ortbResponse = {
+ seatbid: [{
+ bid: [{
+ impid: ortbRequest.imp[0].id,
+ price: 1.25,
+ adm: JSON.stringify(nativeResponse),
+ mtype: 4
+ }]
+ }]
+ };
+ const bids = spec.interpretResponse({ body: ortbResponse }, request);
+ // verify bid
+ const bid = bids[0];
+ expect(bid.cpm).to.equal(1.25);
+ expect(bid.requestId).to.equal('bid12345');
+ expect(bid.ad).to.be.undefined;
+ expect(bid.mediaType).to.equal('native');
+ expect(bid['native']).to.not.be.null;
+ expect(bid['native'].ortb).to.not.be.null;
+ const nativeBid = bid['native'].ortb;
+ expect(nativeBid.assets).to.have.lengthOf(3);
+ expect(nativeBid.assets[0].id).to.equal(1);
+ expect(nativeBid.assets[0].img).to.not.be.null;
+ expect(nativeBid.assets[0].img.type).to.equal(3);
+ expect(nativeBid.assets[0].img.url).to.equal('https://images.cdn.brand.com/123');
+ expect(nativeBid.assets[1].id).to.equal(2);
+ expect(nativeBid.assets[1].title).to.not.be.null;
+ expect(nativeBid.assets[1].title.text).to.equal('Ad Title');
+ expect(nativeBid.assets[2].id).to.equal(3);
+ expect(nativeBid.assets[2].data).to.not.be.null;
+ expect(nativeBid.assets[2].data.type).to.equal(1);
+ expect(nativeBid.assets[2].data.value).to.equal('Sponsored By: Brand');
+ expect(nativeBid.link).to.not.be.null;
+ expect(nativeBid.link.url).to.equal('https://brand.clickme.com/');
+ expect(nativeBid.imptrackers).to.have.lengthOf(2);
+ expect(nativeBid.imptrackers[0]).to.equal('https://imp1.trackme.com/');
+ expect(nativeBid.imptrackers[1]).to.equal('https://imp1.contextweb.com/');
+ });
+ }
+
+ it('Verifies bidder code', function () {
+ expect(spec.code).to.equal('adxcg');
+ });
+
+ it('Verifies bidder aliases', function () {
+ expect(spec.aliases).to.have.lengthOf(1);
+ expect(spec.aliases[0]).to.equal('mediaopti');
+ });
+
+ it('Verifies supported media types', function () {
+ expect(spec.supportedMediaTypes).to.have.lengthOf(3);
+ expect(spec.supportedMediaTypes[0]).to.equal('banner');
+ expect(spec.supportedMediaTypes[1]).to.equal('native');
+ expect(spec.supportedMediaTypes[2]).to.equal('video');
+ });
+
+ if (FEATURES.VIDEO) {
+ it('Verify Video request', function () {
+ const request = spec.buildRequests(videoSlotConfig, syncAddFPDToBidderRequest(bidderRequest));
+ expect(request.url).to.equal('https://pbc.adxcg.net/rtb/ortb/pbc?adExchangeId=1');
+ expect(request.method).to.equal('POST');
+ const ortbRequest = request.data;
+ expect(ortbRequest).to.not.equal(null);
+ expect(ortbRequest.imp).to.have.lengthOf(1);
+ expect(ortbRequest.imp[0].video).to.not.be.null;
+ expect(ortbRequest.imp[0].native).to.be.undefined;
+ expect(ortbRequest.imp[0].banner).to.be.undefined;
+ expect(ortbRequest.imp[0].video.w).to.equal(400);
+ expect(ortbRequest.imp[0].video.h).to.equal(300);
+ expect(ortbRequest.imp[0].video.minduration).to.equal(5);
+ expect(ortbRequest.imp[0].video.maxduration).to.equal(10);
+ expect(ortbRequest.imp[0].video.startdelay).to.equal(0);
+ expect(ortbRequest.imp[0].video.skip).to.equal(1);
+ expect(ortbRequest.imp[0].video.minbitrate).to.equal(200);
+ expect(ortbRequest.imp[0].video.protocols).to.eql([1, 2, 4]);
+ });
+ }
+
+ it('Verify extra parameters', function () {
+ let request = spec.buildRequests(additionalParamsConfig, syncAddFPDToBidderRequest(bidderRequest));
+ let ortbRequest = request.data;
+ expect(ortbRequest).to.not.equal(null);
+ expect(ortbRequest.imp).to.have.lengthOf(1);
+ expect(ortbRequest.imp[0].ext).to.not.equal(null);
+ expect(ortbRequest.imp[0].ext.prebid).to.not.equal(null);
+ expect(ortbRequest.imp[0].ext.prebid).to.not.be.null;
+ expect(ortbRequest.imp[0].ext.prebid.extra_key1).to.equal('extra_val1');
+ expect(ortbRequest.imp[0].ext.prebid.extra_key2).to.equal(12345);
+ expect(ortbRequest.imp[0].ext.prebid.extra_key3).to.not.be.null;
+ expect(ortbRequest.imp[0].ext.prebid.extra_key3.key1).to.equal('val1');
+ expect(ortbRequest.imp[0].ext.prebid.extra_key3.key2).to.equal(23456);
+ expect(ortbRequest.imp[0].ext.prebid.extra_key4).to.eql([1, 2, 3]);
+ expect(Object.keys(ortbRequest.imp[0].ext.prebid)).to.eql(['adzoneid', 'extra_key1', 'extra_key2', 'extra_key3', 'extra_key4']);
+ // attempting with a configuration with no unknown params.
+ request = spec.buildRequests(videoSlotConfig, bidderRequest);
+ ortbRequest = request.data;
+ expect(ortbRequest).to.not.equal(null);
+ expect(ortbRequest.imp).to.have.lengthOf(1);
+ // expect(ortbRequest.imp[0].ext).to.be.undefined;
+ });
+
+ it('Verify user level first party data', function () {
+ const bidderRequest = {
+ refererInfo: {
+ page: 'https://publisher.com/home',
+ ref: 'https://referrer'
+ },
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: 'serialized_gpdr_data'
+ },
+ ortb2: {
+ user: {
+ yob: 1985,
+ gender: 'm',
+ ext: {
+ data: {
+ registered: true,
+ interests: ['cars']
+ }
+ }
+ }
+ }
+ };
+ let request = spec.buildRequests(slotConfigs, syncAddFPDToBidderRequest(bidderRequest));
+ let ortbRequest = request.data;
+ expect(ortbRequest).to.not.equal(null);
+ expect(ortbRequest.user).to.not.equal(null);
+ });
+
+ it('Verify site level first party data', function () {
+ const bidderRequest = {
+ ortb2: {
+ site: {
+ content: {
+ data: [{
+ name: 'www.iris.com',
+ ext: {
+ segtax: 500,
+ cids: ['iris_c73g5jq96mwso4d8']
+ }
+ }]
+ },
+ page: 'http://pub.com/news',
+ ref: 'http://google.com',
+ publisher: {
+ domain: 'pub.com'
+ }
+ }
+ }
+ };
+ let request = spec.buildRequests(slotConfigs, syncAddFPDToBidderRequest(bidderRequest));
+ let ortbRequest = request.data;
+ expect(ortbRequest).to.not.equal(null);
+ expect(ortbRequest.site).to.not.equal(null);
+ expect(ortbRequest.site).to.deep.equal({
+ content: {
+ data: [{
+ name: 'www.iris.com',
+ ext: {
+ segtax: 500,
+ cids: ['iris_c73g5jq96mwso4d8']
+ }
+ }]
+ },
+ page: 'http://pub.com/news',
+ ref: 'http://google.com',
+ publisher: {
+ // id: 'p10000',
+ domain: 'pub.com'
+ }
+ });
+ });
+
+ it('Verify impression/slot level first party data', function () {
+ const bidderRequests = [{
+ placementCode: '/DfpAccount1/slot1',
+ mediaTypes: {
+ banner: {
+ sizes: [[1, 1]]
+ }
+ },
+ bidId: 'bid12345',
+ params: {
+ cp: 'p10000',
+ ct: 't10000',
+ adzoneid: '77',
+ extra_key1: 'extra_val1',
+ extra_key2: 12345
+ },
+ ortb2Imp: {
+ ext: {
+ data: {
+ pbadslot: 'homepage-top-rect',
+ adUnitSpecificAttribute: '123'
+ }
+ }
+ }
+ }];
+ let request = spec.buildRequests(bidderRequests, bidderRequest);
+ let ortbRequest = request.data;
+ expect(ortbRequest).to.not.equal(null);
+ expect(ortbRequest.imp).to.not.equal(null);
+ expect(ortbRequest.imp).to.have.lengthOf(1);
+ expect(ortbRequest.imp[0].ext).to.not.equal(null);
+ expect(ortbRequest.imp[0].ext).to.deep.equal({
+ prebid: {
+ adzoneid: '77',
+ extra_key1: 'extra_val1',
+ extra_key2: 12345
+ },
+ data: {
+ pbadslot: 'homepage-top-rect',
+ adUnitSpecificAttribute: '123'
+ }
+ });
+ });
+
+ it('Verify bid request timeouts', function () {
+ const mkRequest = (bidderRequest) => spec.buildRequests(slotConfigs, bidderRequest).data;
+ // assert default is used when no bidderRequest.timeout value is available
+ expect(mkRequest(bidderRequest).tmax).to.equal(500)
+
+ // assert bidderRequest value is used when available
+ expect(mkRequest(Object.assign({}, { timeout: 6000 }, bidderRequest)).tmax).to.equal(6000)
+ });
});
diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js
index de77c741364..ffd6729397a 100644
--- a/test/spec/modules/adyoulikeBidAdapter_spec.js
+++ b/test/spec/modules/adyoulikeBidAdapter_spec.js
@@ -2,6 +2,7 @@ import { expect } from 'chai';
import { spec } from 'modules/adyoulikeBidAdapter.js';
import { newBidder } from 'src/adapters/bidderFactory.js';
+import { config } from 'src/config.js';
describe('Adyoulike Adapter', function () {
const canonicalUrl = 'https://canonical.url/?t=%26';
@@ -887,4 +888,115 @@ describe('Adyoulike Adapter', function () {
expect(spec.gvlid).to.equal(259)
})
});
+
+ describe('getUserSyncs', function () {
+ const syncurl_iframe = 'https://visitor.omnitagjs.com/visitor/isync?uid=19340f4f097d16f41f34fc0274981ca4';
+
+ const emptySync = [];
+
+ describe('with iframe enabled', function() {
+ const userSyncConfig = { iframeEnabled: true };
+
+ it('should not add parameters if not provided', function() {
+ expect(spec.getUserSyncs(userSyncConfig, {}, undefined, undefined)).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}`
+ }]);
+ });
+
+ it('should add GDPR parameters if provided', function() {
+ expect(spec.getUserSyncs(userSyncConfig, {}, {gdprApplies: true, consentString: undefined}, undefined)).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}&gdpr=1&gdpr_consent=`
+ }]);
+
+ expect(spec.getUserSyncs(userSyncConfig, {}, {gdprApplies: true, consentString: 'foo?'}, undefined)).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}&gdpr=1&gdpr_consent=foo%3F`
+ }]);
+ expect(spec.getUserSyncs(userSyncConfig, {}, {gdprApplies: false, consentString: 'bar'}, undefined)).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}&gdpr=0&gdpr_consent=bar`
+ }]);
+ });
+
+ it('should add CCPA parameters if provided', function() {
+ expect(spec.getUserSyncs(userSyncConfig, {}, undefined, 'foo?')).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}&us_privacy=foo%3F`
+ }]);
+ });
+
+ describe('COPPA', function() {
+ let sandbox;
+
+ this.beforeEach(function() {
+ sandbox = sinon.sandbox.create();
+ });
+
+ this.afterEach(function() {
+ sandbox.restore();
+ });
+
+ it('should add coppa parameters if provided', function() {
+ sandbox.stub(config, 'getConfig').callsFake(key => {
+ const config = {
+ 'coppa': true
+ };
+ return config[key];
+ });
+
+ expect(spec.getUserSyncs(userSyncConfig, {}, undefined, undefined)).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}&coppa=1`
+ }]);
+ });
+ });
+
+ describe('GPP', function() {
+ it('should not apply if not gppConsent.gppString', function() {
+ const gppConsent = { gppString: '', applicableSections: [123] };
+ const result = spec.getUserSyncs(userSyncConfig, {}, undefined, undefined, gppConsent);
+ expect(result).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}`
+ }]);
+ });
+
+ it('should not apply if not gppConsent.applicableSections', function() {
+ const gppConsent = { gppString: '', applicableSections: undefined };
+ const result = spec.getUserSyncs(userSyncConfig, {}, undefined, undefined, gppConsent);
+ expect(result).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}`
+ }]);
+ });
+
+ it('should not apply if empty gppConsent.applicableSections', function() {
+ const gppConsent = { gppString: '', applicableSections: [] };
+ const result = spec.getUserSyncs(userSyncConfig, {}, undefined, undefined, gppConsent);
+ expect(result).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}`
+ }]);
+ });
+
+ it('should apply if all above are available', function() {
+ const gppConsent = { gppString: 'foo?', applicableSections: [123] };
+ const result = spec.getUserSyncs(userSyncConfig, {}, undefined, undefined, gppConsent);
+ expect(result).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}&gpp=foo%3F&gpp_sid=123`
+ }]);
+ });
+
+ it('should support multiple sections', function() {
+ const gppConsent = { gppString: 'foo', applicableSections: [123, 456] };
+ const result = spec.getUserSyncs(userSyncConfig, {}, undefined, undefined, gppConsent);
+ expect(result).to.deep.equal([{
+ type: 'iframe', url: `${syncurl_iframe}&gpp=foo&gpp_sid=123%2C456`
+ }]);
+ });
+ });
+ });
+
+ describe('with iframe disabled', function() {
+ const userSyncConfig = { iframeEnabled: false };
+
+ it('should return empty list of syncs', function() {
+ expect(spec.getUserSyncs(userSyncConfig, {}, undefined, undefined)).to.deep.equal(emptySync);
+ expect(spec.getUserSyncs(userSyncConfig, {}, {gdprApplies: true, consentString: 'foo'}, 'bar')).to.deep.equal(emptySync);
+ });
+ });
+ });
});
diff --git a/test/spec/modules/agmaAnalyticsAdapter_spec.js b/test/spec/modules/agmaAnalyticsAdapter_spec.js
new file mode 100644
index 00000000000..ba71624e3b3
--- /dev/null
+++ b/test/spec/modules/agmaAnalyticsAdapter_spec.js
@@ -0,0 +1,388 @@
+import adapterManager from '../../../src/adapterManager.js';
+import agmaAnalyticsAdapter, {
+ getTiming,
+ getOrtb2Data,
+ getPayload,
+} from '../../../modules/agmaAnalyticsAdapter.js';
+import { gdprDataHandler } from '../../../src/adapterManager.js';
+import { expect } from 'chai';
+import * as events from '../../../src/events.js';
+import constants from '../../../src/constants.json';
+import { generateUUID } from '../../../src/utils.js';
+import { server } from '../../mocks/xhr.js';
+import { config } from 'src/config.js';
+
+const INGEST_URL = 'https://pbc.agma-analytics.de/v1';
+const extendedKey = [
+ 'auctionIds',
+ 'code',
+ 'domain',
+ 'extended',
+ 'gdprApplies',
+ 'gdprConsentString',
+ 'language',
+ 'ortb2',
+ 'pageUrl',
+ 'pageViewId',
+ 'prebidVersion',
+ 'referrer',
+ 'screenHeight',
+ 'screenWidth',
+ 'scriptVersion',
+ 'timestamp',
+ 'timezoneOffset',
+ 'timing',
+ 'triggerEvent',
+ 'userIdsAsEids',
+];
+const nonExtendedKey = [
+ 'auctionIds',
+ 'code',
+ 'domain',
+ 'gdprApplies',
+ 'ortb2',
+ 'pageUrl',
+ 'pageViewId',
+ 'prebidVersion',
+ 'scriptVersion',
+ 'timing',
+ 'triggerEvent',
+];
+
+describe('AGMA Analytics Adapter', () => {
+ let agmaConfig, sandbox, clock;
+
+ beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+ clock = sandbox.useFakeTimers();
+ sandbox.stub(events, 'getEvents').returns([]);
+ agmaConfig = {
+ options: {
+ code: 'test',
+ },
+ };
+ });
+
+ afterEach(() => {
+ sandbox.restore();
+ });
+
+ describe('configuration', () => {
+ it('registers itself with the adapter manager', () => {
+ const adapter = adapterManager.getAnalyticsAdapter('agma');
+ expect(adapter).to.exist;
+ expect(adapter.gvlid).to.equal(1122);
+ });
+ });
+
+ describe('getPayload', () => {
+ it('should use non extended payload with no consent info', () => {
+ sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(() => null)
+ const payload = getPayload([generateUUID()], {
+ code: 'test',
+ });
+
+ expect(payload).to.have.all.keys([...nonExtendedKey, 'debug']);
+ });
+
+ it('should use non extended payload when agma is not in the TC String', () => {
+ sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(() => ({
+ vendorData: {
+ vendor: {
+ consents: {
+ 1122: false,
+ },
+ },
+ },
+ }));
+ const payload = getPayload([generateUUID()], {
+ code: 'test',
+ });
+ expect(payload).to.have.all.keys([...nonExtendedKey, 'debug']);
+ });
+
+ it('should use extended payload when agma is in the TC String', () => {
+ sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(() => ({
+ vendorData: {
+ vendor: {
+ consents: {
+ 1122: true,
+ },
+ },
+ },
+ }));
+ const payload = getPayload([generateUUID()], {
+ code: 'test',
+ });
+ expect(payload).to.have.all.keys([...extendedKey, 'debug']);
+ });
+ });
+
+ describe('getTiming', () => {
+ let originalPerformance;
+ let originalWindowPerformanceNow;
+
+ beforeEach(() => {
+ originalPerformance = global.performance;
+ originalWindowPerformanceNow = window.performance.now;
+ });
+
+ afterEach(() => {
+ global.performance = originalPerformance;
+ window.performance.now = originalWindowPerformanceNow;
+ });
+
+ it('returns TTFB using Timing API V2', () => {
+ global.performance = {
+ getEntriesByType: sinon
+ .stub()
+ .returns([{ responseStart: 100, startTime: 50 }]),
+ now: sinon.stub().returns(150),
+ };
+
+ const result = getTiming();
+
+ expect(result).to.deep.equal({ ttfb: 50, elapsedTime: 150 });
+ });
+
+ it('returns TTFB using Timing API V1 when V2 is not available', () => {
+ global.performance = {
+ getEntriesByType: sinon.stub().throws(),
+ timing: { responseStart: 150, fetchStart: 50 },
+ now: sinon.stub().returns(200),
+ };
+
+ const result = getTiming();
+
+ expect(result).to.deep.equal({ ttfb: 100, elapsedTime: 200 });
+ });
+
+ it('returns null when Timing API is not available', () => {
+ global.performance = {
+ getEntriesByType: sinon.stub().throws(),
+ timing: undefined,
+ };
+
+ const result = getTiming();
+
+ expect(result).to.be.null;
+ });
+
+ it('returns ttfb as 0 if calculated value is negative', () => {
+ global.performance = {
+ getEntriesByType: sinon
+ .stub()
+ .returns([{ responseStart: 50, startTime: 150 }]),
+ now: sinon.stub().returns(200),
+ };
+
+ const result = getTiming();
+
+ expect(result).to.deep.equal({ ttfb: 0, elapsedTime: 200 });
+ });
+
+ it('returns ttfb as 0 if calculated value exceeds performance.now()', () => {
+ global.performance = {
+ getEntriesByType: sinon
+ .stub()
+ .returns([{ responseStart: 50, startTime: 0 }]),
+ now: sinon.stub().returns(40),
+ };
+
+ const result = getTiming();
+
+ expect(result).to.deep.equal({ ttfb: 0, elapsedTime: 40 });
+ });
+ });
+
+ describe('getOrtb2Data', () => {
+ it('returns site and user from options when available', () => {
+ sandbox.stub(config, 'getConfig').callsFake((key) => {
+ return {};
+ });
+
+ const ortb2 = {
+ user: 'user',
+ site: 'site',
+ };
+
+ const result = getOrtb2Data({
+ ortb2,
+ });
+
+ expect(result).to.deep.equal(ortb2);
+ });
+
+ it('returns a combination of data from options and pGlobal.readConfig', () => {
+ sandbox.stub(config, 'getConfig').callsFake((key) => {
+ return {
+ ortb2: {
+ site: {
+ foo: 'bar',
+ },
+ },
+ };
+ });
+
+ const ortb2 = {
+ user: 'user',
+ };
+ const result = getOrtb2Data({
+ ortb2,
+ });
+
+ expect(result).to.deep.equal({
+ site: {
+ foo: 'bar',
+ },
+ user: 'user',
+ });
+ });
+ });
+
+ describe('Event Payload', () => {
+ beforeEach(() => {
+ agmaAnalyticsAdapter.enableAnalytics({
+ ...agmaConfig,
+ });
+ server.respondWith('POST', INGEST_URL, [
+ 200,
+ {
+ 'Content-Type': 'application/json',
+ 'Access-Control-Allow-Origin': '*',
+ },
+ '',
+ ]);
+ });
+
+ afterEach(() => {
+ agmaAnalyticsAdapter.auctionIds = [];
+ if (agmaAnalyticsAdapter.timer) {
+ clearTimeout(agmaAnalyticsAdapter.timer);
+ }
+ agmaAnalyticsAdapter.disableAnalytics();
+ });
+
+ it('should only send once per minute', () => {
+ sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(() => ({
+ gdprApplies: true,
+ consentString: 'consentDataString',
+ vendorData: {
+ vendor: {
+ consents: {
+ 1122: true,
+ },
+ },
+ },
+ }));
+ const auction = {
+ auctionId: generateUUID(),
+ };
+
+ events.emit(constants.EVENTS.AUCTION_INIT, {
+ auctionId: generateUUID('1'),
+ auction,
+ });
+
+ clock.tick(200);
+
+ events.emit(constants.EVENTS.AUCTION_INIT, {
+ auctionId: generateUUID('2'),
+ auction,
+ });
+ events.emit(constants.EVENTS.AUCTION_INIT, {
+ auctionId: generateUUID('3'),
+ auction,
+ });
+ events.emit(constants.EVENTS.AUCTION_INIT, {
+ auctionId: generateUUID('4'),
+ auction,
+ });
+
+ clock.tick(900);
+
+ const [request] = server.requests;
+ const requestBody = JSON.parse(request.requestBody);
+ expect(request.url).to.equal(INGEST_URL);
+ expect(requestBody).to.have.all.keys(extendedKey);
+ expect(requestBody.triggerEvent).to.equal(constants.EVENTS.AUCTION_INIT);
+ expect(server.requests).to.have.length(1);
+ });
+
+ it('should send the extended payload with consent', () => {
+ sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(() => ({
+ gdprApplies: true,
+ consentString: 'consentDataString',
+ vendorData: {
+ vendor: {
+ consents: {
+ 1122: true,
+ },
+ },
+ },
+ }));
+ const auction = {
+ auctionId: generateUUID(),
+ };
+
+ events.emit(constants.EVENTS.AUCTION_INIT, auction);
+ clock.tick(1100);
+
+ const [request] = server.requests;
+ const requestBody = JSON.parse(request.requestBody);
+ expect(request.url).to.equal(INGEST_URL);
+ expect(requestBody).to.have.all.keys(extendedKey);
+ expect(requestBody.triggerEvent).to.equal(constants.EVENTS.AUCTION_INIT);
+ expect(server.requests).to.have.length(1);
+ expect(agmaAnalyticsAdapter.auctionIds).to.have.length(0);
+ });
+
+ it('should send the non extended payload with no explicit consent', () => {
+ sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(() => ({
+ gdprApplies: true,
+ consentString: 'consentDataString',
+ }));
+
+ const auction = {
+ auctionId: generateUUID(),
+ };
+
+ events.emit(constants.EVENTS.AUCTION_INIT, auction);
+ clock.tick(1000);
+
+ const [request] = server.requests;
+ const requestBody = JSON.parse(request.requestBody);
+ expect(request.url).to.equal(INGEST_URL);
+ expect(requestBody.triggerEvent).to.equal(constants.EVENTS.AUCTION_INIT);
+ expect(server.requests).to.have.length(1);
+ expect(agmaAnalyticsAdapter.auctionIds).to.have.length(0);
+ });
+
+ it('should set the trigger Event', () => {
+ sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(() => null);
+ agmaAnalyticsAdapter.disableAnalytics();
+ agmaAnalyticsAdapter.enableAnalytics({
+ provider: 'agma',
+ options: {
+ code: 'test',
+ triggerEvent: constants.EVENTS.AUCTION_END
+ },
+ });
+ const auction = {
+ auctionId: generateUUID(),
+ };
+
+ events.emit(constants.EVENTS.AUCTION_INIT, auction);
+ events.emit(constants.EVENTS.AUCTION_END, auction);
+ clock.tick(1000);
+
+ const [request] = server.requests;
+ const requestBody = JSON.parse(request.requestBody);
+ expect(request.url).to.equal(INGEST_URL);
+ expect(requestBody.auctionIds).to.have.length(1);
+ expect(requestBody.triggerEvent).to.equal(constants.EVENTS.AUCTION_END);
+ expect(server.requests).to.have.length(1);
+ expect(agmaAnalyticsAdapter.auctionIds).to.have.length(0);
+ });
+ });
+});
diff --git a/test/spec/modules/ajaBidAdapter_spec.js b/test/spec/modules/ajaBidAdapter_spec.js
index 7cf5698f7d4..3137c9dc24e 100644
--- a/test/spec/modules/ajaBidAdapter_spec.js
+++ b/test/spec/modules/ajaBidAdapter_spec.js
@@ -62,8 +62,17 @@ describe('AjaAdapter', function () {
model: 'SM-G955U',
bitness: '64',
architecture: ''
+ },
+ ext: {
+ cdep: 'example_label_1'
}
}
+ },
+ ortb2Imp: {
+ ext: {
+ tid: 'cea1eb09-d970-48dc-8585-634d3a7b0544',
+ gpid: '/1111/homepage#300x250'
+ }
}
}
];
@@ -78,7 +87,7 @@ describe('AjaAdapter', function () {
const requests = spec.buildRequests(bidRequests, bidderRequest);
expect(requests[0].url).to.equal(ENDPOINT);
expect(requests[0].method).to.equal('GET');
- expect(requests[0].data).to.equal('asi=123456&skt=5&prebid_id=30b31c1838de1e&prebid_ver=$prebid.version$&page_url=https%3A%2F%2Fhoge.com&sua=%7B%22source%22%3A2%2C%22platform%22%3A%7B%22brand%22%3A%22Android%22%2C%22version%22%3A%5B%228%22%2C%220%22%2C%220%22%5D%7D%2C%22browsers%22%3A%5B%7B%22brand%22%3A%22Not_A%20Brand%22%2C%22version%22%3A%5B%2299%22%2C%220%22%2C%220%22%2C%220%22%5D%7D%2C%7B%22brand%22%3A%22Google%20Chrome%22%2C%22version%22%3A%5B%22109%22%2C%220%22%2C%225414%22%2C%22119%22%5D%7D%2C%7B%22brand%22%3A%22Chromium%22%2C%22version%22%3A%5B%22109%22%2C%220%22%2C%225414%22%2C%22119%22%5D%7D%5D%2C%22mobile%22%3A1%2C%22model%22%3A%22SM-G955U%22%2C%22bitness%22%3A%2264%22%2C%22architecture%22%3A%22%22%7D&');
+ expect(requests[0].data).to.equal('asi=123456&skt=5&gpid=%2F1111%2Fhomepage%23300x250&tid=cea1eb09-d970-48dc-8585-634d3a7b0544&cdep=example_label_1&prebid_id=30b31c1838de1e&prebid_ver=$prebid.version$&page_url=https%3A%2F%2Fhoge.com&ad_format_ids=2&sua=%7B%22source%22%3A2%2C%22platform%22%3A%7B%22brand%22%3A%22Android%22%2C%22version%22%3A%5B%228%22%2C%220%22%2C%220%22%5D%7D%2C%22browsers%22%3A%5B%7B%22brand%22%3A%22Not_A%20Brand%22%2C%22version%22%3A%5B%2299%22%2C%220%22%2C%220%22%2C%220%22%5D%7D%2C%7B%22brand%22%3A%22Google%20Chrome%22%2C%22version%22%3A%5B%22109%22%2C%220%22%2C%225414%22%2C%22119%22%5D%7D%2C%7B%22brand%22%3A%22Chromium%22%2C%22version%22%3A%5B%22109%22%2C%220%22%2C%225414%22%2C%22119%22%5D%7D%5D%2C%22mobile%22%3A1%2C%22model%22%3A%22SM-G955U%22%2C%22bitness%22%3A%2264%22%2C%22architecture%22%3A%22%22%7D&');
});
});
@@ -116,7 +125,7 @@ describe('AjaAdapter', function () {
const requests = spec.buildRequests(bidRequests, bidderRequest);
expect(requests[0].url).to.equal(ENDPOINT);
expect(requests[0].method).to.equal('GET');
- expect(requests[0].data).to.equal('asi=123456&skt=5&prebid_id=30b31c1838de1e&prebid_ver=$prebid.version$&page_url=https%3A%2F%2Fhoge.com&eids=%7B%22eids%22%3A%5B%7B%22source%22%3A%22pubcid.org%22%2C%22uids%22%3A%5B%7B%22id%22%3A%22some-random-id-value%22%2C%22atype%22%3A1%7D%5D%7D%5D%7D&');
+ expect(requests[0].data).to.equal('asi=123456&skt=5&prebid_id=30b31c1838de1e&prebid_ver=$prebid.version$&page_url=https%3A%2F%2Fhoge.com&ad_format_ids=2&eids=%7B%22eids%22%3A%5B%7B%22source%22%3A%22pubcid.org%22%2C%22uids%22%3A%5B%7B%22id%22%3A%22some-random-id-value%22%2C%22atype%22%3A1%7D%5D%7D%5D%7D&');
});
});
@@ -173,138 +182,6 @@ describe('AjaAdapter', function () {
expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0]));
});
- it('handles video responses', function () {
- let response = {
- 'is_ad_return': true,
- 'ad': {
- 'ad_type': 3,
- 'prebid_id': '51ef8751f9aead',
- 'price': 12.34,
- 'currency': 'JPY',
- 'creative_id': '123abc',
- 'video': {
- 'w': 300,
- 'h': 250,
- 'vtag': '',
- 'purl': 'https://cdn/player',
- 'progress': true,
- 'loop': false,
- 'inread': false,
- 'adomain': [
- 'www.example.com'
- ]
- }
- },
- 'syncs': [
- 'https://example.com'
- ]
- };
-
- let bidderRequest;
- let result = spec.interpretResponse({ body: response }, {bidderRequest});
- expect(result[0]).to.have.property('vastXml');
- expect(result[0]).to.have.property('renderer');
- expect(result[0]).to.have.property('mediaType', 'video');
- });
-
- it('handles native response', function () {
- let response = {
- 'is_ad_return': true,
- 'ad': {
- 'ad_type': 2,
- 'prebid_id': '51ef8751f9aead',
- 'price': 12.34,
- 'currency': 'JPY',
- 'creative_id': '123abc',
- 'native': {
- 'template_and_ads': {
- 'head': '',
- 'body_wrapper': '',
- 'body': '',
- 'ads': [
- {
- 'ad_format_id': 10,
- 'assets': {
- 'ad_spot_id': '123abc',
- 'index': 0,
- 'adchoice_url': 'https://aja-kk.co.jp/optout',
- 'cta_text': 'cta',
- 'img_icon': 'https://example.com/img_icon',
- 'img_icon_width': '50',
- 'img_icon_height': '50',
- 'img_main': 'https://example.com/img_main',
- 'img_main_width': '200',
- 'img_main_height': '100',
- 'lp_link': 'https://example.com/lp?k=v',
- 'sponsor': 'sponsor',
- 'title': 'ad_title',
- 'description': 'ad_desc'
- },
- 'imps': [
- 'https://example.com/imp'
- ],
- 'inviews': [
- 'https://example.com/inview'
- ],
- 'jstracker': '',
- 'disable_trimming': false,
- 'adomain': [
- 'www.example.com'
- ]
- }
- ]
- }
- }
- },
- 'syncs': [
- 'https://example.com'
- ]
- };
-
- let expectedResponse = [
- {
- 'requestId': '51ef8751f9aead',
- 'cpm': 12.34,
- 'creativeId': '123abc',
- 'dealId': undefined,
- 'mediaType': 'native',
- 'currency': 'JPY',
- 'ttl': 300,
- 'netRevenue': true,
- 'native': {
- 'title': 'ad_title',
- 'body': 'ad_desc',
- 'cta': 'cta',
- 'sponsoredBy': 'sponsor',
- 'image': {
- 'url': 'https://example.com/img_main',
- 'width': 200,
- 'height': 100
- },
- 'icon': {
- 'url': 'https://example.com/img_icon',
- 'width': 50,
- 'height': 50
- },
- 'clickUrl': 'https://example.com/lp?k=v',
- 'impressionTrackers': [
- 'https://example.com/imp'
- ],
- 'privacyLink': 'https://aja-kk.co.jp/optout'
- },
- 'meta': {
- 'advertiserDomains': [
- 'www.example.com'
- ]
- }
- }
- ];
-
- let bidderRequest;
- let result = spec.interpretResponse({ body: response }, {bidderRequest})
- expect(result).to.deep.equal(expectedResponse)
- });
-
it('handles nobid responses', function () {
let response = {
'is_ad_return': false,
diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js
index 08f00186358..90a9e409e69 100644
--- a/test/spec/modules/alkimiBidAdapter_spec.js
+++ b/test/spec/modules/alkimiBidAdapter_spec.js
@@ -68,7 +68,7 @@ const BIDDER_VIDEO_RESPONSE = {
'ttl': 200,
'creativeId': 2,
'netRevenue': true,
- 'winUrl': 'http://test.com',
+ 'winUrl': 'http://test.com?price=${AUCTION_PRICE}',
'mediaType': 'video',
'adomain': ['test.com']
}]
@@ -112,7 +112,15 @@ describe('alkimiBidAdapter', function () {
vendorData: {},
gdprApplies: true
},
- uspConsent: 'uspConsent'
+ uspConsent: 'uspConsent',
+ ortb2: {
+ site: {
+ keywords: 'test1, test2'
+ },
+ at: 2,
+ bcat: ['BSW1', 'BSW2'],
+ wseat: ['16', '165']
+ }
}
const bidderRequest = spec.buildRequests(bidRequests, requestData)
@@ -138,6 +146,7 @@ describe('alkimiBidAdapter', function () {
expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined)
expect(bidderRequest.data.bidIds).to.deep.contains('456')
expect(bidderRequest.data.signature).to.equal(undefined)
+ expect(bidderRequest.data.ortb2).to.deep.contains({ at: 2, wseat: ['16', '165'], bcat: ['BSW1', 'BSW2'], site: { keywords: 'test1, test2' }, })
expect(bidderRequest.options.customHeaders).to.deep.equal({ 'Rtb-Direct': true })
expect(bidderRequest.options.contentType).to.equal('application/json')
expect(bidderRequest.url).to.equal(ENDPOINT)
@@ -186,9 +195,9 @@ describe('alkimiBidAdapter', function () {
expect(result[0]).to.have.property('ttl').equal(200)
expect(result[0]).to.have.property('creativeId').equal(2)
expect(result[0]).to.have.property('netRevenue').equal(true)
- expect(result[0]).to.have.property('winUrl').equal('http://test.com')
+ expect(result[0]).to.have.property('winUrl').equal('http://test.com?price=${AUCTION_PRICE}')
expect(result[0]).to.have.property('mediaType').equal('video')
- expect(result[0]).to.have.property('vastXml').equal('vast')
+ expect(result[0]).to.have.property('vastUrl').equal('http://test.com?price=800.4')
expect(result[0].meta).to.exist.property('advertiserDomains')
expect(result[0].meta).to.have.property('advertiserDomains').lengthOf(1)
})
diff --git a/test/spec/modules/ampliffyBidAdapter_spec.js b/test/spec/modules/ampliffyBidAdapter_spec.js
new file mode 100644
index 00000000000..5b86f692d7e
--- /dev/null
+++ b/test/spec/modules/ampliffyBidAdapter_spec.js
@@ -0,0 +1,453 @@
+import {
+ parseXML,
+ isAllowedToBidUp,
+ spec,
+ getDefaultParams,
+ mergeParams,
+ paramsToQueryString, setCurrentURL
+} from 'modules/ampliffyBidAdapter.js';
+import {expect} from 'chai';
+import {BANNER, VIDEO} from 'src/mediaTypes';
+import {newBidder} from 'src/adapters/bidderFactory';
+
+describe('Ampliffy bid adapter Test', 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');
+ });
+ });
+ // Global definitions for all tests
+ const xmlStr = `
+
+
+
+ ]]>
+
+
+
+ ES
+ `;
+ const xml = new window.DOMParser().parseFromString(xmlStr, 'text/xml');
+ let companion = xml.getElementsByTagName('Companion')[0];
+ let htmlResource = companion.getElementsByTagName('HTMLResource')[0];
+ let htmlContent = document.createElement('html');
+ htmlContent.innerHTML = htmlResource.textContent;
+
+ describe('Is allowed to bid up', function () {
+ it('Should return true using a URL that is in domainMap', () => {
+ let allowedToBidUp = isAllowedToBidUp(htmlContent, 'https://testSports.com?id=131313&text=aaaaa&foo=foo');
+ expect(allowedToBidUp).to.be.true;
+ })
+
+ it('Should return false using an url that is not in domainMap', () => {
+ let allowedToBidUp = isAllowedToBidUp(htmlContent, 'https://test.com');
+ expect(allowedToBidUp).to.be.false;
+ })
+
+ it('Should return false using an url that is excluded.', () => {
+ let allowedToBidUp = isAllowedToBidUp(htmlContent, 'https://www.no-allowed.com/busqueda/sexo/sexo?test=1#item1');
+ expect(allowedToBidUp).to.be.false;
+ })
+ })
+
+ describe('Helper functions', function () {
+ it('Should default params not to be null', () => {
+ const defaultParams = getDefaultParams();
+
+ expect(defaultParams).not.to.be.null;
+ })
+ it('Should the merge two object params into a new object', () => {
+ const params1 = {
+ 'hello': 'world',
+ 'ampTest': 'this will be replaced'
+ }
+ const params2 = {
+ 'test': 1,
+ 'ampTest': 'This will be replace the param with the same name in other array'
+ }
+ const allParams = mergeParams(params1, params2);
+
+ const paramsComplete =
+ {
+ 'hello': 'world',
+ 'ampTest': 'This will be replace the param with the same name in other array',
+ 'test': 1,
+ }
+ expect(allParams).not.to.be.null;
+ expect(JSON.stringify(allParams)).to.equal(JSON.stringify(paramsComplete));
+ })
+ it('Params to QueryString', () => {
+ const params = {
+ 'test': 1,
+ 'ampTest': 'ret',
+ 'empty': null,
+ 'quoteMark': '?',
+ 'test1': undefined
+ }
+ const queryString = paramsToQueryString(params);
+
+ expect(queryString).not.to.be.null;
+ expect(queryString).to.equal('test=1&Test=ret&empty"eMark=%3F');
+ })
+ })
+
+ describe('isBidRequestValid', function () {
+ it('Should return true when required params found', function () {
+ const bidRequest = {
+ bidder: 'ampliffy',
+ params: {
+ server: 'bidder.ampliffy.com',
+ placementId: 1235465798,
+ format: 'all'
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [1, 1]
+ }
+ },
+ }
+ expect(spec.isBidRequestValid(bidRequest)).to.be.true;
+ })
+ it('Should return false when param format is display but mediaTypes are for video', function () {
+ const bidRequest = {
+ bidder: 'ampliffy',
+ params: {
+ server: 'bidder.ampliffy.com',
+ placementId: 1235465798,
+ format: 'display'
+ },
+ mediaTypes: {
+ video: {
+ sizes: [1, 1]
+ }
+ },
+ }
+ expect(spec.isBidRequestValid(bidRequest)).to.be.false;
+ })
+ it('Should return false when param format is video but mediaTypes are for banner', function () {
+ const bidRequest = {
+ bidder: 'ampliffy',
+ params: {
+ server: 'bidder.ampliffy.com',
+ placementId: 1235465798,
+ format: 'video'
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [1, 1]
+ }
+ },
+ }
+ expect(spec.isBidRequestValid(bidRequest)).to.be.false;
+ })
+ it('Should return true when param format is video and mediaTypes are for video', function () {
+ const bidRequest = {
+ bidder: 'ampliffy',
+ params: {
+ server: 'bidder.ampliffy.com',
+ placementId: 1235465798,
+ format: 'video'
+ },
+ mediaTypes: {
+ video: {
+ sizes: [1, 1]
+ }
+ },
+ }
+ expect(spec.isBidRequestValid(bidRequest)).to.be.true;
+ })
+ it('Should return true when param format is display and mediaTypes are for banner', function () {
+ const bidRequest = {
+ bidder: 'ampliffy',
+ params: {
+ server: 'bidder.ampliffy.com',
+ placementId: 1235465798,
+ format: 'display'
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [1, 1]
+ }
+ },
+ }
+ expect(spec.isBidRequestValid(bidRequest)).to.be.true;
+ })
+ it('Should return true when param format is all and mediaTypes are for banner', function () {
+ const bidRequest = {
+ bidder: 'ampliffy',
+ params: {
+ server: 'bidder.ampliffy.com',
+ placementId: 1235465798,
+ format: 'all'
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [1, 1]
+ }
+ },
+ }
+ expect(spec.isBidRequestValid(bidRequest)).to.be.true;
+ })
+ it('Should return true when param format is all and mediaTypes are for video', function () {
+ const bidRequest = {
+ bidder: 'ampliffy',
+ params: {
+ server: 'bidder.ampliffy.com',
+ placementId: 1235465798,
+ format: 'all'
+ },
+ mediaTypes: {
+ video: {
+ sizes: [1, 1]
+ }
+ },
+ }
+ expect(spec.isBidRequestValid(bidRequest)).to.be.true;
+ })
+ it('Should return false without placementId param', function () {
+ const bidRequest = {
+ bidder: 'ampliffy',
+ params: {}
+ }
+ expect(spec.isBidRequestValid(bidRequest)).to.be.false;
+ })
+ it('Should return false without param object', function () {
+ const bidRequest = {
+ bidder: 'ampliffy',
+ }
+ expect(spec.isBidRequestValid(bidRequest)).to.be.false;
+ })
+ });
+
+ describe('Build request function', function () {
+ const bidderRequest = {
+ 'bidderCode': 'ampliffy',
+ 'auctionId': 'c4a771bf-1791-4513-82b3-96c48d19ddff',
+ 'bidderRequestId': '1134bdcbe47f25',
+ 'bids': [{
+ 'bidder': 'ampliffy',
+ 'params': {
+ 'placementId': 1235465798,
+ 'type': 'bidder.',
+ 'region': 'alan-development.k8s.',
+ 'adnetwork': 'ampliffy.com',
+ 'SERVER': 'bidder.ampliffy.com'
+ },
+ 'crumbs': {'pubcid': '29844d69-c4e5-4b00-8602-6dd09815363a'},
+ 'ortb2Imp': {'ext': {'data': {'pbadslot': 'video1'}}},
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'instream',
+ 'playerSize': [[640, 480]],
+ 'mimes': ['video/mp4'],
+ 'protocols': [1, 2, 3, 4, 5, 6, 7, 8],
+ 'playbackmethod': [2],
+ 'skip': 1
+ }
+ },
+ 'adUnitCode': 'video1',
+ 'transactionId': 'f85c1b10-bad3-4c3f-a2bb-2c484c405bc9',
+ 'sizes': [[640, 480]],
+ 'bidId': '2bc71d9c058842',
+ 'bidderRequestId': '1134bdcbe47f25',
+ 'auctionId': 'c4a771bf-1791-4513-82b3-96c48d19ddff',
+ 'src': 'client',
+ 'bidRequestsCount': 1,
+ 'bidderRequestsCount': 1,
+ 'bidderWinsCount': 0
+ }],
+ 'auctionStart': 1644029483655,
+ 'timeout': 3000,
+ 'refererInfo': {
+ 'referer': 'http://localhost:9999/integrationExamples/gpt/hello_world_video.html?pbjs_debug=true',
+ 'reachedTop': true,
+ 'isAmp': false,
+ 'numIframes': 0,
+ 'stack': ['http://localhost:9999/integrationExamples/gpt/hello_world_video.html?pbjs_debug=true'],
+ 'canonicalUrl': null
+ },
+ 'start': 1644029483708
+ }
+ const validBidRequests = [
+ {
+ 'bidder': 'ampliffy',
+ 'params': {
+ 'placementId': 1235465798,
+ 'type': 'bidder.',
+ 'region': 'alan-development.k8s.',
+ 'adnetwork': 'ampliffy.com',
+ 'SERVER': 'bidder.ampliffy.com'
+ },
+ 'crumbs': {'pubcid': '29844d69-c4e5-4b00-8602-6dd09815363a'},
+ 'ortb2Imp': {'ext': {'data': {'pbadslot': 'video1'}}},
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'instream',
+ 'playerSize': [[640, 480]],
+ 'mimes': ['video/mp4'],
+ 'protocols': [1, 2, 3, 4, 5, 6, 7, 8],
+ 'playbackmethod': [2],
+ 'skip': 1
+ }
+ },
+ 'adUnitCode': 'video1',
+ 'transactionId': 'f85c1b10-bad3-4c3f-a2bb-2c484c405bc9',
+ 'sizes': [[640, 480]],
+ 'bidId': '2bc71d9c058842',
+ 'bidderRequestId': '1134bdcbe47f25',
+ 'auctionId': 'c4a771bf-1791-4513-82b3-96c48d19ddff',
+ 'src': 'client',
+ 'bidRequestsCount': 1,
+ 'bidderRequestsCount': 1,
+ 'bidderWinsCount': 0
+ }
+ ];
+ it('Should return one or more bid requests', function () {
+ expect(spec.buildRequests(validBidRequests, bidderRequest).length).to.be.greaterThan(0);
+ });
+ })
+ describe('Interpret response', function () {
+ let bidRequest = {
+ bidRequest: {
+ adUnitCode: 'div-gpt-ad-1460505748561-0',
+ auctionId: '469bb2e2-351f-4d01-b782-cdbca5e3e0ed',
+ bidId: '2d40b8dcd02ade',
+ bidRequestsCount: 1,
+ bidder: 'ampliffy',
+ bidderRequestId: '128c07edc4680f',
+ bidderRequestsCount: 1,
+ bidderWinsCount: 0,
+ crumbs: {
+ pubcid: '29844d69-c4e5-4b00-8602-6dd09815363a'
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250],
+ [300, 600]
+ ]
+ }
+ },
+ ortb2Imp: {ext: {}},
+ params: {placementId: 13144370},
+ sizes: [
+ [300, 250],
+ [300, 600]
+ ],
+ src: 'client',
+ transactionId: '103b2b58-6ed1-45e9-9486-c942d6042e3'
+ },
+ data: {bidId: '2d40b8dcd02ade'},
+ method: 'GET',
+ url: 'https://test.com',
+ };
+
+ it('Should extract a CPM and currency from the xml', () => {
+ let cpmData = parseXML(xml);
+ expect(cpmData).to.not.be.a('null');
+ expect(cpmData.cpm).to.equal('.23');
+ expect(cpmData.currency).to.equal('USD');
+ });
+
+ it('It should return no ads when the CPM is less than zero.', () => {
+ const xmlStr1 = `
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ ES
+
+
+ `;
+ let serverResponse = {
+ 'body': xmlStr1,
+ }
+ const bidResponses = spec.interpretResponse(serverResponse, bidRequest);
+ expect(bidResponses.length).to.equal(0);
+ })
+
+ it('It should return no ads when the creative url is not in the xml', () => {
+ const xmlStr1 = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
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/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/axisBidAdapter_spec.js b/test/spec/modules/axisBidAdapter_spec.js
new file mode 100644
index 00000000000..083f05f5c0a
--- /dev/null
+++ b/test/spec/modules/axisBidAdapter_spec.js
@@ -0,0 +1,414 @@
+import { expect } from 'chai';
+import { spec } from '../../../modules/axisBidAdapter.js';
+import { BANNER, VIDEO, NATIVE } from '../../../src/mediaTypes.js';
+import { getUniqueIdentifierStr } from '../../../src/utils.js';
+
+const bidder = 'axis'
+
+describe('AxisBidAdapter', function () {
+ const bids = [
+ {
+ bidId: getUniqueIdentifierStr(),
+ bidder: bidder,
+ mediaTypes: {
+ [BANNER]: {
+ sizes: [[300, 250]],
+ pos: 1
+ }
+ },
+ params: {
+ integration: '000000',
+ token: '000000'
+ }
+ },
+ {
+ bidId: getUniqueIdentifierStr(),
+ bidder: bidder,
+ mediaTypes: {
+ [VIDEO]: {
+ playerSize: [[300, 300]],
+ minduration: 5,
+ maxduration: 60,
+ pos: 1
+ }
+ },
+ params: {
+ integration: '000000',
+ token: '000000'
+ }
+ },
+ {
+ bidId: getUniqueIdentifierStr(),
+ bidder: bidder,
+ mediaTypes: {
+ [NATIVE]: {
+ native: {
+ title: {
+ required: true
+ },
+ body: {
+ required: true
+ },
+ icon: {
+ required: true,
+ size: [64, 64]
+ }
+ }
+ }
+ },
+ params: {
+ integration: '000000',
+ token: '000000'
+ }
+ }
+ ];
+
+ const invalidBid = {
+ bidId: getUniqueIdentifierStr(),
+ bidder: bidder,
+ mediaTypes: {
+ [BANNER]: {
+ sizes: [[300, 250]]
+ }
+ },
+ params: {
+
+ }
+ }
+
+ const bidderRequest = {
+ uspConsent: '1---',
+ gdprConsent: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
+ refererInfo: {
+ referer: 'https://test.com'
+ },
+ ortb2: {
+ site: {
+ cat: ['IAB24']
+ }
+ }
+ };
+
+ describe('isBidRequestValid', function () {
+ it('Should return true if there are bidId, params and key parameters present', function () {
+ expect(spec.isBidRequestValid(bids[0])).to.be.true;
+ });
+ it('Should return false if at least one of parameters is not present', function () {
+ expect(spec.isBidRequestValid(invalidBid)).to.be.false;
+ });
+ });
+
+ describe('buildRequests', function () {
+ let serverRequest = spec.buildRequests(bids, bidderRequest);
+
+ it('Creates a ServerRequest object with method, URL and data', function () {
+ expect(serverRequest).to.exist;
+ expect(serverRequest.method).to.exist;
+ expect(serverRequest.url).to.exist;
+ expect(serverRequest.data).to.exist;
+ });
+
+ it('Returns POST method', function () {
+ expect(serverRequest.method).to.equal('POST');
+ });
+
+ it('Returns valid URL', function () {
+ expect(serverRequest.url).to.equal('https://prebid.axis-marketplace.com/pbjs');
+ });
+
+ it('Returns general data valid', function () {
+ let data = serverRequest.data;
+ expect(data).to.be.an('object');
+ expect(data).to.have.all.keys('deviceWidth',
+ 'deviceHeight',
+ 'language',
+ 'secure',
+ 'host',
+ 'page',
+ 'placements',
+ 'iabCat',
+ 'coppa',
+ 'ccpa',
+ 'gdpr',
+ 'tmax'
+ );
+ expect(data.deviceWidth).to.be.a('number');
+ expect(data.deviceHeight).to.be.a('number');
+ expect(data.language).to.be.a('string');
+ expect(data.secure).to.be.within(0, 1);
+ 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.ccpa).to.be.a('string');
+ expect(data.tmax).to.be.a('number');
+ expect(data.iabCat).to.have.lengthOf(1);
+ expect(data.placements).to.have.lengthOf(3);
+ });
+
+ it('Returns valid placements', function () {
+ const { placements } = serverRequest.data;
+ for (let i = 0, len = placements.length; i < len; i++) {
+ const placement = placements[i];
+ expect(placement.adFormat).to.be.oneOf([BANNER, VIDEO, NATIVE]);
+ expect(placement.bidId).to.be.a('string');
+ expect(placement.integration).to.be.a('string');
+ expect(placement.token).to.be.a('string');
+ expect(placement.schain).to.be.an('object');
+ expect(placement.bidfloor).to.exist.and.to.equal(0);
+
+ if (placement.adFormat === BANNER) {
+ expect(placement.sizes).to.be.an('array');
+ }
+ switch (placement.adFormat) {
+ case BANNER:
+ expect(placement.sizes).to.be.an('array');
+ expect(placement.pos).to.be.within(0, 7);
+ break;
+ case VIDEO:
+ expect(placement.playerSize).to.be.an('array');
+ expect(placement.minduration).to.be.an('number');
+ expect(placement.maxduration).to.be.an('number');
+ expect(placement.pos).to.be.within(0, 7);
+ break;
+ case NATIVE:
+ expect(placement.native).to.be.an('object');
+ break;
+ }
+ }
+ });
+
+ it('Returns data with gdprConsent and without uspConsent', function () {
+ delete bidderRequest.uspConsent;
+ 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.ccpa).to.not.exist;
+ delete bidderRequest.gdprConsent;
+ });
+
+ it('Returns data with uspConsent and without gdprConsent', function () {
+ bidderRequest.uspConsent = '1---';
+ delete bidderRequest.gdprConsent;
+ serverRequest = spec.buildRequests(bids, bidderRequest);
+ let data = serverRequest.data;
+ expect(data.ccpa).to.exist;
+ expect(data.ccpa).to.be.a('string');
+ 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 () {
+ it('Should interpret banner response', function () {
+ const banner = {
+ body: [{
+ mediaType: 'banner',
+ width: 300,
+ height: 250,
+ cpm: 0.4,
+ ad: 'Test',
+ requestId: '23fhj33i987f',
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1',
+ meta: {
+ advertiserDomains: ['google.com'],
+ advertiserId: 1234
+ }
+ }]
+ };
+ let bannerResponses = spec.interpretResponse(banner);
+ 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', 'mediaType', 'meta');
+ expect(dataItem.requestId).to.equal(banner.body[0].requestId);
+ expect(dataItem.cpm).to.equal(banner.body[0].cpm);
+ expect(dataItem.width).to.equal(banner.body[0].width);
+ expect(dataItem.height).to.equal(banner.body[0].height);
+ expect(dataItem.ad).to.equal(banner.body[0].ad);
+ expect(dataItem.ttl).to.equal(banner.body[0].ttl);
+ expect(dataItem.creativeId).to.equal(banner.body[0].creativeId);
+ expect(dataItem.netRevenue).to.be.true;
+ expect(dataItem.currency).to.equal(banner.body[0].currency);
+ expect(dataItem.meta).to.be.an('object').that.has.property('advertiserDomains');
+ });
+ it('Should interpret video response', function () {
+ const video = {
+ body: [{
+ vastUrl: 'test.com',
+ mediaType: 'video',
+ cpm: 0.5,
+ requestId: '23fhj33i987f',
+ width: 300,
+ height: 250,
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1',
+ meta: {
+ advertiserDomains: ['google.com'],
+ advertiserId: 1234
+ }
+ }]
+ };
+ let videoResponses = spec.interpretResponse(video);
+ expect(videoResponses).to.be.an('array').that.is.not.empty;
+
+ let dataItem = videoResponses[0];
+ expect(dataItem).to.have.all.keys('requestId', 'cpm', 'vastUrl', 'ttl', 'creativeId',
+ 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta', 'width', 'height');
+ expect(dataItem.requestId).to.equal('23fhj33i987f');
+ expect(dataItem.cpm).to.equal(0.5);
+ expect(dataItem.vastUrl).to.equal('test.com');
+ expect(dataItem.ttl).to.equal(120);
+ expect(dataItem.creativeId).to.equal('2');
+ expect(dataItem.netRevenue).to.be.true;
+ expect(dataItem.currency).to.equal('USD');
+ expect(dataItem.meta).to.be.an('object').that.has.property('advertiserDomains');
+ });
+ it('Should interpret native response', function () {
+ const native = {
+ body: [{
+ mediaType: 'native',
+ native: {
+ clickUrl: 'test.com',
+ title: 'Test',
+ image: 'test.com',
+ impressionTrackers: ['test.com'],
+ },
+ ttl: 120,
+ cpm: 0.4,
+ requestId: '23fhj33i987f',
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ meta: {
+ advertiserDomains: ['google.com'],
+ advertiserId: 1234
+ }
+ }]
+ };
+ let nativeResponses = spec.interpretResponse(native);
+ expect(nativeResponses).to.be.an('array').that.is.not.empty;
+
+ let dataItem = nativeResponses[0];
+ expect(dataItem).to.have.keys('requestId', 'cpm', 'ttl', 'creativeId', 'netRevenue', 'currency', 'mediaType', 'native', 'meta');
+ expect(dataItem.native).to.have.keys('clickUrl', 'impressionTrackers', 'title', 'image')
+ expect(dataItem.requestId).to.equal('23fhj33i987f');
+ expect(dataItem.cpm).to.equal(0.4);
+ expect(dataItem.native.clickUrl).to.equal('test.com');
+ expect(dataItem.native.title).to.equal('Test');
+ expect(dataItem.native.image).to.equal('test.com');
+ expect(dataItem.native.impressionTrackers).to.be.an('array').that.is.not.empty;
+ expect(dataItem.native.impressionTrackers[0]).to.equal('test.com');
+ expect(dataItem.ttl).to.equal(120);
+ expect(dataItem.creativeId).to.equal('2');
+ expect(dataItem.netRevenue).to.be.true;
+ expect(dataItem.currency).to.equal('USD');
+ expect(dataItem.meta).to.be.an('object').that.has.property('advertiserDomains');
+ });
+ it('Should return an empty array if invalid banner response is passed', function () {
+ const invBanner = {
+ body: [{
+ width: 300,
+ cpm: 0.4,
+ ad: 'Test',
+ requestId: '23fhj33i987f',
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1'
+ }]
+ };
+
+ let serverResponses = spec.interpretResponse(invBanner);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ it('Should return an empty array if invalid video response is passed', function () {
+ const invVideo = {
+ body: [{
+ mediaType: 'video',
+ cpm: 0.5,
+ requestId: '23fhj33i987f',
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1'
+ }]
+ };
+ let serverResponses = spec.interpretResponse(invVideo);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ it('Should return an empty array if invalid native response is passed', function () {
+ const invNative = {
+ body: [{
+ mediaType: 'native',
+ clickUrl: 'test.com',
+ title: 'Test',
+ impressionTrackers: ['test.com'],
+ ttl: 120,
+ requestId: '23fhj33i987f',
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ }]
+ };
+ let serverResponses = spec.interpretResponse(invNative);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ it('Should return an empty array if invalid response is passed', function () {
+ const invalid = {
+ body: [{
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1'
+ }]
+ };
+ let serverResponses = spec.interpretResponse(invalid);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ });
+
+ describe('getUserSyncs', function() {
+ it('Should return array of objects with proper sync config , include GDPR', function() {
+ const syncData = spec.getUserSyncs({}, {}, {
+ consentString: 'ALL',
+ gdprApplies: true,
+ }, {});
+ expect(syncData).to.be.an('array').which.is.not.empty;
+ expect(syncData[0]).to.be.an('object')
+ expect(syncData[0].type).to.be.a('string')
+ expect(syncData[0].type).to.equal('image')
+ expect(syncData[0].url).to.be.a('string')
+ expect(syncData[0].url).to.equal('https://cs.axis-marketplace.com/image?pbjs=1&gdpr=1&gdpr_consent=ALL&coppa=0')
+ });
+ it('Should return array of objects with proper sync config , include CCPA', function() {
+ const syncData = spec.getUserSyncs({}, {}, {}, {
+ consentString: '1---'
+ });
+ expect(syncData).to.be.an('array').which.is.not.empty;
+ expect(syncData[0]).to.be.an('object')
+ expect(syncData[0].type).to.be.a('string')
+ expect(syncData[0].type).to.equal('image')
+ expect(syncData[0].url).to.be.a('string')
+ expect(syncData[0].url).to.equal('https://cs.axis-marketplace.com/image?pbjs=1&ccpa=1---&coppa=0')
+ });
+ });
+});
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/bliinkBidAdapter_spec.js b/test/spec/modules/bliinkBidAdapter_spec.js
index 8e96bd76940..3db97a17d88 100644
--- a/test/spec/modules/bliinkBidAdapter_spec.js
+++ b/test/spec/modules/bliinkBidAdapter_spec.js
@@ -1,5 +1,16 @@
-import { expect } from 'chai'
-import { spec, buildBid, BLIINK_ENDPOINT_ENGINE, getMetaList, BLIINK_ENDPOINT_COOKIE_SYNC_IFRAME } from 'modules/bliinkBidAdapter.js'
+import { expect } from 'chai';
+import {
+ spec,
+ buildBid,
+ BLIINK_ENDPOINT_ENGINE,
+ getMetaList,
+ BLIINK_ENDPOINT_COOKIE_SYNC_IFRAME,
+ getEffectiveConnectionType,
+ getUserIds,
+ getDomLoadingDuration,
+ GVL_ID,
+} from 'modules/bliinkBidAdapter.js';
+import { config } from 'src/config.js';
/**
* @description Mockup bidRequest
@@ -20,6 +31,9 @@ import { spec, buildBid, BLIINK_ENDPOINT_ENGINE, getMetaList, BLIINK_ENDPOINT_CO
* crumbs: {pubcid: string},
* ortb2Imp: {ext: {data: {pbadslot: string}}}}}
*/
+
+const connectionType = getEffectiveConnectionType();
+const domLoadingDuration = getDomLoadingDuration().toString();
const getConfigBid = (placement) => {
return {
adUnitCode: '/19968336/test',
@@ -31,31 +45,33 @@ const getConfigBid = (placement) => {
bidderRequestsCount: 1,
bidderWinsCount: 0,
crumbs: {
- pubcid: '55ffadc5-051f-428d-8ecc-dc585e0bde0d'
+ pubcid: '55ffadc5-051f-428d-8ecc-dc585e0bde0d',
},
sizes: [[300, 250]],
mediaTypes: {
banner: {
- sizes: [
- [300, 250]
- ]
- }
+ sizes: [[300, 250]],
+ },
},
ortb2Imp: {
ext: {
data: {
- pbadslot: '/19968336/test'
- }
- }
+ pbadslot: '/19968336/test',
+ },
+ },
},
+ domLoadingDuration,
+ ect: connectionType,
params: {
placement: placement,
- tagId: '14f30eca-85d2-11e8-9eed-0242ac120007'
+ tagId: '14f30eca-85d2-11e8-9eed-0242ac120007',
+ videoUrl: 'https://www.example.com/advideo.mp4',
+ imageUrl: 'https://www.example.com/adimage.jpg',
},
src: 'client',
- transactionId: 'cc6678c4-9746-4082-b9e2-d8065d078ebf'
- }
-}
+ transactionId: 'cc6678c4-9746-4082-b9e2-d8065d078ebf',
+ };
+};
const getConfigBannerBid = () => {
return {
creative: {
@@ -76,14 +92,13 @@ const getConfigBannerBid = () => {
transaction_id: '2def0c5b2a7f6e',
},
currency: 'EUR',
- }
-}
+ };
+};
const getConfigVideoBid = () => {
return {
creative: {
video: {
- content:
- '
',
+ content: '
',
height: 250,
width: 300,
},
@@ -99,8 +114,8 @@ const getConfigVideoBid = () => {
transaction_id: '2def0c5b2a7f6e',
},
currency: 'EUR',
- }
-}
+ };
+};
/**
* @description Mockup response from engine.bliink.io/xxxx
@@ -119,7 +134,7 @@ const getConfigVideoBid = () => {
* }
* }
* }
-* }
+ * }
*/
const getConfigCreative = () => {
return {
@@ -132,8 +147,8 @@ const getConfigCreative = () => {
height: 250,
ttl: 300,
netRevenue: true,
- }
-}
+ };
+};
const getConfigCreativeVideo = (isNoVast) => {
return {
@@ -147,8 +162,8 @@ const getConfigCreativeVideo = (isNoVast) => {
height: 250,
ttl: 300,
netRevenue: true,
- }
-}
+ };
+};
/**
* @description Mockup BuildRequest function
@@ -166,19 +181,19 @@ const getConfigBuildRequest = (placement) => {
reachedTop: true,
page: 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html?pbjs_debug=true',
},
- }
+ };
if (!placement) {
- return buildRequest
+ return buildRequest;
}
return Object.assign(buildRequest, {
params: {
bids: [getConfigBid(placement)],
- placement: placement
+ placement: placement,
},
- })
-}
+ });
+};
/**
* @description Mockup response from API
@@ -189,8 +204,8 @@ const getConfigInterpretResponse = (noAd = false) => {
if (noAd) {
return {
message: 'invalid tag',
- mode: 'no-ad'
- }
+ mode: 'no-ad',
+ };
}
return {
@@ -198,11 +213,12 @@ const getConfigInterpretResponse = (noAd = false) => {
...getConfigCreative(),
mode: 'ad',
transactionId: '2def0c5b2a7f6e',
- token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjgxNzA4MzEsImlhdCI6MTYyNzU2NjAzMSwiaXNzIjoiYmxpaW5rIiwiZGF0YSI6eyJ0eXBlIjoiYWQtc2VydmVyIiwidHJhbnNhY3Rpb25JZCI6IjM1YmU1NDNjLTNkZTQtNGQ1Yy04N2NjLWIzYzEyOGZiYzU0MCIsIm5ldHdvcmtJZCI6MjEsInNpdGVJZCI6NTksInRhZ0lkIjo1OSwiY29va2llSWQiOiJjNGU4MWVhOS1jMjhmLTQwZDItODY1ZC1hNjQzZjE1OTcyZjUiLCJldmVudElkIjozLCJ0YXJnZXRpbmciOnsicGxhdGZvcm0iOiJXZWJzaXRlIiwiaXAiOiI3OC4xMjIuNzUuNzIiLCJ0aW1lIjoxNjI3NTY2MDMxLCJsb2NhdGlvbiI6eyJsYXRpdHVkZSI6NDguOTczOSwibG9uZ2l0dWRlIjozLjMxMTMsInJlZ2lvbiI6IkhERiIsImNvdW50cnkiOiJGUiIsImNpdHkiOiJTYXVsY2hlcnkiLCJ6aXBDb2RlIjoiMDIzMTAiLCJkZXBhcnRtZW50IjoiMDIifSwiY2l0eSI6IlNhdWxjaGVyeSIsImNvdW50cnkiOiJGUiIsImRldmljZU9zIjoibWFjT1MiLCJkZXZpY2VQbGF0Zm9ybSI6IldlYnNpdGUiLCJyYXdVc2VyQWdlbnQiOiJNb3ppbGxhLzUuMCAoTWFjaW50b3NoOyBJbnRlbCBNYWMgT1MgWCAxMF8xNV83KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvOTEuMC40NDcyLjEyNCBTYWZhcmkvNTM3LjM2In0sImdkcHIiOnsiaGFzQ29uc2VudCI6dHJ1ZX0sIndpbiI6ZmFsc2UsImFkSWQiOjU2NDgsImFkdmVydGlzZXJJZCI6MSwiY2FtcGFpZ25JZCI6MSwiY3JlYXRpdmVJZCI6MjgyNSwiZXJyb3IiOmZhbHNlfX0.-UefQH4G0k-RJGemBYffs-KL7EEwma2Wuwgk2xnpij8'
+ token:
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjgxNzA4MzEsImlhdCI6MTYyNzU2NjAzMSwiaXNzIjoiYmxpaW5rIiwiZGF0YSI6eyJ0eXBlIjoiYWQtc2VydmVyIiwidHJhbnNhY3Rpb25JZCI6IjM1YmU1NDNjLTNkZTQtNGQ1Yy04N2NjLWIzYzEyOGZiYzU0MCIsIm5ldHdvcmtJZCI6MjEsInNpdGVJZCI6NTksInRhZ0lkIjo1OSwiY29va2llSWQiOiJjNGU4MWVhOS1jMjhmLTQwZDItODY1ZC1hNjQzZjE1OTcyZjUiLCJldmVudElkIjozLCJ0YXJnZXRpbmciOnsicGxhdGZvcm0iOiJXZWJzaXRlIiwiaXAiOiI3OC4xMjIuNzUuNzIiLCJ0aW1lIjoxNjI3NTY2MDMxLCJsb2NhdGlvbiI6eyJsYXRpdHVkZSI6NDguOTczOSwibG9uZ2l0dWRlIjozLjMxMTMsInJlZ2lvbiI6IkhERiIsImNvdW50cnkiOiJGUiIsImNpdHkiOiJTYXVsY2hlcnkiLCJ6aXBDb2RlIjoiMDIzMTAiLCJkZXBhcnRtZW50IjoiMDIifSwiY2l0eSI6IlNhdWxjaGVyeSIsImNvdW50cnkiOiJGUiIsImRldmljZU9zIjoibWFjT1MiLCJkZXZpY2VQbGF0Zm9ybSI6IldlYnNpdGUiLCJyYXdVc2VyQWdlbnQiOiJNb3ppbGxhLzUuMCAoTWFjaW50b3NoOyBJbnRlbCBNYWMgT1MgWCAxMF8xNV83KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvOTEuMC40NDcyLjEyNCBTYWZhcmkvNTM3LjM2In0sImdkcHIiOnsiaGFzQ29uc2VudCI6dHJ1ZX0sIndpbiI6ZmFsc2UsImFkSWQiOjU2NDgsImFkdmVydGlzZXJJZCI6MSwiY2FtcGFpZ25JZCI6MSwiY3JlYXRpdmVJZCI6MjgyNSwiZXJyb3IiOmZhbHNlfX0.-UefQH4G0k-RJGemBYffs-KL7EEwma2Wuwgk2xnpij8',
},
headers: {},
- }
-}
+ };
+};
/**
* @description Mockup response from API for RTB creative
@@ -213,8 +229,8 @@ const getConfigInterpretResponseRTB = (noAd = false, isInvalidVast = false) => {
if (noAd) {
return {
message: 'invalid tag',
- mode: 'no-ad'
- }
+ mode: 'no-ad',
+ };
}
const validVast = `
@@ -229,41 +245,43 @@ const getConfigInterpretResponseRTB = (noAd = false, isInvalidVast = false) => {
- `
+ `;
const invalidVast = `
- `
+ `;
return {
- body: { bids: [
- {
- 'creative': {
- 'video': {
- 'content': isInvalidVast ? invalidVast : validVast,
- 'height': 250,
- 'width': 300
+ body: {
+ bids: [
+ {
+ creative: {
+ video: {
+ content: isInvalidVast ? invalidVast : validVast,
+ height: 250,
+ width: 300,
+ },
+ media_type: 'video',
+ creativeId: 0,
},
- 'media_type': 'video',
- 'creativeId': 0,
- },
- 'price': 0,
- 'id': '8121',
- 'token': 'token',
- 'mode': 'rtb',
- 'extras': {
- 'deal_id': '34567ertyaza',
- 'transaction_id': '2def0c5b2a7f6e'
+ price: 0,
+ id: '8121',
+ token: 'token',
+ mode: 'rtb',
+ extras: {
+ deal_id: '34567ertyaza',
+ transaction_id: '2def0c5b2a7f6e',
+ },
+ currency: 'EUR',
},
- 'currency': 'EUR'
- }
- ],
- userSyncs: []}
- }
-}
+ ],
+ userSyncs: [],
+ },
+ };
+};
/**
*
@@ -279,9 +297,9 @@ const testsGetMetaList = [
{
title: 'Should return empty array if there are no parameters',
args: {
- fn: getMetaList()
+ fn: getMetaList(),
},
- want: []
+ want: [],
},
{
title: 'Should return list of metas with name associated',
@@ -313,18 +331,63 @@ const testsGetMetaList = [
key: 'property',
value: `'article:${'test'}'`,
},
- ]
- }
-]
+ ],
+ },
+];
-describe('BLIINK Adapter getMetaList', function() {
+describe('BLIINK Adapter getMetaList', function () {
for (const test of testsGetMetaList) {
it(test.title, () => {
- const res = test.args.fn
- expect(res).to.eql(test.want)
- })
+ const res = test.args.fn;
+ expect(res).to.eql(test.want);
+ });
}
-})
+});
+const GetUserIds = [
+ {
+ title: 'Should return undefined if there are no parameters',
+ args: {
+ fn: getUserIds(),
+ },
+ want: undefined,
+ },
+ {
+ title: 'Should return eids if exists',
+ args: {
+ fn: getUserIds([{ userIdAsEids: [
+ {
+ 'source': 'criteo.com',
+ 'uids': [
+ {
+ 'id': 'testId',
+ 'atype': 1
+ }
+ ]
+ }
+ ] }]),
+ },
+ want: [
+ {
+ 'source': 'criteo.com',
+ 'uids': [
+ {
+ 'id': 'testId',
+ 'atype': 1
+ }
+ ]
+ }
+ ],
+ },
+];
+
+describe('BLIINK Adapter getUserIds', function () {
+ for (const test of GetUserIds) {
+ it(test.title, () => {
+ const res = test.args.fn;
+ expect(res).to.eql(test.want);
+ });
+ }
+});
/**
* @description Array of tests used in describe function below
@@ -349,127 +412,142 @@ const testsIsBidRequestValid = [
{
title: 'isBidRequestValid format not valid',
args: {
- fn: spec.isBidRequestValid({})
+ fn: spec.isBidRequestValid({}),
},
want: false,
},
{
title: 'isBidRequestValid does not receive any bid',
args: {
- fn: spec.isBidRequestValid()
+ fn: spec.isBidRequestValid(),
},
want: false,
},
{
title: 'isBidRequestValid Receive a valid bid',
args: {
- fn: spec.isBidRequestValid(getConfigBid('banner'))
+ fn: spec.isBidRequestValid(getConfigBid('banner')),
},
want: true,
- }
-]
+ },
+];
-describe('BLIINK Adapter isBidRequestValid', function() {
+describe('BLIINK Adapter isBidRequestValid', function () {
for (const test of testsIsBidRequestValid) {
it(test.title, () => {
- const res = test.args.fn
- expect(res).to.eql(test.want)
- })
+ const res = test.args.fn;
+ expect(res).to.eql(test.want);
+ });
}
-})
+});
-const vastXml = getConfigInterpretResponseRTB().body.bids[0].creative.video.content
+const vastXml =
+ getConfigInterpretResponseRTB().body.bids[0].creative.video.content;
const testsInterpretResponse = [
{
title: 'Should construct bid for video instream',
args: {
- fn: spec.interpretResponse(getConfigInterpretResponseRTB(false))
+ fn: spec.interpretResponse(getConfigInterpretResponseRTB(false)),
},
- want: [{
- cpm: 0,
- currency: 'EUR',
- height: 250,
- width: 300,
- creativeId: '34567ertyaza',
- mediaType: 'video',
- netRevenue: true,
- requestId: '2def0c5b2a7f6e',
- ttl: 300,
- vastXml,
- vastUrl: 'data:text/xml;charset=utf-8;base64,' + btoa(vastXml.replace(/\\"/g, '"'))
- }]
+ want: [
+ {
+ cpm: 0,
+ currency: 'EUR',
+ height: 250,
+ width: 300,
+ creativeId: '34567ertyaza',
+ mediaType: 'video',
+ netRevenue: true,
+ requestId: '2def0c5b2a7f6e',
+ ttl: 300,
+ vastXml,
+ vastUrl:
+ 'data:text/xml;charset=utf-8;base64,' +
+ btoa(vastXml.replace(/\\"/g, '"')),
+ },
+ ],
},
{
title: 'ServerResponse with message: invalid tag, return empty array',
args: {
- fn: spec.interpretResponse(getConfigInterpretResponse(true))
+ fn: spec.interpretResponse(getConfigInterpretResponse(true)),
},
- want: []
+ want: [],
},
{
title: 'ServerResponse with mediaType banner',
args: {
- fn: spec.interpretResponse({body: {bids: [getConfigBannerBid()]}}),
+ fn: spec.interpretResponse({ body: { bids: [getConfigBannerBid()] } }),
},
- want: [{
- ad: '',
- cpm: 1,
- creativeId: '34567erty',
- currency: 'EUR',
- height: 250,
- mediaType: 'banner',
- netRevenue: true,
- requestId: '2def0c5b2a7f6e',
- ttl: 300,
- width: 300
- }]
+ want: [
+ {
+ ad: '',
+ cpm: 1,
+ creativeId: '34567erty',
+ currency: 'EUR',
+ height: 250,
+ mediaType: 'banner',
+ netRevenue: true,
+ requestId: '2def0c5b2a7f6e',
+ ttl: 300,
+ width: 300,
+ },
+ ],
},
{
title: 'ServerResponse with unhandled mediaType, return empty array',
args: {
- fn: spec.interpretResponse({body: {bids: [{...getConfigBannerBid(),
- creative: {
- unknown: {
- adm: '',
- height: 250,
- width: 300,
- },
- media_type: 'unknown',
- creativeId: 125,
- requestId: '2def0c5b2a7f6e',
- }}]}}),
+ fn: spec.interpretResponse({
+ body: {
+ bids: [
+ {
+ ...getConfigBannerBid(),
+ creative: {
+ unknown: {
+ adm: '',
+ height: 250,
+ width: 300,
+ },
+ media_type: 'unknown',
+ creativeId: 125,
+ requestId: '2def0c5b2a7f6e',
+ },
+ },
+ ],
+ },
+ }),
},
- want: []
+ want: [],
},
-]
+];
-describe('BLIINK Adapter interpretResponse', function() {
+describe('BLIINK Adapter interpretResponse', function () {
for (const test of testsInterpretResponse) {
it(test.title, () => {
- const res = test.args.fn
+ const res = test.args.fn;
if (res) {
- expect(res).to.eql(test.want)
+ expect(res).to.eql(test.want);
}
- })
+ });
}
-})
+});
/**
* @description Array of tests used in describe function below
* @type {[
* {args:
* {fn: {
- * cpm: number,
- * netRevenue: boolean,
- * ad, requestId,
- * meta: {mediaType},
- * width: number,
- * currency: string,
- * ttl: number,
- * creativeId: number,
- * height: number
+ * cpm: number,
+ * netRevenue: boolean,
+ * ad, requestId,
+ * meta: {mediaType},
+ * width: number,
+ * currency: string,
+ * ttl: number,
+ * creativeId: number,
+ * height: number
* }
* }, want, title: string}]}
*/
@@ -478,21 +556,26 @@ const testsBuildBid = [
{
title: 'Should return null if no bid passed in parameters',
args: {
- fn: buildBid()
+ fn: buildBid(),
},
- want: null
+ want: null,
},
{
title: 'Input data must respect the output model',
args: {
- fn: buildBid({ id: 1, test: '123' }, { id: 2, test: '345' }, false, false)
+ fn: buildBid(
+ { id: 1, test: '123' },
+ { id: 2, test: '345' },
+ false,
+ false
+ ),
},
- want: null
+ want: null,
},
{
title: 'input data respect the output model for video',
args: {
- fn: buildBid(getConfigVideoBid('video'), getConfigCreativeVideo())
+ fn: buildBid(getConfigVideoBid('video'), getConfigCreativeVideo()),
},
want: {
requestId: getConfigBid('video').bidId,
@@ -504,25 +587,31 @@ const testsBuildBid = [
creativeId: getConfigVideoBid().extras.deal_id,
netRevenue: true,
vastXml: getConfigCreativeVideo().vastXml,
- vastUrl: 'data:text/xml;charset=utf-8;base64,' + btoa(getConfigCreativeVideo().vastXml.replace(/\\"/g, '"')),
+ vastUrl:
+ 'data:text/xml;charset=utf-8;base64,' +
+ btoa(getConfigCreativeVideo().vastXml.replace(/\\"/g, '"')),
ttl: 300,
- }
+ },
},
{
title: 'use default height width output model for video',
args: {
- fn: buildBid({...getConfigVideoBid('video'),
- creative: {
- video: {
- content:
- '',
- height: null,
- width: null,
+ fn: buildBid(
+ {
+ ...getConfigVideoBid('video'),
+ creative: {
+ video: {
+ content: '',
+ height: null,
+ width: null,
+ },
+ media_type: 'video',
+ creativeId: getConfigVideoBid().extras.deal_id,
+ requestId: '2def0c5b2a7f6e',
},
- media_type: 'video',
- creativeId: getConfigVideoBid().extras.deal_id,
- requestId: '2def0c5b2a7f6e',
- }}, getConfigCreativeVideo())
+ },
+ getConfigCreativeVideo()
+ ),
},
want: {
requestId: getConfigBid('video').bidId,
@@ -534,14 +623,16 @@ const testsBuildBid = [
creativeId: getConfigVideoBid().extras.deal_id,
netRevenue: true,
vastXml: getConfigCreativeVideo().vastXml,
- vastUrl: 'data:text/xml;charset=utf-8;base64,' + btoa(getConfigCreativeVideo().vastXml.replace(/\\"/g, '"')),
+ vastUrl:
+ 'data:text/xml;charset=utf-8;base64,' +
+ btoa(getConfigCreativeVideo().vastXml.replace(/\\"/g, '"')),
ttl: 300,
- }
+ },
},
{
title: 'input data respect the output model for banner',
args: {
- fn: buildBid(getConfigBannerBid())
+ fn: buildBid(getConfigBannerBid()),
},
want: {
requestId: getConfigBid('banner').bidId,
@@ -554,18 +645,18 @@ const testsBuildBid = [
ad: getConfigBannerBid().creative.banner.adm,
ttl: 300,
netRevenue: true,
- }
- }
-]
+ },
+ },
+];
-describe('BLIINK Adapter buildBid', function() {
+describe('BLIINK Adapter buildBid', function () {
for (const test of testsBuildBid) {
it(test.title, () => {
- const res = test.args.fn
- expect(res).to.eql(test.want)
- })
+ const res = test.args.fn;
+ expect(res).to.eql(test.want);
+ });
}
-})
+});
/**
* @description Array of tests used in describe function below
@@ -575,28 +666,33 @@ const testsBuildRequests = [
{
title: 'Should not build request, no bidder request exist',
args: {
- fn: spec.buildRequests()
+ fn: spec.buildRequests(),
},
- want: null
+ want: null,
},
{
title: 'Should build request if bidderRequest exist',
args: {
- fn: spec.buildRequests([], getConfigBuildRequest('banner'))
+ fn: spec.buildRequests([], getConfigBuildRequest('banner')),
},
want: {
method: 'POST',
url: BLIINK_ENDPOINT_ENGINE,
data: {
+ domLoadingDuration,
+ ect: connectionType,
keywords: '',
pageDescription: '',
pageTitle: '',
- pageUrl: 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html?pbjs_debug=true',
+ pageUrl:
+ 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html',
tags: [
{
transactionId: '2def0c5b2a7f6e',
+ refresh: window.bliinkBid['14f30eca-85d2-11e8-9eed-0242ac120007'] || undefined,
id: '14f30eca-85d2-11e8-9eed-0242ac120007',
- imageUrl: '',
+ imageUrl: 'https://www.example.com/adimage.jpg',
+ videoUrl: 'https://www.example.com/advideo.mp4',
mediaTypes: ['banner'],
sizes: [
{
@@ -605,35 +701,43 @@ const testsBuildRequests = [
},
],
},
- ]
- }
- }
+ ],
+ },
+ },
},
{
title: 'Should build request width GDPR configuration',
args: {
- fn: spec.buildRequests([], Object.assign(getConfigBuildRequest('banner'), {
- gdprConsent: {
- gdprApplies: true,
- consentString: 'XXXX'
- },
- }))
+ fn: spec.buildRequests(
+ [],
+ Object.assign(getConfigBuildRequest('banner'), {
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: 'XXXX',
+ },
+ })
+ ),
},
want: {
method: 'POST',
url: BLIINK_ENDPOINT_ENGINE,
data: {
+ domLoadingDuration,
+ ect: connectionType,
gdpr: true,
gdprConsent: 'XXXX',
pageDescription: '',
pageTitle: '',
keywords: '',
- pageUrl: 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html?pbjs_debug=true',
+ pageUrl:
+ 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html',
tags: [
{
transactionId: '2def0c5b2a7f6e',
+ refresh: window.bliinkBid['14f30eca-85d2-11e8-9eed-0242ac120007'] || undefined,
id: '14f30eca-85d2-11e8-9eed-0242ac120007',
- imageUrl: '',
+ imageUrl: 'https://www.example.com/adimage.jpg',
+ videoUrl: 'https://www.example.com/advideo.mp4',
mediaTypes: ['banner'],
sizes: [
{
@@ -642,52 +746,115 @@ const testsBuildRequests = [
},
],
},
- ]
- }
- }
+ ],
+ },
+ },
+ },
+ {
+ title: 'Should build request width uspConsent if exists',
+ args: {
+ fn: spec.buildRequests(
+ [],
+ Object.assign(getConfigBuildRequest('banner'), {
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: 'XXXX',
+ },
+ uspConsent: 'uspConsent',
+ })
+ ),
+ },
+ want: {
+ method: 'POST',
+ url: BLIINK_ENDPOINT_ENGINE,
+ data: {
+ domLoadingDuration,
+ ect: connectionType,
+ gdpr: true,
+ uspConsent: 'uspConsent',
+ gdprConsent: 'XXXX',
+ pageDescription: '',
+ pageTitle: '',
+ keywords: '',
+ pageUrl:
+ 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html',
+ tags: [
+ {
+ transactionId: '2def0c5b2a7f6e',
+ refresh: window.bliinkBid['14f30eca-85d2-11e8-9eed-0242ac120007'] || undefined,
+ id: '14f30eca-85d2-11e8-9eed-0242ac120007',
+ imageUrl: 'https://www.example.com/adimage.jpg',
+ videoUrl: 'https://www.example.com/advideo.mp4',
+ mediaTypes: ['banner'],
+ sizes: [
+ {
+ h: 250,
+ w: 300,
+ },
+ ],
+ },
+ ],
+ },
+ },
},
{
title: 'Should build request width schain if exists',
args: {
- fn: spec.buildRequests([{schain: {
- ver: '1.0',
- complete: 1,
- nodes: [{
- asi: 'ssp.test',
- sid: '00001',
- hp: 1
- }]
- }}], Object.assign(getConfigBuildRequest('banner'), {
- gdprConsent: {
- gdprApplies: true,
- consentString: 'XXXX'
- },
- }))
+ fn: spec.buildRequests(
+ [
+ {
+ schain: {
+ ver: '1.0',
+ complete: 1,
+ nodes: [
+ {
+ asi: 'ssp.test',
+ sid: '00001',
+ hp: 1,
+ },
+ ],
+ },
+ },
+ ],
+ Object.assign(getConfigBuildRequest('banner'), {
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: 'XXXX',
+ },
+ })
+ ),
},
want: {
method: 'POST',
url: BLIINK_ENDPOINT_ENGINE,
data: {
+ domLoadingDuration,
+ ect: connectionType,
gdpr: true,
gdprConsent: 'XXXX',
pageDescription: '',
pageTitle: '',
keywords: '',
- pageUrl: 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html?pbjs_debug=true',
+ pageUrl:
+ 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html',
schain: {
ver: '1.0',
complete: 1,
- nodes: [{
- asi: 'ssp.test',
- sid: '00001',
- hp: 1
- }]
+ nodes: [
+ {
+ asi: 'ssp.test',
+ sid: '00001',
+ hp: 1,
+ },
+ ],
},
tags: [
{
transactionId: '2def0c5b2a7f6e',
+ refresh: window.bliinkBid['14f30eca-85d2-11e8-9eed-0242ac120007'] || undefined,
id: '14f30eca-85d2-11e8-9eed-0242ac120007',
- imageUrl: '',
+ imageUrl: 'https://www.example.com/adimage.jpg',
+ videoUrl: 'https://www.example.com/advideo.mp4',
mediaTypes: ['banner'],
sizes: [
{
@@ -696,107 +863,313 @@ const testsBuildRequests = [
},
],
},
- ]
- }
- }
- }
-]
+ ],
+ },
+ },
+ },
+ {
+ title: 'Should build request with eids if exists',
+ args: {
+ fn: spec.buildRequests(
+ [
+ {
+ userIdAsEids: [
+ {
+ 'source': 'criteo.com',
+ 'uids': [
+ {
+ 'id': 'vG4RRF93V05LRlJUTVVOQTJJJTJGbG1rZWxEeDVvc0NXWE42TzJqU2hG',
+ 'atype': 1
+ }
+ ]
+ },
+ {
+ 'source': 'netid.de',
+ 'uids': [
+ {
+ 'id': 'fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg',
+ 'atype': 1
+ }
+ ]
+ }
+ ],
+ },
+ ],
+ Object.assign(getConfigBuildRequest('banner'), {
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: 'XXXX',
+ },
+ })
+ ),
+ },
+ want: {
+ method: 'POST',
+ url: BLIINK_ENDPOINT_ENGINE,
+ data: {
+ domLoadingDuration,
+ ect: connectionType,
+ gdpr: true,
+ gdprConsent: 'XXXX',
+ pageDescription: '',
+ pageTitle: '',
+ keywords: '',
+ pageUrl:
+ 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html',
+ eids: [
+ {
+ 'source': 'criteo.com',
+ 'uids': [
+ {
+ 'id': 'vG4RRF93V05LRlJUTVVOQTJJJTJGbG1rZWxEeDVvc0NXWE42TzJqU2hG',
+ 'atype': 1
+ }
+ ]
+ },
+ {
+ 'source': 'netid.de',
+ 'uids': [
+ {
+ 'id': 'fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg',
+ 'atype': 1
+ }
+ ]
+ }
+ ],
+ tags: [
+ {
+ transactionId: '2def0c5b2a7f6e',
+ refresh: window.bliinkBid['14f30eca-85d2-11e8-9eed-0242ac120007'] || undefined,
+ id: '14f30eca-85d2-11e8-9eed-0242ac120007',
+ imageUrl: 'https://www.example.com/adimage.jpg',
+ videoUrl: 'https://www.example.com/advideo.mp4',
+ mediaTypes: ['banner'],
+ sizes: [
+ {
+ h: 250,
+ w: 300,
+ },
+ ],
+ },
+ ],
+ },
+ },
+ },
+];
-describe('BLIINK Adapter buildRequests', function() {
+describe('BLIINK Adapter buildRequests', function () {
for (const test of testsBuildRequests) {
it(test.title, () => {
- const res = test.args.fn
- expect(res).to.eql(test.want)
- })
+ const res = test.args.fn;
+ expect(res).to.eql(test.want);
+ test.args.after;
+ });
}
-})
+});
const getSyncOptions = (pixelEnabled = true, iframeEnabled = false) => {
return {
pixelEnabled,
- iframeEnabled
- }
-}
+ iframeEnabled,
+ };
+};
const getServerResponses = () => {
return [
{
- body: {bids: [],
- userSyncs: [ {
- type: 'script',
- url: 'https://prg.smartadserver.com/ac?out=js&nwid=3392&siteid=305791&pgname=rg&fmtid=81127&tgt=[sas_target]&visit=m&tmstp=[timestamp]&clcturl=[countgo]'
- },
- {
- type: 'image',
- url: 'https://sync.smartadserver.com/getuid?nwid=3392&consentString=XXX&url=https%3A%2F%2Fcookiesync.api.bliink.io%2Fcookiesync%3Fpartner%3Dsmart%26uid%3D%5Bsas_uid%5D'
- }]},
- }
- ]
-}
+ body: {
+ bids: [],
+ userSyncs: [
+ {
+ type: 'script',
+ url: 'https://prg.smartadserver.com/ac?out=js&nwid=3392&siteid=305791&pgname=rg&fmtid=81127&tgt=[sas_target]&visit=m&tmstp=[timestamp]&clcturl=[countgo]',
+ },
+ {
+ type: 'image',
+ url: 'https://sync.smartadserver.com/getuid?nwid=3392&consentString=XXX&url=https%3A%2F%2Fcookiesync.api.bliink.io%2Fcookiesync%3Fpartner%3Dsmart%26uid%3D%5Bsas_uid%5D',
+ },
+ ],
+ },
+ },
+ ];
+};
const getGdprConsent = () => {
return {
gdprApplies: 1,
consentString: 'XXX',
- apiVersion: 2
- }
-}
+ apiVersion: 2,
+ };
+};
const testsGetUserSyncs = [
{
title: 'Should not have gdprConsent exist',
args: {
- fn: spec.getUserSyncs(getSyncOptions(), getServerResponses(), getGdprConsent())
+ fn: spec.getUserSyncs(
+ getSyncOptions(),
+ getServerResponses(),
+ getGdprConsent()
+ ),
},
want: [
{
type: 'script',
- url: 'https://prg.smartadserver.com/ac?out=js&nwid=3392&siteid=305791&pgname=rg&fmtid=81127&tgt=[sas_target]&visit=m&tmstp=[timestamp]&clcturl=[countgo]'
+ url: 'https://prg.smartadserver.com/ac?out=js&nwid=3392&siteid=305791&pgname=rg&fmtid=81127&tgt=[sas_target]&visit=m&tmstp=[timestamp]&clcturl=[countgo]',
},
{
type: 'image',
- url: 'https://sync.smartadserver.com/getuid?nwid=3392&consentString=XXX&url=https%3A%2F%2Fcookiesync.api.bliink.io%2Fcookiesync%3Fpartner%3Dsmart%26uid%3D%5Bsas_uid%5D'
- }
- ]
+ url: 'https://sync.smartadserver.com/getuid?nwid=3392&consentString=XXX&url=https%3A%2F%2Fcookiesync.api.bliink.io%2Fcookiesync%3Fpartner%3Dsmart%26uid%3D%5Bsas_uid%5D',
+ },
+ ],
},
{
title: 'Should return iframe cookie sync if iframeEnabled',
args: {
- fn: spec.getUserSyncs(getSyncOptions(true, true), getServerResponses(), getGdprConsent())
+ fn: spec.getUserSyncs(
+ getSyncOptions(true, true),
+ getServerResponses(),
+ getGdprConsent()
+ ),
},
want: [
{
type: 'iframe',
- url: `${BLIINK_ENDPOINT_COOKIE_SYNC_IFRAME}?gdpr=${getGdprConsent().gdprApplies}&coppa=0&gdprConsent=${getGdprConsent().consentString}&apiVersion=${getGdprConsent().apiVersion}`
+ url: `${BLIINK_ENDPOINT_COOKIE_SYNC_IFRAME}?gdpr=${
+ getGdprConsent().gdprApplies
+ }&coppa=0&gdprConsent=${getGdprConsent().consentString}&apiVersion=${
+ getGdprConsent().apiVersion
+ }`,
},
- ]
+ ],
},
{
title: 'ccpa',
args: {
- fn: spec.getUserSyncs(getSyncOptions(true, true), getServerResponses(), getGdprConsent(), 'ccpa-consent')
+ fn: spec.getUserSyncs(
+ getSyncOptions(true, true),
+ getServerResponses(),
+ getGdprConsent(),
+ 'ccpa-consent'
+ ),
},
want: [
{
type: 'iframe',
- url: `${BLIINK_ENDPOINT_COOKIE_SYNC_IFRAME}?gdpr=${getGdprConsent().gdprApplies}&coppa=0&uspConsent=ccpa-consent&gdprConsent=${getGdprConsent().consentString}&apiVersion=${getGdprConsent().apiVersion}`
+ url: `${BLIINK_ENDPOINT_COOKIE_SYNC_IFRAME}?gdpr=${
+ getGdprConsent().gdprApplies
+ }&coppa=0&uspConsent=ccpa-consent&gdprConsent=${
+ getGdprConsent().consentString
+ }&apiVersion=${getGdprConsent().apiVersion}`,
},
- ]
+ ],
},
{
title: 'Should output sync if no gdprConsent',
args: {
- fn: spec.getUserSyncs(getSyncOptions(), getServerResponses())
+ fn: spec.getUserSyncs(getSyncOptions(), getServerResponses()),
},
- want: getServerResponses()[0].body.userSyncs
- }
-]
+ want: getServerResponses()[0].body.userSyncs,
+ },
+ {
+ title: 'Should output empty array if no pixelEnabled',
+ args: {
+ fn: spec.getUserSyncs({}, getServerResponses()),
+ },
+ want: [],
+ },
+];
-describe('BLIINK Adapter getUserSyncs', function() {
+describe('BLIINK Adapter getUserSyncs', function () {
for (const test of testsGetUserSyncs) {
it(test.title, () => {
- const res = test.args.fn
- expect(res).to.eql(test.want)
- })
+ const res = test.args.fn;
+ expect(res).to.eql(test.want);
+ });
}
-})
+});
+
+describe('BLIINK Adapter keywords & coppa true', function () {
+ it('Should build request with keyword and coppa true if exist', () => {
+ const metaElement = document.createElement('meta');
+ metaElement.name = 'keywords';
+ metaElement.content = 'Bliink, Saber, Prebid';
+ sinon.stub(config, 'getConfig').withArgs('coppa').returns(true);
+
+ const querySelectorStub = sinon
+ .stub(document, 'querySelector')
+ .returns(metaElement);
+ expect(
+ spec.buildRequests(
+ [],
+ Object.assign(getConfigBuildRequest('banner'), {
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: 'XXXX',
+ },
+ })
+ )
+ ).to.eql({
+ method: 'POST',
+ url: BLIINK_ENDPOINT_ENGINE,
+ data: {
+ domLoadingDuration,
+ ect: connectionType,
+ gdpr: true,
+ coppa: 1,
+ gdprConsent: 'XXXX',
+ pageDescription: 'Bliink, Saber, Prebid',
+ pageTitle: '',
+ keywords: 'Bliink,Saber,Prebid',
+ pageUrl:
+ 'http://localhost:9999/integrationExamples/gpt/bliink-adapter.html',
+ tags: [
+ {
+ transactionId: '2def0c5b2a7f6e',
+ id: '14f30eca-85d2-11e8-9eed-0242ac120007',
+ imageUrl: 'https://www.example.com/adimage.jpg',
+ videoUrl: 'https://www.example.com/advideo.mp4',
+ mediaTypes: ['banner'],
+ refresh: window.bliinkBid['14f30eca-85d2-11e8-9eed-0242ac120007'] || undefined,
+ sizes: [
+ {
+ h: 250,
+ w: 300,
+ },
+ ],
+ },
+ ],
+ },
+ });
+ querySelectorStub.restore();
+ config.getConfig.restore();
+ });
+});
+
+describe('getEffectiveConnectionType', () => {
+ let navigatorStub;
+
+ beforeEach(() => {
+ if ('connection' in navigator) {
+ navigatorStub = sinon.stub(navigator, 'connection').value({
+ effectiveType: undefined,
+ });
+ }
+ });
+
+ afterEach(() => {
+ if (navigatorStub) {
+ navigatorStub.restore();
+ }
+ });
+ if (navigatorStub) {
+ it('should return "unsupported" when effective connection type is undefined', () => {
+ const result = getEffectiveConnectionType();
+ expect(result).to.equal('unsupported');
+ });
+ }
+});
+
+it('should expose gvlid', function () {
+ expect(spec.gvlid).to.equal(GVL_ID);
+});
diff --git a/test/spec/modules/boldwinBidAdapter_spec.js b/test/spec/modules/boldwinBidAdapter_spec.js
index 5b51183ea6d..9a7b16c0914 100644
--- a/test/spec/modules/boldwinBidAdapter_spec.js
+++ b/test/spec/modules/boldwinBidAdapter_spec.js
@@ -19,7 +19,8 @@ describe('BoldwinBidAdapter', function () {
const bidderRequest = {
refererInfo: {
referer: 'test.com'
- }
+ },
+ ortb2: {}
};
describe('isBidRequestValid', function () {
@@ -110,6 +111,36 @@ describe('BoldwinBidAdapter', function () {
expect(data.placements).to.be.an('array').that.is.empty;
});
});
+
+ describe('gpp consent', function () {
+ it('bidderRequest.gppConsent', () => {
+ bidderRequest.gppConsent = {
+ gppString: 'abc123',
+ applicableSections: [8]
+ };
+
+ let serverRequest = spec.buildRequests([bid], bidderRequest);
+ let data = serverRequest.data;
+ expect(data).to.be.an('object');
+ expect(data).to.have.property('gpp');
+ expect(data).to.have.property('gpp_sid');
+
+ delete bidderRequest.gppConsent;
+ })
+
+ it('bidderRequest.ortb2.regs.gpp', () => {
+ bidderRequest.ortb2.regs = bidderRequest.ortb2.regs || {};
+ bidderRequest.ortb2.regs.gpp = 'abc123';
+ bidderRequest.ortb2.regs.gpp_sid = [8];
+
+ let serverRequest = spec.buildRequests([bid], bidderRequest);
+ let data = serverRequest.data;
+ expect(data).to.be.an('object');
+ expect(data).to.have.property('gpp');
+ expect(data).to.have.property('gpp_sid');
+ })
+ });
+
describe('interpretResponse', function () {
it('Should interpret banner response', function () {
const banner = {
@@ -283,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/cadentApertureMXBidAdapter_spec.js b/test/spec/modules/cadentApertureMXBidAdapter_spec.js
index 64f3d047a3a..3ccb5405552 100644
--- a/test/spec/modules/cadentApertureMXBidAdapter_spec.js
+++ b/test/spec/modules/cadentApertureMXBidAdapter_spec.js
@@ -237,6 +237,11 @@ describe('cadent_aperture_mx Adapter', function () {
'bidId': '30b31c2501de1e',
'auctionId': 'e19f1eff-8b27-42a6-888d-9674e5a6130c',
'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec',
+ 'ortb2Imp': {
+ 'ext': {
+ 'tid': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ed',
+ },
+ },
}]
};
let request = spec.buildRequests(bidderRequest.bids, bidderRequest);
@@ -297,12 +302,22 @@ describe('cadent_aperture_mx Adapter', function () {
expect(data.id).to.equal(bidderRequest.auctionId);
expect(data.imp.length).to.equal(1);
expect(data.imp[0].id).to.equal('30b31c2501de1e');
- expect(data.imp[0].tid).to.equal('d7b773de-ceaa-484d-89ca-d9f51b8d61ec');
+ expect(data.imp[0].tid).to.equal('d7b773de-ceaa-484d-89ca-d9f51b8d61ed');
expect(data.imp[0].tagid).to.equal('25251');
expect(data.imp[0].secure).to.equal(0);
expect(data.imp[0].vastXml).to.equal(undefined);
});
+ it('populates id even when auctionId is not available', function () {
+ // addressing https://github.com/prebid/Prebid.js/issues/9781
+ bidderRequest.auctionId = null;
+ request = spec.buildRequests(bidderRequest.bids, bidderRequest);
+
+ const data = JSON.parse(request.data);
+ expect(data.id).not.to.be.null;
+ expect(data.id).not.to.equal(bidderRequest.auctionId);
+ });
+
it('properly sends site information and protocol', function () {
request = spec.buildRequests(bidderRequest.bids, bidderRequest);
request = JSON.parse(request.data);
@@ -834,5 +849,38 @@ describe('cadent_aperture_mx Adapter', function () {
expect(syncs[0].url).to.contains('usp=test');
expect(syncs[0].url).to.equal('https://biddr.brealtime.com/check.html?gdpr=1&gdpr_consent=test&usp=test')
});
+
+ it('should pass gpp string and section id', function() {
+ let syncs = spec.getUserSyncs({iframeEnabled: true}, {}, {}, {}, {
+ gppString: 'abcdefgs',
+ applicableSections: [1, 2, 4]
+ });
+ expect(syncs).to.not.be.an('undefined');
+ expect(syncs[0].url).to.contains('gpp=abcdefgs')
+ expect(syncs[0].url).to.contains('gpp_sid=1,2,4')
+ });
+
+ it('should pass us_privacy and gdpr string and gpp string', function () {
+ let syncs = spec.getUserSyncs({ iframeEnabled: true }, {},
+ {
+ gdprApplies: true,
+ consentString: 'test'
+ },
+ {
+ consentString: 'test'
+ },
+ {
+ gppString: 'abcdefgs',
+ applicableSections: [1, 2, 4]
+ }
+ );
+ expect(syncs).to.not.be.an('undefined');
+ expect(syncs).to.have.lengthOf(1);
+ expect(syncs[0].type).to.equal('iframe');
+ expect(syncs[0].url).to.contains('gdpr=1');
+ expect(syncs[0].url).to.contains('usp=test');
+ expect(syncs[0].url).to.contains('gpp=abcdefgs');
+ expect(syncs[0].url).to.equal('https://biddr.brealtime.com/check.html?gdpr=1&gdpr_consent=test&usp=test&gpp=abcdefgs&gpp_sid=1,2,4');
+ });
});
});
diff --git a/test/spec/modules/concertBidAdapter_spec.js b/test/spec/modules/concertBidAdapter_spec.js
index 4a6a4f2ba60..0a76ed3e62d 100644
--- a/test/spec/modules/concertBidAdapter_spec.js
+++ b/test/spec/modules/concertBidAdapter_spec.js
@@ -94,7 +94,7 @@ describe('ConcertAdapter', function () {
});
describe('spec.isBidRequestValid', function() {
- it('should return when it recieved all the required params', function() {
+ it('should return when it received all the required params', function() {
const bid = bidRequests[0];
expect(spec.isBidRequestValid(bid)).to.equal(true);
});
@@ -116,7 +116,20 @@ describe('ConcertAdapter', function () {
expect(payload).to.have.property('meta');
expect(payload).to.have.property('slots');
- const metaRequiredFields = ['prebidVersion', 'pageUrl', 'screen', 'debug', 'uid', 'optedOut', 'adapterVersion', 'uspConsent', 'gdprConsent', 'gppConsent', 'browserLanguage'];
+ const metaRequiredFields = [
+ 'prebidVersion',
+ 'pageUrl',
+ 'screen',
+ 'debug',
+ 'uid',
+ 'optedOut',
+ 'adapterVersion',
+ 'uspConsent',
+ 'gdprConsent',
+ 'gppConsent',
+ 'browserLanguage',
+ 'tdid'
+ ];
const slotsRequiredFields = ['name', 'bidId', 'transactionId', 'sizes', 'partnerId', 'slotType'];
metaRequiredFields.forEach(function(field) {
@@ -199,6 +212,31 @@ describe('ConcertAdapter', function () {
expect(slot.offsetCoordinates.x).to.equal(100)
expect(slot.offsetCoordinates.y).to.equal(0)
})
+
+ it('should not pass along tdid if the user has opted out', function() {
+ storage.setDataInLocalStorage('c_nap', 'true');
+ const request = spec.buildRequests(bidRequests, bidRequest);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.meta.tdid).to.be.null;
+ });
+
+ it('should not pass along tdid if USP consent disallows', function() {
+ storage.removeDataFromLocalStorage('c_nap');
+ const request = spec.buildRequests(bidRequests, { ...bidRequest, uspConsent: '1YY' });
+ const payload = JSON.parse(request.data);
+
+ expect(payload.meta.tdid).to.be.null;
+ });
+
+ it('should pass along tdid if the user has not opted out', function() {
+ storage.removeDataFromLocalStorage('c_nap', 'true');
+ const tdid = '123abc';
+ const bidRequestsWithTdid = [{ ...bidRequests[0], userId: { tdid } }]
+ const request = spec.buildRequests(bidRequestsWithTdid, bidRequest);
+ const payload = JSON.parse(request.data);
+ expect(payload.meta.tdid).to.equal(tdid);
+ });
});
describe('spec.interpretResponse', function() {
diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js
index 16ead9f9458..78f6a9d410d 100644
--- a/test/spec/modules/connatixBidAdapter_spec.js
+++ b/test/spec/modules/connatixBidAdapter_spec.js
@@ -135,14 +135,12 @@ describe('connatixBidAdapter', function () {
describe('interpretResponse', function () {
const CustomerId = '99f20d18-c4b4-4a28-3d8e-d43e2c8cb4ac';
const PlayerId = 'e4984e88-9ff4-45a3-8b9d-33aabcad634f';
- const Bid = {Cpm: 0.1, LineItems: [], RequestId: '2f897340c4eaa3', Ttl: 86400};
+ const Bid = {Cpm: 0.1, RequestId: '2f897340c4eaa3', Ttl: 86400, CustomerId, PlayerId};
let serverResponse;
this.beforeEach(function () {
serverResponse = {
body: {
- CustomerId,
- PlayerId,
Bids: [ Bid ]
},
headers: function() { }
@@ -162,18 +160,6 @@ describe('connatixBidAdapter', function () {
expect(response).to.be.an('array').that.is.empty;
});
- it('Should return an empty array if CustomerId is null', function () {
- serverResponse.body.CustomerId = null;
- const response = spec.interpretResponse(serverResponse);
- expect(response).to.be.an('array').that.is.empty;
- });
-
- it('Should return an empty array if PlayerId is null', function () {
- serverResponse.body.PlayerId = null;
- const response = spec.interpretResponse(serverResponse);
- expect(response).to.be.an('array').that.is.empty;
- });
-
it('Should return one bid response for one bid', function() {
const bidResponses = spec.interpretResponse(serverResponse);
expect(bidResponses.length).to.equal(1);
@@ -212,12 +198,10 @@ describe('connatixBidAdapter', function () {
const CustomerId = '99f20d18-c4b4-4a28-3d8e-d43e2c8cb4ac';
const PlayerId = 'e4984e88-9ff4-45a3-8b9d-33aabcad634f';
const UserSyncEndpoint = 'https://connatix.com/sync'
- const Bid = {Cpm: 0.1, LineItems: [], RequestId: '2f897340c4eaa3', Ttl: 86400};
+ const Bid = {Cpm: 0.1, RequestId: '2f897340c4eaa3', Ttl: 86400, CustomerId, PlayerId};
const serverResponse = {
body: {
- CustomerId,
- PlayerId,
UserSyncEndpoint,
Bids: [ Bid ]
},
diff --git a/test/spec/modules/connectIdSystem_spec.js b/test/spec/modules/connectIdSystem_spec.js
index 5376ba60886..686c3d63a63 100644
--- a/test/spec/modules/connectIdSystem_spec.js
+++ b/test/spec/modules/connectIdSystem_spec.js
@@ -3,6 +3,7 @@ import {connectIdSubmodule, storage} from 'modules/connectIdSystem.js';
import {server} from '../../mocks/xhr';
import {parseQS, parseUrl} from 'src/utils.js';
import {uspDataHandler, gppDataHandler} from 'src/adapterManager.js';
+import * as refererDetection from '../../../src/refererDetection';
const TEST_SERVER_URL = 'http://localhost:9876/';
@@ -288,6 +289,79 @@ describe('Yahoo ConnectID Submodule', () => {
expect(setCookieStub.firstCall.args[2]).to.equal(expiryDelta.toUTCString());
});
+ it('returns an object with the stored ID from cookies and syncs because of expired TTL', () => {
+ const last2Days = Date.now() - (60 * 60 * 24 * 1000 * 2);
+ const last21Days = Date.now() - (60 * 60 * 24 * 1000 * 21);
+ const ttl = 10000;
+ const cookieData = {connectId: 'foo', he: 'email', lastSynced: last2Days, puid: '9', lastUsed: last21Days, ttl};
+ getCookieStub.withArgs(STORAGE_KEY).returns(JSON.stringify(cookieData));
+
+ let result = invokeGetIdAPI({
+ he: HASHED_EMAIL,
+ pixelId: PIXEL_ID
+ }, consentData);
+
+ expect(result).to.be.an('object').that.has.all.keys('id', 'callback');
+ expect(result.id).to.deep.equal(cookieData);
+ expect(typeof result.callback).to.equal('function');
+ });
+
+ it('returns an object with the stored ID from cookies and not syncs because of valid TTL', () => {
+ const last2Days = Date.now() - (60 * 60 * 24 * 1000 * 2);
+ const last21Days = Date.now() - (60 * 60 * 24 * 1000 * 21);
+ const ttl = 60 * 60 * 24 * 1000 * 3;
+ const cookieData = {connectId: 'foo', he: HASHED_EMAIL, lastSynced: last2Days, puid: '9', lastUsed: last21Days, ttl};
+ getCookieStub.withArgs(STORAGE_KEY).returns(JSON.stringify(cookieData));
+
+ let result = invokeGetIdAPI({
+ he: HASHED_EMAIL,
+ pixelId: PIXEL_ID
+ }, consentData);
+
+ expect(result).to.be.an('object').that.has.all.keys('id');
+ cookieData.lastUsed = result.id.lastUsed;
+ expect(result.id).to.deep.equal(cookieData);
+ });
+
+ it('returns an object with the stored ID from cookies and not syncs because of valid TTL with provided puid', () => {
+ const last2Days = Date.now() - (60 * 60 * 24 * 1000 * 2);
+ const last21Days = Date.now() - (60 * 60 * 24 * 1000 * 21);
+ const ttl = 60 * 60 * 24 * 1000 * 3;
+ const cookieData = {connectId: 'foo', he: HASHED_EMAIL, lastSynced: last2Days, puid: '9', lastUsed: last21Days, ttl};
+ getCookieStub.withArgs(STORAGE_KEY).returns(JSON.stringify(cookieData));
+
+ let result = invokeGetIdAPI({
+ he: HASHED_EMAIL,
+ pixelId: PIXEL_ID,
+ puid: '9'
+ }, consentData);
+
+ expect(result).to.be.an('object').that.has.all.keys('id');
+ cookieData.lastUsed = result.id.lastUsed;
+ expect(result.id).to.deep.equal(cookieData);
+ });
+
+ it('returns an object with the stored ID from cookies and syncs because is O&O traffic', () => {
+ const last2Days = Date.now() - (60 * 60 * 24 * 1000 * 2);
+ const last21Days = Date.now() - (60 * 60 * 24 * 1000 * 21);
+ const ttl = 60 * 60 * 24 * 1000 * 3;
+ const cookieData = {connectId: 'foo', he: HASHED_EMAIL, lastSynced: last2Days, puid: '9', lastUsed: last21Days, ttl};
+ getCookieStub.withArgs(STORAGE_KEY).returns(JSON.stringify(cookieData));
+ const getRefererInfoStub = sinon.stub(refererDetection, 'getRefererInfo');
+ getRefererInfoStub.returns({
+ ref: 'https://dev.fc.yahoo.com?test'
+ });
+ let result = invokeGetIdAPI({
+ he: HASHED_EMAIL,
+ pixelId: PIXEL_ID
+ }, consentData);
+ getRefererInfoStub.restore();
+
+ expect(result).to.be.an('object').that.has.all.keys('id', 'callback');
+ expect(result.id).to.deep.equal(cookieData);
+ expect(typeof result.callback).to.equal('function');
+ });
+
it('Makes an ajax GET request to the production API endpoint with stored puid when id is stale', () => {
const last15Days = Date.now() - (60 * 60 * 24 * 1000 * 15);
const last29Days = Date.now() - (60 * 60 * 24 * 1000 * 29);
diff --git a/test/spec/modules/consentManagementGpp_spec.js b/test/spec/modules/consentManagementGpp_spec.js
index e15ce30940c..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]) => {
@@ -572,6 +572,17 @@ describe('consentManagementGpp', function () {
expect(err.message).to.eql('err');
done();
});
+ });
+
+ it('should not choke if supportedAPIs is missing', () => {
+ [gppData, pingData].forEach(ob => { delete ob.supportedAPIs; })
+ mockCmpCommands({
+ getGPPData: () => gppData
+ });
+ return gppClient.getGPPData(pingData).then(res => {
+ expect(res.gppString).to.eql(gppData.gppString);
+ expect(res.parsedSections).to.eql({});
+ })
})
describe('section data', () => {
diff --git a/test/spec/modules/consentManagementUsp_spec.js b/test/spec/modules/consentManagementUsp_spec.js
index e98486754ab..c372c66f7f0 100644
--- a/test/spec/modules/consentManagementUsp_spec.js
+++ b/test/spec/modules/consentManagementUsp_spec.js
@@ -522,6 +522,19 @@ describe('consentManagement', function () {
setConsentConfig(goodConfig);
expect(uspDataHandler.getConsentData()).to.eql('string');
});
+
+ it('does not invoke registerDeletion if the CMP calls back with an error', () => {
+ sandbox.stub(window, '__uspapi').callsFake((cmd, _, cb) => {
+ if (cmd === 'registerDeletion') {
+ cb(null, false);
+ } else {
+ // eslint-disable-next-line standard/no-callback-literal
+ cb({uspString: 'string'}, true);
+ }
+ });
+ setConsentConfig(goodConfig);
+ sinon.assert.notCalled(adapterManager.callDataDeletionRequest);
+ })
});
});
});
diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js
index deeb8f7100d..d8e75454245 100644
--- a/test/spec/modules/consumableBidAdapter_spec.js
+++ b/test/spec/modules/consumableBidAdapter_spec.js
@@ -651,21 +651,30 @@ describe('Consumable BidAdapter', function () {
expect(opts[0].url).to.equal('https://sync.serverbid.com/ss/730181.html?gdpr=0&gdpr_consent=GDPR_CONSENT_STRING');
})
- it('should return a sync url if iframe syncs are enabled and GPP applies', function () {
+ it('should return a sync url if iframe syncs are enabled and has GPP consent with applicable sections', function () {
let gppConsent = {
applicableSections: [1, 2],
gppString: 'GPP_CONSENT_STRING'
}
- let opts = spec.getUserSyncs(syncOptions, [AD_SERVER_RESPONSE], {}, {}, gppConsent);
+ let opts = spec.getUserSyncs(syncOptions, [AD_SERVER_RESPONSE], {}, '', gppConsent);
expect(opts.length).to.equal(1);
- expect(opts[0].url).to.equal('https://sync.serverbid.com/ss/730181.html?gpp=GPP_CONSENT_STRING&gpp_sid=1,2');
+ expect(opts[0].url).to.equal('https://sync.serverbid.com/ss/730181.html?gpp=GPP_CONSENT_STRING&gpp_sid=1%2C2');
})
- it('should return a sync url if iframe syncs are enabled and USP applies', function () {
- let uspConsent = {
- consentString: 'USP_CONSENT_STRING',
+ it('should return a sync url if iframe syncs are enabled and has GPP consent without applicable sections', function () {
+ let gppConsent = {
+ applicableSections: [],
+ gppString: 'GPP_CONSENT_STRING'
}
+ let opts = spec.getUserSyncs(syncOptions, [AD_SERVER_RESPONSE], {}, '', gppConsent);
+
+ expect(opts.length).to.equal(1);
+ expect(opts[0].url).to.equal('https://sync.serverbid.com/ss/730181.html?gpp=GPP_CONSENT_STRING');
+ })
+
+ it('should return a sync url if iframe syncs are enabled and USP applies', function () {
+ let uspConsent = 'USP_CONSENT_STRING';
let opts = spec.getUserSyncs(syncOptions, [AD_SERVER_RESPONSE], {}, uspConsent);
expect(opts.length).to.equal(1);
@@ -677,9 +686,7 @@ describe('Consumable BidAdapter', function () {
consentString: 'GDPR_CONSENT_STRING',
gdprApplies: true,
}
- let uspConsent = {
- consentString: 'USP_CONSENT_STRING',
- }
+ let uspConsent = 'USP_CONSENT_STRING';
let opts = spec.getUserSyncs(syncOptions, [AD_SERVER_RESPONSE], gdprConsent, uspConsent);
expect(opts.length).to.equal(1);
@@ -704,50 +711,22 @@ describe('Consumable BidAdapter', function () {
sandbox.restore();
});
- it('Request should have unifiedId config params', function() {
+ it('Request should have EIDs', function() {
bidderRequest.bidRequest[0].userId = {};
bidderRequest.bidRequest[0].userId.tdid = 'TTD_ID';
- bidderRequest.bidRequest[0].userIdAsEids = createEidsArray(bidderRequest.bidRequest[0].userId);
- let request = spec.buildRequests(bidderRequest.bidRequest, BIDDER_REQUEST_1);
- let data = JSON.parse(request.data);
- expect(data.user.eids).to.deep.equal([{
+ bidderRequest.bidRequest[0].userIdAsEids = [{
'source': 'adserver.org',
'uids': [{
- 'id': 'TTD_ID',
+ 'id': 'TTD_ID_FROM_USER_ID_MODULE',
'atype': 1,
'ext': {
'rtiPartner': 'TDID'
}
}]
- }]);
- });
-
- it('Request should have adsrvrOrgId from UserId Module if config and userId module both have TTD ID', function() {
- sandbox.stub(config, 'getConfig').callsFake((key) => {
- var config = {
- adsrvrOrgId: {
- 'TDID': 'TTD_ID_FROM_CONFIG',
- 'TDID_LOOKUP': 'TRUE',
- 'TDID_CREATED_AT': '2022-06-21T09:47:00'
- }
- };
- return config[key];
- });
- bidderRequest.bidRequest[0].userId = {};
- bidderRequest.bidRequest[0].userId.tdid = 'TTD_ID';
- bidderRequest.bidRequest[0].userIdAsEids = createEidsArray(bidderRequest.bidRequest[0].userId);
+ }];
let request = spec.buildRequests(bidderRequest.bidRequest, BIDDER_REQUEST_1);
let data = JSON.parse(request.data);
- expect(data.user.eids).to.deep.equal([{
- 'source': 'adserver.org',
- 'uids': [{
- 'id': 'TTD_ID',
- 'atype': 1,
- 'ext': {
- 'rtiPartner': 'TDID'
- }
- }]
- }]);
+ expect(data.user.eids).to.deep.equal(bidderRequest.bidRequest[0].userIdAsEids);
});
it('Request should NOT have adsrvrOrgId params if userId is NOT object', function() {
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/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js
index 7cba0e2fbdf..5dc6d74d90e 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 = [
@@ -1326,12 +1263,25 @@ describe('The Criteo bidding adapter', function () {
sizes: [[640, 480]],
mediaTypes: {
video: {
+ context: 'instream',
playerSize: [640, 480],
mimes: ['video/mp4', 'video/x-flv'],
maxduration: 30,
api: [1, 2],
protocols: [2, 3],
- plcmt: 3
+ plcmt: 3,
+ w: 640,
+ h: 480,
+ linearity: 1,
+ skipmin: 30,
+ skipafter: 30,
+ minbitrate: 10000,
+ maxbitrate: 48000,
+ delivery: [1, 2, 3],
+ pos: 1,
+ playbackend: 1,
+ adPodDurationSec: 30,
+ durationRangeSec: [1, 30],
}
},
params: {
@@ -1350,6 +1300,7 @@ describe('The Criteo bidding adapter', function () {
expect(request.url).to.match(/^https:\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/);
expect(request.method).to.equal('POST');
const ortbRequest = request.data;
+ expect(ortbRequest.slots[0].video.context).to.equal('instream');
expect(ortbRequest.slots[0].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']);
expect(ortbRequest.slots[0].sizes).to.deep.equal([]);
expect(ortbRequest.slots[0].video.playersizes).to.deep.equal(['640x480']);
@@ -1362,6 +1313,18 @@ describe('The Criteo bidding adapter', function () {
expect(ortbRequest.slots[0].video.playbackmethod).to.deep.equal([1, 3]);
expect(ortbRequest.slots[0].video.placement).to.equal(2);
expect(ortbRequest.slots[0].video.plcmt).to.equal(3);
+ expect(ortbRequest.slots[0].video.w).to.equal(640);
+ expect(ortbRequest.slots[0].video.h).to.equal(480);
+ expect(ortbRequest.slots[0].video.linearity).to.equal(1);
+ expect(ortbRequest.slots[0].video.skipmin).to.equal(30);
+ expect(ortbRequest.slots[0].video.skipafter).to.equal(30);
+ expect(ortbRequest.slots[0].video.minbitrate).to.equal(10000);
+ expect(ortbRequest.slots[0].video.maxbitrate).to.equal(48000);
+ expect(ortbRequest.slots[0].video.delivery).to.deep.equal([1, 2, 3]);
+ expect(ortbRequest.slots[0].video.pos).to.equal(1);
+ expect(ortbRequest.slots[0].video.playbackend).to.equal(1);
+ expect(ortbRequest.slots[0].video.adPodDurationSec).to.equal(30);
+ expect(ortbRequest.slots[0].video.durationRangeSec).to.deep.equal([1, 30]);
});
it('should properly build a video request with more than one player size', function () {
@@ -1879,6 +1842,86 @@ describe('The Criteo bidding adapter', function () {
const request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.data.slots[0].rwdd).to.be.undefined;
});
+
+ it('should properly build a request when FLEDGE is enabled', function () {
+ const bidderRequest = {
+ fledgeEnabled: true,
+ };
+ const bidRequests = [
+ {
+ bidder: 'criteo',
+ adUnitCode: 'bid-123',
+ transactionId: 'transaction-123',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90]]
+ }
+ },
+ params: {
+ zoneId: 123,
+ ext: {
+ bidfloor: 0.75
+ }
+ },
+ ortb2Imp: {
+ ext: {
+ ae: 1
+ }
+ }
+ },
+ ];
+
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.slots[0].ext.ae).to.equal(1);
+ });
+
+ it('should properly build a request when FLEDGE is disabled', function () {
+ const bidderRequest = {
+ fledgeEnabled: false,
+ };
+ const bidRequests = [
+ {
+ bidder: 'criteo',
+ adUnitCode: 'bid-123',
+ transactionId: 'transaction-123',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90]]
+ }
+ },
+ params: {
+ zoneId: 123,
+ ext: {
+ bidfloor: 0.75
+ }
+ },
+ ortb2Imp: {
+ ext: {
+ ae: 1
+ }
+ }
+ },
+ ];
+
+ 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 () {
@@ -2410,6 +2453,144 @@ describe('The Criteo bidding adapter', function () {
expect(bids[0].height).to.equal(90);
});
+ it('should properly parse a bid response with FLEDGE auction configs', function () {
+ const response = {
+ body: {
+ ext: {
+ igbid: [{
+ impid: 'test-bidId',
+ igbuyer: [{
+ origin: 'https://first-buyer-domain.com',
+ buyerdata: {
+ foo: 'bar',
+ },
+ }, {
+ origin: 'https://second-buyer-domain.com',
+ buyerdata: {
+ 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',
+ }
+ },
+ },
+ },
+ };
+ const bidderRequest = {
+ ortb2: {
+ source: {
+ tid: 'abc'
+ }
+ }
+ };
+ const bidRequests = [
+ {
+ bidId: 'test-bidId',
+ bidder: 'criteo',
+ adUnitCode: 'bid-123',
+ transactionId: 'transaction-123',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90]]
+ }
+ },
+ params: {
+ bidFloor: 1,
+ 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(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',
+ 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',
+ floor: 1,
+ sellerCurrency: 'EUR',
+ },
+ },
+ });
+ });
+
[{
hasBidResponseLevelPafData: true,
hasBidResponseBidLevelPafData: true,
diff --git a/test/spec/modules/criteoIdSystem_spec.js b/test/spec/modules/criteoIdSystem_spec.js
index aaf63873d93..975271738e5 100644
--- a/test/spec/modules/criteoIdSystem_spec.js
+++ b/test/spec/modules/criteoIdSystem_spec.js
@@ -52,17 +52,21 @@ describe('CriteoId module', function () {
});
const storageTestCases = [
- { cookie: 'bidId', localStorage: 'bidId2', expected: 'bidId' },
- { cookie: 'bidId', localStorage: undefined, expected: 'bidId' },
- { cookie: undefined, localStorage: 'bidId', expected: 'bidId' },
- { cookie: undefined, localStorage: undefined, expected: undefined },
+ { submoduleConfig: undefined, cookie: 'bidId', localStorage: 'bidId2', expected: 'bidId' },
+ { submoduleConfig: undefined, cookie: 'bidId', localStorage: undefined, expected: 'bidId' },
+ { submoduleConfig: undefined, cookie: undefined, localStorage: 'bidId', expected: 'bidId' },
+ { submoduleConfig: undefined, cookie: undefined, localStorage: undefined, expected: undefined },
+ { submoduleConfig: { storage: { type: 'cookie' } }, cookie: 'bidId', localStorage: 'bidId2', expected: 'bidId' },
+ { submoduleConfig: { storage: { type: 'cookie' } }, cookie: undefined, localStorage: 'bidId2', expected: undefined },
+ { submoduleConfig: { storage: { type: 'html5' } }, cookie: 'bidId', localStorage: 'bidId2', expected: 'bidId2' },
+ { submoduleConfig: { storage: { type: 'html5' } }, cookie: 'bidId', localStorage: undefined, expected: undefined },
]
- storageTestCases.forEach(testCase => it('getId() should return the bidId when it exists in local storages', function () {
+ storageTestCases.forEach(testCase => it('getId() should return the user id depending on the storage type enabled and the data available', function () {
getCookieStub.withArgs('cto_bidid').returns(testCase.cookie);
getLocalStorageStub.withArgs('cto_bidid').returns(testCase.localStorage);
- const result = criteoIdSubmodule.getId();
+ const result = criteoIdSubmodule.getId(testCase.submoduleConfig);
expect(result.id).to.be.deep.equal(testCase.expected ? { criteoId: testCase.expected } : undefined);
expect(result.callback).to.be.a('function');
}))
@@ -95,22 +99,24 @@ describe('CriteoId module', function () {
});
const responses = [
- { bundle: 'bundle', bidId: 'bidId', acwsUrl: 'acwsUrl' },
- { bundle: 'bundle', bidId: undefined, acwsUrl: 'acwsUrl' },
- { bundle: 'bundle', bidId: 'bidId', acwsUrl: undefined },
- { bundle: undefined, bidId: 'bidId', acwsUrl: 'acwsUrl' },
- { bundle: 'bundle', bidId: undefined, acwsUrl: undefined },
- { bundle: undefined, bidId: 'bidId', acwsUrl: undefined },
- { bundle: undefined, bidId: undefined, acwsUrl: 'acwsUrl' },
- { bundle: undefined, bidId: undefined, acwsUrl: ['acwsUrl', 'acwsUrl2'] },
- { bundle: undefined, bidId: undefined, acwsUrl: undefined },
+ { submoduleConfig: undefined, shouldWriteCookie: true, shouldWriteLocalStorage: true, bundle: 'bundle', bidId: 'bidId', acwsUrl: 'acwsUrl' },
+ { submoduleConfig: undefined, shouldWriteCookie: true, shouldWriteLocalStorage: true, bundle: 'bundle', bidId: undefined, acwsUrl: 'acwsUrl' },
+ { submoduleConfig: undefined, shouldWriteCookie: true, shouldWriteLocalStorage: true, bundle: 'bundle', bidId: 'bidId', acwsUrl: undefined },
+ { submoduleConfig: undefined, shouldWriteCookie: true, shouldWriteLocalStorage: true, bundle: undefined, bidId: 'bidId', acwsUrl: 'acwsUrl' },
+ { submoduleConfig: undefined, shouldWriteCookie: true, shouldWriteLocalStorage: true, bundle: 'bundle', bidId: undefined, acwsUrl: undefined },
+ { submoduleConfig: undefined, shouldWriteCookie: true, shouldWriteLocalStorage: true, bundle: undefined, bidId: 'bidId', acwsUrl: undefined },
+ { submoduleConfig: undefined, shouldWriteCookie: true, shouldWriteLocalStorage: true, bundle: undefined, bidId: undefined, acwsUrl: 'acwsUrl' },
+ { submoduleConfig: undefined, shouldWriteCookie: true, shouldWriteLocalStorage: true, bundle: undefined, bidId: undefined, acwsUrl: ['acwsUrl', 'acwsUrl2'] },
+ { submoduleConfig: undefined, shouldWriteCookie: true, shouldWriteLocalStorage: true, bundle: undefined, bidId: undefined, acwsUrl: undefined },
+ { submoduleConfig: { storage: { type: 'cookie' } }, shouldWriteCookie: true, shouldWriteLocalStorage: false, bundle: 'bundle', bidId: 'bidId', acwsUrl: undefined },
+ { submoduleConfig: { storage: { type: 'html5' } }, shouldWriteCookie: false, shouldWriteLocalStorage: true, bundle: 'bundle', bidId: 'bidId', acwsUrl: undefined },
]
responses.forEach(response => describe('test user sync response behavior', function () {
const expirationTs = new Date(nowTimestamp + cookiesMaxAge).toString();
it('should save bidId if it exists', function () {
- const result = criteoIdSubmodule.getId();
+ const result = criteoIdSubmodule.getId(response.submoduleConfig);
result.callback((id) => {
expect(id).to.be.deep.equal(response.bidId ? { criteoId: response.bidId } : undefined);
});
@@ -127,16 +133,35 @@ describe('CriteoId module', function () {
expect(setCookieStub.calledWith('cto_bundle')).to.be.false;
expect(setLocalStorageStub.calledWith('cto_bundle')).to.be.false;
} else if (response.bundle) {
- expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs, null, '.com')).to.be.true;
- expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs, null, '.testdev.com')).to.be.true;
- expect(setLocalStorageStub.calledWith('cto_bundle', response.bundle)).to.be.true;
+ if (response.shouldWriteCookie) {
+ expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs, null, '.com')).to.be.true;
+ expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs, null, '.testdev.com')).to.be.true;
+ } else {
+ expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs, null, '.com')).to.be.false;
+ expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs, null, '.testdev.com')).to.be.false;
+ }
+
+ if (response.shouldWriteLocalStorage) {
+ expect(setLocalStorageStub.calledWith('cto_bundle', response.bundle)).to.be.true;
+ } else {
+ expect(setLocalStorageStub.calledWith('cto_bundle', response.bundle)).to.be.false;
+ }
expect(triggerPixelStub.called).to.be.false;
}
if (response.bidId) {
- expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs, null, '.com')).to.be.true;
- expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs, null, '.testdev.com')).to.be.true;
- expect(setLocalStorageStub.calledWith('cto_bidid', response.bidId)).to.be.true;
+ if (response.shouldWriteCookie) {
+ expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs, null, '.com')).to.be.true;
+ expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs, null, '.testdev.com')).to.be.true;
+ } else {
+ expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs, null, '.com')).to.be.false;
+ expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs, null, '.testdev.com')).to.be.false;
+ }
+ if (response.shouldWriteLocalStorage) {
+ expect(setLocalStorageStub.calledWith('cto_bidid', response.bidId)).to.be.true;
+ } else {
+ expect(setLocalStorageStub.calledWith('cto_bidid', response.bidId)).to.be.false;
+ }
} else {
expect(setCookieStub.calledWith('cto_bidid', '', pastDateString, null, '.com')).to.be.true;
expect(setCookieStub.calledWith('cto_bidid', '', pastDateString, null, '.testdev.com')).to.be.true;
diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js
index f7c2580f3f3..fa44b7daa7a 100644
--- a/test/spec/modules/currency_spec.js
+++ b/test/spec/modules/currency_spec.js
@@ -10,11 +10,12 @@ import {
addBidResponseHook,
currencySupportEnabled,
currencyRates,
- ready
+ responseReady
} from 'modules/currency.js';
import {createBid} from '../../../src/bidfactory.js';
import CONSTANTS from '../../../src/constants.json';
import {server} from '../../mocks/xhr.js';
+import * as events from 'src/events.js';
var assert = require('chai').assert;
var expect = require('chai').expect;
@@ -32,7 +33,6 @@ describe('currency', function () {
beforeEach(function () {
fakeCurrencyFileServer = server;
- ready.reset();
});
afterEach(function () {
@@ -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',
@@ -287,32 +300,56 @@ describe('currency', function () {
expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('1000.000');
});
- it('uses default rates when currency file fails to load', function () {
- setConfig({});
-
- setConfig({
- adServerCurrency: 'USD',
- defaultRates: {
- USD: {
- JPY: 100
+ describe('when rates fail to load', () => {
+ let bid, addBidResponse, reject;
+ beforeEach(() => {
+ bid = makeBid({cpm: 100, currency: 'JPY', bidder: 'rubicoin'});
+ addBidResponse = sinon.spy();
+ reject = sinon.spy();
+ })
+ it('uses default rates if specified', function () {
+ setConfig({
+ adServerCurrency: 'USD',
+ defaultRates: {
+ USD: {
+ JPY: 100
+ }
}
- }
- });
-
- // default response is 404
- fakeCurrencyFileServer.respond();
+ });
- var bid = { cpm: 100, currency: 'JPY', bidder: 'rubicon' };
- var innerBid;
+ // default response is 404
+ addBidResponseHook(addBidResponse, 'au', bid);
+ fakeCurrencyFileServer.respond();
+ sinon.assert.calledWith(addBidResponse, 'au', sinon.match(innerBid => {
+ expect(innerBid.cpm).to.equal('1.0000');
+ expect(typeof innerBid.getCpmInNewCurrency).to.equal('function');
+ expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000');
+ return true;
+ }));
+ });
- addBidResponseHook(function(adCodeId, bid) {
- innerBid = bid;
- }, 'elementId', bid);
+ it('rejects bids if no default rates are specified', () => {
+ setConfig({
+ adServerCurrency: 'USD',
+ });
+ addBidResponseHook(addBidResponse, 'au', bid, reject);
+ fakeCurrencyFileServer.respond();
+ sinon.assert.notCalled(addBidResponse);
+ sinon.assert.calledWith(reject, CONSTANTS.REJECTION_REASON.CANNOT_CONVERT_CURRENCY);
+ });
- expect(innerBid.cpm).to.equal('1.0000');
- expect(typeof innerBid.getCpmInNewCurrency).to.equal('function');
- expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000');
- });
+ it('attempts to load rates again on the next auction', () => {
+ setConfig({
+ adServerCurrency: 'USD',
+ });
+ fakeCurrencyFileServer.respond();
+ fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates()));
+ events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {});
+ addBidResponseHook(addBidResponse, 'au', bid, reject);
+ fakeCurrencyFileServer.respond();
+ sinon.assert.calledWith(addBidResponse, 'au', bid, reject);
+ })
+ })
});
describe('currency.addBidResponseDecorator bidResponseQueue', function () {
@@ -321,29 +358,26 @@ describe('currency', function () {
fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates()));
- var bid = { 'cpm': 1, 'currency': 'USD' };
+ const bid = { 'cpm': 1, 'currency': 'USD' };
setConfig({ 'adServerCurrency': 'JPY' });
- var marker = false;
- let promiseResolved = false;
+ let responseAdded = false;
+ let isReady = false;
+ responseReady.promise.then(() => { isReady = true });
+
addBidResponseHook(Object.assign(function() {
- marker = true;
- }, {
- bail: function (promise) {
- promise.then(() => promiseResolved = true);
- }
+ responseAdded = true;
}), 'elementId', bid);
- expect(marker).to.equal(false);
-
setTimeout(() => {
- expect(promiseResolved).to.be.false;
+ expect(responseAdded).to.equal(false);
+ expect(isReady).to.equal(false);
fakeCurrencyFileServer.respond();
setTimeout(() => {
- expect(marker).to.equal(true);
- expect(promiseResolved).to.be.true;
+ expect(responseAdded).to.equal(true);
+ expect(isReady).to.equal(true);
done();
});
});
@@ -419,6 +453,23 @@ describe('currency', function () {
expect(reject.calledOnce).to.be.true;
});
+ it('should reject bid when rates have not loaded when the auction times out', () => {
+ fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates()));
+ setConfig({'adServerCurrency': 'JPY'});
+ const bid = makeBid({cpm: 1, currency: 'USD', auctionId: 'aid'});
+ const noConversionBid = makeBid({cpm: 1, currency: 'JPY', auctionId: 'aid'});
+ const reject = sinon.spy();
+ const addBidResponse = sinon.spy();
+ addBidResponseHook(addBidResponse, 'au', bid, reject);
+ addBidResponseHook(addBidResponse, 'au', noConversionBid, reject);
+ events.emit(CONSTANTS.EVENTS.AUCTION_TIMEOUT, {auctionId: 'aid'});
+ fakeCurrencyFileServer.respond();
+ sinon.assert.calledOnce(addBidResponse);
+ sinon.assert.calledWith(addBidResponse, 'au', noConversionBid, reject);
+ sinon.assert.calledOnce(reject);
+ sinon.assert.calledWith(reject, CONSTANTS.REJECTION_REASON.CANNOT_CONVERT_CURRENCY);
+ })
+
it('should return 1 when currency support is enabled and same currency code is requested as is set to adServerCurrency', function () {
fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates()));
setConfig({ 'adServerCurrency': 'JPY' });
diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js
index 89485adf28b..4c12e9fa211 100644
--- a/test/spec/modules/dfpAdServerVideo_spec.js
+++ b/test/spec/modules/dfpAdServerVideo_spec.js
@@ -58,8 +58,18 @@ describe('The DFP video support module', function () {
}, options)));
const prm = utils.parseQS(url.query);
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);
+ 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 () {
diff --git a/test/spec/modules/dgkeywordRtdProvider_spec.js b/test/spec/modules/dgkeywordRtdProvider_spec.js
index 754740b7a64..ff88ea0512f 100644
--- a/test/spec/modules/dgkeywordRtdProvider_spec.js
+++ b/test/spec/modules/dgkeywordRtdProvider_spec.js
@@ -91,6 +91,22 @@ describe('Digital Garage Keyword Module', function () {
expect(dgRtd.getTargetBidderOfDgKeywords(adUnits_no_target)).an('array')
.that.is.empty;
});
+ it('convertKeywordsToString method unit test', function () {
+ const keywordsTest = [
+ { keywords: { param1: 'keywords1' }, result: 'param1=keywords1' },
+ { keywords: { param1: 'keywords1', param2: 'keywords2' }, result: 'param1=keywords1,param2=keywords2' },
+ { keywords: { p1: 'k1', p2: 'k2', p: 'k' }, result: 'p1=k1,p2=k2,p=k' },
+ { keywords: { p1: 'k1', p2: 'k2', p: ['k'] }, result: 'p1=k1,p2=k2,p=k' },
+ { keywords: { p1: 'k1', p2: ['k21', 'k22'], p: ['k'] }, result: 'p1=k1,p2=k21,p2=k22,p=k' },
+ { keywords: { p1: ['k11', 'k12', 'k13'], p2: ['k21', 'k22'], p: ['k'] }, result: 'p1=k11,p1=k12,p1=k13,p2=k21,p2=k22,p=k' },
+ { keywords: { p1: [], p2: ['', ''], p: [''] }, result: 'p1,p2,p' },
+ { keywords: { p1: 1, p2: [1, 'k2'], p: '' }, result: 'p1,p2=k2,p' },
+ { keywords: { p1: ['k1', 2, 'k3'], p2: [1, 2], p: 3 }, result: 'p1=k1,p1=k3,p2,p' },
+ ];
+ for (const test of keywordsTest) {
+ expect(dgRtd.convertKeywordsToString(test.keywords)).equal(test.result);
+ }
+ })
it('should have targets', function () {
const adUnits_targets = [
{
@@ -242,16 +258,16 @@ describe('Digital Garage Keyword Module', function () {
expect(targets[1].bidder).to.be.equal('dg2');
expect(targets[1].params.placementId).to.be.equal(99999998);
expect(targets[1].params.dgkeyword).to.be.an('undefined');
- expect(targets[1].params.keywords).to.be.an('undefined');
+ expect(targets[1].params.ortb2Imp).to.be.an('undefined');
targets = pbjs.adUnits[1].bids;
expect(targets[0].bidder).to.be.equal('dg');
expect(targets[0].params.placementId).to.be.equal(99999996);
expect(targets[0].params.dgkeyword).to.be.an('undefined');
- expect(targets[0].params.keywords).to.be.an('undefined');
+ expect(targets[0].params.ortb2Imp).to.be.an('undefined');
expect(targets[2].bidder).to.be.equal('dg3');
expect(targets[2].params.placementId).to.be.equal(99999994);
expect(targets[2].params.dgkeyword).to.be.an('undefined');
- expect(targets[2].params.keywords).to.be.an('undefined');
+ expect(targets[2].params.ortb2Imp).to.be.an('undefined');
expect(pbjs.getBidderConfig()).to.be.deep.equal({});
@@ -275,16 +291,16 @@ describe('Digital Garage Keyword Module', function () {
expect(targets[1].bidder).to.be.equal('dg2');
expect(targets[1].params.placementId).to.be.equal(99999998);
expect(targets[1].params.dgkeyword).to.be.an('undefined');
- expect(targets[1].params.keywords).to.be.an('undefined');
+ expect(targets[1].params.ortb2Imp).to.be.an('undefined');
targets = pbjs.adUnits[1].bids;
expect(targets[0].bidder).to.be.equal('dg');
expect(targets[0].params.placementId).to.be.equal(99999996);
expect(targets[0].params.dgkeyword).to.be.an('undefined');
- expect(targets[0].params.keywords).to.be.an('undefined');
+ expect(targets[0].params.ortb2Imp).to.be.an('undefined');
expect(targets[2].bidder).to.be.equal('dg3');
expect(targets[2].params.placementId).to.be.equal(99999994);
expect(targets[2].params.dgkeyword).to.be.an('undefined');
- expect(targets[2].params.keywords).to.be.an('undefined');
+ expect(targets[2].params.ortb2Imp).to.be.an('undefined');
expect(pbjs.getBidderConfig()).to.be.deep.equal({});
@@ -318,16 +334,16 @@ describe('Digital Garage Keyword Module', function () {
expect(targets[1].bidder).to.be.equal('dg2');
expect(targets[1].params.placementId).to.be.equal(99999998);
expect(targets[1].params.dgkeyword).to.be.an('undefined');
- expect(targets[1].params.keywords).to.be.deep.equal(SUCCESS_RESULT);
+ expect(targets[1].ortb2Imp.ext.data.keywords).to.be.deep.equal(dgRtd.convertKeywordsToString(SUCCESS_RESULT));
targets = pbjs.adUnits[1].bids;
expect(targets[0].bidder).to.be.equal('dg');
expect(targets[0].params.placementId).to.be.equal(99999996);
expect(targets[0].params.dgkeyword).to.be.an('undefined');
- expect(targets[0].params.keywords).to.be.deep.equal(SUCCESS_RESULT);
+ expect(targets[0].ortb2Imp.ext.data.keywords).to.be.deep.equal(dgRtd.convertKeywordsToString(SUCCESS_RESULT));
expect(targets[2].bidder).to.be.equal('dg3');
expect(targets[2].params.placementId).to.be.equal(99999994);
expect(targets[2].params.dgkeyword).to.be.an('undefined');
- expect(targets[2].params.keywords).to.be.an('undefined');
+ expect(targets[2].ortb2Imp).to.be.an('undefined');
if (!IGNORE_SET_ORTB2) {
expect(pbjs.getBidderConfig()).to.be.deep.equal({
diff --git a/test/spec/modules/discoveryBidAdapter_spec.js b/test/spec/modules/discoveryBidAdapter_spec.js
index 078add73046..05216ff126c 100644
--- a/test/spec/modules/discoveryBidAdapter_spec.js
+++ b/test/spec/modules/discoveryBidAdapter_spec.js
@@ -1,5 +1,6 @@
import { expect } from 'chai';
-import { spec } from 'modules/discoveryBidAdapter.js';
+import { spec, getPmgUID, storage, getPageTitle, getPageDescription, getPageKeywords, getConnectionDownLink } from 'modules/discoveryBidAdapter.js';
+import * as utils from 'src/utils.js';
describe('discovery:BidAdapterTests', function () {
let bidRequestData = {
@@ -11,12 +12,59 @@ describe('discovery:BidAdapterTests', function () {
bidder: 'discovery',
params: {
token: 'd0f4902b616cc5c38cbe0a08676d0ed9',
+ siteId: 'siteId_01',
+ zoneId: 'zoneId_01',
+ publisher: '52',
+ position: 'left',
+ 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]],
@@ -51,6 +99,47 @@ describe('discovery:BidAdapterTests', function () {
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';
@@ -90,4 +179,269 @@ 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;
+ });
+ });
+ });
});
diff --git a/test/spec/modules/docereeAdManagerBidAdapter_spec.js b/test/spec/modules/docereeAdManagerBidAdapter_spec.js
new file mode 100644
index 00000000000..26b054f4e29
--- /dev/null
+++ b/test/spec/modules/docereeAdManagerBidAdapter_spec.js
@@ -0,0 +1,125 @@
+import { expect } from 'chai';
+import { spec } from '../../../modules/docereeAdManagerBidAdapter.js';
+import { config } from '../../../src/config.js';
+
+describe('docereeadmanager', function () {
+ config.setConfig({
+ docereeadmanager: {
+ user: {
+ data: {
+ email: '',
+ firstname: '',
+ lastname: '',
+ mobile: '',
+ specialization: '',
+ organization: '',
+ hcpid: '',
+ dob: '',
+ gender: '',
+ city: '',
+ state: '',
+ country: '',
+ hashedhcpid: '',
+ hashedemail: '',
+ hashedmobile: '',
+ userid: '',
+ zipcode: '',
+ userconsent: '',
+ },
+ },
+ },
+ });
+ let bid = {
+ bidId: 'testing',
+ bidder: 'docereeadmanager',
+ params: {
+ placementId: 'DOC-19-1',
+ gdpr: '1',
+ gdprconsent:
+ 'CPQfU1jPQfU1jG0AAAENAwCAAAAAAAAAAAAAAAAAAAAA.IGLtV_T9fb2vj-_Z99_tkeYwf95y3p-wzhheMs-8NyZeH_B4Wv2MyvBX4JiQKGRgksjLBAQdtHGlcTQgBwIlViTLMYk2MjzNKJrJEilsbO2dYGD9Pn8HT3ZCY70-vv__7v3ff_3g',
+ },
+ };
+
+ describe('isBidRequestValid', function () {
+ it('Should return true if placementId is present', function () {
+ expect(spec.isBidRequestValid(bid)).to.be.true;
+ });
+ it('Should return false if placementId is not present', function () {
+ delete bid.params.placementId;
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ });
+ });
+
+ describe('isGdprConsentPresent', function () {
+ it('Should return true if gdpr consent is present', function () {
+ expect(spec.isGdprConsentPresent(bid)).to.be.true;
+ });
+ });
+
+ describe('buildRequests', function () {
+ let serverRequest = spec.buildRequests([bid]);
+ serverRequest = serverRequest[0];
+ it('Creates a ServerRequest object with method, URL and data', function () {
+ expect(serverRequest).to.exist;
+ expect(serverRequest.method).to.exist;
+ expect(serverRequest.url).to.exist;
+ expect(serverRequest.data).to.exist;
+ });
+ it('Returns POST method', function () {
+ expect(serverRequest.method).to.equal('POST');
+ });
+ it('Returns valid URL', function () {
+ expect(serverRequest.url).to.equal('https://dai.doceree.com/drs/quest');
+ });
+ });
+ describe('interpretResponse', function () {
+ it('Should interpret banner response', function () {
+ const banner = {
+ body: {
+ cpm: 3.576,
+ currency: 'USD',
+ width: 250,
+ height: 300,
+ ad: 'I am an ad
',
+ ttl: 30,
+ creativeId: 'div-1',
+ netRevenue: false,
+ bidderCode: '123',
+ dealId: 232,
+ requestId: '123',
+ meta: {
+ brandId: null,
+ advertiserDomains: ['https://dai.doceree.com/drs/quest'],
+ },
+ },
+ };
+ let bannerResponses = spec.interpretResponse(banner);
+ 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',
+ 'netRevenue',
+ 'currency',
+ 'mediaType',
+ 'creativeId',
+ 'meta'
+ );
+ expect(dataItem.requestId).to.equal('123');
+ expect(dataItem.cpm).to.equal(3.576);
+ expect(dataItem.width).to.equal(250);
+ expect(dataItem.height).to.equal(300);
+ expect(dataItem.ad).to.equal('I am an ad
');
+ expect(dataItem.ttl).to.equal(30);
+ expect(dataItem.netRevenue).to.be.true;
+ expect(dataItem.currency).to.equal('USD');
+ expect(dataItem.creativeId).to.equal('div-1');
+ expect(dataItem.meta.advertiserDomains).to.be.an('array').that.is.not
+ .empty;
+ });
+ });
+});
diff --git a/test/spec/modules/docereeBidAdapter_spec.js b/test/spec/modules/docereeBidAdapter_spec.js
index dadbb56b0c0..25da8b256fc 100644
--- a/test/spec/modules/docereeBidAdapter_spec.js
+++ b/test/spec/modules/docereeBidAdapter_spec.js
@@ -1,6 +1,7 @@
import {expect} from 'chai';
import {spec} from '../../../modules/docereeBidAdapter.js';
import { config } from '../../../src/config.js';
+import * as utils from 'src/utils.js';
describe('BidlabBidAdapter', function () {
config.setConfig({
@@ -102,4 +103,36 @@ describe('BidlabBidAdapter', function () {
expect(dataItem.meta.advertiserDomains[0]).to.equal('doceree.com')
});
})
+ describe('onBidWon', function () {
+ beforeEach(function() {
+ sinon.stub(utils, 'triggerPixel');
+ });
+ afterEach(function() {
+ utils.triggerPixel.restore();
+ });
+ it('exists and is a function', () => {
+ expect(spec.onBidWon).to.exist.and.to.be.a('function');
+ });
+ it('should return nothing', function () {
+ var response = spec.onBidWon({});
+ expect(response).to.be.an('undefined')
+ expect(utils.triggerPixel.called).to.equal(true);
+ });
+ });
+ describe('onTimeout', function () {
+ beforeEach(function() {
+ sinon.stub(utils, 'triggerPixel');
+ });
+ afterEach(function() {
+ utils.triggerPixel.restore();
+ });
+ it('exists and is a function', () => {
+ expect(spec.onTimeout).to.exist.and.to.be.a('function');
+ });
+ it('should return nothing', function () {
+ var response = spec.onBidWon([]);
+ expect(response).to.be.an('undefined')
+ expect(utils.triggerPixel.called).to.equal(true);
+ });
+ });
});
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
new file mode 100644
index 00000000000..a752c81cb6e
--- /dev/null
+++ b/test/spec/modules/dxkultureBidAdapter_spec.js
@@ -0,0 +1,649 @@
+import {expect} from 'chai';
+import {spec, SYNC_URL} from 'modules/dxkultureBidAdapter.js';
+import {BANNER, VIDEO} from 'src/mediaTypes.js';
+
+const getBannerRequest = () => {
+ return {
+ bidderCode: 'dxkulture',
+ auctionId: 'ba87bfdf-493e-4a88-8e26-17b4cbc9adbd',
+ bidderRequestId: 'bidderRequestId',
+ bids: [
+ {
+ bidder: 'dxkulture',
+ params: {
+ placementId: 123456,
+ publisherId: 'publisherId',
+ bidfloor: 10,
+ },
+ auctionId: 'auctionId-56a2-4f71-9098-720a68f2f708',
+ placementCode: 'div-gpt-dummy-placement-code',
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [ 300, 250 ],
+ ]
+ }
+ },
+ bidId: '2e9f38ea93bb9e',
+ bidderRequestId: 'bidderRequestId',
+ }
+ ],
+ start: 1487883186070,
+ auctionStart: 1487883186069,
+ timeout: 3000
+ }
+};
+
+const getVideoRequest = () => {
+ return {
+ bidderCode: 'dxkulture',
+ auctionId: 'e158486f-8c7f-472f-94ce-b0cbfbb50ab4',
+ bidderRequestId: '34feaad34lkj2',
+ bids: [{
+ mediaTypes: {
+ video: {
+ context: 'instream',
+ playerSize: [[640, 480]],
+ }
+ },
+ bidder: 'dxkulture',
+ sizes: [640, 480],
+ bidId: '30b3efwfwe1e',
+ adUnitCode: 'video1',
+ params: {
+ video: {
+ playerWidth: 640,
+ playerHeight: 480,
+ mimes: ['video/mp4', 'application/javascript'],
+ protocols: [2, 5],
+ api: [2],
+ position: 1,
+ delivery: [2],
+ sid: 134,
+ rewarded: 1,
+ placement: 1,
+ plcmt: 1,
+ hp: 1,
+ inventoryid: 123
+ },
+ site: {
+ id: 1,
+ page: 'https://test.com',
+ referrer: 'http://test.com'
+ },
+ publisherId: 'km123',
+ bidfloor: 10,
+ }
+ }, {
+ mediaTypes: {
+ video: {
+ context: 'instream',
+ playerSize: [[640, 480]],
+ }
+ },
+ bidder: 'dxkulture',
+ sizes: [640, 480],
+ bidId: '30b3efwfwe2e',
+ adUnitCode: 'video1',
+ params: {
+ video: {
+ playerWidth: 640,
+ playerHeight: 480,
+ mimes: ['video/mp4', 'application/javascript'],
+ protocols: [2, 5],
+ api: [2],
+ position: 1,
+ delivery: [2],
+ sid: 134,
+ rewarded: 1,
+ placement: 1,
+ plcmt: 1,
+ hp: 1,
+ inventoryid: 123
+ },
+ site: {
+ id: 1,
+ page: 'https://test.com',
+ referrer: 'http://test.com'
+ },
+ publisherId: 'km123',
+ bidfloor: 10,
+ }
+ }],
+ auctionStart: 1520001292880,
+ timeout: 5000,
+ start: 1520001292884,
+ doneCbCallCount: 0,
+ refererInfo: {
+ numIframes: 1,
+ reachedTop: true,
+ referer: 'test.com'
+ }
+ };
+};
+
+const getBidderResponse = () => {
+ return {
+ headers: null,
+ body: {
+ id: 'bid-response',
+ seatbid: [
+ {
+ bid: [
+ {
+ id: '2e9f38ea93bb9e',
+ impid: '2e9f38ea93bb9e',
+ price: 0.18,
+ adm: '',
+ adid: '144762342',
+ adomain: [
+ 'https://dummydomain.com'
+ ],
+ iurl: 'iurl',
+ cid: '109',
+ crid: 'creativeId',
+ cat: [],
+ w: 300,
+ h: 250,
+ ext: {
+ prebid: {
+ type: 'banner'
+ },
+ bidder: {
+ appnexus: {
+ brand_id: 334553,
+ auction_id: 514667951122925701,
+ bidder_id: 2,
+ bid_ad_type: 0
+ }
+ }
+ }
+ }
+ ],
+ seat: 'dxkulture'
+ }
+ ],
+ ext: {
+ usersync: {
+ sovrn: {
+ status: 'none',
+ syncs: [
+ {
+ url: 'urlsovrn',
+ type: 'iframe'
+ }
+ ]
+ },
+ appnexus: {
+ status: 'none',
+ syncs: [
+ {
+ url: 'urlappnexus',
+ type: 'pixel'
+ }
+ ]
+ }
+ },
+ responsetimemillis: {
+ appnexus: 127
+ }
+ }
+ }
+ };
+}
+
+describe('dxkultureBidAdapter', function() {
+ let videoBidRequest;
+
+ const VIDEO_REQUEST = {
+ 'bidderCode': 'dxkulture',
+ 'auctionId': 'e158486f-8c7f-472f-94ce-b0cbfbb50ab4',
+ 'bidderRequestId': '34feaad34lkj2',
+ 'bids': videoBidRequest,
+ 'auctionStart': 1520001292880,
+ 'timeout': 3000,
+ 'start': 1520001292884,
+ 'doneCbCallCount': 0,
+ 'refererInfo': {
+ 'numIframes': 1,
+ 'reachedTop': true,
+ 'referer': 'test.com'
+ }
+ };
+
+ beforeEach(function () {
+ videoBidRequest = {
+ mediaTypes: {
+ video: {
+ context: 'instream',
+ playerSize: [[640, 480]],
+ }
+ },
+ bidder: 'dxkulture',
+ sizes: [640, 480],
+ bidId: '30b3efwfwe1e',
+ adUnitCode: 'video1',
+ params: {
+ video: {
+ playerWidth: 640,
+ playerHeight: 480,
+ mimes: ['video/mp4', 'application/javascript'],
+ protocols: [2, 5],
+ api: [2],
+ position: 1,
+ delivery: [2],
+ sid: 134,
+ rewarded: 1,
+ placement: 1,
+ plcmt: 1,
+ hp: 1,
+ inventoryid: 123
+ },
+ site: {
+ id: 1,
+ page: 'https://test.com',
+ referrer: 'http://test.com'
+ },
+ publisherId: 'km123',
+ bidfloor: 0
+ }
+ };
+ });
+
+ describe('isValidRequest', function() {
+ let bidderRequest;
+
+ beforeEach(function() {
+ bidderRequest = getBannerRequest();
+ });
+
+ it('should accept request if placementId and publisherId are passed', function () {
+ expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.be.true;
+ });
+
+ it('reject requests without params', function () {
+ bidderRequest.bids[0].params = {};
+ expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.be.false;
+ });
+
+ it('returns false when banner mediaType does not exist', function () {
+ bidderRequest.bids[0].mediaTypes = {}
+ expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.be.false;
+ });
+ });
+
+ describe('buildRequests', function() {
+ let bidderRequest;
+
+ beforeEach(function() {
+ bidderRequest = getBannerRequest();
+ });
+
+ it('should return expected request object', function() {
+ const bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest);
+ expect(bidRequest.url).equal('https://ads.dxkulture.com/pbjs?pid=publisherId&placementId=123456');
+ expect(bidRequest.method).equal('POST');
+ });
+ });
+
+ context('banner validation', function () {
+ let bidderRequest;
+
+ beforeEach(function() {
+ bidderRequest = getBannerRequest();
+ });
+
+ it('returns true when banner sizes are defined', function () {
+ const bid = {
+ bidder: 'dxkulture',
+ mediaTypes: {
+ banner: {
+ sizes: [[250, 300]]
+ }
+ },
+ params: {
+ placementId: 'placementId',
+ publisherId: 'publisherId',
+ }
+ };
+
+ expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.be.true;
+ });
+
+ it('returns false when banner sizes are invalid', function () {
+ const invalidSizes = [
+ undefined,
+ '2:1',
+ 123,
+ 'test'
+ ];
+
+ invalidSizes.forEach((sizes) => {
+ const bid = {
+ bidder: 'dxkulture',
+ mediaTypes: {
+ banner: {
+ sizes
+ }
+ },
+ params: {
+ placementId: 'placementId',
+ publisherId: 'publisherId',
+ }
+ };
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ });
+ });
+ });
+
+ context('video validation', function () {
+ beforeEach(function () {
+ // Basic Valid BidRequest
+ this.bid = {
+ bidder: 'dxkulture',
+ mediaTypes: {
+ video: {
+ playerSize: [[300, 50]],
+ context: 'instream',
+ mimes: ['foo', 'bar'],
+ protocols: [1, 2]
+ }
+ },
+ params: {
+ placementId: 'placementId',
+ publisherId: 'publisherId',
+ }
+ };
+ });
+
+ it('should return true (skip validations) when e2etest = true', function () {
+ this.bid.params = {
+ e2etest: true
+ };
+ expect(spec.isBidRequestValid(this.bid)).to.equal(true);
+ });
+
+ it('returns false when video context is not defined', function () {
+ delete this.bid.mediaTypes.video.context;
+
+ expect(spec.isBidRequestValid(this.bid)).to.be.false;
+ });
+
+ it('returns false when video playserSize is invalid', function () {
+ const invalidSizes = [
+ undefined,
+ '2:1',
+ 123,
+ 'test'
+ ];
+
+ invalidSizes.forEach((playerSize) => {
+ this.bid.mediaTypes.video.playerSize = playerSize;
+ expect(spec.isBidRequestValid(this.bid)).to.be.false;
+ });
+ });
+
+ it('returns false when video mimes is invalid', function () {
+ const invalidMimes = [
+ undefined,
+ 'test',
+ 1,
+ []
+ ]
+
+ invalidMimes.forEach((mimes) => {
+ this.bid.mediaTypes.video.mimes = mimes;
+ expect(spec.isBidRequestValid(this.bid)).to.be.false;
+ })
+ });
+
+ it('returns false when video protocols is invalid', function () {
+ const invalidMimes = [
+ undefined,
+ 'test',
+ 1,
+ []
+ ]
+
+ invalidMimes.forEach((protocols) => {
+ this.bid.mediaTypes.video.protocols = protocols;
+ expect(spec.isBidRequestValid(this.bid)).to.be.false;
+ })
+ });
+ });
+
+ describe('buildRequests', function () {
+ let bidderBannerRequest;
+ let bidRequestsWithMediaTypes;
+ let mockBidderRequest;
+
+ beforeEach(function() {
+ bidderBannerRequest = getBannerRequest();
+
+ mockBidderRequest = {refererInfo: {}};
+
+ bidRequestsWithMediaTypes = [{
+ bidder: 'dxkulture',
+ params: {
+ publisherId: 'km123',
+ },
+ adUnitCode: '/adunit-code/test-path',
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250], [300, 600]]
+ }
+ },
+ bidId: 'test-bid-id-1',
+ bidderRequestId: 'test-bid-request-1',
+ auctionId: 'test-auction-1',
+ transactionId: 'test-transactionId-1',
+ ortb2Imp: {
+ ext: {
+ ae: 2
+ }
+ }
+ }, {
+ bidder: 'dxkulture',
+ params: {
+ publisherId: 'km123',
+ },
+ adUnitCode: 'adunit-code',
+ mediaTypes: {
+ video: {
+ playerSize: [640, 480],
+ placement: 1,
+ plcmt: 1,
+ }
+ },
+ bidId: 'test-bid-id-2',
+ bidderRequestId: 'test-bid-request-2',
+ auctionId: 'test-auction-2',
+ transactionId: 'test-transactionId-2'
+ }];
+ });
+
+ context('when mediaType is banner', function () {
+ it('creates request data', function () {
+ let request = spec.buildRequests(bidderBannerRequest.bids, bidderBannerRequest)
+
+ expect(request).to.exist.and.to.be.a('object');
+ const payload = request.data;
+ expect(payload.imp[0]).to.have.property('id', bidderBannerRequest.bids[0].bidId);
+ });
+
+ it('has gdpr data if applicable', function () {
+ const req = Object.assign({}, getBannerRequest(), {
+ gdprConsent: {
+ consentString: 'consentString',
+ gdprApplies: true,
+ }
+ });
+ let request = spec.buildRequests(bidderBannerRequest.bids, req);
+
+ const payload = request.data;
+ expect(payload.user.ext).to.have.property('consent', req.gdprConsent.consentString);
+ expect(payload.regs.ext).to.have.property('gdpr', 1);
+ });
+ });
+
+ if (FEATURES.VIDEO) {
+ context('video', function () {
+ it('should create a POST request for every bid', function () {
+ const requests = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
+ expect(requests.method).to.equal('POST');
+ expect(requests.url.trim()).to.equal(spec.ENDPOINT + '?pid=' + videoBidRequest.params.publisherId);
+ });
+
+ it('should attach request data', function () {
+ const requests = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
+ const data = requests.data;
+ const [width, height] = videoBidRequest.sizes;
+ const VERSION = '1.0.0';
+
+ expect(data.imp[1].video.w).to.equal(width);
+ expect(data.imp[1].video.h).to.equal(height);
+ expect(data.imp[1].bidfloor).to.equal(videoBidRequest.params.bidfloor);
+ expect(data.imp[1]['video']['placement']).to.equal(videoBidRequest.params.video['placement']);
+ expect(data.imp[1]['video']['plcmt']).to.equal(videoBidRequest.params.video['plcmt']);
+ expect(data.ext.prebidver).to.equal('$prebid.version$');
+ expect(data.ext.adapterver).to.equal(spec.VERSION);
+ });
+
+ it('should set pubId to e2etest when bid.params.e2etest = true', function () {
+ bidRequestsWithMediaTypes[0].params.e2etest = true;
+ const requests = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
+ expect(requests.method).to.equal('POST');
+ expect(requests.url).to.equal(spec.ENDPOINT + '?pid=e2etest');
+ });
+
+ it('should attach End 2 End test data', function () {
+ bidRequestsWithMediaTypes[1].params.e2etest = true;
+ const requests = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
+ const data = requests.data;
+ expect(data.imp[1].bidfloor).to.equal(0);
+ expect(data.imp[1].video.w).to.equal(640);
+ expect(data.imp[1].video.h).to.equal(480);
+ });
+ });
+ }
+ });
+
+ describe('interpretResponse', function() {
+ context('when mediaType is banner', function() {
+ let bidRequest, bidderResponse;
+ beforeEach(function() {
+ const bidderRequest = getBannerRequest();
+ bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest);
+ bidderResponse = getBidderResponse();
+ });
+
+ it('handles empty response', function () {
+ const EMPTY_RESP = Object.assign({}, bidderResponse, {'body': {}});
+ const bids = spec.interpretResponse(EMPTY_RESP, bidRequest);
+
+ expect(bids).to.be.empty;
+ });
+
+ it('have bids', function () {
+ let bids = spec.interpretResponse(bidderResponse, bidRequest);
+ expect(bids).to.be.an('array').that.is.not.empty;
+ validateBidOnIndex(0);
+
+ function validateBidOnIndex(index) {
+ expect(bids[index]).to.have.property('currency', 'USD');
+ expect(bids[index]).to.have.property('requestId', getBidderResponse().body.seatbid[0].bid[index].impid);
+ expect(bids[index]).to.have.property('cpm', getBidderResponse().body.seatbid[0].bid[index].price);
+ expect(bids[index]).to.have.property('width', getBidderResponse().body.seatbid[0].bid[index].w);
+ expect(bids[index]).to.have.property('height', getBidderResponse().body.seatbid[0].bid[index].h);
+ expect(bids[index]).to.have.property('ad', getBidderResponse().body.seatbid[0].bid[index].adm);
+ expect(bids[index]).to.have.property('creativeId', getBidderResponse().body.seatbid[0].bid[index].crid);
+ expect(bids[index].meta).to.have.property('advertiserDomains');
+ expect(bids[index]).to.have.property('ttl', 300);
+ expect(bids[index]).to.have.property('netRevenue', true);
+ }
+ });
+ });
+
+ context('when mediaType is video', function () {
+ let bidRequest, bidderResponse;
+ beforeEach(function() {
+ const bidderRequest = getVideoRequest();
+ bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest);
+ bidderResponse = getBidderResponse();
+ });
+
+ it('handles empty response', function () {
+ const EMPTY_RESP = Object.assign({}, bidderResponse, {'body': {}});
+ const bids = spec.interpretResponse(EMPTY_RESP, bidRequest);
+
+ expect(bids).to.be.empty;
+ });
+
+ it('should return no bids if the response "nurl" and "adm" are missing', function () {
+ const SERVER_RESP = Object.assign({}, bidderResponse, {'body': {
+ seatbid: [{
+ bid: [{
+ price: 6.01
+ }]
+ }]
+ }});
+ const bids = spec.interpretResponse(SERVER_RESP, bidRequest);
+ expect(bids.length).to.equal(0);
+ });
+
+ it('should return no bids if the response "price" is missing', function () {
+ const SERVER_RESP = Object.assign({}, bidderResponse, {'body': {
+ seatbid: [{
+ bid: [{
+ adm: ''
+ }]
+ }]
+ }});
+ const bids = spec.interpretResponse(SERVER_RESP, bidRequest);
+ expect(bids.length).to.equal(0);
+ });
+ });
+ });
+
+ 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;
+ });
+ it('returns non if sync is not allowed', function () {
+ let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false});
+
+ expect(opts).to.be.an('array').that.is.empty;
+ });
+
+ it('iframe sync enabled should return results', function () {
+ let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [bidderResponse]);
+
+ 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);
+ });
+
+ it('pixel sync enabled should return results', function () {
+ let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [bidderResponse]);
+
+ 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);
+ });
+
+ it('all sync enabled should prioritize iframe', function () {
+ let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, [bidderResponse]);
+
+ expect(opts.length).to.equal(1);
+ });
+ });
+});
diff --git a/test/spec/modules/dynamicAdBoostRtdProvider_spec.js b/test/spec/modules/dynamicAdBoostRtdProvider_spec.js
new file mode 100644
index 00000000000..66c24435589
--- /dev/null
+++ b/test/spec/modules/dynamicAdBoostRtdProvider_spec.js
@@ -0,0 +1,77 @@
+import { subModuleObj as rtdProvider } from 'modules/dynamicAdBoostRtdProvider.js';
+import { loadExternalScript } from '../../../src/adloader.js';
+import { expect } from 'chai';
+
+const configWithParams = {
+ params: {
+ keyId: 'dynamic',
+ adUnits: ['gpt-123'],
+ threshold: 1
+ }
+};
+
+const configWithoutRequiredParams = {
+ params: {
+ keyId: ''
+ }
+};
+
+describe('dynamicAdBoost', function() {
+ let clock;
+ let sandbox;
+ beforeEach(function () {
+ sandbox = sinon.sandbox.create();
+ clock = sandbox.useFakeTimers(Date.now());
+ });
+ afterEach(function () {
+ sandbox.restore();
+ });
+ describe('init', function() {
+ describe('initialize without expected params', function() {
+ it('fails initalize when keyId is not present', function() {
+ expect(rtdProvider.init(configWithoutRequiredParams)).to.be.false;
+ })
+ })
+
+ describe('initialize with expected params', function() {
+ it('successfully initialize with load script', function() {
+ expect(rtdProvider.init(configWithParams)).to.be.true;
+ clock.tick(1000);
+ expect(loadExternalScript.called).to.be.true;
+ })
+ });
+ });
+})
+
+describe('markViewed tests', function() {
+ let sandbox;
+ const mockObserver = {
+ unobserve: sinon.spy()
+ };
+ const makeElement = (id) => {
+ const el = document.createElement('div');
+ el.setAttribute('id', id);
+ return el;
+ }
+ const mockEntry = {
+ target: makeElement('target_id')
+ };
+
+ beforeEach(function() {
+ sandbox = sinon.sandbox.create();
+ })
+
+ afterEach(function() {
+ sandbox.restore()
+ })
+
+ it('markViewed returns a function', function() {
+ expect(rtdProvider.markViewed(mockEntry, mockObserver)).to.be.a('function')
+ });
+
+ it('markViewed unobserves', function() {
+ const func = rtdProvider.markViewed(mockEntry, mockObserver);
+ func();
+ expect(mockObserver.unobserve.calledOnce).to.be.true;
+ });
+})
diff --git a/test/spec/modules/edge226BidAdapter_spec.js b/test/spec/modules/edge226BidAdapter_spec.js
new file mode 100644
index 00000000000..4819d8d4a4e
--- /dev/null
+++ b/test/spec/modules/edge226BidAdapter_spec.js
@@ -0,0 +1,373 @@
+import { expect } from 'chai';
+import { spec } from '../../../modules/edge226BidAdapter.js';
+import { BANNER, VIDEO, NATIVE } from '../../../src/mediaTypes.js';
+import { getUniqueIdentifierStr } from '../../../src/utils.js';
+
+const bidder = 'edge226'
+
+describe('Edge226BidAdapter', function () {
+ const bids = [
+ {
+ bidId: getUniqueIdentifierStr(),
+ bidder: bidder,
+ mediaTypes: {
+ [BANNER]: {
+ sizes: [[300, 250]]
+ }
+ },
+ params: {
+ placementId: 'testBanner',
+ }
+ },
+ {
+ bidId: getUniqueIdentifierStr(),
+ bidder: bidder,
+ mediaTypes: {
+ [VIDEO]: {
+ playerSize: [[300, 300]],
+ minduration: 5,
+ maxduration: 60
+ }
+ },
+ params: {
+ placementId: 'testVideo',
+ }
+ },
+ {
+ bidId: getUniqueIdentifierStr(),
+ bidder: bidder,
+ mediaTypes: {
+ [NATIVE]: {
+ native: {
+ title: {
+ required: true
+ },
+ body: {
+ required: true
+ },
+ icon: {
+ required: true,
+ size: [64, 64]
+ }
+ }
+ }
+ },
+ params: {
+ placementId: 'testNative',
+ }
+ }
+ ];
+
+ const invalidBid = {
+ bidId: getUniqueIdentifierStr(),
+ bidder: bidder,
+ mediaTypes: {
+ [BANNER]: {
+ sizes: [[300, 250]]
+ }
+ },
+ params: {
+
+ }
+ }
+
+ const bidderRequest = {
+ uspConsent: '1---',
+ gdprConsent: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
+ refererInfo: {
+ referer: 'https://test.com'
+ },
+ timeout: 500
+ };
+
+ describe('isBidRequestValid', function () {
+ it('Should return true if there are bidId, params and key parameters present', function () {
+ expect(spec.isBidRequestValid(bids[0])).to.be.true;
+ });
+ it('Should return false if at least one of parameters is not present', function () {
+ expect(spec.isBidRequestValid(invalidBid)).to.be.false;
+ });
+ });
+
+ describe('buildRequests', function () {
+ let serverRequest = spec.buildRequests(bids, bidderRequest);
+
+ it('Creates a ServerRequest object with method, URL and data', function () {
+ expect(serverRequest).to.exist;
+ expect(serverRequest.method).to.exist;
+ expect(serverRequest.url).to.exist;
+ expect(serverRequest.data).to.exist;
+ });
+
+ it('Returns POST method', function () {
+ expect(serverRequest.method).to.equal('POST');
+ });
+
+ it('Returns valid URL', function () {
+ expect(serverRequest.url).to.equal('https://ssp.dauup.com/pbjs');
+ });
+
+ it('Returns general data valid', function () {
+ let data = serverRequest.data;
+ expect(data).to.be.an('object');
+ expect(data).to.have.all.keys('deviceWidth',
+ 'deviceHeight',
+ 'language',
+ 'secure',
+ 'host',
+ 'page',
+ 'placements',
+ 'coppa',
+ 'ccpa',
+ 'gdpr',
+ 'tmax'
+ );
+ expect(data.deviceWidth).to.be.a('number');
+ expect(data.deviceHeight).to.be.a('number');
+ expect(data.language).to.be.a('string');
+ expect(data.secure).to.be.within(0, 1);
+ 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.ccpa).to.be.a('string');
+ expect(data.tmax).to.be.a('number');
+ expect(data.placements).to.have.lengthOf(3);
+ });
+
+ it('Returns valid placements', function () {
+ const { placements } = serverRequest.data;
+ for (let i = 0, len = placements.length; i < len; i++) {
+ const placement = placements[i];
+ expect(placement.placementId).to.be.oneOf(['testBanner', 'testVideo', 'testNative']);
+ expect(placement.adFormat).to.be.oneOf([BANNER, VIDEO, NATIVE]);
+ expect(placement.bidId).to.be.a('string');
+ 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');
+
+ if (placement.adFormat === BANNER) {
+ expect(placement.sizes).to.be.an('array');
+ }
+ switch (placement.adFormat) {
+ case BANNER:
+ expect(placement.sizes).to.be.an('array');
+ break;
+ case VIDEO:
+ expect(placement.playerSize).to.be.an('array');
+ expect(placement.minduration).to.be.an('number');
+ expect(placement.maxduration).to.be.an('number');
+ break;
+ case NATIVE:
+ expect(placement.native).to.be.an('object');
+ break;
+ }
+ }
+ });
+
+ it('Returns data with gdprConsent and without uspConsent', function () {
+ delete bidderRequest.uspConsent;
+ 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.ccpa).to.not.exist;
+ delete bidderRequest.gdprConsent;
+ });
+
+ it('Returns data with uspConsent and without gdprConsent', function () {
+ bidderRequest.uspConsent = '1---';
+ delete bidderRequest.gdprConsent;
+ serverRequest = spec.buildRequests(bids, bidderRequest);
+ let data = serverRequest.data;
+ expect(data.ccpa).to.exist;
+ expect(data.ccpa).to.be.a('string');
+ 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 () {
+ it('Should interpret banner response', function () {
+ const banner = {
+ body: [{
+ mediaType: 'banner',
+ width: 300,
+ height: 250,
+ cpm: 0.4,
+ ad: 'Test',
+ requestId: '23fhj33i987f',
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1',
+ meta: {
+ advertiserDomains: ['google.com'],
+ advertiserId: 1234
+ }
+ }]
+ };
+ let bannerResponses = spec.interpretResponse(banner);
+ 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', 'mediaType', 'meta');
+ expect(dataItem.requestId).to.equal(banner.body[0].requestId);
+ expect(dataItem.cpm).to.equal(banner.body[0].cpm);
+ expect(dataItem.width).to.equal(banner.body[0].width);
+ expect(dataItem.height).to.equal(banner.body[0].height);
+ expect(dataItem.ad).to.equal(banner.body[0].ad);
+ expect(dataItem.ttl).to.equal(banner.body[0].ttl);
+ expect(dataItem.creativeId).to.equal(banner.body[0].creativeId);
+ expect(dataItem.netRevenue).to.be.true;
+ expect(dataItem.currency).to.equal(banner.body[0].currency);
+ expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains');
+ });
+ it('Should interpret video response', function () {
+ const video = {
+ body: [{
+ vastUrl: 'test.com',
+ mediaType: 'video',
+ cpm: 0.5,
+ requestId: '23fhj33i987f',
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1',
+ meta: {
+ advertiserDomains: ['google.com'],
+ advertiserId: 1234
+ }
+ }]
+ };
+ let videoResponses = spec.interpretResponse(video);
+ expect(videoResponses).to.be.an('array').that.is.not.empty;
+
+ let dataItem = videoResponses[0];
+ expect(dataItem).to.have.all.keys('requestId', 'cpm', 'vastUrl', 'ttl', 'creativeId',
+ 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta');
+ expect(dataItem.requestId).to.equal('23fhj33i987f');
+ expect(dataItem.cpm).to.equal(0.5);
+ expect(dataItem.vastUrl).to.equal('test.com');
+ expect(dataItem.ttl).to.equal(120);
+ expect(dataItem.creativeId).to.equal('2');
+ expect(dataItem.netRevenue).to.be.true;
+ expect(dataItem.currency).to.equal('USD');
+ expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains');
+ });
+ it('Should interpret native response', function () {
+ const native = {
+ body: [{
+ mediaType: 'native',
+ native: {
+ clickUrl: 'test.com',
+ title: 'Test',
+ image: 'test.com',
+ impressionTrackers: ['test.com'],
+ },
+ ttl: 120,
+ cpm: 0.4,
+ requestId: '23fhj33i987f',
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ meta: {
+ advertiserDomains: ['google.com'],
+ advertiserId: 1234
+ }
+ }]
+ };
+ let nativeResponses = spec.interpretResponse(native);
+ expect(nativeResponses).to.be.an('array').that.is.not.empty;
+
+ let dataItem = nativeResponses[0];
+ expect(dataItem).to.have.keys('requestId', 'cpm', 'ttl', 'creativeId', 'netRevenue', 'currency', 'mediaType', 'native', 'meta');
+ expect(dataItem.native).to.have.keys('clickUrl', 'impressionTrackers', 'title', 'image')
+ expect(dataItem.requestId).to.equal('23fhj33i987f');
+ expect(dataItem.cpm).to.equal(0.4);
+ expect(dataItem.native.clickUrl).to.equal('test.com');
+ expect(dataItem.native.title).to.equal('Test');
+ expect(dataItem.native.image).to.equal('test.com');
+ expect(dataItem.native.impressionTrackers).to.be.an('array').that.is.not.empty;
+ expect(dataItem.native.impressionTrackers[0]).to.equal('test.com');
+ expect(dataItem.ttl).to.equal(120);
+ expect(dataItem.creativeId).to.equal('2');
+ expect(dataItem.netRevenue).to.be.true;
+ expect(dataItem.currency).to.equal('USD');
+ expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains');
+ });
+ it('Should return an empty array if invalid banner response is passed', function () {
+ const invBanner = {
+ body: [{
+ width: 300,
+ cpm: 0.4,
+ ad: 'Test',
+ requestId: '23fhj33i987f',
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1'
+ }]
+ };
+
+ let serverResponses = spec.interpretResponse(invBanner);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ it('Should return an empty array if invalid video response is passed', function () {
+ const invVideo = {
+ body: [{
+ mediaType: 'video',
+ cpm: 0.5,
+ requestId: '23fhj33i987f',
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1'
+ }]
+ };
+ let serverResponses = spec.interpretResponse(invVideo);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ it('Should return an empty array if invalid native response is passed', function () {
+ const invNative = {
+ body: [{
+ mediaType: 'native',
+ clickUrl: 'test.com',
+ title: 'Test',
+ impressionTrackers: ['test.com'],
+ ttl: 120,
+ requestId: '23fhj33i987f',
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ }]
+ };
+ let serverResponses = spec.interpretResponse(invNative);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ it('Should return an empty array if invalid response is passed', function () {
+ const invalid = {
+ body: [{
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1'
+ }]
+ };
+ let serverResponses = spec.interpretResponse(invalid);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ });
+});
diff --git a/test/spec/modules/eids_spec.js b/test/spec/modules/eids_spec.js
index 1597790e652..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'}
@@ -304,6 +337,72 @@ describe('eids array generation for known sub-modules', function() {
});
});
+ it('openx', function () {
+ const userId = {
+ openx: { 'id': 'sample_id' }
+ };
+ const newEids = createEidsArray(userId);
+ expect(newEids.length).to.equal(1);
+ expect(newEids[0]).to.deep.equal({
+ source: 'openx.net',
+ uids: [{
+ id: 'sample_id',
+ atype: 3
+ }]
+ });
+ });
+
+ it('openx with ext', function () {
+ const userId = {
+ openx: { '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: 'openx.net',
+ uids: [{
+ id: 'sample_id',
+ atype: 3,
+ ext: {
+ provider: 'some.provider.com'
+ }
+ }]
+ });
+ });
+
+ it('pubmatic', function() {
+ const userId = {
+ pubmatic: {'id': 'sample_id'}
+ };
+ const newEids = createEidsArray(userId);
+ expect(newEids.length).to.equal(1);
+ expect(newEids[0]).to.deep.equal({
+ source: 'pubmatic.com',
+ uids: [{
+ id: 'sample_id',
+ atype: 3
+ }]
+ });
+ });
+
+ it('pubmatic with ext', function() {
+ const userId = {
+ pubmatic: {'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: 'pubmatic.com',
+ uids: [{
+ id: 'sample_id',
+ atype: 3,
+ ext: {
+ provider: 'some.provider.com'
+ }
+ }]
+ });
+ });
+
it('liveIntentId; getValue call and NO ext', function() {
const userId = {
lipb: {
diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js
index 1a6cfd7afe4..a381d7644a1 100644
--- a/test/spec/modules/eplanningBidAdapter_spec.js
+++ b/test/spec/modules/eplanningBidAdapter_spec.js
@@ -74,6 +74,53 @@ describe('E-Planning Adapter', function () {
},
'sizes': [[300, 250], [300, 600]],
};
+ const validBidSpaceNameWithBidFloor = {
+ bidder: 'eplanning',
+ 'bidId': BID_ID,
+ params: {
+ 'ci': CI,
+ 'sn': SN,
+ },
+ getFloor: () => ({ currency: 'USD', floor: 1.16 }),
+ 'sizes': [[300, 250], [300, 600]],
+ };
+ const validBidSpaceOutstreamWithBidFloor = {
+ 'bidder': 'eplanning',
+ 'bidId': BID_ID,
+ 'params': {
+ 'ci': CI,
+ 'sn': SN,
+ },
+ getFloor: () => ({ currency: 'USD', floor: 1.16 }),
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'outstream',
+ 'playerSize': [300, 600],
+ 'mimes': ['video/mp4'],
+ 'protocols': [1, 2, 3, 4, 5, 6],
+ 'playbackmethod': [2],
+ 'skip': 1
+ }
+ },
+ };
+ const validBidSpaceInstreamWithBidFloor = {
+ 'bidder': 'eplanning',
+ 'bidId': BID_ID,
+ 'params': {
+ 'ci': CI,
+ 'sn': SN,
+ },
+ getFloor: () => ({ currency: 'USD', floor: 1.16 }),
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'instream',
+ 'mimes': ['video/mp4'],
+ 'protocols': [1, 2, 3, 4, 5, 6],
+ 'playbackmethod': [2],
+ 'skip': 1
+ }
+ },
+ };
const validBidSpaceOutstream = {
'bidder': 'eplanning',
'bidId': BID_ID,
@@ -573,6 +620,26 @@ describe('E-Planning Adapter', function () {
expect(e).to.equal(SN + ':300x250,300x600');
});
+ it('should return e parameter with space name attribute with value according to the adunit sizes and bidFloor', function () {
+ const e = spec.buildRequests([validBidSpaceNameWithBidFloor], bidderRequest).data.e;
+ expect(e).to.equal(SN + ':300x250,300x600|' + validBidSpaceNameWithBidFloor.getFloor().floor);
+ });
+
+ it('should return correct e parameter with support vast with one space with size outstream and bidFloor', function () {
+ const data = spec.buildRequests([validBidSpaceOutstreamWithBidFloor], bidderRequest).data;
+ expect(data.e).to.equal('video_300x600_0:300x600;1|' + validBidSpaceOutstreamWithBidFloor.getFloor().floor);
+ expect(data.vctx).to.equal(2);
+ expect(data.vv).to.equal(3);
+ });
+
+ it('should return correct e parameter with support vast with one space with size instream with bidFloor', function () {
+ let bidRequests = [validBidSpaceInstreamWithBidFloor];
+ const data = spec.buildRequests(bidRequests, bidderRequest).data;
+ expect(data.e).to.equal('video_640x480_0:640x480;1|' + validBidSpaceInstreamWithBidFloor.getFloor().floor);
+ expect(data.vctx).to.equal(1);
+ expect(data.vv).to.equal(3);
+ });
+
it('should return correct e parameter with more than one adunit', function () {
const NEW_CODE = ADUNIT_CODE + '2';
const CLEAN_NEW_CODE = CLEAN_ADUNIT_CODE + '2';
diff --git a/test/spec/modules/euidIdSystem_spec.js b/test/spec/modules/euidIdSystem_spec.js
index 4f6bacebe6a..98770fa80bc 100644
--- a/test/spec/modules/euidIdSystem_spec.js
+++ b/test/spec/modules/euidIdSystem_spec.js
@@ -3,9 +3,11 @@ 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';
+import {server} from 'test/mocks/xhr';
let expect = require('chai').expect;
@@ -21,21 +23,26 @@ 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');
describe('EUID module', function() {
- let suiteSandbox, testSandbox, timerSpy, fullTestTitle, restoreSubtleToUndefined = false;
- let server;
+ 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,22 +50,28 @@ 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();
if (restoreSubtleToUndefined) window.crypto.subtle = undefined;
});
beforeEach(function() {
- server = sinon.createFakeServer();
init(config);
setSubmoduleRegistry([euidIdSubmodule]);
});
afterEach(function() {
- server.restore();
$$PREBID_GLOBAL$$.requestBids.removeAll();
config.resetConfig();
cookieHelpers.clearCookies(moduleCookieName, publisherCookieName);
@@ -115,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/experianRtdProvider_spec.js b/test/spec/modules/experianRtdProvider_spec.js
new file mode 100644
index 00000000000..fd104674d70
--- /dev/null
+++ b/test/spec/modules/experianRtdProvider_spec.js
@@ -0,0 +1,365 @@
+import {
+ EXPERIAN_RTID_DATA_KEY,
+ EXPERIAN_RTID_EXPIRATION_KEY,
+ EXPERIAN_RTID_STALE_KEY,
+ SUBMODULE_NAME,
+ experianRtdObj,
+ experianRtdSubmodule, EXPERIAN_RTID_NO_TRACK_KEY
+} from '../../../modules/experianRtdProvider.js';
+import { getStorageManager } from '../../../src/storageManager.js';
+import { MODULE_TYPE_RTD } from '../../../src/activities/modules';
+import { safeJSONParse, timestamp } from '../../../src/utils';
+import {server} from '../../mocks/xhr.js';
+
+describe('Experian realtime module', () => {
+ const sandbox = sinon.createSandbox();
+ let requests;
+
+ const storage = getStorageManager({ moduleType: MODULE_TYPE_RTD, moduleName: SUBMODULE_NAME })
+ beforeEach(() => {
+ requests = server.requests;
+ storage.removeDataFromLocalStorage(EXPERIAN_RTID_DATA_KEY, null)
+ storage.removeDataFromLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY, null)
+ storage.removeDataFromLocalStorage(EXPERIAN_RTID_STALE_KEY, null)
+ storage.removeDataFromLocalStorage(EXPERIAN_RTID_NO_TRACK_KEY, null)
+ })
+ afterEach(() => {
+ sandbox.restore();
+ })
+ // Bid request config
+ const reqBidsConfigObj = {
+ adUnits: [{
+ bids: [
+ { bidder: 'appnexus' }
+ ]
+ }]
+ };
+ describe('init', () => {
+ it('succeeds when params have accountId', () => {
+ const initResult = experianRtdSubmodule.init({ params: { accountId: 'ZylatYg' } })
+ expect(initResult).to.be.true;
+ })
+
+ it('fails when params don\'t have accountId', () => {
+ const initResult = experianRtdSubmodule.init({ })
+ expect(initResult).to.be.false;
+ })
+ })
+
+ describe('getBidRequestData', () => {
+ describe('when local storage has data, isn\'t no track, isn\'t stale and isn\'t expired', () => {
+ beforeEach(() => {
+ const now = timestamp()
+ storage.setDataInLocalStorage(EXPERIAN_RTID_DATA_KEY, JSON.stringify([
+ {
+ bidder: 'pubmatic',
+ data: {
+ key: 'pubmatic-encryption-key-1',
+ data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }
+ },
+ {
+ bidder: 'sovrn',
+ data: {
+ key: 'sovrn-encryption-key-1',
+ data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }
+ }
+ ]), null)
+
+ storage.setDataInLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY, new Date(now + 100000).toISOString(), null)
+ storage.setDataInLocalStorage(EXPERIAN_RTID_STALE_KEY, new Date(now + 50000).toISOString(), null)
+ })
+ it('doesn\'t request data envelope, and alters bids', () => {
+ const bidsConfig = {
+ ortb2Fragments: {
+ bidder: {}
+ }
+ }
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic', 'sovrn'] } }
+ const dataEnvelopeSpy = sandbox.spy(experianRtdObj, 'requestDataEnvelope')
+ const alterBidsSpy = sandbox.spy(experianRtdObj, 'alterBids')
+ experianRtdSubmodule.getBidRequestData(bidsConfig, sinon.stub, moduleConfig)
+ sandbox.assert.calledWithExactly(alterBidsSpy, bidsConfig, moduleConfig)
+ expect(dataEnvelopeSpy.called).to.be.false;
+ })
+ })
+
+ describe('when local storage has data but it is stale', () => {
+ beforeEach(() => {
+ const now = timestamp()
+ storage.setDataInLocalStorage(EXPERIAN_RTID_DATA_KEY, JSON.stringify([
+ {
+ bidder: 'pubmatic',
+ data: {
+ key: 'pubmatic-encryption-key-1',
+ data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }
+ },
+ {
+ bidder: 'sovrn',
+ data: {
+ key: 'sovrn-encryption-key-1',
+ data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }
+ }
+ ]), null)
+
+ storage.setDataInLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY, new Date(now + 100000).toISOString(), null)
+ storage.setDataInLocalStorage(EXPERIAN_RTID_STALE_KEY, new Date(now - 50000).toISOString(), null)
+ })
+ it('it requests data envelope and alters bids', () => {
+ const bidsConfig = {
+ ortb2Fragments: {
+ bidder: {}
+ }
+ }
+ const userConsent = {gdpr: {}, uspConsent: {}}
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic', 'sovrn'] } }
+ const dataEnvelopeSpy = sandbox.spy(experianRtdObj, 'requestDataEnvelope')
+ const alterBidsSpy = sandbox.spy(experianRtdObj, 'alterBids')
+ experianRtdSubmodule.getBidRequestData(bidsConfig, sinon.stub, moduleConfig, userConsent)
+ sandbox.assert.calledWithExactly(alterBidsSpy, bidsConfig, moduleConfig)
+ sandbox.assert.calledWithExactly(dataEnvelopeSpy, moduleConfig, userConsent)
+ })
+ })
+ describe('when local storage has data but it is expired', () => {
+ beforeEach(() => {
+ const now = timestamp()
+ storage.setDataInLocalStorage(EXPERIAN_RTID_DATA_KEY, JSON.stringify([
+ {
+ bidder: 'pubmatic',
+ data: {
+ key: 'pubmatic-encryption-key-1',
+ data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }
+ },
+ {
+ bidder: 'sovrn',
+ data: {
+ key: 'sovrn-encryption-key-1',
+ data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }
+ }
+ ]), null)
+
+ storage.setDataInLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY, new Date(now - 50000).toISOString(), null)
+ storage.setDataInLocalStorage(EXPERIAN_RTID_STALE_KEY, new Date(now - 100000).toISOString(), null)
+ })
+ it('requests data envelope, and doesn\'t alter bids', () => {
+ const bidsConfig = {
+ ortb2Fragments: {
+ bidder: {}
+ }
+ }
+ const userConsent = {gdpr: {}, uspConsent: {}}
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic', 'sovrn'] } }
+ const dataEnvelopeSpy = sandbox.spy(experianRtdObj, 'requestDataEnvelope')
+ const alterBidsSpy = sandbox.spy(experianRtdObj, 'alterBids')
+ experianRtdSubmodule.getBidRequestData(bidsConfig, sinon.stub, moduleConfig, userConsent)
+ sandbox.assert.calledWithExactly(dataEnvelopeSpy, moduleConfig, userConsent)
+ expect(alterBidsSpy.called).to.be.false;
+ })
+ })
+ describe('when local storage has no data envelope', () => {
+ it('requests data envelope, and doesn\'t alter bids', () => {
+ const bidsConfig = {
+ ortb2Fragments: {
+ bidder: {}
+ }
+ }
+ const userConsent = {gdpr: {}, uspConsent: {}}
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic', 'sovrn'] } }
+ const dataEnvelopeSpy = sandbox.spy(experianRtdObj, 'requestDataEnvelope')
+ const alterBidsSpy = sandbox.spy(experianRtdObj, 'alterBids')
+ experianRtdSubmodule.getBidRequestData(bidsConfig, sinon.stub, moduleConfig, userConsent)
+ sandbox.assert.calledWithExactly(dataEnvelopeSpy, moduleConfig, userConsent)
+ expect(alterBidsSpy.called).to.be.false;
+ })
+ })
+ describe('when local storage has no track and is expired', () => {
+ beforeEach(() => {
+ const now = timestamp()
+ storage.setDataInLocalStorage(EXPERIAN_RTID_NO_TRACK_KEY, 'no_track', null)
+
+ storage.setDataInLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY, new Date(now - 50000).toISOString(), null)
+ storage.setDataInLocalStorage(EXPERIAN_RTID_STALE_KEY, new Date(now - 100000).toISOString(), null)
+ })
+ it('requests data envelope, and doesn\'t alter bids', () => {
+ const bidsConfig = {
+ ortb2Fragments: {
+ bidder: {}
+ }
+ }
+ const userConsent = {gdpr: {}, uspConsent: {}}
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic', 'sovrn'] } }
+ const dataEnvelopeSpy = sandbox.spy(experianRtdObj, 'requestDataEnvelope')
+ const alterBidsSpy = sandbox.spy(experianRtdObj, 'alterBids')
+ experianRtdSubmodule.getBidRequestData(bidsConfig, sinon.stub, moduleConfig, userConsent)
+ sandbox.assert.calledWithExactly(dataEnvelopeSpy, moduleConfig, userConsent)
+ expect(alterBidsSpy.called).to.be.false;
+ })
+ })
+
+ describe('when local storage has no track and is stale', () => {
+ beforeEach(() => {
+ const now = timestamp()
+ storage.setDataInLocalStorage(EXPERIAN_RTID_NO_TRACK_KEY, 'no_track', null)
+
+ storage.setDataInLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY, new Date(now + 100000).toISOString(), null)
+ storage.setDataInLocalStorage(EXPERIAN_RTID_STALE_KEY, new Date(now - 50000).toISOString(), null)
+ })
+ it('requests data envelope, and doesn\'t alter bids', () => {
+ const bidsConfig = {
+ ortb2Fragments: {
+ bidder: {}
+ }
+ }
+ const userConsent = {gdpr: {}, uspConsent: {}}
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic', 'sovrn'] } }
+ const dataEnvelopeSpy = sandbox.spy(experianRtdObj, 'requestDataEnvelope')
+ const alterBidsSpy = sandbox.spy(experianRtdObj, 'alterBids')
+ experianRtdSubmodule.getBidRequestData(bidsConfig, sinon.stub, moduleConfig, userConsent)
+ sandbox.assert.calledWithExactly(dataEnvelopeSpy, moduleConfig, userConsent)
+ expect(alterBidsSpy.called).to.be.false;
+ })
+ })
+
+ describe('when local storage has no track and isn\'t expired or stale', () => {
+ beforeEach(() => {
+ const now = timestamp()
+ storage.setDataInLocalStorage(EXPERIAN_RTID_NO_TRACK_KEY, 'no_track', null)
+
+ storage.setDataInLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY, new Date(now + 100000).toISOString(), null)
+ storage.setDataInLocalStorage(EXPERIAN_RTID_STALE_KEY, new Date(now + 50000).toISOString(), null)
+ })
+ it('doesn\'t alter bids and doesn\'t request data envelope', () => {
+ const bidsConfig = {
+ ortb2Fragments: {
+ bidder: {}
+ }
+ }
+ const userConsent = {gdpr: {}, uspConsent: {}}
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic', 'sovrn'] } }
+ const dataEnvelopeSpy = sandbox.spy(experianRtdObj, 'requestDataEnvelope')
+ const alterBidsSpy = sandbox.spy(experianRtdObj, 'alterBids')
+ experianRtdSubmodule.getBidRequestData(bidsConfig, sinon.stub, moduleConfig, userConsent)
+ expect(alterBidsSpy.called).to.be.false;
+ expect(dataEnvelopeSpy.called).to.be.false;
+ })
+ })
+ })
+
+ describe('alterBids', () => {
+ describe('data envelope has every bidder from config', () => {
+ beforeEach(() => {
+ const now = timestamp()
+ storage.setDataInLocalStorage(EXPERIAN_RTID_DATA_KEY, JSON.stringify([
+ {
+ bidder: 'pubmatic',
+ data: {
+ key: 'pubmatic-encryption-key-1',
+ data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }
+ },
+ {
+ bidder: 'sovrn',
+ data: {
+ key: 'sovrn-encryption-key-1',
+ data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }
+ }
+ ]), null)
+
+ storage.setDataInLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY, new Date(now + 100000).toISOString(), null)
+ storage.setDataInLocalStorage(EXPERIAN_RTID_STALE_KEY, new Date(now + 50000).toISOString(), null)
+ })
+
+ it('alters bids for the bidders in the module config', () => {
+ const bidsConfig = {
+ ortb2Fragments: {
+ bidder: {}
+ }
+ }
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic'] } }
+ experianRtdObj.alterBids(bidsConfig, moduleConfig);
+ expect(bidsConfig.ortb2Fragments.bidder).to.deep.equal({pubmatic: {
+ experianRtidKey: 'pubmatic-encryption-key-1',
+ experianRtidData: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }})
+ })
+ })
+ describe('data envelope is missing bidders from config', () => {
+ beforeEach(() => {
+ const now = timestamp()
+ storage.setDataInLocalStorage(EXPERIAN_RTID_DATA_KEY, JSON.stringify([
+ {
+ bidder: 'sovrn',
+ data: {
+ key: 'sovrn-encryption-key-1',
+ data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }
+ }
+ ]), null)
+
+ storage.setDataInLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY, new Date(now + 100000).toISOString(), null)
+ storage.setDataInLocalStorage(EXPERIAN_RTID_STALE_KEY, new Date(now + 50000).toISOString(), null)
+ })
+
+ it('alters bids for the bidders in the module config', () => {
+ const bidsConfig = {
+ ortb2Fragments: {
+ bidder: {}
+ }
+ }
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic', 'sovrn'] } }
+ experianRtdObj.alterBids(bidsConfig, moduleConfig);
+ expect(bidsConfig.ortb2Fragments.bidder).to.deep.equal({
+ sovrn: {
+ experianRtidKey: 'sovrn-encryption-key-1',
+ experianRtidData: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='
+ }})
+ })
+ })
+ })
+
+ describe('requestDataEnvelope', () => {
+ it('sends request to experian rtd and stores response', () => {
+ const moduleConfig = { params: { accountId: 'ZylatYg', bidders: ['pubmatic', 'sovrn'] } }
+ experianRtdObj.requestDataEnvelope(moduleConfig, { gdpr: { gdprApplies: 0, consentString: 'wow' }, uspConsent: '1YYY' })
+ requests[0].respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{"staleAt":"2023-06-01T00:00:00","expiresAt":"2023-06-03T00:00:00","status":"ok","data":[{"bidder":"pubmatic","data":{"key":"pubmatic-encryption-key-1","data":"IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=="}},{"bidder":"sovrn","data":{"key":"sovrn-encryption-key-1","data":"IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=="}}]}'
+ )
+
+ expect(requests[0].url).to.equal('https://rtid.tapad.com/acc/ZylatYg/ids?gdpr=0&gdpr_consent=wow&us_privacy=1YYY')
+ expect(safeJSONParse(storage.getDataFromLocalStorage(EXPERIAN_RTID_DATA_KEY, null))).to.deep.equal([{bidder: 'pubmatic', data: {key: 'pubmatic-encryption-key-1', data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='}}, {bidder: 'sovrn', data: {key: 'sovrn-encryption-key-1', data: 'IkhlbGxvLCB3b3JsZC4gSGVsbG8sIHdvcmxkLiBIZWxsbywgd29ybGQuIg=='}}])
+ expect(storage.getDataFromLocalStorage(EXPERIAN_RTID_STALE_KEY)).to.equal('2023-06-01T00:00:00')
+ expect(storage.getDataFromLocalStorage(EXPERIAN_RTID_EXPIRATION_KEY)).to.equal('2023-06-03T00:00:00')
+ })
+ })
+
+ describe('extractConsentQueryString', () => {
+ describe('when userConsent is empty', () => {
+ it('returns undefined', () => {
+ expect(experianRtdObj.extractConsentQueryString({})).to.be.undefined
+ })
+ })
+
+ describe('when userConsent exists', () => {
+ it('builds query string', () => {
+ expect(
+ experianRtdObj.extractConsentQueryString({}, { gdpr: { gdprApplies: 1, consentString: 'this-is-something' }, uspConsent: '1YYY' })
+ ).to.equal('?gdpr=1&gdpr_consent=this-is-something&us_privacy=1YYY')
+ })
+ })
+
+ describe('when config.ids exists', () => {
+ it('builds query string', () => {
+ expect(experianRtdObj.extractConsentQueryString({ params: { accountId: 'ZylatYg', ids: { maid: ['424', '2982'], hem: 'my-hem' } } }, { gdpr: { gdprApplies: 1, consentString: 'this-is-something' }, uspConsent: '1YYY' }))
+ .to.equal('?gdpr=1&gdpr_consent=this-is-something&us_privacy=1YYY&id.maid=424&id.maid=2982&id.hem=my-hem')
+ })
+ })
+ })
+})
diff --git a/test/spec/modules/fledgeForGpt_spec.js b/test/spec/modules/fledgeForGpt_spec.js
new file mode 100644
index 00000000000..60a8e196ae0
--- /dev/null
+++ b/test/spec/modules/fledgeForGpt_spec.js
@@ -0,0 +1,419 @@
+import {
+ expect
+} from 'chai';
+import * as fledge from 'modules/fledgeForGpt.js';
+import {config} from '../../../src/config.js';
+import adapterManager from '../../../src/adapterManager.js';
+import * as utils from '../../../src/utils.js';
+import * as gptUtils from '../../../libraries/gptUtils/gptUtils.js';
+import {hook} from '../../../src/hook.js';
+import 'modules/appnexusBidAdapter.js';
+import 'modules/rubiconBidAdapter.js';
+import {parseExtPrebidFledge, setImpExtAe, setResponseFledgeConfigs} from 'modules/fledgeForGpt.js';
+import * as events from 'src/events.js';
+import CONSTANTS from 'src/constants.json';
+import {getGlobal} from '../../../src/prebidGlobal.js';
+
+describe('fledgeForGpt module', () => {
+ let sandbox;
+
+ beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+ });
+ afterEach(() => {
+ sandbox.restore();
+ });
+ describe('addComponentAuction', function () {
+ before(() => {
+ fledge.init({enabled: true});
+ });
+
+ const fledgeAuctionConfig = {
+ seller: 'bidder',
+ mock: 'config'
+ };
+
+ describe('addComponentAuctionHook', function () {
+ let nextFnSpy, mockGptSlot;
+ beforeEach(function () {
+ nextFnSpy = sinon.spy();
+ mockGptSlot = {
+ setConfig: sinon.stub(),
+ getAdUnitPath: () => 'mock/gpt/au'
+ };
+ sandbox.stub(gptUtils, 'getGptSlotForAdUnitCode').callsFake(() => mockGptSlot);
+ });
+
+ it('should call next()', function () {
+ const request = {auctionId: 'aid', adUnitCode: 'auc'};
+ fledge.addComponentAuctionHook(nextFnSpy, request, fledgeAuctionConfig);
+ sinon.assert.calledWith(nextFnSpy, request, fledgeAuctionConfig);
+ });
+
+ it('should collect auction configs and route them to GPT at end of auction', () => {
+ events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 'aid'});
+ const cf1 = {...fledgeAuctionConfig, id: 1, seller: 'b1'};
+ const cf2 = {...fledgeAuctionConfig, id: 2, seller: 'b2'};
+ fledge.addComponentAuctionHook(nextFnSpy, {auctionId: 'aid', adUnitCode: 'au1'}, cf1);
+ fledge.addComponentAuctionHook(nextFnSpy, {auctionId: 'aid', adUnitCode: 'au2'}, cf2);
+ events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: 'aid'});
+ sinon.assert.calledWith(gptUtils.getGptSlotForAdUnitCode, 'au1');
+ sinon.assert.calledWith(gptUtils.getGptSlotForAdUnitCode, 'au2');
+ sinon.assert.calledWith(mockGptSlot.setConfig, {
+ componentAuction: [{
+ configKey: 'b1',
+ auctionConfig: cf1,
+ }]
+ });
+ sinon.assert.calledWith(mockGptSlot.setConfig, {
+ componentAuction: [{
+ configKey: 'b2',
+ auctionConfig: cf2,
+ }]
+ });
+ });
+
+ it('should drop auction configs after end of auction', () => {
+ events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 'aid'});
+ events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: 'aid'});
+ fledge.addComponentAuctionHook(nextFnSpy, {auctionId: 'aid', adUnitCode: 'au'}, fledgeAuctionConfig);
+ events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: 'aid'});
+ sinon.assert.notCalled(mockGptSlot.setConfig);
+ });
+
+ it('should augment auctionSignals with FPD', () => {
+ events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 'aid'});
+ fledge.addComponentAuctionHook(nextFnSpy, {auctionId: 'aid', adUnitCode: 'au1', ortb2: {fpd: 1}, ortb2Imp: {fpd: 2}}, fledgeAuctionConfig);
+ events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: 'aid'});
+ sinon.assert.calledWith(mockGptSlot.setConfig, {
+ componentAuction: [{
+ configKey: 'bidder',
+ auctionConfig: {
+ ...fledgeAuctionConfig,
+ auctionSignals: {
+ prebid: {
+ ortb2: {fpd: 1},
+ ortb2Imp: {fpd: 2}
+ }
+ }
+ },
+ }]
+ })
+ })
+
+ describe('floor signal', () => {
+ before(() => {
+ if (!getGlobal().convertCurrency) {
+ getGlobal().convertCurrency = () => null;
+ getGlobal().convertCurrency.mock = true;
+ }
+ });
+ after(() => {
+ if (getGlobal().convertCurrency.mock) {
+ delete getGlobal().convertCurrency;
+ }
+ });
+
+ beforeEach(() => {
+ sandbox.stub(getGlobal(), 'convertCurrency').callsFake((amount, from, to) => {
+ if (from === to) return amount;
+ if (from === 'USD' && to === 'JPY') return amount * 100;
+ if (from === 'JPY' && to === 'USD') return amount / 100;
+ throw new Error('unexpected currency conversion');
+ });
+ });
+
+ Object.entries({
+ 'bids': (payload, values) => {
+ payload.bidsReceived = values
+ .map((val) => ({adUnitCode: 'au', cpm: val.amount, currency: val.cur}))
+ .concat([{adUnitCode: 'other', cpm: 10000, currency: 'EUR'}])
+ },
+ 'no bids': (payload, values) => {
+ payload.bidderRequests = values
+ .map((val) => ({bids: [{adUnitCode: 'au', getFloor: () => ({floor: val.amount, currency: val.cur})}]}))
+ .concat([{bids: {adUnitCode: 'other', getFloor: () => ({floor: -10000, currency: 'EUR'})}}])
+ }
+ }).forEach(([tcase, setup]) => {
+ describe(`when auction has ${tcase}`, () => {
+ Object.entries({
+ 'no currencies': {
+ values: [{amount: 1}, {amount: 100}, {amount: 10}, {amount: 100}],
+ 'bids': {
+ bidfloor: 100,
+ bidfloorcur: undefined
+ },
+ 'no bids': {
+ bidfloor: 1,
+ bidfloorcur: undefined,
+ }
+ },
+ 'only zero values': {
+ values: [{amount: 0, cur: 'USD'}, {amount: 0, cur: 'JPY'}],
+ 'bids': {
+ bidfloor: undefined,
+ bidfloorcur: undefined,
+ },
+ 'no bids': {
+ bidfloor: undefined,
+ bidfloorcur: undefined,
+ }
+ },
+ 'matching currencies': {
+ values: [{amount: 10, cur: 'JPY'}, {amount: 100, cur: 'JPY'}],
+ 'bids': {
+ bidfloor: 100,
+ bidfloorcur: 'JPY',
+ },
+ 'no bids': {
+ bidfloor: 10,
+ bidfloorcur: 'JPY',
+ }
+ },
+ 'mixed currencies': {
+ values: [{amount: 10, cur: 'USD'}, {amount: 10, cur: 'JPY'}],
+ 'bids': {
+ bidfloor: 10,
+ bidfloorcur: 'USD'
+ },
+ 'no bids': {
+ bidfloor: 10,
+ bidfloorcur: 'JPY',
+ }
+ }
+ }).forEach(([t, testConfig]) => {
+ const values = testConfig.values;
+ const {bidfloor, bidfloorcur} = testConfig[tcase];
+
+ describe(`with ${t}`, () => {
+ let payload;
+ beforeEach(() => {
+ payload = {auctionId: 'aid'};
+ setup(payload, values);
+ });
+
+ it('should populate bidfloor/bidfloorcur', () => {
+ events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {auctionId: 'aid'});
+ fledge.addComponentAuctionHook(nextFnSpy, {auctionId: 'aid', adUnitCode: 'au'}, fledgeAuctionConfig);
+ events.emit(CONSTANTS.EVENTS.AUCTION_END, payload);
+ sinon.assert.calledWith(mockGptSlot.setConfig, sinon.match(arg => {
+ return arg.componentAuction.some(au => au.auctionConfig.auctionSignals?.prebid?.bidfloor === bidfloor && au.auctionConfig.auctionSignals?.prebid?.bidfloorcur === bidfloorcur)
+ }))
+ })
+ });
+ });
+ })
+ })
+ });
+ });
+ });
+
+ describe('fledgeEnabled', function () {
+ const navProps = Object.fromEntries(['runAdAuction', 'joinAdInterestGroup'].map(p => [p, navigator[p]]));
+
+ before(function () {
+ // navigator.runAdAuction & co may not exist, so we can't stub it normally with
+ // sinon.stub(navigator, 'runAdAuction') or something
+ Object.keys(navProps).forEach(p => {
+ navigator[p] = sinon.stub();
+ });
+ hook.ready();
+ });
+
+ after(function () {
+ Object.entries(navProps).forEach(([p, orig]) => navigator[p] = orig);
+ });
+
+ afterEach(function () {
+ config.resetConfig();
+ });
+
+ const adUnits = [{
+ 'code': '/19968336/header-bid-tag1',
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [[728, 90]]
+ },
+ },
+ 'bids': [
+ {
+ 'bidder': 'appnexus',
+ },
+ {
+ 'bidder': 'rubicon',
+ },
+ ]
+ }];
+ function expectFledgeFlags(...enableFlags) {
+ const bidRequests = adapterManager.makeBidRequests(
+ adUnits,
+ Date.now(),
+ utils.getUniqueIdentifierStr(),
+ function callback() {
+ },
+ []
+ );
+
+ expect(bidRequests[0].bids[0].bidder).equals('appnexus');
+ expect(bidRequests[0].fledgeEnabled).to.eql(enableFlags[0].enabled)
+ bidRequests[0].bids.forEach(bid => expect(bid.ortb2Imp.ext.ae).to.eql(enableFlags[0].ae))
+
+ expect(bidRequests[1].bids[0].bidder).equals('rubicon');
+ expect(bidRequests[1].fledgeEnabled).to.eql(enableFlags[1].enabled)
+ bidRequests[1].bids.forEach(bid => expect(bid.ortb2Imp?.ext?.ae).to.eql(enableFlags[1].ae));
+ }
+
+ describe('with setBidderConfig()', () => {
+ it('should set fledgeEnabled correctly per bidder', function () {
+ config.setConfig({bidderSequence: 'fixed'});
+ config.setBidderConfig({
+ bidders: ['appnexus'],
+ config: {
+ fledgeEnabled: true,
+ defaultForSlots: 1,
+ }
+ });
+ expectFledgeFlags({enabled: true, ae: 1}, {enabled: void 0, ae: void 0});
+ });
+ });
+
+ describe('with setConfig()', () => {
+ it('should set fledgeEnabled correctly per bidder', function () {
+ config.setConfig({
+ bidderSequence: 'fixed',
+ fledgeForGpt: {
+ enabled: true,
+ bidders: ['appnexus'],
+ defaultForSlots: 1,
+ }
+ });
+ expectFledgeFlags({enabled: true, ae: 1}, {enabled: void 0, ae: void 0});
+ });
+
+ it('should set fledgeEnabled correctly for all bidders', function () {
+ config.setConfig({
+ bidderSequence: 'fixed',
+ fledgeForGpt: {
+ enabled: true,
+ defaultForSlots: 1,
+ }
+ });
+ expectFledgeFlags({enabled: true, ae: 1}, {enabled: true, ae: 1});
+ });
+
+ it('should not override pub-defined ext.ae', () => {
+ config.setConfig({
+ bidderSequence: 'fixed',
+ fledgeForGpt: {
+ enabled: true,
+ defaultForSlots: 1,
+ }
+ });
+ Object.assign(adUnits[0], {ortb2Imp: {ext: {ae: 0}}});
+ expectFledgeFlags({enabled: true, ae: 0}, {enabled: true, ae: 0});
+ })
+ });
+ });
+
+ describe('ortb processors for fledge', () => {
+ it('imp.ext.ae should be removed if fledge is not enabled', () => {
+ const imp = {ext: {ae: 1}};
+ setImpExtAe(imp, {}, {bidderRequest: {}});
+ expect(imp.ext.ae).to.not.exist;
+ });
+ it('imp.ext.ae should be left intact if fledge is enabled', () => {
+ const imp = {ext: {ae: 2}};
+ setImpExtAe(imp, {}, {bidderRequest: {fledgeEnabled: true}});
+ expect(imp.ext.ae).to.equal(2);
+ });
+ describe('parseExtPrebidFledge', () => {
+ function packageConfigs(configs) {
+ return {
+ ext: {
+ prebid: {
+ fledge: {
+ auctionconfigs: configs
+ }
+ }
+ }
+ };
+ }
+
+ function generateImpCtx(fledgeFlags) {
+ return Object.fromEntries(Object.entries(fledgeFlags).map(([impid, fledgeEnabled]) => [impid, {imp: {ext: {ae: fledgeEnabled}}}]));
+ }
+
+ function generateCfg(impid, ...ids) {
+ return ids.map((id) => ({impid, config: {id}}));
+ }
+
+ function extractResult(ctx) {
+ return Object.fromEntries(
+ Object.entries(ctx)
+ .map(([impid, ctx]) => [impid, ctx.fledgeConfigs?.map(cfg => cfg.config.id)])
+ .filter(([_, val]) => val != null)
+ );
+ }
+
+ it('should collect fledge configs by imp', () => {
+ const ctx = {
+ impContext: generateImpCtx({e1: 1, e2: 1, d1: 0})
+ };
+ const resp = packageConfigs(
+ generateCfg('e1', 1, 2, 3)
+ .concat(generateCfg('e2', 4)
+ .concat(generateCfg('d1', 5, 6)))
+ );
+ parseExtPrebidFledge({}, resp, ctx);
+ expect(extractResult(ctx.impContext)).to.eql({
+ e1: [1, 2, 3],
+ e2: [4],
+ });
+ });
+ it('should not choke if fledge config references unknown imp', () => {
+ const ctx = {impContext: generateImpCtx({i: 1})};
+ const resp = packageConfigs(generateCfg('unknown', 1));
+ parseExtPrebidFledge({}, resp, ctx);
+ expect(extractResult(ctx.impContext)).to.eql({});
+ });
+ });
+ describe('setResponseFledgeConfigs', () => {
+ it('should set fledgeAuctionConfigs paired with their corresponding bid id', () => {
+ const ctx = {
+ impContext: {
+ 1: {
+ bidRequest: {bidId: 'bid1'},
+ fledgeConfigs: [{config: {id: 1}}, {config: {id: 2}}]
+ },
+ 2: {
+ bidRequest: {bidId: 'bid2'},
+ fledgeConfigs: [{config: {id: 3}}]
+ },
+ 3: {
+ bidRequest: {bidId: 'bid3'}
+ }
+ }
+ };
+ const resp = {};
+ setResponseFledgeConfigs(resp, {}, ctx);
+ expect(resp.fledgeAuctionConfigs).to.eql([
+ {bidId: 'bid1', config: {id: 1}},
+ {bidId: 'bid1', config: {id: 2}},
+ {bidId: 'bid2', config: {id: 3}},
+ ]);
+ });
+ it('should not set fledgeAuctionConfigs if none exist', () => {
+ const resp = {};
+ setResponseFledgeConfigs(resp, {}, {
+ impContext: {
+ 1: {
+ fledgeConfigs: []
+ },
+ 2: {}
+ }
+ });
+ expect(resp).to.eql({});
+ });
+ });
+ });
+});
diff --git a/test/spec/modules/fledge_spec.js b/test/spec/modules/fledge_spec.js
deleted file mode 100644
index 7a670fa2381..00000000000
--- a/test/spec/modules/fledge_spec.js
+++ /dev/null
@@ -1,282 +0,0 @@
-import {
- expect
-} from 'chai';
-import * as fledge from 'modules/fledgeForGpt.js';
-import {config} from '../../../src/config.js';
-import adapterManager from '../../../src/adapterManager.js';
-import * as utils from '../../../src/utils.js';
-import {hook} from '../../../src/hook.js';
-import 'modules/appnexusBidAdapter.js';
-import 'modules/rubiconBidAdapter.js';
-import {parseExtPrebidFledge, setImpExtAe, setResponseFledgeConfigs} from 'modules/fledgeForGpt.js';
-
-const CODE = 'sampleBidder';
-const AD_UNIT_CODE = 'mock/placement';
-
-describe('fledgeForGpt module', function() {
- let nextFnSpy;
- before(() => {
- fledge.init({enabled: true})
- });
-
- const bidRequest = {
- adUnitCode: AD_UNIT_CODE,
- bids: [{
- bidId: '1',
- bidder: CODE,
- auctionId: 'first-bid-id',
- adUnitCode: AD_UNIT_CODE,
- transactionId: 'au',
- }]
- };
- const fledgeAuctionConfig = {
- bidId: '1',
- }
-
- describe('addComponentAuctionHook', function() {
- beforeEach(function() {
- nextFnSpy = sinon.spy();
- });
-
- it('should call next() when a proper adUnitCode and fledgeAuctionConfig are provided', function() {
- fledge.addComponentAuctionHook(nextFnSpy, bidRequest.adUnitCode, fledgeAuctionConfig);
- expect(nextFnSpy.called).to.be.true;
- });
- });
-});
-
-describe('fledgeEnabled', function () {
- const navProps = Object.fromEntries(['runAdAuction', 'joinAdInterestGroup'].map(p => [p, navigator[p]]))
-
- before(function () {
- // navigator.runAdAuction & co may not exist, so we can't stub it normally with
- // sinon.stub(navigator, 'runAdAuction') or something
- Object.keys(navProps).forEach(p => { navigator[p] = sinon.stub() });
- hook.ready();
- });
-
- after(function() {
- Object.entries(navProps).forEach(([p, orig]) => navigator[p] = orig);
- })
-
- afterEach(function () {
- config.resetConfig();
- });
-
- const adUnits = [{
- 'code': '/19968336/header-bid-tag1',
- 'mediaTypes': {
- 'banner': {
- 'sizes': [[728, 90]]
- },
- },
- 'bids': [
- {
- 'bidder': 'appnexus',
- },
- {
- 'bidder': 'rubicon',
- },
- ]
- }];
-
- describe('with setBidderConfig()', () => {
- it('should set fledgeEnabled correctly per bidder', function () {
- config.setConfig({bidderSequence: 'fixed'})
- config.setBidderConfig({
- bidders: ['appnexus'],
- config: {
- fledgeEnabled: true,
- defaultForSlots: 1,
- }
- });
-
- const bidRequests = adapterManager.makeBidRequests(
- adUnits,
- Date.now(),
- utils.getUniqueIdentifierStr(),
- function callback() {},
- []
- );
-
- expect(bidRequests[0].bids[0].bidder).equals('appnexus');
- expect(bidRequests[0].fledgeEnabled).to.be.true;
- expect(bidRequests[0].defaultForSlots).to.equal(1);
-
- expect(bidRequests[1].bids[0].bidder).equals('rubicon');
- expect(bidRequests[1].fledgeEnabled).to.be.undefined;
- expect(bidRequests[1].defaultForSlots).to.be.undefined;
- });
- });
-
- describe('with setConfig()', () => {
- it('should set fledgeEnabled correctly per bidder', function () {
- config.setConfig({
- bidderSequence: 'fixed',
- fledgeForGpt: {
- enabled: true,
- bidders: ['appnexus'],
- defaultForSlots: 1,
- }
- });
-
- const bidRequests = adapterManager.makeBidRequests(
- adUnits,
- Date.now(),
- utils.getUniqueIdentifierStr(),
- function callback() {},
- []
- );
-
- expect(bidRequests[0].bids[0].bidder).equals('appnexus');
- expect(bidRequests[0].fledgeEnabled).to.be.true;
- expect(bidRequests[0].defaultForSlots).to.equal(1);
-
- expect(bidRequests[1].bids[0].bidder).equals('rubicon');
- expect(bidRequests[1].fledgeEnabled).to.be.undefined;
- expect(bidRequests[1].defaultForSlots).to.be.undefined;
- });
-
- it('should set fledgeEnabled correctly for all bidders', function () {
- config.setConfig({
- bidderSequence: 'fixed',
- fledgeForGpt: {
- enabled: true,
- defaultForSlots: 1,
- }
- });
-
- const bidRequests = adapterManager.makeBidRequests(
- adUnits,
- Date.now(),
- utils.getUniqueIdentifierStr(),
- function callback() {},
- []
- );
-
- expect(bidRequests[0].bids[0].bidder).equals('appnexus');
- expect(bidRequests[0].fledgeEnabled).to.be.true;
- expect(bidRequests[0].defaultForSlots).to.equal(1);
-
- expect(bidRequests[1].bids[0].bidder).equals('rubicon');
- expect(bidRequests[0].fledgeEnabled).to.be.true;
- expect(bidRequests[0].defaultForSlots).to.equal(1);
- });
- });
-});
-
-describe('ortb processors for fledge', () => {
- describe('when defaultForSlots is set', () => {
- it('imp.ext.ae should be set if fledge is enabled', () => {
- const imp = {};
- setImpExtAe(imp, {}, {bidderRequest: {fledgeEnabled: true, defaultForSlots: 1}});
- expect(imp.ext.ae).to.equal(1);
- });
- it('imp.ext.ae should be left intact if set on adunit and fledge is enabled', () => {
- const imp = {ext: {ae: 2}};
- setImpExtAe(imp, {}, {bidderRequest: {fledgeEnabled: true, defaultForSlots: 1}});
- expect(imp.ext.ae).to.equal(2);
- });
- });
- describe('when defaultForSlots is not defined', () => {
- it('imp.ext.ae should be removed if fledge is not enabled', () => {
- const imp = {ext: {ae: 1}};
- setImpExtAe(imp, {}, {bidderRequest: {}});
- expect(imp.ext.ae).to.not.exist;
- })
- it('imp.ext.ae should be left intact if fledge is enabled', () => {
- const imp = {ext: {ae: 2}};
- setImpExtAe(imp, {}, {bidderRequest: {fledgeEnabled: true}});
- expect(imp.ext.ae).to.equal(2);
- });
- });
- describe('parseExtPrebidFledge', () => {
- function packageConfigs(configs) {
- return {
- ext: {
- prebid: {
- fledge: {
- auctionconfigs: configs
- }
- }
- }
- }
- }
-
- function generateImpCtx(fledgeFlags) {
- return Object.fromEntries(Object.entries(fledgeFlags).map(([impid, fledgeEnabled]) => [impid, {imp: {ext: {ae: fledgeEnabled}}}]));
- }
-
- function generateCfg(impid, ...ids) {
- return ids.map((id) => ({impid, config: {id}}));
- }
-
- function extractResult(ctx) {
- return Object.fromEntries(
- Object.entries(ctx)
- .map(([impid, ctx]) => [impid, ctx.fledgeConfigs?.map(cfg => cfg.config.id)])
- .filter(([_, val]) => val != null)
- );
- }
-
- it('should collect fledge configs by imp', () => {
- const ctx = {
- impContext: generateImpCtx({e1: 1, e2: 1, d1: 0})
- };
- const resp = packageConfigs(
- generateCfg('e1', 1, 2, 3)
- .concat(generateCfg('e2', 4)
- .concat(generateCfg('d1', 5, 6)))
- );
- parseExtPrebidFledge({}, resp, ctx);
- expect(extractResult(ctx.impContext)).to.eql({
- e1: [1, 2, 3],
- e2: [4],
- });
- });
- it('should not choke if fledge config references unknown imp', () => {
- const ctx = {impContext: generateImpCtx({i: 1})};
- const resp = packageConfigs(generateCfg('unknown', 1));
- parseExtPrebidFledge({}, resp, ctx);
- expect(extractResult(ctx.impContext)).to.eql({});
- });
- });
- describe('setResponseFledgeConfigs', () => {
- it('should set fledgeAuctionConfigs paired with their corresponding bid id', () => {
- const ctx = {
- impContext: {
- 1: {
- bidRequest: {bidId: 'bid1'},
- fledgeConfigs: [{config: {id: 1}}, {config: {id: 2}}]
- },
- 2: {
- bidRequest: {bidId: 'bid2'},
- fledgeConfigs: [{config: {id: 3}}]
- },
- 3: {
- bidRequest: {bidId: 'bid3'}
- }
- }
- };
- const resp = {};
- setResponseFledgeConfigs(resp, {}, ctx);
- expect(resp.fledgeAuctionConfigs).to.eql([
- {bidId: 'bid1', config: {id: 1}},
- {bidId: 'bid1', config: {id: 2}},
- {bidId: 'bid2', config: {id: 3}},
- ]);
- });
- it('should not set fledgeAuctionConfigs if none exist', () => {
- const resp = {};
- setResponseFledgeConfigs(resp, {}, {
- impContext: {
- 1: {
- fledgeConfigs: []
- },
- 2: {}
- }
- });
- expect(resp).to.eql({});
- });
- });
-});
diff --git a/test/spec/modules/flippBidAdapter_spec.js b/test/spec/modules/flippBidAdapter_spec.js
new file mode 100644
index 00000000000..518052ad91e
--- /dev/null
+++ b/test/spec/modules/flippBidAdapter_spec.js
@@ -0,0 +1,170 @@
+import {expect} from 'chai';
+import {spec} from 'modules/flippBidAdapter';
+import {newBidder} from 'src/adapters/bidderFactory';
+const ENDPOINT = 'https://gateflipp.flippback.com/flyer-locator-service/client_bidding';
+describe('flippAdapter', function () {
+ const adapter = newBidder(spec);
+
+ describe('inherited functions', function () {
+ it('exists and is a function', function () {
+ expect(adapter.callBids).to.exist.and.to.be.a('function');
+ });
+ });
+
+ describe('isBidRequestValid', function () {
+ const bid = {
+ bidder: 'flipp',
+ params: {
+ publisherNameIdentifier: 'random',
+ siteId: 1234,
+ zoneIds: [1, 2, 3, 4],
+ }
+ };
+ it('should return true when required params found', function () {
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+
+ it('should return false when required params are not passed', function () {
+ let invalidBid = Object.assign({}, bid);
+ invalidBid.params = { siteId: 1234 }
+ expect(spec.isBidRequestValid(invalidBid)).to.equal(false);
+ });
+ });
+
+ describe('buildRequests', function () {
+ const bidRequests = [{
+ bidder: 'flipp',
+ params: {
+ siteId: 1234,
+ },
+ adUnitCode: '/10000/unit_code',
+ sizes: [[300, 600]],
+ mediaTypes: {banner: {sizes: [[300, 600]]}},
+ bidId: '237f4d1a293f99',
+ bidderRequestId: '1a857fa34c1c96',
+ auctionId: 'a297d1aa-7900-4ce4-a0aa-caa8d46c4af7',
+ transactionId: '00b2896c-2731-4f01-83e4-7a3ad5da13b6',
+ }];
+ const bidderRequest = {
+ refererInfo: {
+ referer: 'http://example.com'
+ }
+ };
+
+ it('sends bid request to ENDPOINT via POST', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.method).to.equal('POST');
+ });
+
+ it('sends bid request to ENDPOINT with query parameter', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.url).to.equal(ENDPOINT);
+ });
+ });
+
+ describe('interpretResponse', function() {
+ it('should get correct bid response', function() {
+ const bidRequest = {
+ method: 'POST',
+ url: ENDPOINT,
+ data: {
+ placements: [{
+ divName: 'slot',
+ networkId: 12345,
+ siteId: 12345,
+ adTypes: [12345],
+ count: 1,
+ prebid: {
+ requestId: '237f4d1a293f99',
+ publisherNameIdentifier: 'bid.params.publisherNameIdentifier',
+ height: 600,
+ width: 300,
+ },
+ user: '10462725-da61-4d3a-beff-6d05239e9a6e"',
+ }],
+ url: 'http://example.com',
+ },
+ };
+
+ const serverResponse = {
+ body: {
+ 'decisions': {
+ 'inline': [{
+ 'bidCpm': 1,
+ 'adId': 262838368,
+ 'height': 600,
+ 'width': 300,
+ 'storefront': { 'flyer_id': 5435567 },
+ 'prebid': {
+ 'requestId': '237f4d1a293f99',
+ 'cpm': 1.11,
+ 'creative': 'Returned from server',
+ }
+ }]
+ },
+ 'location': {'city': 'Oakville'},
+ },
+ };
+
+ const expectedResponse = [
+ {
+ bidderCode: 'flipp',
+ requestId: '237f4d1a293f99',
+ currency: 'USD',
+ cpm: 1.11,
+ netRevenue: true,
+ width: 300,
+ height: 600,
+ creativeId: 262838368,
+ ttl: 30,
+ ad: 'Returned from server',
+ }
+ ];
+
+ const result = spec.interpretResponse(serverResponse, bidRequest);
+ expect(result).to.have.lengthOf(1);
+ expect(result).to.deep.have.same.members(expectedResponse);
+ });
+
+ it('should get empty bid response when no ad is returned', function() {
+ const bidRequest = {
+ method: 'POST',
+ url: ENDPOINT,
+ data: {
+ placements: [{
+ divName: 'slot',
+ networkId: 12345,
+ siteId: 12345,
+ adTypes: [12345],
+ count: 1,
+ prebid: {
+ requestId: '237f4d1a293f99',
+ publisherNameIdentifier: 'bid.params.publisherNameIdentifier',
+ height: 600,
+ width: 300,
+ },
+ user: '10462725-da61-4d3a-beff-6d05239e9a6e"',
+ }],
+ url: 'http://example.com',
+ },
+ };
+
+ const serverResponse = {
+ body: {
+ 'decisions': {
+ 'inline': []
+ },
+ 'location': {'city': 'Oakville'},
+ },
+ };
+
+ const result = spec.interpretResponse(serverResponse, bidRequest);
+ expect(result).to.have.lengthOf(0);
+ expect(result).to.deep.have.same.members([]);
+ })
+
+ it('should get empty response when bid server returns 204', function() {
+ expect(spec.interpretResponse({})).to.be.empty;
+ });
+ });
+});
diff --git a/test/spec/modules/freepassIdSystem_spec.js b/test/spec/modules/freepassIdSystem_spec.js
index f7407f5eb94..0a9fa956cd4 100644
--- a/test/spec/modules/freepassIdSystem_spec.js
+++ b/test/spec/modules/freepassIdSystem_spec.js
@@ -1,4 +1,4 @@
-import {freepassIdSubmodule} from 'modules/freepassIdSystem';
+import { freepassIdSubmodule, storage, FREEPASS_COOKIE_KEY } from 'modules/freepassIdSystem';
import sinon from 'sinon';
import * as utils from '../../../src/utils';
@@ -6,15 +6,16 @@ let expect = require('chai').expect;
describe('FreePass ID System', function () {
const UUID = '15fde1dc-1861-4894-afdf-b757272f3568';
+ let getCookieStub;
before(function () {
- sinon.stub(utils, 'generateUUID').returns(UUID);
sinon.stub(utils, 'logMessage');
+ getCookieStub = sinon.stub(storage, 'getCookie');
});
after(function () {
- utils.generateUUID.restore();
utils.logMessage.restore();
+ getCookieStub.restore();
});
describe('freepassIdSubmodule', function () {
@@ -39,71 +40,19 @@ describe('FreePass ID System', function () {
};
it('should return an IdObject with a UUID', function () {
+ getCookieStub.withArgs(FREEPASS_COOKIE_KEY).returns(UUID);
const objectId = freepassIdSubmodule.getId(config, undefined);
expect(objectId).to.be.an('object');
expect(objectId.id).to.be.an('object');
expect(objectId.id.userId).to.equal(UUID);
});
- it('should include userIp in IdObject', function () {
+ it('should return an IdObject without UUID when absent in cookie', function () {
+ getCookieStub.withArgs(FREEPASS_COOKIE_KEY).returns(null);
const objectId = freepassIdSubmodule.getId(config, undefined);
expect(objectId).to.be.an('object');
expect(objectId.id).to.be.an('object');
- expect(objectId.id.userIp).to.equal('127.0.0.1');
- });
- it('should skip userIp in IdObject if not available', function () {
- const localConfig = Object.assign({}, config);
- delete localConfig.params.freepassData.userIp;
- const objectId = freepassIdSubmodule.getId(localConfig, undefined);
- expect(objectId).to.be.an('object');
- expect(objectId.id).to.be.an('object');
- expect(objectId.id.userIp).to.be.undefined;
- });
- it('should skip userIp in IdObject if freepassData is not available', function () {
- const localConfig = JSON.parse(JSON.stringify(config));
- delete localConfig.params.freepassData;
- const objectId = freepassIdSubmodule.getId(localConfig, undefined);
- expect(objectId).to.be.an('object');
- expect(objectId.id).to.be.an('object');
- expect(objectId.id.userIp).to.be.undefined;
- });
- it('should skip userIp in IdObject if params is not available', function () {
- const localConfig = JSON.parse(JSON.stringify(config));
- delete localConfig.params;
- const objectId = freepassIdSubmodule.getId(localConfig, undefined);
- expect(objectId).to.be.an('object');
- expect(objectId.id).to.be.an('object');
- expect(objectId.id.userIp).to.be.undefined;
- });
- it('should include commonId in IdObject', function () {
- const objectId = freepassIdSubmodule.getId(config, undefined);
- expect(objectId).to.be.an('object');
- expect(objectId.id).to.be.an('object');
- expect(objectId.id.commonId).to.equal('commonId');
- });
- it('should skip commonId in IdObject if not available', function () {
- const localConfig = Object.assign({}, config);
- delete localConfig.params.freepassData.commonId;
- const objectId = freepassIdSubmodule.getId(localConfig, undefined);
- expect(objectId).to.be.an('object');
- expect(objectId.id).to.be.an('object');
- expect(objectId.id.commonId).to.be.undefined;
- });
- it('should skip commonId in IdObject if freepassData is not available', function () {
- const localConfig = JSON.parse(JSON.stringify(config));
- delete localConfig.params.freepassData;
- const objectId = freepassIdSubmodule.getId(localConfig, undefined);
- expect(objectId).to.be.an('object');
- expect(objectId.id).to.be.an('object');
- expect(objectId.id.commonId).to.be.undefined;
- });
- it('should skip commonId in IdObject if params is not available', function () {
- const localConfig = JSON.parse(JSON.stringify(config));
- delete localConfig.params;
- const objectId = freepassIdSubmodule.getId(localConfig, undefined);
- expect(objectId).to.be.an('object');
- expect(objectId.id).to.be.an('object');
- expect(objectId.id.commonId).to.be.undefined;
+ expect(objectId.id.userId).to.be.undefined;
});
});
@@ -142,12 +91,15 @@ describe('FreePass ID System', function () {
};
it('should return cachedIdObject if there are no changes', function () {
+ getCookieStub.withArgs(FREEPASS_COOKIE_KEY).returns(UUID);
const idObject = freepassIdSubmodule.getId(config, undefined);
const cachedIdObject = Object.assign({}, idObject.id);
const extendedIdObject = freepassIdSubmodule.extendId(config, undefined, cachedIdObject);
expect(extendedIdObject).to.be.an('object');
expect(extendedIdObject.id).to.be.an('object');
- expect(extendedIdObject.id).to.equal(cachedIdObject);
+ expect(extendedIdObject.id.userId).to.equal(UUID);
+ expect(extendedIdObject.id.userIp).to.equal(config.params.freepassData.userIp);
+ expect(extendedIdObject.id.commonId).to.equal(config.params.freepassData.commonId);
});
it('should return cachedIdObject if there are no new data', function () {
@@ -182,5 +134,20 @@ describe('FreePass ID System', function () {
expect(extendedIdObject.id).to.be.an('object');
expect(extendedIdObject.id.userIp).to.equal('192.168.1.1');
});
+
+ it('should return new userId when changed from cache', function () {
+ getCookieStub.withArgs(FREEPASS_COOKIE_KEY).returns(UUID);
+ const idObject = freepassIdSubmodule.getId(config, undefined);
+ const cachedIdObject = Object.assign({}, idObject.id);
+ const localConfig = JSON.parse(JSON.stringify(config));
+ localConfig.params.freepassData.userIp = '192.168.1.1';
+
+ getCookieStub.withArgs(FREEPASS_COOKIE_KEY).returns('NEW_UUID');
+ const extendedIdObject = freepassIdSubmodule.extendId(localConfig, undefined, cachedIdObject);
+ expect(extendedIdObject).to.be.an('object');
+ expect(extendedIdObject.id).to.be.an('object');
+ expect(extendedIdObject.id.userIp).to.equal('192.168.1.1');
+ expect(extendedIdObject.id.userId).to.equal('NEW_UUID');
+ });
});
});
diff --git a/test/spec/modules/freewheel-sspBidAdapter_spec.js b/test/spec/modules/freewheel-sspBidAdapter_spec.js
index c42c5e2528d..90ebe0b80ee 100644
--- a/test/spec/modules/freewheel-sspBidAdapter_spec.js
+++ b/test/spec/modules/freewheel-sspBidAdapter_spec.js
@@ -2,6 +2,7 @@ import { expect } from 'chai';
import { spec } from 'modules/freewheel-sspBidAdapter.js';
import { newBidder } from 'src/adapters/bidderFactory.js';
import { createEidsArray } from 'modules/userId/eids.js';
+import { config } from 'src/config.js';
const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php';
const PREBID_VERSION = '$prebid.version$';
@@ -203,6 +204,14 @@ describe('freewheelSSP BidAdapter Test', () => {
let bidderRequest = {
'gdprConsent': {
'consentString': gdprConsentString
+ },
+ 'ortb2': {
+ 'site': {
+ 'content': {
+ 'test': 'news',
+ 'test2': 'param'
+ }
+ }
}
};
@@ -216,6 +225,7 @@ describe('freewheelSSP BidAdapter Test', () => {
expect(payload.playerSize).to.equal('300x600');
expect(payload._fw_gdpr_consent).to.exist.and.to.be.a('string');
expect(payload._fw_gdpr_consent).to.equal(gdprConsentString);
+ expect(payload._fw_prebid_content).to.deep.equal('{\"test\":\"news\",\"test2\":\"param\"}');
let gdprConsent = {
'gdprApplies': true,
diff --git a/test/spec/modules/gdprEnforcement_spec.js b/test/spec/modules/gdprEnforcement_spec.js
index 1d0eee923b9..295b14dd796 100644
--- a/test/spec/modules/gdprEnforcement_spec.js
+++ b/test/spec/modules/gdprEnforcement_spec.js
@@ -1,13 +1,12 @@
import {
accessDeviceRule,
- deviceAccessHook,
- enforcementRules,
enrichEidsRule,
fetchBidsRule,
+ transmitEidsRule,
+ transmitPreciseGeoRule,
getGvlid,
getGvlidFromAnalyticsAdapter,
- purpose1Rule,
- purpose2Rule,
+ ACTIVE_RULES,
reportAnalyticsRule,
setEnforcementConfig,
STRICT_STORAGE_ENFORCEMENT,
@@ -27,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';
@@ -474,6 +473,261 @@ describe('gdpr enforcement', function () {
});
});
+ describe('transmitEidsRule', () => {
+ const GVL_ID = 123;
+ const BIDDER = 'mockBidder';
+ let cd;
+ const RULES_2_10 = {
+ basicAds: 2,
+ personalizedAds: 4,
+ measurement: 7,
+ }
+
+ beforeEach(() => {
+ cd = setupConsentData();
+ cd.vendorData = {
+ vendor: {
+ consents: {},
+ legitimateInterests: {},
+ },
+ purpose: {
+ consents: {},
+ legitimateInterests: {}
+ }
+ };
+ Object.assign(gvlids, {
+ [BIDDER]: GVL_ID
+ });
+ });
+
+ function setVendorConsent(type = 'consents') {
+ cd.vendorData.vendor[type][GVL_ID] = true;
+ }
+
+ function runRule() {
+ return transmitEidsRule(activityParams(MODULE_TYPE_BIDDER, BIDDER));
+ }
+
+ describe('default behavior', () => {
+ const CS_PURPOSES = [3, 4, 5, 6, 7, 8, 9, 10];
+ const LI_PURPOSES = [2];
+ const CONSENT_TYPES = ['consents', 'legitimateInterests'];
+
+ describe('should deny if', () => {
+ describe('config is default', () => {
+ beforeEach(() => {
+ setEnforcementConfig({});
+ });
+
+ it('no consent is given, of any type or for any vendor', () => {
+ expectAllow(false, runRule());
+ });
+
+ CONSENT_TYPES.forEach(type => {
+ it(`vendor ${type} is given, but no purpose has consent`, () => {
+ setVendorConsent(type);
+ expectAllow(false, runRule());
+ });
+
+ it(`${type} is given for purpose other than 2-10`, () => {
+ setVendorConsent(type);
+ cd.vendorData.purpose[type][1] = true;
+ expectAllow(false, runRule());
+ });
+
+ LI_PURPOSES.forEach(purpose => {
+ it(`purpose ${purpose} has ${type}, but vendor does not`, () => {
+ cd.vendorData.purpose[type][purpose] = true;
+ expectAllow(false, runRule());
+ });
+ });
+ });
+ });
+
+ describe(`no consent is given`, () => {
+ [
+ {
+ enforcePurpose: false,
+ },
+ {
+ enforceVendor: false,
+ },
+ {
+ enforcePurpose: false,
+ enforceVendor: false,
+ }
+ ].forEach(t => {
+ it(`config has ${JSON.stringify(t)} for each of ${Object.keys(RULES_2_10).join(', ')}`, () => {
+ setEnforcementConfig({
+ gdpr: {
+ rules: Object.keys(RULES_2_10).map(rule => Object.assign({
+ purpose: rule,
+ vendorExceptions: [],
+ enforcePurpose: true,
+ enforceVendor: true
+ }, t))
+ }
+ });
+ expectAllow(false, runRule());
+ });
+ });
+ });
+ });
+
+ describe('should allow if', () => {
+ describe('config is default', () => {
+ beforeEach(() => {
+ setEnforcementConfig({});
+ });
+ LI_PURPOSES.forEach(purpose => {
+ it(`purpose ${purpose} has LI, vendor has LI`, () => {
+ setVendorConsent('legitimateInterests');
+ cd.vendorData.purpose.legitimateInterests[purpose] = true;
+ expectAllow(true, runRule());
+ });
+ });
+
+ LI_PURPOSES.concat(CS_PURPOSES).forEach(purpose => {
+ it(`purpose ${purpose} has consent, vendor has consent`, () => {
+ setVendorConsent();
+ cd.vendorData.purpose.consents[purpose] = true;
+ expectAllow(true, runRule());
+ });
+ });
+ });
+
+ Object.keys(RULES_2_10).forEach(rule => {
+ it(`no consent given, but '${rule}' config has a vendor exception`, () => {
+ setEnforcementConfig({
+ gdpr: {
+ rules: [
+ {
+ purpose: rule,
+ enforceVendor: false,
+ enforcePurpose: false,
+ vendorExceptions: [BIDDER]
+ }
+ ]
+ }
+ });
+ expectAllow(true, runRule());
+ });
+
+ it(`vendor consent is missing, but '${rule}' config has a softVendorException`, () => {
+ setEnforcementConfig({
+ gdpr: {
+ rules: [
+ {
+ purpose: rule,
+ enforceVendor: false,
+ enforcePurpose: false,
+ softVendorExceptions: [BIDDER]
+ }
+ ]
+ }
+ });
+ cd.vendorData.purpose.consents[RULES_2_10[rule]] = true;
+ expectAllow(true, runRule());
+ })
+ });
+ });
+ });
+
+ describe('with eidsRequireP4consent', () => {
+ function setupPAdsRule(cfg = {}) {
+ setEnforcementConfig({
+ gdpr: {
+ rules: [
+ Object.assign({
+ purpose: 'personalizedAds',
+ eidsRequireP4Consent: true,
+ enforcePurpose: true,
+ enforceVendor: true,
+ }, cfg)
+ ]
+ }
+ })
+ }
+ describe('allows when', () => {
+ Object.entries({
+ 'purpose 4 consent is given'() {
+ setupPAdsRule();
+ setVendorConsent();
+ cd.vendorData.purpose.consents[4] = true
+ },
+ 'enforcePurpose is false, with vendor consent given'() {
+ setupPAdsRule({enforcePurpose: false});
+ setVendorConsent();
+ },
+ 'enforceVendor is false, with purpose consent given'() {
+ setupPAdsRule({enforceVendor: false});
+ cd.vendorData.purpose.consents[4] = true;
+ },
+ 'vendor is excepted'() {
+ setupPAdsRule({vendorExceptions: [BIDDER]});
+ },
+ 'vendor is softly excepted, with purpose consent given'() {
+ setupPAdsRule({softVendorExceptions: [BIDDER]});
+ cd.vendorData.purpose.consents[4] = true;
+ }
+ }).forEach(([t, setup]) => {
+ it(t, () => {
+ setup();
+ expectAllow(true, runRule());
+ });
+ });
+ });
+ describe('denies when', () => {
+ Object.entries({
+ 'purpose 4 consent is not given'() {
+ setupPAdsRule();
+ setVendorConsent();
+ },
+ 'vendor consent is not given'() {
+ setupPAdsRule();
+ cd.vendorData.purpose.consents[4] = true
+ },
+ }).forEach(([t, setup]) => {
+ it(t, () => {
+ setup();
+ expectAllow(false, runRule());
+ })
+ })
+ })
+ })
+ });
+
+ describe('transmitPreciseGeoRule', () => {
+ const BIDDER = 'mockBidder';
+ let cd;
+
+ function runRule() {
+ return transmitPreciseGeoRule(activityParams(MODULE_TYPE_BIDDER, BIDDER))
+ }
+
+ beforeEach(() => {
+ cd = setupConsentData();
+ setEnforcementConfig({
+ gdpr: {
+ rules: [{
+ purpose: 'transmitPreciseGeo',
+ enforcePurpose: true,
+ enforceVendor: false
+ }]
+ }
+ })
+ });
+
+ it('should allow when special feature 1 consent is given', () => {
+ cd.vendorData.specialFeatureOptins[1] = true;
+ expectAllow(true, runRule());
+ })
+ it('should deny when configured, but consent is missing', () => {
+ cd.vendorData.specialFeatureOptins[1] = false;
+ expectAllow(false, runRule());
+ });
+ });
+
describe('validateRules', function () {
const createGdprRule = (purposeName = 'storage', enforcePurpose = true, enforceVendor = true, vendorExceptions = [], softVendorExceptions = []) => ({
purpose: purposeName,
@@ -535,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],
@@ -631,7 +900,8 @@ describe('gdpr enforcement', function () {
});
expect(logWarnSpy.calledOnce).to.equal(true);
- expect(enforcementRules).to.deep.equal(DEFAULT_RULES);
+ expect(ACTIVE_RULES.purpose[1]).to.deep.equal(DEFAULT_RULES[0]);
+ expect(ACTIVE_RULES.purpose[2]).to.deep.equal(DEFAULT_RULES[1]);
});
it('should enforce TCF2 Purpose 2 also if only Purpose 1 is defined in "rules"', function () {
@@ -647,8 +917,8 @@ describe('gdpr enforcement', function () {
}
});
- expect(purpose1Rule).to.deep.equal(purpose1RuleDefinedInConfig);
- expect(purpose2Rule).to.deep.equal(DEFAULT_RULES[1]);
+ expect(ACTIVE_RULES.purpose[1]).to.deep.equal(purpose1RuleDefinedInConfig);
+ expect(ACTIVE_RULES.purpose[2]).to.deep.equal(DEFAULT_RULES[1]);
});
it('should enforce TCF2 Purpose 1 also if only Purpose 2 is defined in "rules"', function () {
@@ -664,8 +934,8 @@ describe('gdpr enforcement', function () {
}
});
- expect(purpose1Rule).to.deep.equal(DEFAULT_RULES[0]);
- expect(purpose2Rule).to.deep.equal(purpose2RuleDefinedInConfig);
+ expect(ACTIVE_RULES.purpose[1]).to.deep.equal(DEFAULT_RULES[0]);
+ expect(ACTIVE_RULES.purpose[2]).to.deep.equal(purpose2RuleDefinedInConfig);
});
it('should use the "rules" defined in config if a definition found', function() {
@@ -679,8 +949,8 @@ describe('gdpr enforcement', function () {
enforceVendor: false
}]
setEnforcementConfig({gdpr: { rules }});
-
- expect(enforcementRules).to.deep.equal(rules);
+ expect(ACTIVE_RULES.purpose[1]).to.deep.equal(rules[0]);
+ expect(ACTIVE_RULES.purpose[2]).to.deep.equal(rules[1]);
});
});
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/goldfishAdsRtdProvider_spec.js b/test/spec/modules/goldfishAdsRtdProvider_spec.js
new file mode 100755
index 00000000000..39a1e0c9b33
--- /dev/null
+++ b/test/spec/modules/goldfishAdsRtdProvider_spec.js
@@ -0,0 +1,163 @@
+import {
+ goldfishAdsSubModule,
+ manageCallbackResponse,
+} from 'modules/goldfishAdsRtdProvider.js';
+import { getStorageManager } from '../../../src/storageManager.js';
+import { expect } from 'chai';
+import { server } from 'test/mocks/xhr.js';
+import { config as _config } from 'src/config.js';
+import { DATA_STORAGE_KEY, MODULE_NAME, MODULE_TYPE, getStorageData, updateUserData } from '../../../modules/goldfishAdsRtdProvider';
+
+const responseHeader = { 'Content-Type': 'application/json' };
+
+const sampleConfig = {
+ name: 'golfishAds',
+ waitForIt: true,
+ params: {
+ key: 'testkey'
+ }
+};
+
+const sampleAdUnits = [
+ {
+ code: 'one-div-id',
+ mediaTypes: {
+ banner: {
+ sizes: [970, 250]
+ }
+ },
+ bids: [
+ {
+ bidder: 'appnexus',
+ params: {
+ placementId: 12345370,
+ }
+ }]
+ },
+ {
+ code: 'two-div-id',
+ mediaTypes: {
+ banner: { sizes: [300, 250] }
+ },
+ bids: [
+ {
+ bidder: 'appnexus',
+ params: {
+ placementId: 12345370,
+ }
+ }]
+ }];
+
+const sampleOutputData = [1, 2, 3]
+
+describe('goldfishAdsRtdProvider is a RTD provider that', function () {
+ describe('has a method `init` that', function () {
+ it('exists', function () {
+ expect(goldfishAdsSubModule.init).to.be.a('function');
+ });
+ it('returns false missing config params', function () {
+ const config = {
+ name: 'goldfishAds',
+ waitForIt: true,
+ };
+ const value = goldfishAdsSubModule.init(config);
+ expect(value).to.equal(false);
+ });
+ it('returns false if missing providers param', function () {
+ const config = {
+ name: 'goldfishAds',
+ waitForIt: true,
+ params: {}
+ };
+ const value = goldfishAdsSubModule.init(config);
+ expect(value).to.equal(false);
+ });
+ it('returns false if wrong providers param included', function () {
+ const config = {
+ name: 'goldfishAds',
+ waitForIt: true,
+ params: {
+ account: 'test'
+ }
+ };
+ const value = goldfishAdsSubModule.init(config);
+ expect(value).to.equal(false);
+ });
+ it('returns true if good providers param included', function () {
+ const config = {
+ name: 'goldfishAds',
+ waitForIt: true,
+ params: {
+ key: 'testkey'
+ }
+ };
+ const value = goldfishAdsSubModule.init(config);
+ expect(value).to.equal(true);
+ });
+ });
+
+ describe('has a method `getBidRequestData` that', function () {
+ it('exists', function () {
+ expect(goldfishAdsSubModule.getBidRequestData).to.be.a('function');
+ });
+
+ it('send correct request', function () {
+ const callback = sinon.spy();
+ let request;
+ const reqBidsConfigObj = { adUnits: sampleAdUnits };
+ goldfishAdsSubModule.getBidRequestData(reqBidsConfigObj, callback, sampleConfig);
+ request = server.requests[0];
+ request.respond(200, responseHeader, JSON.stringify(sampleOutputData));
+ expect(request.url).to.be.include(`?key=testkey`);
+ });
+ });
+
+ describe('has a manageCallbackResponse that', function () {
+ it('properly transforms the response', function () {
+ const response = { response: '[\"1\", \"2\", \"3\"]' };
+ const output = manageCallbackResponse(response);
+ expect(output.name).to.be.equal('goldfishads.com');
+ });
+ });
+
+ describe('has an updateUserData that', function () {
+ it('properly transforms the response', function () {
+ const userData = {
+ segment: [{id: '1'}, {id: '2'}],
+ ext: {
+ segtax: 4,
+ }
+ };
+ const reqBidsConfigObj = { ortb2Fragments: { bidder: { appnexus: { user: { data: [] } } } } };
+ const output = updateUserData(userData, reqBidsConfigObj);
+ expect(output.ortb2Fragments.bidder.appnexus.user.data[0].segment).to.be.length(2);
+ expect(output.ortb2Fragments.bidder.appnexus.user.data[0].segment[0].id).to.be.eql('1');
+ });
+ });
+
+ describe('uses Local Storage to ', function () {
+ const sandbox = sinon.createSandbox();
+ const storage = getStorageManager({ moduleType: MODULE_TYPE, moduleName: MODULE_NAME })
+ beforeEach(() => {
+ storage.setDataInLocalStorage(DATA_STORAGE_KEY, JSON.stringify({
+ targeting: {
+ name: 'goldfishads.com',
+ segment: [{id: '1'}, {id: '2'}],
+ ext: {
+ segtax: 4,
+ }
+ },
+ expiry: new Date().getTime() + 1000 * 60 * 60 * 24 * 30,
+ }));
+ });
+ afterEach(() => {
+ sandbox.restore();
+ });
+ it('get data from local storage', function () {
+ const output = getStorageData();
+ expect(output.name).to.be.equal('goldfishads.com');
+ expect(output.segment).to.be.length(2);
+ expect(output.ext.segtax).to.be.equal(4);
+ });
+ });
+});
diff --git a/test/spec/modules/gptPreAuction_spec.js b/test/spec/modules/gptPreAuction_spec.js
index 2bfce71806e..fa2236f77c6 100644
--- a/test/spec/modules/gptPreAuction_spec.js
+++ b/test/spec/modules/gptPreAuction_spec.js
@@ -97,6 +97,18 @@ describe('GPT pre-auction module', () => {
expect(adUnit.ortb2Imp.ext.data.adserver).to.deep.equal({ name: 'gam', adslot: 'slotCode2' });
});
+ it('should add adServer object to context if matching slot is found (in case of twin ad unit)', () => {
+ window.googletag.pubads().setSlots(testSlots);
+ const adUnit1 = { code: 'slotCode2', ortb2Imp: { ext: { data: {} } } };
+ const adUnit2 = { code: 'slotCode2', ortb2Imp: { ext: { data: {} } } };
+ appendGptSlots([adUnit1, adUnit2]);
+ expect(adUnit1.ortb2Imp.ext.data.adserver).to.be.an('object');
+ expect(adUnit1.ortb2Imp.ext.data.adserver).to.deep.equal({ name: 'gam', adslot: 'slotCode2' });
+
+ expect(adUnit2.ortb2Imp.ext.data.adserver).to.be.an('object');
+ expect(adUnit2.ortb2Imp.ext.data.adserver).to.deep.equal({ name: 'gam', adslot: 'slotCode2' });
+ });
+
it('will trim child id if mcmEnabled is set to true', () => {
config.setConfig({ gptPreAuction: { enabled: true, mcmEnabled: true } });
window.googletag.pubads().setSlots([
diff --git a/test/spec/modules/greenbidsAnalyticsAdapter_spec.js b/test/spec/modules/greenbidsAnalyticsAdapter_spec.js
index 870fbd23870..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$',
});
}
@@ -246,6 +243,13 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
skip: 1,
protocols: [1, 2, 3, 4]
},
+ },
+ ortb2Imp: {
+ ext: {
+ data: {
+ adunitDFP: 'adunitcustomPathExtension'
+ }
+ }
}
},
],
@@ -253,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({
@@ -266,6 +272,7 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
sizes: [[300, 250], [300, 600]]
}
},
+ ortb2Imp: {},
bidders: [
{
bidder: 'greenbids',
@@ -281,6 +288,13 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
},
{
code: 'adunit-2',
+ ortb2Imp: {
+ ext: {
+ data: {
+ adunitDFP: 'adunitcustomPathExtension'
+ }
+ }
+ },
mediaTypes: {
banner: {
sizes: [[300, 250], [300, 600]]
@@ -315,7 +329,7 @@ describe('Greenbids Prebid AnalyticsAdapter Testing', function () {
timeout: 3000,
auctionEnd: 1234567990,
bidsReceived: receivedBids,
- noBids: noBids
+ noBids: noBids,
}];
greenbidsAnalyticsAdapter.handleBidTimeout(args);
@@ -338,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 () {
@@ -354,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 da51ed058be..0611fa68bf8 100644
--- a/test/spec/modules/gridBidAdapter_spec.js
+++ b/test/spec/modules/gridBidAdapter_spec.js
@@ -941,6 +941,15 @@ describe('TheMediaGrid Adapter', function () {
getDataFromLocalStorageStub.restore();
})
+ it('tmax should be set as integer', function() {
+ let [request] = spec.buildRequests([bidRequests[0]], {...bidderRequest, timeout: '10'});
+ let payload = parseRequest(request.data);
+ expect(payload.tmax).to.equal(10);
+ [request] = spec.buildRequests([bidRequests[0]], {...bidderRequest, timeout: 'ddqwdwdq'});
+ payload = parseRequest(request.data);
+ expect(payload.tmax).to.equal(null);
+ })
+
describe('floorModule', function () {
const floorTestData = {
'currency': 'USD',
@@ -975,6 +984,15 @@ describe('TheMediaGrid Adapter', function () {
const payload = parseRequest(request.data);
expect(payload.imp[0].bidfloor).to.equal(bidfloor);
});
+ it('should return the bidfloor string value if it is greater than getFloor.floor', function () {
+ const bidfloor = '1.80';
+ const bidRequestsWithFloor = { ...bidRequest };
+ bidRequestsWithFloor.params = Object.assign({bidFloor: bidfloor}, bidRequestsWithFloor.params);
+ const [request] = spec.buildRequests([bidRequestsWithFloor], bidderRequest);
+ expect(request.data).to.be.an('string');
+ const payload = parseRequest(request.data);
+ expect(payload.imp[0].bidfloor).to.equal(1.80);
+ });
});
});
@@ -1541,37 +1559,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/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js
index 0e64ec67b27..e0529a895f5 100644
--- a/test/spec/modules/gumgumBidAdapter_spec.js
+++ b/test/spec/modules/gumgumBidAdapter_spec.js
@@ -102,6 +102,8 @@ describe('gumgumAdapter', function () {
let sizesArray = [[300, 250], [300, 600]];
let bidRequests = [
{
+ gppString: 'DBACNYA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN',
+ gppSid: [7],
bidder: 'gumgum',
params: {
inSlot: 9
@@ -119,6 +121,30 @@ describe('gumgumAdapter', function () {
}
}
},
+ pubProvidedId: [
+ {
+ uids: [
+ {
+ ext: {
+ stype: 'ppuid',
+ },
+ id: 'aac4504f-ef89-401b-a891-ada59db44336',
+ },
+ ],
+ source: 'sonobi.com',
+ },
+ {
+ uids: [
+ {
+ ext: {
+ stype: 'ppuid',
+ },
+ id: 'y-zqTHmW9E2uG3jEETC6i6BjGcMhPXld2F~A',
+ },
+ ],
+ source: 'aol.com',
+ },
+ ],
adUnitCode: 'adunit-code',
sizes: sizesArray,
bidId: '30b31c1838de1e',
@@ -155,6 +181,7 @@ describe('gumgumAdapter', function () {
linearity: 1,
startdelay: 1,
placement: 123456,
+ plcmt: 3,
protocols: [1, 2]
}
};
@@ -166,6 +193,11 @@ describe('gumgumAdapter', function () {
const bidRequest = spec.buildRequests([request])[0];
expect(bidRequest.data.aun).to.equal(bidRequests[0].adUnitCode);
});
+ it('should set pubProvidedId if the uid and pubProvidedId are available', function () {
+ const request = { ...bidRequests[0] };
+ const bidRequest = spec.buildRequests([request])[0];
+ expect(bidRequest.data.pubProvidedId).to.equal(JSON.stringify(bidRequests[0].userId.pubProvidedId));
+ });
it('should set id5Id and id5IdLinkType if the uid and linkType are available', function () {
const request = { ...bidRequests[0] };
const bidRequest = spec.buildRequests([request])[0];
@@ -265,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];
@@ -426,6 +466,7 @@ describe('gumgumAdapter', function () {
linearity: 1,
startdelay: 1,
placement: 123456,
+ plcmt: 3,
protocols: [1, 2]
};
const request = Object.assign({}, bidRequests[0]);
@@ -444,6 +485,7 @@ describe('gumgumAdapter', function () {
expect(bidRequest.data.li).to.eq(videoVals.linearity);
expect(bidRequest.data.sd).to.eq(videoVals.startdelay);
expect(bidRequest.data.pt).to.eq(videoVals.placement);
+ expect(bidRequest.data.vplcmt).to.eq(videoVals.plcmt);
expect(bidRequest.data.pr).to.eq(videoVals.protocols.join(','));
expect(bidRequest.data.viw).to.eq(videoVals.playerSize[0].toString());
expect(bidRequest.data.vih).to.eq(videoVals.playerSize[1].toString());
@@ -457,6 +499,7 @@ describe('gumgumAdapter', function () {
linearity: 1,
startdelay: 1,
placement: 123456,
+ plcmt: 3,
protocols: [1, 2]
};
const request = Object.assign({}, bidRequests[0]);
@@ -475,6 +518,7 @@ describe('gumgumAdapter', function () {
expect(bidRequest.data.li).to.eq(inVideoVals.linearity);
expect(bidRequest.data.sd).to.eq(inVideoVals.startdelay);
expect(bidRequest.data.pt).to.eq(inVideoVals.placement);
+ expect(bidRequest.data.vplcmt).to.eq(inVideoVals.plcmt);
expect(bidRequest.data.pr).to.eq(inVideoVals.protocols.join(','));
expect(bidRequest.data.viw).to.eq(inVideoVals.playerSize[0].toString());
expect(bidRequest.data.vih).to.eq(inVideoVals.playerSize[1].toString());
@@ -486,6 +530,12 @@ describe('gumgumAdapter', function () {
expect(request.data).to.not.include.any.keys('eAdBuyId');
expect(request.data).to.not.include.any.keys('adBuyId');
});
+ it('should set pubProvidedId if the uid and pubProvidedId are available', function () {
+ const request = { ...bidRequests[0] };
+ const bidRequest = spec.buildRequests([request])[0];
+ expect(bidRequest.data.pubProvidedId).to.equal(JSON.stringify(bidRequests[0].userId.pubProvidedId));
+ });
+
it('should add gdpr consent parameters if gdprConsent is present', function () {
const gdprConsent = { consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', gdprApplies: true };
const fakeBidRequest = { gdprConsent: gdprConsent };
@@ -503,10 +553,9 @@ describe('gumgumAdapter', function () {
const gppConsent = { gppString: 'DBACNYA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN', applicableSections: [7] }
const fakeBidRequest = { gppConsent: gppConsent };
const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0];
- expect(bidRequest.data.gppConsent).to.exist;
- expect(bidRequest.data.gppConsent.gppString).to.equal(gppConsent.gppString);
- expect(bidRequest.data.gppConsent.gpp_sid).to.equal(gppConsent.applicableSections);
- expect(bidRequest.data.gppConsent.gppString).to.eq('DBACNYA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN');
+ expect(bidRequest.data.gppString).to.equal(gppConsent.gppString);
+ expect(bidRequest.data.gppSid).to.equal(gppConsent.applicableSections.join(','));
+ expect(bidRequest.data.gppString).to.eq('DBACNYA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN');
});
it('should handle ortb2 parameters', function () {
const ortb2 = {
@@ -517,15 +566,14 @@ describe('gumgumAdapter', function () {
}
const fakeBidRequest = { gppConsent: ortb2 };
const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0];
- expect(bidRequest.data.gppConsent.gppString).to.eq(fakeBidRequest[0])
+ expect(bidRequest.data.gpp).to.eq(fakeBidRequest[0])
});
it('should handle gppConsent is present but values are undefined case', function () {
const gppConsent = { gppString: undefined, applicableSections: undefined }
const fakeBidRequest = { gppConsent: gppConsent };
const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0];
- expect(bidRequest.data.gppConsent).to.exist;
- expect(bidRequest.data.gppConsent.gppString).to.equal(undefined);
- expect(bidRequest.data.gppConsent.gpp_sid).to.equal(undefined);
+ expect(bidRequest.data.gppString).to.equal('');
+ expect(bidRequest.data.gppSid).to.equal('');
});
it('should handle ortb2 undefined parameters', function () {
const ortb2 = {
@@ -536,8 +584,8 @@ describe('gumgumAdapter', function () {
}
const fakeBidRequest = { gppConsent: ortb2 };
const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0];
- expect(bidRequest.data.gppConsent.gppString).to.eq(undefined)
- expect(bidRequest.data.gppConsent.gpp_sid).to.eq(undefined)
+ expect(bidRequest.data.gppString).to.eq('')
+ expect(bidRequest.data.gppSid).to.eq('')
});
it('should not set coppa parameter if coppa config is set to false', function () {
config.setConfig({
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..d3d91db010d 100644
--- a/test/spec/modules/id5IdSystem_spec.js
+++ b/test/spec/modules/id5IdSystem_spec.js
@@ -15,7 +15,7 @@ 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 {uspDataHandler, gppDataHandler} from 'src/adapterManager.js';
import 'src/prebid.js';
import {hook} from '../../../src/hook.js';
import {mockGdprConsent} from '../../helpers/consentData.js';
@@ -259,12 +259,14 @@ describe('ID5 ID System', function () {
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 () {
@@ -730,6 +732,26 @@ describe('ID5 ID System', function () {
});
});
+ it('should pass gpp_string and gpp_sid to ID5 server', function () {
+ let xhrServerMock = new XhrServerMock(server)
+ 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(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
+ });
+ });
+
describe('when legacy cookies are set', () => {
let sandbox;
beforeEach(() => {
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/illuminBidAdapter_spec.js b/test/spec/modules/illuminBidAdapter_spec.js
new file mode 100644
index 00000000000..9b702c027f9
--- /dev/null
+++ b/test/spec/modules/illuminBidAdapter_spec.js
@@ -0,0 +1,634 @@
+import {expect} from 'chai';
+import {
+ spec as adapter,
+ createDomain,
+ hashCode,
+ extractPID,
+ extractCID,
+ extractSubDomain,
+ getStorageItem,
+ setStorageItem,
+ tryParseJSON,
+ getUniqueDealId,
+} from 'modules/illuminBidAdapter.js';
+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': '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
+ },
+ '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': ['illumin.com'],
+ '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('IlluminBidAdapter', 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 = {
+ illumin: {
+ 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.illumin.com/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.illumin.com/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.illumin.com/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: ['illumin.com'],
+ agencyName: 'Agency Name',
+ };
+ const responses = adapter.interpretResponse(serverResponse, REQUEST);
+ expect(responses[0].meta).to.deep.equal({
+ advertiserDomains: ['illumin.com'],
+ 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: ['illumin.com']
+ }
+ });
+ });
+
+ 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 = {
+ illumin: {
+ 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 = {
+ illumin: {
+ 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/imdsBidAdapter_spec.js b/test/spec/modules/imdsBidAdapter_spec.js
index 7d808a2528f..b71a0bc51d9 100644
--- a/test/spec/modules/imdsBidAdapter_spec.js
+++ b/test/spec/modules/imdsBidAdapter_spec.js
@@ -1362,17 +1362,17 @@ describe('imdsBidAdapter ', function () {
expect(usersyncs[0].url).to.contain('https://ad-cdn.technoratimedia.com/html/usersync.html');
});
- it('should return a pixel usersync when pixels is enabled', function () {
+ it('should return an image usersync when pixels are enabled', function () {
let usersyncs = spec.getUserSyncs({
pixelEnabled: true
}, null);
expect(usersyncs).to.be.an('array').with.lengthOf(1);
- expect(usersyncs[0]).to.have.property('type', 'pixel');
+ expect(usersyncs[0]).to.have.property('type', 'image');
expect(usersyncs[0]).to.have.property('url');
expect(usersyncs[0].url).to.contain('https://sync.technoratimedia.com/services');
});
- it('should return an iframe usersync when both iframe and pixels is enabled', function () {
+ it('should return an iframe usersync when both iframe and pixel are enabled', function () {
let usersyncs = spec.getUserSyncs({
iframeEnabled: true,
pixelEnabled: true
diff --git a/test/spec/modules/impactifyBidAdapter_spec.js b/test/spec/modules/impactifyBidAdapter_spec.js
index 215972ff450..d9bf4becb22 100644
--- a/test/spec/modules/impactifyBidAdapter_spec.js
+++ b/test/spec/modules/impactifyBidAdapter_spec.js
@@ -1,6 +1,7 @@
import { expect } from 'chai';
-import { spec } from 'modules/impactifyBidAdapter.js';
+import { spec, STORAGE, STORAGE_KEY } from 'modules/impactifyBidAdapter.js';
import * as utils from 'src/utils.js';
+import sinon from 'sinon';
const BIDDER_CODE = 'impactify';
const BIDDER_ALIAS = ['imp'];
@@ -19,89 +20,202 @@ var gdprData = {
};
describe('ImpactifyAdapter', function () {
+ let getLocalStorageStub;
+ let localStorageIsEnabledStub;
+ let sandbox;
+
+ beforeEach(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {
+ impactify: {
+ storageAllowed: true
+ }
+ };
+ sinon.stub(document.body, 'appendChild');
+ sandbox = sinon.sandbox.create();
+ getLocalStorageStub = sandbox.stub(STORAGE, 'getDataFromLocalStorage');
+ localStorageIsEnabledStub = sandbox.stub(STORAGE, 'localStorageIsEnabled');
+ });
+
+ afterEach(function () {
+ $$PREBID_GLOBAL$$.bidderSettings = {};
+ document.body.appendChild.restore();
+ sandbox.restore();
+ });
+
describe('isBidRequestValid', function () {
- let validBid = {
- bidder: 'impactify',
- params: {
- appId: '1',
- format: 'screen',
- style: 'inline'
+ let validBids = [
+ {
+ bidder: 'impactify',
+ params: {
+ appId: 'example.com',
+ format: 'screen',
+ style: 'inline'
+ }
+ },
+ {
+ bidder: 'impactify',
+ params: {
+ appId: 'example.com',
+ format: 'display',
+ style: 'static'
+ }
+ }
+ ];
+
+ let videoBidRequests = [
+ {
+ bidder: 'impactify',
+ params: {
+ appId: '1',
+ format: 'screen',
+ style: 'inline'
+ },
+ mediaTypes: {
+ video: {
+ context: 'instream'
+ }
+ },
+ adUnitCode: 'adunit-code',
+ sizes: [[DEFAULT_VIDEO_WIDTH, DEFAULT_VIDEO_HEIGHT]],
+ bidId: '123456789',
+ bidderRequestId: '987654321',
+ auctionId: '19ab94a9-b0d7-4ed7-9f80-ad0c033cf1b1',
+ transactionId: 'f7b2c372-7a7b-11eb-9439-0242ac130002',
+ userId: {
+ pubcid: '87a0327b-851c-4bb3-a925-0c7be94548f5'
+ },
+ userIdAsEids: [
+ {
+ source: 'pubcid.org',
+ uids: [
+ {
+ id: '87a0327b-851c-4bb3-a925-0c7be94548f5',
+ atype: 1
+ }
+ ]
+ }
+ ]
+ }
+ ];
+ let videoBidderRequest = {
+ bidderRequestId: '98845765110',
+ auctionId: '165410516454',
+ bidderCode: 'impactify',
+ bids: [
+ {
+ ...videoBidRequests[0]
+ }
+ ],
+ refererInfo: {
+ referer: 'https://impactify.io'
}
};
it('should return true when required params found', function () {
- expect(spec.isBidRequestValid(validBid)).to.equal(true);
+ expect(spec.isBidRequestValid(validBids[0])).to.equal(true);
+ expect(spec.isBidRequestValid(validBids[1])).to.equal(true);
});
it('should return false when required params are not passed', function () {
- let bid = Object.assign({}, validBid);
+ let bid = Object.assign({}, validBids[0]);
delete bid.params;
bid.params = {};
expect(spec.isBidRequestValid(bid)).to.equal(false);
+
+ let bid2 = Object.assign({}, validBids[1]);
+ delete bid2.params;
+ bid2.params = {};
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
});
it('should return false when appId is missing', () => {
- const bid = utils.deepClone(validBid);
+ const bid = utils.deepClone(validBids[0]);
delete bid.params.appId;
-
expect(spec.isBidRequestValid(bid)).to.equal(false);
+
+ const bid2 = utils.deepClone(validBids[1]);
+ delete bid2.params.appId;
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
});
it('should return false when appId is not a string', () => {
- const bid = utils.deepClone(validBid);
+ const bid = utils.deepClone(validBids[0]);
+ const bid2 = utils.deepClone(validBids[1]);
bid.params.appId = 123;
+ bid2.params.appId = 123;
expect(spec.isBidRequestValid(bid)).to.equal(false);
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
bid.params.appId = false;
+ bid2.params.appId = false;
expect(spec.isBidRequestValid(bid)).to.equal(false);
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
bid.params.appId = void (0);
+ bid2.params.appId = void (0);
expect(spec.isBidRequestValid(bid)).to.equal(false);
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
bid.params.appId = {};
+ bid2.params.appId = {};
expect(spec.isBidRequestValid(bid)).to.equal(false);
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
});
it('should return false when format is missing', () => {
- const bid = utils.deepClone(validBid);
+ const bid = utils.deepClone(validBids[0]);
delete bid.params.format;
expect(spec.isBidRequestValid(bid)).to.equal(false);
});
it('should return false when format is not a string', () => {
- const bid = utils.deepClone(validBid);
+ const bid = utils.deepClone(validBids[0]);
+ const bid2 = utils.deepClone(validBids[1]);
bid.params.format = 123;
+ bid2.params.format = 123;
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
expect(spec.isBidRequestValid(bid)).to.equal(false);
bid.params.format = false;
+ bid2.params.format = false;
expect(spec.isBidRequestValid(bid)).to.equal(false);
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
bid.params.format = void (0);
+ bid2.params.format = void (0);
expect(spec.isBidRequestValid(bid)).to.equal(false);
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
bid.params.format = {};
+ bid2.params.format = {};
expect(spec.isBidRequestValid(bid)).to.equal(false);
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
});
it('should return false when format is not equals to screen or display', () => {
- const bid = utils.deepClone(validBid);
+ const bid = utils.deepClone(validBids[0]);
if (bid.params.format != 'screen' && bid.params.format != 'display') {
expect(spec.isBidRequestValid(bid)).to.equal(false);
}
+
+ const bid2 = utils.deepClone(validBids[1]);
+ if (bid2.params.format != 'screen' && bid2.params.format != 'display') {
+ expect(spec.isBidRequestValid(bid2)).to.equal(false);
+ }
});
it('should return false when style is missing', () => {
- const bid = utils.deepClone(validBid);
+ const bid = utils.deepClone(validBids[0]);
delete bid.params.style;
expect(spec.isBidRequestValid(bid)).to.equal(false);
});
it('should return false when style is not a string', () => {
- const bid = utils.deepClone(validBid);
+ const bid = utils.deepClone(validBids[0]);
bid.params.style = 123;
expect(spec.isBidRequestValid(bid)).to.equal(false);
@@ -167,22 +281,44 @@ describe('ImpactifyAdapter', function () {
};
it('should pass bidfloor', function () {
- videoBidRequests[0].getFloor = function() {
+ videoBidRequests[0].getFloor = function () {
return {
currency: 'USD',
floor: 1.23,
}
}
- const res = spec.buildRequests(videoBidRequests, videoBidderRequest)
+ const res = spec.buildRequests(videoBidRequests, videoBidderRequest);
const resData = JSON.parse(res.data)
expect(resData.imp[0].bidfloor).to.equal(1.23)
});
it('sends video bid request to ENDPOINT via POST', function () {
+ localStorageIsEnabledStub.returns(true);
+
+ getLocalStorageStub.returns('testValue');
+
const request = spec.buildRequests(videoBidRequests, videoBidderRequest);
+
expect(request.url).to.equal(ORIGIN + AUCTIONURI);
expect(request.method).to.equal('POST');
+ expect(request.options.customHeaders['x-impact']).to.equal('testValue');
+ });
+
+ it('should set header value from localstorage correctly', function () {
+ localStorageIsEnabledStub.returns(true);
+ getLocalStorageStub.returns('testValue');
+
+ const request = spec.buildRequests(videoBidRequests, videoBidderRequest);
+ expect(request.options.customHeaders).to.be.an('object');
+ expect(request.options.customHeaders['x-impact']).to.equal('testValue');
+ });
+
+ it('should set header value to empty if localstorage is not enabled', function () {
+ localStorageIsEnabledStub.returns(false);
+
+ const request = spec.buildRequests(videoBidRequests, videoBidderRequest);
+ expect(request.options.customHeaders).to.be.undefined;
});
});
describe('interpretResponse', function () {
@@ -205,7 +341,7 @@ describe('ImpactifyAdapter', function () {
h: 1,
hash: 'test',
expiry: 166192938,
- meta: {'advertiserDomains': ['testdomain.com']},
+ meta: { 'advertiserDomains': ['testdomain.com'] },
ext: {
prebid: {
'type': 'video'
@@ -281,7 +417,7 @@ describe('ImpactifyAdapter', function () {
height: 1,
hash: 'test',
expiry: 166192938,
- meta: {'advertiserDomains': ['testdomain.com']},
+ meta: { 'advertiserDomains': ['testdomain.com'] },
ttl: 300,
creativeId: '97517771'
}
@@ -343,7 +479,7 @@ describe('ImpactifyAdapter', function () {
h: 1,
hash: 'test',
expiry: 166192938,
- meta: {'advertiserDomains': ['testdomain.com']},
+ meta: { 'advertiserDomains': ['testdomain.com'] },
ext: {
prebid: {
'type': 'video'
@@ -399,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/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js
index f427f9e7624..a86b9be73e6 100644
--- a/test/spec/modules/improvedigitalBidAdapter_spec.js
+++ b/test/spec/modules/improvedigitalBidAdapter_spec.js
@@ -1181,6 +1181,16 @@ describe('Improve Digital Adapter Tests', function () {
expect(bids[0].dealId).to.equal(268515);
});
+ it('should set deal type targeting KV for PG', function () {
+ const request = makeRequest(bidderRequest);
+ const response = deepClone(serverResponse);
+ let bids;
+
+ response.body.seatbid[0].bid[0].ext.improvedigital.pg = 1;
+ bids = spec.interpretResponse(response, request);
+ expect(bids[0].adserverTargeting.hb_deal_type_improve).to.equal('pg');
+ });
+
it('should set currency', function () {
const response = deepClone(serverResponse);
response.body.cur = 'EUR';
diff --git a/test/spec/modules/insticatorBidAdapter_spec.js b/test/spec/modules/insticatorBidAdapter_spec.js
index e24bcb3b455..f9aa3b913c6 100644
--- a/test/spec/modules/insticatorBidAdapter_spec.js
+++ b/test/spec/modules/insticatorBidAdapter_spec.js
@@ -179,6 +179,113 @@ 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;
+ });
});
describe('buildRequests', function () {
@@ -570,4 +677,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/integr8BidAdapter_spec.js b/test/spec/modules/integr8BidAdapter_spec.js
index 8c5a4b47903..01bb706df25 100644
--- a/test/spec/modules/integr8BidAdapter_spec.js
+++ b/test/spec/modules/integr8BidAdapter_spec.js
@@ -72,7 +72,7 @@ describe('integr8AdapterTest', () => {
});
it('bidRequest url', () => {
- const endpointUrl = 'https://integr8.central.gjirafa.tech/bid';
+ const endpointUrl = 'https://central.sea.integr8.digital/bid';
const requests = spec.buildRequests(bidRequests);
requests.forEach(function (requestItem) {
expect(requestItem.url).to.match(new RegExp(`${endpointUrl}`));
@@ -113,7 +113,7 @@ describe('integr8AdapterTest', () => {
describe('interpretResponse', () => {
const bidRequest = {
'method': 'POST',
- 'url': 'https://integr8.central.gjirafa.tech/bid',
+ 'url': 'https://central.sea.integr8.digital/bid',
'data': {
'sizes': '728x90',
'adUnitId': 'hb-leaderboard',
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 eee0335524d..500f2239e55 100644
--- a/test/spec/modules/ixBidAdapter_spec.js
+++ b/test/spec/modules/ixBidAdapter_spec.js
@@ -188,6 +188,35 @@ describe('IndexexchangeAdapter', function () {
}
];
+ const DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED = [
+ {
+ bidder: 'ix',
+ params: {
+ siteId: '123',
+ size: [300, 250]
+ },
+ sizes: [[300, 250], [300, 600]],
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250], [300, 600]],
+ pos: 0
+ }
+ },
+ ortb2Imp: {
+ ext: {
+ tid: '173f49a8-7549-4218-a23c-e7ba59b47229',
+ ae: 1 // Fledge enabled
+ },
+ },
+ adUnitCode: 'div-fledge-ad-1460505748561-0',
+ transactionId: '173f49a8-7549-4218-a23c-e7ba59b47229',
+ bidId: '1a2b3c4d',
+ bidderRequestId: '11a22b33c44d',
+ auctionId: '1aa2bb3cc4dd',
+ schain: SAMPLE_SCHAIN
+ }
+ ];
+
const DEFAULT_BANNER_VALID_BID_PARAM_NO_SIZE = [
{
bidder: 'ix',
@@ -735,6 +764,49 @@ describe('IndexexchangeAdapter', function () {
}
};
+ const DEFAULT_OPTION_FLEDGE_ENABLED_GLOBALLY = {
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: '3huaa11=qu3198ae',
+ vendorData: {}
+ },
+ refererInfo: {
+ page: 'https://www.prebid.org',
+ canonicalUrl: 'https://www.prebid.org/the/link/to/the/page'
+ },
+ ortb2: {
+ site: {
+ page: 'https://www.prebid.org'
+ },
+ source: {
+ tid: 'mock-tid'
+ }
+ },
+ fledgeEnabled: true,
+ defaultForSlots: 1
+ };
+
+ const DEFAULT_OPTION_FLEDGE_ENABLED = {
+ gdprConsent: {
+ gdprApplies: true,
+ consentString: '3huaa11=qu3198ae',
+ vendorData: {}
+ },
+ refererInfo: {
+ page: 'https://www.prebid.org',
+ canonicalUrl: 'https://www.prebid.org/the/link/to/the/page'
+ },
+ ortb2: {
+ site: {
+ page: 'https://www.prebid.org'
+ },
+ source: {
+ tid: 'mock-tid'
+ }
+ },
+ fledgeEnabled: true
+ };
+
const DEFAULT_IDENTITY_RESPONSE = {
IdentityIp: {
responsePending: false,
@@ -759,7 +831,10 @@ describe('IndexexchangeAdapter', function () {
// similar to uid2, but id5's getValue takes .uid
id5id: { uid: 'testid5id' }, // ID5
imuid: 'testimuid',
- '33acrossId': { envelope: 'v1.5fs.1000.fjdiosmclds' }
+ '33acrossId': { envelope: 'v1.5fs.1000.fjdiosmclds' },
+ 'criteoID': { envelope: 'testcriteoID' },
+ 'euidID': { envelope: 'testeuid' },
+ pairId: {envelope: 'testpairId'}
};
const DEFAULT_USERID_PAYLOAD = [
@@ -818,6 +893,21 @@ describe('IndexexchangeAdapter', function () {
uids: [{
id: DEFAULT_USERID_DATA['33acrossId'].envelope
}]
+ }, {
+ source: 'criteo.com',
+ uids: [{
+ id: DEFAULT_USERID_DATA['criteoID'].envelope
+ }]
+ }, {
+ source: 'euid.eu',
+ uids: [{
+ id: DEFAULT_USERID_DATA['euidID'].envelope
+ }]
+ }, {
+ source: 'google.com',
+ uids: [{
+ id: DEFAULT_USERID_DATA['pairId'].envelope
+ }]
}
];
@@ -1224,7 +1314,7 @@ describe('IndexexchangeAdapter', function () {
const payload = extractPayload(request[0]);
expect(request).to.be.an('array');
expect(request).to.have.lengthOf.above(0); // should be 1 or more
- expect(payload.user.eids).to.have.lengthOf(8);
+ expect(payload.user.eids).to.have.lengthOf(11);
expect(payload.user.eids).to.deep.include(DEFAULT_USERID_PAYLOAD[0]);
});
});
@@ -1412,7 +1502,7 @@ describe('IndexexchangeAdapter', function () {
cloneValidBid[0].userIdAsEids = utils.deepClone(DEFAULT_USERIDASEIDS_DATA);
const request = spec.buildRequests(cloneValidBid, DEFAULT_OPTION)[0];
const payload = extractPayload(request);
- expect(payload.user.eids).to.have.lengthOf(8);
+ expect(payload.user.eids).to.have.lengthOf(11);
expect(payload.user.eids).to.have.deep.members(DEFAULT_USERID_PAYLOAD);
});
@@ -1545,7 +1635,7 @@ describe('IndexexchangeAdapter', function () {
})
expect(payload.user).to.exist;
- expect(payload.user.eids).to.have.lengthOf(10);
+ expect(payload.user.eids).to.have.lengthOf(13);
expect(payload.user.eids).to.have.deep.members(validUserIdPayload);
});
@@ -1587,7 +1677,7 @@ describe('IndexexchangeAdapter', function () {
});
const payload = extractPayload(request);
- expect(payload.user.eids).to.have.lengthOf(9);
+ expect(payload.user.eids).to.have.lengthOf(12);
expect(payload.user.eids).to.have.deep.members(validUserIdPayload);
});
});
@@ -3140,6 +3230,149 @@ describe('IndexexchangeAdapter', function () {
});
});
+ describe('buildRequestFledge', function () {
+ it('impression should have ae=1 in ext when fledge module is enabled and ae is set in ad unit', function () {
+ const bidderRequest = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED);
+ const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED[0]);
+ const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0];
+ const impression = extractPayload(requestBidFloor).imp[0];
+
+ expect(impression.ext.ae).to.equal(1);
+ });
+
+ it('impression should have ae=1 in ext when fledge module is enabled globally and default is set through setConfig', function () {
+ const bidderRequest = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED_GLOBALLY);
+ const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
+ const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0];
+ const impression = extractPayload(requestBidFloor).imp[0];
+
+ expect(impression.ext.ae).to.equal(1);
+ });
+
+ it('impression should have ae=1 in ext when fledge module is enabled globally but no default set through setConfig but set at ad unit level', function () {
+ const bidderRequest = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED);
+ const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED[0]);
+ const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0];
+ const impression = extractPayload(requestBidFloor).imp[0];
+
+ expect(impression.ext.ae).to.equal(1);
+ });
+
+ it('impression should not have ae=1 in ext when fledge module is enabled globally through setConfig but overidden at ad unit level', function () {
+ const bidderRequest = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED);
+ const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
+ const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0];
+ const impression = extractPayload(requestBidFloor).imp[0];
+
+ expect(impression.ext.ae).to.be.undefined;
+ });
+
+ it('impression should not have ae=1 in ext when fledge module is disabled', function () {
+ const bidderRequest = deepClone(DEFAULT_OPTION);
+ const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
+ const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0];
+ const impression = extractPayload(requestBidFloor).imp[0];
+
+ expect(impression.ext.ae).to.be.undefined;
+ });
+
+ it('should contain correct IXdiag ae property for Fledge', function () {
+ const bid = DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED[0];
+ const bidderRequestWithFledgeEnabled = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED);
+ const request = spec.buildRequests([bid], bidderRequestWithFledgeEnabled);
+ const diagObj = extractPayload(request[0]).ext.ixdiag;
+ expect(diagObj.ae).to.equal(true);
+ });
+
+ it('should log warning for non integer auction environment in ad unit for fledge', () => {
+ const logWarnSpy = sinon.spy(utils, 'logWarn');
+ const bid = DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED[0];
+ bid.ortb2Imp.ext.ae = 'malformed'
+ const bidderRequestWithFledgeEnabled = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED);
+ spec.buildRequests([bid], bidderRequestWithFledgeEnabled);
+ expect(logWarnSpy.calledWith('error setting auction environment flag - must be an integer')).to.be.true;
+ logWarnSpy.restore();
+ });
+ });
+
+ describe('integration through exchangeId and externalId', function () {
+ const expectedExchangeId = 123456;
+ // create banner bids with externalId but no siteId as bidder param
+ const bannerBids = utils.deepClone(DEFAULT_BANNER_VALID_BID);
+ delete bannerBids[0].params.siteId;
+ bannerBids[0].params.externalId = 'exteranl_id_1';
+
+ beforeEach(() => {
+ config.setConfig({ exchangeId: expectedExchangeId });
+ spec.resetSiteID();
+ });
+
+ afterEach(() => {
+ config.resetConfig();
+ });
+
+ it('when exchangeId and externalId set but no siteId, isBidRequestValid should return true', function () {
+ const bid = utils.deepClone(bannerBids[0]);
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+
+ it('when neither exchangeId nor siteId set, isBidRequestValid should return false', function () {
+ config.resetConfig();
+ const bid = utils.deepClone(bannerBids[0]);
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+
+ it('when exchangeId and externalId set with banner impression but no siteId, bidrequest sent to endpoint with p param and externalID inside imp.ext', function () {
+ const requests = spec.buildRequests(bannerBids, DEFAULT_OPTION);
+ const payload = extractPayload(requests[0]);
+
+ const expectedURL = IX_SECURE_ENDPOINT + '?p=' + expectedExchangeId;
+ expect(requests[0].url).to.equal(expectedURL);
+ expect(payload.imp[0].ext.externalID).to.equal(bannerBids[0].params.externalId);
+ expect(payload.imp[0].banner.format[0].ext).to.be.undefined;
+ expect(payload.imp[0].ext.siteID).to.be.undefined;
+ });
+
+ it('when exchangeId and externalId set with video impression, bidrequest sent to endpoint with p param and externalID inside imp.ext', function () {
+ const validBids = utils.deepClone(DEFAULT_VIDEO_VALID_BID);
+ delete validBids[0].params.siteId;
+ validBids[0].params.externalId = 'exteranl_id_1';
+
+ const requests = spec.buildRequests(validBids, DEFAULT_OPTION);
+ const payload = extractPayload(requests[0]);
+
+ const expectedURL = IX_SECURE_ENDPOINT + '?p=' + expectedExchangeId;
+ expect(requests[0].url).to.equal(expectedURL);
+ expect(payload.imp[0].ext.externalID).to.equal(validBids[0].params.externalId);
+ expect(payload.imp[0].ext.siteID).to.be.undefined;
+ });
+
+ it('when exchangeId and externalId set beside siteId, bidrequest sent to endpoint with both p param and s param and externalID inside imp.ext and siteID inside imp.banner.format.ext', function () {
+ bannerBids[0].params.siteId = '1234';
+ const requests = spec.buildRequests(bannerBids, DEFAULT_OPTION);
+ const payload = extractPayload(requests[0]);
+
+ const expectedURL = IX_SECURE_ENDPOINT + '?s=' + bannerBids[0].params.siteId + '&p=' + expectedExchangeId;
+ expect(requests[0].url).to.equal(expectedURL);
+ expect(payload.imp[0].ext.externalID).to.equal(bannerBids[0].params.externalId);
+ expect(payload.imp[0].banner.format[0].ext.externalID).to.be.undefined;
+ expect(payload.imp[0].ext.siteID).to.be.undefined;
+ expect(payload.imp[0].banner.format[0].ext.siteID).to.equal(bannerBids[0].params.siteId);
+ });
+
+ it('when exchangeId and siteId set, but no externalId, bidrequest sent to exchange', function () {
+ bannerBids[0].params.siteId = '1234';
+ delete bannerBids[0].params.externalId;
+ const requests = spec.buildRequests(bannerBids, DEFAULT_OPTION);
+ const payload = extractPayload(requests[0]);
+
+ const expectedURL = IX_SECURE_ENDPOINT + '?s=' + bannerBids[0].params.siteId + '&p=' + expectedExchangeId;
+ expect(requests[0].url).to.equal(expectedURL);
+ expect(payload.imp[0].ext.externalID).to.be.undefined;
+ expect(payload.imp[0].banner.format[0].ext.siteID).to.equal(bannerBids[0].params.siteId);
+ });
+ });
+
describe('interpretResponse', function () {
// generate bidderRequest with real buildRequest logic for intepretResponse testing
let bannerBidderRequest
@@ -3663,6 +3896,140 @@ describe('IndexexchangeAdapter', function () {
const result = spec.interpretResponse({ body: DEFAULT_NATIVE_BID_RESPONSE }, nativeBidderRequest);
expect(result[0]).to.deep.equal(expectedParse[0]);
});
+
+ describe('Auction config response', function () {
+ let bidderRequestWithFledgeEnabled;
+ let serverResponseWithoutFledgeConfigs;
+ let serverResponseWithFledgeConfigs;
+ let serverResponseWithMalformedAuctionConfig;
+ let serverResponseWithMalformedAuctionConfigs;
+
+ beforeEach(() => {
+ bidderRequestWithFledgeEnabled = spec.buildRequests(DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED, {})[0];
+ bidderRequestWithFledgeEnabled.fledgeEnabled = true;
+
+ serverResponseWithoutFledgeConfigs = {
+ body: {
+ ...DEFAULT_BANNER_BID_RESPONSE
+ }
+ };
+
+ serverResponseWithFledgeConfigs = {
+ body: {
+ ...DEFAULT_BANNER_BID_RESPONSE,
+ ext: {
+ protectedAudienceAuctionConfigs: [
+ {
+ bidId: '59f219e54dc2fc',
+ config: {
+ seller: 'https://seller.test.indexexchange.com',
+ decisionLogicUrl: 'https://seller.test.indexexchange.com/decision-logic.js',
+ interestGroupBuyers: ['https://buyer.test.indexexchange.com'],
+ sellerSignals: {
+ callbackURL: 'https://test.com/ig/v1/ck74j8bcvc9c73a8eg6g'
+ },
+ perBuyerSignals: {
+ 'https://buyer.test.indexexchange.com': {}
+ }
+ }
+ }
+ ]
+ }
+ }
+ };
+
+ serverResponseWithMalformedAuctionConfig = {
+ body: {
+ ...DEFAULT_BANNER_BID_RESPONSE,
+ ext: {
+ protectedAudienceAuctionConfigs: ['malformed']
+ }
+ }
+ };
+
+ serverResponseWithMalformedAuctionConfigs = {
+ body: {
+ ...DEFAULT_BANNER_BID_RESPONSE,
+ ext: {
+ protectedAudienceAuctionConfigs: 'malformed'
+ }
+ }
+ };
+ });
+
+ it('should correctly interpret response with auction configs', () => {
+ const result = spec.interpretResponse(serverResponseWithFledgeConfigs, bidderRequestWithFledgeEnabled);
+ const expectedOutput = [
+ {
+ bidId: '59f219e54dc2fc',
+ config: {
+ ...serverResponseWithFledgeConfigs.body.ext.protectedAudienceAuctionConfigs[0].config,
+ perBuyerSignals: {
+ 'https://buyer.test.indexexchange.com': {}
+ }
+ }
+ }
+ ];
+ expect(result.fledgeAuctionConfigs).to.deep.equal(expectedOutput);
+ });
+
+ it('should correctly interpret response without auction configs', () => {
+ const result = spec.interpretResponse(serverResponseWithoutFledgeConfigs, bidderRequestWithFledgeEnabled);
+ expect(result.fledgeAuctionConfigs).to.be.undefined;
+ });
+
+ it('should handle malformed auction configs gracefully', () => {
+ const result = spec.interpretResponse(serverResponseWithMalformedAuctionConfig, bidderRequestWithFledgeEnabled);
+ expect(result.fledgeAuctionConfigs).to.be.empty;
+ });
+
+ it('should log warning for malformed auction configs', () => {
+ const logWarnSpy = sinon.spy(utils, 'logWarn');
+ spec.interpretResponse(serverResponseWithMalformedAuctionConfig, bidderRequestWithFledgeEnabled);
+ expect(logWarnSpy.calledWith('Malformed auction config detected:', 'malformed')).to.be.true;
+ logWarnSpy.restore();
+ });
+
+ it('should return bids when protected audience auction conigs is malformed', () => {
+ const result = spec.interpretResponse(serverResponseWithMalformedAuctionConfigs, bidderRequestWithFledgeEnabled);
+ expect(result.fledgeAuctionConfigs).to.be.undefined;
+ expect(result.length).to.be.greaterThan(0);
+ });
+ });
+
+ describe('interpretResponse when server response is empty', function() {
+ let serverResponseWithoutBody;
+ let serverResponseWithoutSeatbid;
+ let bidderRequestWithFledgeEnabled;
+ let bidderRequestWithoutFledgeEnabled;
+
+ beforeEach(() => {
+ serverResponseWithoutBody = {};
+
+ serverResponseWithoutSeatbid = {
+ body: {}
+ };
+
+ bidderRequestWithFledgeEnabled = spec.buildRequests(DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED, {})[0];
+ bidderRequestWithFledgeEnabled.fledgeEnabled = true;
+
+ bidderRequestWithoutFledgeEnabled = spec.buildRequests(DEFAULT_BANNER_VALID_BID, {})[0];
+ });
+
+ it('should return empty bids when response does not have body', function () {
+ let result = spec.interpretResponse(serverResponseWithoutBody, bidderRequestWithFledgeEnabled);
+ expect(result).to.deep.equal([]);
+ result = spec.interpretResponse(serverResponseWithoutBody, bidderRequestWithoutFledgeEnabled);
+ expect(result).to.deep.equal([]);
+ });
+
+ it('should return empty bids when response body does not have seatbid', function () {
+ let result = spec.interpretResponse(serverResponseWithoutSeatbid, bidderRequestWithFledgeEnabled);
+ expect(result).to.deep.equal([]);
+ result = spec.interpretResponse(serverResponseWithoutSeatbid, bidderRequestWithoutFledgeEnabled);
+ expect(result).to.deep.equal([]);
+ });
+ });
});
describe('bidrequest consent', function () {
diff --git a/test/spec/modules/jixieBidAdapter_spec.js b/test/spec/modules/jixieBidAdapter_spec.js
index 4a0fa3b4d57..fa7618814f8 100644
--- a/test/spec/modules/jixieBidAdapter_spec.js
+++ b/test/spec/modules/jixieBidAdapter_spec.js
@@ -2,6 +2,7 @@ import { expect } from 'chai';
import { spec, internal as jixieaux, storage } from 'modules/jixieBidAdapter.js';
import { newBidder } from 'src/adapters/bidderFactory.js';
import { config } from 'src/config.js';
+import { deepClone } from 'src/utils.js';
describe('jixie Adapter', function () {
const pageurl_ = 'https://testdomain.com/testpage.html';
@@ -74,13 +75,16 @@ describe('jixie Adapter', function () {
const jxtokoTest1_ = 'eyJJRCI6ImFiYyJ9';
const jxifoTest1_ = 'fffffbbbbbcccccaaaaae890606aaaaa';
const jxtdidTest1_ = '222223d1-1111-2222-3333-b9f129299999';
- const __uid2_advertising_token_Test1 = 'AAAAABBBBBCCCCCDDDDDEEEEEUkkZPQfifpkPnnlJhtsa4o+gf4nfqgN5qHiTVX73ymTSbLT9jz1nf+Q7QdxNh9nTad9UaN5pzfHMt/rs1woQw72c1ip+8heZXPfKGZtZP7ldJesYhlo3/0FVcL/wl9ZlAo1jYOEfHo7Y9zFzNXABbbbbb==';
-
+ const jxcompTest1_ = 'AAAAABBBBBCCCCCDDDDDEEEEEUkkZPQfifpkPnnlJhtsa4o+gf4nfqgN5qHiTVX73ymTSbLT9jz1nf+Q7QdxNh9nTad9UaN5pzfHMt/rs1woQw72c1ip+8heZXPfKGZtZP7ldJesYhlo3/0FVcL/wl9ZlAo1jYOEfHo7Y9zFzNXABbbbbb==';
+ const ckname1Val_ = 'ckckname1';
+ const ckname2Val_ = 'ckckname2';
const refJxEids_ = {
+ 'pubid1': ckname1Val_,
+ 'pubid2': ckname2Val_,
'_jxtoko': jxtokoTest1_,
'_jxifo': jxifoTest1_,
'_jxtdid': jxtdidTest1_,
- '__uid2_advertising_token': __uid2_advertising_token_Test1
+ '_jxcomp': jxcompTest1_
};
// to serve as the object that prebid will call jixie buildRequest with: (param2)
@@ -205,6 +209,17 @@ describe('jixie Adapter', function () {
}
];
+ const testJixieCfg_ = {
+ genids: [
+ { id: 'pubid1', ck: 'ckname1' },
+ { id: 'pubid2', ck: 'ckname2' },
+ { id: '_jxtoko' },
+ { id: '_jxifo' },
+ { id: '_jxtdid' },
+ { id: '_jxcomp' }
+ ]
+ };
+
it('should attach valid params to the adserver endpoint (1)', function () {
// this one we do not intercept the cookie stuff so really don't know
// what will be in there. so we do not check here (using expect)
@@ -215,7 +230,6 @@ describe('jixie Adapter', function () {
})
expect(request.data).to.be.an('string');
const payload = JSON.parse(request.data);
- expect(payload).to.have.property('auctionid', auctionId_);
expect(payload).to.have.property('timeout', timeout_);
expect(payload).to.have.property('currency', currency_);
expect(payload).to.have.property('bids').that.deep.equals(refBids_);
@@ -225,8 +239,25 @@ describe('jixie Adapter', function () {
// similar to above test case but here we force some clientid sessionid values
// and domain, pageurl
// get the interceptors ready:
+ let getConfigStub = sinon.stub(config, 'getConfig');
+ getConfigStub.callsFake(function fakeFn(prop) {
+ if (prop == 'jixie') {
+ return testJixieCfg_;
+ }
+ return null;
+ });
+
let getCookieStub = sinon.stub(storage, 'getCookie');
let getLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage');
+ getCookieStub
+ .withArgs('ckname1')
+ .returns(ckname1Val_);
+ getCookieStub
+ .withArgs('ckname2')
+ .returns(ckname2Val_);
+ getCookieStub
+ .withArgs('_jxtoko')
+ .returns(jxtokoTest1_);
getCookieStub
.withArgs('_jxtoko')
.returns(jxtokoTest1_);
@@ -237,8 +268,8 @@ describe('jixie Adapter', function () {
.withArgs('_jxtdid')
.returns(jxtdidTest1_);
getCookieStub
- .withArgs('__uid2_advertising_token')
- .returns(__uid2_advertising_token_Test1);
+ .withArgs('_jxcomp')
+ .returns(jxcompTest1_);
getCookieStub
.withArgs('_jxx')
.returns(clientIdTest1_);
@@ -264,7 +295,6 @@ describe('jixie Adapter', function () {
expect(request.data).to.be.an('string');
const payload = JSON.parse(request.data);
- expect(payload).to.have.property('auctionid', auctionId_);
expect(payload).to.have.property('client_id_c', clientIdTest1_);
expect(payload).to.have.property('client_id_ls', clientIdTest1_);
expect(payload).to.have.property('session_id_c', sessionIdTest1_);
@@ -281,6 +311,7 @@ describe('jixie Adapter', function () {
// unwire interceptors
getCookieStub.restore();
getLocalStorageStub.restore();
+ getConfigStub.restore();
miscDimsStub.restore();
});// it
@@ -345,6 +376,43 @@ describe('jixie Adapter', function () {
expect(payload.schain).to.deep.include(schain);
});
+ it('it should populate the floor info when available', function () {
+ let oneSpecialBidReq = deepClone(bidRequests_[0]);
+ let request, payload = null;
+ // 1 floor is not set
+ request = spec.buildRequests([oneSpecialBidReq], bidderRequest_);
+ payload = JSON.parse(request.data);
+ expect(payload.bids[0].bidFloor).to.not.exist;
+
+ // 2 floor is set
+ let getFloorResponse = { currency: 'USD', floor: 2.1 };
+ oneSpecialBidReq.getFloor = () => getFloorResponse;
+ request = spec.buildRequests([oneSpecialBidReq], bidderRequest_);
+ payload = JSON.parse(request.data);
+ expect(payload.bids[0].bidFloor).to.exist.and.to.equal(2.1);
+ });
+
+ it('it should populate the aid field when available', function () {
+ let oneSpecialBidReq = deepClone(bidRequests_[0]);
+ // 1 aid is not set in the jixie config
+ let request = spec.buildRequests([oneSpecialBidReq], bidderRequest_);
+ let payload = JSON.parse(request.data);
+ expect(payload.aid).to.eql('');
+
+ // 2 aid is set in the jixie config
+ let getConfigStub = sinon.stub(config, 'getConfig');
+ getConfigStub.callsFake(function fakeFn(prop) {
+ if (prop == 'jixie') {
+ return { aid: '11223344556677889900' };
+ }
+ return null;
+ });
+ request = spec.buildRequests([oneSpecialBidReq], bidderRequest_);
+ payload = JSON.parse(request.data);
+ expect(payload.aid).to.exist.and.to.equal('11223344556677889900');
+ getConfigStub.restore();
+ });
+
it('should populate eids when supported userIds are available', function () {
const oneSpecialBidReq = Object.assign({}, bidRequests_[0], {
userIdAsEids: [
@@ -408,7 +476,6 @@ describe('jixie Adapter', function () {
'bids': [
// video (vast tag url) returned here
{
- 'trackingUrlBase': 'https://traid.jixie.io/sync/ad?',
'jxBidId': '62847e4c696edcb-028d5dee-2c83-44e3-bed1-b75002475cdf',
'requestId': '62847e4c696edcb',
'cpm': 2.19,
@@ -441,7 +508,6 @@ describe('jixie Adapter', function () {
// display ad returned here: This one there is advertiserDomains
// in the response . Will be checked in the unit tests below
{
- 'trackingUrlBase': 'https://traid.jixie.io/sync/ad?',
'jxBidId': '600c9ae6fda1acb-028d5dee-2c83-44e3-bed1-b75002475cdf',
'requestId': '600c9ae6fda1acb',
'cpm': 1.999,
@@ -478,7 +544,6 @@ describe('jixie Adapter', function () {
},
// outstream, jx non-default renderer specified:
{
- 'trackingUrlBase': 'https://traid.jixie.io/sync/ad?',
'jxBidId': '99bc539c81b00ce-028d5dee-2c83-44e3-bed1-b75002475cdf',
'requestId': '99bc539c81b00ce',
'cpm': 2.99,
@@ -497,7 +562,6 @@ describe('jixie Adapter', function () {
},
// outstream, jx default renderer:
{
- 'trackingUrlBase': 'https://traid.jixie.io/sync/ad?',
'jxBidId': '61bc539c81b00ce-028d5dee-2c83-44e3-bed1-b75002475cdf',
'requestId': '61bc539c81b00ce',
'cpm': 1.99,
@@ -568,7 +632,6 @@ describe('jixie Adapter', function () {
expect(result[0].netRevenue).to.equal(true)
expect(result[0].ttl).to.equal(300)
expect(result[0].vastUrl).to.include('https://ad.jixie.io/v1/video?creativeid=')
- expect(result[0].trackingUrlBase).to.include('sync')
// We will always make sure the meta->advertiserDomains property is there
// If no info it is an empty array.
expect(result[0].meta.advertiserDomains.length).to.equal(0)
@@ -584,7 +647,6 @@ describe('jixie Adapter', function () {
expect(result[1].ttl).to.equal(300)
expect(result[1].ad).to.include('jxoutstream')
expect(result[1].meta.advertiserDomains.length).to.equal(3)
- expect(result[1].trackingUrlBase).to.include('sync')
// should pick up about using alternative outstream renderer
expect(result[2].requestId).to.equal('99bc539c81b00ce')
@@ -596,7 +658,6 @@ describe('jixie Adapter', function () {
expect(result[2].netRevenue).to.equal(true)
expect(result[2].ttl).to.equal(300)
expect(result[2].vastXml).to.include('')
- expect(result[2].trackingUrlBase).to.include('sync');
expect(result[2].renderer.id).to.equal('demoslot4-div')
expect(result[2].meta.advertiserDomains.length).to.equal(0)
expect(result[2].renderer.url).to.equal(JX_OTHER_OUTSTREAM_RENDERER_URL);
@@ -611,7 +672,6 @@ describe('jixie Adapter', function () {
expect(result[3].netRevenue).to.equal(true)
expect(result[3].ttl).to.equal(300)
expect(result[3].vastXml).to.include('')
- expect(result[3].trackingUrlBase).to.include('sync');
expect(result[3].renderer.id).to.equal('demoslot2-div')
expect(result[3].meta.advertiserDomains.length).to.equal(0)
expect(result[3].renderer.url).to.equal(JX_OUTSTREAM_RENDERER_URL)
@@ -646,116 +706,5 @@ describe('jixie Adapter', function () {
spec.onBidWon({ trackingUrl: TRACKINGURL_ })
expect(jixieaux.ajax.calledWith(TRACKINGURL_)).to.equal(true);
})
-
- it('Should not fire if the adserver response indicates no firing', function() {
- let called = false;
- ajaxStub.callsFake(function fakeFn() {
- called = true;
- });
- spec.onBidWon({ notrack: 1 })
- expect(called).to.equal(false);
- });
-
- // A reference to check again:
- const QPARAMS_ = {
- action: 'hbbidwon',
- device: device_,
- pageurl: encodeURIComponent(pageurl_),
- domain: encodeURIComponent(domain_),
- cid: 121,
- cpid: 99,
- jxbidid: '62847e4c696edcb-028d5dee-2c83-44e3-bed1-b75002475cdf',
- auctionid: '028d5dee-2c83-44e3-bed1-b75002475cdf',
- cpm: 1.11,
- requestid: '62847e4c696edcb'
- };
-
- it('check it is sending the correct ajax url and qparameters', function() {
- spec.onBidWon({
- trackingUrlBase: 'https://mytracker.com/sync?',
- cid: 121,
- cpid: 99,
- jxBidId: '62847e4c696edcb-028d5dee-2c83-44e3-bed1-b75002475cdf',
- auctionId: '028d5dee-2c83-44e3-bed1-b75002475cdf',
- cpm: 1.11,
- requestId: '62847e4c696edcb'
- })
- expect(jixieaux.ajax.calledWith('https://mytracker.com/sync?', null, QPARAMS_)).to.equal(true);
- });
}); // describe
-
- /**
- * onTimeout
- */
- describe('onTimeout', function() {
- let ajaxStub;
- let miscDimsStub;
- beforeEach(function() {
- ajaxStub = sinon.stub(jixieaux, 'ajax');
- miscDimsStub = sinon.stub(jixieaux, 'getMiscDims');
- miscDimsStub
- .returns({ device: device_, pageurl: pageurl_, domain: domain_, mkeywords: keywords_ });
- })
-
- afterEach(function() {
- miscDimsStub.restore();
- ajaxStub.restore();
- })
-
- // reference to check against:
- const QPARAMS_ = {
- action: 'hbtimeout',
- device: device_,
- pageurl: encodeURIComponent(pageurl_),
- domain: encodeURIComponent(domain_),
- auctionid: '028d5dee-2c83-44e3-bed1-b75002475cdf',
- timeout: 1000,
- count: 2
- };
-
- it('check it is sending the correct ajax url and qparameters', function() {
- spec.onTimeout([
- {auctionId: '028d5dee-2c83-44e3-bed1-b75002475cdf', timeout: 1000},
- {auctionId: '028d5dee-2c83-44e3-bed1-b75002475cdf', timeout: 1000}
- ])
- expect(jixieaux.ajax.calledWith(spec.EVENTS_URL, null, QPARAMS_)).to.equal(true);
- })
-
- it('if turned off via config then dont do onTimeout sending of event', function() {
- let getConfigStub = sinon.stub(config, 'getConfig');
- getConfigStub.callsFake(function fakeFn(prop) {
- if (prop == 'jixie') {
- return { onTimeout: 'off' };
- }
- return null;
- });
- let called = false;
- ajaxStub.callsFake(function fakeFn() {
- called = true;
- });
- spec.onTimeout([
- {auctionId: '028d5dee-2c83-44e3-bed1-b75002475cdf', timeout: 1000},
- {auctionId: '028d5dee-2c83-44e3-bed1-b75002475cdf', timeout: 1000}
- ])
- expect(called).to.equal(false);
- getConfigStub.restore();
- })
-
- const otherUrl_ = 'https://other.azurewebsites.net/sync/evt?';
- it('if config specifies a different endpoint then should send there instead', function() {
- let getConfigStub = sinon.stub(config, 'getConfig');
- getConfigStub.callsFake(function fakeFn(prop) {
- if (prop == 'jixie') {
- return { onTimeoutUrl: otherUrl_ };
- }
- return null;
- });
- spec.onTimeout([
- {auctionId: '028d5dee-2c83-44e3-bed1-b75002475cdf', timeout: 1000},
- {auctionId: '028d5dee-2c83-44e3-bed1-b75002475cdf', timeout: 1000}
- ])
- expect(jixieaux.ajax.calledWith(otherUrl_, null, QPARAMS_)).to.equal(true);
- getConfigStub.restore();
- })
- });// describe
});
diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js
index 9f7a4854063..f43c3b11aac 100644
--- a/test/spec/modules/kargoBidAdapter_spec.js
+++ b/test/spec/modules/kargoBidAdapter_spec.js
@@ -142,6 +142,27 @@ describe('kargo adapter tests', function () {
model: 'model',
source: 1,
}
+ },
+ site: {
+ id: '1234',
+ name: 'SiteName',
+ cat: ['IAB1', 'IAB2', 'IAB3']
+ },
+ user: {
+ data: [
+ {
+ name: 'prebid.org',
+ ext: {
+ segtax: 600,
+ segclass: 'v1',
+ },
+ segment: [
+ {
+ id: '133'
+ },
+ ]
+ },
+ ]
}
},
ortb2Imp: {
@@ -150,9 +171,9 @@ describe('kargo adapter tests', function () {
data: {
adServer: {
name: 'gam',
- adSlot: '/22558409563,18834096/dfy_mobile_adhesion'
+ adslot: '/22558409563,18834096/dfy_mobile_adhesion'
},
- pbAdSlot: '/22558409563,18834096/dfy_mobile_adhesion'
+ pbadslot: '/22558409563,18834096/dfy_mobile_adhesion'
},
gpid: '/22558409563,18834096/dfy_mobile_adhesion'
}
@@ -179,9 +200,9 @@ describe('kargo adapter tests', function () {
data: {
adServer: {
name: 'gam',
- adSlot: '/22558409563,18834096/dfy_mobile_adhesion'
+ adslot: '/22558409563,18834096/dfy_mobile_adhesion'
},
- pbAdSlot: '/22558409563,18834096/dfy_mobile_adhesion'
+ pbadslot: '/22558409563,18834096/dfy_mobile_adhesion'
}
}
}
@@ -204,9 +225,10 @@ describe('kargo adapter tests', function () {
data: {
adServer: {
name: 'gam',
- adSlot: '/22558409563,18834096/dfy_mobile_adhesion'
+ adslot: '/22558409563,18834096/dfy_mobile_adhesion'
}
- }
+ },
+ gpid: '/22558409563,18834096/dfy_mobile_adhesion'
}
}
}
@@ -439,6 +461,9 @@ describe('kargo adapter tests', function () {
source: 1
},
},
+ site: {
+ cat: ['IAB1', 'IAB2', 'IAB3']
+ },
imp: [
{
code: '101',
@@ -513,6 +538,20 @@ describe('kargo adapter tests', function () {
}
]
}
+ ],
+ data: [
+ {
+ name: 'prebid.org',
+ ext: {
+ segtax: 600,
+ segclass: 'v1',
+ },
+ segment: [
+ {
+ id: '133'
+ }
+ ]
+ }
]
}
};
diff --git a/test/spec/modules/kulturemediaBidAdapter_spec.js b/test/spec/modules/kulturemediaBidAdapter_spec.js
deleted file mode 100644
index f21fe4a8810..00000000000
--- a/test/spec/modules/kulturemediaBidAdapter_spec.js
+++ /dev/null
@@ -1,612 +0,0 @@
-import {expect} from 'chai';
-import {spec} from 'modules/kulturemediaBidAdapter.js';
-
-const BANNER_REQUEST = {
- 'bidderCode': 'kulturemedia',
- 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708',
- 'bidderRequestId': 'requestId',
- 'bidRequest': [{
- 'bidder': 'kulturemedia',
- 'params': {
- 'placementId': 123456,
- },
- 'placementCode': 'div-gpt-dummy-placement-code',
- 'mediaTypes': {'banner': {'sizes': [[300, 250]]}},
- 'bidId': 'bidId1',
- 'bidderRequestId': 'bidderRequestId',
- 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708'
- },
- {
- 'bidder': 'kulturemedia',
- 'params': {
- 'placementId': 123456,
- },
- 'placementCode': 'div-gpt-dummy-placement-code',
- 'mediaTypes': {'banner': {'sizes': [[300, 250]]}},
- 'bidId': 'bidId2',
- 'bidderRequestId': 'bidderRequestId',
- 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708'
- }],
- 'start': 1487883186070,
- 'auctionStart': 1487883186069,
- 'timeout': 3000
-};
-
-const RESPONSE = {
- 'headers': null,
- 'body': {
- 'id': 'responseId',
- 'seatbid': [
- {
- 'bid': [
- {
- 'id': 'bidId1',
- 'impid': 'bidId1',
- 'price': 0.18,
- 'adm': '',
- 'adid': '144762342',
- 'adomain': [
- 'https://dummydomain.com'
- ],
- 'iurl': 'iurl',
- 'cid': '109',
- 'crid': 'creativeId',
- 'cat': [],
- 'w': 300,
- 'h': 250,
- 'ext': {
- 'prebid': {
- 'type': 'banner'
- },
- 'bidder': {
- 'appnexus': {
- 'brand_id': 334553,
- 'auction_id': 514667951122925701,
- 'bidder_id': 2,
- 'bid_ad_type': 0
- }
- }
- }
- },
- {
- 'id': 'bidId2',
- 'impid': 'bidId2',
- 'price': 0.1,
- 'adm': '',
- 'adid': '144762342',
- 'adomain': [
- 'https://dummydomain.com'
- ],
- 'iurl': 'iurl',
- 'cid': '109',
- 'crid': 'creativeId',
- 'cat': [],
- 'w': 300,
- 'h': 250,
- 'ext': {
- 'prebid': {
- 'type': 'banner'
- },
- 'bidder': {
- 'appnexus': {
- 'brand_id': 386046,
- 'auction_id': 517067951122925501,
- 'bidder_id': 2,
- 'bid_ad_type': 0
- }
- }
- }
- }
- ],
- 'seat': 'kulturemedia'
- }
- ],
- 'ext': {
- 'usersync': {
- 'sovrn': {
- 'status': 'none',
- 'syncs': [
- {
- 'url': 'urlsovrn',
- 'type': 'iframe'
- }
- ]
- },
- 'appnexus': {
- 'status': 'none',
- 'syncs': [
- {
- 'url': 'urlappnexus',
- 'type': 'pixel'
- }
- ]
- }
- },
- 'responsetimemillis': {
- 'appnexus': 127
- }
- }
- }
-};
-
-const DEFAULT_NETWORK_ID = 1;
-
-describe('kulturemediaBidAdapter:', function () {
- let videoBidRequest;
-
- const VIDEO_REQUEST = {
- 'bidderCode': 'kulturemedia',
- 'auctionId': 'e158486f-8c7f-472f-94ce-b0cbfbb50ab4',
- 'bidderRequestId': '34feaad34lkj2',
- 'bids': videoBidRequest,
- 'auctionStart': 1520001292880,
- 'timeout': 3000,
- 'start': 1520001292884,
- 'doneCbCallCount': 0,
- 'refererInfo': {
- 'numIframes': 1,
- 'reachedTop': true,
- 'referer': 'test.com'
- }
- };
-
- beforeEach(function () {
- videoBidRequest = {
- mediaTypes: {
- video: {
- context: 'instream',
- playerSize: [[640, 480]],
- }
- },
- bidder: 'kulturemedia',
- sizes: [640, 480],
- bidId: '30b3efwfwe1e',
- adUnitCode: 'video1',
- params: {
- video: {
- playerWidth: 640,
- playerHeight: 480,
- mimes: ['video/mp4', 'application/javascript'],
- protocols: [2, 5],
- api: [2],
- position: 1,
- delivery: [2],
- sid: 134,
- rewarded: 1,
- placement: 1,
- hp: 1,
- inventoryid: 123
- },
- site: {
- id: 1,
- page: 'https://test.com',
- referrer: 'http://test.com'
- },
- publisherId: 'km123'
- }
- };
- });
-
- describe('isBidRequestValid', function () {
- context('basic validation', function () {
- beforeEach(function () {
- // Basic Valid BidRequest
- this.bid = {
- bidder: 'kulturemedia',
- mediaTypes: {
- banner: {
- sizes: [[250, 300]]
- }
- },
- params: {
- placementId: 'placementId',
- publisherId: 'publisherId',
- }
- };
- });
-
- it('should accept request if placementId and publisherId are passed', function () {
- expect(spec.isBidRequestValid(this.bid)).to.be.true;
- });
-
- it('reject requests without params', function () {
- this.bid.params = {};
- expect(spec.isBidRequestValid(this.bid)).to.be.false;
- });
-
- it('returns false when banner mediaType does not exist', function () {
- this.bid.mediaTypes = {}
- expect(spec.isBidRequestValid(this.bid)).to.be.false;
- });
- });
-
- context('banner validation', function () {
- it('returns true when banner sizes are defined', function () {
- const bid = {
- bidder: 'kulturemedia',
- mediaTypes: {
- banner: {
- sizes: [[250, 300]]
- }
- },
- params: {
- placementId: 'placementId',
- publisherId: 'publisherId',
- }
- };
-
- expect(spec.isBidRequestValid(bid)).to.be.true;
- });
-
- it('returns false when banner sizes are invalid', function () {
- const invalidSizes = [
- undefined,
- '2:1',
- 123,
- 'test'
- ];
-
- invalidSizes.forEach((sizes) => {
- const bid = {
- bidder: 'kulturemedia',
- mediaTypes: {
- banner: {
- sizes
- }
- },
- params: {
- placementId: 'placementId',
- publisherId: 'publisherId',
- }
- };
-
- expect(spec.isBidRequestValid(bid)).to.be.false;
- });
- });
- });
-
- context('video validation', function () {
- beforeEach(function () {
- // Basic Valid BidRequest
- this.bid = {
- bidder: 'kulturemedia',
- mediaTypes: {
- video: {
- playerSize: [[300, 50]],
- context: 'instream',
- mimes: ['foo', 'bar'],
- protocols: [1, 2]
- }
- },
- params: {
- placementId: 'placementId',
- publisherId: 'publisherId',
- }
- };
- });
-
- it('should return true (skip validations) when e2etest = true', function () {
- this.bid.params = {
- e2etest: true
- };
- expect(spec.isBidRequestValid(this.bid)).to.equal(true);
- });
-
- it('returns false when video context is not defined', function () {
- delete this.bid.mediaTypes.video.context;
-
- expect(spec.isBidRequestValid(this.bid)).to.be.false;
- });
-
- it('returns false when video playserSize is invalid', function () {
- const invalidSizes = [
- undefined,
- '2:1',
- 123,
- 'test'
- ];
-
- invalidSizes.forEach((playerSize) => {
- this.bid.mediaTypes.video.playerSize = playerSize;
- expect(spec.isBidRequestValid(this.bid)).to.be.false;
- });
- });
-
- it('returns false when video mimes is invalid', function () {
- const invalidMimes = [
- undefined,
- 'test',
- 1,
- []
- ]
-
- invalidMimes.forEach((mimes) => {
- this.bid.mediaTypes.video.mimes = mimes;
- expect(spec.isBidRequestValid(this.bid)).to.be.false;
- })
- });
-
- it('returns false when video protocols is invalid', function () {
- const invalidMimes = [
- undefined,
- 'test',
- 1,
- []
- ]
-
- invalidMimes.forEach((protocols) => {
- this.bid.mediaTypes.video.protocols = protocols;
- expect(spec.isBidRequestValid(this.bid)).to.be.false;
- })
- });
- });
- });
-
- describe('buildRequests', function () {
- context('when mediaType is banner', function () {
- it('creates request data', function () {
- let request = spec.buildRequests(BANNER_REQUEST.bidRequest, BANNER_REQUEST);
-
- expect(request).to.exist.and.to.be.a('object');
- const payload = JSON.parse(request.data);
- expect(payload.imp[0]).to.have.property('id', BANNER_REQUEST.bidRequest[0].bidId);
- expect(payload.imp[1]).to.have.property('id', BANNER_REQUEST.bidRequest[1].bidId);
- });
-
- it('has gdpr data if applicable', function () {
- const req = Object.assign({}, BANNER_REQUEST, {
- gdprConsent: {
- consentString: 'consentString',
- gdprApplies: true,
- }
- });
- let request = spec.buildRequests(BANNER_REQUEST.bidRequest, req);
-
- const payload = JSON.parse(request.data);
- expect(payload.user.ext).to.have.property('consent', req.gdprConsent.consentString);
- expect(payload.regs.ext).to.have.property('gdpr', 1);
- });
-
- it('should properly forward eids parameters', function () {
- const req = Object.assign({}, BANNER_REQUEST);
- req.bidRequest[0].userIdAsEids = [
- {
- source: 'dummy.com',
- uids: [
- {
- id: 'd6d0a86c-20c6-4410-a47b-5cba383a698a',
- atype: 1
- }
- ]
- }];
- let request = spec.buildRequests(req.bidRequest, req);
-
- const payload = JSON.parse(request.data);
- expect(payload.user.ext.eids[0].source).to.equal('dummy.com');
- expect(payload.user.ext.eids[0].uids[0].id).to.equal('d6d0a86c-20c6-4410-a47b-5cba383a698a');
- expect(payload.user.ext.eids[0].uids[0].atype).to.equal(1);
- });
- });
-
- context('when mediaType is video', function () {
- it('should create a POST request for every bid', function () {
- const requests = spec.buildRequests([videoBidRequest], VIDEO_REQUEST);
- expect(requests.method).to.equal('POST');
- expect(requests.url.trim()).to.equal(spec.ENDPOINT + '?pid=' + videoBidRequest.params.publisherId + '&nId=' + DEFAULT_NETWORK_ID);
- });
-
- it('should attach request data', function () {
- const requests = spec.buildRequests([videoBidRequest], VIDEO_REQUEST);
- const data = JSON.parse(requests.data);
- const [width, height] = videoBidRequest.sizes;
- const VERSION = '1.0.0';
- expect(data.imp[0].video.w).to.equal(width);
- expect(data.imp[0].video.h).to.equal(height);
- expect(data.imp[0].bidfloor).to.equal(videoBidRequest.params.bidfloor);
- expect(data.ext.prebidver).to.equal('$prebid.version$');
- expect(data.ext.adapterver).to.equal(spec.VERSION);
- });
-
- it('should set pubId to e2etest when bid.params.e2etest = true', function () {
- videoBidRequest.params.e2etest = true;
- const requests = spec.buildRequests([videoBidRequest], VIDEO_REQUEST);
- expect(requests.method).to.equal('POST');
- expect(requests.url).to.equal(spec.ENDPOINT + '?pid=e2etest&nId=' + DEFAULT_NETWORK_ID);
- });
-
- it('should attach End 2 End test data', function () {
- videoBidRequest.params.e2etest = true;
- const requests = spec.buildRequests([videoBidRequest], VIDEO_REQUEST);
- const data = JSON.parse(requests.data);
- expect(data.imp[0].bidfloor).to.not.exist;
- expect(data.imp[0].video.w).to.equal(640);
- expect(data.imp[0].video.h).to.equal(480);
- });
- });
- });
-
- describe('interpretResponse', function () {
- context('when mediaType is banner', function () {
- it('have bids', function () {
- let bids = spec.interpretResponse(RESPONSE, BANNER_REQUEST);
- expect(bids).to.be.an('array').that.is.not.empty;
- validateBidOnIndex(0);
- validateBidOnIndex(1);
-
- function validateBidOnIndex(index) {
- expect(bids[index]).to.have.property('currency', 'USD');
- expect(bids[index]).to.have.property('requestId', RESPONSE.body.seatbid[0].bid[index].impid);
- expect(bids[index]).to.have.property('cpm', RESPONSE.body.seatbid[0].bid[index].price);
- expect(bids[index]).to.have.property('width', RESPONSE.body.seatbid[0].bid[index].w);
- expect(bids[index]).to.have.property('height', RESPONSE.body.seatbid[0].bid[index].h);
- expect(bids[index]).to.have.property('ad', RESPONSE.body.seatbid[0].bid[index].adm);
- expect(bids[index]).to.have.property('creativeId', RESPONSE.body.seatbid[0].bid[index].crid);
- expect(bids[index].meta).to.have.property('advertiserDomains', RESPONSE.body.seatbid[0].bid[index].adomain);
- expect(bids[index]).to.have.property('ttl', 300);
- expect(bids[index]).to.have.property('netRevenue', true);
- }
- });
-
- it('handles empty response', function () {
- const EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {}});
- const bids = spec.interpretResponse(EMPTY_RESP, BANNER_REQUEST);
-
- expect(bids).to.be.empty;
- });
- });
-
- context('when mediaType is video', function () {
- it('should return no bids if the response is not valid', function () {
- const bidResponse = spec.interpretResponse({
- body: null
- }, {
- videoBidRequest
- });
- expect(bidResponse.length).to.equal(0);
- });
-
- it('should return no bids if the response "nurl" and "adm" are missing', function () {
- const serverResponse = {
- seatbid: [{
- bid: [{
- price: 6.01
- }]
- }]
- };
- const bidResponse = spec.interpretResponse({
- body: serverResponse
- }, {
- videoBidRequest
- });
- expect(bidResponse.length).to.equal(0);
- });
-
- it('should return no bids if the response "price" is missing', function () {
- const serverResponse = {
- seatbid: [{
- bid: [{
- adm: ''
- }]
- }]
- };
- const bidResponse = spec.interpretResponse({
- body: serverResponse
- }, {
- videoBidRequest
- });
- expect(bidResponse.length).to.equal(0);
- });
-
- it('should return a valid video bid response with just "adm"', function () {
- const serverResponse = {
- id: '123',
- seatbid: [{
- bid: [{
- id: 1,
- adid: 123,
- impid: 456,
- crid: 2,
- price: 6.01,
- adm: '',
- adomain: [
- 'kulturemedia.com'
- ],
- w: 640,
- h: 480,
- ext: {
- prebid: {
- type: 'video'
- },
- }
- }]
- }],
- cur: 'USD'
- };
- const bidResponse = spec.interpretResponse({
- body: serverResponse
- }, {
- videoBidRequest
- });
- let o = {
- requestId: serverResponse.seatbid[0].bid[0].impid,
- ad: '',
- cpm: serverResponse.seatbid[0].bid[0].price,
- creativeId: serverResponse.seatbid[0].bid[0].crid,
- vastXml: serverResponse.seatbid[0].bid[0].adm,
- width: 640,
- height: 480,
- mediaType: 'video',
- currency: 'USD',
- ttl: 300,
- netRevenue: true,
- meta: {
- advertiserDomains: ['kulturemedia.com']
- }
- };
- expect(bidResponse[0]).to.deep.equal(o);
- });
-
- it('should default ttl to 300', function () {
- const serverResponse = {
- seatbid: [{bid: [{id: 1, adid: 123, crid: 2, price: 6.01, adm: ''}]}],
- cur: 'USD'
- };
- const bidResponse = spec.interpretResponse({body: serverResponse}, {videoBidRequest});
- expect(bidResponse[0].ttl).to.equal(300);
- });
- it('should not allow ttl above 3601, default to 300', function () {
- videoBidRequest.params.video.ttl = 3601;
- const serverResponse = {
- seatbid: [{bid: [{id: 1, adid: 123, crid: 2, price: 6.01, adm: ''}]}],
- cur: 'USD'
- };
- const bidResponse = spec.interpretResponse({body: serverResponse}, {videoBidRequest});
- expect(bidResponse[0].ttl).to.equal(300);
- });
- it('should not allow ttl below 1, default to 300', function () {
- videoBidRequest.params.video.ttl = 0;
- const serverResponse = {
- seatbid: [{bid: [{id: 1, adid: 123, crid: 2, price: 6.01, adm: ''}]}],
- cur: 'USD'
- };
- const bidResponse = spec.interpretResponse({body: serverResponse}, {videoBidRequest});
- expect(bidResponse[0].ttl).to.equal(300);
- });
- });
- });
-
- describe('getUserSyncs', function () {
- it('handles no parameters', function () {
- let opts = spec.getUserSyncs({});
- expect(opts).to.be.an('array').that.is.empty;
- });
- it('returns non if sync is not allowed', function () {
- let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false});
-
- expect(opts).to.be.an('array').that.is.empty;
- });
-
- it('iframe sync enabled should return results', function () {
- let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [RESPONSE]);
-
- expect(opts.length).to.equal(1);
- expect(opts[0].type).to.equal('iframe');
- expect(opts[0].url).to.equal(RESPONSE.body.ext.usersync['sovrn'].syncs[0].url);
- });
-
- it('pixel sync enabled should return results', function () {
- let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [RESPONSE]);
-
- expect(opts.length).to.equal(1);
- expect(opts[0].type).to.equal('image');
- expect(opts[0].url).to.equal(RESPONSE.body.ext.usersync['appnexus'].syncs[0].url);
- });
-
- it('all sync enabled should return all results', function () {
- let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, [RESPONSE]);
-
- expect(opts.length).to.equal(2);
- });
- });
-})
-;
diff --git a/test/spec/modules/liveIntentIdMinimalSystem_spec.js b/test/spec/modules/liveIntentIdMinimalSystem_spec.js
index 0929a022937..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'}}});
@@ -271,6 +276,16 @@ describe('LiveIntentMinimalId', function() {
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 () {
+ 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() {
+ 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'}}});
+ });
+
it('should allow disabling nonId resolution', function() {
let callBackSpy = sinon.spy();
let submoduleCallback = liveIntentIdSubmodule.getId({ params: {
diff --git a/test/spec/modules/liveIntentIdSystem_spec.js b/test/spec/modules/liveIntentIdSystem_spec.js
index 4f11af57711..3af598c5d4e 100644
--- a/test/spec/modules/liveIntentIdSystem_spec.js
+++ b/test/spec/modules/liveIntentIdSystem_spec.js
@@ -1,6 +1,6 @@
import { liveIntentIdSubmodule, reset as resetLiveIntentIdSubmodule, storage } from 'modules/liveIntentIdSystem.js';
import * as utils from 'src/utils.js';
-import { gdprDataHandler, uspDataHandler } from '../../../src/adapterManager.js';
+import { gdprDataHandler, uspDataHandler, gppDataHandler } from '../../../src/adapterManager.js';
import { server } from 'test/mocks/xhr.js';
resetLiveIntentIdSubmodule();
liveIntentIdSubmodule.setModuleMode('standard')
@@ -12,6 +12,7 @@ describe('LiveIntentId', function() {
let logErrorStub;
let uspConsentDataStub;
let gdprConsentDataStub;
+ let gppConsentDataStub;
let getCookieStub;
let getDataFromLocalStorageStub;
let imgStub;
@@ -24,6 +25,7 @@ describe('LiveIntentId', function() {
logErrorStub = sinon.stub(utils, 'logError');
uspConsentDataStub = sinon.stub(uspDataHandler, 'getConsentData');
gdprConsentDataStub = sinon.stub(gdprDataHandler, 'getConsentData');
+ gppConsentDataStub = sinon.stub(gppDataHandler, 'getConsentData');
});
afterEach(function() {
@@ -33,6 +35,7 @@ describe('LiveIntentId', function() {
logErrorStub.restore();
uspConsentDataStub.restore();
gdprConsentDataStub.restore();
+ gppConsentDataStub.restore();
resetLiveIntentIdSubmodule();
});
@@ -42,11 +45,15 @@ describe('LiveIntentId', function() {
gdprApplies: true,
consentString: 'consentDataString'
})
+ gppConsentDataStub.returns({
+ gppString: 'gppConsentDataString',
+ applicableSections: [1, 2]
+ })
let callBackSpy = sinon.spy();
let submoduleCallback = liveIntentIdSubmodule.getId(defaultConfigParams).callback;
submoduleCallback(callBackSpy);
let request = server.requests[0];
- expect(request.url).to.match(/.*us_privacy=1YNY.*&gdpr=1&n3pc=1&gdpr_consent=consentDataString.*/);
+ expect(request.url).to.match(/.*us_privacy=1YNY.*&gdpr=1&n3pc=1&gdpr_consent=consentDataString.*&gpp_s=gppConsentDataString&gpp_as=1%2C2.*/);
const response = {
unifiedId: 'a_unified_id',
segments: [123, 234]
@@ -65,9 +72,13 @@ describe('LiveIntentId', function() {
gdprApplies: true,
consentString: 'consentDataString'
})
+ gppConsentDataStub.returns({
+ gppString: 'gppConsentDataString',
+ applicableSections: [1]
+ })
liveIntentIdSubmodule.getId(defaultConfigParams);
setTimeout(() => {
- expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?.*&us_privacy=1YNY.*&wpn=prebid.*&gdpr=1&n3pc=1&n3pct=1&nb=1&gdpr_consent=consentDataString.*/);
+ expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?.*&us_privacy=1YNY.*&wpn=prebid.*&gdpr=1&n3pc=1&n3pct=1&nb=1&gdpr_consent=consentDataString&gpp_s=gppConsentDataString&gpp_as=1.*/);
done();
}, 200);
});
@@ -83,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,
@@ -123,9 +144,13 @@ describe('LiveIntentId', function() {
gdprApplies: false,
consentString: 'consentDataString'
})
+ gppConsentDataStub.returns({
+ gppString: 'gppConsentDataString',
+ applicableSections: [1]
+ })
liveIntentIdSubmodule.decode({}, defaultConfigParams);
setTimeout(() => {
- expect(server.requests[0].url).to.match(/.*us_privacy=1YNY.*&gdpr=0&gdpr_consent=consentDataString.*/);
+ expect(server.requests[0].url).to.match(/.*us_privacy=1YNY.*&gdpr=0&gdpr_consent=consentDataString.*&gpp_s=gppConsentDataString&gpp_as=1.*/);
done();
}, 200);
});
@@ -171,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
@@ -179,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
@@ -193,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
@@ -219,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,
@@ -234,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,
@@ -249,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,
@@ -266,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,
@@ -289,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,
@@ -311,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,
@@ -344,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,
@@ -353,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'}}});
});
@@ -363,26 +388,41 @@ 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 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 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'}}});
+ });
+
it('should allow disabling nonId resolution', function() {
let callBackSpy = sinon.spy();
let submoduleCallback = liveIntentIdSubmodule.getId({ params: {
@@ -391,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/lm_kiviadsBidAdapter_spec.js b/test/spec/modules/lm_kiviadsBidAdapter_spec.js
new file mode 100644
index 00000000000..68ac73289cd
--- /dev/null
+++ b/test/spec/modules/lm_kiviadsBidAdapter_spec.js
@@ -0,0 +1,455 @@
+import {expect} from 'chai';
+import {config} from 'src/config.js';
+import {spec, getBidFloor} from 'modules/lm_kiviadsBidAdapter.js';
+import {deepClone} from 'src/utils';
+
+const ENDPOINT = 'https://pbjs.kiviads.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: 'lm_kiviads',
+ params: {
+ env: 'lm_kiviads',
+ pid: '40',
+ ext: {}
+ },
+ bidRequestsCount: 1
+};
+
+const defaultRequestVideo = deepClone(defaultRequest);
+defaultRequestVideo.mediaTypes = {
+ video: {
+ playerSize: [640, 480],
+ context: 'instream',
+ skipppable: true
+ }
+};
+describe('lm_kiviadsBidAdapter', () => {
+ 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: 'lm_kiviads',
+ 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: ['lm_kiviads']
+ },
+ 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: ['lm_kiviads']});
+ });
+
+ 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/magniteAnalyticsAdapter_spec.js b/test/spec/modules/magniteAnalyticsAdapter_spec.js
index 304ce2ed7a5..0864a976d7d 100644
--- a/test/spec/modules/magniteAnalyticsAdapter_spec.js
+++ b/test/spec/modules/magniteAnalyticsAdapter_spec.js
@@ -1492,6 +1492,40 @@ describe('magnite analytics adapter', function () {
expect(message).to.deep.equal(expectedMessage);
});
+ describe('when eventDispatcher is present', () => {
+ beforeEach(() => {
+ window.pbjs = window.pbjs || {};
+ pbjs.rp = pbjs.rp || {};
+ pbjs.rp.eventDispatcher = pbjs.rp.eventDispatcher || document.createElement('fakeElem');
+ });
+
+ afterEach(() => {
+ delete pbjs.rp.eventDispatcher;
+ delete pbjs.rp;
+ });
+
+ it('should dispatch beforeSendingMagniteAnalytics if possible', () => {
+ pbjs.rp.eventDispatcher.addEventListener('beforeSendingMagniteAnalytics', (data) => {
+ data.detail.test = 'testData';
+ });
+
+ performStandardAuction();
+
+ expect(server.requests.length).to.equal(1);
+ let request = server.requests[0];
+
+ expect(request.url).to.equal('http://localhost:9999/event');
+
+ let message = JSON.parse(request.requestBody);
+
+ const AnalyticsMessageWithCustomData = {
+ ...ANALYTICS_MESSAGE,
+ test: 'testData'
+ }
+ expect(message).to.deep.equal(AnalyticsMessageWithCustomData);
+ });
+ })
+
describe('when handling bid caching', () => {
let auctionInits, bidRequests, bidResponses, bidsWon;
beforeEach(function () {
diff --git a/test/spec/modules/mediabramaBidAdapter_spec.js b/test/spec/modules/mediabramaBidAdapter_spec.js
new file mode 100644
index 00000000000..d7341e02f17
--- /dev/null
+++ b/test/spec/modules/mediabramaBidAdapter_spec.js
@@ -0,0 +1,256 @@
+import {expect} from 'chai';
+import {spec} from '../../../modules/mediabramaBidAdapter.js';
+import { BANNER } from '../../../src/mediaTypes.js';
+import * as utils from '../../../src/utils.js';
+
+describe('MediaBramaBidAdapter', function () {
+ const bid = {
+ bidId: '23dc19818e5293',
+ bidder: 'mediabrama',
+ mediaTypes: {
+ [BANNER]: {
+ sizes: [[300, 250]]
+ }
+ },
+ params: {
+ placementId: 24428,
+ }
+ };
+
+ const bidderRequest = {
+ refererInfo: {
+ referer: 'test.com'
+ }
+ };
+
+ describe('isBidRequestValid', function () {
+ it('Should return true if there are bidId, params and key parameters present', function () {
+ expect(spec.isBidRequestValid(bid)).to.be.true;
+ });
+ it('Should return false if at least one of parameters is not present', function () {
+ delete bid.params.placementId;
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ });
+ });
+
+ describe('buildRequests', function () {
+ let serverRequest = spec.buildRequests([bid], bidderRequest);
+ it('Creates a ServerRequest object with method, URL and data', function () {
+ expect(serverRequest).to.exist;
+ expect(serverRequest.method).to.exist;
+ expect(serverRequest.url).to.exist;
+ expect(serverRequest.data).to.exist;
+ });
+ it('Returns POST method', function () {
+ expect(serverRequest.method).to.equal('POST');
+ });
+ it('Returns valid URL', function () {
+ expect(serverRequest.url).to.equal('https://prebid.mediabrama.com/pbjs');
+ });
+ it('Returns valid data if array of bids is valid', function () {
+ let data = serverRequest.data;
+ expect(data).to.be.an('object');
+ expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'host', 'page', 'placements');
+ expect(data.deviceWidth).to.be.a('number');
+ expect(data.deviceHeight).to.be.a('number');
+ expect(data.language).to.be.a('string');
+ expect(data.host).to.be.a('string');
+ expect(data.page).to.be.a('string');
+ expect(data.gdpr).to.not.exist;
+ expect(data.ccpa).to.not.exist;
+ let placement = data['placements'][0];
+ expect(placement).to.have.keys('placementId', 'bidId', 'adFormat', 'sizes', 'schain', 'bidfloor');
+ expect(placement.placementId).to.equal(24428);
+ expect(placement.bidId).to.equal('23dc19818e5293');
+ expect(placement.adFormat).to.equal(BANNER);
+ expect(placement.schain).to.be.an('object');
+ expect(placement.sizes).to.be.an('array');
+ expect(placement.bidfloor).to.exist.and.to.equal(0);
+ });
+
+ it('Returns data with gdprConsent and without uspConsent', function () {
+ bidderRequest.gdprConsent = 'test';
+ serverRequest = spec.buildRequests([bid], 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.ccpa).to.not.exist;
+ delete bidderRequest.gdprConsent;
+ });
+
+ it('Returns data with uspConsent and without gdprConsent', function () {
+ bidderRequest.uspConsent = 'test';
+ serverRequest = spec.buildRequests([bid], bidderRequest);
+ let data = serverRequest.data;
+ expect(data.ccpa).to.exist;
+ expect(data.ccpa).to.be.a('string');
+ 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([]);
+ let data = serverRequest.data;
+ expect(data.placements).to.be.an('array').that.is.empty;
+ });
+ });
+ describe('interpretResponse', function () {
+ it('Should interpret banner response', function () {
+ const banner = {
+ body: [{
+ mediaType: 'banner',
+ width: 300,
+ height: 250,
+ cpm: 0.4,
+ ad: 'Test',
+ requestId: '23dc19818e5293',
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1',
+ meta: {}
+ }]
+ };
+ let bannerResponses = spec.interpretResponse(banner);
+ 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', 'mediaType', 'meta');
+ expect(dataItem.requestId).to.equal('23dc19818e5293');
+ expect(dataItem.cpm).to.equal(0.4);
+ expect(dataItem.width).to.equal(300);
+ expect(dataItem.height).to.equal(250);
+ expect(dataItem.ad).to.equal('Test');
+ expect(dataItem.ttl).to.equal(120);
+ expect(dataItem.creativeId).to.equal('2');
+ expect(dataItem.netRevenue).to.be.true;
+ expect(dataItem.currency).to.equal('USD');
+ expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains');
+ });
+ it('Should return an empty array if invalid banner response is passed', function () {
+ const invBanner = {
+ body: [{
+ width: 300,
+ cpm: 0.4,
+ ad: 'Test',
+ requestId: '23dc19818e5293',
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1'
+ }]
+ };
+
+ let serverResponses = spec.interpretResponse(invBanner);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ it('Should return an empty array if invalid response is passed', function () {
+ const invalid = {
+ body: [{
+ ttl: 120,
+ creativeId: '2',
+ netRevenue: true,
+ currency: 'USD',
+ dealId: '1'
+ }]
+ };
+ let serverResponses = spec.interpretResponse(invalid);
+ expect(serverResponses).to.be.an('array').that.is.empty;
+ });
+ });
+
+ describe('getUserSyncs', function () {
+ it('should do nothing on getUserSyncs', function () {
+ const syncData = spec.getUserSyncs({}, {}, {
+ consentString: 'ALL',
+ gdprApplies: true
+ }, {});
+ expect(syncData).to.be.an('array').which.is.not.empty;
+ expect(syncData[0]).to.be.an('object')
+ expect(syncData[0].type).to.be.a('string')
+ expect(syncData[0].type).to.equal('image')
+ expect(syncData[0].url).to.be.a('string')
+ expect(syncData[0].url).to.equal('https://prebid.mediabrama.com/sync/image?pbjs=1&gdpr=1&gdpr_consent=ALL&coppa=0')
+ });
+ });
+
+ describe('on bidWon', function () {
+ beforeEach(function() {
+ sinon.stub(utils, 'triggerPixel');
+ });
+ afterEach(function() {
+ utils.triggerPixel.restore();
+ });
+ it('should replace nurl for banner', function () {
+ const nurl = 'nurl/?ap=${' + 'AUCTION_PRICE}';
+ const bid = {
+ 'bidderCode': 'mediabrama',
+ 'width': 300,
+ 'height': 250,
+ 'statusMessage': 'Bid available',
+ 'adId': '5691dd18ba6ab6',
+ 'requestId': '23dc19818e5293',
+ 'transactionId': '948c716b-bf64-4303-bcf4-395c2f6a9770',
+ 'auctionId': 'a6b7c61f-15a9-481b-8f64-e859787e9c07',
+ 'mediaType': 'banner',
+ 'source': 'client',
+ 'ad': "\n",
+ 'cpm': 0.61,
+ 'nurl': nurl,
+ 'creativeId': 'test',
+ 'currency': 'USD',
+ 'dealId': '',
+ 'meta': {
+ 'advertiserDomains': [],
+ 'dchain': {
+ 'ver': '1.0',
+ 'complete': 0,
+ 'nodes': [
+ {
+ 'name': 'mediabrama'
+ }
+ ]
+ }
+ },
+ 'netRevenue': true,
+ 'ttl': 185,
+ 'metrics': {},
+ 'adapterCode': 'mediabrama',
+ 'originalCpm': 0.61,
+ 'originalCurrency': 'USD',
+ 'responseTimestamp': 1668162732297,
+ 'requestTimestamp': 1668162732292,
+ 'bidder': 'mediabrama',
+ 'adUnitCode': 'div-prebid',
+ 'timeToRespond': 5,
+ 'pbLg': '0.50',
+ 'pbMg': '0.60',
+ 'pbHg': '0.61',
+ 'pbAg': '0.61',
+ 'pbDg': '0.61',
+ 'pbCg': '',
+ 'size': '300x250',
+ 'adserverTargeting': {
+ 'hb_bidder': 'mediabrama',
+ 'hb_adid': '5691dd18ba6ab6',
+ 'hb_pb': '0.61',
+ 'hb_size': '300x250',
+ 'hb_source': 'client',
+ 'hb_format': 'banner',
+ 'hb_adomain': ''
+ },
+ 'status': 'rendered',
+ 'params': [
+ {
+ 'placementId': 24428
+ }
+ ]
+ };
+ spec.onBidWon(bid);
+ expect(bid.nurl).to.deep.equal('nurl/?ap=0.61');
+ });
+ });
+});
diff --git a/test/spec/modules/mediafilterRtdProvider_spec.js b/test/spec/modules/mediafilterRtdProvider_spec.js
new file mode 100644
index 00000000000..3395c7be691
--- /dev/null
+++ b/test/spec/modules/mediafilterRtdProvider_spec.js
@@ -0,0 +1,147 @@
+import * as utils from '../../../src/utils.js';
+import * as hook from '../../../src/hook.js'
+import * as events from '../../../src/events.js';
+import CONSTANTS from '../../../src/constants.json';
+
+import {
+ MediaFilter,
+ MEDIAFILTER_EVENT_TYPE,
+ MEDIAFILTER_BASE_URL
+} from '../../../modules/mediafilterRtdProvider.js';
+
+describe('The Media Filter RTD module', function () {
+ describe('register()', function() {
+ let submoduleSpy, generateInitHandlerSpy;
+
+ beforeEach(function () {
+ submoduleSpy = sinon.spy(hook, 'submodule');
+ generateInitHandlerSpy = sinon.spy(MediaFilter, 'generateInitHandler');
+ });
+
+ afterEach(function () {
+ submoduleSpy.restore();
+ generateInitHandlerSpy.restore();
+ });
+
+ it('should register and call the submodule function(s)', function () {
+ MediaFilter.register();
+
+ expect(submoduleSpy.calledOnceWithExactly('realTimeData', sinon.match.object)).to.be.true;
+ expect(submoduleSpy.called).to.be.true;
+ expect(generateInitHandlerSpy.called).to.be.true;
+ });
+ });
+
+ describe('setup()', function() {
+ let setupEventListenerSpy, setupScriptSpy;
+
+ beforeEach(function() {
+ setupEventListenerSpy = sinon.spy(MediaFilter, 'setupEventListener');
+ setupScriptSpy = sinon.spy(MediaFilter, 'setupScript');
+ });
+
+ afterEach(function() {
+ setupEventListenerSpy.restore();
+ setupScriptSpy.restore();
+ });
+
+ it('should call setupEventListener and setupScript function(s)', function() {
+ MediaFilter.setup({ configurationHash: 'abc123' });
+
+ expect(setupEventListenerSpy.called).to.be.true;
+ expect(setupScriptSpy.called).to.be.true;
+ });
+ });
+
+ describe('setupEventListener()', function() {
+ let setupEventListenerSpy, addEventListenerSpy;
+
+ beforeEach(function() {
+ setupEventListenerSpy = sinon.spy(MediaFilter, 'setupEventListener');
+ addEventListenerSpy = sinon.spy(window, 'addEventListener');
+ });
+
+ afterEach(function() {
+ setupEventListenerSpy.restore();
+ addEventListenerSpy.restore();
+ });
+
+ it('should call addEventListener function(s)', function() {
+ MediaFilter.setupEventListener();
+ expect(addEventListenerSpy.called).to.be.true;
+ expect(addEventListenerSpy.calledWith('message', sinon.match.func)).to.be.true;
+ });
+ });
+
+ describe('generateInitHandler()', function() {
+ let generateInitHandlerSpy, setupMock, logErrorSpy;
+
+ beforeEach(function() {
+ generateInitHandlerSpy = sinon.spy(MediaFilter, 'generateInitHandler');
+ setupMock = sinon.stub(MediaFilter, 'setup').throws(new Error('Mocked error!'));
+ logErrorSpy = sinon.spy(utils, 'logError');
+ });
+
+ afterEach(function() {
+ generateInitHandlerSpy.restore();
+ setupMock.restore();
+ logErrorSpy.restore();
+ });
+
+ it('should handle errors in the catch block when setup throws an error', function() {
+ const initHandler = MediaFilter.generateInitHandler();
+ initHandler({});
+
+ expect(logErrorSpy.calledWith('Error in initialization: Mocked error!')).to.be.true;
+ });
+ });
+
+ describe('generateEventHandler()', function() {
+ let generateEventHandlerSpy, eventsEmitSpy;
+
+ beforeEach(function() {
+ generateEventHandlerSpy = sinon.spy(MediaFilter, 'generateEventHandler');
+ eventsEmitSpy = sinon.spy(events, 'emit');
+ });
+
+ afterEach(function() {
+ generateEventHandlerSpy.restore();
+ eventsEmitSpy.restore();
+ });
+
+ it('should emit a billable event when the event type matches', function() {
+ const configurationHash = 'abc123';
+ const eventHandler = MediaFilter.generateEventHandler(configurationHash);
+
+ const mockEvent = {
+ data: {
+ type: MEDIAFILTER_EVENT_TYPE.concat('.', configurationHash)
+ }
+ };
+
+ eventHandler(mockEvent);
+
+ expect(eventsEmitSpy.calledWith(CONSTANTS.EVENTS.BILLABLE_EVENT, {
+ 'billingId': sinon.match.string,
+ 'configurationHash': configurationHash,
+ 'type': 'impression',
+ 'vendor': 'mediafilter',
+ })).to.be.true;
+ });
+
+ it('should not emit a billable event when the event type does not match', function() {
+ const configurationHash = 'abc123';
+ const eventHandler = MediaFilter.generateEventHandler(configurationHash);
+
+ const mockEvent = {
+ data: {
+ type: 'differentEventType'
+ }
+ };
+
+ eventHandler(mockEvent);
+
+ expect(eventsEmitSpy.called).to.be.false;
+ });
+ });
+});
diff --git a/test/spec/modules/mediagoBidAdapter_spec.js b/test/spec/modules/mediagoBidAdapter_spec.js
index e77af544429..601bcff527a 100644
--- a/test/spec/modules/mediagoBidAdapter_spec.js
+++ b/test/spec/modules/mediagoBidAdapter_spec.js
@@ -11,12 +11,49 @@ describe('mediago:BidAdapterTests', function () {
bidder: 'mediago',
params: {
token: '85a6b01e41ac36d49744fad726e3655d',
+ siteId: 'siteId_01',
+ zoneId: 'zoneId_01',
+ publisher: '52',
+ position: 'left',
+ referrer: 'https://trace.mediago.io',
bidfloor: 0.01,
+ ortb2Imp: {
+ ext: {
+ gpid: 'adslot_gpid',
+ tid: 'tid_01',
+ data: {
+ browsi: {
+ browsiViewability: 'NA'
+ },
+ adserver: {
+ name: 'adserver_name',
+ adslot: 'adslot_name'
+ },
+ pbadslot: '/12345/my-gpt-tag-0'
+ }
+ }
+ }
},
mediaTypes: {
banner: {
sizes: [[300, 250]],
+ pos: 'left'
+ }
+ },
+ ortb2: {
+ 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',
@@ -27,9 +64,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 = [];
@@ -38,8 +149,8 @@ describe('mediago:BidAdapterTests', function () {
spec.isBidRequestValid({
bidder: 'mediago',
params: {
- token: ['85a6b01e41ac36d49744fad726e3655d'],
- },
+ token: ['85a6b01e41ac36d49744fad726e3655d']
+ }
})
).to.equal(true);
});
@@ -51,10 +162,12 @@ describe('mediago:BidAdapterTests', function () {
});
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);
@@ -72,13 +185,13 @@ describe('mediago:BidAdapterTests', function () {
cid: '1339145',
crid: 'ff32b6f9b3bbc45c00b78b6674a2952e',
w: 300,
- h: 250,
- },
- ],
- },
+ h: 250
+ }
+ ]
+ }
],
- cur: 'USD',
- },
+ cur: 'USD'
+ }
};
let bids = spec.interpretResponse(serverResponse);
diff --git a/test/spec/modules/mediasquareBidAdapter_spec.js b/test/spec/modules/mediasquareBidAdapter_spec.js
index 125d4bef02b..d7984c05967 100644
--- a/test/spec/modules/mediasquareBidAdapter_spec.js
+++ b/test/spec/modules/mediasquareBidAdapter_spec.js
@@ -101,6 +101,7 @@ describe('MediaSquare bid adapter tests', function () {
'adomain': ['test.com'],
'context': 'instream',
'increment': 1.0,
+ 'ova': 'cleared',
}],
}};
@@ -171,6 +172,7 @@ describe('MediaSquare bid adapter tests', function () {
expect(bid.mediasquare.increment).to.exist;
expect(bid.mediasquare.increment).to.equal(1.0);
expect(bid.mediasquare.code).to.equal([DEFAULT_PARAMS[0].params.owner, DEFAULT_PARAMS[0].params.code].join('/'));
+ expect(bid.mediasquare.ova).to.exist.and.to.equal('cleared');
expect(bid.meta).to.exist;
expect(bid.meta.advertiserDomains).to.exist;
expect(bid.meta.advertiserDomains).to.have.lengthOf(1);
@@ -213,6 +215,7 @@ describe('MediaSquare bid adapter tests', function () {
let message = JSON.parse(server.requests[0].requestBody);
expect(message).to.have.property('increment').exist;
expect(message).to.have.property('increment').and.to.equal('1');
+ expect(message).to.have.property('ova').and.to.equal('cleared');
});
it('Verifies user sync without cookie in bid response', function () {
var syncs = spec.getUserSyncs({}, [BID_RESPONSE], DEFAULT_OPTIONS.gdprConsent, DEFAULT_OPTIONS.uspConsent);
diff --git a/test/spec/modules/mgidXBidAdapter_spec.js b/test/spec/modules/mgidXBidAdapter_spec.js
index 14619e9c0e1..978ca3de036 100644
--- a/test/spec/modules/mgidXBidAdapter_spec.js
+++ b/test/spec/modules/mgidXBidAdapter_spec.js
@@ -76,7 +76,10 @@ describe('MGIDXBidAdapter', function () {
const bidderRequest = {
uspConsent: '1---',
- gdprConsent: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
+ gdprConsent: {
+ consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
+ vendorData: {}
+ },
refererInfo: {
referer: 'https://test.com'
}
@@ -131,7 +134,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 +175,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;
});
diff --git a/test/spec/modules/minutemediaBidAdapter_spec.js b/test/spec/modules/minutemediaBidAdapter_spec.js
index 48f694bc79d..7e22114aeed 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: {
diff --git a/test/spec/modules/missenaBidAdapter_spec.js b/test/spec/modules/missenaBidAdapter_spec.js
index f61987298e8..a51cb8bbac9 100644
--- a/test/spec/modules/missenaBidAdapter_spec.js
+++ b/test/spec/modules/missenaBidAdapter_spec.js
@@ -1,23 +1,64 @@
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';
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]] } },
+ params: {
+ apiKey: 'PA-34745704',
+ placement: 'sticky',
+ formats: ['sticky-banner'],
+ },
+ getFloor: (inputParams) => {
+ if (inputParams.mediaType === BANNER) {
+ return {
+ currency: 'EUR',
+ floor: 3.5,
+ };
+ } else {
+ return {};
+ }
+ },
+ };
+ const bidWithoutFloor = {
+ bidder: 'missena',
+ bidId: bidId,
+ sizes: [[1, 1]],
+ mediaTypes: { banner: { sizes: [[1, 1]] } },
params: {
apiKey: 'PA-34745704',
placement: 'sticky',
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');
@@ -31,34 +72,27 @@ describe('Missena Adapter', function () {
it('should return false if the apiKey is missing', function () {
expect(
- spec.isBidRequestValid(Object.assign(bid, { params: {} }))
+ spec.isBidRequestValid(Object.assign(bid, { params: {} })),
).to.equal(false);
});
it('should return false if the apiKey is an empty string', function () {
expect(
- spec.isBidRequestValid(Object.assign(bid, { params: { apiKey: '' } }))
+ spec.isBidRequestValid(Object.assign(bid, { params: { apiKey: '' } })),
).to.equal(false);
});
});
describe('buildRequests', function () {
- const consentString = 'AAAAAAAAA==';
+ let getDataFromLocalStorageStub = sinon.stub(
+ storage,
+ 'getDataFromLocalStorage',
+ );
- const bidderRequest = {
- gdprConsent: {
- consentString: consentString,
- gdprApplies: true,
- },
- refererInfo: {
- topmostLocation: 'https://referer',
- canonicalUrl: 'https://canonical',
- },
- };
-
- const requests = spec.buildRequests([bid, bid], bidderRequest);
+ const requests = spec.buildRequests(bids, bidderRequest);
const request = requests[0];
const payload = JSON.parse(request.data);
+ const payloadNoFloor = JSON.parse(requests[1].data);
it('should return as many server requests as bidder requests', function () {
expect(requests.length).to.equal(2);
@@ -81,7 +115,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');
});
@@ -89,6 +123,66 @@ describe('Missena Adapter', function () {
expect(payload.consent_string).to.equal(consentString);
expect(payload.consent_required).to.equal(true);
});
+ it('should send floor data', function () {
+ expect(payload.floor).to.equal(3.5);
+ expect(payload.floor_currency).to.equal('EUR');
+ });
+ it('should not send floor data if not available', function () {
+ expect(payloadNoFloor.floor).to.equal(undefined);
+ expect(payloadNoFloor.floor_currency).to.equal(undefined);
+ });
+
+ 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);
+ });
});
describe('interpretResponse', function () {
@@ -121,14 +215,14 @@ describe('Missena Adapter', function () {
expect(result.length).to.equal(1);
expect(Object.keys(result[0])).to.have.members(
- Object.keys(serverResponse)
+ Object.keys(serverResponse),
);
});
it('should return an empty response when the server answers with a timeout', function () {
const result = spec.interpretResponse(
{ body: serverTimeoutResponse },
- bid
+ bid,
);
expect(result).to.deep.equal([]);
});
@@ -136,7 +230,7 @@ describe('Missena Adapter', function () {
it('should return an empty response when the server answers with an empty ad', function () {
const result = spec.interpretResponse(
{ body: serverEmptyAdResponse },
- bid
+ bid,
);
expect(result).to.deep.equal([]);
});
diff --git a/test/spec/modules/mobfoxpbBidAdapter_spec.js b/test/spec/modules/mobfoxpbBidAdapter_spec.js
index 766f8d1a848..a4e58afbd1b 100644
--- a/test/spec/modules/mobfoxpbBidAdapter_spec.js
+++ b/test/spec/modules/mobfoxpbBidAdapter_spec.js
@@ -20,7 +20,8 @@ describe('MobfoxHBBidAdapter', function () {
const bidderRequest = {
refererInfo: {
referer: 'test.com'
- }
+ },
+ ortb2: {}
};
describe('isBidRequestValid', function () {
@@ -143,6 +144,36 @@ describe('MobfoxHBBidAdapter', function () {
expect(data.placements).to.be.an('array').that.is.empty;
});
});
+
+ describe('gpp consent', function () {
+ it('bidderRequest.gppConsent', () => {
+ bidderRequest.gppConsent = {
+ gppString: 'abc123',
+ applicableSections: [8]
+ };
+
+ let serverRequest = spec.buildRequests([bid], bidderRequest);
+ let data = serverRequest.data;
+ expect(data).to.be.an('object');
+ expect(data).to.have.property('gpp');
+ expect(data).to.have.property('gpp_sid');
+
+ delete bidderRequest.gppConsent;
+ })
+
+ it('bidderRequest.ortb2.regs.gpp', () => {
+ bidderRequest.ortb2.regs = bidderRequest.ortb2.regs || {};
+ bidderRequest.ortb2.regs.gpp = 'abc123';
+ bidderRequest.ortb2.regs.gpp_sid = [8];
+
+ let serverRequest = spec.buildRequests([bid], bidderRequest);
+ let data = serverRequest.data;
+ expect(data).to.be.an('object');
+ expect(data).to.have.property('gpp');
+ expect(data).to.have.property('gpp_sid');
+ })
+ });
+
describe('interpretResponse', function () {
it('Should interpret banner response', function () {
const banner = {
diff --git a/test/spec/modules/multibid_spec.js b/test/spec/modules/multibid_spec.js
index eaf8fa33a66..c11113473ce 100644
--- a/test/spec/modules/multibid_spec.js
+++ b/test/spec/modules/multibid_spec.js
@@ -1,16 +1,15 @@
import {expect} from 'chai';
import {
- validateMultibid,
- adjustBidderRequestsHook,
addBidResponseHook,
+ adjustBidderRequestsHook,
resetMultibidUnits,
+ resetMultiConfig,
sortByMultibid,
targetBidPoolHook,
- resetMultiConfig
+ validateMultibid
} from 'modules/multibid/index.js';
-import {parse as parseQuery} from 'querystring';
import {config} from 'src/config.js';
-import * as utils from 'src/utils.js';
+import {getHighestCpm} from '../../../src/utils/reducers.js';
describe('multibid adapter', function () {
let bidArray = [{
@@ -545,7 +544,7 @@ describe('multibid adapter', function () {
it('it does not run filter on bidsReceived if no multibid configuration found', function () {
let bids = [{...bidArray[0]}, {...bidArray[1]}];
- targetBidPoolHook(callbackFn, bids, utils.getHighestCpm);
+ targetBidPoolHook(callbackFn, bids, getHighestCpm);
expect(result).to.not.equal(null);
expect(result.bidsReceived).to.not.equal(null);
@@ -562,7 +561,7 @@ describe('multibid adapter', function () {
config.setConfig({multibid: [{bidder: 'bidderA', maxBids: 2}]});
- targetBidPoolHook(callbackFn, bids, utils.getHighestCpm);
+ targetBidPoolHook(callbackFn, bids, getHighestCpm);
bids.pop();
expect(result).to.not.equal(null);
@@ -584,7 +583,7 @@ describe('multibid adapter', function () {
config.setConfig({multibid: [{bidder: 'bidderA', maxBids: 2, targetBiddercodePrefix: 'bidA'}]});
- targetBidPoolHook(callbackFn, modifiedBids, utils.getHighestCpm);
+ targetBidPoolHook(callbackFn, modifiedBids, getHighestCpm);
expect(result).to.not.equal(null);
expect(result.bidsReceived).to.not.equal(null);
@@ -609,7 +608,7 @@ describe('multibid adapter', function () {
config.setConfig({multibid: [{bidder: 'bidderA', maxBids: 2, targetBiddercodePrefix: 'bidA'}]});
- targetBidPoolHook(callbackFn, modifiedBids, utils.getHighestCpm);
+ targetBidPoolHook(callbackFn, modifiedBids, getHighestCpm);
expect(result).to.not.equal(null);
expect(result.bidsReceived).to.not.equal(null);
@@ -642,7 +641,7 @@ describe('multibid adapter', function () {
config.setConfig({ multibid: [{bidder: 'bidderA', maxBids: 2, targetBiddercodePrefix: 'bidA'}] });
- targetBidPoolHook(callbackFn, modifiedBids, utils.getHighestCpm, 3);
+ targetBidPoolHook(callbackFn, modifiedBids, getHighestCpm, 3);
expect(result).to.not.equal(null);
expect(result.bidsReceived).to.not.equal(null);
@@ -670,7 +669,7 @@ describe('multibid adapter', function () {
expect(bidPool.length).to.equal(6);
- targetBidPoolHook(callbackFn, bidPool, utils.getHighestCpm);
+ targetBidPoolHook(callbackFn, bidPool, getHighestCpm);
expect(result).to.not.equal(null);
expect(result.bidsReceived).to.not.equal(null);
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..f57db82aedc 100644
--- a/test/spec/modules/nextMillenniumBidAdapter_spec.js
+++ b/test/spec/modules/nextMillenniumBidAdapter_spec.js
@@ -1,32 +1,510 @@
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',
+ },
+ },
-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',
+ 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',
+ },
},
- site: {
- domain: 'example.com',
- page: 'http://example.com'
- }
+
+ expected: {
+ id: 'test-video-1',
+ ext: {prebid: {storedrequest: {id: '234'}}},
+ video: {w: 400, h: 300},
+ },
+ },
+ ];
+
+ for (let {title, data, expected} of dataTests) {
+ it(title, () => {
+ const {bid, id} = data;
+ const imp = getImp(bid, id);
+ 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: '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 +527,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 +595,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 +613,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
new file mode 100644
index 00000000000..06a39ffd020
--- /dev/null
+++ b/test/spec/modules/nobidAnalyticsAdapter_spec.js
@@ -0,0 +1,498 @@
+import nobidAnalytics from 'modules/nobidAnalyticsAdapter.js';
+import {expect} from 'chai';
+import {server} from 'test/mocks/xhr.js';
+let events = require('src/events');
+let adapterManager = require('src/adapterManager').default;
+let constants = require('src/constants.json');
+
+const TOP_LOCATION = 'https://www.somesite.com';
+const SITE_ID = 1234;
+
+describe('NoBid Prebid Analytic', function () {
+ var clock;
+ describe('enableAnalytics', 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('auctionInit test', function (done) {
+ const initOptions = {
+ options: {
+ /* siteId: SITE_ID */
+ }
+ };
+
+ nobidAnalytics.enableAnalytics(initOptions);
+ expect(nobidAnalytics.initOptions).to.equal(undefined);
+
+ initOptions.options.siteId = SITE_ID;
+ nobidAnalytics.enableAnalytics(initOptions);
+ expect(nobidAnalytics.initOptions.siteId).to.equal(SITE_ID);
+
+ // Step 1: Initialize adapter
+ adapterManager.enableAnalytics({
+ provider: 'nobid',
+ options: initOptions
+ });
+
+ // Step 2: Send init auction event
+ events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions,
+ auctionId: '13',
+ timestamp: Date.now(),
+ bidderRequests: [{refererInfo: {topmostLocation: TOP_LOCATION}}]});
+ expect(nobidAnalytics.initOptions).to.have.property('siteId', SITE_ID);
+ expect(nobidAnalytics).to.have.property('topLocation', TOP_LOCATION);
+
+ const data = { ts: Date.now() };
+ clock.tick(5000);
+ const expired = nobidAnalytics.isExpired(data);
+ expect(expired).to.equal(false);
+
+ done();
+ });
+
+ it('BID_REQUESTED/BID_RESPONSE/BID_TIMEOUT/AD_RENDER_SUCCEEDED test', function (done) {
+ const initOptions = {
+ options: {
+ siteId: SITE_ID
+ }
+ };
+
+ nobidAnalytics.enableAnalytics(initOptions);
+
+ // Step 1: Initialize adapter
+ adapterManager.enableAnalytics({
+ provider: 'nobid',
+ options: initOptions
+ });
+
+ // Step 2: Send init auction event
+ events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions,
+ auctionId: '13',
+ timestamp: Date.now(),
+ bidderRequests: [{refererInfo: {topmostLocation: TOP_LOCATION}}]});
+ events.emit(constants.EVENTS.BID_WON, {});
+ clock.tick(5000);
+ expect(server.requests).to.have.length(1);
+
+ events.emit(constants.EVENTS.BID_REQUESTED, {});
+ clock.tick(5000);
+ expect(server.requests).to.have.length(1);
+
+ events.emit(constants.EVENTS.BID_RESPONSE, {});
+ clock.tick(5000);
+ expect(server.requests).to.have.length(1);
+
+ events.emit(constants.EVENTS.BID_TIMEOUT, {});
+ clock.tick(5000);
+ expect(server.requests).to.have.length(1);
+
+ events.emit(constants.EVENTS.AD_RENDER_SUCCEEDED, {});
+ clock.tick(5000);
+ expect(server.requests).to.have.length(1);
+
+ done();
+ });
+
+ it('bidWon test', function (done) {
+ const initOptions = {
+ options: {
+ siteId: SITE_ID
+ }
+ };
+
+ nobidAnalytics.enableAnalytics(initOptions);
+
+ const TOP_LOCATION = 'https://www.somesite.com';
+
+ const requestIncoming = {
+ bidderCode: 'nobid',
+ width: 728,
+ height: 9,
+ statusMessage: 'Bid available',
+ adId: '106d14b7d06b607',
+ requestId: '67a7f0e7ea55c4',
+ transactionId: 'd58cbeae-92c8-4262-ba8d-0e649cbf5470',
+ auctionId: 'd758cce5-d178-408c-b777-8cac605ef7ca',
+ mediaType: 'banner',
+ source: 'client',
+ cpm: 6.4,
+ creativeId: 'TEST',
+ dealId: '',
+ currency: 'USD',
+ netRevenue: true,
+ ttl: 300,
+ ad: 'AD HERE',
+ meta: {
+ advertiserDomains: ['advertiser_domain.com']
+ },
+ metrics: {
+ 'requestBids.usp': 0
+ },
+ adapterCode: 'nobid',
+ originalCpm: 6.44,
+ originalCurrency: 'USD',
+ responseTimestamp: 1692156287517,
+ requestTimestamp: 1692156286972,
+ bidder: 'nobid',
+ adUnitCode: 'leaderboard',
+ timeToRespond: 545,
+ pbCg: '',
+ size: '728x90',
+ adserverTargeting: {
+ hb_bidder: 'nobid',
+ hb_adid: '106d14b7d06b607',
+ hb_pb: '6.40',
+ hb_size: '728x90',
+ hb_source: 'client',
+ hb_format: 'banner',
+ hb_adomain: 'advertiser_domain.com',
+ 'hb_crid': 'TEST'
+ },
+ status: 'rendered',
+ params: [
+ {
+ siteId: SITE_ID
+ }
+ ]
+ };
+
+ const requestOutgoing = {
+ bidderCode: 'nobid',
+ statusMessage: 'Bid available',
+ adId: '106d14b7d06b607',
+ requestId: '67a7f0e7ea55c4',
+ mediaType: 'banner',
+ cpm: 6.4,
+ adUnitCode: 'leaderboard',
+ timeToRespond: 545,
+ size: '728x90',
+ topLocation: TOP_LOCATION
+ };
+
+ // Step 1: Initialize adapter
+ adapterManager.enableAnalytics({
+ provider: 'nobid',
+ options: initOptions
+ });
+
+ // Step 2: Send init auction event
+ events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions,
+ auctionId: '13',
+ timestamp: Date.now(),
+ bidderRequests: [{refererInfo: {topmostLocation: TOP_LOCATION}}]});
+
+ // Step 3: Send bid won event
+ events.emit(constants.EVENTS.BID_WON, requestIncoming);
+ clock.tick(5000);
+ expect(server.requests).to.have.length(1);
+ const bidWonRequest = JSON.parse(server.requests[0].requestBody);
+ expect(bidWonRequest).to.have.property('bidderCode', requestOutgoing.bidderCode);
+ expect(bidWonRequest).to.have.property('statusMessage', requestOutgoing.statusMessage);
+ expect(bidWonRequest).to.have.property('adId', requestOutgoing.adId);
+ expect(bidWonRequest).to.have.property('requestId', requestOutgoing.requestId);
+ expect(bidWonRequest).to.have.property('mediaType', requestOutgoing.mediaType);
+ expect(bidWonRequest).to.have.property('cpm', requestOutgoing.cpm);
+ expect(bidWonRequest).to.have.property('adUnitCode', requestOutgoing.adUnitCode);
+ expect(bidWonRequest).to.have.property('timeToRespond', requestOutgoing.timeToRespond);
+ expect(bidWonRequest).to.have.property('size', requestOutgoing.size);
+ expect(bidWonRequest).to.have.property('topLocation', requestOutgoing.topLocation);
+ expect(bidWonRequest).to.not.have.property('pbCg');
+
+ done();
+ });
+
+ it('auctionEnd test', function (done) {
+ const initOptions = {
+ options: {
+ siteId: SITE_ID
+ }
+ };
+
+ nobidAnalytics.enableAnalytics(initOptions);
+
+ const TOP_LOCATION = 'https://www.somesite.com';
+
+ const requestIncoming = {
+ auctionId: '4c056b3c-f1a6-46bd-8d82-58c15b22fcfa',
+ timestamp: 1692224437573,
+ auctionEnd: 1692224437986,
+ auctionStatus: 'completed',
+ adUnits: [
+ {
+ code: 'leaderboard',
+ sizes: [[728, 90]],
+ sizeConfig: [
+ { minViewPort: [0, 0], sizes: [[300, 250]] },
+ { minViewPort: [750, 0], sizes: [[728, 90]] }
+ ],
+ adunit: '/111111/adunit',
+ bids: [{ bidder: 'nobid', params: { siteId: SITE_ID } }]
+ }
+ ],
+ adUnitCodes: ['leaderboard'],
+ bidderRequests: [
+ {
+ bidderCode: 'nobid',
+ auctionId: '4c056b3c-f1a6-46bd-8d82-58c15b22fcfa',
+ bidderRequestId: '5beedb9f99ad98',
+ bids: [
+ {
+ bidder: 'nobid',
+ params: { siteId: SITE_ID },
+ mediaTypes: { banner: { sizes: [[728, 90]] } },
+ adUnitCode: 'leaderboard',
+ transactionId: 'bcda424d-f4f4-419b-acf9-1808d2dd22b1',
+ sizes: [[728, 90]],
+ bidId: '6ef0277f36c8df',
+ bidderRequestId: '5beedb9f99ad98',
+ auctionId: '4c056b3c-f1a6-46bd-8d82-58c15b22fcfa',
+ src: 'client',
+ bidRequestsCount: 1,
+ bidderRequestsCount: 1,
+ bidderWinsCount: 0,
+ ortb2: {
+ site: {
+ domain: 'site.me',
+ publisher: {
+ domain: 'site.me'
+ },
+ page: TOP_LOCATION
+ },
+ device: {
+ w: 2605,
+ h: 895,
+ dnt: 0,
+ ua: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
+ language: 'en',
+ }
+ }
+ }
+ ],
+ auctionStart: 1692224437573,
+ timeout: 3000,
+ refererInfo: {
+ topmostLocation: TOP_LOCATION,
+ location: TOP_LOCATION,
+ page: TOP_LOCATION,
+ domain: 'site.me',
+ ref: null,
+ }
+ }
+ ],
+ noBids: [
+ ],
+ bidsReceived: [
+ {
+ bidderCode: 'nobid',
+ width: 728,
+ height: 90,
+ statusMessage: 'Bid available',
+ adId: '95781b6ae5ef2f',
+ requestId: '6ef0277f36c8df',
+ transactionId: 'bcda424d-f4f4-419b-acf9-1808d2dd22b1',
+ auctionId: '4c056b3c-f1a6-46bd-8d82-58c15b22fcfa',
+ mediaType: 'banner',
+ source: 'client',
+ cpm: 6.44,
+ creativeId: 'TEST',
+ dealId: '',
+ currency: 'USD',
+ netRevenue: true,
+ ttl: 300,
+ ad: '',
+ meta: {
+ advertiserDomains: [
+ 'advertiser_domain.com'
+ ]
+ },
+ adapterCode: 'nobid',
+ originalCpm: 6.44,
+ originalCurrency: 'USD',
+ responseTimestamp: 1692224437982,
+ requestTimestamp: 1692224437576,
+ bidder: 'nobid',
+ adUnitCode: 'leaderboard',
+ timeToRespond: 0,
+ pbLg: 5.00,
+ pbCg: '',
+ size: '728x90',
+ adserverTargeting: { hb_bidder: 'nobid', hb_pb: '6.40' },
+ status: 'targetingSet'
+ }
+ ],
+ bidsRejected: [],
+ winningBids: [],
+ timeout: 3000
+ };
+
+ const requestOutgoing = {
+ auctionId: '4c056b3c-f1a6-46bd-8d82-58c15b22fcfa',
+ bidderRequests: [
+ {
+ bidderCode: 'nobid',
+ bidderRequestId: '7c1940bb285731',
+ bids: [
+ {
+ bidder: 'nobid',
+ params: { siteId: SITE_ID },
+ mediaTypes: { banner: { sizes: [[728, 90]] } },
+ adUnitCode: 'leaderboard',
+ sizes: [[728, 90]],
+ src: 'client',
+ bidRequestsCount: 1,
+ bidderRequestsCount: 1
+ }
+ ],
+ refererInfo: {
+ topmostLocation: TOP_LOCATION
+ }
+ }
+ ],
+ bidsReceived: [
+ {
+ bidderCode: 'nobid',
+ width: 728,
+ height: 90,
+ mediaType: 'banner',
+ cpm: 6.44,
+ adUnitCode: 'leaderboard'
+ }
+ ]
+ };
+
+ // Step 1: Initialize adapter
+ adapterManager.enableAnalytics({
+ provider: 'nobid',
+ options: initOptions
+ });
+
+ // Step 2: Send init auction event
+ events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions,
+ auctionId: '13',
+ timestamp: Date.now(),
+ bidderRequests: [{refererInfo: {topmostLocation: `${TOP_LOCATION}_something`}}]});
+
+ // Step 3: Send bid won event
+ events.emit(constants.EVENTS.AUCTION_END, requestIncoming);
+ clock.tick(5000);
+ expect(server.requests).to.have.length(1);
+ 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].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);
+
+ done();
+ });
+
+ it('Analytics disabled test', function (done) {
+ let disabled;
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled: false}));
+ disabled = nobidAnalytics.isAnalyticsDisabled();
+ expect(disabled).to.equal(false);
+ events.emit(constants.EVENTS.AUCTION_END, {auctionId: '1234567890'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(1);
+ events.emit(constants.EVENTS.AUCTION_END, {auctionId: '12345678901'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(2);
+
+ nobidAnalytics.processServerResponse('disabled: true');
+ events.emit(constants.EVENTS.AUCTION_END, {auctionId: '12345678902'});
+ clock.tick(1000);
+ expect(server.requests).to.have.length(3);
+
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled: true}));
+ disabled = nobidAnalytics.isAnalyticsDisabled();
+ expect(disabled).to.equal(true);
+ events.emit(constants.EVENTS.AUCTION_END, {auctionId: '12345678902'});
+ clock.tick(5000);
+ expect(server.requests).to.have.length(3);
+
+ nobidAnalytics.retentionSeconds = 5;
+ nobidAnalytics.processServerResponse(JSON.stringify({disabled: true}));
+ clock.tick(1000);
+ disabled = nobidAnalytics.isAnalyticsDisabled();
+ expect(disabled).to.equal(true);
+ clock.tick(6000);
+ disabled = nobidAnalytics.isAnalyticsDisabled();
+ expect(disabled).to.equal(false);
+
+ done();
+ });
+ });
+
+ describe('NoBid Carbonizer', 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('Carbonizer test', function (done) {
+ let active = nobidCarbonizer.isActive();
+ expect(active).to.equal(false);
+
+ active = nobidCarbonizer.isActive(JSON.stringify({carbonizer_active: false}));
+ expect(active).to.equal(false);
+
+ nobidAnalytics.processServerResponse(JSON.stringify({carbonizer_active: true}));
+ active = nobidCarbonizer.isActive();
+ expect(active).to.equal(true);
+
+ const previousRetention = nobidAnalytics.retentionSeconds;
+ nobidAnalytics.retentionSeconds = 3;
+ nobidAnalytics.processServerResponse(JSON.stringify({carbonizer_active: true}));
+ let stored = nobidCarbonizer.getStoredLocalData();
+ expect(stored[nobidAnalytics.ANALYTICS_DATA_NAME]).to.contain(`{"carbonizer_active":true,"ts":`);
+ clock.tick(5000);
+ active = nobidCarbonizer.isActive(adunits, true);
+ expect(active).to.equal(false);
+
+ nobidAnalytics.retentionSeconds = previousRetention;
+ nobidAnalytics.processServerResponse(JSON.stringify({carbonizer_active: true}));
+ active = nobidCarbonizer.isActive(adunits, true);
+ expect(active).to.equal(true);
+
+ let adunits = [
+ {
+ bids: [
+ { bidder: 'bidder1' },
+ { bidder: 'bidder2' }
+ ]
+ }
+ ]
+ 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/oguryBidAdapter_spec.js b/test/spec/modules/oguryBidAdapter_spec.js
index ed358af19b6..aad753571a8 100644
--- a/test/spec/modules/oguryBidAdapter_spec.js
+++ b/test/spec/modules/oguryBidAdapter_spec.js
@@ -42,7 +42,21 @@ describe('OguryBidAdapter', function () {
return floorResult;
},
- transactionId: 'transactionId'
+ transactionId: 'transactionId',
+ userId: {
+ pubcid: '2abb10e5-c4f6-4f70-9f45-2200e4487714'
+ },
+ userIdAsEids: [
+ {
+ source: 'pubcid.org',
+ uids: [
+ {
+ id: '2abb10e5-c4f6-4f70-9f45-2200e4487714',
+ atype: 1
+ }
+ ]
+ }
+ ]
},
{
adUnitCode: 'adUnitCode2',
@@ -407,12 +421,26 @@ describe('OguryBidAdapter', function () {
},
user: {
ext: {
- consent: bidderRequest.gdprConsent.consentString
+ consent: bidderRequest.gdprConsent.consentString,
+ uids: {
+ pubcid: '2abb10e5-c4f6-4f70-9f45-2200e4487714'
+ },
+ eids: [
+ {
+ source: 'pubcid.org',
+ uids: [
+ {
+ id: '2abb10e5-c4f6-4f70-9f45-2200e4487714',
+ atype: 1
+ }
+ ]
+ }
+ ],
},
},
ext: {
prebidversion: '$prebid.version$',
- adapterversion: '1.5.0'
+ adapterversion: '1.6.0'
},
device: {
w: stubbedWidth,
@@ -637,7 +665,9 @@ describe('OguryBidAdapter', function () {
},
user: {
ext: {
- consent: ''
+ consent: '',
+ uids: expectedRequestObject.user.ext.uids,
+ eids: expectedRequestObject.user.ext.eids
},
}
};
@@ -663,7 +693,9 @@ describe('OguryBidAdapter', function () {
},
user: {
ext: {
- consent: ''
+ consent: '',
+ uids: expectedRequestObject.user.ext.uids,
+ eids: expectedRequestObject.user.ext.eids
},
}
};
@@ -689,7 +721,9 @@ describe('OguryBidAdapter', function () {
},
user: {
ext: {
- consent: ''
+ consent: '',
+ uids: expectedRequestObject.user.ext.uids,
+ eids: expectedRequestObject.user.ext.eids
},
}
};
@@ -701,6 +735,48 @@ describe('OguryBidAdapter', function () {
expect(request.data.regs.ext.gdpr).to.be.a('number');
});
+ it('should should not add uids infos if userId is undefined', () => {
+ const expectedRequestWithUndefinedUserId = {
+ ...expectedRequestObject,
+ user: {
+ ext: {
+ consent: expectedRequestObject.user.ext.consent,
+ eids: expectedRequestObject.user.ext.eids
+ }
+ }
+ };
+
+ const validBidRequests = utils.deepClone(bidRequests);
+ validBidRequests[0] = {
+ ...validBidRequests[0],
+ userId: undefined
+ };
+
+ const request = spec.buildRequests(validBidRequests, bidderRequest);
+ expect(request.data).to.deep.equal(expectedRequestWithUndefinedUserId);
+ });
+
+ it('should should not add uids infos if userIdAsEids is undefined', () => {
+ const expectedRequestWithUndefinedUserIdAsEids = {
+ ...expectedRequestObject,
+ user: {
+ ext: {
+ consent: expectedRequestObject.user.ext.consent,
+ uids: expectedRequestObject.user.ext.uids
+ }
+ }
+ };
+
+ const validBidRequests = utils.deepClone(bidRequests);
+ validBidRequests[0] = {
+ ...validBidRequests[0],
+ userIdAsEids: undefined
+ };
+
+ const request = spec.buildRequests(validBidRequests, bidderRequest);
+ expect(request.data).to.deep.equal(expectedRequestWithUndefinedUserIdAsEids);
+ });
+
it('should handle bidFloor undefined', () => {
const expectedRequestWithUndefinedFloor = {
...expectedRequestObject
@@ -814,7 +890,7 @@ describe('OguryBidAdapter', function () {
advertiserDomains: openRtbBidResponse.body.seatbid[0].bid[0].adomain
},
nurl: openRtbBidResponse.body.seatbid[0].bid[0].nurl,
- adapterVersion: '1.5.0',
+ adapterVersion: '1.6.0',
prebidVersion: '$prebid.version$'
}, {
requestId: openRtbBidResponse.body.seatbid[0].bid[1].impid,
@@ -831,7 +907,7 @@ describe('OguryBidAdapter', function () {
advertiserDomains: openRtbBidResponse.body.seatbid[0].bid[1].adomain
},
nurl: openRtbBidResponse.body.seatbid[0].bid[1].nurl,
- adapterVersion: '1.5.0',
+ adapterVersion: '1.6.0',
prebidVersion: '$prebid.version$'
}]
diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js
index df6456db82e..7960574c1a4 100644
--- a/test/spec/modules/onetagBidAdapter_spec.js
+++ b/test/spec/modules/onetagBidAdapter_spec.js
@@ -15,9 +15,14 @@ describe('onetag', function () {
'bidId': '30b31c1838de1e',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475',
- ortb2Imp: {
- ext: {
- tid: 'qwerty123'
+ 'ortb2Imp': {
+ 'ext': {
+ 'tid': '0000'
+ }
+ },
+ 'ortb2': {
+ 'source': {
+ 'tid': '1111'
}
},
'schain': {
@@ -184,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';
});
@@ -208,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'];
@@ -256,6 +262,15 @@ describe('onetag', function () {
expect(dataObj.bids).to.be.an('array').that.is.empty;
} catch (e) { }
});
+ it('Should pick each bid\'s auctionId and transactionId from ortb2 related fields', function () {
+ const serverRequest = spec.buildRequests([bannerBid]);
+ const payload = JSON.parse(serverRequest.data);
+
+ expect(payload).to.exist;
+ expect(payload.bids).to.exist.and.to.have.length(1);
+ expect(payload.bids[0].auctionId).to.equal(bannerBid.ortb2.source.tid);
+ expect(payload.bids[0].transactionId).to.equal(bannerBid.ortb2Imp.ext.tid);
+ });
it('should send GDPR consent data', function () {
let consentString = 'consentString';
let bidderRequest = {
@@ -382,13 +397,61 @@ describe('onetag', function () {
expect(payload.ortb2).to.exist.and.to.deep.equal(firtPartyData);
});
});
+ 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');
@@ -586,6 +649,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 f2cff7f470c..1af0fce103d 100644
--- a/test/spec/modules/openxBidAdapter_spec.js
+++ b/test/spec/modules/openxBidAdapter_spec.js
@@ -14,6 +14,7 @@ import 'modules/consentManagement.js';
import 'modules/consentManagementUsp.js';
import 'modules/schain.js';
import {deepClone} from 'src/utils.js';
+import {version} from 'package.json';
import {syncAddFPDToBidderRequest} from '../../helpers/fpd.js';
import {hook} from '../../../src/hook.js';
@@ -316,6 +317,7 @@ describe('OpenxRtbAdapter', function () {
const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
expect(request[0].url).to.equal(REQUEST_URL);
expect(request[0].method).to.equal('POST');
+ expect(request[0].data.ext.pv).to.equal(version);
});
it('should send delivery domain, if available', function () {
diff --git a/test/spec/modules/operaadsBidAdapter_spec.js b/test/spec/modules/operaadsBidAdapter_spec.js
index 37d4a2c7bc0..9a8981235d5 100644
--- a/test/spec/modules/operaadsBidAdapter_spec.js
+++ b/test/spec/modules/operaadsBidAdapter_spec.js
@@ -266,6 +266,95 @@ describe('Opera Ads Bid Adapter', function () {
}
});
+ describe('test fulfilling inventory information', function () {
+ const bidRequest = {
+ adUnitCode: 'test-div',
+ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917',
+ bidId: '22c4871113f461',
+ bidder: 'operaads',
+ bidderRequestId: '15246a574e859f',
+ mediaTypes: {
+ banner: {sizes: [[300, 250]]}
+ },
+ params: {
+ placementId: 's12345678',
+ publisherId: 'pub12345678',
+ endpointId: 'ep12345678'
+ }
+ }
+
+ const getRequest = function () {
+ let reqs;
+ expect(function () {
+ reqs = spec.buildRequests([bidRequest], bidderRequest);
+ }).to.not.throw();
+ return JSON.parse(reqs[0].data);
+ }
+
+ it('test default case', function () {
+ let requestData = getRequest();
+ expect(requestData.site).to.be.an('object');
+ expect(requestData.site.id).to.equal(bidRequest.params.publisherId);
+ expect(requestData.site.domain).to.not.be.empty;
+ expect(requestData.site.page).to.equal(bidderRequest.refererInfo.page);
+ });
+
+ it('test a case with site information specified', function () {
+ bidRequest.params = {
+ placementId: 's12345678',
+ publisherId: 'pub12345678',
+ endpointId: 'ep12345678',
+ site: {
+ name: 'test-site-1',
+ domain: 'www.test.com'
+ }
+ }
+ let requestData = getRequest();
+ expect(requestData.site).to.be.an('object');
+ expect(requestData.site.id).to.equal(bidRequest.params.publisherId);
+ expect(requestData.site.name).to.equal('test-site-1');
+ expect(requestData.site.domain).to.equal('www.test.com');
+ expect(requestData.site.page).to.equal(bidderRequest.refererInfo.page);
+ });
+
+ it('test a case with app information specified', function () {
+ bidRequest.params = {
+ placementId: 's12345678',
+ publisherId: 'pub12345678',
+ endpointId: 'ep12345678',
+ app: {
+ name: 'test-app-1'
+ }
+ }
+ let requestData = getRequest();
+ expect(requestData.app).to.be.an('object');
+ expect(requestData.app.id).to.equal(bidRequest.params.publisherId);
+ expect(requestData.app.name).to.equal('test-app-1');
+ expect(requestData.app.domain).to.not.be.empty;
+ });
+
+ it('test a case with both site and app information specified', function () {
+ bidRequest.params = {
+ placementId: 's12345678',
+ publisherId: 'pub12345678',
+ endpointId: 'ep12345678',
+ site: {
+ name: 'test-site-2',
+ page: 'test-page'
+ },
+ app: {
+ name: 'test-app-1'
+ }
+ }
+ let requestData = getRequest();
+ expect(requestData.site).to.be.an('object');
+ expect(requestData.site.id).to.equal(bidRequest.params.publisherId);
+ expect(requestData.site.name).to.equal('test-site-2');
+ expect(requestData.site.page).to.equal('test-page');
+ expect(requestData.site.domain).to.not.be.empty;
+ });
+ });
+
it('test getBidFloor', function() {
const bidRequests = [
{
diff --git a/test/spec/modules/optidigitalBidAdapter_spec.js b/test/spec/modules/optidigitalBidAdapter_spec.js
index 62c37f85cc8..30e72452c39 100755
--- a/test/spec/modules/optidigitalBidAdapter_spec.js
+++ b/test/spec/modules/optidigitalBidAdapter_spec.js
@@ -479,6 +479,28 @@ describe('optidigitalAdapterTests', function () {
expect(payload.imp[0].bidFloor).to.exist;
});
+ it('should add userEids to payload', function() {
+ const userIdAsEids = [{
+ source: 'pubcid.org',
+ uids: [{
+ id: '121213434342343',
+ atype: 1
+ }]
+ }];
+ validBidRequests[0].userIdAsEids = userIdAsEids;
+ bidderRequest.userIdAsEids = userIdAsEids;
+ const request = spec.buildRequests(validBidRequests, bidderRequest);
+ const payload = JSON.parse(request.data);
+ expect(payload.user.eids).to.deep.equal(userIdAsEids);
+ });
+
+ it('should not add userIdAsEids to payload when userIdAsEids is not present', function() {
+ validBidRequests[0].userIdAsEids = undefined;
+ const request = spec.buildRequests(validBidRequests, bidderRequest);
+ const payload = JSON.parse(request.data);
+ expect(payload.user).to.deep.equal(undefined);
+ });
+
function returnBannerSizes(mediaTypes, expectedSizes) {
const bidRequest = Object.assign(validBidRequests[0], mediaTypes);
const request = spec.buildRequests([bidRequest], bidderRequest);
diff --git a/test/spec/modules/optimeraRtdProvider_spec.js b/test/spec/modules/optimeraRtdProvider_spec.js
index aec8b79045e..8a9f000bbb9 100644
--- a/test/spec/modules/optimeraRtdProvider_spec.js
+++ b/test/spec/modules/optimeraRtdProvider_spec.js
@@ -21,13 +21,80 @@ describe('Optimera RTD sub module', () => {
});
});
-describe('Optimera RTD score file url is properly set', () => {
- it('Proerly set the score file url', () => {
+describe('Optimera RTD score file URL is properly set for v0', () => {
+ it('should properly set the score file URL', () => {
+ const conf = {
+ dataProviders: [{
+ name: 'optimeraRTD',
+ params: {
+ clientID: '9999',
+ optimeraKeyName: 'optimera',
+ device: 'de',
+ apiVersion: 'v0',
+ }
+ }]
+ };
+ optimeraRTD.init(conf.dataProviders[0]);
+ optimeraRTD.setScores();
+ expect(optimeraRTD.apiVersion).to.equal('v0');
+ expect(optimeraRTD.scoresURL).to.equal('https://dyv1bugovvq1g.cloudfront.net/9999/localhost:9876/context.html.js');
+ });
+
+ it('should properly set the score file URL without apiVersion set', () => {
+ const conf = {
+ dataProviders: [{
+ name: 'optimeraRTD',
+ params: {
+ clientID: '9999',
+ optimeraKeyName: 'optimera',
+ device: 'de',
+ }
+ }]
+ };
+ optimeraRTD.init(conf.dataProviders[0]);
+ optimeraRTD.setScores();
+ expect(optimeraRTD.apiVersion).to.equal('v0');
+ expect(optimeraRTD.scoresURL).to.equal('https://dyv1bugovvq1g.cloudfront.net/9999/localhost:9876/context.html.js');
+ });
+
+ it('should properly set the score file URL with an api version other than v0 or v1', () => {
+ const conf = {
+ dataProviders: [{
+ name: 'optimeraRTD',
+ params: {
+ clientID: '9999',
+ optimeraKeyName: 'optimera',
+ device: 'de',
+ apiVersion: 'v15',
+ }
+ }]
+ };
+ optimeraRTD.init(conf.dataProviders[0]);
optimeraRTD.setScores();
expect(optimeraRTD.scoresURL).to.equal('https://dyv1bugovvq1g.cloudfront.net/9999/localhost:9876/context.html.js');
});
});
+describe('Optimera RTD score file URL is properly set for v1', () => {
+ it('should properly set the score file URL', () => {
+ const conf = {
+ dataProviders: [{
+ name: 'optimeraRTD',
+ params: {
+ clientID: '9999',
+ optimeraKeyName: 'optimera',
+ device: 'de',
+ apiVersion: 'v1',
+ }
+ }]
+ };
+ optimeraRTD.init(conf.dataProviders[0]);
+ optimeraRTD.setScores();
+ expect(optimeraRTD.apiVersion).to.equal('v1');
+ expect(optimeraRTD.scoresURL).to.equal('https://v1.oapi26b.com/api/products/scores?c=9999&h=localhost:9876&p=/context.html&s=de');
+ });
+});
+
describe('Optimera RTD score file properly sets targeting values', () => {
const scores = {
'div-0': ['A1', 'A2'],
diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js
index acb779b436d..cf58d35e636 100644
--- a/test/spec/modules/orbidderBidAdapter_spec.js
+++ b/test/spec/modules/orbidderBidAdapter_spec.js
@@ -1,6 +1,6 @@
-import {expect} from 'chai';
-import {spec} from 'modules/orbidderBidAdapter.js';
-import {newBidder} from 'src/adapters/bidderFactory.js';
+import { expect } from 'chai';
+import { spec } from 'modules/orbidderBidAdapter.js';
+import { newBidder } from 'src/adapters/bidderFactory.js';
import * as _ from 'lodash';
import { BANNER, NATIVE } from '../../../src/mediaTypes.js';
@@ -9,39 +9,57 @@ describe('orbidderBidAdapter', () => {
const defaultBidRequestBanner = {
bidId: 'd66fa86787e0b0ca900a96eacfd5f0bb',
auctionId: 'ccc4c7cdfe11cfbd74065e6dd28413d8',
- ortb2Imp: {
- ext: {
- tid: 'd58851660c0c4461e4aa06344fc9c0c6',
- }
- },
+ transactionId: 'd58851660c0c4461e4aa06344fc9c0c6',
bidRequestCount: 1,
adUnitCode: 'adunit-code',
sizes: [[300, 250], [300, 600]],
params: {
'accountId': 'string1',
- 'placementId': 'string2'
+ 'placementId': 'string2',
+ 'bidfloor': 1.23
},
mediaTypes: {
banner: {
- sizes: [[300, 250], [300, 600]],
+ sizes: [[300, 250], [300, 600]]
}
- }
+ },
+ userId: {
+ 'id5id': {
+ 'uid': 'ID5*XXXXXXXXXXXXX',
+ 'ext': {
+ 'linkType': 2,
+ 'pba': 'XXXXXXXXXXXX=='
+ }
+ }
+ },
+ userIdAsEids: [
+ {
+ 'source': 'id5-sync.com',
+ 'uids': [
+ {
+ 'id': 'ID5*XXXXXXXXXXXXX',
+ 'atype': 1,
+ 'ext': {
+ 'linkType': 2,
+ 'pba': 'XXXXXXXXXXXX=='
+ }
+ }
+ ]
+ }
+ ]
};
const defaultBidRequestNative = {
bidId: 'd66fa86787e0b0ca900a96eacfd5f0bc',
auctionId: 'ccc4c7cdfe11cfbd74065e6dd28413d9',
- ortb2Imp: {
- ext: {
- tid: 'd58851660c0c4461e4aa06344fc9c0c7',
- }
- },
+ transactionId: 'd58851660c0c4461e4aa06344fc9c0c6',
bidRequestCount: 1,
adUnitCode: 'adunit-code-native',
sizes: [],
params: {
'accountId': 'string3',
- 'placementId': 'string4'
+ 'placementId': 'string4',
+ 'bidfloor': 2.34
},
mediaTypes: {
native: {
@@ -56,10 +74,34 @@ describe('orbidderBidAdapter', () => {
required: true
}
}
- }
+ },
+ userId: {
+ 'id5id': {
+ 'uid': 'ID5*YYYYYYYYYYYYYYY',
+ 'ext': {
+ 'linkType': 2,
+ 'pba': 'YYYYYYYYYYYYY=='
+ }
+ }
+ },
+ userIdAsEids: [
+ {
+ 'source': 'id5-sync.com',
+ 'uids': [
+ {
+ 'id': 'ID5*YYYYYYYYYYYYYYY',
+ 'atype': 1,
+ 'ext': {
+ 'linkType': 2,
+ 'pba': 'YYYYYYYYYYYYY=='
+ }
+ }
+ ]
+ }
+ ]
};
- const deepClone = function (val) {
+ const deepClone = function(val) {
return JSON.parse(JSON.stringify(val));
};
@@ -91,15 +133,15 @@ describe('orbidderBidAdapter', () => {
expect(spec.isBidRequestValid(defaultBidRequestNative)).to.equal(true);
});
- it('banner: accepts optional profile object', () => {
+ it('banner: accepts optional keyValues object', () => {
const bidRequest = deepClone(defaultBidRequestBanner);
- bidRequest.params.profile = {'key': 'value'};
+ bidRequest.params.keyValues = { 'key': 'value' };
expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
});
- it('native: accepts optional profile object', () => {
+ it('native: accepts optional keyValues object', () => {
const bidRequest = deepClone(defaultBidRequestNative);
- bidRequest.params.profile = {'key': 'value'};
+ bidRequest.params.keyValues = { 'key': 'value' };
expect(spec.isBidRequestValid(bidRequest)).to.equal(true);
});
@@ -115,15 +157,15 @@ describe('orbidderBidAdapter', () => {
expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
});
- it('banner: doesn\'t accept malformed profile', () => {
+ it('banner: doesn\'t accept malformed keyValues', () => {
const bidRequest = deepClone(defaultBidRequestBanner);
- bidRequest.params.profile = 'another not usable string';
+ bidRequest.params.keyValues = 'another not usable string';
expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
});
- it('native: doesn\'t accept malformed profile', () => {
+ it('native: doesn\'t accept malformed keyValues', () => {
const bidRequest = deepClone(defaultBidRequestNative);
- bidRequest.params.profile = 'another not usable string';
+ bidRequest.params.keyValues = 'another not usable string';
expect(spec.isBidRequestValid(bidRequest)).to.equal(false);
});
@@ -179,34 +221,20 @@ describe('orbidderBidAdapter', () => {
// we add two, because we add pageUrl and version from bidderRequest object
expect(Object.keys(request.data).length).to.equal(Object.keys(defaultBidRequestBanner).length + 2);
- expect(request.data.bidId).to.equal(defaultBidRequestBanner.bidId);
- expect(request.data.auctionId).to.equal(defaultBidRequestBanner.auctionId);
- expect(request.data.transactionId).to.equal(defaultBidRequestBanner.ortb2Imp.ext.tid);
- expect(request.data.bidRequestCount).to.equal(defaultBidRequestBanner.bidRequestCount);
- expect(request.data.adUnitCode).to.equal(defaultBidRequestBanner.adUnitCode);
- expect(request.data.pageUrl).to.equal('https://localhost:9876/');
- expect(request.data.v).to.equal($$PREBID_GLOBAL$$.version);
- expect(request.data.sizes).to.equal(defaultBidRequestBanner.sizes);
-
- expect(_.isEqual(request.data.params, defaultBidRequestBanner.params)).to.be.true;
- expect(_.isEqual(request.data.mediaTypes, defaultBidRequestBanner.mediaTypes)).to.be.true;
+ const expectedBidRequest = deepClone(defaultBidRequestBanner);
+ expectedBidRequest.pageUrl = 'https://localhost:9876/';
+ expectedBidRequest.v = $$PREBID_GLOBAL$$.version;
+ expect(request.data).to.deep.equal(expectedBidRequest);
});
it('native: sends correct bid parameters', () => {
// we add two, because we add pageUrl and version from bidderRequest object
expect(Object.keys(nativeRequest.data).length).to.equal(Object.keys(defaultBidRequestNative).length + 2);
- expect(nativeRequest.data.bidId).to.equal(defaultBidRequestNative.bidId);
- expect(nativeRequest.data.auctionId).to.equal(defaultBidRequestNative.auctionId);
- expect(nativeRequest.data.transactionId).to.equal(defaultBidRequestNative.ortb2Imp.ext.tid);
- expect(nativeRequest.data.bidRequestCount).to.equal(defaultBidRequestNative.bidRequestCount);
- expect(nativeRequest.data.adUnitCode).to.equal(defaultBidRequestNative.adUnitCode);
- expect(nativeRequest.data.pageUrl).to.equal('https://localhost:9876/');
- expect(nativeRequest.data.v).to.equal($$PREBID_GLOBAL$$.version);
- expect(nativeRequest.data.sizes).to.be.empty;
-
- expect(_.isEqual(nativeRequest.data.params, defaultBidRequestNative.params)).to.be.true;
- expect(_.isEqual(nativeRequest.data.mediaTypes, defaultBidRequestNative.mediaTypes)).to.be.true;
+ const expectedBidRequest = deepClone(defaultBidRequestNative);
+ expectedBidRequest.pageUrl = 'https://localhost:9876/';
+ expectedBidRequest.v = $$PREBID_GLOBAL$$.version;
+ expect(nativeRequest.data).to.deep.equal(expectedBidRequest);
});
it('banner: handles empty gdpr object', () => {
@@ -347,7 +375,7 @@ describe('orbidderBidAdapter', () => {
}
];
- const result = spec.interpretResponse({body: serverResponse});
+ const result = spec.interpretResponse({ body: serverResponse });
expect(result.length).to.equal(expectedResponse.length);
expect(_.isEqual(expectedResponse, serverResponse)).to.be.true;
});
@@ -387,7 +415,7 @@ describe('orbidderBidAdapter', () => {
}
];
- const result = spec.interpretResponse({body: serverResponse});
+ const result = spec.interpretResponse({ body: serverResponse });
expect(result.length).to.equal(expectedResponse.length);
Object.keys(expectedResponse[0]).forEach((key) => {
@@ -454,7 +482,7 @@ describe('orbidderBidAdapter', () => {
}
];
- const result = spec.interpretResponse({body: serverResponse});
+ const result = spec.interpretResponse({ body: serverResponse });
expect(result.length).to.equal(expectedResponse.length);
expect(_.isEqual(expectedResponse, serverResponse)).to.be.true;
@@ -474,7 +502,7 @@ describe('orbidderBidAdapter', () => {
'netRevenue': true,
}
];
- const result = spec.interpretResponse({body: serverResponse});
+ const result = spec.interpretResponse({ body: serverResponse });
expect(result.length).to.equal(0);
});
@@ -492,7 +520,7 @@ describe('orbidderBidAdapter', () => {
'creativeId': '29681110',
}
];
- const result = spec.interpretResponse({body: serverResponse});
+ const result = spec.interpretResponse({ body: serverResponse });
expect(result.length).to.equal(0);
});
@@ -518,13 +546,13 @@ describe('orbidderBidAdapter', () => {
}
}
];
- const result = spec.interpretResponse({body: serverResponse});
+ const result = spec.interpretResponse({ body: serverResponse });
expect(result.length).to.equal(0);
});
it('handles nobid responses', () => {
const serverResponse = [];
- const result = spec.interpretResponse({body: serverResponse});
+ const result = spec.interpretResponse({ body: serverResponse });
expect(result.length).to.equal(0);
});
});
diff --git a/test/spec/modules/outbrainBidAdapter_spec.js b/test/spec/modules/outbrainBidAdapter_spec.js
index d8690aeb6a5..e6abb5e9caa 100644
--- a/test/spec/modules/outbrainBidAdapter_spec.js
+++ b/test/spec/modules/outbrainBidAdapter_spec.js
@@ -1,5 +1,5 @@
import { expect } from 'chai';
-import { spec } from 'modules/outbrainBidAdapter.js';
+import { spec, storage } from 'modules/outbrainBidAdapter.js';
import { config } from 'src/config.js';
import { server } from 'test/mocks/xhr';
@@ -213,15 +213,18 @@ describe('Outbrain Adapter', function () {
})
describe('buildRequests', function () {
+ let getDataFromLocalStorageStub;
+
before(() => {
+ getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage')
config.setConfig({
outbrain: {
bidderUrl: 'https://bidder-url.com',
}
- }
- )
+ })
})
after(() => {
+ getDataFromLocalStorageStub.restore()
config.resetConfig()
})
@@ -424,7 +427,7 @@ describe('Outbrain Adapter', function () {
expect(resData.badv).to.deep.equal(['bad-advertiser'])
});
- it('first party data', function () {
+ it('should pass first party data', function () {
const bidRequest = {
...commonBidRequest,
...nativeBidRequestParams,
@@ -505,6 +508,28 @@ describe('Outbrain Adapter', function () {
config.resetConfig()
});
+ it('should pass gpp information', function () {
+ const bidRequest = {
+ ...commonBidRequest,
+ ...nativeBidRequestParams,
+ };
+ const bidderRequest = {
+ ...commonBidderRequest,
+ 'gppConsent': {
+ 'gppString': 'abc12345',
+ 'applicableSections': [8]
+ }
+ }
+
+ const res = spec.buildRequests([bidRequest], bidderRequest);
+ const resData = JSON.parse(res.data);
+
+ expect(resData.regs.ext.gpp).to.exist;
+ expect(resData.regs.ext.gpp_sid).to.exist;
+ expect(resData.regs.ext.gpp).to.equal('abc12345');
+ expect(resData.regs.ext.gpp_sid).to.deep.equal([8]);
+ });
+
it('should pass extended ids', function () {
let bidRequest = {
bidId: 'bidId',
@@ -522,6 +547,22 @@ describe('Outbrain Adapter', function () {
]);
});
+ it('should pass OB user token', function () {
+ getDataFromLocalStorageStub.returns('12345');
+
+ let bidRequest = {
+ bidId: 'bidId',
+ params: {},
+ ...commonBidRequest,
+ };
+
+ let res = spec.buildRequests([bidRequest], commonBidderRequest);
+ const resData = JSON.parse(res.data)
+ expect(resData.user.ext.obusertoken).to.equal('12345')
+ expect(getDataFromLocalStorageStub.called).to.be.true;
+ sinon.assert.calledWith(getDataFromLocalStorageStub, 'OB-USER-TOKEN');
+ });
+
it('should pass bidfloor', function () {
const bidRequest = {
...commonBidRequest,
@@ -842,6 +883,12 @@ describe('Outbrain Adapter', function () {
type: 'image', url: `${usersyncUrl}?gdpr=1&gdpr_consent=foo&us_privacy=1NYN`
}]);
});
+
+ it('should pass gpp consent', function () {
+ expect(spec.getUserSyncs({ pixelEnabled: true }, {}, undefined, '', { gppString: 'abc12345', applicableSections: [1, 2] })).to.deep.equal([{
+ type: 'image', url: `${usersyncUrl}?gpp=abc12345&gpp_sid=1%2C2`
+ }]);
+ });
})
describe('onBidWon', function () {
diff --git a/test/spec/modules/oxxionAnalyticsAdapter_spec.js b/test/spec/modules/oxxionAnalyticsAdapter_spec.js
index 13dc395968a..9d06be24f68 100644
--- a/test/spec/modules/oxxionAnalyticsAdapter_spec.js
+++ b/test/spec/modules/oxxionAnalyticsAdapter_spec.js
@@ -86,20 +86,21 @@ describe('Oxxion Analytics', function () {
}
},
'adUnitCode': 'tag_200124_banner',
- 'transactionId': 'de664ccb-e18b-4436-aeb0-362382eb1b40',
+ 'transactionId': '8b2a8629-d1ea-4bb1-aff0-e335b96dd002',
'sizes': [
[
300,
600
]
],
- 'bidId': '34a63e5d5378a3',
+ 'bidId': '2bd3e8ff8a113f',
'bidderRequestId': '11dc6ff6378de7',
'auctionId': '1e8b993d-8f0a-4232-83eb-3639ddf3a44b',
'src': 'client',
'bidRequestsCount': 1,
'bidderRequestsCount': 1,
- 'bidderWinsCount': 0
+ 'bidderWinsCount': 0,
+ 'ova': 'cleared'
}
],
'auctionStart': 1647424261187,
@@ -149,12 +150,12 @@ describe('Oxxion Analytics', function () {
'bidsReceived': [
{
'bidderCode': 'appnexus',
- 'width': 300,
- 'height': 600,
+ 'width': 970,
+ 'height': 250,
'statusMessage': 'Bid available',
- 'adId': '7a4ced80f33d33',
- 'requestId': '34a63e5d5378a3',
- 'transactionId': 'de664ccb-e18b-4436-aeb0-362382eb1b40',
+ 'adId': '65d16ef039a97a',
+ 'requestId': '2bd3e8ff8a113f',
+ 'transactionId': '8b2a8629-d1ea-4bb1-aff0-e335b96dd002',
'auctionId': '1e8b993d-8f0a-4232-83eb-3639ddf3a44b',
'mediaType': 'video',
'source': 'client',
@@ -187,7 +188,7 @@ describe('Oxxion Analytics', function () {
'size': '300x600',
'adserverTargeting': {
'hb_bidder': 'appnexus',
- 'hb_adid': '7a4ced80f33d33',
+ 'hb_adid': '65d16ef039a97a',
'hb_pb': '20.000000',
'hb_size': '300x600',
'hb_source': 'client',
@@ -342,7 +343,7 @@ describe('Oxxion Analytics', function () {
expect(message).to.have.property('adId')
expect(message).to.have.property('cpmIncrement').and.to.equal(27.4276);
expect(message).to.have.property('oxxionMode').and.to.have.property('abtest').and.to.equal(true);
- // sinon.assert.callCount(oxxionAnalytics.track, 1);
+ expect(message).to.have.property('ova').and.to.equal('cleared');
});
});
});
diff --git a/test/spec/modules/oxxionRtdProvider_spec.js b/test/spec/modules/oxxionRtdProvider_spec.js
index 7bccf2319a4..2a8024f3565 100644
--- a/test/spec/modules/oxxionRtdProvider_spec.js
+++ b/test/spec/modules/oxxionRtdProvider_spec.js
@@ -113,77 +113,6 @@ let bids = [{
},
];
-let originalBidderRequests = [{
- 'bidderCode': 'rubicon',
- 'auctionId': 'dd42b870-2072-4b71-8ab7-e7789b14c5ce',
- 'bidderRequestId': '16c2bceb2e891a',
- 'bids': [
- {
- 'bidder': 'rubicon',
- 'params': {
- 'accountId': 1234,
- 'siteId': 2345,
- 'zoneId': 3456
- },
- 'auctionId': 'dd42b870-2072-4b71-8ab7-e7789b14c5ce',
- 'mediaTypes': {'banner': {'sizes': [[970, 250]]}},
- 'adUnitCode': 'adunit1',
- 'transactionId': '8f20b49c-5e47-4bb5-a7d5-0b816cf527f3',
- 'bidId': '2d9920072ab028',
- 'bidderRequestId': '16c2bceb2e891a',
- },
- {
- 'bidder': 'rubicon',
- 'params': {
- 'accountId': 1234,
- 'siteId': 2345,
- 'zoneId': 4567
- },
- 'auctionId': 'dd42b870-2072-4b71-8ab7-e7789b14c5ce',
- 'mediaTypes': {'banner': {'sizes': [[300, 250]]}},
- 'adUnitCode': 'adunit2',
- 'transactionId': '4161f09e-7870-4486-b2a6-b4158a327bc4',
- 'bidId': '331c3d708f4864',
- 'bidderRequestId': '16c2bceb2e891a',
- 'src': 'client',
- }
- ],
- 'auctionStart': 1683383333809,
- 'timeout': 3000,
- 'gdprConsent': {
- 'consentString': 'consent_hash',
- 'gdprApplies': true,
- 'apiVersion': 2
- }
-},
-{
- 'bidderCode': 'appnexusAst',
- 'auctionId': 'dd42b870-2072-4b71-8ab7-e7789b14c5ce',
- 'bidderRequestId': '4d83b8c60d45e7',
- 'bids': [
- {
- 'bidder': 'appnexusAst',
- 'params': {
- 'placementId': 10471298
- },
- 'auctionId': 'dd42b870-2072-4b71-8ab7-e7789b14c5ce',
- 'mediaTypes': {'banner': {'sizes': [[300, 250]]}},
- 'adUnitCode': 'adunit2',
- 'transactionId': '4161f09e-7870-4486-b2a6-b4158a327bc4',
- 'bidId': '5b7cd5abc6aea3',
- 'bidderRequestId': '4d83b8c60d45e7',
- }
- ],
- 'auctionStart': 1683383333809,
- 'timeout': 3000,
- 'gdprConsent': {
- 'consentString': 'consent_hash',
- 'gdprApplies': true,
- 'apiVersion': 2
- }
-}
-];
-
let bidInterests = [
{'id': 0, 'rate': 50.0, 'suggestion': true},
{'id': 1, 'rate': 12.0, 'suggestion': false},
@@ -212,8 +141,6 @@ describe('oxxionRtdProvider', () => {
auctionEnd.bidsReceived = bids;
it('call everything', function() {
oxxionSubmodule.getBidRequestData(request, null, moduleConfig);
- oxxionSubmodule.onBidResponseEvent(auctionEnd.bidsReceived[0], moduleConfig);
- oxxionSubmodule.onBidResponseEvent(auctionEnd.bidsReceived[1], moduleConfig);
});
it('check bid filtering', function() {
let requestsList = oxxionSubmodule.getRequestsList(request);
@@ -229,27 +156,5 @@ describe('oxxionRtdProvider', () => {
expect(filteredBiddderRequests[1]).to.have.property('bids');
expect(filteredBiddderRequests[1].bids.length).to.equal(1);
});
- it('check vastImpUrl', function() {
- expect(auctionEnd.bidsReceived[0]).to.have.property('vastImpUrl');
- let expectVastImpUrl = 'https://' + moduleConfig.params.domain + '.oxxion.io/analytics/vast_imp?';
- expect(auctionEnd.bidsReceived[1].vastImpUrl).to.contain(expectVastImpUrl);
- expect(auctionEnd.bidsReceived[1].vastImpUrl).to.contain(encodeURI('https://some.tracking-url.com'));
- });
- it('check vastXml', function() {
- expect(auctionEnd.bidsReceived[0]).to.have.property('vastXml');
- let vastWrapper = new DOMParser().parseFromString(auctionEnd.bidsReceived[0].vastXml, 'text/xml');
- let impressions = vastWrapper.querySelectorAll('VAST Ad Wrapper Impression');
- expect(impressions.length).to.equal(2);
- expect(auctionEnd.bidsReceived[1]).to.have.property('vastXml');
- expect(auctionEnd.bidsReceived[1].adId).to.equal('4b2e1581c0ca1a');
- let vastInline = new DOMParser().parseFromString(auctionEnd.bidsReceived[1].vastXml, 'text/xml');
- let inline = vastInline.querySelectorAll('VAST Ad InLine');
- expect(inline).to.have.lengthOf(1);
- let inlineImpressions = vastInline.querySelectorAll('VAST Ad InLine Impression');
- expect(inlineImpressions).to.have.lengthOf.above(0);
- });
- it('check cpmIncrement', function() {
- expect(auctionEnd.bidsReceived[1].vastImpUrl).to.contain(encodeURI('cpmIncrement=0'));
- });
});
});
diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js
index 64b345c5d9c..73df2fba8fd 100644
--- a/test/spec/modules/ozoneBidAdapter_spec.js
+++ b/test/spec/modules/ozoneBidAdapter_spec.js
@@ -2069,6 +2069,19 @@ describe('ozone Adapter', function () {
expect(request.length).to.equal(3);
config.resetConfig();
});
+ it('should not batch into 10s if config is set to false and singleRequest is true', function () {
+ config.setConfig({ozone: {'batchRequests': false, 'singleRequest': true}});
+ var specMock = utils.deepClone(spec);
+ let arrReq = [];
+ for (let i = 0; i < 15; i++) {
+ let b = validBidRequests[0];
+ b.adUnitCode += i;
+ arrReq.push(b);
+ }
+ const request = specMock.buildRequests(arrReq, validBidderRequest);
+ expect(request.method).to.equal('POST');
+ config.resetConfig();
+ });
it('should use GET values auction=dev & cookiesync=dev if set', function() {
var specMock = utils.deepClone(spec);
specMock.getGetParametersAsObject = function() {
diff --git a/test/spec/modules/pangleBidAdapter_spec.js b/test/spec/modules/pangleBidAdapter_spec.js
new file mode 100644
index 00000000000..6d8f9a66bcf
--- /dev/null
+++ b/test/spec/modules/pangleBidAdapter_spec.js
@@ -0,0 +1,387 @@
+import { expect } from 'chai';
+import { spec } from 'modules/pangleBidAdapter.js';
+
+const REQUEST = [{
+ adUnitCode: 'adUnitCode1',
+ bidId: 'bidId1',
+ auctionId: 'auctionId-56a2-4f71-9098-720a68f2f708',
+ ortb2Imp: {
+ ext: {
+ tid: 'cccc1234',
+ }
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250]
+ ]
+ }
+ },
+ bidder: 'pangle',
+ params: {
+ placementid: 999,
+ appid: 111,
+ },
+},
+{
+ adUnitCode: 'adUnitCode2',
+ bidId: 'bidId2',
+ auctionId: 'auctionId-56a2-4f71-9098-720a68f2f708',
+ ortb2Imp: {
+ ext: {
+ tid: 'cccc1234',
+ }
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250]
+ ]
+ }
+ },
+ bidder: 'pangle',
+ params: {
+ placementid: 999,
+ appid: 111,
+ },
+}];
+
+const DEFAULT_OPTIONS = {
+ userId: {
+ britepoolid: 'pangle-britepool',
+ criteoId: 'pangle-criteo',
+ digitrustid: { data: { id: 'pangle-digitrust' } },
+ id5id: { uid: 'pangle-id5' },
+ idl_env: 'pangle-idl-env',
+ lipb: { lipbid: 'pangle-liveintent' },
+ netId: 'pangle-netid',
+ parrableId: { eid: 'pangle-parrable' },
+ pubcid: 'pangle-pubcid',
+ tdid: 'pangle-ttd',
+ }
+};
+
+const RESPONSE = {
+ 'headers': null,
+ 'body': {
+ 'id': 'requestId',
+ 'seatbid': [
+ {
+ 'bid': [
+ {
+ 'id': 'bidId1',
+ 'impid': 'bidId1',
+ 'price': 0.18,
+ 'adm': '',
+ 'adid': '144762342',
+ 'adomain': [
+ 'https://dummydomain.com'
+ ],
+ 'iurl': 'iurl',
+ 'cid': '109',
+ 'crid': 'creativeId',
+ 'cat': [],
+ 'w': 300,
+ 'h': 250,
+ 'mtype': 1,
+ 'ext': {
+ 'prebid': {
+ 'type': 'banner'
+ },
+ 'bidder': {
+ 'pangle': {
+ 'brand_id': 334553,
+ 'auction_id': 514667951122925701,
+ 'bidder_id': 2,
+ 'bid_ad_type': 0
+ }
+ }
+ }
+ }
+ ],
+ 'seat': 'seat'
+ }
+ ]
+ }
+};
+
+describe('pangle bid adapter', function () {
+ describe('isBidRequestValid', function () {
+ it('should accept request if placementid and appid is passed', function () {
+ let bid = {
+ bidder: 'pangle',
+ params: {
+ token: 'xxx',
+ }
+ };
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+ it('reject requests without params', function () {
+ let bid = {
+ bidder: 'pangle',
+ params: {}
+ };
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ });
+
+ describe('buildRequests', function () {
+ it('creates request data', function () {
+ let request = spec.buildRequests(REQUEST, DEFAULT_OPTIONS)[0];
+ expect(request).to.exist.and.to.be.a('object');
+ const payload = request.data;
+ expect(payload.imp[0]).to.have.property('id', REQUEST[0].bidId);
+ expect(payload.imp[1]).to.have.property('id', REQUEST[1].bidId);
+ });
+ });
+
+ describe('interpretResponse', function () {
+ it('has bids', function () {
+ let request = spec.buildRequests(REQUEST, DEFAULT_OPTIONS)[0];
+ let bids = spec.interpretResponse(RESPONSE, request);
+ expect(bids).to.be.an('array').that.is.not.empty;
+ validateBidOnIndex(0);
+
+ function validateBidOnIndex(index) {
+ expect(bids[index]).to.have.property('currency', 'USD');
+ expect(bids[index]).to.have.property('requestId', RESPONSE.body.seatbid[0].bid[index].id);
+ expect(bids[index]).to.have.property('cpm', RESPONSE.body.seatbid[0].bid[index].price);
+ expect(bids[index]).to.have.property('width', RESPONSE.body.seatbid[0].bid[index].w);
+ expect(bids[index]).to.have.property('height', RESPONSE.body.seatbid[0].bid[index].h);
+ expect(bids[index]).to.have.property('ad', RESPONSE.body.seatbid[0].bid[index].adm);
+ expect(bids[index]).to.have.property('creativeId', RESPONSE.body.seatbid[0].bid[index].crid);
+ expect(bids[index]).to.have.property('ttl', 30);
+ expect(bids[index]).to.have.property('netRevenue', true);
+ }
+ });
+
+ it('handles empty response', function () {
+ let request = spec.buildRequests(REQUEST, DEFAULT_OPTIONS)[0];
+ const EMPTY_RESP = Object.assign({}, RESPONSE, { 'body': {} });
+ const bids = spec.interpretResponse(EMPTY_RESP, request);
+ expect(bids).to.be.empty;
+ });
+ });
+
+ describe('parseUserAgent', function () {
+ let desktop, mobile, tablet;
+ beforeEach(function () {
+ desktop = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36';
+ mobile = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1';
+ tablet = 'Apple iPad: Mozilla/5.0 (iPad; CPU OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/605.1.15';
+ });
+
+ it('should return correct device type: tablet', function () {
+ let deviceType = spec.getDeviceType(tablet);
+ expect(deviceType).to.equal(5);
+ });
+
+ it('should return correct device type: mobile', function () {
+ let deviceType = spec.getDeviceType(mobile);
+ expect(deviceType).to.equal(4);
+ });
+
+ it('should return correct device type: desktop', function () {
+ let deviceType = spec.getDeviceType(desktop);
+ expect(deviceType).to.equal(2);
+ });
+ });
+});
+
+describe('Pangle Adapter with video', function() {
+ const videoBidRequest = [
+ {
+ bidId: '2820132fe18114',
+ mediaTypes: { video: { context: 'outstream', playerSize: [[300, 250]] } },
+ params: { token: 'test-token' }
+ }
+ ];
+ const bidderRequest = {
+ refererInfo: {
+ referer: 'https://example.com'
+ }
+ };
+ const serverResponse = {
+ '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'
+ }
+ ]
+ }
+ };
+
+ describe('Video: buildRequests', function() {
+ it('should create a POST request for video bid', function() {
+ const requests = spec.buildRequests(videoBidRequest, bidderRequest);
+ expect(requests[0].method).to.equal('POST');
+ });
+
+ it('should have a valid URL and payload for an out-stream video bid', function () {
+ const requests = spec.buildRequests(videoBidRequest, bidderRequest);
+ expect(requests[0].url).to.equal('https://pangle.pangleglobal.com/api/ad/union/web_js/common/get_ads');
+ expect(requests[0].data).to.exist;
+ });
+ });
+
+ describe('interpretResponse: Video', function () {
+ it('should get correct bid response', function () {
+ const request = spec.buildRequests(videoBidRequest, bidderRequest)[0];
+ const interpretedResponse = spec.interpretResponse(serverResponse, request);
+ expect(interpretedResponse).to.be.an('array');
+ const bid = interpretedResponse[0];
+ expect(bid).to.exist;
+ expect(bid.requestId).to.exist;
+ expect(bid.cpm).to.be.above(0);
+ expect(bid.ttl).to.exist;
+ expect(bid.creativeId).to.exist;
+ if (bid.renderer) {
+ expect(bid.renderer.render).to.exist;
+ }
+ });
+ });
+});
+
+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/acuityAdsBidAdapter_spec.js b/test/spec/modules/pgamsspBidAdapter_spec.js
similarity index 96%
rename from test/spec/modules/acuityAdsBidAdapter_spec.js
rename to test/spec/modules/pgamsspBidAdapter_spec.js
index 05c59036ff3..0766219eda8 100644
--- a/test/spec/modules/acuityAdsBidAdapter_spec.js
+++ b/test/spec/modules/pgamsspBidAdapter_spec.js
@@ -1,11 +1,11 @@
import { expect } from 'chai';
-import { spec } from '../../../modules/acuityAdsBidAdapter';
+import { spec } from '../../../modules/pgamsspBidAdapter.js';
import { BANNER, VIDEO, NATIVE } from '../../../src/mediaTypes.js';
import { getUniqueIdentifierStr } from '../../../src/utils.js';
-const bidder = 'acuityads'
+const bidder = 'pgamssp'
-describe('AcuityAdsBidAdapter', function () {
+describe('PGAMBidAdapter', function () {
const bids = [
{
bidId: getUniqueIdentifierStr(),
@@ -104,7 +104,7 @@ describe('AcuityAdsBidAdapter', function () {
});
it('Returns valid URL', function () {
- expect(serverRequest.url).to.equal('https://prebid.admanmedia.com/pbjs');
+ expect(serverRequest.url).to.equal('https://us-east.pgammedia.com/pbjs');
});
it('Returns general data valid', function () {
@@ -145,6 +145,7 @@ describe('AcuityAdsBidAdapter', 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');
@@ -382,7 +383,7 @@ describe('AcuityAdsBidAdapter', function () {
expect(syncData[0].type).to.be.a('string')
expect(syncData[0].type).to.equal('image')
expect(syncData[0].url).to.be.a('string')
- expect(syncData[0].url).to.equal('https://cs.admanmedia.com/image?pbjs=1&gdpr=1&gdpr_consent=ALL&coppa=0')
+ expect(syncData[0].url).to.equal('https://cs.pgammedia.com/image?pbjs=1&gdpr=1&gdpr_consent=ALL&coppa=0')
});
it('Should return array of objects with proper sync config , include CCPA', function() {
const syncData = spec.getUserSyncs({}, {}, {}, {
@@ -393,7 +394,7 @@ describe('AcuityAdsBidAdapter', function () {
expect(syncData[0].type).to.be.a('string')
expect(syncData[0].type).to.equal('image')
expect(syncData[0].url).to.be.a('string')
- expect(syncData[0].url).to.equal('https://cs.admanmedia.com/image?pbjs=1&ccpa_consent=1---&coppa=0')
+ expect(syncData[0].url).to.equal('https://cs.pgammedia.com/image?pbjs=1&ccpa_consent=1---&coppa=0')
});
});
});
diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js
index ad6c4318cc7..5b591804b95 100644
--- a/test/spec/modules/prebidServerBidAdapter_spec.js
+++ b/test/spec/modules/prebidServerBidAdapter_spec.js
@@ -14,7 +14,6 @@ import {config} from 'src/config.js';
import * as events from 'src/events.js';
import CONSTANTS from 'src/constants.json';
import {server} from 'test/mocks/xhr.js';
-import {createEidsArray} from 'modules/userId/eids.js';
import 'modules/appnexusBidAdapter.js'; // appnexus alias test
import 'modules/rubiconBidAdapter.js'; // rubicon alias test
import 'src/prebid.js'; // $$PREBID_GLOBAL$$.aliasBidder test
@@ -34,11 +33,9 @@ import {auctionManager} from '../../../src/auctionManager.js';
import {stubAuctionIndex} from '../../helpers/indexStub.js';
import {addComponentAuction, registerBidder} from 'src/adapters/bidderFactory.js';
import {getGlobal} from '../../../src/prebidGlobal.js';
-import {syncAddFPDEnrichments, syncAddFPDToBidderRequest} from '../../helpers/fpd.js';
+import {syncAddFPDToBidderRequest} from '../../helpers/fpd.js';
import {deepSetValue} from '../../../src/utils.js';
-import {sandbox} from 'sinon';
import {ACTIVITY_TRANSMIT_UFPD} from '../../../src/activities/activities.js';
-import {activityParams} from '../../../src/activities/activityParams.js';
import {MODULE_TYPE_PREBID} from '../../../src/activities/modules.js';
let CONFIG = {
@@ -712,8 +709,8 @@ describe('S2S Adapter', function () {
beforeEach(() => {
s2sReq = {
...REQUEST,
- ortb2Fragments: {global: {source: {tid: 'mock-tid'}}},
- ad_units: REQUEST.ad_units.map(au => ({...au, ortb2Imp: {ext: {tid: 'mock-tid'}}}))
+ ortb2Fragments: {global: {}},
+ ad_units: REQUEST.ad_units.map(au => ({...au, ortb2Imp: {ext: {tid: 'mock-tid'}}})),
};
BID_REQUESTS[0].bids[0].ortb2Imp = {ext: {tid: 'mock-tid'}};
});
@@ -726,15 +723,15 @@ describe('S2S Adapter', function () {
it('should not be set when transmitTid is not allowed, with ext.prebid.createtids: false', () => {
config.setConfig({ s2sConfig: CONFIG, enableTIDs: false });
const req = makeRequest();
- expect(req.source.tid).to.not.exist;
- expect(req.imp[0].ext.tid).to.not.exist;
+ expect(req.source?.tid).to.not.exist;
+ expect(req.imp[0].ext?.tid).to.not.exist;
expect(req.ext.prebid.createtids).to.equal(false);
});
- it('should be picked from FPD otherwise', () => {
+ it('should be set to auction ID otherwise', () => {
config.setConfig({s2sConfig: CONFIG, enableTIDs: true});
const req = makeRequest();
- expect(req.source.tid).to.eql('mock-tid');
+ expect(req.source.tid).to.eql(BID_REQUESTS[0].auctionId);
expect(req.imp[0].ext.tid).to.eql('mock-tid');
})
})
@@ -2054,7 +2051,7 @@ describe('S2S Adapter', function () {
const bidRequests = utils.deepClone(BID_REQUESTS);
adapter.callBids(REQUEST, bidRequests, addBidResponse, done, ajax);
- const parsedRequestBody = JSON.parse(server.requests[1].requestBody);
+ const parsedRequestBody = JSON.parse(server.requests.find(req => req.method === 'POST').requestBody);
expect(parsedRequestBody.cur).to.deep.equal(['NZ']);
});
@@ -2876,6 +2873,15 @@ describe('S2S Adapter', function () {
events.emit.restore();
});
+ it('triggers BIDDER_ERROR on server error', () => {
+ config.setConfig({ s2sConfig: CONFIG });
+ adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax);
+ server.requests[0].respond(400, {}, {});
+ BID_REQUESTS.forEach(bidderRequest => {
+ sinon.assert.calledWith(events.emit, CONSTANTS.EVENTS.BIDDER_ERROR, sinon.match({bidderRequest}))
+ })
+ })
+
// 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 });
@@ -3416,29 +3422,6 @@ describe('S2S Adapter', function () {
});
});
describe('when the response contains ext.prebid.fledge', () => {
- let fledgeStub, request, bidderRequests;
-
- function fledgeHook(next, ...args) {
- fledgeStub(...args);
- }
-
- before(() => {
- addComponentAuction.before(fledgeHook);
- });
-
- after(() => {
- addComponentAuction.getHooks({hook: fledgeHook}).remove();
- })
-
- beforeEach(function () {
- fledgeStub = sinon.stub();
- config.setConfig({CONFIG});
- request = deepClone(REQUEST);
- request.ad_units.forEach(au => deepSetValue(au, 'ortb2Imp.ext.ae', 1));
- bidderRequests = deepClone(BID_REQUESTS);
- bidderRequests.forEach(req => req.fledgeEnabled = true);
- });
-
const AU = 'div-gpt-ad-1460505748561-0';
const FLEDGE_RESP = {
ext: {
@@ -3447,12 +3430,14 @@ describe('S2S Adapter', function () {
auctionconfigs: [
{
impid: AU,
+ bidder: 'appnexus',
config: {
id: 1
}
},
{
impid: AU,
+ bidder: 'other',
config: {
id: 2
}
@@ -3463,20 +3448,62 @@ describe('S2S Adapter', function () {
}
}
+ let fledgeStub, request, bidderRequests;
+
+ function fledgeHook(next, ...args) {
+ fledgeStub(...args);
+ }
+
+ before(() => {
+ addComponentAuction.before(fledgeHook);
+ });
+
+ after(() => {
+ addComponentAuction.getHooks({hook: fledgeHook}).remove();
+ })
+
+ beforeEach(function () {
+ fledgeStub = sinon.stub();
+ config.setConfig({CONFIG});
+ bidderRequests = deepClone(BID_REQUESTS);
+ AU
+ bidderRequests.forEach(req => {
+ Object.assign(req, {
+ fledgeEnabled: true,
+ ortb2: {
+ fpd: 1
+ }
+ })
+ req.bids.forEach(bid => {
+ Object.assign(bid, {
+ ortb2Imp: {
+ fpd: 2
+ }
+ })
+ })
+ });
+ request = deepClone(REQUEST);
+ request.ad_units.forEach(au => deepSetValue(au, 'ortb2Imp.ext.ae', 1));
+ });
+
+ function expectFledgeCalls() {
+ const auctionId = bidderRequests[0].auctionId;
+ sinon.assert.calledWith(fledgeStub, sinon.match({auctionId, adUnitCode: AU, ortb2: bidderRequests[0].ortb2, ortb2Imp: bidderRequests[0].bids[0].ortb2Imp}), {id: 1})
+ sinon.assert.calledWith(fledgeStub, sinon.match({auctionId, adUnitCode: AU, ortb2: undefined, ortb2Imp: undefined}), {id: 2})
+ }
+
it('calls addComponentAuction alongside addBidResponse', function () {
adapter.callBids(request, bidderRequests, addBidResponse, done, ajax);
server.requests[0].respond(200, {}, JSON.stringify(mergeDeep({}, RESPONSE_OPENRTB, FLEDGE_RESP)));
expect(addBidResponse.called).to.be.true;
- sinon.assert.calledWith(fledgeStub, AU, {id: 1});
- sinon.assert.calledWith(fledgeStub, AU, {id: 2});
+ expectFledgeCalls();
});
it('calls addComponentAuction when there is no bid in the response', () => {
adapter.callBids(request, bidderRequests, addBidResponse, done, ajax);
server.requests[0].respond(200, {}, JSON.stringify(FLEDGE_RESP));
expect(addBidResponse.called).to.be.false;
- sinon.assert.calledWith(fledgeStub, AU, {id: 1});
- sinon.assert.calledWith(fledgeStub, AU, {id: 2});
+ expectFledgeCalls();
})
});
});
@@ -3626,33 +3653,6 @@ describe('S2S Adapter', function () {
sinon.assert.calledOnce(logErrorSpy);
});
- it('should configure the s2sConfig object with appnexus vendor defaults unless specified by user', function () {
- const options = {
- accountId: '123',
- bidders: ['appnexus'],
- defaultVendor: 'appnexus',
- timeout: 750
- };
-
- config.setConfig({ s2sConfig: options });
- sinon.assert.notCalled(logErrorSpy);
-
- let vendorConfig = config.getConfig('s2sConfig');
- expect(vendorConfig).to.have.property('accountId', '123');
- expect(vendorConfig).to.have.property('adapter', 'prebidServer');
- expect(vendorConfig.bidders).to.deep.equal(['appnexus']);
- expect(vendorConfig.enabled).to.be.true;
- expect(vendorConfig.endpoint).to.deep.equal({
- p1Consent: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction',
- noP1Consent: 'https://prebid.adnxs-simple.com/pbs/v1/openrtb2/auction'
- });
- expect(vendorConfig.syncEndpoint).to.deep.equal({
- p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync',
- noP1Consent: 'https://prebid.adnxs-simple.com/pbs/v1/cookie_sync'
- });
- expect(vendorConfig).to.have.property('timeout', 750);
- });
-
it('should configure the s2sConfig object with appnexuspsp vendor defaults unless specified by user', function () {
const options = {
accountId: '123',
@@ -3673,7 +3673,10 @@ describe('S2S Adapter', function () {
p1Consent: 'https://ib.adnxs.com/openrtb2/prebid',
noP1Consent: 'https://ib.adnxs-simple.com/openrtb2/prebid'
});
- expect(vendorConfig.syncEndpoint).to.be.undefined;
+ expect(vendorConfig.syncEndpoint).to.deep.equal({
+ p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync',
+ noP1Consent: 'https://prebid.adnxs-simple.com/pbs/v1/cookie_sync'
+ });
expect(vendorConfig).to.have.property('timeout', 750);
});
@@ -3758,6 +3761,74 @@ describe('S2S Adapter', function () {
})
});
+ it('should configure the s2sConfig object with openwrap vendor defaults unless specified by user', function () {
+ const options = {
+ accountId: '1234',
+ bidders: ['pubmatic'],
+ defaultVendor: 'openwrap'
+ };
+
+ config.setConfig({ s2sConfig: options });
+ sinon.assert.notCalled(logErrorSpy);
+
+ let vendorConfig = config.getConfig('s2sConfig');
+ expect(vendorConfig).to.have.property('accountId', '1234');
+ expect(vendorConfig).to.have.property('adapter', 'prebidServer');
+ expect(vendorConfig.bidders).to.deep.equal(['pubmatic']);
+ expect(vendorConfig.enabled).to.be.true;
+ expect(vendorConfig.endpoint).to.deep.equal({
+ p1Consent: 'https://ow.pubmatic.com/openrtb2/auction?source=pbjs',
+ noP1Consent: 'https://ow.pubmatic.com/openrtb2/auction?source=pbjs'
+ });
+ expect(vendorConfig).to.have.property('timeout', 500);
+ });
+
+ it('should return proper defaults', function () {
+ const options = {
+ accountId: '1234',
+ bidders: ['pubmatic'],
+ defaultVendor: 'openwrap',
+ timeout: 500
+ };
+
+ config.setConfig({ s2sConfig: options });
+ expect(config.getConfig('s2sConfig')).to.deep.equal({
+ 'accountId': '1234',
+ 'adapter': 'prebidServer',
+ 'bidders': ['pubmatic'],
+ 'defaultVendor': 'openwrap',
+ 'enabled': true,
+ 'endpoint': {
+ p1Consent: 'https://ow.pubmatic.com/openrtb2/auction?source=pbjs',
+ noP1Consent: 'https://ow.pubmatic.com/openrtb2/auction?source=pbjs'
+ },
+ 'timeout': 500
+ })
+ });
+
+ it('should return default adapterOptions if not set', function () {
+ config.setConfig({
+ s2sConfig: {
+ accountId: '1234',
+ bidders: ['pubmatic'],
+ defaultVendor: 'openwrap',
+ timeout: 500
+ }
+ });
+ expect(config.getConfig('s2sConfig')).to.deep.equal({
+ enabled: true,
+ timeout: 500,
+ adapter: 'prebidServer',
+ accountId: '1234',
+ bidders: ['pubmatic'],
+ defaultVendor: 'openwrap',
+ endpoint: {
+ p1Consent: 'https://ow.pubmatic.com/openrtb2/auction?source=pbjs',
+ noP1Consent: 'https://ow.pubmatic.com/openrtb2/auction?source=pbjs'
+ },
+ })
+ });
+
it('should set adapterOptions', function () {
config.setConfig({
s2sConfig: {
diff --git a/test/spec/modules/precisoBidAdapter_spec.js b/test/spec/modules/precisoBidAdapter_spec.js
index db38845c11a..78a1615a02e 100644
--- a/test/spec/modules/precisoBidAdapter_spec.js
+++ b/test/spec/modules/precisoBidAdapter_spec.js
@@ -1,5 +1,5 @@
-import {expect} from 'chai';
-import {spec} from '../../../modules/precisoBidAdapter.js';
+import { expect } from 'chai';
+import { spec } from '../../../modules/precisoBidAdapter.js';
import { config } from '../../../src/config.js';
const DEFAULT_PRICE = 1
@@ -10,17 +10,27 @@ const BIDDER_CODE = 'preciso';
describe('PrecisoAdapter', function () {
let bid = {
-
bidId: '23fhj33i987f',
bidder: 'preciso',
+ mediaTypes: {
+ banner: {
+ sizes: [[DEFAULT_BANNER_WIDTH, DEFAULT_BANNER_HEIGHT]]
+ }
+ },
params: {
host: 'prebid',
sourceid: '0',
publisherId: '0',
- traffic: 'banner',
+ mediaType: 'banner',
region: 'prebid-eu'
- }
+ },
+ userId: {
+ pubcid: '12355454test'
+
+ },
+ geo: 'NA',
+ city: 'Asia,delhi'
};
describe('isBidRequestValid', function () {
@@ -49,35 +59,37 @@ describe('PrecisoAdapter', function () {
});
it('Returns valid data if array of bids is valid', function () {
let data = serverRequest.data;
- expect(data).to.be.an('object');
- expect(data).to.have.all.keys('id', 'imp', 'site', 'deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'coppa');
+ // expect(data).to.be.an('object');
+
+ // expect(data).to.have.all.keys('bidId', 'imp', 'site', 'deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'coppa');
+
expect(data.deviceWidth).to.be.a('number');
expect(data.deviceHeight).to.be.a('number');
expect(data.coppa).to.be.a('number');
expect(data.language).to.be.a('string');
- expect(data.secure).to.be.within(0, 1);
+ // expect(data.secure).to.be.within(0, 1);
expect(data.host).to.be.a('string');
expect(data.page).to.be.a('string');
- let placement = data['placements'][0];
- expect(placement).to.have.keys('region', 'bidId', 'traffic', 'sizes', 'publisherId');
- expect(placement.bidId).to.equal('23fhj33i987f');
- expect(placement.traffic).to.equal('banner');
- expect(placement.region).to.equal('prebid-eu');
- });
- it('Returns empty data if no valid requests are passed', function () {
- serverRequest = spec.buildRequests([]);
- let data = serverRequest.data;
- expect(data.placements).to.be.an('array').that.is.empty;
+
+ expect(data.city).to.be.a('string');
+ expect(data.geo).to.be.a('object');
+ // expect(data.userId).to.be.a('string');
+ // expect(data.imp).to.be.a('object');
});
+ // it('Returns empty data if no valid requests are passed', function () {
+ /// serverRequest = spec.buildRequests([]);
+ // let data = serverRequest.data;
+ // expect(data.imp).to.be.an('array').that.is.empty;
+ // });
});
- describe('with COPPA', function() {
- beforeEach(function() {
+ describe('with COPPA', function () {
+ beforeEach(function () {
sinon.stub(config, 'getConfig')
.withArgs('coppa')
.returns(true);
});
- afterEach(function() {
+ afterEach(function () {
config.getConfig.restore();
});
@@ -90,7 +102,9 @@ describe('PrecisoAdapter', function () {
describe('interpretResponse', function () {
it('should get correct bid response', function () {
let response = {
- id: 'f6adb85f-4e19-45a0-b41e-2a5b9a48f23a',
+
+ bidderRequestId: 'f6adb85f-4e19-45a0-b41e-2a5b9a48f23a',
+
seatbid: [
{
bid: [
@@ -131,7 +145,7 @@ describe('PrecisoAdapter', function () {
})
})
describe('getUserSyncs', function () {
- const syncUrl = 'https://ck.2trk.info/rtb/user/usersync.aspx?id=preciso_srl&gdpr=0&gdpr_consent=&us_privacy=&t=4';
+ const syncUrl = 'https://ck.2trk.info/rtb/user/usersync.aspx?id=NA&gdpr=0&gdpr_consent=&us_privacy=&t=4';
const syncOptions = {
iframeEnabled: true
};
diff --git a/test/spec/modules/priceFloors_spec.js b/test/spec/modules/priceFloors_spec.js
index e2b8ca38792..a31f07fecef 100644
--- a/test/spec/modules/priceFloors_spec.js
+++ b/test/spec/modules/priceFloors_spec.js
@@ -12,7 +12,7 @@ import {
isFloorsDataValid,
addBidResponseHook,
fieldMatchingFunctions,
- allowedFields
+ 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';
@@ -123,7 +123,7 @@ describe('the price floors module', function () {
return {
code,
mediaTypes: {banner: { sizes: [[300, 200], [300, 600]] }, native: {}},
- bids: [{bidder: 'someBidder'}, {bidder: 'someOtherBidder'}]
+ bids: [{bidder: 'someBidder', adUnitCode: code}, {bidder: 'someOtherBidder', adUnitCode: code}]
};
}
beforeEach(function() {
@@ -143,6 +143,76 @@ describe('the price floors module', function () {
getGlobal().bidderSettings = {};
});
+ describe('parseFloorData', () => {
+ it('should accept just a default floor', () => {
+ const fd = parseFloorData({
+ default: 1.23
+ });
+ expect(getFirstMatchingFloor(fd, {}, {}).matchingFloor).to.eql(1.23);
+ });
+ });
+
+ describe('getFloorDataFromAdUnits', () => {
+ let adUnits;
+
+ function setFloorValues(rule) {
+ adUnits.forEach((au, i) => {
+ au.floors = {
+ values: {
+ [rule]: i + 1
+ }
+ }
+ })
+ }
+
+ beforeEach(() => {
+ adUnits = ['au1', 'au2', 'au3'].map(getAdUnitMock);
+ })
+
+ it('should use one schema for all adUnits', () => {
+ setFloorValues('*;*')
+ adUnits[1].floors.schema = {
+ fields: ['mediaType', 'gptSlot'],
+ delimiter: ';'
+ }
+ sinon.assert.match(getFloorDataFromAdUnits(adUnits), {
+ schema: {
+ fields: ['adUnitCode', 'mediaType', 'gptSlot'],
+ delimiter: ';'
+ },
+ values: {
+ 'au1;*;*': 1,
+ 'au2;*;*': 2,
+ 'au3;*;*': 3
+ }
+ })
+ });
+ it('should ignore adUnits that declare different schema', () => {
+ setFloorValues('*|*');
+ adUnits[0].floors.schema = {
+ fields: ['mediaType', 'gptSlot']
+ };
+ adUnits[2].floors.schema = {
+ fields: ['gptSlot', 'mediaType']
+ };
+ expect(getFloorDataFromAdUnits(adUnits).values).to.eql({
+ 'au1|*|*': 1,
+ 'au2|*|*': 2
+ })
+ });
+ it('should ignore adUnits that declare no values', () => {
+ setFloorValues('*');
+ adUnits[0].floors.schema = {
+ fields: ['mediaType']
+ };
+ delete adUnits[2].floors.values;
+ expect(getFloorDataFromAdUnits(adUnits).values).to.eql({
+ 'au1|*': 1,
+ 'au2|*': 2,
+ })
+ })
+ })
+
describe('getFloorsDataForAuction', function () {
it('converts basic input floor data into a floorData map for the auction correctly', function () {
// basic input where nothing needs to be updated
@@ -233,8 +303,8 @@ describe('the price floors module', function () {
});
describe('getFirstMatchingFloor', function () {
- it('uses a 0 floor as overrite', function () {
- let inputFloorData = {
+ it('uses a 0 floor as override', function () {
+ let inputFloorData = normalizeDefault({
currency: 'USD',
schema: {
delimiter: '|',
@@ -245,7 +315,7 @@ describe('the price floors module', function () {
'test_div_2': 2
},
default: 0.5
- };
+ });
expect(getFirstMatchingFloor(inputFloorData, basicBidRequest, {mediaType: 'banner', size: '*'})).to.deep.equal({
floorMin: 0,
@@ -434,7 +504,7 @@ describe('the price floors module', function () {
});
});
it('selects the right floor for more complex rules', function () {
- let inputFloorData = {
+ let inputFloorData = normalizeDefault({
currency: 'USD',
schema: {
delimiter: '^',
@@ -448,7 +518,7 @@ describe('the price floors module', function () {
'weird_div^*^300x250': 5.5
},
default: 0.5
- };
+ });
// banner with 300x250 size
expect(getFirstMatchingFloor(inputFloorData, basicBidRequest, {mediaType: 'banner', size: [300, 250]})).to.deep.equal({
floorMin: 0,
@@ -490,10 +560,8 @@ describe('the price floors module', function () {
matchingFloor: undefined
});
// if default is there use it
- inputFloorData = { default: 5.0 };
- expect(getFirstMatchingFloor(inputFloorData, basicBidRequest, {mediaType: 'banner', size: '*'})).to.deep.equal({
- matchingFloor: 5.0
- });
+ inputFloorData = normalizeDefault({ default: 5.0 });
+ expect(getFirstMatchingFloor(inputFloorData, basicBidRequest, {mediaType: 'banner', size: '*'}).matchingFloor).to.equal(5.0);
});
describe('with gpt enabled', function () {
let gptFloorData;
@@ -580,6 +648,90 @@ 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);
+ });
+ });
+
describe('pre-auction tests', function () {
let exposedAdUnits;
const validateBidRequests = (getFloorExpected, FloorDataExpected) => {
@@ -621,6 +773,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,
@@ -693,6 +963,95 @@ describe('the price floors module', function () {
floorProvider: undefined
});
});
+ describe('default floor', () => {
+ let adUnits;
+ beforeEach(() => {
+ adUnits = ['au1', 'au2'].map(getAdUnitMock);
+ })
+ function expectFloors(floors) {
+ runStandardAuction(adUnits);
+ adUnits.forEach((au, i) => {
+ au.bids.forEach(bid => {
+ expect(bid.getFloor().floor).to.eql(floors[i]);
+ })
+ })
+ }
+ describe('should be sufficient by itself', () => {
+ it('globally', () => {
+ handleSetFloorsConfig({
+ ...basicFloorConfig,
+ data: {
+ default: 1.23
+ }
+ });
+ expectFloors([1.23, 1.23])
+ });
+ it('on adUnits', () => {
+ handleSetFloorsConfig({
+ ...basicFloorConfig,
+ data: undefined
+ });
+ adUnits[0].floors = {default: 1};
+ adUnits[1].floors = {default: 2};
+ expectFloors([1, 2])
+ });
+ it('on an adUnit with hidden schema', () => {
+ handleSetFloorsConfig({
+ ...basicFloorConfig,
+ data: undefined
+ });
+ adUnits[0].floors = {
+ schema: {
+ fields: ['mediaType', 'gptSlot'],
+ },
+ default: 1
+ }
+ adUnits[1].floors = {
+ default: 2
+ }
+ expectFloors([1, 2]);
+ })
+ });
+ describe('should NOT be used when a star rule exists', () => {
+ it('globally', () => {
+ handleSetFloorsConfig({
+ ...basicFloorConfig,
+ data: {
+ schema: {
+ fields: ['mediaType', 'gptSlot'],
+ },
+ values: {
+ '*|*': 2
+ },
+ default: 3,
+ }
+ });
+ expectFloors([2, 2]);
+ });
+ it('on adUnits', () => {
+ handleSetFloorsConfig({
+ ...basicFloorConfig,
+ data: undefined
+ });
+ adUnits[0].floors = {
+ schema: {
+ fields: ['mediaType', 'gptSlot'],
+ },
+ values: {
+ '*|*': 1
+ },
+ default: 3
+ };
+ adUnits[1].floors = {
+ values: {
+ '*|*': 2
+ },
+ default: 4
+ }
+ expectFloors([1, 2]);
+ })
+ });
+ })
it('bidRequests should have getFloor function and flooring meta data when setConfig occurs', function () {
handleSetFloorsConfig({...basicFloorConfig, floorProvider: 'floorprovider'});
runStandardAuction();
@@ -1382,7 +1741,7 @@ describe('the price floors module', function () {
it('picks the right rule with more complex rules', function () {
_floorDataForAuction[bidRequest.auctionId] = {
...basicFloorConfig,
- data: {
+ data: normalizeDefault({
currency: 'USD',
schema: { fields: ['mediaType', 'size'], delimiter: '|' },
values: {
@@ -1394,7 +1753,7 @@ describe('the price floors module', function () {
'video|*': 5.5
},
default: 10.0
- }
+ })
};
// assumes banner *
@@ -1854,6 +2213,12 @@ describe('the price floors module', function () {
expect(returnedBidResponse).to.not.haveOwnProperty('floorData');
expect(logWarnSpy.calledOnce).to.equal(true);
});
+ it('if it finds a rule with a floor price of zero it should not call log warn', function () {
+ _floorDataForAuction[AUCTION_ID] = utils.deepClone(basicFloorConfig);
+ _floorDataForAuction[AUCTION_ID].data.values = { '*': 0 };
+ runBidResponse();
+ expect(logWarnSpy.calledOnce).to.equal(false);
+ });
it('if it finds a rule and floors should update the bid accordingly', function () {
_floorDataForAuction[AUCTION_ID] = utils.deepClone(basicFloorConfig);
_floorDataForAuction[AUCTION_ID].data.values = { 'banner': 1.0 };
diff --git a/test/spec/modules/programmaticaBidAdapter_spec.js b/test/spec/modules/programmaticaBidAdapter_spec.js
new file mode 100644
index 00000000000..247d20752c3
--- /dev/null
+++ b/test/spec/modules/programmaticaBidAdapter_spec.js
@@ -0,0 +1,263 @@
+import { expect } from 'chai';
+import { spec } from 'modules/programmaticaBidAdapter.js';
+import { deepClone } from 'src/utils.js';
+
+describe('programmaticaBidAdapterTests', function () {
+ let bidRequestData = {
+ bids: [
+ {
+ bidId: 'testbid',
+ bidder: 'programmatica',
+ params: {
+ siteId: 'testsite',
+ placementId: 'testplacement',
+ },
+ sizes: [[300, 250]]
+ }
+ ]
+ };
+ let request = [];
+
+ it('validate_pub_params', function () {
+ expect(
+ spec.isBidRequestValid({
+ bidder: 'programmatica',
+ params: {
+ siteId: 'testsite',
+ placementId: 'testplacement',
+ }
+ })
+ ).to.equal(true);
+ });
+
+ it('validate_generated_url', function () {
+ const request = spec.buildRequests(deepClone(bidRequestData.bids), { timeout: 1234 });
+ let req_url = request[0].url;
+
+ expect(req_url).to.equal('https://asr.programmatica.com/get');
+ });
+
+ it('validate_response_params', function () {
+ let serverResponse = {
+ body: {
+ 'id': 'crid',
+ 'type': {
+ 'format': 'Image',
+ 'source': 'passback',
+ 'dspId': '',
+ 'dspCreativeId': ''
+ },
+ 'content': {
+ 'data': 'test ad',
+ 'imps': null,
+ 'click': {
+ 'url': '',
+ 'track': null
+ }
+ },
+ 'size': '300x250',
+ 'matching': '',
+ 'cpm': 10,
+ 'currency': 'USD'
+ }
+ };
+
+ const bidRequest = deepClone(bidRequestData.bids)
+ bidRequest[0].mediaTypes = {
+ banner: {}
+ }
+
+ const request = spec.buildRequests(bidRequest);
+ let bids = spec.interpretResponse(serverResponse, request[0]);
+ expect(bids).to.have.lengthOf(1);
+
+ let bid = bids[0];
+ expect(bid.ad).to.equal('test ad');
+ expect(bid.cpm).to.equal(10);
+ expect(bid.currency).to.equal('USD');
+ expect(bid.width).to.equal(300);
+ expect(bid.height).to.equal(250);
+ expect(bid.creativeId).to.equal('crid');
+ expect(bid.meta.advertiserDomains).to.deep.equal(['programmatica.com']);
+ });
+
+ it('validate_response_params_imps', function () {
+ let serverResponse = {
+ body: {
+ 'id': 'crid',
+ 'type': {
+ 'format': 'Image',
+ 'source': 'passback',
+ 'dspId': '',
+ 'dspCreativeId': ''
+ },
+ 'content': {
+ 'data': 'test ad',
+ 'imps': [
+ 'testImp'
+ ],
+ 'click': {
+ 'url': '',
+ 'track': null
+ }
+ },
+ 'size': '300x250',
+ 'matching': '',
+ 'cpm': 10,
+ 'currency': 'USD'
+ }
+ };
+
+ const bidRequest = deepClone(bidRequestData.bids)
+ bidRequest[0].mediaTypes = {
+ banner: {}
+ }
+
+ const request = spec.buildRequests(bidRequest);
+ let bids = spec.interpretResponse(serverResponse, request[0]);
+ expect(bids).to.have.lengthOf(1);
+
+ let bid = bids[0];
+ expect(bid.ad).to.equal('test ad');
+ expect(bid.cpm).to.equal(10);
+ expect(bid.currency).to.equal('USD');
+ expect(bid.width).to.equal(300);
+ expect(bid.height).to.equal(250);
+ expect(bid.creativeId).to.equal('crid');
+ expect(bid.meta.advertiserDomains).to.deep.equal(['programmatica.com']);
+ })
+
+ it('validate_invalid_response', function () {
+ let serverResponse = {
+ body: {}
+ };
+
+ const bidRequest = deepClone(bidRequestData.bids)
+ bidRequest[0].mediaTypes = {
+ banner: {}
+ }
+
+ const request = spec.buildRequests(bidRequest);
+ let bids = spec.interpretResponse(serverResponse, request[0]);
+ expect(bids).to.have.lengthOf(0);
+ })
+
+ it('video_bid', function () {
+ const bidRequest = deepClone(bidRequestData.bids);
+ bidRequest[0].mediaTypes = {
+ video: {
+ playerSize: [234, 765]
+ }
+ };
+
+ const request = spec.buildRequests(bidRequest, { timeout: 1234 });
+ const vastXml = '';
+ let serverResponse = {
+ body: {
+ 'id': 'cki2n3n6snkuulqutpf0',
+ 'type': {
+ 'format': '',
+ 'source': 'rtb',
+ 'dspId': '1'
+ },
+ 'content': {
+ 'data': vastXml,
+ 'imps': [
+ 'https://asr.dev.programmatica.com/track/imp'
+ ],
+ 'click': {
+ 'url': '',
+ 'track': null
+ }
+ },
+ 'size': '',
+ 'matching': '',
+ 'cpm': 70,
+ 'currency': 'RUB'
+ }
+ };
+
+ let bids = spec.interpretResponse(serverResponse, request[0]);
+ expect(bids).to.have.lengthOf(1);
+
+ let bid = bids[0];
+ expect(bid.mediaType).to.equal('video');
+ expect(bid.vastXml).to.equal(vastXml);
+ expect(bid.width).to.equal(234);
+ expect(bid.height).to.equal(765);
+ });
+});
+
+describe('getUserSyncs', function() {
+ it('returns empty sync array', function() {
+ const syncOptions = {};
+
+ expect(spec.getUserSyncs(syncOptions)).to.deep.equal([]);
+ });
+
+ it('Should return array of objects with proper sync config , include CCPA', function() {
+ const syncData = spec.getUserSyncs({
+ pixelEnabled: true,
+ }, {}, {}, '1---');
+ expect(syncData).to.be.an('array').which.is.not.empty;
+ expect(syncData[0]).to.be.an('object')
+ expect(syncData[0].type).to.be.a('string')
+ expect(syncData[0].type).to.equal('image')
+ expect(syncData[0].url).to.be.a('string')
+ expect(syncData[0].url).to.equal('//sync.programmatica.com/match/sp?usp=1---&consent=')
+ });
+
+ it('Should return array of objects with proper sync config , include GDPR', function() {
+ const syncData = spec.getUserSyncs({
+ iframeEnabled: true,
+ }, {}, {
+ gdprApplies: true,
+ consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
+ vendorData: {
+ purpose: {
+ consents: {
+ 1: true
+ },
+ },
+ }
+ }, '');
+ expect(syncData).to.be.an('array').which.is.not.empty;
+ expect(syncData[0]).to.be.an('object')
+ expect(syncData[0].type).to.be.a('string')
+ expect(syncData[0].type).to.equal('iframe')
+ expect(syncData[0].url).to.be.a('string')
+ expect(syncData[0].url).to.equal('//sync.programmatica.com/match/sp.ifr?usp=&consent=COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&gdpr=1')
+ });
+
+ it('Should return array of objects with proper sync config , include GDPR, no purpose', function() {
+ const syncData = spec.getUserSyncs({
+ iframeEnabled: true,
+ }, {}, {
+ gdprApplies: true,
+ consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
+ vendorData: {
+ purpose: {
+ consents: {
+ 1: false
+ },
+ },
+ }
+ }, '');
+ expect(syncData).is.empty;
+ });
+
+ it('Should return array of objects with proper sync config , GDPR not applies', function() {
+ const syncData = spec.getUserSyncs({
+ iframeEnabled: true,
+ }, {}, {
+ gdprApplies: false,
+ consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
+ }, '');
+ expect(syncData).to.be.an('array').which.is.not.empty;
+ expect(syncData[0]).to.be.an('object')
+ expect(syncData[0].type).to.be.a('string')
+ expect(syncData[0].type).to.equal('iframe')
+ expect(syncData[0].url).to.be.a('string')
+ expect(syncData[0].url).to.equal('//sync.programmatica.com/match/sp.ifr?usp=&consent=COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&gdpr=0')
+ });
+})
diff --git a/test/spec/modules/publinkIdSystem_spec.js b/test/spec/modules/publinkIdSystem_spec.js
index f35a7453403..5ad58ea1a37 100644
--- a/test/spec/modules/publinkIdSystem_spec.js
+++ b/test/spec/modules/publinkIdSystem_spec.js
@@ -72,11 +72,6 @@ describe('PublinkIdSystem', () => {
expect(result.callback).to.be.a('function');
});
- it('Use local copy', () => {
- const result = publinkIdSubmodule.getId({}, undefined, TEST_COOKIE_VALUE);
- expect(result).to.be.undefined;
- });
-
describe('callout for id', () => {
let callbackSpy = sinon.spy();
@@ -84,6 +79,44 @@ describe('PublinkIdSystem', () => {
callbackSpy.resetHistory();
});
+ it('Has cached id', () => {
+ const config = {storage: {type: 'cookie'}};
+ let submoduleCallback = publinkIdSubmodule.getId(config, undefined, TEST_COOKIE_VALUE).callback;
+ submoduleCallback(callbackSpy);
+
+ const request = server.requests[0];
+ const parsed = parseUrl(request.url);
+
+ expect(parsed.hostname).to.equal('proc.ad.cpe.dotomi.com');
+ expect(parsed.pathname).to.equal('/cvx/client/sync/publink/refresh');
+ expect(parsed.search.mpn).to.equal('Prebid.js');
+ expect(parsed.search.mpv).to.equal('$prebid.version$');
+ expect(parsed.search.publink).to.equal(TEST_COOKIE_VALUE);
+
+ request.respond(200, {}, JSON.stringify(serverResponse));
+ expect(callbackSpy.calledOnce).to.be.true;
+ expect(callbackSpy.lastCall.lastArg).to.equal(serverResponse.publink);
+ });
+
+ it('Request path has priority', () => {
+ const config = {storage: {type: 'cookie'}, params: {e: 'ca11c0ca7', site_id: '102030'}};
+ let submoduleCallback = publinkIdSubmodule.getId(config, undefined, TEST_COOKIE_VALUE).callback;
+ submoduleCallback(callbackSpy);
+
+ const request = server.requests[0];
+ const parsed = parseUrl(request.url);
+
+ expect(parsed.hostname).to.equal('proc.ad.cpe.dotomi.com');
+ expect(parsed.pathname).to.equal('/cvx/client/sync/publink');
+ expect(parsed.search.mpn).to.equal('Prebid.js');
+ expect(parsed.search.mpv).to.equal('$prebid.version$');
+ expect(parsed.search.publink).to.equal(TEST_COOKIE_VALUE);
+
+ request.respond(200, {}, JSON.stringify(serverResponse));
+ expect(callbackSpy.calledOnce).to.be.true;
+ expect(callbackSpy.lastCall.lastArg).to.equal(serverResponse.publink);
+ });
+
it('Fetch with consent data', () => {
const config = {storage: {type: 'cookie'}, params: {e: 'ca11c0ca7', site_id: '102030'}};
const consentData = {gdprApplies: 1, consentString: 'myconsentstring'};
diff --git a/test/spec/modules/pubmaticAnalyticsAdapter_spec.js b/test/spec/modules/pubmaticAnalyticsAdapter_spec.js
index 1b2e80aa730..c6447905ecd 100755
--- a/test/spec/modules/pubmaticAnalyticsAdapter_spec.js
+++ b/test/spec/modules/pubmaticAnalyticsAdapter_spec.js
@@ -1,10 +1,11 @@
-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';
-import {setConfig} from 'modules/currency.js';
-import {server} from '../../mocks/xhr.js';
+import { config } from 'src/config.js';
+import { setConfig } from 'modules/currency.js';
+import { server } from '../../mocks/xhr.js';
import 'src/prebid.js';
+import { getGlobal } from 'src/prebidGlobal';
let events = require('src/events');
let ajax = require('src/ajax');
@@ -315,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({
@@ -367,15 +570,20 @@ describe('pubmatic analytics adapter', function () {
expect(data.tgid).to.equal(15);
expect(data.fmv).to.equal('floorModelTest');
expect(data.ft).to.equal(1);
+ expect(data.pbv).to.equal(getGlobal()?.version || '-1');
expect(data.s).to.be.an('array');
expect(data.s.length).to.equal(2);
// 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');
@@ -386,9 +594,10 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[0].ps[0].psz).to.equal('640x480');
expect(data.s[0].ps[0].eg).to.equal(1.23);
expect(data.s[0].ps[0].en).to.equal(1.23);
- expect(data.s[0].ps[0].di).to.equal('');
+ 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(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);
@@ -400,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);
@@ -417,7 +630,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[1].ps[0].l1).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);
@@ -455,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';
@@ -572,15 +786,20 @@ describe('pubmatic analytics adapter', function () {
expect(data.pid).to.equal('1111');
expect(data.fmv).to.equal('floorModelTest');
expect(data.ft).to.equal(1);
+ expect(data.pbv).to.equal(getGlobal()?.version || '-1');
expect(data.s).to.be.an('array');
expect(data.s.length).to.equal(2);
expect(data.tgid).to.equal(0);
// 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');
@@ -646,6 +865,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.tgid).to.equal(0);// test group id should be between 0-15 else set to 0
expect(data.fmv).to.equal('floorModelTest');
expect(data.ft).to.equal(1);
+ expect(data.pbv).to.equal(getGlobal()?.version || '-1');
expect(data.s).to.be.an('array');
expect(data.s.length).to.equal(2);
// slot 1
@@ -653,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');
@@ -696,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);
@@ -708,7 +935,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].psz).to.equal('0x0');
expect(data.s[1].ps[0].eg).to.equal(0);
expect(data.s[1].ps[0].en).to.equal(0);
- expect(data.s[1].ps[0].di).to.equal('');
+ expect(data.s[1].ps[0].di).to.equal('-1');
expect(data.s[1].ps[0].dc).to.equal('');
expect(data.s[1].ps[0].mi).to.equal(undefined);
expect(data.s[1].ps[0].l1).to.equal(0);
@@ -746,7 +973,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].psz).to.equal('0x0');
expect(data.s[1].ps[0].eg).to.equal(0);
expect(data.s[1].ps[0].en).to.equal(0);
- expect(data.s[1].ps[0].di).to.equal('');
+ expect(data.s[1].ps[0].di).to.equal('-1');
expect(data.s[1].ps[0].dc).to.equal('');
expect(data.s[1].ps[0].mi).to.equal(undefined);
expect(data.s[1].ps[0].l1).to.equal(0);
@@ -778,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);
@@ -794,7 +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[1].ps[0].l1).to.equal(3214);
+ 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);
@@ -839,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');
@@ -853,7 +1086,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[1].ps[0].l1).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);
@@ -885,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);
@@ -901,7 +1139,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[1].ps[0].l1).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);
@@ -943,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');
@@ -958,7 +1198,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[1].ps[0].l1).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);
@@ -996,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);
@@ -1012,7 +1257,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[1].ps[0].l1).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);
@@ -1052,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');
@@ -1067,7 +1314,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[1].ps[0].l1).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);
@@ -1109,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');
@@ -1126,7 +1378,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[1].ps[0].l1).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);
@@ -1175,6 +1428,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.tst).to.equal(1519767016);
expect(data.tgid).to.equal(15);
expect(data.fmv).to.equal('floorModelTest');
+ expect(data.pbv).to.equal(getGlobal()?.version || '-1');
expect(data.ft).to.equal(1);
expect(data.s).to.be.an('array');
expect(data.s.length).to.equal(2);
@@ -1182,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');
@@ -1196,9 +1454,10 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[0].ps[0].psz).to.equal('640x480');
expect(data.s[0].ps[0].eg).to.equal(1.23);
expect(data.s[0].ps[0].en).to.equal(1.23);
- expect(data.s[0].ps[0].di).to.equal('');
+ 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(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(0);
expect(data.s[0].ps[0].t).to.equal(0);
@@ -1211,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');
@@ -1228,7 +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[1].ps[0].l1).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);
@@ -1294,6 +1558,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.tst).to.equal(1519767016);
expect(data.tgid).to.equal(15);
expect(data.fmv).to.equal('floorModelTest');
+ expect(data.pbv).to.equal(getGlobal()?.version || '-1');
expect(data.ft).to.equal(1);
expect(data.s).to.be.an('array');
expect(data.s.length).to.equal(2);
@@ -1301,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');
@@ -1315,9 +1584,10 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[0].ps[0].psz).to.equal('640x480');
expect(data.s[0].ps[0].eg).to.equal(1.23);
expect(data.s[0].ps[0].en).to.equal(1.23);
- expect(data.s[0].ps[0].di).to.equal('');
+ 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(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(0);
expect(data.s[0].ps[0].t).to.equal(0);
@@ -1330,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');
@@ -1346,7 +1617,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[1].ps[0].l1).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);
diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js
index 0ed764c8f7e..5d59ff99a89 100644
--- a/test/spec/modules/pubmaticBidAdapter_spec.js
+++ b/test/spec/modules/pubmaticBidAdapter_spec.js
@@ -82,6 +82,7 @@ describe('PubMatic adapter', function () {
ortb2Imp: {
ext: {
tid: '92489f71-1bf2-49a0-adf9-000cea934729',
+ gpid: '/1111/homepage-leftnav'
}
},
schain: schainConfig
@@ -103,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,
@@ -153,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,
@@ -212,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',
@@ -277,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',
@@ -303,6 +308,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '5670',
adSlot: '/43743431/NativeAutomationPrebid@1x1',
+ wiid: 'new-unique-wiid'
}
}];
@@ -343,6 +349,7 @@ describe('PubMatic adapter', function () {
params: {
publisherId: '5670',
adSlot: '/43743431/NativeAutomationPrebid@1x1',
+ wiid: 'new-unique-wiid'
}
}];
@@ -501,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,
@@ -571,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,
@@ -1172,6 +1181,7 @@ describe('PubMatic adapter', function () {
expect(data.imp[0].tagid).to.equal('/15671365/DMDemo'); // tagid
expect(data.imp[0].banner.w).to.equal(300); // width
expect(data.imp[0].banner.h).to.equal(250); // height
+ expect(data.imp[0].ext.gpid).to.equal(bidRequests[0].ortb2Imp.ext.gpid);
expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid
expect(data.imp[0].ext.key_val).to.exist.and.to.equal(bidRequests[0].params.dctr);
expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency);
@@ -1439,6 +1449,7 @@ describe('PubMatic adapter', function () {
expect(data.imp[0].banner.w).to.equal(728); // width
expect(data.imp[0].banner.h).to.equal(90); // height
expect(data.imp[0].banner.format).to.deep.equal([{w: 160, h: 600}]);
+ expect(data.imp[0].ext.gpid).to.equal(bidRequests[0].ortb2Imp.ext.gpid);
expect(data.imp[0].ext.key_val).to.exist.and.to.equal(bidRequests[0].params.dctr);
expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid
expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency);
@@ -1663,6 +1674,7 @@ describe('PubMatic adapter', function () {
expect(data.imp[0].tagid).to.equal('/15671365/DMDemo'); // tagid
expect(data.imp[0].banner.w).to.equal(300); // width
expect(data.imp[0].banner.h).to.equal(250); // height
+ expect(data.imp[0].ext.gpid).to.equal(bidRequests[0].ortb2Imp.ext.gpid);
expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid
});
@@ -1711,6 +1723,7 @@ describe('PubMatic adapter', function () {
expect(data.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as id
expect(data.imp[0].bidfloor).to.equal(parseFloat(bidRequests[0].params.kadfloor)); // kadfloor
expect(data.imp[0].tagid).to.equal('/15671365/DMDemo'); // tagid
+ expect(data.imp[0].ext.gpid).to.equal(bidRequests[0].ortb2Imp.ext.gpid);
expect(data.imp[0].banner.w).to.equal(300); // width
expect(data.imp[0].banner.h).to.equal(250); // height
expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid
@@ -1759,6 +1772,7 @@ describe('PubMatic adapter', function () {
expect(data.imp[0].tagid).to.equal('/15671365/DMDemo'); // tagid
expect(data.imp[0].banner.w).to.equal(300); // width
expect(data.imp[0].banner.h).to.equal(250); // height
+ expect(data.imp[0].ext.gpid).to.equal(bidRequests[0].ortb2Imp.ext.gpid);
expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid
// second request without USP/CCPA
@@ -1908,7 +1922,43 @@ 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 () {
+ if (bidRequests[0].hasOwnProperty('ortb2Imp')) {
+ delete bidRequests[0].ortb2Imp;
+ }
+ });
+
+ it('should send gpid if imp[].ext.gpid is specified', function() {
+ bidRequests[0].ortb2Imp = {
+ ext: {
+ gpid: 'ortb2Imp.ext.gpid'
+ }
+ };
+ const request = spec.buildRequests(bidRequests, {});
+ let data = JSON.parse(request.data);
+ expect(data.imp[0].ext).to.have.property('gpid');
+ expect(data.imp[0].ext.gpid).to.equal('ortb2Imp.ext.gpid');
+ });
+
+ it('should not send if imp[].ext.gpid is not specified', function() {
+ bidRequests[0].ortb2Imp = { ext: { } };
+ const request = spec.buildRequests(bidRequests, {});
+ let data = JSON.parse(request.data);
+ expect(data.imp[0].ext).to.not.have.property('gpid');
+ });
+ });
+
describe('ortb2Imp.ext.data.pbadslot', function() {
beforeEach(function () {
if (bidRequests[0].hasOwnProperty('ortb2Imp')) {
@@ -2278,6 +2328,23 @@ describe('PubMatic adapter', function () {
expect(data.device.sua).to.deep.equal(suaObject);
});
+ it('should pass device.ext.cdep if present in bidderRequest fpd ortb2 object', function () {
+ const cdepObj = {
+ cdep: 'example_label_1'
+ };
+ let request = spec.buildRequests(multipleMediaRequests, {
+ auctionId: 'new-auction-id',
+ ortb2: {
+ device: {
+ ext: cdepObj
+ }
+ }
+ });
+ let data = JSON.parse(request.data);
+ expect(data.device.ext.cdep).to.exist.and.to.be.an('string');
+ expect(data.device.ext).to.deep.equal(cdepObj);
+ });
+
it('Request params should have valid native bid request for all valid params', function () {
let request = spec.buildRequests(nativeBidRequests, {
auctionId: 'new-auction-id'
@@ -3601,6 +3668,89 @@ describe('PubMatic adapter', function () {
}
});
+ describe('Fledge Auction config Response', function () {
+ let response;
+ let bidRequestConfigs = [
+ {
+ bidder: 'pubmatic',
+ mediaTypes: {
+ banner: {
+ sizes: [[728, 90], [160, 600]]
+ }
+ },
+ params: {
+ publisherId: '5670',
+ adSlot: '/15671365/DMDemo@300x250:0',
+ kadfloor: '1.2',
+ pmzoneid: 'aabc, ddef',
+ kadpageurl: 'www.publisher.com',
+ yob: '1986',
+ gender: 'M',
+ lat: '12.3',
+ lon: '23.7',
+ wiid: '1234567890',
+ profId: '100',
+ verId: '200',
+ currency: 'AUD',
+ dctr: 'key1:val1,val2|key2:val1'
+ },
+ placementCode: '/19968336/header-bid-tag-1',
+ sizes: [[300, 250], [300, 600]],
+ bidId: 'test_bid_id',
+ requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99',
+ bidderRequestId: '1c56ad30b9b8ca8',
+ ortb2Imp: {
+ ext: {
+ tid: '92489f71-1bf2-49a0-adf9-000cea934729',
+ ae: 1
+ }
+ },
+ }
+ ];
+
+ let bidRequest = spec.buildRequests(bidRequestConfigs, {});
+ let bidResponse = {
+ seatbid: [{
+ bid: [{
+ impid: 'test_bid_id',
+ price: 2,
+ w: 728,
+ h: 250,
+ crid: 'test-creative-id',
+ dealid: 'test-deal-id',
+ adm: 'test-ad-markup'
+ }]
+ }],
+ cur: 'AUS',
+ ext: {
+ fledge_auction_configs: {
+ 'test_bid_id': {
+ seller: 'ads.pubmatic.com',
+ interestGroupBuyers: ['dsp1.com'],
+ sellerTimeout: 0,
+ perBuyerSignals: {
+ 'dsp1.com': {
+ bid_macros: 0.1,
+ disallowed_adv_ids: [
+ '5678',
+ '5890'
+ ],
+ }
+ }
+ }
+ }
+ }
+ };
+
+ response = spec.interpretResponse({ body: bidResponse }, bidRequest);
+ it('should return FLEDGE auction_configs alongside bids', function () {
+ expect(response).to.have.property('bids');
+ expect(response).to.have.property('fledgeAuctionConfigs');
+ expect(response.fledgeAuctionConfigs.length).to.equal(1);
+ expect(response.fledgeAuctionConfigs[0].bidId).to.equal('test_bid_id');
+ });
+ });
+
describe('Preapare metadata', function () {
it('Should copy all fields from ext to meta', function () {
const bid = {
diff --git a/test/spec/modules/pubxaiAnalyticsAdapter_spec.js b/test/spec/modules/pubxaiAnalyticsAdapter_spec.js
index 1dce87e4b8e..e0f4497a8c8 100644
--- a/test/spec/modules/pubxaiAnalyticsAdapter_spec.js
+++ b/test/spec/modules/pubxaiAnalyticsAdapter_spec.js
@@ -1,13 +1,9 @@
-import pubxaiAnalyticsAdapter from 'modules/pubxaiAnalyticsAdapter.js';
-import { getDeviceType, getBrowser, getOS } from 'modules/pubxaiAnalyticsAdapter.js';
-import {
- expect
-} from 'chai';
+import pubxaiAnalyticsAdapter, {getBrowser, getDeviceType, getOS} from 'modules/pubxaiAnalyticsAdapter.js';
+import {expect} from 'chai';
import adapterManager from 'src/adapterManager.js';
import * as utils from 'src/utils.js';
-import {
- server
-} from 'test/mocks/xhr.js';
+import {server} from 'test/mocks/xhr.js';
+import {getGptSlotInfoForAdUnitCode} from '../../../libraries/gptUtils/gptUtils.js';
let events = require('src/events');
let constants = require('src/constants.json');
@@ -527,7 +523,7 @@ describe('pubxai analytics adapter', function() {
'bidderCode': 'appnexus',
'bidId': '248f9a4489835e',
'adUnitCode': '/19968336/header-bid-tag-1',
- 'gptSlotCode': utils.getGptSlotInfoForAdUnitCode('/19968336/header-bid-tag-1').gptSlot || null,
+ 'gptSlotCode': getGptSlotInfoForAdUnitCode('/19968336/header-bid-tag-1').gptSlot || null,
'auctionId': 'bc3806e4-873e-453c-8ae5-204f35e923b4',
'sizes': '300x250',
'renderStatus': 2,
@@ -596,7 +592,7 @@ describe('pubxai analytics adapter', function() {
let expectedAfterBidWon = {
'winningBid': {
'adUnitCode': '/19968336/header-bid-tag-1',
- 'gptSlotCode': utils.getGptSlotInfoForAdUnitCode('/19968336/header-bid-tag-1').gptSlot || null,
+ 'gptSlotCode': getGptSlotInfoForAdUnitCode('/19968336/header-bid-tag-1').gptSlot || null,
'auctionId': 'bc3806e4-873e-453c-8ae5-204f35e923b4',
'bidderCode': 'appnexus',
'bidId': '248f9a4489835e',
diff --git a/test/spec/modules/qortexRtdProvider_spec.js b/test/spec/modules/qortexRtdProvider_spec.js
new file mode 100644
index 00000000000..9baa526e4cc
--- /dev/null
+++ b/test/spec/modules/qortexRtdProvider_spec.js
@@ -0,0 +1,333 @@
+import * as utils from 'src/utils';
+import * as ajax from 'src/ajax.js';
+import * as events from 'src/events.js';
+import CONSTANTS from '../../../src/constants.json';
+import {loadExternalScript} from 'src/adloader.js';
+import {
+ qortexSubmodule as module,
+ getContext,
+ addContextToRequests,
+ setContextData,
+ initializeModuleData,
+ loadScriptTag
+} from '../../../modules/qortexRtdProvider';
+import {server} from '../../mocks/xhr.js';
+import { cloneDeep } from 'lodash';
+
+describe('qortexRtdProvider', () => {
+ let logWarnSpy;
+ let ortb2Stub;
+
+ const defaultApiHost = 'https://demand.qortex.ai';
+ const defaultGroupId = 'test';
+
+ const validBidderArray = ['qortex', 'test'];
+ const validTagConfig = {
+ videoContainer: 'my-video-container'
+ }
+
+ const validModuleConfig = {
+ params: {
+ groupId: defaultGroupId,
+ apiUrl: defaultApiHost,
+ bidders: validBidderArray
+ }
+ },
+ emptyModuleConfig = {
+ params: {}
+ }
+
+ const validImpressionEvent = {
+ detail: {
+ uid: 'uid123',
+ type: 'qx-impression'
+ }
+ },
+ validImpressionEvent2 = {
+ detail: {
+ uid: 'uid1234',
+ type: 'qx-impression'
+ }
+ },
+ missingIdImpressionEvent = {
+ detail: {
+ type: 'qx-impression'
+ }
+ },
+ invalidTypeQortexEvent = {
+ detail: {
+ type: 'invalid-type'
+ }
+ }
+
+ const responseHeaders = {
+ 'content-type': 'application/json',
+ 'access-control-allow-origin': '*'
+ };
+
+ const responseObj = {
+ content: {
+ id: '123456',
+ episode: 15,
+ title: 'test episode',
+ series: 'test show',
+ season: '1',
+ url: 'https://example.com/file.mp4'
+ }
+ };
+
+ const apiResponse = JSON.stringify(responseObj);
+
+ const reqBidsConfig = {
+ adUnits: [{
+ bids: [
+ { bidder: 'qortex' }
+ ]
+ }],
+ ortb2Fragments: {
+ bidder: {},
+ global: {}
+ }
+ }
+
+ beforeEach(() => {
+ ortb2Stub = sinon.stub(reqBidsConfig, 'ortb2Fragments').value({bidder: {}, global: {}})
+ logWarnSpy = sinon.spy(utils, 'logWarn');
+ })
+
+ afterEach(() => {
+ logWarnSpy.restore();
+ ortb2Stub.restore();
+ setContextData(null);
+ })
+
+ describe('init', () => {
+ it('returns true for valid config object', () => {
+ expect(module.init(validModuleConfig)).to.be.true;
+ })
+
+ it('returns false and logs error for missing groupId', () => {
+ expect(module.init(emptyModuleConfig)).to.be.false;
+ expect(logWarnSpy.calledOnce).to.be.true;
+ expect(logWarnSpy.calledWith('Qortex RTD module config does not contain valid groupId parameter. Config params: {}')).to.be.ok;
+ })
+
+ it('loads Qortex script if tagConfig is present in module config params', () => {
+ const config = cloneDeep(validModuleConfig);
+ config.params.tagConfig = validTagConfig;
+ expect(module.init(config)).to.be.true;
+ expect(loadExternalScript.calledOnce).to.be.true;
+ })
+ })
+
+ describe('loadScriptTag', () => {
+ let addEventListenerSpy;
+ let billableEvents = [];
+
+ let config = cloneDeep(validModuleConfig);
+ config.params.tagConfig = validTagConfig;
+
+ events.on(CONSTANTS.EVENTS.BILLABLE_EVENT, (e) => {
+ billableEvents.push(e);
+ })
+
+ beforeEach(() => {
+ initializeModuleData(config);
+ addEventListenerSpy = sinon.spy(window, 'addEventListener');
+ })
+
+ afterEach(() => {
+ addEventListenerSpy.restore();
+ billableEvents = [];
+ })
+
+ it('adds event listener', () => {
+ loadScriptTag(config);
+ expect(addEventListenerSpy.calledOnce).to.be.true;
+ })
+
+ it('parses incoming qortex-impression events', () => {
+ loadScriptTag(config);
+ dispatchEvent(new CustomEvent('qortex-rtd', validImpressionEvent));
+ expect(billableEvents.length).to.be.equal(1);
+ expect(billableEvents[0].type).to.be.equal(validImpressionEvent.detail.type);
+ expect(billableEvents[0].transactionId).to.be.equal(validImpressionEvent.detail.uid);
+ })
+
+ it('will emit two events for impressions with two different ids', () => {
+ loadScriptTag(config);
+ dispatchEvent(new CustomEvent('qortex-rtd', validImpressionEvent));
+ dispatchEvent(new CustomEvent('qortex-rtd', validImpressionEvent2));
+ expect(billableEvents.length).to.be.equal(2);
+ expect(billableEvents[0].transactionId).to.be.equal(validImpressionEvent.detail.uid);
+ expect(billableEvents[1].transactionId).to.be.equal(validImpressionEvent2.detail.uid);
+ })
+
+ it('will not allow multiple events with the same id', () => {
+ loadScriptTag(config);
+ dispatchEvent(new CustomEvent('qortex-rtd', validImpressionEvent));
+ dispatchEvent(new CustomEvent('qortex-rtd', validImpressionEvent));
+ expect(billableEvents.length).to.be.equal(1);
+ expect(logWarnSpy.calledWith('received invalid billable event due to duplicate uid: qx-impression')).to.be.ok;
+ })
+
+ it('will not allow events with missing uid', () => {
+ loadScriptTag(config);
+ dispatchEvent(new CustomEvent('qortex-rtd', missingIdImpressionEvent));
+ expect(billableEvents.length).to.be.equal(0);
+ expect(logWarnSpy.calledWith('received invalid billable event due to missing uid: qx-impression')).to.be.ok;
+ })
+
+ it('will not allow events with unavailable type', () => {
+ loadScriptTag(config);
+ dispatchEvent(new CustomEvent('qortex-rtd', invalidTypeQortexEvent));
+ expect(billableEvents.length).to.be.equal(0);
+ expect(logWarnSpy.calledWith('received invalid billable event: invalid-type')).to.be.ok;
+ })
+ })
+
+ describe('getBidRequestData', () => {
+ let callbackSpy;
+
+ beforeEach(() => {
+ initializeModuleData(validModuleConfig);
+ callbackSpy = sinon.spy();
+ })
+
+ afterEach(() => {
+ initializeModuleData(emptyModuleConfig);
+ callbackSpy.resetHistory();
+ })
+
+ it('will call callback immediately if no adunits', () => {
+ const reqBidsConfigNoBids = { adUnits: [] };
+ module.getBidRequestData(reqBidsConfigNoBids, callbackSpy);
+ expect(callbackSpy.calledOnce).to.be.true;
+ expect(logWarnSpy.calledWith('No adunits found on request bids configuration: ' + JSON.stringify(reqBidsConfigNoBids))).to.be.ok;
+ })
+
+ it('will call callback if getContext does not throw', () => {
+ const cb = function () {
+ expect(logWarnSpy.calledOnce).to.be.false;
+ done();
+ }
+ module.getBidRequestData(reqBidsConfig, cb);
+ server.requests[0].respond(200, responseHeaders, apiResponse);
+ })
+
+ it('will catch and log error and fire callback', (done) => {
+ const a = sinon.stub(ajax, 'ajax').throws(new Error('test'));
+ const cb = function () {
+ expect(logWarnSpy.calledWith('test')).to.be.eql(true);
+ done();
+ }
+ module.getBidRequestData(reqBidsConfig, cb);
+ a.restore();
+ })
+ })
+
+ describe('getContext', () => {
+ beforeEach(() => {
+ initializeModuleData(validModuleConfig);
+ })
+
+ afterEach(() => {
+ initializeModuleData(emptyModuleConfig);
+ })
+
+ it('returns a promise', (done) => {
+ const result = getContext();
+ expect(result).to.be.a('promise');
+ done();
+ })
+
+ it('uses request url generated from initialize function in config and resolves to content object data', (done) => {
+ let requestUrl = `${validModuleConfig.params.apiUrl}/api/v1/analyze/${validModuleConfig.params.groupId}/prebid`;
+ const ctx = getContext()
+ expect(server.requests.length).to.be.eql(1);
+ expect(server.requests[0].url).to.be.eql(requestUrl);
+ server.requests[0].respond(200, responseHeaders, apiResponse);
+ ctx.then(response => {
+ expect(response).to.be.eql(responseObj.content);
+ done();
+ });
+ })
+
+ it('will return existing context data instead of ajax call if the source was not updated', (done) => {
+ setContextData(responseObj.content);
+ const ctx = getContext();
+ expect(server.requests.length).to.be.eql(0);
+ ctx.then(response => {
+ expect(response).to.be.eql(responseObj.content);
+ done();
+ });
+ })
+
+ it('returns null for non erroring api responses other than 200', (done) => {
+ const nullContentResponse = { content: null }
+ const ctx = getContext()
+ server.requests[0].respond(200, responseHeaders, JSON.stringify(nullContentResponse))
+ ctx.then(response => {
+ expect(response).to.be.null;
+ expect(server.requests.length).to.be.eql(1);
+ expect(logWarnSpy.called).to.be.false;
+ done();
+ });
+ })
+ })
+
+ describe(' addContextToRequests', () => {
+ it('logs error if no data was retrieved from get context call', () => {
+ initializeModuleData(validModuleConfig);
+ addContextToRequests(reqBidsConfig);
+ expect(logWarnSpy.calledOnce).to.be.true;
+ expect(logWarnSpy.calledWith('No context data received at this time')).to.be.ok;
+ expect(reqBidsConfig.ortb2Fragments.global).to.be.eql({});
+ expect(reqBidsConfig.ortb2Fragments.bidder).to.be.eql({});
+ })
+
+ it('adds site.content only to global ortb2 when bidders array is omitted', () => {
+ const omittedBidderArrayConfig = cloneDeep(validModuleConfig);
+ delete omittedBidderArrayConfig.params.bidders;
+ initializeModuleData(omittedBidderArrayConfig);
+ setContextData(responseObj.content);
+ addContextToRequests(reqBidsConfig);
+ expect(reqBidsConfig.ortb2Fragments.global).to.have.property('site');
+ expect(reqBidsConfig.ortb2Fragments.global.site).to.have.property('content');
+ expect(reqBidsConfig.ortb2Fragments.global.site.content).to.be.eql(responseObj.content);
+ expect(reqBidsConfig.ortb2Fragments.bidder).to.be.eql({});
+ })
+
+ it('adds site.content only to bidder ortb2 when bidders array is included', () => {
+ initializeModuleData(validModuleConfig);
+ setContextData(responseObj.content);
+ addContextToRequests(reqBidsConfig);
+
+ const qortexOrtb2Fragment = reqBidsConfig.ortb2Fragments.bidder['qortex']
+ expect(qortexOrtb2Fragment).to.not.be.null;
+ expect(qortexOrtb2Fragment).to.have.property('site');
+ expect(qortexOrtb2Fragment.site).to.have.property('content');
+ expect(qortexOrtb2Fragment.site.content).to.be.eql(responseObj.content);
+
+ const testOrtb2Fragment = reqBidsConfig.ortb2Fragments.bidder['test']
+ expect(testOrtb2Fragment).to.not.be.null;
+ expect(testOrtb2Fragment).to.have.property('site');
+ expect(testOrtb2Fragment.site).to.have.property('content');
+ expect(testOrtb2Fragment.site.content).to.be.eql(responseObj.content);
+
+ expect(reqBidsConfig.ortb2Fragments.global).to.be.eql({});
+ })
+
+ it('logs error if there is an empty bidder array', () => {
+ const invalidBidderArrayConfig = cloneDeep(validModuleConfig);
+ invalidBidderArrayConfig.params.bidders = [];
+ initializeModuleData(invalidBidderArrayConfig);
+ setContextData(responseObj.content)
+ addContextToRequests(reqBidsConfig);
+
+ expect(logWarnSpy.calledWith('Config contains an empty bidders array, unable to determine which bids to enrich')).to.be.ok;
+ expect(reqBidsConfig.ortb2Fragments.global).to.be.eql({});
+ expect(reqBidsConfig.ortb2Fragments.bidder).to.be.eql({});
+ })
+ })
+})
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/rasBidAdapter_spec.js b/test/spec/modules/rasBidAdapter_spec.js
index bfa72a2510e..719e15ad695 100644
--- a/test/spec/modules/rasBidAdapter_spec.js
+++ b/test/spec/modules/rasBidAdapter_spec.js
@@ -1,6 +1,7 @@
import { expect } from 'chai';
import { spec } from 'modules/rasBidAdapter.js';
import { newBidder } from 'src/adapters/bidderFactory.js';
+import {getAdUnitSizes} from '../../../src/utils';
const CSR_ENDPOINT = 'https://csr.onet.pl/4178463/csr-006/csr.json?nid=4178463&';
@@ -192,5 +193,56 @@ describe('rasBidAdapter', function () {
const resp = spec.interpretResponse({ body: res }, {});
expect(resp).to.deep.equal([]);
});
+
+ it('should generate auctionConfig when fledge is enabled', function () {
+ let bidRequest = {
+ method: 'GET',
+ url: 'https://example.com',
+ bidIds: [{
+ slot: 'top',
+ bidId: '123',
+ network: 'testnetwork',
+ sizes: ['300x250'],
+ params: {
+ site: 'testsite',
+ area: 'testarea',
+ network: 'testnetwork'
+ },
+ fledgeEnabled: true
+ },
+ {
+ slot: 'top',
+ bidId: '456',
+ network: 'testnetwork',
+ sizes: ['300x250'],
+ params: {
+ site: 'testsite',
+ area: 'testarea',
+ network: 'testnetwork'
+ },
+ fledgeEnabled: false
+ }]
+ };
+
+ let auctionConfigs = [{
+ 'bidId': '123',
+ 'config': {
+ 'seller': 'https://csr.onet.pl',
+ 'decisionLogicUrl': 'https://csr.onet.pl/testnetwork/v1/protected-audience-api/decision-logic.js',
+ 'interestGroupBuyers': ['https://csr.onet.pl'],
+ 'auctionSignals': {
+ 'params': {
+ site: 'testsite',
+ area: 'testarea',
+ network: 'testnetwork'
+ },
+ 'sizes': ['300x250'],
+ 'gctx': '1234567890'
+ }
+ }
+ }];
+ const resp = spec.interpretResponse({body: {gctx: '1234567890'}}, bidRequest);
+ expect(resp).to.deep.equal({bids: [], fledgeAuctionConfigs: auctionConfigs});
+ });
});
});
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/relevantdigitalBidAdapter_spec.js b/test/spec/modules/relevantdigitalBidAdapter_spec.js
index b2a5495b3cb..0e21453c8ba 100644
--- a/test/spec/modules/relevantdigitalBidAdapter_spec.js
+++ b/test/spec/modules/relevantdigitalBidAdapter_spec.js
@@ -1,5 +1,10 @@
import {spec, resetBidderConfigs} from 'modules/relevantdigitalBidAdapter.js';
import { parseUrl, deepClone } from 'src/utils.js';
+import { config } from 'src/config.js';
+import CONSTANTS from 'src/constants.json';
+
+import adapterManager, {
+} from 'src/adapterManager.js';
const expect = require('chai').expect;
@@ -9,14 +14,29 @@ const ACCOUNT_ID = 'example_account_id';
const TEST_DOMAIN = 'example.com';
const TEST_PAGE = `https://${TEST_DOMAIN}/page.html`;
-const BID_REQUEST =
-{
- 'bidder': 'relevantdigital',
+const CONFIG = {
+ enabled: true,
+ endpoint: CONSTANTS.S2S.DEFAULT_ENDPOINT,
+ timeout: 1000,
+ maxBids: 1,
+ adapter: 'prebidServer',
+ bidders: ['relevantdigital'],
+ accountId: 'abc'
+};
+
+const ADUNIT_CODE = '/19968336/header-bid-tag-0';
+
+const BID_PARAMS = {
'params': {
'placementId': PLACEMENT_ID,
'accountId': ACCOUNT_ID,
- 'pbsHost': PBS_HOST,
- },
+ 'pbsHost': PBS_HOST
+ }
+};
+
+const BID_REQUEST = {
+ 'bidder': 'relevantdigital',
+ ...BID_PARAMS,
'ortb2Imp': {
'ext': {
'tid': 'e13391ea-00f3-495d-99a6-d937990d73a9'
@@ -32,7 +52,7 @@ const BID_REQUEST =
]
}
},
- 'adUnitCode': '/19968336/header-bid-tag-0',
+ 'adUnitCode': ADUNIT_CODE,
'transactionId': 'e13391ea-00f3-495d-99a6-d937990d73a9',
'sizes': [
[
@@ -292,4 +312,64 @@ describe('Relevant Digital Bid Adaper', function () {
expect(allSyncs).to.deep.equal(expectedResult)
});
});
+ describe('transformBidParams', function () {
+ beforeEach(() => {
+ config.setConfig({
+ s2sConfig: CONFIG,
+ });
+ });
+ afterEach(() => {
+ config.resetConfig();
+ });
+
+ const adUnit = (params) => ({
+ code: ADUNIT_CODE,
+ bids: [
+ {
+ bidder: 'relevantdigital',
+ adUnitCode: ADUNIT_CODE,
+ params,
+ }
+ ]
+ });
+
+ const request = (params) => adapterManager.makeBidRequests([adUnit(params)], 123, 'auction-id', 123, [], {})[0];
+
+ it('transforms adunit bid params and config params correctly', function () {
+ config.setConfig({
+ relevantdigital: {
+ pbsHost: PBS_HOST,
+ accountId: ACCOUNT_ID,
+ },
+ });
+ const adUnitParams = { placementId: PLACEMENT_ID };
+ const expextedTransformedBidParams = {
+ ...BID_PARAMS.params, pbsHost: `https://${BID_PARAMS.params.pbsHost}`, 'pbsBufferMs': 250
+ };
+ expect(spec.transformBidParams(adUnitParams, null, null, [request(adUnitParams)])).to.deep.equal(expextedTransformedBidParams);
+ });
+ it('transforms adunit bid params correctly', function () {
+ const adUnitParams = { ...BID_PARAMS.params, pbsHost: 'host.relevant-digital.com', pbsBufferMs: 500 };
+ const expextedTransformedBidParams = {
+ ...BID_PARAMS.params, pbsHost: 'host.relevant-digital.com', pbsBufferMs: 500
+ };
+ expect(spec.transformBidParams(adUnitParams, null, null, [request(adUnitParams)])).to.deep.equal(expextedTransformedBidParams);
+ });
+ it('transforms adunit bid params correctly', function () {
+ const adUnitParams = { ...BID_PARAMS.params, pbsHost: 'host.relevant-digital.com', pbsBufferMs: 500 };
+ const expextedTransformedBidParams = {
+ ...BID_PARAMS.params, pbsHost: 'host.relevant-digital.com', pbsBufferMs: 500
+ };
+ expect(spec.transformBidParams(adUnitParams, null, null, [request(adUnitParams)])).to.deep.equal(expextedTransformedBidParams);
+ });
+ it('does not transform bid params if placementId is missing', function () {
+ const adUnitParams = { ...BID_PARAMS.params, placementId: null };
+ expect(spec.transformBidParams(adUnitParams, null, null, [request(adUnitParams)])).to.equal(undefined);
+ });
+ it('does not transform bid params s2s config is missing', function () {
+ config.resetConfig();
+ const adUnitParams = BID_PARAMS.params;
+ expect(spec.transformBidParams(adUnitParams, null, null, [request(adUnitParams)])).to.equal(undefined);
+ });
+ })
});
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..28bd123cb5d 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: {
diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js
index d04b8075134..f0e33ce940e 100644
--- a/test/spec/modules/rubiconBidAdapter_spec.js
+++ b/test/spec/modules/rubiconBidAdapter_spec.js
@@ -696,6 +696,16 @@ describe('the rubicon adapter', function () {
expect(data['p_pos']).to.equal('atf;;btf;;');
});
+ it('should correctly send cdep signal when requested', () => {
+ var badposRequest = utils.deepClone(bidderRequest);
+ badposRequest.bids[0].ortb2 = {device: {ext: {cdep: 3}}};
+
+ let [request] = spec.buildRequests(badposRequest.bids, badposRequest);
+ let data = parseQuery(request.data);
+
+ expect(data['o_cdep']).to.equal('3');
+ });
+
it('ad engine query params should be ordered correctly', function () {
sandbox.stub(Math, 'random').callsFake(() => 0.1);
let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
@@ -1577,6 +1587,22 @@ describe('the rubicon adapter', function () {
expect(data['eid_catchall']).to.equal('11111^2');
});
+
+ it('should send rubiconproject special case', function () {
+ const clonedBid = utils.deepClone(bidderRequest.bids[0]);
+ // Hardcoding userIdAsEids since createEidsArray returns empty array if source not found in eids.js
+ clonedBid.userIdAsEids = [{
+ source: 'rubiconproject.com',
+ uids: [{
+ id: 'some-cool-id',
+ atype: 3
+ }]
+ }]
+ let [request] = spec.buildRequests([clonedBid], bidderRequest);
+ let data = parseQuery(request.data);
+
+ expect(data['eid_rubiconproject.com']).to.equal('some-cool-id');
+ });
});
describe('Config user.id support', function () {
@@ -1792,6 +1818,126 @@ describe('the rubicon adapter', function () {
expect(data['tg_i.dfp_ad_unit_code']).to.equal('/a/b/c');
});
});
+
+ describe('client hints', function () {
+ let standardSuaObject;
+ beforeEach(function () {
+ standardSuaObject = {
+ source: 2,
+ platform: {
+ brand: 'macOS',
+ version: [
+ '12',
+ '6',
+ '0'
+ ]
+ },
+ browsers: [
+ {
+ brand: 'Not.A/Brand',
+ version: [
+ '8',
+ '0',
+ '0',
+ '0'
+ ]
+ },
+ {
+ brand: 'Chromium',
+ version: [
+ '114',
+ '0',
+ '5735',
+ '198'
+ ]
+ },
+ {
+ brand: 'Google Chrome',
+ version: [
+ '114',
+ '0',
+ '5735',
+ '198'
+ ]
+ }
+ ],
+ mobile: 0,
+ model: '',
+ bitness: '64',
+ architecture: 'x86'
+ }
+ });
+ it('should send m_ch_* params if ortb2.device.sua object is there', function () {
+ let bidRequestSua = utils.deepClone(bidderRequest);
+ bidRequestSua.bids[0].ortb2 = { device: { sua: standardSuaObject } };
+
+ // How should fastlane query be constructed with default SUA
+ let expectedValues = {
+ m_ch_arch: 'x86',
+ m_ch_bitness: '64',
+ m_ch_ua: `"Not.A/Brand"|v="8","Chromium"|v="114","Google Chrome"|v="114"`,
+ m_ch_full_ver: `"Not.A/Brand"|v="8.0.0.0","Chromium"|v="114.0.5735.198","Google Chrome"|v="114.0.5735.198"`,
+ m_ch_mobile: '?0',
+ m_ch_platform: 'macOS',
+ m_ch_platform_ver: '12.6.0'
+ }
+
+ // Build Fastlane call
+ let [request] = spec.buildRequests(bidRequestSua.bids, bidRequestSua);
+ let data = parseQuery(request.data);
+
+ // Loop through expected values and if they do not match push an error
+ const errors = Object.entries(expectedValues).reduce((accum, [key, val]) => {
+ if (data[key] !== val) accum.push(`${key} - expect: ${val} - got: ${data[key]}`)
+ return accum;
+ }, []);
+
+ // should be no errors
+ expect(errors).to.deep.equal([]);
+ });
+ it('should not send invalid values for m_ch_*', function () {
+ let bidRequestSua = utils.deepClone(bidderRequest);
+
+ // Alter input SUA object
+ // send model
+ standardSuaObject.model = 'Suface Duo';
+ // send mobile = 1
+ standardSuaObject.mobile = 1;
+
+ // make browsers not an array
+ standardSuaObject.browsers = 'My Browser';
+
+ // make platform not have version
+ delete standardSuaObject.platform.version;
+
+ // delete architecture
+ delete standardSuaObject.architecture;
+
+ // add SUA to bid
+ bidRequestSua.bids[0].ortb2 = { device: { sua: standardSuaObject } };
+
+ // Build Fastlane request
+ let [request] = spec.buildRequests(bidRequestSua.bids, bidRequestSua);
+ let data = parseQuery(request.data);
+
+ // should show new names
+ expect(data.m_ch_model).to.equal('Suface Duo');
+ expect(data.m_ch_mobile).to.equal('?1');
+
+ // should still send platform
+ expect(data.m_ch_platform).to.equal('macOS');
+
+ // platform version not sent
+ expect(data).to.not.haveOwnProperty('m_ch_platform_ver');
+
+ // both ua and full_ver not sent because browsers not array
+ expect(data).to.not.haveOwnProperty('m_ch_ua');
+ expect(data).to.not.haveOwnProperty('m_ch_full_ver');
+
+ // arch not sent
+ expect(data).to.not.haveOwnProperty('m_ch_arch');
+ });
+ });
});
if (FEATURES.VIDEO) {
@@ -2235,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 () {
@@ -2573,6 +2709,15 @@ describe('the rubicon adapter', function () {
const slotParams = spec.createSlotParams(bidderRequest.bids[0], bidderRequest);
expect(slotParams.kw).to.equal('a,b,c');
});
+
+ it('should pass along o_ae param when fledge is enabled', () => {
+ const localBidRequest = Object.assign({}, bidderRequest.bids[0]);
+ localBidRequest.ortb2Imp.ext.ae = true;
+
+ const slotParams = spec.createSlotParams(localBidRequest, bidderRequest);
+
+ expect(slotParams['o_ae']).to.equal(1)
+ });
});
describe('classifiedAsVideo', function () {
@@ -2636,6 +2781,18 @@ describe('the rubicon adapter', function () {
expect(request.data.imp).to.have.nested.property('[0].native');
});
+ it('should not break if position is set and no video MT', function () {
+ const bidReq = addNativeToBidRequest(bidderRequest);
+ delete bidReq.bids[0].mediaTypes.banner;
+ bidReq.bids[0].params = {
+ position: 'atf'
+ }
+ let [request] = spec.buildRequests(bidReq.bids, bidReq);
+ expect(request.method).to.equal('POST');
+ expect(request.url).to.equal('https://prebid-server.rubiconproject.com/openrtb2/auction');
+ expect(request.data.imp).to.have.nested.property('[0].native');
+ });
+
describe('that contains also a banner mediaType', function () {
it('should send the banner to fastlane BUT NOT the native bid because missing params.video', function() {
const bidReq = addNativeToBidRequest(bidderRequest);
@@ -3281,6 +3438,43 @@ describe('the rubicon adapter', function () {
expect(bids).to.be.lengthOf(0);
});
+ it('Should support recieving an auctionConfig and pass it along to Prebid', function () {
+ let response = {
+ 'status': 'ok',
+ 'account_id': 14062,
+ 'site_id': 70608,
+ 'zone_id': 530022,
+ 'size_id': 15,
+ 'alt_size_ids': [
+ 43
+ ],
+ 'tracking': '',
+ 'inventory': {},
+ 'ads': [{
+ 'status': 'ok',
+ 'cpm': 0,
+ 'size_id': 15
+ }],
+ 'component_auction_config': [{
+ 'random': 'value',
+ 'bidId': '5432'
+ },
+ {
+ 'random': 'string',
+ 'bidId': '6789'
+ }]
+ };
+
+ let {bids, fledgeAuctionConfigs} = spec.interpretResponse({body: response}, {
+ bidRequest: bidderRequest.bids[0]
+ });
+
+ expect(bids).to.be.lengthOf(1);
+ expect(fledgeAuctionConfigs[0].bidId).to.equal('5432');
+ expect(fledgeAuctionConfigs[0].config.random).to.equal('value');
+ expect(fledgeAuctionConfigs[1].bidId).to.equal('6789');
+ });
+
it('should handle an error', function () {
let response = {
'status': 'ok',
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 68bf14ae9c1..6a63ae681e7 100644
--- a/test/spec/modules/sharethroughBidAdapter_spec.js
+++ b/test/spec/modules/sharethroughBidAdapter_spec.js
@@ -409,12 +409,12 @@ describe('sharethrough adapter spec', function () {
it('should properly attach GPP information to the request when applicable', () => {
bidderRequest.gppConsent = {
gppString: 'some-gpp-string',
- applicableSections: [3, 5]
+ applicableSections: [3, 5],
};
const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data;
- expect(openRtbReq.regs.gpp).to.equal(bidderRequest.gppConsent.gppString)
- expect(openRtbReq.regs.gpp_sid).to.equal(bidderRequest.gppConsent.applicableSections)
+ expect(openRtbReq.regs.gpp).to.equal(bidderRequest.gppConsent.gppString);
+ expect(openRtbReq.regs.gpp_sid).to.equal(bidderRequest.gppConsent.applicableSections);
});
it('should populate request accordingly when gpp explicitly does not apply', function () {
@@ -588,6 +588,43 @@ describe('sharethrough adapter spec', function () {
});
});
+ 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;
+ });
+ });
+
describe('first party data', () => {
const firstPartyData = {
site: {
@@ -618,7 +655,7 @@ describe('sharethrough adapter spec', function () {
badv: ['domain1.com', 'domain2.com'],
regs: {
gpp: 'gpp_string',
- gpp_sid: [7]
+ gpp_sid: [7],
},
};
@@ -870,25 +907,6 @@ describe('sharethrough adapter spec', function () {
const syncArray = spec.getUserSyncs({ pixelEnabled: false }, serverResponses);
expect(syncArray).to.be.an('array').that.is.empty;
});
-
- it('returns GDPR Consent Params in UserSync url', function () {
- const syncArray = spec.getUserSyncs({ pixelEnabled: true }, serverResponses, { gdprApplies: true,
- consentString: 'consent' });
- expect(syncArray).to.deep.equal([
- { type: 'image', url: 'cookieUrl1&gdpr=1&gdpr_consent=consent' },
- { type: 'image', url: 'cookieUrl2&gdpr=1&gdpr_consent=consent' },
- { type: 'image', url: 'cookieUrl3&gdpr=1&gdpr_consent=consent' },
- ]);
- });
-
- it('returns GPP Consent Params in UserSync url', function () {
- const syncArray = spec.getUserSyncs({ pixelEnabled: true }, serverResponses, {}, {gppString: 'gpp-string', applicableSections: [1, 2]});
- expect(syncArray).to.deep.equal([
- { type: 'image', url: 'cookieUrl1&gdpr=0&gdpr_consent=&gpp=gpp-string&gpp_sid=1%2C2' },
- { type: 'image', url: 'cookieUrl2&gdpr=0&gdpr_consent=&gpp=gpp-string&gpp_sid=1%2C2' },
- { type: 'image', url: 'cookieUrl3&gdpr=0&gdpr_consent=&gpp=gpp-string&gpp_sid=1%2C2' },
- ]);
- });
});
});
});
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/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/smartyadsBidAdapter_spec.js b/test/spec/modules/smartyadsBidAdapter_spec.js
index 350cad33704..458ccc37759 100644
--- a/test/spec/modules/smartyadsBidAdapter_spec.js
+++ b/test/spec/modules/smartyadsBidAdapter_spec.js
@@ -52,7 +52,11 @@ describe('SmartyadsAdapter', function () {
expect(serverRequest.method).to.equal('POST');
});
it('Returns valid URL', function () {
- expect(serverRequest.url).to.equal('https://n1.smartyads.com/?c=o&m=prebid&secret_key=prebid_js');
+ expect(serverRequest.url).to.be.oneOf([
+ 'https://n1.smartyads.com/?c=o&m=prebid&secret_key=prebid_js',
+ 'https://n2.smartyads.com/?c=o&m=prebid&secret_key=prebid_js',
+ 'https://n6.smartyads.com/?c=o&m=prebid&secret_key=prebid_js'
+ ]);
});
it('Returns valid data if array of bids is valid', function () {
let data = serverRequest.data;
@@ -280,7 +284,21 @@ describe('SmartyadsAdapter', function () {
});
it('should send a valid bid won notice', function () {
- spec.onBidWon(bidResponse);
+ const bid = {
+ 'c': 'o',
+ 'm': 'prebid',
+ 'secret_key': 'prebid_js',
+ 'winTest': '1',
+ 'postData': [{
+ 'bidder': 'smartyads',
+ 'params': [
+ {'host': 'prebid',
+ 'accountid': '123',
+ 'sourceid': '12345'
+ }]
+ }]
+ };
+ spec.onBidWon(bid);
expect(server.requests.length).to.equal(1);
});
});
@@ -291,7 +309,21 @@ describe('SmartyadsAdapter', function () {
});
it('should send a valid bid timeout notice', function () {
- spec.onTimeout({});
+ const bid = {
+ 'c': 'o',
+ 'm': 'prebid',
+ 'secret_key': 'prebid_js',
+ 'bidTimeout': '1',
+ 'postData': [{
+ 'bidder': 'smartyads',
+ 'params': [
+ {'host': 'prebid',
+ 'accountid': '123',
+ 'sourceid': '12345'
+ }]
+ }]
+ };
+ spec.onTimeout(bid);
expect(server.requests.length).to.equal(1);
});
});
@@ -302,7 +334,21 @@ describe('SmartyadsAdapter', function () {
});
it('should send a valid bidder error notice', function () {
- spec.onBidderError({});
+ const bid = {
+ 'c': 'o',
+ 'm': 'prebid',
+ 'secret_key': 'prebid_js',
+ 'bidderError': '1',
+ 'postData': [{
+ 'bidder': 'smartyads',
+ 'params': [
+ {'host': 'prebid',
+ 'accountid': '123',
+ 'sourceid': '12345'
+ }]
+ }]
+ };
+ spec.onBidderError(bid);
expect(server.requests.length).to.equal(1);
});
});
diff --git a/test/spec/modules/snigelBidAdapter_spec.js b/test/spec/modules/snigelBidAdapter_spec.js
index 7fe2387ca6c..3ba84228872 100644
--- a/test/spec/modules/snigelBidAdapter_spec.js
+++ b/test/spec/modules/snigelBidAdapter_spec.js
@@ -23,6 +23,7 @@ const BASE_BIDDER_REQUEST = {
auctionId: 'test',
bidderRequestId: 'test',
refererInfo: {
+ page: 'https://localhost',
canonicalUrl: 'https://localhost',
},
};
diff --git a/test/spec/modules/sonobiAnalyticsAdapter_spec.js b/test/spec/modules/sonobiAnalyticsAdapter_spec.js
index 76ff88836d4..ed8ccd22eea 100644
--- a/test/spec/modules/sonobiAnalyticsAdapter_spec.js
+++ b/test/spec/modules/sonobiAnalyticsAdapter_spec.js
@@ -1,4 +1,4 @@
-import sonobiAnalytics from 'modules/sonobiAnalyticsAdapter.js';
+import sonobiAnalytics, {DEFAULT_EVENT_URL} from 'modules/sonobiAnalyticsAdapter.js';
import {expect} from 'chai';
import {server} from 'test/mocks/xhr.js';
let events = require('src/events');
@@ -76,8 +76,8 @@ describe('Sonobi Prebid Analytic', function () {
events.emit(constants.EVENTS.AUCTION_END, {auctionId: '13', bidsReceived: [bid]});
clock.tick(5000);
- expect(server.requests).to.have.length(1);
- expect(JSON.parse(server.requests[0].requestBody)).to.have.length(3)
+ const req = server.requests.find(req => req.url.indexOf(DEFAULT_EVENT_URL) !== -1);
+ expect(JSON.parse(req.requestBody)).to.have.length(3)
done();
});
});
diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js
index de8d0a5bda7..83db7c0a812 100644
--- a/test/spec/modules/sonobiBidAdapter_spec.js
+++ b/test/spec/modules/sonobiBidAdapter_spec.js
@@ -1,9 +1,9 @@
-import { expect } from 'chai'
-import { spec, _getPlatform } from 'modules/sonobiBidAdapter.js'
-import { newBidder } from 'src/adapters/bidderFactory.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 utils from '../../../src/utils.js';
+import * as gptUtils from '../../../libraries/gptUtils/gptUtils.js';
describe('SonobiBidAdapter', function () {
const adapter = newBidder(spec)
@@ -248,13 +248,13 @@ describe('SonobiBidAdapter', function () {
let sandbox;
beforeEach(function () {
sinon.stub(userSync, 'canBidderRegisterSync');
- sinon.stub(utils, 'getGptSlotInfoForAdUnitCode')
+ sinon.stub(gptUtils, 'getGptSlotInfoForAdUnitCode')
.onFirstCall().returns({ gptSlot: '/123123/gpt_publisher/adunit-code-3', divId: 'adunit-code-3-div-id' });
sandbox = sinon.createSandbox();
});
afterEach(function () {
userSync.canBidderRegisterSync.restore();
- utils.getGptSlotInfoForAdUnitCode.restore();
+ gptUtils.getGptSlotInfoForAdUnitCode.restore();
sandbox.restore();
});
let bidRequest = [{
@@ -295,7 +295,10 @@ describe('SonobiBidAdapter', function () {
mediaTypes: {
video: {
playerSize: [640, 480],
- context: 'outstream'
+ context: 'outstream',
+ playbackmethod: [1, 2, 3],
+ plcmt: 3,
+ placement: 2
}
}
},
@@ -339,7 +342,7 @@ describe('SonobiBidAdapter', function () {
}];
let keyMakerData = {
- '30b31c1838de1f': '1a2b3c4d5e6f1a2b3c4d|640x480|f=1.25,gpid=/123123/gpt_publisher/adunit-code-1,c=v,',
+ '30b31c1838de1f': '1a2b3c4d5e6f1a2b3c4d|640x480|f=1.25,gpid=/123123/gpt_publisher/adunit-code-1,c=v,pm=1:2:3,p=2,pl=3,',
'30b31c1838de1d': '1a2b3c4d5e6f1a2b3c4e|300x250,300x600|f=0.42,gpid=/123123/gpt_publisher/adunit-code-3,c=d,',
'/7780971/sparks_prebid_LB|30b31c1838de1e': '300x250,300x600|gpid=/7780971/sparks_prebid_LB,c=d,',
};
@@ -356,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 () {
@@ -490,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 90913c6f130..f165a6da6d1 100644
--- a/test/spec/modules/sovrnBidAdapter_spec.js
+++ b/test/spec/modules/sovrnBidAdapter_spec.js
@@ -64,6 +64,29 @@ describe('sovrnBidAdapter', function() {
expect(spec.isBidRequestValid(bidRequest)).to.equal(false)
})
+
+ it('should return true when minduration is not passed', function() {
+ const width = 300
+ const height = 250
+ const mimes = ['video/mp4', 'application/javascript']
+ const protocols = [2, 5]
+ const maxduration = 60
+ const startdelay = 0
+ const videoBidRequest = {
+ ...baseBidRequest,
+ mediaTypes: {
+ video: {
+ mimes,
+ protocols,
+ playerSize: [[width, height], [360, 240]],
+ maxduration,
+ startdelay
+ }
+ }
+ }
+
+ expect(spec.isBidRequestValid(videoBidRequest)).to.equal(true)
+ })
})
describe('buildRequests', function () {
@@ -295,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
new file mode 100644
index 00000000000..293f7da30a1
--- /dev/null
+++ b/test/spec/modules/sparteoBidAdapter_spec.js
@@ -0,0 +1,467 @@
+import {expect} from 'chai';
+import { deepClone, mergeDeep } from 'src/utils';
+import {spec as adapter} from 'modules/sparteoBidAdapter';
+
+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',
+ formats: ['corner']
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [1, 1]
+ ]
+ }
+ }
+};
+
+const VALID_BID_VIDEO = {
+ bidder: 'sparteo',
+ bidId: '5e6f7g8h',
+ adUnitCode: 'id-5678',
+ params: {
+ networkId: '1234567a-eb1b-1fae-1d23-e1fbaef234cf'
+ },
+ mediaTypes: {
+ video: {
+ playerSize: [640, 360],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ api: [1, 2],
+ mimes: ['video/mp4'],
+ skip: 1,
+ startdelay: 0,
+ placement: 1,
+ linearity: 1,
+ minduration: 5,
+ maxduration: 30,
+ context: 'instream'
+ }
+ },
+ ortb2Imp: {
+ ext: {
+ pbadslot: 'video'
+ }
+ }
+};
+
+const VALID_REQUEST_BANNER = {
+ method: HTTP_METHOD,
+ url: REQUEST_URL,
+ data: {
+ 'imp': [{
+ 'id': '1a2b3c4d',
+ 'banner': {
+ 'format': [{
+ 'h': 1,
+ 'w': 1
+ }],
+ 'topframe': 0
+ },
+ 'ext': {
+ 'sparteo': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf',
+ 'formats': ['corner']
+ }
+ }
+ }
+ }],
+ 'site': {
+ 'publisher': {
+ 'ext': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf'
+ }
+ }
+ }
+ },
+ 'test': 0
+ }
+};
+
+const VALID_REQUEST_VIDEO = {
+ method: HTTP_METHOD,
+ url: REQUEST_URL,
+ data: {
+ 'imp': [{
+ 'id': '5e6f7g8h',
+ 'video': {
+ 'w': 640,
+ 'h': 360,
+ 'protocols': [1, 2, 3, 4, 5, 6, 7, 8],
+ 'api': [1, 2],
+ 'mimes': ['video/mp4'],
+ 'skip': 1,
+ 'startdelay': 0,
+ 'placement': 1,
+ 'linearity': 1,
+ 'minduration': 5,
+ 'maxduration': 30,
+ },
+ 'ext': {
+ 'pbadslot': 'video',
+ 'sparteo': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf'
+ }
+ }
+ }
+ }],
+ 'site': {
+ 'publisher': {
+ 'ext': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf'
+ }
+ }
+ }
+ },
+ 'test': 0
+ }
+};
+
+const VALID_REQUEST = {
+ method: HTTP_METHOD,
+ url: REQUEST_URL,
+ data: {
+ 'imp': [{
+ 'id': '1a2b3c4d',
+ 'banner': {
+ 'format': [{
+ 'h': 1,
+ 'w': 1
+ }],
+ 'topframe': 0
+ },
+ 'ext': {
+ 'sparteo': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf',
+ 'formats': ['corner']
+ }
+ }
+ }
+ }, {
+ 'id': '5e6f7g8h',
+ 'video': {
+ 'w': 640,
+ 'h': 360,
+ 'protocols': [1, 2, 3, 4, 5, 6, 7, 8],
+ 'api': [1, 2],
+ 'mimes': ['video/mp4'],
+ 'skip': 1,
+ 'startdelay': 0,
+ 'placement': 1,
+ 'linearity': 1,
+ 'minduration': 5,
+ 'maxduration': 30,
+ },
+ 'ext': {
+ 'pbadslot': 'video',
+ 'sparteo': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf'
+ }
+ }
+ }
+ }],
+ 'site': {
+ 'publisher': {
+ 'ext': {
+ 'params': {
+ 'networkId': '1234567a-eb1b-1fae-1d23-e1fbaef234cf'
+ }
+ }
+ }
+ },
+ 'test': 0
+ }
+};
+
+const BIDDER_REQUEST = {
+ bids: [VALID_BID_BANNER, VALID_BID_VIDEO]
+}
+
+const BIDDER_REQUEST_BANNER = {
+ bids: [VALID_BID_BANNER]
+}
+
+const BIDDER_REQUEST_VIDEO = {
+ bids: [VALID_BID_VIDEO]
+}
+
+describe('SparteoAdapter', function () {
+ describe('isBidRequestValid', function () {
+ describe('Check method return', function () {
+ it('should return true', function () {
+ expect(adapter.isBidRequestValid(VALID_BID_BANNER)).to.equal(true);
+ expect(adapter.isBidRequestValid(VALID_BID_VIDEO)).to.equal(true);
+ });
+
+ it('should return false because the networkId is missing', function () {
+ let wrongBid = deepClone(VALID_BID_BANNER);
+ delete wrongBid.params.networkId;
+
+ expect(adapter.isBidRequestValid(wrongBid)).to.equal(false);
+ });
+
+ it('should return false because the banner size is missing', function () {
+ let wrongBid = deepClone(VALID_BID_BANNER);
+
+ wrongBid.mediaTypes.banner.sizes = '123456';
+ expect(adapter.isBidRequestValid(wrongBid)).to.equal(false);
+
+ delete wrongBid.mediaTypes.banner.sizes;
+ expect(adapter.isBidRequestValid(wrongBid)).to.equal(false);
+ });
+
+ it('should return false because the video player size paramater is missing', function () {
+ let wrongBid = deepClone(VALID_BID_VIDEO);
+
+ wrongBid.mediaTypes.video.playerSize = '123456';
+ expect(adapter.isBidRequestValid(wrongBid)).to.equal(false);
+
+ delete wrongBid.mediaTypes.video.playerSize;
+ expect(adapter.isBidRequestValid(wrongBid)).to.equal(false);
+ });
+ });
+ });
+
+ describe('buildRequests', function () {
+ describe('Check method return', function () {
+ if (FEATURES.VIDEO) {
+ it('should return the right formatted requests', function() {
+ const request = adapter.buildRequests([VALID_BID_BANNER, VALID_BID_VIDEO], BIDDER_REQUEST);
+ delete request.data.id;
+
+ expect(request).to.deep.equal(VALID_REQUEST);
+ });
+ }
+
+ it('should return the right formatted banner requests', function() {
+ const request = adapter.buildRequests([VALID_BID_BANNER], BIDDER_REQUEST_BANNER);
+ delete request.data.id;
+
+ expect(request).to.deep.equal(VALID_REQUEST_BANNER);
+ });
+
+ if (FEATURES.VIDEO) {
+ it('should return the right formatted video requests', function() {
+ const request = adapter.buildRequests([VALID_BID_VIDEO], BIDDER_REQUEST_VIDEO);
+ delete request.data.id;
+
+ expect(request).to.deep.equal(VALID_REQUEST_VIDEO);
+ });
+ }
+
+ it('should return the right formatted request with endpoint test', function() {
+ let endpoint = 'https://bid-test.sparteo.com/auction';
+
+ let bids = mergeDeep(deepClone([VALID_BID_BANNER, VALID_BID_VIDEO]), {
+ params: {
+ endpoint: endpoint
+ }
+ });
+
+ let requests = mergeDeep(deepClone(VALID_REQUEST));
+
+ const request = adapter.buildRequests(bids, BIDDER_REQUEST);
+ requests.url = endpoint;
+ delete request.data.id;
+
+ expect(requests).to.deep.equal(requests);
+ });
+ });
+ });
+
+ describe('interpretResponse', function() {
+ describe('Check method return', function () {
+ it('should return the right formatted response', function() {
+ let response = {
+ body: {
+ 'id': '63f4d300-6896-4bdc-8561-0932f73148b1',
+ 'cur': 'EUR',
+ 'seatbid': [
+ {
+ 'seat': 'sparteo',
+ 'group': 0,
+ 'bid': [
+ {
+ 'id': 'cdbb6982-a269-40c7-84e5-04797f11d87a',
+ 'impid': '1a2b3c4d',
+ 'price': 4.5,
+ 'ext': {
+ 'prebid': {
+ 'type': 'banner'
+ }
+ },
+ 'adm': 'script',
+ 'crid': 'crid',
+ 'w': 1,
+ 'h': 1,
+ 'nurl': 'https://t.bidder.sparteo.com/img'
+ }
+ ]
+ }
+ ]
+ }
+ };
+
+ if (FEATURES.VIDEO) {
+ response.body.seatbid[0].bid.push({
+ 'id': 'cdbb6982-a269-40c7-84e5-04797f11d87b',
+ 'impid': '5e6f7g8h',
+ 'price': 5,
+ 'ext': {
+ 'prebid': {
+ 'type': 'video',
+ 'cache': {
+ 'vastXml': {
+ 'url': 'https://pbs.tet.com/cache?uuid=1234'
+ }
+ }
+ }
+ },
+ 'adm': 'tag',
+ 'crid': 'crid',
+ 'w': 640,
+ 'h': 480,
+ 'nurl': 'https://t.bidder.sparteo.com/img'
+ });
+ }
+
+ let formattedReponse = [
+ {
+ requestId: '1a2b3c4d',
+ seatBidId: 'cdbb6982-a269-40c7-84e5-04797f11d87a',
+ cpm: 4.5,
+ width: 1,
+ height: 1,
+ creativeId: 'crid',
+ creative_id: 'crid',
+ currency: CURRENCY,
+ netRevenue: true,
+ ttl: TTL,
+ mediaType: 'banner',
+ meta: {},
+ ad: 'script'
+ }
+ ];
+
+ if (FEATURES.VIDEO) {
+ formattedReponse.push({
+ requestId: '5e6f7g8h',
+ seatBidId: 'cdbb6982-a269-40c7-84e5-04797f11d87b',
+ cpm: 5,
+ width: 640,
+ height: 480,
+ playerWidth: 640,
+ playerHeight: 360,
+ creativeId: 'crid',
+ creative_id: 'crid',
+ currency: CURRENCY,
+ netRevenue: true,
+ ttl: TTL,
+ mediaType: 'video',
+ meta: {},
+ nurl: 'https://t.bidder.sparteo.com/img',
+ vastUrl: 'https://pbs.tet.com/cache?uuid=1234',
+ vastXml: 'tag'
+ });
+ }
+
+ if (FEATURES.VIDEO) {
+ const request = adapter.buildRequests([VALID_BID_BANNER, VALID_BID_VIDEO], BIDDER_REQUEST);
+ expect(adapter.interpretResponse(response, request)).to.deep.equal(formattedReponse);
+ } else {
+ const request = adapter.buildRequests([VALID_BID_BANNER], BIDDER_REQUEST_BANNER);
+ expect(adapter.interpretResponse(response, request)).to.deep.equal(formattedReponse);
+ }
+ });
+ });
+ });
+
+ describe('onBidWon', function() {
+ describe('Check methods succeed', function () {
+ it('should not throw error', function() {
+ let bids = [
+ {
+ requestId: '1a2b3c4d',
+ seatBidId: 'cdbb6982-a269-40c7-84e5-04797f11d87a',
+ cpm: 4.5,
+ width: 1,
+ height: 1,
+ creativeId: 'crid',
+ creative_id: 'crid',
+ currency: CURRENCY,
+ netRevenue: true,
+ ttl: TTL,
+ mediaType: 'banner',
+ meta: {},
+ ad: 'script',
+ nurl: [
+ 'win.domain.com'
+ ]
+ },
+ {
+ requestId: '2570',
+ seatBidId: 'cdbb6982-a269-40c7-84e5-04797f11d87b',
+ id: 'id-5678',
+ cpm: 5,
+ width: 640,
+ height: 480,
+ creativeId: 'crid',
+ currency: CURRENCY,
+ netRevenue: true,
+ ttl: TTL,
+ mediaType: 'video',
+ meta: {},
+ vastXml: 'vast xml',
+ nurl: [
+ 'win.domain2.com'
+ ]
+ }
+ ];
+
+ bids.forEach(function(bid) {
+ expect(adapter.onBidWon.bind(adapter, bid)).to.not.throw();
+ });
+ });
+ });
+ });
+
+ 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/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 7d31e291667..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}/${commonBidRequest.params.publisherId}`);
- expect(res.data).to.deep.equal(JSON.stringify(expectedData));
+ expect(res.url).to.equal(`${END_POINT_URL}?publisher=${commonBidRequest.params.publisherId}`);
+ 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 9bd8c44b88a..98f706f5193 100644
--- a/test/spec/modules/teadsBidAdapter_spec.js
+++ b/test/spec/modules/teadsBidAdapter_spec.js
@@ -1,23 +1,21 @@
import {expect} from 'chai';
import {spec, storage} from 'modules/teadsBidAdapter.js';
import {newBidder} from 'src/adapters/bidderFactory.js';
-import {getStorageManager} from 'src/storageManager';
+import { off } from '../../../src/events';
const ENDPOINT = 'https://a.teads.tv/hb/bid-request';
const AD_SCRIPT = '"';
describe('teadsBidAdapter', () => {
const adapter = newBidder(spec);
- let cookiesAreEnabledStub, getCookieStub;
+ let sandbox;
beforeEach(function () {
- cookiesAreEnabledStub = sinon.stub(storage, 'cookiesAreEnabled');
- getCookieStub = sinon.stub(storage, 'getCookie');
+ sandbox = sinon.sandbox.create();
});
afterEach(function () {
- cookiesAreEnabledStub.restore();
- getCookieStub.restore();
+ sandbox.restore();
});
describe('inherited functions', () => {
@@ -257,20 +255,156 @@ describe('teadsBidAdapter', () => {
expect(payload.pageReferrer).to.deep.equal(document.referrer);
});
- it('should add pageTitle info to payload', function () {
+ 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
- expect(payload.pageTitle).to.exist;
- expect(payload.pageTitle).to.deep.equal(window.top.document.title || document.title);
+ if (screenOrientation) {
+ expect(payload.screenOrientation).to.exist;
+ expect(payload.screenOrientation).to.deep.equal(screenOrientation);
+ } else expect(payload.screenOrientation).to.not.exist;
});
- it('should add pageDescription info to payload', function () {
+ it('should add historyLength info to payload', function () {
const request = spec.buildRequests(bidRequests, bidderRequestDefault);
const payload = JSON.parse(request.data);
- expect(payload.pageDescription).to.exist;
- expect(payload.pageDescription).to.deep.equal('');
+ 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';
+ sandbox.stub(window.top.document, 'title').value(testText);
+
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.pageTitle).to.exist;
+ expect(payload.pageTitle).to.deep.equal(testText);
+ });
+
+ it('should add pageTitle info to payload based on open-graph title', function () {
+ const testText = 'This is a title from open-graph';
+ sandbox.stub(window.top.document, 'title').value('');
+ sandbox.stub(window.top.document, 'querySelector').withArgs('meta[property="og:title"]').returns({ content: testText });
+
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.pageTitle).to.exist;
+ expect(payload.pageTitle).to.deep.equal(testText);
+ });
+
+ it('should add pageTitle info to payload sliced on 300 first characters', function () {
+ const testText = Array(500).join('a');
+ sandbox.stub(window.top.document, 'title').value(testText);
+
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.pageTitle).to.exist;
+ expect(payload.pageTitle).to.have.length(300);
+ });
+
+ it('should add pageTitle info to payload when fallbacking from window.top', function () {
+ const testText = 'This is a fallback title';
+ sandbox.stub(window.top.document, 'querySelector').throws();
+ sandbox.stub(document, 'title').value(testText);
+
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.pageTitle).to.exist;
+ expect(payload.pageTitle).to.deep.equal(testText);
+ });
+ });
+
+ describe('pageDescription', function () {
+ it('should add pageDescription info to payload based on open-graph description', function () {
+ const testText = 'This is a description';
+ sandbox.stub(window.top.document, 'querySelector').withArgs('meta[name="description"]').returns({ content: testText });
+
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.pageDescription).to.exist;
+ expect(payload.pageDescription).to.deep.equal(testText);
+ });
+
+ it('should add pageDescription info to payload based on open-graph description', function () {
+ const testText = 'This is a description from open-graph';
+ sandbox.stub(window.top.document, 'querySelector').withArgs('meta[property="og:description"]').returns({ content: testText });
+
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.pageDescription).to.exist;
+ expect(payload.pageDescription).to.deep.equal(testText);
+ });
+
+ it('should add pageDescription info to payload sliced on 300 first characters', function () {
+ const testText = Array(500).join('a');
+ sandbox.stub(window.top.document, 'querySelector').withArgs('meta[name="description"]').returns({ content: testText });
+
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.pageDescription).to.exist;
+ expect(payload.pageDescription).to.have.length(300);
+ });
+
+ it('should add pageDescription info to payload when fallbacking from window.top', function () {
+ const testText = 'This is a fallback description';
+ sandbox.stub(window.top.document, 'querySelector').throws();
+ sandbox.stub(document, 'querySelector').withArgs('meta[name="description"]').returns({ content: testText });
+
+ const request = spec.buildRequests(bidRequests, bidderRequestDefault);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.pageDescription).to.exist;
+ expect(payload.pageDescription).to.deep.equal(testText);
+ });
});
it('should add timeToFirstByte info to payload', function () {
@@ -697,7 +831,7 @@ describe('teadsBidAdapter', () => {
describe('First-party cookie Teads ID', function () {
it('should not add firstPartyCookieTeadsId param to payload if cookies are not enabled' +
' and teads user id not available', function () {
- cookiesAreEnabledStub.returns(false);
+ sandbox.stub(storage, 'cookiesAreEnabled').returns(false);
const bidRequest = {
...baseBidRequest,
@@ -714,8 +848,8 @@ describe('teadsBidAdapter', () => {
it('should not add firstPartyCookieTeadsId param to payload if cookies are enabled ' +
'but first-party cookie and teads user id are not available', function () {
- cookiesAreEnabledStub.returns(true);
- getCookieStub.withArgs('_tfpvi').returns(undefined);
+ sandbox.stub(storage, 'cookiesAreEnabled').returns(true);
+ sandbox.stub(storage, 'getCookie').withArgs('_tfpvi').returns(undefined);
const bidRequest = {
...baseBidRequest,
@@ -732,8 +866,8 @@ describe('teadsBidAdapter', () => {
it('should add firstPartyCookieTeadsId from cookie if it\'s available ' +
'and teads user id is not', function () {
- cookiesAreEnabledStub.returns(true);
- getCookieStub.withArgs('_tfpvi').returns('my-teads-id');
+ sandbox.stub(storage, 'cookiesAreEnabled').returns(true);
+ sandbox.stub(storage, 'getCookie').withArgs('_tfpvi').returns('my-teads-id');
const bidRequest = {
...baseBidRequest,
@@ -751,8 +885,8 @@ describe('teadsBidAdapter', () => {
it('should add firstPartyCookieTeadsId from user id module if it\'s available ' +
'even if cookie is available too', function () {
- cookiesAreEnabledStub.returns(true);
- getCookieStub.withArgs('_tfpvi').returns('my-teads-id');
+ sandbox.stub(storage, 'cookiesAreEnabled').returns(true);
+ sandbox.stub(storage, 'getCookie').withArgs('_tfpvi').returns('my-teads-id');
const bidRequest = {
...baseBidRequest,
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/tpmnBidAdapter_spec.js b/test/spec/modules/tpmnBidAdapter_spec.js
index e2b14b18f61..505bc9d878f 100644
--- a/test/spec/modules/tpmnBidAdapter_spec.js
+++ b/test/spec/modules/tpmnBidAdapter_spec.js
@@ -1,16 +1,130 @@
/* eslint-disable no-tabs */
-import {expect} from 'chai';
-import {spec, storage} from 'modules/tpmnBidAdapter.js';
-import {generateUUID} from '../../../src/utils.js';
-import {newBidder} from '../../../src/adapters/bidderFactory';
+import { spec, storage, VIDEO_RENDERER_URL, ADAPTER_VERSION } from 'modules/tpmnBidAdapter.js';
+import { generateUUID } from '../../../src/utils.js';
+import { expect } from 'chai';
+import * as utils from 'src/utils';
import * as sinon from 'sinon';
+import 'modules/consentManagement.js';
+import {syncAddFPDToBidderRequest} from '../../helpers/fpd.js';
+import {mockGdprConsent} from '../../helpers/consentData.js';
+
+const BIDDER_CODE = 'tpmn';
+const BANNER_BID = {
+ bidder: BIDDER_CODE,
+ params: {
+ inventoryId: 1
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250]
+ ],
+ },
+ },
+ adUnitCode: 'adUnitCode1',
+ bidId: 'bidId',
+ bidderRequestId: 'bidderRequestId',
+ auctionId: 'auctionId-56a2-4f71-9098-720a68f2f708',
+};
+
+const VIDEO_BID = {
+ bidder: BIDDER_CODE,
+ params: {
+ inventoryId: 1
+ },
+ mediaTypes: {
+ video: {
+ context: 'outstream',
+ api: [1, 2, 4, 6],
+ mimes: ['video/mp4'],
+ playbackmethod: [2, 4, 6],
+ playerSize: [[1024, 768]],
+ protocols: [3, 4, 7, 8, 10],
+ placement: 1,
+ plcmt: 1,
+ minduration: 0,
+ maxduration: 60,
+ startdelay: 0
+ },
+ },
+ adUnitCode: 'adUnitCode1',
+ bidId: 'bidId',
+ bidderRequestId: 'bidderRequestId',
+ auctionId: 'auctionId-56a2-4f71-9098-720a68f2f708',
+};
+
+const BIDDER_REQUEST = {
+ auctionId: 'auctionId-56a2-4f71-9098-720a68f2f708',
+ bidderRequestId: 'bidderRequestId',
+ timeout: 500,
+ refererInfo: {
+ page: 'https://hello-world-page.com/',
+ domain: 'hello-world-page.com',
+ ref: 'http://example-domain.com/foo',
+ }
+};
+
+const BANNER_BID_RESPONSE = {
+ 'id': 'bidderRequestId',
+ 'bidId': 'bidid',
+ 'seatbid': [
+ {
+ 'bid': [
+ {
+ 'id': 'id',
+ 'impid': 'bidId',
+ 'price': 0.18,
+ 'adm': '',
+ 'adid': '144762342',
+ 'burl': 'http://0.0.0.0:8181/burl',
+ 'adomain': [
+ 'https://dummydomain.com'
+ ],
+ 'cid': 'cid',
+ 'crid': 'crid',
+ 'iurl': 'iurl',
+ 'cat': [],
+ 'w': 300,
+ 'h': 250
+ }
+ ]
+ }
+ ],
+ 'cur': 'USD'
+};
+
+const VIDEO_BID_RESPONSE = {
+ 'id': 'bidderRequestId',
+ 'bidid': 'bidid',
+ 'seatbid': [
+ {
+ 'bid': [
+ {
+ 'id': 'id',
+ 'impid': 'bidId',
+ 'price': 1.09,
+ 'adid': '144762342',
+ 'burl': 'http://0.0.0.0:8181/burl',
+ 'adm': '',
+ 'adomain': [
+ 'https://dummydomain.com'
+ ],
+ 'cid': 'cid',
+ 'crid': 'crid',
+ 'iurl': 'iurl',
+ 'cat': [],
+ 'h': 768,
+ 'w': 1024
+ }
+ ]
+ }
+ ],
+ 'cur': 'USD'
+};
describe('tpmnAdapterTests', function () {
- const adapter = newBidder(spec);
- const BIDDER_CODE = 'tpmn';
let sandbox = sinon.sandbox.create();
let getCookieStub;
-
beforeEach(function () {
$$PREBID_GLOBAL$$.bidderSettings = {
tpmn: {
@@ -27,152 +141,277 @@ describe('tpmnAdapterTests', function () {
$$PREBID_GLOBAL$$.bidderSettings = {};
});
- describe('inherited functions', function () {
- it('exists and is a function', function () {
- expect(adapter.callBids).to.exist.and.to.be.a('function')
- })
- });
-
- describe('isBidRequestValid', function () {
- let bid = {
- adUnitCode: 'temp-unitcode',
- bidder: 'tpmn',
- params: {
- inventoryId: '1',
- publisherId: 'TPMN'
- },
- bidId: '29092404798c9',
- bidderRequestId: 'a01',
- auctionId: 'da1d7a33-0260-4e83-a621-14674116f3f9',
- mediaTypes: {
- banner: {
- sizes: [[300, 250]]
- }
- }
- };
-
- it('should return true if a bid is valid banner bid request', function () {
- expect(spec.isBidRequestValid(bid)).to.be.equal(true);
- });
-
- it('should return false where requried param is missing', function () {
- let bid = Object.assign({}, bid);
- bid.params = {};
- expect(spec.isBidRequestValid(bid)).to.be.equal(false);
- });
-
- it('should return false when required param values have invalid type', function () {
- let bid = Object.assign({}, bid);
- bid.params = {
- 'inventoryId': null,
- 'publisherId': null
- };
- expect(spec.isBidRequestValid(bid)).to.be.equal(false);
- });
- });
-
- describe('buildRequests', function () {
- it('should return an empty list if there are no bid requests', function () {
- const emptyBidRequests = [];
- const bidderRequest = {};
- const request = spec.buildRequests(emptyBidRequests, bidderRequest);
- expect(request).to.be.an('array').that.is.empty;
- });
- it('should generate a POST server request with bidder API url, data', function () {
- const bid = {
- adUnitCode: 'temp-unitcode',
- bidder: 'tpmn',
+ describe('isBidRequestValid()', function () {
+ it('should accept request if placementId is passed', function () {
+ let bid = {
+ bidder: BIDDER_CODE,
params: {
- inventoryId: '1',
- publisherId: 'TPMN'
+ inventoryId: 123
},
- bidId: '29092404798c9',
- bidderRequestId: 'a01',
- auctionId: 'da1d7a33-0260-4e83-a621-14674116f3f9',
mediaTypes: {
banner: {
sizes: [[300, 250]]
}
}
};
- const tempBidRequests = [bid];
- const tempBidderRequest = {
- refererInfo: {
- page: 'http://localhost/test',
- site: {
- domain: 'localhost',
- page: 'http://localhost/test'
- }
- }
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+
+ it('should reject requests without params', function () {
+ let bid = {
+ bidder: BIDDER_CODE,
+ params: {}
};
- const builtRequest = spec.buildRequests(tempBidRequests, tempBidderRequest);
-
- expect(builtRequest).to.have.lengthOf(1);
- expect(builtRequest[0].method).to.equal('POST');
- expect(builtRequest[0].url).to.match(/ad.tpmn.co.kr\/prebidhb.tpmn/);
- const apiRequest = builtRequest[0].data;
- expect(apiRequest.site).to.deep.equal({
- domain: 'localhost',
- page: 'http://localhost/test'
- });
- expect(apiRequest.bids).to.have.lengthOf('1');
- expect(apiRequest.bids[0].inventoryId).to.equal('1');
- expect(apiRequest.bids[0].publisherId).to.equal('TPMN');
- expect(apiRequest.bids[0].bidId).to.equal('29092404798c9');
- expect(apiRequest.bids[0].adUnitCode).to.equal('temp-unitcode');
- expect(apiRequest.bids[0].auctionId).to.equal('da1d7a33-0260-4e83-a621-14674116f3f9');
- expect(apiRequest.bids[0].sizes).to.have.lengthOf('1');
- expect(apiRequest.bids[0].sizes[0]).to.deep.equal({
- width: 300,
- height: 250
- });
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+
+ it('should return true when required params found', () => {
+ expect(spec.isBidRequestValid(BANNER_BID)).to.equal(true);
+ expect(spec.isBidRequestValid(VIDEO_BID)).to.equal(true);
});
});
- describe('interpretResponse', function () {
- const bid = {
- adUnitCode: 'temp-unitcode',
- bidder: 'tpmn',
- params: {
- inventoryId: '1',
- publisherId: 'TPMN'
- },
- bidId: '29092404798c9',
- bidderRequestId: 'a01',
- auctionId: 'da1d7a33-0260-4e83-a621-14674116f3f9',
- mediaTypes: {
- banner: {
- sizes: [[300, 250]]
+ describe('buildRequests()', function () {
+ it('should have gdpr data if applicable', function () {
+ const bid = utils.deepClone(BANNER_BID);
+
+ const req = syncAddFPDToBidderRequest(Object.assign({}, BIDDER_REQUEST, {
+ gdprConsent: {
+ consentString: 'consentString',
+ gdprApplies: true,
}
+ }));
+ let request = spec.buildRequests([bid], req)[0];
+
+ const payload = request.data;
+ expect(payload.user.ext).to.have.property('consent', req.gdprConsent.consentString);
+ expect(payload.regs.ext).to.have.property('gdpr', 1);
+ });
+
+ it('should properly forward ORTB blocking params', function () {
+ let bid = utils.deepClone(BANNER_BID);
+ bid = utils.mergeDeep(bid, {
+ params: { bcat: ['IAB1-1'], badv: ['example.com'], bapp: ['com.example'], battr: [1] },
+ mediaTypes: { banner: { battr: [1] } }
+ });
+
+ let [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+
+ expect(request).to.exist.and.to.be.an('object');
+ const payload = request.data;
+ expect(payload).to.have.deep.property('bcat', ['IAB1-1']);
+ expect(payload).to.have.deep.property('badv', ['example.com']);
+ expect(payload).to.have.deep.property('bapp', ['com.example']);
+ expect(payload.imp[0].banner).to.have.deep.property('battr', [1]);
+ });
+
+ context('when mediaType is banner', function () {
+ it('should build correct request for banner bid with both w, h', () => {
+ const bid = utils.deepClone(BANNER_BID);
+
+ const [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+ const requestData = request.data;
+ // expect(requestData.imp[0].banner).to.equal(null);
+ expect(requestData.imp[0].banner.format[0].w).to.equal(300);
+ expect(requestData.imp[0].banner.format[0].h).to.equal(250);
+ });
+
+ it('should create request data', function () {
+ const bid = utils.deepClone(BANNER_BID);
+
+ let [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+ expect(request).to.exist.and.to.be.a('object');
+ const payload = request.data;
+ expect(payload.imp[0]).to.have.property('id', bid.bidId);
+ });
+ });
+
+ context('when mediaType is video', function () {
+ if (FEATURES.VIDEO) {
+ it('should return false when there is no video in mediaTypes', () => {
+ const bid = utils.deepClone(VIDEO_BID);
+ delete bid.mediaTypes.video;
+
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
}
- };
- const tempBidRequests = [bid];
- it('should return an empty aray to indicate no valid bids', function () {
- const emptyServerResponse = {};
- const bidResponses = spec.interpretResponse(emptyServerResponse, tempBidRequests);
- expect(bidResponses).is.an('array').that.is.empty;
+ if (FEATURES.VIDEO) {
+ it('should reutrn false if player size is not set', () => {
+ const bid = utils.deepClone(VIDEO_BID);
+ delete bid.mediaTypes.video.playerSize;
+
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ }
+ if (FEATURES.VIDEO) {
+ it('when mediaType is Video - check', () => {
+ const bid = utils.deepClone(VIDEO_BID);
+ const check = {
+ w: 1024,
+ h: 768,
+ mimes: ['video/mp4'],
+ playbackmethod: [2, 4, 6],
+ api: [1, 2, 4, 6],
+ protocols: [3, 4, 7, 8, 10],
+ placement: 1,
+ minduration: 0,
+ maxduration: 60,
+ startdelay: 0,
+ plcmt: 1
+ };
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ const requests = spec.buildRequests([bid], BIDDER_REQUEST);
+ const request = requests[0].data;
+ expect(request.imp[0].video).to.deep.include({...check});
+ });
+ }
+
+ if (FEATURES.VIDEO) {
+ it('when mediaType New Video', () => {
+ const NEW_VIDEO_BID = {
+ 'bidder': 'tpmn',
+ 'params': {'inventoryId': 2, 'bidFloor': 2},
+ 'userId': {'pubcid': '88a49ee6-beeb-4dd6-92ac-3b6060e127e1'},
+ 'mediaTypes': {
+ 'video': {
+ 'context': 'outstream',
+ 'mimes': ['video/mp4'],
+ 'playerSize': [[1024, 768]],
+ 'playbackmethod': [2, 4, 6],
+ 'protocols': [3, 4],
+ 'api': [1, 2, 3, 6],
+ 'placement': 1,
+ 'minduration': 0,
+ 'maxduration': 30,
+ 'startdelay': 0,
+ 'skip': 1,
+ 'plcmt': 4
+ }
+ },
+ };
+
+ const check = {
+ w: 1024,
+ h: 768,
+ mimes: [ 'video/mp4' ],
+ playbackmethod: [2, 4, 6],
+ api: [1, 2, 3, 6],
+ protocols: [3, 4],
+ placement: 1,
+ minduration: 0,
+ maxduration: 30,
+ startdelay: 0,
+ skip: 1,
+ plcmt: 4
+ }
+
+ expect(spec.isBidRequestValid(NEW_VIDEO_BID)).to.equal(true);
+ let requests = spec.buildRequests([NEW_VIDEO_BID], BIDDER_REQUEST);
+ const request = requests[0].data;
+ expect(request.imp[0].video.w).to.equal(check.w);
+ expect(request.imp[0].video.h).to.equal(check.h);
+ expect(request.imp[0].video.placement).to.equal(check.placement);
+ expect(request.imp[0].video.minduration).to.equal(check.minduration);
+ expect(request.imp[0].video.maxduration).to.equal(check.maxduration);
+ expect(request.imp[0].video.startdelay).to.equal(check.startdelay);
+ expect(request.imp[0].video.skip).to.equal(check.skip);
+ expect(request.imp[0].video.plcmt).to.equal(check.plcmt);
+ expect(request.imp[0].video.mimes).to.deep.have.same.members(check.mimes);
+ expect(request.imp[0].video.playbackmethod).to.deep.have.same.members(check.playbackmethod);
+ expect(request.imp[0].video.api).to.deep.have.same.members(check.api);
+ expect(request.imp[0].video.protocols).to.deep.have.same.members(check.protocols);
+ });
+ }
+
+ if (FEATURES.VIDEO) {
+ it('should use bidder video params if they are set', () => {
+ let bid = utils.deepClone(VIDEO_BID);
+ const check = {
+ api: [1, 2],
+ mimes: ['video/mp4', 'video/x-flv'],
+ playbackmethod: [3, 4],
+ protocols: [5, 6],
+ placement: 1,
+ plcmt: 1,
+ minduration: 0,
+ maxduration: 30,
+ startdelay: 0,
+ w: 640,
+ h: 480
+
+ };
+ bid.mediaTypes.video = {...check};
+ bid.mediaTypes.video.context = 'instream';
+ bid.mediaTypes.video.playerSize = [[640, 480]];
+
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ const requests = spec.buildRequests([bid], BIDDER_REQUEST);
+ const request = requests[0].data;
+ expect(request.imp[0].video).to.deep.include({...check});
+ });
+ }
});
- it('should return an empty array to indicate no valid bids', function () {
- const mockBidResult = {
- requestId: '9cf19229-34f6-4d06-bc1d-0e44e8d616c8',
- cpm: 10.0,
- creativeId: '1',
- width: 300,
- height: 250,
- netRevenue: true,
- currency: 'USD',
- ttl: 1800,
- ad: '',
- adType: 'banner'
- };
- const testServerResponse = {
- headers: [],
- body: [mockBidResult]
- };
- const bidResponses = spec.interpretResponse(testServerResponse, tempBidRequests);
- expect(bidResponses).deep.equal([mockBidResult]);
+ });
+
+ describe('interpretResponse()', function () {
+ context('when mediaType is banner', function () {
+ it('should correctly interpret valid banner response', function () {
+ const bid = utils.deepClone(BANNER_BID);
+ const [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+ const response = utils.deepClone(BANNER_BID_RESPONSE);
+
+ const bids = spec.interpretResponse({ body: response }, request);
+ expect(bids).to.be.an('array').that.is.not.empty;
+
+ expect(bids[0].mediaType).to.equal('banner');
+ expect(bids[0].burl).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].burl);
+ expect(bids[0].currency).to.equal('USD');
+ expect(bids[0].requestId).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].impid);
+ expect(bids[0].cpm).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].price);
+ expect(bids[0].width).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].w);
+ expect(bids[0].height).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].h);
+ expect(bids[0].ad).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].adm);
+ expect(bids[0].creativeId).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].crid);
+ expect(bids[0].meta.advertiserDomains[0]).to.equal('https://dummydomain.com');
+ expect(bids[0].ttl).to.equal(500);
+ expect(bids[0].netRevenue).to.equal(true);
+ });
+
+ it('should handle empty bid response', function () {
+ const bid = utils.deepClone(BANNER_BID);
+
+ let request = spec.buildRequests([bid], BIDDER_REQUEST)[0];
+ const EMPTY_RESP = Object.assign({}, BANNER_BID_RESPONSE, { 'body': {} });
+ const bids = spec.interpretResponse(EMPTY_RESP, request);
+ expect(bids).to.be.empty;
+ });
});
+ if (FEATURES.VIDEO) {
+ context('when mediaType is video', function () {
+ it('should correctly interpret valid instream video response', () => {
+ const bid = utils.deepClone(VIDEO_BID);
+
+ const [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+ const bids = spec.interpretResponse({ body: VIDEO_BID_RESPONSE }, request);
+ expect(bids).to.be.an('array').that.is.not.empty;
+
+ expect(bids[0].mediaType).to.equal('video');
+ expect(bids[0].burl).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].burl);
+ expect(bids[0].currency).to.equal('USD');
+ expect(bids[0].requestId).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].impid);
+ expect(bids[0].cpm).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].price);
+ expect(bids[0].width).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].w);
+ expect(bids[0].height).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].h);
+ expect(bids[0].vastXml).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].adm);
+ expect(bids[0].rendererUrl).to.equal(VIDEO_RENDERER_URL);
+ expect(bids[0].creativeId).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].crid);
+ expect(bids[0].meta.advertiserDomains[0]).to.equal('https://dummydomain.com');
+ expect(bids[0].ttl).to.equal(500);
+ expect(bids[0].netRevenue).to.equal(true);
+ });
+ });
+ }
});
describe('getUserSync', function () {
diff --git a/test/spec/modules/ttdBidAdapter_spec.js b/test/spec/modules/ttdBidAdapter_spec.js
index 56c506dea6b..1fe504ba8e8 100644
--- a/test/spec/modules/ttdBidAdapter_spec.js
+++ b/test/spec/modules/ttdBidAdapter_spec.js
@@ -262,6 +262,11 @@ describe('ttdBidAdapter', function () {
expect(request.data).to.be.not.null;
});
+ it('sets bidrequest.id to bidderRequestId', function () {
+ const requestBody = testBuildRequests(baseBannerBidRequests, baseBidderRequest).data;
+ expect(requestBody.id).to.equal('18084284054531');
+ });
+
it('sets impression id to ad unit\'s bid id', function () {
const requestBody = testBuildRequests(baseBannerBidRequests, baseBidderRequest).data;
expect(requestBody.imp[0].id).to.equal('243310435309b5');
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_helpers.js b/test/spec/modules/uid2IdSystem_helpers.js
index 5006a50dedd..e0bef047acb 100644
--- a/test/spec/modules/uid2IdSystem_helpers.js
+++ b/test/spec/modules/uid2IdSystem_helpers.js
@@ -26,12 +26,12 @@ export const runAuction = async () => {
}
export const apiHelpers = {
- makeTokenResponse: (token, shouldRefresh = false, expired = false) => ({
+ makeTokenResponse: (token, shouldRefresh = false, expired = false, refreshExpired = false) => ({
advertising_token: token,
refresh_token: 'fake-refresh-token',
identity_expires: expired ? Date.now() - 1000 : Date.now() + 60 * 60 * 1000,
refresh_from: shouldRefresh ? Date.now() - 1000 : Date.now() + 60 * 1000,
- refresh_expires: Date.now() + 24 * 60 * 60 * 1000, // 24 hours
+ refresh_expires: refreshExpired ? Date.now() - 1000 : Date.now() + 24 * 60 * 60 * 1000, // 24 hours
refresh_response_key: 'wR5t6HKMfJ2r4J7fEGX9Gw==', // Fake data
}),
respondAfterDelay: (delay, srv = server) => new Promise((resolve) => setTimeout(() => {
diff --git a/test/spec/modules/uid2IdSystem_spec.js b/test/spec/modules/uid2IdSystem_spec.js
index f33060869df..901e0c57e32 100644
--- a/test/spec/modules/uid2IdSystem_spec.js
+++ b/test/spec/modules/uid2IdSystem_spec.js
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
-import {coreStorage, init, setSubmoduleRegistry, requestBidsHook} from 'modules/userId/index.js';
+import {coreStorage, init, setSubmoduleRegistry} from 'modules/userId/index.js';
import {config} from 'src/config.js';
import * as utils from 'src/utils.js';
import { uid2IdSubmodule } from 'modules/uid2IdSystem.js';
@@ -11,6 +11,7 @@ import { configureTimerInterceptors } from 'test/mocks/timers.js';
import { cookieHelpers, runAuction, apiHelpers, setGdprApplies } from './uid2IdSystem_helpers.js';
import {hook} from 'src/hook.js';
import {uninstall as uninstallGdprEnforcement} from 'modules/gdprEnforcement.js';
+import {server} from 'test/mocks/xhr';
let expect = require('chai').expect;
@@ -23,16 +24,22 @@ const auctionDelayMs = 10;
const initialToken = `initial-advertising-token`;
const legacyToken = 'legacy-advertising-token';
const refreshedToken = 'refreshed-advertising-token';
+const clientSideGeneratedToken = 'client-side-generated-advertising-token';
const legacyConfigParams = {storage: null};
const serverCookieConfigParams = { uid2ServerCookie: publisherCookieName };
const newServerCookieConfigParams = { uid2Cookie: publisherCookieName };
+const cstgConfigParams = { serverPublicKey: 'UID2-X-L-24B8a/eLYBmRkXA9yPgRZt+ouKbXewG2OPs23+ov3JC8mtYJBCx6AxGwJ4MlwUcguebhdDp2CvzsCgS9ogwwGA==', subscriptionId: 'subscription-id' }
const makeUid2IdentityContainer = (token) => ({uid2: {id: token}});
let useLocalStorage = false;
const makePrebidConfig = (params = null, extraSettings = {}, debug = false) => ({
userSync: { auctionDelay: auctionDelayMs, userIds: [{name: 'uid2', params: {storage: useLocalStorage ? 'localStorage' : 'cookie', ...params}}] }, debug, ...extraSettings
});
+const makeOriginalIdentity = (identity, salt = 1) => ({
+ identity: utils.cyrb53Hash(identity, salt),
+ salt
+})
const getFromAppropriateStorage = () => {
if (useLocalStorage) return coreStorage.getDataFromLocalStorage(moduleCookieName);
@@ -46,15 +53,18 @@ const expectGlobalToHaveToken = (token) => expect(getGlobal().getUserIds()).to.d
const expectGlobalToHaveNoUid2 = () => expect(getGlobal().getUserIds()).to.not.haveOwnProperty('uid2');
const expectNoLegacyToken = (bid) => expect(bid.userId).to.not.deep.include(makeUid2IdentityContainer(legacyToken));
const expectModuleStorageEmptyOrMissing = () => expect(getFromAppropriateStorage()).to.be.null;
-const expectModuleStorageToContain = (initialIdentity, latestIdentity) => {
+const expectModuleStorageToContain = (originalAdvertisingToken, latestAdvertisingToken, originalIdentity) => {
const cookie = JSON.parse(getFromAppropriateStorage());
- if (initialIdentity) expect(cookie.originalToken.advertising_token).to.equal(initialIdentity);
- if (latestIdentity) expect(cookie.latestToken.advertising_token).to.equal(latestIdentity);
+ if (originalAdvertisingToken) expect(cookie.originalToken.advertising_token).to.equal(originalAdvertisingToken);
+ if (latestAdvertisingToken) expect(cookie.latestToken.advertising_token).to.equal(latestAdvertisingToken);
+ if (originalIdentity) expect(cookie.originalIdentity).to.eql(makeOriginalIdentity(Object.values(originalIdentity)[0], cookie.originalIdentity.salt));
}
-const apiUrl = 'https://prod.uidapi.com/v2/token/refresh';
+const apiUrl = 'https://prod.uidapi.com/v2/token'
+const refreshApiUrl = `${apiUrl}/refresh`;
const headers = { 'Content-Type': 'application/json' };
-const makeSuccessResponseBody = () => btoa(JSON.stringify({ status: 'success', body: { ...apiHelpers.makeTokenResponse(initialToken), advertising_token: refreshedToken } }));
+const makeSuccessResponseBody = (responseToken) => btoa(JSON.stringify({ status: 'success', body: { ...apiHelpers.makeTokenResponse(initialToken), advertising_token: responseToken } }));
+const cstgApiUrl = `${apiUrl}/client-generate`;
const testCookieAndLocalStorage = (description, test, only = false) => {
const describeFn = only ? describe.only : describe;
@@ -76,7 +86,7 @@ const testCookieAndLocalStorage = (description, test, only = false) => {
};
describe(`UID2 module`, function () {
- let server, suiteSandbox, testSandbox, timerSpy, fullTestTitle, restoreSubtleToUndefined = false;
+ let suiteSandbox, testSandbox, timerSpy, fullTestTitle, restoreSubtleToUndefined = false;
before(function () {
timerSpy = configureTimerInterceptors(debugOutput);
hook.ready();
@@ -87,10 +97,18 @@ describe(`UID2 module`, function () {
// I've confirmed it's available in Firefox since v34 (it seems to be unavailable on BrowserStack in Firefox v106).
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 () {
@@ -99,18 +117,18 @@ describe(`UID2 module`, function () {
if (restoreSubtleToUndefined) window.crypto.subtle = undefined;
});
- const configureUid2Response = (httpStatus, response) => server.respondWith('POST', apiUrl, (xhr) => xhr.respond(httpStatus, headers, response));
- const configureUid2ApiSuccessResponse = () => configureUid2Response(200, makeSuccessResponseBody());
- const configureUid2ApiFailResponse = () => configureUid2Response(500, 'Error');
+ const configureUid2Response = (apiUrl, httpStatus, response) => server.respondWith('POST', apiUrl, (xhr) => xhr.respond(httpStatus, headers, response));
+ const configureUid2ApiSuccessResponse = (apiUrl, responseToken) => configureUid2Response(apiUrl, 200, makeSuccessResponseBody(responseToken));
+ const configureUid2ApiFailResponse = (apiUrl) => configureUid2Response(apiUrl, 500, 'Error');
// Runs the provided test twice - once with a successful API mock, once with one which returns a server error
- const testApiSuccessAndFailure = (act, testDescription, failTestDescription, only = false) => {
+ const testApiSuccessAndFailure = (act, apiUrl, testDescription, failTestDescription, only = false, responseToken = refreshedToken) => {
const testFn = only ? it.only : it;
testFn(`API responds successfully: ${testDescription}`, async function() {
- configureUid2ApiSuccessResponse();
+ configureUid2ApiSuccessResponse(apiUrl, responseToken);
await act(true);
});
testFn(`API responds with an error: ${failTestDescription ?? testDescription}`, async function() {
- configureUid2ApiFailResponse();
+ configureUid2ApiFailResponse(apiUrl);
await act(false);
});
}
@@ -123,8 +141,6 @@ describe(`UID2 module`, function () {
debugOutput(fullTestTitle);
testSandbox = sinon.sandbox.create();
testSandbox.stub(utils, 'logWarn');
- server = sinon.createFakeServer();
-
init(config);
setSubmoduleRegistry([uid2IdSubmodule]);
});
@@ -151,13 +167,13 @@ describe(`UID2 module`, function () {
it('When no baseUrl is provided in config, the module calls the production endpoint', function() {
const uid2Token = apiHelpers.makeTokenResponse(initialToken, true, true);
config.setConfig(makePrebidConfig({uid2Token}));
- expect(server.requests[0]?.url).to.have.string('https://prod.uidapi.com/');
+ expect(server.requests[0]?.url).to.have.string('https://prod.uidapi.com/v2/token/refresh');
});
it('When a baseUrl is provided in config, the module calls the provided endpoint', function() {
const uid2Token = apiHelpers.makeTokenResponse(initialToken, true, true);
config.setConfig(makePrebidConfig({uid2Token, uid2ApiBase: 'https://operator-integ.uidapi.com'}));
- expect(server.requests[0]?.url).to.have.string('https://operator-integ.uidapi.com/');
+ expect(server.requests[0]?.url).to.have.string('https://operator-integ.uidapi.com/v2/token/refresh');
});
});
@@ -238,7 +254,7 @@ describe(`UID2 module`, function () {
cookieHelpers.setPublisherCookie(publisherCookieName, token);
config.setConfig(makePrebidConfig(serverCookieConfigParams, extraConfig));
},
- }
+ },
]
scenarios.forEach(function(scenario) {
@@ -252,7 +268,7 @@ describe(`UID2 module`, function () {
if (apiSucceeds) expectToken(bid, refreshedToken);
else expectNoIdentity(bid);
- }, 'it should be used in the auction', 'the auction should have no uid2');
+ }, refreshApiUrl, 'it should be used in the auction', 'the auction should have no uid2');
testApiSuccessAndFailure(async function(apiSucceeds) {
scenario.setConfig(apiHelpers.makeTokenResponse(initialToken, true, true));
@@ -264,14 +280,14 @@ describe(`UID2 module`, function () {
} else {
expectModuleStorageEmptyOrMissing();
}
- }, 'the refreshed token should be stored in the module storage', 'the module storage should not be set');
+ }, refreshApiUrl, 'the refreshed token should be stored in the module storage', 'the module storage should not be set');
});
describe(`when the response doesn't arrive before the auction timer`, function() {
testApiSuccessAndFailure(async function() {
scenario.setConfig(apiHelpers.makeTokenResponse(initialToken, true, true));
const bid = await runAuction();
expectNoIdentity(bid);
- }, 'it should run the auction');
+ }, refreshApiUrl, 'it should run the auction');
testApiSuccessAndFailure(async function(apiSucceeds) {
scenario.setConfig(apiHelpers.makeTokenResponse(initialToken, true, true));
@@ -283,7 +299,7 @@ describe(`UID2 module`, function () {
await promise;
if (apiSucceeds) expectGlobalToHaveToken(refreshedToken);
else expectGlobalToHaveNoUid2();
- }, 'it should update the userId after the auction', 'there should be no global identity');
+ }, refreshApiUrl, 'it should update the userId after the auction', 'there should be no global identity');
})
describe('and there is a refreshed token in the module cookie', function() {
it('the refreshed value from the cookie is used', async function() {
@@ -322,7 +338,7 @@ describe(`UID2 module`, function () {
apiHelpers.respondAfterDelay(10, server);
const bid = await runAuction();
expectToken(bid, initialToken);
- }, 'it should not be refreshed before the auction runs');
+ }, refreshApiUrl, 'it should not be refreshed before the auction runs');
testApiSuccessAndFailure(async function(success) {
const promise = apiHelpers.respondAfterDelay(1, server);
@@ -333,7 +349,7 @@ describe(`UID2 module`, function () {
} else {
expectModuleStorageToContain(initialToken, initialToken);
}
- }, 'the refreshed token should be stored in the module cookie after the auction runs', 'the module cookie should only have the original token');
+ }, refreshApiUrl, 'the refreshed token should be stored in the module cookie after the auction runs', 'the module cookie should only have the original token');
it('it should use the current token in the auction', async function() {
const bid = await runAuction();
@@ -342,4 +358,273 @@ describe(`UID2 module`, function () {
});
});
});
+
+ if (FEATURES.UID2_CSTG) {
+ describe('When CSTG is enabled provided', function () {
+ const scenarios = [
+ {
+ name: 'email provided in config',
+ identity: { email: 'test@example.com' },
+ setConfig: function (extraConfig) { config.setConfig(makePrebidConfig({ ...cstgConfigParams, ...this.identity }, extraConfig)) },
+ setInvalidConfig: (extraConfig) => config.setConfig(makePrebidConfig({ ...cstgConfigParams, email: 'test . test@gmail.com' }, extraConfig))
+ },
+ {
+ name: 'phone provided in config',
+ identity: { phone: '+12345678910' },
+ setConfig: function (extraConfig) { config.setConfig(makePrebidConfig({ ...cstgConfigParams, ...this.identity }, extraConfig)) },
+ setInvalidConfig: (extraConfig) => config.setConfig(makePrebidConfig({ ...cstgConfigParams, phone: 'test123' }, extraConfig))
+ },
+ {
+ name: 'email hash provided in config',
+ identity: { email_hash: 'lz3+Rj7IV4X1+Vr1ujkG7tstkxwk5pgkqJ6mXbpOgTs=' },
+ setConfig: function (extraConfig) { config.setConfig(makePrebidConfig({ ...cstgConfigParams, emailHash: this.identity.email_hash }, extraConfig)) },
+ setInvalidConfig: (extraConfig) => config.setConfig(makePrebidConfig({ ...cstgConfigParams, emailHash: 'test@example.com' }, extraConfig))
+ },
+ {
+ name: 'phone hash provided in config',
+ identity: { phone_hash: 'kVJ+4ilhrqm3HZDDnCQy4niZknvCoM4MkoVzZrQSdJw=' },
+ setConfig: function (extraConfig) { config.setConfig(makePrebidConfig({ ...cstgConfigParams, phoneHash: this.identity.phone_hash }, extraConfig)) },
+ setInvalidConfig: (extraConfig) => config.setConfig(makePrebidConfig({ ...cstgConfigParams, phoneHash: '614332222111' }, extraConfig))
+ },
+ ]
+ scenarios.forEach(function(scenario) {
+ describe(`And ${scenario.name}`, function() {
+ describe(`When invalid identity is provided`, function() {
+ it('the auction should have no uid2', async function () {
+ scenario.setInvalidConfig()
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ expectGlobalToHaveNoUid2();
+ expectModuleStorageEmptyOrMissing();
+ })
+ });
+
+ describe('When valid identity is provided, and the auction is set to run immediately', function() {
+ it('it should ignores token provided in config, and the auction should have no uid2', async function() {
+ scenario.setConfig({ uid2Token: apiHelpers.makeTokenResponse(initialToken), auctionDelay: 0, syncDelay: 1 });
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ expectGlobalToHaveNoUid2();
+ expectModuleStorageEmptyOrMissing();
+ })
+
+ it('it should ignores token provided in server-set cookie', async function() {
+ cookieHelpers.setPublisherCookie(publisherCookieName, initialToken);
+ scenario.setConfig({ ...newServerCookieConfigParams, auctionDelay: 0, syncDelay: 1 })
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ expectGlobalToHaveNoUid2();
+ expectModuleStorageEmptyOrMissing();
+ })
+
+ describe('When the token generated in time', function() {
+ testApiSuccessAndFailure(async function(apiSucceeds) {
+ scenario.setConfig();
+ apiHelpers.respondAfterDelay(auctionDelayMs / 10, server);
+ const bid = await runAuction();
+
+ if (apiSucceeds) expectToken(bid, clientSideGeneratedToken);
+ else expectNoIdentity(bid);
+ }, cstgApiUrl, 'it should be used in the auction', 'the auction should have no uid2', false, clientSideGeneratedToken);
+
+ testApiSuccessAndFailure(async function(apiSucceeds) {
+ scenario.setConfig();
+ apiHelpers.respondAfterDelay(auctionDelayMs / 10, server);
+
+ await runAuction();
+ if (apiSucceeds) {
+ expectModuleStorageToContain(undefined, clientSideGeneratedToken, scenario.identity);
+ } else {
+ expectModuleStorageEmptyOrMissing();
+ }
+ }, cstgApiUrl, 'the generated token should be stored in the module storage', 'the module storage should not be set', false, clientSideGeneratedToken);
+ });
+ });
+ });
+ });
+ describe(`when the response doesn't arrive before the auction timer`, function() {
+ testApiSuccessAndFailure(async function() {
+ config.setConfig(makePrebidConfig({ ...cstgConfigParams, email: 'test@test.com' }));
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ }, cstgApiUrl, 'it should run the auction', undefined, false, clientSideGeneratedToken);
+
+ testApiSuccessAndFailure(async function(apiSucceeds) {
+ config.setConfig(makePrebidConfig({ ...cstgConfigParams, email: 'test@test.com' }));
+ const promise = apiHelpers.respondAfterDelay(auctionDelayMs * 2, server);
+
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ expectGlobalToHaveNoUid2();
+ await promise;
+ if (apiSucceeds) expectGlobalToHaveToken(clientSideGeneratedToken);
+ else expectGlobalToHaveNoUid2();
+ }, cstgApiUrl, 'it should update the userId after the auction', 'there should be no global identity', false, clientSideGeneratedToken);
+ })
+
+ describe('when there is a token in the module cookie', function() {
+ describe('when originalIdentity matches', function() {
+ describe('When the storedToken is valid', function() {
+ it('it should use the stored token in the auction', async function() {
+ const refreshedIdentity = apiHelpers.makeTokenResponse(refreshedToken);
+ 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', auctionDelay: 0, syncDelay: 1 }));
+ const bid = await runAuction();
+ expectToken(bid, refreshedToken);
+ });
+ })
+
+ describe('When the storedToken is expired and can be refreshed ', 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);
+
+ 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');
+ })
+
+ describe('When the storedToken is expired for refresh', 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);
+
+ 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);
+ })
+ })
+
+ it('when originalIdentity not match, the auction should has no uid2', async function() {
+ const refreshedIdentity = apiHelpers.makeTokenResponse(refreshedToken);
+ const moduleCookie = {originalIdentity: makeOriginalIdentity('123@test.com'), latestToken: refreshedIdentity};
+ coreStorage.setCookie(moduleCookieName, JSON.stringify(moduleCookie), cookieHelpers.getFutureCookieExpiry());
+ config.setConfig(makePrebidConfig({ ...cstgConfigParams, email: 'test@test.com' }));
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ });
+ })
+ });
+ describe('When invalid CSTG configuration is provided', function () {
+ const invalidConfigs = [
+ {
+ name: 'CSTG option is not a object',
+ cstgOptions: ''
+ },
+ {
+ name: 'CSTG option is null',
+ cstgOptions: ''
+ },
+ {
+ name: 'serverPublicKey is not a string',
+ cstgOptions: { subscriptionId: cstgConfigParams.subscriptionId, serverPublicKey: {} }
+ },
+ {
+ name: 'serverPublicKey not match regular expression',
+ cstgOptions: { subscriptionId: cstgConfigParams.subscriptionId, serverPublicKey: 'serverPublicKey' }
+ },
+ {
+ name: 'subscriptionId is not a string',
+ cstgOptions: { subscriptionId: {}, serverPublicKey: cstgConfigParams.serverPublicKey }
+ },
+ {
+ name: 'subscriptionId is empty',
+ cstgOptions: { subscriptionId: '', serverPublicKey: cstgConfigParams.serverPublicKey }
+ },
+ ]
+ invalidConfigs.forEach(function(scenario) {
+ describe(`When ${scenario.name}`, function() {
+ it('should not generate token using identity', async () => {
+ config.setConfig(makePrebidConfig({ ...scenario.cstgOptions, email: 'test@email.com' }));
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ expectGlobalToHaveNoUid2();
+ expectModuleStorageEmptyOrMissing();
+ });
+ });
+ });
+ });
+ describe('When email is provided in different format', function () {
+ const testCases = [
+ { originalEmail: 'TEst.TEST@Test.com ', normalizedEmail: 'test.test@test.com' },
+ { originalEmail: 'test+test@test.com', normalizedEmail: 'test+test@test.com' },
+ { originalEmail: ' testtest@test.com ', normalizedEmail: 'testtest@test.com' },
+ { originalEmail: 'TEst.TEst+123@GMail.Com', normalizedEmail: 'testtest@gmail.com' }
+ ];
+ testCases.forEach((testCase) => {
+ describe('it should normalize the email and generate token on normalized email', async () => {
+ testApiSuccessAndFailure(async function(apiSucceeds) {
+ config.setConfig(makePrebidConfig({ ...cstgConfigParams, email: testCase.originalEmail }));
+ apiHelpers.respondAfterDelay(auctionDelayMs / 10, server);
+
+ await runAuction();
+ if (apiSucceeds) {
+ expectModuleStorageToContain(undefined, clientSideGeneratedToken, { email: testCase.normalizedEmail });
+ } else {
+ expectModuleStorageEmptyOrMissing();
+ }
+ }, cstgApiUrl, 'the generated token should be stored in the module storage', 'the module storage should not be set', false, clientSideGeneratedToken);
+ });
+ });
+ });
+ }
+
+ describe('When neither token nor CSTG config provided', function () {
+ describe('when there is a non-cstg-derived token in the module cookie', function () {
+ it('the auction use stored token if it is valid', async function () {
+ const originalIdentity = apiHelpers.makeTokenResponse(initialToken);
+ const moduleCookie = {originalToken: originalIdentity, latestToken: originalIdentity};
+ coreStorage.setCookie(moduleCookieName, JSON.stringify(moduleCookie), cookieHelpers.getFutureCookieExpiry());
+ config.setConfig(makePrebidConfig({}));
+ const bid = await runAuction();
+ expectToken(bid, initialToken);
+ })
+
+ it('the auction should has no uid2 if stored token is invalid', async function () {
+ const originalIdentity = apiHelpers.makeTokenResponse(initialToken, true, true, true);
+ const moduleCookie = {originalToken: originalIdentity, latestToken: originalIdentity};
+ coreStorage.setCookie(moduleCookieName, JSON.stringify(moduleCookie), cookieHelpers.getFutureCookieExpiry());
+ config.setConfig(makePrebidConfig({}));
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ })
+ })
+
+ describe('when there is a cstg-derived token in the module cookie', function () {
+ it('the auction use stored token if it is valid', async function () {
+ const originalIdentity = apiHelpers.makeTokenResponse(initialToken);
+ const moduleCookie = {originalIdentity: makeOriginalIdentity('123@test.com'), originalToken: originalIdentity, latestToken: originalIdentity};
+ coreStorage.setCookie(moduleCookieName, JSON.stringify(moduleCookie), cookieHelpers.getFutureCookieExpiry());
+ config.setConfig(makePrebidConfig({}));
+ const bid = await runAuction();
+ expectToken(bid, initialToken);
+ })
+
+ it('the auction should has no uid2 if stored token is invalid', async function () {
+ const originalIdentity = apiHelpers.makeTokenResponse(initialToken, true, true, true);
+ const moduleCookie = {originalIdentity: makeOriginalIdentity('123@test.com'), originalToken: originalIdentity, latestToken: originalIdentity};
+ coreStorage.setCookie(moduleCookieName, JSON.stringify(moduleCookie), cookieHelpers.getFutureCookieExpiry());
+ config.setConfig(makePrebidConfig({}));
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ })
+ })
+
+ it('the auction should has no uid2', async function () {
+ config.setConfig(makePrebidConfig({}));
+ const bid = await runAuction();
+ expectNoIdentity(bid);
+ })
+ })
});
diff --git a/test/spec/modules/underdogmediaBidAdapter_spec.js b/test/spec/modules/underdogmediaBidAdapter_spec.js
index 2d7c1f11178..c0e2e8dddce 100644
--- a/test/spec/modules/underdogmediaBidAdapter_spec.js
+++ b/test/spec/modules/underdogmediaBidAdapter_spec.js
@@ -5,6 +5,7 @@ import {
spec,
resetUserSync
} from 'modules/underdogmediaBidAdapter.js';
+import { config } from '../../../src/config';
describe('UnderdogMedia adapter', function () {
let bidRequests;
@@ -763,6 +764,20 @@ describe('UnderdogMedia adapter', function () {
expect(request.data.ref).to.equal(undefined);
});
+ it('should have pbTimeout to be 3001 if bidder timeout does not exists', function () {
+ config.setConfig({ bidderTimeout: '' })
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+
+ expect(request.data.pbTimeout).to.equal(3001)
+ })
+
+ it('should have pbTimeout to be a numerical value if bidder timeout is in a string', function () {
+ config.setConfig({ bidderTimeout: '1000' })
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+
+ expect(request.data.pbTimeout).to.equal(1000)
+ })
+
it('should have pubcid if it exists', function () {
let bidRequests = [{
adUnitCode: 'div-gpt-ad-1460505748561-0',
diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js
index 7f9c2e7b3d5..5cf53c661a9 100644
--- a/test/spec/modules/undertoneBidAdapter_spec.js
+++ b/test/spec/modules/undertoneBidAdapter_spec.js
@@ -39,12 +39,19 @@ const videoBidReq = [{
maxDuration: 30
}
},
- mediaTypes: {video: {
- context: 'outstream',
- playerSize: [640, 480],
- placement: 1,
- plcmt: 1
- }},
+ ortb2Imp: {
+ ext: {
+ gpid: '/1111/gpid#728x90',
+ }
+ },
+ mediaTypes: {
+ video: {
+ context: 'outstream',
+ playerSize: [640, 480],
+ placement: 1,
+ plcmt: 1
+ }
+ },
sizes: [[300, 250], [300, 600]],
bidId: '263be71e91dd9d',
auctionId: '9ad1fa8d-2297-4660-a018-b39945054746'
@@ -56,10 +63,19 @@ const videoBidReq = [{
placementId: '10433395',
publisherId: 12345
},
- mediaTypes: {video: {
- context: 'outstream',
- playerSize: [640, 480]
- }},
+ ortb2Imp: {
+ ext: {
+ data: {
+ pbadslot: '/1111/pbadslot#728x90'
+ }
+ }
+ },
+ mediaTypes: {
+ video: {
+ context: 'outstream',
+ playerSize: [640, 480]
+ }
+ },
sizes: [[300, 250], [300, 600]],
bidId: '263be71e91dd9d',
auctionId: '9ad1fa8d-2297-4660-a018-b39945054746'
@@ -463,12 +479,14 @@ describe('Undertone Adapter', () => {
expect(bidVideo.video.skippable).to.equal(true);
expect(bidVideo.video.placement).to.equal(1);
expect(bidVideo.video.plcmt).to.equal(1);
+ expect(bidVideo.gpid).to.equal('/1111/gpid#728x90');
expect(bidVideo2.video.skippable).to.equal(null);
expect(bidVideo2.video.maxDuration).to.equal(null);
expect(bidVideo2.video.playbackMethod).to.equal(null);
expect(bidVideo2.video.placement).to.equal(null);
expect(bidVideo2.video.plcmt).to.equal(null);
+ expect(bidVideo2.gpid).to.equal('/1111/pbadslot#728x90');
});
it('should send all userIds data to server', function () {
const request = spec.buildRequests(bidReqUserIds, bidderReq);
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 6a2d259fdd7..18f49f4943e 100644
--- a/test/spec/modules/userId_spec.js
+++ b/test/spec/modules/userId_spec.js
@@ -382,6 +382,93 @@ describe('User ID', function () {
});
});
+ describe('createEidsArray', () => {
+ beforeEach(() => {
+ init(config);
+ setSubmoduleRegistry([
+ createMockIdSubmodule('mockId1', null, null,
+ {'mockId1': {source: 'mock1source', atype: 1}}),
+ createMockIdSubmodule('mockId2v1', null, null,
+ {'mockId2v1': {source: 'mock2source', atype: 2, getEidExt: () => ({v: 1})}}),
+ createMockIdSubmodule('mockId2v2', null, null,
+ {'mockId2v2': {source: 'mock2source', atype: 2, getEidExt: () => ({v: 2})}}),
+ ]);
+ });
+
+ it('should group UIDs by source and ext', () => {
+ const eids = createEidsArray({
+ mockId1: ['mock-1-1', 'mock-1-2'],
+ mockId2v1: ['mock-2-1', 'mock-2-2'],
+ mockId2v2: ['mock-2-1', 'mock-2-2']
+ });
+ expect(eids).to.eql([
+ {
+ source: 'mock1source',
+ uids: [
+ {
+ id: 'mock-1-1',
+ atype: 1,
+ },
+ {
+ id: 'mock-1-2',
+ atype: 1,
+ }
+ ]
+ },
+ {
+ source: 'mock2source',
+ ext: {
+ v: 1
+ },
+ uids: [
+ {
+ id: 'mock-2-1',
+ atype: 2,
+ },
+ {
+ id: 'mock-2-2',
+ atype: 2,
+ }
+ ]
+ },
+ {
+ source: 'mock2source',
+ ext: {
+ v: 2
+ },
+ uids: [
+ {
+ id: 'mock-2-1',
+ atype: 2,
+ },
+ {
+ id: 'mock-2-2',
+ atype: 2,
+ }
+ ]
+ }
+ ])
+ });
+
+ 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) {
init(config);
setSubmoduleRegistry([sharedIdSystemSubmodule]);
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/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/vrtcalBidAdapter_spec.js b/test/spec/modules/vrtcalBidAdapter_spec.js
index cc4dc0a3882..938934170e9 100644
--- a/test/spec/modules/vrtcalBidAdapter_spec.js
+++ b/test/spec/modules/vrtcalBidAdapter_spec.js
@@ -134,4 +134,39 @@ describe('vrtcalBidAdapter', function () {
).to.be.true
})
})
+
+ describe('getUserSyncs', function() {
+ const syncurl_iframe = 'https://usync.vrtcal.com/i?ssp=1804&synctype=iframe';
+ const syncurl_redirect = 'https://usync.vrtcal.com/i?ssp=1804&synctype=redirect';
+
+ it('base iframe sync pper config', function() {
+ expect(spec.getUserSyncs({ iframeEnabled: true }, {}, undefined, undefined)).to.deep.equal([{
+ type: 'iframe', url: syncurl_iframe + '&us_privacy=&gdpr=0&gdpr_consent=&gpp=&gpp_sid=&surl='
+ }]);
+ });
+
+ it('base redirect sync per config', function() {
+ expect(spec.getUserSyncs({ iframeEnabled: false }, {}, undefined, undefined)).to.deep.equal([{
+ type: 'image', url: syncurl_redirect + '&us_privacy=&gdpr=0&gdpr_consent=&gpp=&gpp_sid=&surl='
+ }]);
+ });
+
+ it('pass with ccpa data', function() {
+ expect(spec.getUserSyncs({ iframeEnabled: true }, {}, undefined, 'ccpa_consent_string', undefined)).to.deep.equal([{
+ type: 'iframe', url: syncurl_iframe + '&us_privacy=ccpa_consent_string&gdpr=0&gdpr_consent=&gpp=&gpp_sid=&surl='
+ }]);
+ });
+
+ it('pass with gdpr data', function() {
+ expect(spec.getUserSyncs({ iframeEnabled: true }, {}, {gdprApplies: 1, consentString: 'gdpr_consent_string'}, undefined, undefined)).to.deep.equal([{
+ type: 'iframe', url: syncurl_iframe + '&us_privacy=&gdpr=1&gdpr_consent=gdpr_consent_string&gpp=&gpp_sid=&surl='
+ }]);
+ });
+
+ it('pass with gpp data', function() {
+ expect(spec.getUserSyncs({ iframeEnabled: true }, {}, undefined, undefined, {gppString: 'gpp_consent_string', applicableSections: [1, 5]})).to.deep.equal([{
+ type: 'iframe', url: syncurl_iframe + '&us_privacy=&gdpr=0&gdpr_consent=&gpp=gpp_consent_string&gpp_sid=1,5&surl='
+ }]);
+ });
+ })
})
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/yieldloveBidAdapter_spec.js b/test/spec/modules/yieldloveBidAdapter_spec.js
new file mode 100644
index 00000000000..b142eef0ffa
--- /dev/null
+++ b/test/spec/modules/yieldloveBidAdapter_spec.js
@@ -0,0 +1,128 @@
+import { expect } from 'chai';
+import { spec } from 'modules/yieldloveBidAdapter.js';
+
+const ENDPOINT_URL = 'https://s2s.yieldlove-ad-serving.net/openrtb2/auction';
+
+// test params
+const pid = 34437;
+const rid = 'website.com';
+
+describe('Yieldlove Bid Adaper', function () {
+ const bidRequests = [
+ {
+ 'bidder': 'yieldlove',
+ 'adUnitCode': 'adunit-code',
+ 'sizes': [ [300, 250] ],
+ 'params': {
+ pid,
+ rid
+ }
+ }
+ ];
+
+ const serverResponse = {
+ body: {
+ seatbid: [
+ {
+ bid: [
+ {
+ impid: 'aaaa',
+ price: 0.5,
+ w: 300,
+ h: 250,
+ adm: 'test
',
+ crid: '1234',
+ }
+ ]
+ }
+ ],
+ ext: {}
+ }
+ }
+
+ describe('isBidRequestValid', () => {
+ const bid = bidRequests[0];
+
+ it('should return true when required params found', function () {
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+
+ it('should return false when required params are not present', function () {
+ const invalidBid = { ...bid, params: {} };
+ expect(spec.isBidRequestValid(invalidBid)).to.equal(false);
+ });
+
+ it('should return false when required param "pid" is not present', function () {
+ const invalidBid = { ...bid, params: { ...bid.params, pid: undefined } };
+ expect(spec.isBidRequestValid(invalidBid)).to.equal(false);
+ });
+
+ it('should return false when required param "rid" is not present', function () {
+ const invalidBid = { ...bid, params: { ...bid.params, rid: undefined } };
+ expect(spec.isBidRequestValid(invalidBid)).to.equal(false);
+ });
+ });
+
+ describe('buildRequests', () => {
+ it('should build the request', function () {
+ const request = spec.buildRequests(bidRequests, {});
+ const payload = request.data;
+ const url = request.url;
+
+ expect(url).to.equal(ENDPOINT_URL);
+
+ expect(payload.site).to.exist;
+ expect(payload.site.publisher).to.exist;
+ expect(payload.site.publisher.id).to.exist;
+ expect(payload.site.publisher.id).to.equal(rid);
+ expect(payload.site.domain).to.exist;
+ expect(payload.site.domain).to.equal(rid);
+
+ expect(payload.imp).to.exist;
+ expect(payload.imp[0]).to.exist;
+ expect(payload.imp[0].ext).to.exist;
+ expect(payload.imp[0].ext.prebid).to.exist;
+ expect(payload.imp[0].ext.prebid.storedrequest).to.exist;
+ expect(payload.imp[0].ext.prebid.storedrequest.id).to.exist;
+ expect(payload.imp[0].ext.prebid.storedrequest.id).to.equal(pid.toString());
+ });
+ });
+
+ describe('interpretResponse', () => {
+ it('should interpret the response by pushing it in the bids elem', function () {
+ const allResponses = spec.interpretResponse(serverResponse);
+ const response = allResponses[0];
+ const seatbid = serverResponse.body.seatbid[0].bid[0];
+
+ expect(response.requestId).to.exist;
+ expect(response.requestId).to.equal(seatbid.impid);
+ expect(response.cpm).to.exist;
+ expect(response.cpm).to.equal(seatbid.price);
+ expect(response.width).to.exist;
+ expect(response.width).to.equal(seatbid.w);
+ expect(response.height).to.exist;
+ expect(response.height).to.equal(seatbid.h);
+ expect(response.ad).to.exist;
+ expect(response.ad).to.equal(seatbid.adm);
+ expect(response.ttl).to.exist;
+ expect(response.creativeId).to.exist;
+ expect(response.creativeId).to.equal(seatbid.crid);
+ expect(response.netRevenue).to.exist;
+ expect(response.currency).to.exist;
+ });
+ });
+
+ describe('getUserSyncs', function() {
+ it('should retrieve user iframe syncs', function () {
+ expect(spec.getUserSyncs({ iframeEnabled: true }, [serverResponse], undefined, undefined)).to.deep.equal([{
+ type: 'iframe',
+ url: 'https://cdn-a.yieldlove.com/load-cookie.html?endpoint=yieldlove&max_sync_count=100&gdpr=NaN&gdpr_consent=&'
+ }]);
+
+ expect(spec.getUserSyncs({ iframeEnabled: true }, [serverResponse], { gdprApplies: true, consentString: 'example' }, undefined)).to.deep.equal([{
+ type: 'iframe',
+ url: 'https://cdn-a.yieldlove.com/load-cookie.html?endpoint=yieldlove&max_sync_count=100&gdpr=1&gdpr_consent=example&'
+ }]);
+ });
+ });
+})
diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js
index 25fe176553d..edb3ef3af27 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()]) => ({
@@ -74,7 +74,6 @@ describe('YieldmoAdapter', function () {
bidderRequestId: '14c4ede8c693f',
bids,
auctionStart: 1520001292880,
- timeout: 3000,
start: 1520001292884,
doneCbCallCount: 0,
refererInfo: {
@@ -169,6 +168,14 @@ describe('YieldmoAdapter', function () {
expect(requests[0].url).to.be.equal(BANNER_ENDPOINT);
});
+ it('should pass default timeout in bid request', function () {
+ const requests = build([mockBannerBid()]);
+ expect(requests[0].data.tmax).to.equal(400);
+ });
+ it('should pass tmax to bid request', function () {
+ const requests = build([mockBannerBid()], mockBidderRequest({timeout: 1000}));
+ expect(requests[0].data.tmax).to.equal(1000);
+ });
it('should not blow up if crumbs is undefined', function () {
expect(function () {
build([mockBannerBid({crumbs: undefined})]);
@@ -425,6 +432,18 @@ describe('YieldmoAdapter', function () {
expect(requests[0].url).to.be.equal(VIDEO_ENDPOINT);
});
+ it('should not require params.video if required props in mediaTypes.video', function () {
+ videoBid.mediaTypes.video = {
+ ...videoBid.mediaTypes.video,
+ ...videoBid.params.video
+ };
+ delete videoBid.params.video;
+ const requests = build([videoBid]);
+ expect(requests.length).to.equal(1);
+ expect(requests[0].method).to.equal('POST');
+ expect(requests[0].url).to.be.equal(VIDEO_ENDPOINT);
+ });
+
it('should add mediaTypes.video prop to the imp.video prop', function () {
utils.deepAccess(videoBid, 'mediaTypes.video')['minduration'] = 40;
expect(buildVideoBidAndGetVideoParam().minduration).to.equal(40);
@@ -441,6 +460,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'];
diff --git a/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js b/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js
index cbba815cfc1..5194a6a526a 100644
--- a/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js
+++ b/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js
@@ -2,19 +2,20 @@ import zetaAnalyticsAdapter from 'modules/zeta_global_sspAnalyticsAdapter.js';
import {config} from 'src/config';
import CONSTANTS from 'src/constants.json';
import {server} from '../../mocks/xhr.js';
+import {logError} from '../../../src/utils';
let utils = require('src/utils');
let events = require('src/events');
-const MOCK = {
- STUB: {
- 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa'
- },
+const EVENTS = {
AUCTION_END: {
'auctionId': '75e394d9-ccce-4978-9238-91e6a1ac88a1',
'timestamp': 1638441234544,
'auctionEnd': 1638441234784,
'auctionStatus': 'completed',
+ 'metrics': {
+ 'someMetric': 1
+ },
'adUnits': [
{
'code': '/19968336/header-bid-tag-0',
@@ -74,13 +75,6 @@ const MOCK = {
'bids': [
{
'bidder': 'zeta_global_ssp',
- 'params': {
- 'sid': 111,
- 'tags': {
- 'shortname': 'prebid_analytics_event_test_shortname',
- 'position': 'test_position'
- }
- },
'mediaTypes': {
'banner': {
'sizes': [
@@ -309,6 +303,9 @@ const MOCK = {
'cpm': 2.258302852806723,
'currency': 'USD',
'ad': 'test_ad',
+ 'metrics': {
+ 'someMetric': 0
+ },
'ttl': 200,
'creativeId': '456456456',
'netRevenue': true,
@@ -344,11 +341,7 @@ const MOCK = {
'status': 'rendered',
'params': [
{
- 'sid': 111,
- 'tags': {
- 'shortname': 'prebid_analytics_event_test_shortname',
- 'position': 'test_position'
- }
+ 'nonZetaParam': 'nonZetaValue'
}
]
},
@@ -392,33 +385,45 @@ describe('Zeta Global SSP Analytics Adapter', function() {
zetaAnalyticsAdapter.disableAnalytics();
});
- it('events are sent', function() {
- this.timeout(5000);
- events.emit(CONSTANTS.EVENTS.AUCTION_INIT, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.AUCTION_END, MOCK.AUCTION_END);
- events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.BID_REQUESTED, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.BID_RESPONSE, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.NO_BID, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.BID_WON, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.BIDDER_DONE, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.BIDDER_ERROR, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.SET_TARGETING, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.BEFORE_REQUEST_BIDS, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.BEFORE_BIDDER_HTTP, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.REQUEST_BIDS, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.ADD_AD_UNITS, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.AD_RENDER_FAILED, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED, MOCK.AD_RENDER_SUCCEEDED);
- events.emit(CONSTANTS.EVENTS.TCF2_ENFORCEMENT, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.AUCTION_DEBUG, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.BID_VIEWABLE, MOCK.STUB);
- events.emit(CONSTANTS.EVENTS.STALE_RENDER, MOCK.STUB);
+ it('Move ZetaParams through analytics events', function() {
+ this.timeout(3000);
+
+ events.emit(CONSTANTS.EVENTS.AUCTION_END, EVENTS.AUCTION_END);
+ events.emit(CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED, EVENTS.AD_RENDER_SUCCEEDED);
+
+ expect(requests.length).to.equal(2);
+ const auctionEnd = JSON.parse(requests[0].requestBody);
+ const auctionSucceeded = JSON.parse(requests[1].requestBody);
+
+ expect(auctionSucceeded.bid.params[0]).to.be.deep.equal(EVENTS.AUCTION_END.adUnits[0].bids[0].params);
+ expect(EVENTS.AUCTION_END.adUnits[0].bids[0].bidder).to.be.equal('zeta_global_ssp');
+ });
+
+ it('Keep only needed fields', function() {
+ this.timeout(3000);
+
+ events.emit(CONSTANTS.EVENTS.AUCTION_END, EVENTS.AUCTION_END);
+ events.emit(CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED, EVENTS.AD_RENDER_SUCCEEDED);
expect(requests.length).to.equal(2);
- expect(JSON.parse(requests[0].requestBody)).to.deep.equal(MOCK.AUCTION_END);
- expect(JSON.parse(requests[1].requestBody)).to.deep.equal(MOCK.AD_RENDER_SUCCEEDED);
+ const auctionEnd = JSON.parse(requests[0].requestBody);
+ const auctionSucceeded = JSON.parse(requests[1].requestBody);
+
+ expect(auctionEnd.adUnitCodes[0]).to.be.equal('/19968336/header-bid-tag-0');
+ expect(auctionEnd.adUnits[0].bids[0].bidder).to.be.equal('zeta_global_ssp');
+ expect(auctionEnd.auctionEnd).to.be.equal(1638441234784);
+ expect(auctionEnd.auctionId).to.be.equal('75e394d9-ccce-4978-9238-91e6a1ac88a1');
+ expect(auctionEnd.bidderRequests[0].bidderCode).to.be.equal('zeta_global_ssp');
+ expect(auctionEnd.bidsReceived[0].bidderCode).to.be.equal('zeta_global_ssp');
+ expect(auctionEnd.noBids[0].bidder).to.be.equal('appnexus');
+
+ expect(auctionSucceeded.adId).to.be.equal('5759bb3ef7be1e8');
+ expect(auctionSucceeded.bid.auctionId).to.be.equal('75e394d9-ccce-4978-9238-91e6a1ac88a1');
+ expect(auctionSucceeded.bid.requestId).to.be.equal('206be9a13236af');
+ expect(auctionSucceeded.bid.bidderCode).to.be.equal('zeta_global_ssp');
+ expect(auctionSucceeded.bid.creativeId).to.be.equal('456456456');
+ expect(auctionSucceeded.bid.size).to.be.equal('480x320');
+ expect(auctionSucceeded.doc.location.hostname).to.be.equal('localhost');
});
});
});
diff --git a/test/spec/modules/zeta_global_sspBidAdapter_spec.js b/test/spec/modules/zeta_global_sspBidAdapter_spec.js
index 601f4546a29..9ef97019a98 100644
--- a/test/spec/modules/zeta_global_sspBidAdapter_spec.js
+++ b/test/spec/modules/zeta_global_sspBidAdapter_spec.js
@@ -1,5 +1,6 @@
import {spec} from '../../../modules/zeta_global_sspBidAdapter.js'
import {BANNER, VIDEO} from '../../../src/mediaTypes';
+import {deepClone} from '../../../src/utils';
describe('Zeta Ssp Bid Adapter', function () {
const eids = [
@@ -50,7 +51,6 @@ describe('Zeta Ssp Bid Adapter', function () {
someTag: 444,
},
sid: 'publisherId',
- shortname: 'test_shortname',
tagid: 'test_tag_id',
site: {
page: 'testPage'
@@ -124,7 +124,24 @@ describe('Zeta Ssp Bid Adapter', function () {
uspConsent: 'someCCPAString',
params: params,
userIdAsEids: eids,
- timeout: 500
+ timeout: 500,
+ ortb2: {
+ user: {
+ data: [
+ {
+ ext: {
+ segtax: 600,
+ segclass: 'classifier_v1'
+ },
+ segment: [
+ { id: '3' },
+ { id: '44' },
+ { id: '59' }
+ ]
+ }
+ ]
+ }
+ }
}];
const bannerWithFewSizesRequest = [{
@@ -253,11 +270,13 @@ describe('Zeta Ssp Bid Adapter', function () {
};
it('Test the bid validation function', function () {
- const validBid = spec.isBidRequestValid(bannerRequest[0]);
- const invalidBid = spec.isBidRequestValid(null);
+ const invalidBid = deepClone(bannerRequest[0]);
+ invalidBid.params = {};
+ const isValidBid = spec.isBidRequestValid(bannerRequest[0]);
+ const isInvalidBid = spec.isBidRequestValid(null);
- expect(validBid).to.be.true;
- expect(invalidBid).to.be.false;
+ expect(isValidBid).to.be.true;
+ expect(isInvalidBid).to.be.false;
});
it('Test provide eids', function () {
@@ -453,7 +472,7 @@ describe('Zeta Ssp Bid Adapter', function () {
it('Test required params in banner request', function () {
const request = spec.buildRequests(bannerRequest, bannerRequest[0]);
const payload = JSON.parse(request.data);
- expect(request.url).to.eql('https://ssp.disqus.com/bid/prebid?shortname=test_shortname');
+ expect(request.url).to.eql('https://ssp.disqus.com/bid/prebid?sid=publisherId');
expect(payload.ext.sid).to.eql('publisherId');
expect(payload.ext.tags.someTag).to.eql(444);
expect(payload.ext.tags.shortname).to.be.undefined;
@@ -462,7 +481,7 @@ describe('Zeta Ssp Bid Adapter', function () {
it('Test required params in video request', function () {
const request = spec.buildRequests(videoRequest, videoRequest[0]);
const payload = JSON.parse(request.data);
- expect(request.url).to.eql('https://ssp.disqus.com/bid/prebid?shortname=test_shortname');
+ expect(request.url).to.eql('https://ssp.disqus.com/bid/prebid?sid=publisherId');
expect(payload.ext.sid).to.eql('publisherId');
expect(payload.ext.tags.someTag).to.eql(444);
expect(payload.ext.tags.shortname).to.be.undefined;
@@ -471,7 +490,7 @@ describe('Zeta Ssp Bid Adapter', function () {
it('Test multi imp', function () {
const request = spec.buildRequests(multiImpRequest, multiImpRequest[0]);
const payload = JSON.parse(request.data);
- expect(request.url).to.eql('https://ssp.disqus.com/bid/prebid?shortname=test_shortname');
+ expect(request.url).to.eql('https://ssp.disqus.com/bid/prebid?sid=publisherId');
expect(payload.imp.length).to.eql(2);
@@ -604,4 +623,13 @@ 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');
+ });
});
diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js
index cff26df2e4d..98d841d9c7c 100644
--- a/test/spec/unit/core/adapterManager_spec.js
+++ b/test/spec/unit/core/adapterManager_spec.js
@@ -965,13 +965,23 @@ describe('adapterManager tests', function () {
}];
it('invokes callBids on the S2S adapter', function () {
+ const done = sinon.stub();
+ const onTimelyResponse = sinon.stub();
+ prebidServerAdapterMock.callBids.callsFake((_1, _2, _3, done) => {
+ done();
+ });
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));
});
// Enable this test when prebidServer adapter is made 1.0 compliant
diff --git a/test/spec/unit/core/ajax_spec.js b/test/spec/unit/core/ajax_spec.js
index df0ce02c15c..a3a0459b980 100644
--- a/test/spec/unit/core/ajax_spec.js
+++ b/test/spec/unit/core/ajax_spec.js
@@ -1,7 +1,8 @@
-import {dep, attachCallbacks, fetcherFactory, toFetchRequest} from '../../../../src/ajax.js';
+import {attachCallbacks, dep, fetcherFactory, toFetchRequest} from '../../../../src/ajax.js';
import {config} from 'src/config.js';
import {server} from '../../../mocks/xhr.js';
-import {sandbox} from 'sinon';
+import * as utils from 'src/utils.js';
+import {logError} from 'src/utils.js';
const EXAMPLE_URL = 'https://www.example.com';
@@ -312,13 +313,24 @@ describe('attachCallbacks', () => {
const cbType = success ? 'success' : 'error';
describe(`for ${t}`, () => {
- let response, body;
+ let sandbox, response, body;
beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+ sandbox.spy(utils, 'logError');
({response, body} = makeResponse());
});
+ afterEach(() => {
+ sandbox.restore();
+ })
+
function checkXHR(xhr) {
- sinon.assert.match(xhr, {
+ utils.logError.resetHistory();
+ const serialized = JSON.parse(JSON.stringify(xhr))
+ // serialization of `responseXML` should not generate console messages
+ sinon.assert.notCalled(utils.logError);
+
+ sinon.assert.match(serialized, {
readyState: XMLHttpRequest.DONE,
status: response.status,
statusText: response.statusText,
@@ -330,7 +342,7 @@ describe('attachCallbacks', () => {
if (xml) {
expect(xhr.responseXML.querySelectorAll('*').length > 0).to.be.true;
} else {
- expect(xhr.responseXML).to.not.exist;
+ expect(serialized.responseXML).to.not.exist;
}
Array.from(response.headers.entries()).forEach(([name, value]) => {
expect(xhr.getResponseHeader(name)).to.eql(value);
diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js
index 0360679ca52..9dcdb627698 100644
--- a/test/spec/unit/core/bidderFactory_spec.js
+++ b/test/spec/unit/core/bidderFactory_spec.js
@@ -48,1040 +48,1151 @@ before(() => {
let wrappedCallback = config.callbackWithBidder(CODE);
-describe('bidders created by newBidder', function () {
- let spec;
- let bidder;
- let addBidResponseStub;
- let doneStub;
-
- beforeEach(function () {
- spec = {
- code: CODE,
- isBidRequestValid: sinon.stub(),
- buildRequests: sinon.stub(),
- interpretResponse: sinon.stub(),
- getUserSyncs: sinon.stub()
- };
-
- addBidResponseStub = sinon.stub();
- addBidResponseStub.reject = sinon.stub();
- doneStub = sinon.stub();
- });
-
- describe('when the ajax response is irrelevant', function () {
- let sandbox;
- let ajaxStub;
- let getConfigSpy;
- let aliasRegistryStub, aliasRegistry;
+describe('bidderFactory', () => {
+ describe('bidders created by newBidder', function () {
+ let spec;
+ let bidder;
+ let addBidResponseStub;
+ let doneStub;
beforeEach(function () {
- sandbox = sinon.sandbox.create();
- sandbox.stub(activityRules, 'isActivityAllowed').callsFake(() => true);
- ajaxStub = sandbox.stub(ajax, 'ajax');
- addBidResponseStub.reset();
- getConfigSpy = sandbox.spy(config, 'getConfig');
- doneStub.reset();
- aliasRegistry = {};
- aliasRegistryStub = sandbox.stub(adapterManager, 'aliasRegistry');
- aliasRegistryStub.get(() => aliasRegistry);
- });
+ spec = {
+ code: CODE,
+ isBidRequestValid: sinon.stub(),
+ buildRequests: sinon.stub(),
+ interpretResponse: sinon.stub(),
+ getUserSyncs: sinon.stub()
+ };
- afterEach(function () {
- sandbox.restore();
+ addBidResponseStub = sinon.stub();
+ addBidResponseStub.reject = sinon.stub();
+ doneStub = sinon.stub();
});
- it('should let registerSyncs run with invalid alias and aliasSync enabled', function () {
- config.setConfig({
- userSync: {
- aliasSyncEnabled: true
- }
+ describe('when the ajax response is irrelevant', function () {
+ let sandbox;
+ let ajaxStub;
+ let getConfigSpy;
+ let aliasRegistryStub, aliasRegistry;
+
+ beforeEach(function () {
+ sandbox = sinon.sandbox.create();
+ sandbox.stub(activityRules, 'isActivityAllowed').callsFake(() => true);
+ ajaxStub = sandbox.stub(ajax, 'ajax');
+ addBidResponseStub.reset();
+ getConfigSpy = sandbox.spy(config, 'getConfig');
+ doneStub.reset();
+ aliasRegistry = {};
+ aliasRegistryStub = sandbox.stub(adapterManager, 'aliasRegistry');
+ aliasRegistryStub.get(() => aliasRegistry);
});
- spec.code = 'fakeBidder';
- const bidder = newBidder(spec);
- bidder.callBids({ bids: [] }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(true);
- });
- it('should let registerSyncs run with valid alias and aliasSync enabled', function () {
- config.setConfig({
- userSync: {
- aliasSyncEnabled: true
- }
+ afterEach(function () {
+ sandbox.restore();
});
- spec.code = 'aliasBidder';
- const bidder = newBidder(spec);
- bidder.callBids({ bids: [] }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(true);
- });
- it('should let registerSyncs run with invalid alias and aliasSync disabled', function () {
- config.setConfig({
- userSync: {
- aliasSyncEnabled: false
- }
+ it('should let registerSyncs run with invalid alias and aliasSync enabled', function () {
+ config.setConfig({
+ userSync: {
+ aliasSyncEnabled: true
+ }
+ });
+ spec.code = 'fakeBidder';
+ const bidder = newBidder(spec);
+ bidder.callBids({ bids: [] }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(true);
});
- spec.code = 'fakeBidder';
- const bidder = newBidder(spec);
- bidder.callBids({ bids: [] }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(true);
- });
- it('should not let registerSyncs run with valid alias and aliasSync disabled', function () {
- config.setConfig({
- userSync: {
- aliasSyncEnabled: false
- }
+ it('should let registerSyncs run with valid alias and aliasSync enabled', function () {
+ config.setConfig({
+ userSync: {
+ aliasSyncEnabled: true
+ }
+ });
+ spec.code = 'aliasBidder';
+ const bidder = newBidder(spec);
+ bidder.callBids({ bids: [] }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(true);
});
- spec.code = 'aliasBidder';
- const bidder = newBidder(spec);
- aliasRegistry = {[spec.code]: CODE};
- bidder.callBids({ bids: [] }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(false);
- });
- describe('transaction IDs', () => {
- beforeEach(() => {
- activityRules.isActivityAllowed.reset();
- ajaxStub.callsFake((_, callback) => callback.success(null, {getResponseHeader: sinon.stub()}));
- spec.interpretResponse.callsFake(() => [
- {
- requestId: 'bid',
- cpm: 123,
- ttl: 300,
- creativeId: 'crid',
- netRevenue: true,
- currency: 'USD'
+ it('should let registerSyncs run with invalid alias and aliasSync disabled', function () {
+ config.setConfig({
+ userSync: {
+ aliasSyncEnabled: false
+ }
+ });
+ spec.code = 'fakeBidder';
+ const bidder = newBidder(spec);
+ bidder.callBids({ bids: [] }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(true);
+ });
+
+ it('should not let registerSyncs run with valid alias and aliasSync disabled', function () {
+ config.setConfig({
+ userSync: {
+ aliasSyncEnabled: false
}
- ])
+ });
+ spec.code = 'aliasBidder';
+ const bidder = newBidder(spec);
+ aliasRegistry = {[spec.code]: CODE};
+ bidder.callBids({ bids: [] }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(false);
});
- Object.entries({
- 'be hidden': false,
- 'not be hidden': true,
- }).forEach(([t, allowed]) => {
- const expectation = allowed ? (val) => expect(val).to.exist : (val) => expect(val).to.not.exist;
+ describe('transaction IDs', () => {
+ beforeEach(() => {
+ activityRules.isActivityAllowed.reset();
+ ajaxStub.callsFake((_, callback) => callback.success(null, {getResponseHeader: sinon.stub()}));
+ spec.interpretResponse.callsFake(() => [
+ {
+ requestId: 'bid',
+ cpm: 123,
+ ttl: 300,
+ creativeId: 'crid',
+ netRevenue: true,
+ currency: 'USD'
+ }
+ ])
+ });
- function checkBidRequest(br) {
- ['auctionId', 'transactionId'].forEach((prop) => expectation(br[prop]));
- }
+ Object.entries({
+ 'be hidden': false,
+ 'not be hidden': true,
+ }).forEach(([t, allowed]) => {
+ const expectation = allowed ? (val) => expect(val).to.exist : (val) => expect(val).to.not.exist;
- function checkBidderRequest(br) {
- expectation(br.auctionId);
- br.bids.forEach(checkBidRequest);
- }
+ function checkBidRequest(br) {
+ ['auctionId', 'transactionId'].forEach((prop) => expectation(br[prop]));
+ }
- it(`should ${t} from the spec logic when the transmitTid activity is${allowed ? '' : ' not'} allowed`, () => {
- spec.isBidRequestValid.callsFake(br => {
- checkBidRequest(br);
- return true;
- });
- spec.buildRequests.callsFake((bidReqs, bidderReq) => {
- checkBidderRequest(bidderReq);
- bidReqs.forEach(checkBidRequest);
- return {method: 'POST'};
- });
- activityRules.isActivityAllowed.callsFake(() => allowed);
+ function checkBidderRequest(br) {
+ expectation(br.auctionId);
+ br.bids.forEach(checkBidRequest);
+ }
- const bidder = newBidder(spec);
+ it(`should ${t} from the spec logic when the transmitTid activity is${allowed ? '' : ' not'} allowed`, () => {
+ spec.isBidRequestValid.callsFake(br => {
+ checkBidRequest(br);
+ return true;
+ });
+ spec.buildRequests.callsFake((bidReqs, bidderReq) => {
+ checkBidderRequest(bidderReq);
+ bidReqs.forEach(checkBidRequest);
+ return {method: 'POST'};
+ });
+ activityRules.isActivityAllowed.callsFake(() => allowed);
+
+ const bidder = newBidder(spec);
+
+ bidder.callBids({
+ bidderCode: 'mockBidder',
+ auctionId: 'aid',
+ bids: [
+ {
+ adUnitCode: 'mockAU',
+ bidId: 'bid',
+ transactionId: 'tid',
+ auctionId: 'aid'
+ }
+ ]
+ }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+
+ sinon.assert.calledWithMatch(activityRules.isActivityAllowed, ACTIVITY_TRANSMIT_TID, {
+ componentType: MODULE_TYPE_BIDDER,
+ componentName: 'mockBidder'
+ });
+ sinon.assert.calledWithMatch(addBidResponseStub, sinon.match.any, {
+ transactionId: 'tid',
+ auctionId: 'aid'
+ })
+ });
+ });
- bidder.callBids({
+ it('should not be hidden from request methods', (done) => {
+ const bidderRequest = {
bidderCode: 'mockBidder',
auctionId: 'aid',
+ getAID() { return this.auctionId },
bids: [
{
adUnitCode: 'mockAU',
bidId: 'bid',
transactionId: 'tid',
- auctionId: 'aid'
+ auctionId: 'aid',
+ getTIDs() {
+ return [this.auctionId, this.transactionId]
+ }
}
]
- }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
-
- sinon.assert.calledWithMatch(activityRules.isActivityAllowed, ACTIVITY_TRANSMIT_TID, {
- componentType: MODULE_TYPE_BIDDER,
- componentName: 'mockBidder'
+ };
+ activityRules.isActivityAllowed.callsFake(() => false);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.callsFake((reqs, bidderReq) => {
+ expect(bidderReq.getAID()).to.eql('aid');
+ expect(reqs[0].getTIDs()).to.eql(['aid', 'tid']);
+ done();
});
- sinon.assert.calledWithMatch(addBidResponseStub, sinon.match.any, {
- transactionId: 'tid',
- auctionId: 'aid'
- })
- });
+ newBidder(spec).callBids(bidderRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ })
});
- it('should not be hidden from request methods', (done) => {
- const bidderRequest = {
- bidderCode: 'mockBidder',
- auctionId: 'aid',
- getAID() { return this.auctionId },
- bids: [
- {
- adUnitCode: 'mockAU',
- bidId: 'bid',
- transactionId: 'tid',
- auctionId: 'aid',
- getTIDs() {
- return [this.auctionId, this.transactionId]
- }
- }
- ]
- };
- activityRules.isActivityAllowed.callsFake(() => false);
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.callsFake((reqs, bidderReq) => {
- expect(bidderReq.getAID()).to.eql('aid');
- expect(reqs[0].getTIDs()).to.eql(['aid', 'tid']);
- done();
- });
- newBidder(spec).callBids(bidderRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- })
- });
-
- it('should handle bad bid requests gracefully', function () {
- const bidder = newBidder(spec);
-
- spec.getUserSyncs.returns([]);
+ it('should handle bad bid requests gracefully', function () {
+ const bidder = newBidder(spec);
- bidder.callBids({});
- bidder.callBids({ bids: 'nothing useful' }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ spec.getUserSyncs.returns([]);
- expect(ajaxStub.called).to.equal(false);
- expect(spec.isBidRequestValid.called).to.equal(false);
- expect(spec.buildRequests.called).to.equal(false);
- expect(spec.interpretResponse.called).to.equal(false);
- });
+ bidder.callBids({});
+ bidder.callBids({ bids: 'nothing useful' }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should call buildRequests(bidRequest) the params are valid', function () {
- const bidder = newBidder(spec);
+ expect(ajaxStub.called).to.equal(false);
+ expect(spec.isBidRequestValid.called).to.equal(false);
+ expect(spec.buildRequests.called).to.equal(false);
+ expect(spec.interpretResponse.called).to.equal(false);
+ });
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns([]);
+ it('should call buildRequests(bidRequest) the params are valid', function () {
+ const bidder = newBidder(spec);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns([]);
- expect(ajaxStub.called).to.equal(false);
- expect(spec.isBidRequestValid.calledTwice).to.equal(true);
- expect(spec.buildRequests.calledOnce).to.equal(true);
- expect(spec.buildRequests.firstCall.args[0]).to.deep.equal(MOCK_BIDS_REQUEST.bids);
- });
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should not call buildRequests the params are invalid', function () {
- const bidder = newBidder(spec);
+ expect(ajaxStub.called).to.equal(false);
+ expect(spec.isBidRequestValid.calledTwice).to.equal(true);
+ expect(spec.buildRequests.calledOnce).to.equal(true);
+ expect(spec.buildRequests.firstCall.args[0]).to.deep.equal(MOCK_BIDS_REQUEST.bids);
+ });
- spec.isBidRequestValid.returns(false);
- spec.buildRequests.returns([]);
+ it('should not call buildRequests the params are invalid', function () {
+ const bidder = newBidder(spec);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ spec.isBidRequestValid.returns(false);
+ spec.buildRequests.returns([]);
- expect(ajaxStub.called).to.equal(false);
- expect(spec.isBidRequestValid.calledTwice).to.equal(true);
- expect(spec.buildRequests.called).to.equal(false);
- });
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should filter out invalid bids before calling buildRequests', function () {
- const bidder = newBidder(spec);
+ expect(ajaxStub.called).to.equal(false);
+ expect(spec.isBidRequestValid.calledTwice).to.equal(true);
+ expect(spec.buildRequests.called).to.equal(false);
+ });
- spec.isBidRequestValid.onFirstCall().returns(true);
- spec.isBidRequestValid.onSecondCall().returns(false);
- spec.buildRequests.returns([]);
+ it('should filter out invalid bids before calling buildRequests', function () {
+ const bidder = newBidder(spec);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ spec.isBidRequestValid.onFirstCall().returns(true);
+ spec.isBidRequestValid.onSecondCall().returns(false);
+ spec.buildRequests.returns([]);
- expect(ajaxStub.called).to.equal(false);
- expect(spec.isBidRequestValid.calledTwice).to.equal(true);
- expect(spec.buildRequests.calledOnce).to.equal(true);
- expect(spec.buildRequests.firstCall.args[0]).to.deep.equal([MOCK_BIDS_REQUEST.bids[0]]);
- });
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should make no server requests if the spec doesn\'t return any', function () {
- const bidder = newBidder(spec);
+ expect(ajaxStub.called).to.equal(false);
+ expect(spec.isBidRequestValid.calledTwice).to.equal(true);
+ expect(spec.buildRequests.calledOnce).to.equal(true);
+ expect(spec.buildRequests.firstCall.args[0]).to.deep.equal([MOCK_BIDS_REQUEST.bids[0]]);
+ });
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns([]);
+ it('should make no server requests if the spec doesn\'t return any', function () {
+ const bidder = newBidder(spec);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns([]);
- expect(ajaxStub.called).to.equal(false);
- });
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should make the appropriate POST request', function () {
- const bidder = newBidder(spec);
- const url = 'test.url.com';
- const data = { arg: 2 };
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: url,
- data: data
+ expect(ajaxStub.called).to.equal(false);
});
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should make the appropriate POST request', function () {
+ const bidder = newBidder(spec);
+ const url = 'test.url.com';
+ const data = { arg: 2 };
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: url,
+ data: data
+ });
- expect(ajaxStub.calledOnce).to.equal(true);
- expect(ajaxStub.firstCall.args[0]).to.equal(url);
- expect(ajaxStub.firstCall.args[2]).to.equal(JSON.stringify(data));
- sinon.assert.match(ajaxStub.firstCall.args[3], {
- method: 'POST',
- contentType: 'text/plain',
- withCredentials: true
- });
- });
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should make the appropriate POST request when options are passed', function () {
- const bidder = newBidder(spec);
- const url = 'test.url.com';
- const data = { arg: 2 };
- const options = { contentType: 'application/json' };
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: url,
- data: data,
- options: options
+ expect(ajaxStub.calledOnce).to.equal(true);
+ expect(ajaxStub.firstCall.args[0]).to.equal(url);
+ expect(ajaxStub.firstCall.args[2]).to.equal(JSON.stringify(data));
+ sinon.assert.match(ajaxStub.firstCall.args[3], {
+ method: 'POST',
+ contentType: 'text/plain',
+ withCredentials: true
+ });
});
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should make the appropriate POST request when options are passed', function () {
+ const bidder = newBidder(spec);
+ const url = 'test.url.com';
+ const data = { arg: 2 };
+ const options = { contentType: 'application/json' };
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: url,
+ data: data,
+ options: options
+ });
- expect(ajaxStub.calledOnce).to.equal(true);
- expect(ajaxStub.firstCall.args[0]).to.equal(url);
- expect(ajaxStub.firstCall.args[2]).to.equal(JSON.stringify(data));
- sinon.assert.match(ajaxStub.firstCall.args[3], {
- method: 'POST',
- contentType: 'application/json',
- withCredentials: true
- })
- });
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should make the appropriate GET request', function () {
- const bidder = newBidder(spec);
- const url = 'test.url.com';
- const data = { arg: 2 };
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'GET',
- url: url,
- data: data
+ expect(ajaxStub.calledOnce).to.equal(true);
+ expect(ajaxStub.firstCall.args[0]).to.equal(url);
+ expect(ajaxStub.firstCall.args[2]).to.equal(JSON.stringify(data));
+ sinon.assert.match(ajaxStub.firstCall.args[3], {
+ method: 'POST',
+ contentType: 'application/json',
+ withCredentials: true
+ })
});
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should make the appropriate GET request', function () {
+ const bidder = newBidder(spec);
+ const url = 'test.url.com';
+ const data = { arg: 2 };
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'GET',
+ url: url,
+ data: data
+ });
- expect(ajaxStub.calledOnce).to.equal(true);
- expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2`);
- expect(ajaxStub.firstCall.args[2]).to.be.undefined;
- sinon.assert.match(ajaxStub.firstCall.args[3], {
- method: 'GET',
- withCredentials: true
- })
- });
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should make the appropriate GET request when options are passed', function () {
- const bidder = newBidder(spec);
- const url = 'test.url.com';
- const data = { arg: 2 };
- const opt = { withCredentials: false }
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'GET',
- url: url,
- data: data,
- options: opt
+ expect(ajaxStub.calledOnce).to.equal(true);
+ expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2`);
+ expect(ajaxStub.firstCall.args[2]).to.be.undefined;
+ sinon.assert.match(ajaxStub.firstCall.args[3], {
+ method: 'GET',
+ withCredentials: true
+ })
});
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
-
- expect(ajaxStub.calledOnce).to.equal(true);
- expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2`);
- expect(ajaxStub.firstCall.args[2]).to.be.undefined;
- sinon.assert.match(ajaxStub.firstCall.args[3], {
- method: 'GET',
- withCredentials: false
- })
- });
-
- it('should make multiple calls if the spec returns them', function () {
- const bidder = newBidder(spec);
- const url = 'test.url.com';
- const data = { arg: 2 };
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns([
- {
- method: 'POST',
- url: url,
- data: data
- },
- {
+ it('should make the appropriate GET request when options are passed', function () {
+ const bidder = newBidder(spec);
+ const url = 'test.url.com';
+ const data = { arg: 2 };
+ const opt = { withCredentials: false }
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
method: 'GET',
url: url,
- data: data
- }
- ]);
-
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ data: data,
+ options: opt
+ });
- expect(ajaxStub.calledTwice).to.equal(true);
- });
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- describe('browsingTopics ajax option', () => {
- let transmitUfpdAllowed, bidder;
- beforeEach(() => {
- activityRules.isActivityAllowed.reset();
- activityRules.isActivityAllowed.callsFake((activity) => activity === ACTIVITY_TRANSMIT_UFPD ? transmitUfpdAllowed : true);
- bidder = newBidder(spec);
- spec.isBidRequestValid.returns(true);
+ expect(ajaxStub.calledOnce).to.equal(true);
+ expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2`);
+ expect(ajaxStub.firstCall.args[2]).to.be.undefined;
+ sinon.assert.match(ajaxStub.firstCall.args[3], {
+ method: 'GET',
+ withCredentials: false
+ })
});
- it(`should be set to false when adapter sets browsingTopics = false`, () => {
- transmitUfpdAllowed = true;
+ it('should make multiple calls if the spec returns them', function () {
+ const bidder = newBidder(spec);
+ const url = 'test.url.com';
+ const data = { arg: 2 };
+ spec.isBidRequestValid.returns(true);
spec.buildRequests.returns([
+ {
+ method: 'POST',
+ url: url,
+ data: data
+ },
{
method: 'GET',
- url: 'url',
- options: {
- browsingTopics: false
- }
+ url: url,
+ data: data
}
]);
+
bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- sinon.assert.calledWith(ajaxStub, 'url', sinon.match.any, sinon.match.any, sinon.match({
- browsingTopics: false
- }));
+
+ expect(ajaxStub.calledTwice).to.equal(true);
});
- Object.entries({
- 'allowed': true,
- 'not allowed': false
- }).forEach(([t, allow]) => {
- it(`should be set to ${allow} when transmitUfpd is ${t}`, () => {
- transmitUfpdAllowed = allow;
+ describe('browsingTopics ajax option', () => {
+ 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);
+ bidder = newBidder(spec);
+ spec.isBidRequestValid.returns(true);
+ });
+
+ it(`should be set to false when adapter sets browsingTopics = false`, () => {
+ transmitUfpdAllowed = true;
spec.buildRequests.returns([
{
method: 'GET',
- url: '1',
- },
- {
- method: 'POST',
- url: '2',
- data: {}
- },
- {
- method: 'GET',
- url: '3',
+ url: 'url',
options: {
- browsingTopics: true
- }
- },
- {
- method: 'POST',
- url: '4',
- data: {},
- options: {
- browsingTopics: true
+ browsingTopics: false
}
}
]);
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})
- );
- });
+ sinon.assert.calledWith(ajaxStub, 'url', sinon.match.any, sinon.match.any, sinon.match({
+ browsingTopics: false
+ }));
});
+
+ Object.entries({
+ '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
+ }
+ }
+ });
+
+ 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 () {
- const bidder = newBidder(spec);
+ it('should not add bids for each placement code if no requests are given', function () {
+ const bidder = newBidder(spec);
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns([]);
- spec.interpretResponse.returns([]);
- spec.getUserSyncs.returns([]);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns([]);
+ spec.interpretResponse.returns([]);
+ spec.getUserSyncs.returns([]);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(addBidResponseStub.callCount).to.equal(0);
- });
+ expect(addBidResponseStub.callCount).to.equal(0);
+ });
- it('should emit BEFORE_BIDDER_HTTP events before network requests', function () {
- const bidder = newBidder(spec);
- const req = {
- method: 'POST',
- url: 'test.url.com',
- data: { arg: 2 }
- };
+ it('should emit BEFORE_BIDDER_HTTP events before network requests', function () {
+ const bidder = newBidder(spec);
+ const req = {
+ method: 'POST',
+ url: 'test.url.com',
+ data: { arg: 2 }
+ };
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns([req, req]);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns([req, req]);
- const eventEmitterSpy = sinon.spy(events, 'emit');
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ const eventEmitterSpy = sinon.spy(events, 'emit');
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(ajaxStub.calledTwice).to.equal(true);
- expect(eventEmitterSpy.getCalls()
- .filter(call => call.args[0] === CONSTANTS.EVENTS.BEFORE_BIDDER_HTTP)
- ).to.length(2);
+ expect(ajaxStub.calledTwice).to.equal(true);
+ expect(eventEmitterSpy.getCalls()
+ .filter(call => call.args[0] === CONSTANTS.EVENTS.BEFORE_BIDDER_HTTP)
+ ).to.length(2);
- eventEmitterSpy.restore();
+ eventEmitterSpy.restore();
+ });
});
- });
- describe('when the ajax call succeeds', function () {
- let ajaxStub;
- let userSyncStub;
- let logErrorSpy;
+ describe('when the ajax call succeeds', function () {
+ let ajaxStub;
+ let userSyncStub;
+ let logErrorSpy;
- beforeEach(function () {
- ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) {
- const fakeResponse = sinon.stub();
- fakeResponse.returns('headerContent');
- callbacks.success('response body', { getResponseHeader: fakeResponse });
+ beforeEach(function () {
+ ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) {
+ const fakeResponse = sinon.stub();
+ fakeResponse.returns('headerContent');
+ callbacks.success('response body', { getResponseHeader: fakeResponse });
+ });
+ addBidResponseStub.reset();
+ doneStub.resetBehavior();
+ userSyncStub = sinon.stub(userSync, 'registerSync')
+ logErrorSpy = sinon.spy(utils, 'logError');
});
- addBidResponseStub.reset();
- doneStub.resetBehavior();
- userSyncStub = sinon.stub(userSync, 'registerSync')
- logErrorSpy = sinon.spy(utils, 'logError');
- });
- afterEach(function () {
- ajaxStub.restore();
- userSyncStub.restore();
- utils.logError.restore();
- });
+ afterEach(function () {
+ ajaxStub.restore();
+ userSyncStub.restore();
+ utils.logError.restore();
+ });
- it('should call spec.interpretResponse() with the response content', function () {
- const bidder = newBidder(spec);
+ it('should call spec.interpretResponse() with the response content', function () {
+ const bidder = newBidder(spec);
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
+ spec.getUserSyncs.returns([]);
+
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+
+ expect(spec.interpretResponse.calledOnce).to.equal(true);
+ const response = spec.interpretResponse.firstCall.args[0]
+ expect(response.body).to.equal('response body')
+ expect(response.headers.get('some-header')).to.equal('headerContent');
+ expect(spec.interpretResponse.firstCall.args[1]).to.deep.equal({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
+ expect(doneStub.calledOnce).to.equal(true);
});
- spec.getUserSyncs.returns([]);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should call spec.interpretResponse() once for each request made', function () {
+ const bidder = newBidder(spec);
- expect(spec.interpretResponse.calledOnce).to.equal(true);
- const response = spec.interpretResponse.firstCall.args[0]
- expect(response.body).to.equal('response body')
- expect(response.headers.get('some-header')).to.equal('headerContent');
- expect(spec.interpretResponse.firstCall.args[1]).to.deep.equal({
- method: 'POST',
- url: 'test.url.com',
- data: {}
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns([
+ {
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ },
+ {
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ },
+ ]);
+ spec.getUserSyncs.returns([]);
+
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+
+ expect(spec.interpretResponse.calledTwice).to.equal(true);
+ expect(doneStub.calledOnce).to.equal(true);
});
- expect(doneStub.calledOnce).to.equal(true);
- });
- it('should call spec.interpretResponse() once for each request made', function () {
- const bidder = newBidder(spec);
+ it('should only add bids for valid adUnit code into the auction, even if the bidder doesn\'t bid on all of them', function () {
+ const bidder = newBidder(spec);
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns([
- {
+ const bid = {
+ creativeId: 'creative-id',
+ requestId: '1',
+ ad: 'ad-url.com',
+ cpm: 0.5,
+ height: 200,
+ width: 300,
+ adUnitCode: 'mock/placement',
+ currency: 'USD',
+ netRevenue: true,
+ ttl: 300,
+ bidderCode: 'sampleBidder',
+ sampleBidder: {advertiserId: '12345', networkId: '111222'}
+ };
+ const bidderRequest = Object.assign({}, MOCK_BIDS_REQUEST);
+ bidderRequest.bids[0].bidder = 'sampleBidder';
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
method: 'POST',
url: 'test.url.com',
data: {}
- },
- {
+ });
+ spec.getUserSyncs.returns([]);
+
+ spec.interpretResponse.returns(bid);
+
+ bidder.callBids(bidderRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+
+ expect(addBidResponseStub.calledOnce).to.equal(true);
+ expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
+ let bidObject = addBidResponseStub.firstCall.args[1];
+ // checking the fields added by our code
+ expect(bidObject.originalCpm).to.equal(bid.cpm);
+ expect(bidObject.originalCurrency).to.equal(bid.currency);
+ expect(doneStub.calledOnce).to.equal(true);
+ expect(logErrorSpy.callCount).to.equal(0);
+ expect(bidObject.meta).to.exist;
+ expect(bidObject.meta).to.deep.equal({advertiserId: '12345', networkId: '111222'});
+ });
+
+ it('should call spec.getUserSyncs() with the response', function () {
+ const bidder = newBidder(spec);
+
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
method: 'POST',
url: 'test.url.com',
data: {}
- },
- ]);
- spec.getUserSyncs.returns([]);
+ });
+ spec.getUserSyncs.returns([]);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(spec.interpretResponse.calledTwice).to.equal(true);
- expect(doneStub.calledOnce).to.equal(true);
- });
+ expect(spec.getUserSyncs.calledOnce).to.equal(true);
+ expect(spec.getUserSyncs.firstCall.args[1].length).to.equal(1);
+ expect(spec.getUserSyncs.firstCall.args[1][0].body).to.equal('response body');
+ expect(spec.getUserSyncs.firstCall.args[1][0].headers).to.have.property('get');
+ expect(spec.getUserSyncs.firstCall.args[1][0].headers.get).to.be.a('function');
+ });
- it('should only add bids for valid adUnit code into the auction, even if the bidder doesn\'t bid on all of them', function () {
- const bidder = newBidder(spec);
+ it('should register usersync pixels', function () {
+ const bidder = newBidder(spec);
- const bid = {
- creativeId: 'creative-id',
- requestId: '1',
- ad: 'ad-url.com',
- cpm: 0.5,
- height: 200,
- width: 300,
- adUnitCode: 'mock/placement',
- currency: 'USD',
- netRevenue: true,
- ttl: 300,
- bidderCode: 'sampleBidder',
- sampleBidder: {advertiserId: '12345', networkId: '111222'}
- };
- const bidderRequest = Object.assign({}, MOCK_BIDS_REQUEST);
- bidderRequest.bids[0].bidder = 'sampleBidder';
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
+ spec.isBidRequestValid.returns(false);
+ spec.buildRequests.returns([]);
+ spec.getUserSyncs.returns([{
+ type: 'iframe',
+ url: 'usersync.com'
+ }]);
+
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+
+ expect(userSyncStub.called).to.equal(true);
+ expect(userSyncStub.firstCall.args[0]).to.equal('iframe');
+ expect(userSyncStub.firstCall.args[1]).to.equal(spec.code);
+ expect(userSyncStub.firstCall.args[2]).to.equal('usersync.com');
});
- spec.getUserSyncs.returns([]);
- spec.interpretResponse.returns(bid);
+ it('should logError and reject bid when required bid response params are missing', function () {
+ const bidder = newBidder(spec);
- bidder.callBids(bidderRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ const bid = {
+ requestId: '1',
+ ad: 'ad-url.com',
+ cpm: 0.5,
+ height: 200,
+ width: 300,
+ placementCode: 'mock/placement'
+ };
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
+ spec.getUserSyncs.returns([]);
- expect(addBidResponseStub.calledOnce).to.equal(true);
- expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
- let bidObject = addBidResponseStub.firstCall.args[1];
- // checking the fields added by our code
- expect(bidObject.originalCpm).to.equal(bid.cpm);
- expect(bidObject.originalCurrency).to.equal(bid.currency);
- expect(doneStub.calledOnce).to.equal(true);
- expect(logErrorSpy.callCount).to.equal(0);
- expect(bidObject.meta).to.exist;
- expect(bidObject.meta).to.deep.equal({advertiserId: '12345', networkId: '111222'});
- });
+ spec.interpretResponse.returns(bid);
- it('should call spec.getUserSyncs() with the response', function () {
- const bidder = newBidder(spec);
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
+ expect(logErrorSpy.calledOnce).to.equal(true);
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
});
- spec.getUserSyncs.returns([]);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should logError and reject bid when required response params are undefined', function () {
+ const bidder = newBidder(spec);
- expect(spec.getUserSyncs.calledOnce).to.equal(true);
- expect(spec.getUserSyncs.firstCall.args[1].length).to.equal(1);
- expect(spec.getUserSyncs.firstCall.args[1][0].body).to.equal('response body');
- expect(spec.getUserSyncs.firstCall.args[1][0].headers).to.have.property('get');
- expect(spec.getUserSyncs.firstCall.args[1][0].headers.get).to.be.a('function');
- });
+ const bid = {
+ 'ad': 'creative',
+ 'cpm': '1.99',
+ 'width': 300,
+ 'height': 250,
+ 'requestId': '1',
+ 'creativeId': 'some-id',
+ 'currency': undefined,
+ 'netRevenue': true,
+ 'ttl': 360
+ };
- it('should register usersync pixels', function () {
- const bidder = newBidder(spec);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
+ spec.getUserSyncs.returns([]);
- spec.isBidRequestValid.returns(false);
- spec.buildRequests.returns([]);
- spec.getUserSyncs.returns([{
- type: 'iframe',
- url: 'usersync.com'
- }]);
+ spec.interpretResponse.returns(bid);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(userSyncStub.called).to.equal(true);
- expect(userSyncStub.firstCall.args[0]).to.equal('iframe');
- expect(userSyncStub.firstCall.args[1]).to.equal(spec.code);
- expect(userSyncStub.firstCall.args[2]).to.equal('usersync.com');
- });
+ expect(logErrorSpy.calledOnce).to.equal(true);
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ });
- it('should logError and reject bid when required bid response params are missing', function () {
- const bidder = newBidder(spec);
+ it('should require requestId from interpretResponse', () => {
+ const bidder = newBidder(spec);
+ const bid = {
+ 'ad': 'creative',
+ 'cpm': '1.99',
+ 'creativeId': 'some-id',
+ 'currency': 'USD',
+ 'netRevenue': true,
+ 'ttl': 360
+ };
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
+ spec.getUserSyncs.returns([]);
+ spec.interpretResponse.returns(bid);
- const bid = {
- requestId: '1',
- ad: 'ad-url.com',
- cpm: 0.5,
- height: 200,
- width: 300,
- placementCode: 'mock/placement'
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+
+ expect(addBidResponseStub.called).to.be.false;
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ });
+ });
+
+ describe('when the ajax call fails', function () {
+ let ajaxStub;
+ let callBidderErrorStub;
+ let eventEmitterStub;
+ let xhrErrorMock = {
+ status: 500,
+ statusText: 'Internal Server Error'
};
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
+
+ beforeEach(function () {
+ ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) {
+ callbacks.error('ajax call failed.', xhrErrorMock);
+ });
+ callBidderErrorStub = sinon.stub(adapterManager, 'callBidderError');
+ eventEmitterStub = sinon.stub(events, 'emit');
+ addBidResponseStub.reset();
+ doneStub.reset();
});
- spec.getUserSyncs.returns([]);
- spec.interpretResponse.returns(bid);
+ afterEach(function () {
+ ajaxStub.restore();
+ callBidderErrorStub.restore();
+ eventEmitterStub.restore();
+ });
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should not spec.interpretResponse()', function () {
+ const bidder = newBidder(spec);
- expect(logErrorSpy.calledOnce).to.equal(true);
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
- });
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
+ spec.getUserSyncs.returns([]);
- it('should logError and reject bid when required response params are undefined', function () {
- const bidder = newBidder(spec);
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- const bid = {
- 'ad': 'creative',
- 'cpm': '1.99',
- 'width': 300,
- 'height': 250,
- 'requestId': '1',
- 'creativeId': 'some-id',
- 'currency': undefined,
- 'netRevenue': true,
- 'ttl': 360
- };
+ expect(spec.interpretResponse.called).to.equal(false);
+ expect(doneStub.calledOnce).to.equal(true);
+ expect(callBidderErrorStub.calledOnce).to.equal(true);
+ expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE);
+ expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock);
+ expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST);
+ sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, {
+ error: xhrErrorMock,
+ bidderRequest: MOCK_BIDS_REQUEST
+ });
+ });
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
+ it('should not add bids for each adunit code into the auction', function () {
+ const bidder = newBidder(spec);
+
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
+ spec.interpretResponse.returns([]);
+ spec.getUserSyncs.returns([]);
+
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+
+ expect(addBidResponseStub.callCount).to.equal(0);
+ expect(doneStub.calledOnce).to.equal(true);
+ expect(callBidderErrorStub.calledOnce).to.equal(true);
+ expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE);
+ expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock);
+ expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST);
+ sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, {
+ error: xhrErrorMock,
+ bidderRequest: MOCK_BIDS_REQUEST
+ });
});
- spec.getUserSyncs.returns([]);
- spec.interpretResponse.returns(bid);
+ it('should call spec.getUserSyncs() with no responses', function () {
+ const bidder = newBidder(spec);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
+ spec.getUserSyncs.returns([]);
- expect(logErrorSpy.calledOnce).to.equal(true);
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
- });
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should require requestId from interpretResponse', () => {
- const bidder = newBidder(spec);
- const bid = {
- 'ad': 'creative',
- 'cpm': '1.99',
- 'creativeId': 'some-id',
- 'currency': 'USD',
- 'netRevenue': true,
- 'ttl': 360
- };
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
+ expect(spec.getUserSyncs.calledOnce).to.equal(true);
+ expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]);
+ expect(doneStub.calledOnce).to.equal(true);
+ expect(callBidderErrorStub.calledOnce).to.equal(true);
+ expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE);
+ expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock);
+ expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST);
+ sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, {
+ error: xhrErrorMock,
+ bidderRequest: MOCK_BIDS_REQUEST
+ });
});
- spec.getUserSyncs.returns([]);
- spec.interpretResponse.returns(bid);
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should call spec.getUserSyncs() with no responses', function () {
+ const bidder = newBidder(spec);
- expect(addBidResponseStub.called).to.be.false;
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
+ spec.getUserSyncs.returns([]);
+
+ bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+
+ expect(spec.getUserSyncs.calledOnce).to.equal(true);
+ expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]);
+ expect(doneStub.calledOnce).to.equal(true);
+ expect(callBidderErrorStub.calledOnce).to.equal(true);
+ expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE);
+ expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock);
+ expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST);
+ sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, {
+ error: xhrErrorMock,
+ bidderRequest: MOCK_BIDS_REQUEST
+ });
+ });
});
});
- describe('when the ajax call fails', function () {
- let ajaxStub;
- let callBidderErrorStub;
- let eventEmitterStub;
- let xhrErrorMock = {
- status: 500,
- statusText: 'Internal Server Error'
- };
+ describe('registerBidder', function () {
+ let registerBidAdapterStub;
+ let aliasBidAdapterStub;
beforeEach(function () {
- ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) {
- callbacks.error('ajax call failed.', xhrErrorMock);
- });
- callBidderErrorStub = sinon.stub(adapterManager, 'callBidderError');
- eventEmitterStub = sinon.stub(events, 'emit');
- addBidResponseStub.reset();
- doneStub.reset();
+ registerBidAdapterStub = sinon.stub(adapterManager, 'registerBidAdapter');
+ aliasBidAdapterStub = sinon.stub(adapterManager, 'aliasBidAdapter');
});
afterEach(function () {
- ajaxStub.restore();
- callBidderErrorStub.restore();
- eventEmitterStub.restore();
+ registerBidAdapterStub.restore();
+ aliasBidAdapterStub.restore();
});
- it('should not spec.interpretResponse()', function () {
- const bidder = newBidder(spec);
+ function newEmptySpec() {
+ return {
+ code: CODE,
+ isBidRequestValid: function() { },
+ buildRequests: function() { },
+ interpretResponse: function() { },
+ };
+ }
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
- });
- spec.getUserSyncs.returns([]);
-
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
-
- expect(spec.interpretResponse.called).to.equal(false);
- expect(doneStub.calledOnce).to.equal(true);
- expect(callBidderErrorStub.calledOnce).to.equal(true);
- expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE);
- expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock);
- expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST);
- sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, {
- error: xhrErrorMock,
- bidderRequest: MOCK_BIDS_REQUEST
- });
- });
+ it('should register a bidder with the adapterManager', function () {
+ registerBidder(newEmptySpec());
+ expect(registerBidAdapterStub.calledOnce).to.equal(true);
+ expect(registerBidAdapterStub.firstCall.args[0]).to.have.property('callBids');
+ expect(registerBidAdapterStub.firstCall.args[0].callBids).to.be.a('function');
- it('should not add bids for each adunit code into the auction', function () {
- const bidder = newBidder(spec);
+ expect(registerBidAdapterStub.firstCall.args[1]).to.equal(CODE);
+ expect(registerBidAdapterStub.firstCall.args[2]).to.be.undefined;
+ });
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
- });
- spec.interpretResponse.returns([]);
- spec.getUserSyncs.returns([]);
-
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
-
- expect(addBidResponseStub.callCount).to.equal(0);
- expect(doneStub.calledOnce).to.equal(true);
- expect(callBidderErrorStub.calledOnce).to.equal(true);
- expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE);
- expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock);
- expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST);
- sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, {
- error: xhrErrorMock,
- bidderRequest: MOCK_BIDS_REQUEST
- });
+ it('should register a bidder with the appropriate mediaTypes', function () {
+ const thisSpec = Object.assign(newEmptySpec(), { supportedMediaTypes: ['video'] });
+ registerBidder(thisSpec);
+ expect(registerBidAdapterStub.calledOnce).to.equal(true);
+ expect(registerBidAdapterStub.firstCall.args[2]).to.deep.equal({supportedMediaTypes: ['video']});
});
- it('should call spec.getUserSyncs() with no responses', function () {
- const bidder = newBidder(spec);
+ it('should register bidders with the appropriate aliases', function () {
+ const thisSpec = Object.assign(newEmptySpec(), { aliases: ['foo', 'bar'] });
+ registerBidder(thisSpec);
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
- });
- spec.getUserSyncs.returns([]);
-
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
-
- expect(spec.getUserSyncs.calledOnce).to.equal(true);
- expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]);
- expect(doneStub.calledOnce).to.equal(true);
- expect(callBidderErrorStub.calledOnce).to.equal(true);
- expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE);
- expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock);
- expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST);
- sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, {
- error: xhrErrorMock,
- bidderRequest: MOCK_BIDS_REQUEST
- });
- });
+ expect(registerBidAdapterStub.calledThrice).to.equal(true);
- it('should call spec.getUserSyncs() with no responses', function () {
- const bidder = newBidder(spec);
+ // Make sure our later calls don't override the bidder code from previous calls.
+ expect(registerBidAdapterStub.firstCall.args[0].getBidderCode()).to.equal(CODE);
+ expect(registerBidAdapterStub.secondCall.args[0].getBidderCode()).to.equal('foo')
+ expect(registerBidAdapterStub.thirdCall.args[0].getBidderCode()).to.equal('bar')
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
- });
- spec.getUserSyncs.returns([]);
-
- bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
-
- expect(spec.getUserSyncs.calledOnce).to.equal(true);
- expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]);
- expect(doneStub.calledOnce).to.equal(true);
- expect(callBidderErrorStub.calledOnce).to.equal(true);
- expect(callBidderErrorStub.firstCall.args[0]).to.equal(CODE);
- expect(callBidderErrorStub.firstCall.args[1]).to.equal(xhrErrorMock);
- expect(callBidderErrorStub.firstCall.args[2]).to.equal(MOCK_BIDS_REQUEST);
- sinon.assert.calledWith(eventEmitterStub, CONSTANTS.EVENTS.BIDDER_ERROR, {
- error: xhrErrorMock,
- bidderRequest: MOCK_BIDS_REQUEST
- });
+ expect(registerBidAdapterStub.firstCall.args[1]).to.equal(CODE);
+ expect(registerBidAdapterStub.secondCall.args[1]).to.equal('foo')
+ expect(registerBidAdapterStub.thirdCall.args[1]).to.equal('bar')
});
- });
-});
-describe('registerBidder', function () {
- let registerBidAdapterStub;
- let aliasBidAdapterStub;
+ it('should register alias with their gvlid', function() {
+ const aliases = [
+ {
+ code: 'foo',
+ gvlid: 1
+ },
+ {
+ code: 'bar',
+ gvlid: 2
+ },
+ {
+ code: 'baz'
+ }
+ ]
+ const thisSpec = Object.assign(newEmptySpec(), { aliases: aliases });
+ registerBidder(thisSpec);
- beforeEach(function () {
- registerBidAdapterStub = sinon.stub(adapterManager, 'registerBidAdapter');
- aliasBidAdapterStub = sinon.stub(adapterManager, 'aliasBidAdapter');
- });
+ expect(registerBidAdapterStub.getCall(1).args[0].getSpec().gvlid).to.equal(1);
+ expect(registerBidAdapterStub.getCall(2).args[0].getSpec().gvlid).to.equal(2);
+ expect(registerBidAdapterStub.getCall(3).args[0].getSpec().gvlid).to.equal(undefined);
+ })
- afterEach(function () {
- registerBidAdapterStub.restore();
- aliasBidAdapterStub.restore();
- });
+ it('should register alias with skipPbsAliasing', function() {
+ const aliases = [
+ {
+ code: 'foo',
+ skipPbsAliasing: true
+ },
+ {
+ code: 'bar',
+ skipPbsAliasing: false
+ },
+ {
+ code: 'baz'
+ }
+ ]
+ const thisSpec = Object.assign(newEmptySpec(), { aliases: aliases });
+ registerBidder(thisSpec);
- function newEmptySpec() {
- return {
- code: CODE,
- isBidRequestValid: function() { },
- buildRequests: function() { },
- interpretResponse: function() { },
- };
- }
-
- it('should register a bidder with the adapterManager', function () {
- registerBidder(newEmptySpec());
- expect(registerBidAdapterStub.calledOnce).to.equal(true);
- expect(registerBidAdapterStub.firstCall.args[0]).to.have.property('callBids');
- expect(registerBidAdapterStub.firstCall.args[0].callBids).to.be.a('function');
-
- expect(registerBidAdapterStub.firstCall.args[1]).to.equal(CODE);
- expect(registerBidAdapterStub.firstCall.args[2]).to.be.undefined;
- });
+ expect(registerBidAdapterStub.getCall(1).args[0].getSpec().skipPbsAliasing).to.equal(true);
+ expect(registerBidAdapterStub.getCall(2).args[0].getSpec().skipPbsAliasing).to.equal(false);
+ expect(registerBidAdapterStub.getCall(3).args[0].getSpec().skipPbsAliasing).to.equal(undefined);
+ })
+ })
- it('should register a bidder with the appropriate mediaTypes', function () {
- const thisSpec = Object.assign(newEmptySpec(), { supportedMediaTypes: ['video'] });
- registerBidder(thisSpec);
- expect(registerBidAdapterStub.calledOnce).to.equal(true);
- expect(registerBidAdapterStub.firstCall.args[2]).to.deep.equal({supportedMediaTypes: ['video']});
- });
+ describe('validate bid response: ', function () {
+ let spec;
+ let indexStub, adUnits, bidderRequests;
+ let addBidResponseStub;
+ let doneStub;
+ let ajaxStub;
+ let logErrorSpy;
+
+ let bids = [{
+ 'ad': 'creative',
+ 'cpm': '1.99',
+ 'width': 300,
+ 'height': 250,
+ 'requestId': '1',
+ 'creativeId': 'some-id',
+ 'currency': 'USD',
+ 'netRevenue': true,
+ 'ttl': 360
+ }];
+
+ beforeEach(function () {
+ spec = {
+ code: CODE,
+ isBidRequestValid: sinon.stub(),
+ buildRequests: sinon.stub(),
+ interpretResponse: sinon.stub(),
+ };
- it('should register bidders with the appropriate aliases', function () {
- const thisSpec = Object.assign(newEmptySpec(), { aliases: ['foo', 'bar'] });
- registerBidder(thisSpec);
+ spec.isBidRequestValid.returns(true);
+ spec.buildRequests.returns({
+ method: 'POST',
+ url: 'test.url.com',
+ data: {}
+ });
- expect(registerBidAdapterStub.calledThrice).to.equal(true);
+ addBidResponseStub = sinon.stub();
+ addBidResponseStub.reject = sinon.stub();
+ doneStub = sinon.stub();
+ ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) {
+ const fakeResponse = sinon.stub();
+ fakeResponse.returns('headerContent');
+ callbacks.success('response body', { getResponseHeader: fakeResponse });
+ });
+ logErrorSpy = sinon.spy(utils, 'logError');
+ indexStub = sinon.stub(auctionManager, 'index');
+ adUnits = [];
+ bidderRequests = [];
+ indexStub.get(() => stubAuctionIndex({adUnits: adUnits, bidderRequests: bidderRequests}))
+ });
- // Make sure our later calls don't override the bidder code from previous calls.
- expect(registerBidAdapterStub.firstCall.args[0].getBidderCode()).to.equal(CODE);
- expect(registerBidAdapterStub.secondCall.args[0].getBidderCode()).to.equal('foo')
- expect(registerBidAdapterStub.thirdCall.args[0].getBidderCode()).to.equal('bar')
+ afterEach(function () {
+ ajaxStub.restore();
+ logErrorSpy.restore();
+ indexStub.restore;
+ });
- expect(registerBidAdapterStub.firstCall.args[1]).to.equal(CODE);
- expect(registerBidAdapterStub.secondCall.args[1]).to.equal('foo')
- expect(registerBidAdapterStub.thirdCall.args[1]).to.equal('bar')
- });
+ if (FEATURES.NATIVE) {
+ it('should add native bids that do have required assets', function () {
+ adUnits = [{
+ transactionId: 'au',
+ nativeParams: {
+ title: {'required': true},
+ }
+ }]
+ decorateAdUnitsWithNativeParams(adUnits);
+ let bidRequest = {
+ bids: [{
+ bidId: '1',
+ auctionId: 'first-bid-id',
+ adUnitCode: 'mock/placement',
+ transactionId: 'au',
+ params: {
+ param: 5
+ },
+ mediaType: 'native',
+ }]
+ };
- it('should register alias with their gvlid', function() {
- const aliases = [
- {
- code: 'foo',
- gvlid: 1
- },
- {
- code: 'bar',
- gvlid: 2
- },
- {
- code: 'baz'
- }
- ]
- const thisSpec = Object.assign(newEmptySpec(), { aliases: aliases });
- registerBidder(thisSpec);
+ let bids1 = Object.assign({},
+ bids[0],
+ {
+ 'mediaType': 'native',
+ 'native': {
+ 'title': 'Native Creative',
+ 'clickUrl': 'https://www.link.example',
+ }
+ }
+ );
- expect(registerBidAdapterStub.getCall(1).args[0].getSpec().gvlid).to.equal(1);
- expect(registerBidAdapterStub.getCall(2).args[0].getSpec().gvlid).to.equal(2);
- expect(registerBidAdapterStub.getCall(3).args[0].getSpec().gvlid).to.equal(undefined);
- })
+ const bidder = newBidder(spec);
- it('should register alias with skipPbsAliasing', function() {
- const aliases = [
- {
- code: 'foo',
- skipPbsAliasing: true
- },
- {
- code: 'bar',
- skipPbsAliasing: false
- },
- {
- code: 'baz'
- }
- ]
- const thisSpec = Object.assign(newEmptySpec(), { aliases: aliases });
- registerBidder(thisSpec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(registerBidAdapterStub.getCall(1).args[0].getSpec().skipPbsAliasing).to.equal(true);
- expect(registerBidAdapterStub.getCall(2).args[0].getSpec().skipPbsAliasing).to.equal(false);
- expect(registerBidAdapterStub.getCall(3).args[0].getSpec().skipPbsAliasing).to.equal(undefined);
- })
-})
+ expect(addBidResponseStub.calledOnce).to.equal(true);
+ expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
+ expect(logErrorSpy.callCount).to.equal(0);
+ });
-describe('validate bid response: ', function () {
- let spec;
- let indexStub, adUnits, bidderRequests;
- let addBidResponseStub;
- let doneStub;
- let ajaxStub;
- let logErrorSpy;
-
- let bids = [{
- 'ad': 'creative',
- 'cpm': '1.99',
- 'width': 300,
- 'height': 250,
- 'requestId': '1',
- 'creativeId': 'some-id',
- 'currency': 'USD',
- 'netRevenue': true,
- 'ttl': 360
- }];
-
- beforeEach(function () {
- spec = {
- code: CODE,
- isBidRequestValid: sinon.stub(),
- buildRequests: sinon.stub(),
- interpretResponse: sinon.stub(),
- };
-
- spec.isBidRequestValid.returns(true);
- spec.buildRequests.returns({
- method: 'POST',
- url: 'test.url.com',
- data: {}
- });
+ it('should not add native bids that do not have required assets', function () {
+ adUnits = [{
+ transactionId: 'au',
+ nativeParams: {
+ title: {'required': true},
+ },
+ }];
+ decorateAdUnitsWithNativeParams(adUnits);
+ let bidRequest = {
+ bids: [{
+ bidId: '1',
+ auctionId: 'first-bid-id',
+ adUnitCode: 'mock/placement',
+ transactionId: 'au',
+ params: {
+ param: 5
+ },
+ mediaType: 'native',
+ }]
+ };
+ let bids1 = Object.assign({},
+ bids[0],
+ {
+ bidderCode: CODE,
+ mediaType: 'native',
+ native: {
+ title: undefined,
+ clickUrl: 'https://www.link.example',
+ }
+ }
+ );
- addBidResponseStub = sinon.stub();
- addBidResponseStub.reject = sinon.stub();
- doneStub = sinon.stub();
- ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) {
- const fakeResponse = sinon.stub();
- fakeResponse.returns('headerContent');
- callbacks.success('response body', { getResponseHeader: fakeResponse });
- });
- logErrorSpy = sinon.spy(utils, 'logError');
- indexStub = sinon.stub(auctionManager, 'index');
- adUnits = [];
- bidderRequests = [];
- indexStub.get(() => stubAuctionIndex({adUnits: adUnits, bidderRequests: bidderRequests}))
- });
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- afterEach(function () {
- ajaxStub.restore();
- logErrorSpy.restore();
- indexStub.restore;
- });
+ expect(addBidResponseStub.called).to.equal(false);
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ expect(logErrorSpy.calledWithMatch('Ignoring bid: Native bid missing some required properties.')).to.equal(true);
+ });
+ }
- if (FEATURES.NATIVE) {
- it('should add native bids that do have required assets', function () {
+ it('should add bid when renderer is present on outstream bids', function () {
adUnits = [{
transactionId: 'au',
- nativeParams: {
- title: {'required': true},
+ mediaTypes: {
+ video: {context: 'outstream'}
}
}]
- decorateAdUnitsWithNativeParams(adUnits);
let bidRequest = {
bids: [{
bidId: '1',
auctionId: 'first-bid-id',
- adUnitCode: 'mock/placement',
transactionId: 'au',
+ adUnitCode: 'mock/placement',
params: {
param: 5
},
- mediaType: 'native',
}]
};
let bids1 = Object.assign({},
bids[0],
{
- 'mediaType': 'native',
- 'native': {
- 'title': 'Native Creative',
- 'clickUrl': 'https://www.link.example',
- }
+ bidderCode: CODE,
+ mediaType: 'video',
+ renderer: {render: () => true, url: 'render.js'},
}
);
@@ -1095,413 +1206,335 @@ describe('validate bid response: ', function () {
expect(logErrorSpy.callCount).to.equal(0);
});
- it('should not add native bids that do not have required assets', function () {
- adUnits = [{
- transactionId: 'au',
- nativeParams: {
- title: {'required': true},
- },
- }];
- decorateAdUnitsWithNativeParams(adUnits);
+ it('should add banner bids that have no width or height but single adunit size', function () {
let bidRequest = {
bids: [{
+ bidder: CODE,
bidId: '1',
auctionId: 'first-bid-id',
adUnitCode: 'mock/placement',
- transactionId: 'au',
params: {
param: 5
},
- mediaType: 'native',
+ sizes: [[300, 250]],
}]
};
+ bidderRequests = [bidRequest];
let bids1 = Object.assign({},
bids[0],
{
- bidderCode: CODE,
- mediaType: 'native',
- native: {
- title: undefined,
- clickUrl: 'https://www.link.example',
- }
+ width: undefined,
+ height: undefined
}
);
const bidder = newBidder(spec);
+
spec.interpretResponse.returns(bids1);
bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(addBidResponseStub.called).to.equal(false);
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
- expect(logErrorSpy.calledWithMatch('Ignoring bid: Native bid missing some required properties.')).to.equal(true);
+ expect(addBidResponseStub.calledOnce).to.equal(true);
+ expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
+ expect(logErrorSpy.callCount).to.equal(0);
});
- }
-
- it('should add bid when renderer is present on outstream bids', function () {
- adUnits = [{
- transactionId: 'au',
- mediaTypes: {
- video: {context: 'outstream'}
- }
- }]
- let bidRequest = {
- bids: [{
- bidId: '1',
- auctionId: 'first-bid-id',
- transactionId: 'au',
- adUnitCode: 'mock/placement',
- params: {
- param: 5
- },
- }]
- };
-
- let bids1 = Object.assign({},
- bids[0],
- {
- bidderCode: CODE,
- mediaType: 'video',
- renderer: {render: () => true, url: 'render.js'},
- }
- );
-
- const bidder = newBidder(spec);
-
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
-
- expect(addBidResponseStub.calledOnce).to.equal(true);
- expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
- expect(logErrorSpy.callCount).to.equal(0);
- });
-
- it('should add banner bids that have no width or height but single adunit size', function () {
- let bidRequest = {
- bids: [{
- bidder: CODE,
- bidId: '1',
- auctionId: 'first-bid-id',
- adUnitCode: 'mock/placement',
- params: {
- param: 5
- },
- sizes: [[300, 250]],
- }]
- };
- bidderRequests = [bidRequest];
- let bids1 = Object.assign({},
- bids[0],
- {
- width: undefined,
- height: undefined
- }
- );
-
- const bidder = newBidder(spec);
-
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
-
- expect(addBidResponseStub.calledOnce).to.equal(true);
- expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
- expect(logErrorSpy.callCount).to.equal(0);
- });
-
- it('should disregard auctionId/transactionId set by the adapter', () => {
- let bidderRequest = {
- bids: [{
- bidder: CODE,
- bidId: '1',
- auctionId: 'aid',
- transactionId: 'tid',
- adUnitCode: 'au',
- }]
- };
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(Object.assign({}, bids[0], {transactionId: 'ignored', auctionId: 'ignored'}));
- bidder.callBids(bidderRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- sinon.assert.calledWith(addBidResponseStub, sinon.match.any, sinon.match({
- transactionId: 'tid',
- auctionId: 'aid'
- }));
- })
-
- describe(' Check for alternateBiddersList ', function() {
- let bidRequest;
- let bids1;
- let logWarnSpy;
- let bidderSettingStub, aliasRegistryStub;
- let aliasRegistry;
- beforeEach(function () {
- bidRequest = {
+ it('should disregard auctionId/transactionId set by the adapter', () => {
+ let bidderRequest = {
bids: [{
- bidId: '1',
bidder: CODE,
- auctionId: 'first-bid-id',
- adUnitCode: 'mock/placement',
- transactionId: 'au',
+ bidId: '1',
+ auctionId: 'aid',
+ transactionId: 'tid',
+ adUnitCode: 'au',
}]
};
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(Object.assign({}, bids[0], {transactionId: 'ignored', auctionId: 'ignored'}));
+ bidder.callBids(bidderRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ sinon.assert.calledWith(addBidResponseStub, sinon.match.any, sinon.match({
+ transactionId: 'tid',
+ auctionId: 'aid'
+ }));
+ })
- bids1 = Object.assign({},
- bids[0],
- {
- bidderCode: 'validalternatebidder',
- adapterCode: 'knownadapter1'
- }
- );
- logWarnSpy = sinon.spy(utils, 'logWarn');
- bidderSettingStub = sinon.stub(bidderSettings, 'get');
- aliasRegistry = {};
- aliasRegistryStub = sinon.stub(adapterManager, 'aliasRegistry');
- aliasRegistryStub.get(() => aliasRegistry);
- });
+ describe(' Check for alternateBiddersList ', function() {
+ let bidRequest;
+ let bids1;
+ let logWarnSpy;
+ let bidderSettingStub, aliasRegistryStub;
+ let aliasRegistry;
- afterEach(function () {
- logWarnSpy.restore();
- bidderSettingStub.restore();
- aliasRegistryStub.restore();
- });
+ beforeEach(function () {
+ bidRequest = {
+ bids: [{
+ bidId: '1',
+ bidder: CODE,
+ auctionId: 'first-bid-id',
+ adUnitCode: 'mock/placement',
+ transactionId: 'au',
+ }]
+ };
- it('should log warning when bidder is unknown and allowAlternateBidderCodes flag is false', function () {
- bidderSettingStub.returns(false);
+ bids1 = Object.assign({},
+ bids[0],
+ {
+ bidderCode: 'validalternatebidder',
+ adapterCode: 'knownadapter1'
+ }
+ );
+ logWarnSpy = sinon.spy(utils, 'logWarn');
+ bidderSettingStub = sinon.stub(bidderSettings, 'get');
+ aliasRegistry = {};
+ aliasRegistryStub = sinon.stub(adapterManager, 'aliasRegistry');
+ aliasRegistryStub.get(() => aliasRegistry);
+ });
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ afterEach(function () {
+ logWarnSpy.restore();
+ bidderSettingStub.restore();
+ aliasRegistryStub.restore();
+ });
- expect(addBidResponseStub.called).to.equal(false);
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
- expect(logWarnSpy.callCount).to.equal(1);
- });
+ it('should log warning when bidder is unknown and allowAlternateBidderCodes flag is false', function () {
+ bidderSettingStub.returns(false);
- it('should reject the bid, when allowAlternateBidderCodes flag is undefined (default should be false)', function () {
- bidderSettingStub.returns(undefined);
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(addBidResponseStub.called).to.equal(false);
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ expect(logWarnSpy.callCount).to.equal(1);
+ });
- expect(addBidResponseStub.called).to.equal(false);
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
- });
+ it('should reject the bid, when allowAlternateBidderCodes flag is undefined (default should be false)', function () {
+ bidderSettingStub.returns(undefined);
- it('should log warning when the particular bidder is not specified in allowedAlternateBidderCodes and allowAlternateBidderCodes flag is true', function () {
- bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
- bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(['invalidAlternateBidder02']);
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(addBidResponseStub.called).to.equal(false);
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ });
- expect(addBidResponseStub.called).to.equal(false);
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
- expect(logWarnSpy.callCount).to.equal(1);
- });
+ it('should log warning when the particular bidder is not specified in allowedAlternateBidderCodes and allowAlternateBidderCodes flag is true', function () {
+ bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
+ bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(['invalidAlternateBidder02']);
- it('should accept the bid, when allowedAlternateBidderCodes is empty and allowAlternateBidderCodes flag is true', function () {
- bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
- bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns();
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(addBidResponseStub.called).to.equal(false);
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ expect(logWarnSpy.callCount).to.equal(1);
+ });
- expect(addBidResponseStub.calledOnce).to.equal(true);
- expect(logWarnSpy.callCount).to.equal(0);
- expect(logErrorSpy.callCount).to.equal(0);
- });
+ it('should accept the bid, when allowedAlternateBidderCodes is empty and allowAlternateBidderCodes flag is true', function () {
+ bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
+ bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns();
- it('should accept the bid, when allowedAlternateBidderCodes is marked as * and allowAlternateBidderCodes flag is true', function () {
- bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
- bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(['*']);
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(addBidResponseStub.calledOnce).to.equal(true);
+ expect(logWarnSpy.callCount).to.equal(0);
+ expect(logErrorSpy.callCount).to.equal(0);
+ });
- expect(addBidResponseStub.calledOnce).to.equal(true);
- expect(logWarnSpy.callCount).to.equal(0);
- expect(logErrorSpy.callCount).to.equal(0);
- });
+ it('should accept the bid, when allowedAlternateBidderCodes is marked as * and allowAlternateBidderCodes flag is true', function () {
+ bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
+ bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(['*']);
- it('should accept the bid, when allowedAlternateBidderCodes is marked as * (with space) and allowAlternateBidderCodes flag is true', function () {
- bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
- bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns([' * ']);
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(addBidResponseStub.calledOnce).to.equal(true);
+ expect(logWarnSpy.callCount).to.equal(0);
+ expect(logErrorSpy.callCount).to.equal(0);
+ });
- expect(addBidResponseStub.calledOnce).to.equal(true);
- expect(logWarnSpy.callCount).to.equal(0);
- expect(logErrorSpy.callCount).to.equal(0);
- });
+ it('should accept the bid, when allowedAlternateBidderCodes is marked as * (with space) and allowAlternateBidderCodes flag is true', function () {
+ bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
+ bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns([' * ']);
+
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should not accept the bid, when allowedAlternateBidderCodes is marked as empty array and allowAlternateBidderCodes flag is true', function () {
- bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
- bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns([]);
+ expect(addBidResponseStub.calledOnce).to.equal(true);
+ expect(logWarnSpy.callCount).to.equal(0);
+ expect(logErrorSpy.callCount).to.equal(0);
+ });
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should not accept the bid, when allowedAlternateBidderCodes is marked as empty array and allowAlternateBidderCodes flag is true', function () {
+ bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
+ bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns([]);
- expect(addBidResponseStub.called).to.equal(false);
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
- expect(logWarnSpy.callCount).to.equal(1);
- });
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should accept the bid, when allowedAlternateBidderCodes contains bidder name and allowAlternateBidderCodes flag is true', function () {
- bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
- bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(['validAlternateBidder']);
+ expect(addBidResponseStub.called).to.equal(false);
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ expect(logWarnSpy.callCount).to.equal(1);
+ });
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should accept the bid, when allowedAlternateBidderCodes contains bidder name and allowAlternateBidderCodes flag is true', function () {
+ bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(true);
+ bidderSettingStub.withArgs(CODE, 'allowedAlternateBidderCodes').returns(['validAlternateBidder']);
- expect(addBidResponseStub.called).to.equal(true);
- expect(logWarnSpy.callCount).to.equal(0);
- expect(logErrorSpy.callCount).to.equal(0);
- });
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should not accept the bid, when bidder is an alias but bidderSetting is missing for the bidder. It should fallback to standard setting and reject the bid', function () {
- bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(false);
- aliasRegistry = {'validAlternateBidder': CODE};
+ expect(addBidResponseStub.called).to.equal(true);
+ expect(logWarnSpy.callCount).to.equal(0);
+ expect(logErrorSpy.callCount).to.equal(0);
+ });
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should not accept the bid, when bidder is an alias but bidderSetting is missing for the bidder. It should fallback to standard setting and reject the bid', function () {
+ bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(false);
+ aliasRegistry = {'validAlternateBidder': CODE};
- expect(addBidResponseStub.called).to.equal(false);
- expect(logWarnSpy.callCount).to.equal(1);
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
- });
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should not accept the bid, when bidderSetting is missing for the bidder. It should fallback to standard setting and reject the bid', function () {
- bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(false);
+ expect(addBidResponseStub.called).to.equal(false);
+ expect(logWarnSpy.callCount).to.equal(1);
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ });
- const bidder = newBidder(spec);
- spec.interpretResponse.returns(bids1);
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ it('should not accept the bid, when bidderSetting is missing for the bidder. It should fallback to standard setting and reject the bid', function () {
+ bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(false);
+
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns(bids1);
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(addBidResponseStub.called).to.equal(false);
- expect(addBidResponseStub.reject.calledOnce).to.be.true;
- expect(logWarnSpy.callCount).to.equal(1);
+ expect(addBidResponseStub.called).to.equal(false);
+ expect(addBidResponseStub.reject.calledOnce).to.be.true;
+ expect(logWarnSpy.callCount).to.equal(1);
+ });
});
- });
- describe('when interpretResponse returns BidderAuctionResponse', function() {
- const bidRequest = {
- bids: [{
+ describe('when interpretResponse returns BidderAuctionResponse', function() {
+ const bidRequest = {
+ auctionId: 'aid',
+ bids: [{
+ bidId: '1',
+ bidder: CODE,
+ auctionId: 'aid',
+ adUnitCode: 'mock/placement',
+ transactionId: 'au',
+ }]
+ };
+ const fledgeAuctionConfig = {
bidId: '1',
- bidder: CODE,
- auctionId: 'first-bid-id',
- adUnitCode: 'mock/placement',
- transactionId: 'au',
- }]
- };
- const fledgeAuctionConfig = {
- bidId: '1',
- config: {
- foo: 'bar'
- }
- }
- describe('when response has FLEDGE auction config', function() {
- let fledgeStub;
-
- function fledgeHook(next, ...args) {
- fledgeStub(...args);
+ config: {
+ foo: 'bar'
+ }
}
+ describe('when response has FLEDGE auction config', function() {
+ let fledgeStub;
- before(() => {
- addComponentAuction.before(fledgeHook);
- });
+ function fledgeHook(next, ...args) {
+ fledgeStub(...args);
+ }
- after(() => {
- addComponentAuction.getHooks({hook: fledgeHook}).remove();
- })
+ before(() => {
+ addComponentAuction.before(fledgeHook);
+ });
- beforeEach(function () {
- fledgeStub = sinon.stub();
- });
+ after(() => {
+ addComponentAuction.getHooks({hook: fledgeHook}).remove();
+ })
- it('should unwrap bids', function() {
- const bidder = newBidder(spec);
- spec.interpretResponse.returns({
- bids: bids,
- fledgeAuctionConfigs: []
+ beforeEach(function () {
+ fledgeStub = sinon.stub();
});
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(addBidResponseStub.calledOnce).to.equal(true);
- expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
- });
- it('should call fledgeManager with FLEDGE configs', function() {
- const bidder = newBidder(spec);
- spec.interpretResponse.returns({
- bids: bids,
- fledgeAuctionConfigs: [fledgeAuctionConfig]
+ it('should unwrap bids', function() {
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns({
+ bids: bids,
+ fledgeAuctionConfigs: []
+ });
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(addBidResponseStub.calledOnce).to.equal(true);
+ expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
});
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- expect(fledgeStub.calledOnce).to.equal(true);
- sinon.assert.calledWith(fledgeStub, 'mock/placement', fledgeAuctionConfig.config);
- expect(addBidResponseStub.calledOnce).to.equal(true);
- expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
- })
+ it('should call fledgeManager with FLEDGE configs', function() {
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns({
+ bids: bids,
+ fledgeAuctionConfigs: [fledgeAuctionConfig]
+ });
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
- it('should call fledgeManager with FLEDGE configs even if no bids returned', function() {
- const bidder = newBidder(spec);
- spec.interpretResponse.returns({
- bids: [],
- fledgeAuctionConfigs: [fledgeAuctionConfig]
- });
- bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+ expect(fledgeStub.calledOnce).to.equal(true);
+ sinon.assert.calledWith(fledgeStub, bidRequest.bids[0], fledgeAuctionConfig.config);
+ expect(addBidResponseStub.calledOnce).to.equal(true);
+ expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement');
+ })
- expect(fledgeStub.calledOnce).to.be.true;
- sinon.assert.calledWith(fledgeStub, 'mock/placement', fledgeAuctionConfig.config);
- expect(addBidResponseStub.calledOnce).to.equal(false);
+ it('should call fledgeManager with FLEDGE configs even if no bids returned', function() {
+ const bidder = newBidder(spec);
+ spec.interpretResponse.returns({
+ bids: [],
+ fledgeAuctionConfigs: [fledgeAuctionConfig]
+ });
+ bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback);
+
+ expect(fledgeStub.calledOnce).to.be.true;
+ sinon.assert.calledWith(fledgeStub, bidRequest.bids[0], fledgeAuctionConfig.config);
+ expect(addBidResponseStub.calledOnce).to.equal(false);
+ })
})
})
- })
-});
+ });
-describe('bid response isValid', () => {
- describe('size check', () => {
- let req, index;
+ describe('bid response isValid', () => {
+ describe('size check', () => {
+ let req, index;
- beforeEach(() => {
- req = {
- ...MOCK_BIDS_REQUEST.bids[0],
- mediaTypes: {
- banner: {
- sizes: [[1, 2], [3, 4]]
+ beforeEach(() => {
+ req = {
+ ...MOCK_BIDS_REQUEST.bids[0],
+ mediaTypes: {
+ banner: {
+ sizes: [[1, 2], [3, 4]]
+ }
}
}
- }
- });
+ });
- function mkResponse(width, height) {
- return {
- requestId: req.bidId,
- width,
- height,
- cpm: 1,
- ttl: 60,
- creativeId: '123',
- netRevenue: true,
- currency: 'USD',
- mediaType: 'banner',
+ function mkResponse(width, height) {
+ return {
+ requestId: req.bidId,
+ width,
+ height,
+ cpm: 1,
+ ttl: 60,
+ creativeId: '123',
+ netRevenue: true,
+ currency: 'USD',
+ mediaType: 'banner',
+ }
}
- }
- function checkValid(bid) {
- return isValid('au', bid, {index: stubAuctionIndex({bidRequests: [req]})});
- }
+ function checkValid(bid) {
+ return isValid('au', bid, {index: stubAuctionIndex({bidRequests: [req]})});
+ }
- it('should succeed when response has a size that was in request', () => {
- expect(checkValid(mkResponse(3, 4))).to.be.true;
- });
- })
-});
+ it('should succeed when response has a size that was in request', () => {
+ expect(checkValid(mkResponse(3, 4))).to.be.true;
+ });
+ })
+ });
+})
diff --git a/test/spec/unit/core/events_spec.js b/test/spec/unit/core/events_spec.js
new file mode 100644
index 00000000000..e1451f657b5
--- /dev/null
+++ b/test/spec/unit/core/events_spec.js
@@ -0,0 +1,45 @@
+import {config} from 'src/config.js';
+import {emit, clearEvents, getEvents, on, off} from '../../../../src/events.js';
+import * as utils from '../../../../src/utils.js'
+
+describe('events', () => {
+ let clock;
+ beforeEach(() => {
+ clock = sinon.useFakeTimers();
+ clearEvents();
+ });
+ afterEach(() => {
+ clock.restore();
+ });
+
+ it('should clear event log using eventHistoryTTL config', () => {
+ emit('testEvent', {});
+ expect(getEvents().length).to.eql(1);
+ config.setConfig({eventHistoryTTL: 1});
+ clock.tick(500);
+ expect(getEvents().length).to.eql(1);
+ clock.tick(6000);
+ expect(getEvents().length).to.eql(0);
+ });
+
+ it('should take history TTL in seconds', () => {
+ emit('testEvent', {});
+ 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/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js
index f16d6208087..ba9aeff70d1 100644
--- a/test/spec/unit/core/targeting_spec.js
+++ b/test/spec/unit/core/targeting_spec.js
@@ -1,13 +1,19 @@
-import { expect } from 'chai';
-import { targeting as targetingInstance, filters, getHighestCpmBidsFromBidPool, sortByDealAndPriceBucketOrCpm } from 'src/targeting.js';
-import { config } from 'src/config.js';
-import { createBidReceived } from 'test/fixtures/fixtures.js';
+import {expect} from 'chai';
+import {
+ filters,
+ getHighestCpmBidsFromBidPool,
+ sortByDealAndPriceBucketOrCpm,
+ targeting as targetingInstance
+} from 'src/targeting.js';
+import {config} from 'src/config.js';
+import {createBidReceived} from 'test/fixtures/fixtures.js';
import CONSTANTS from 'src/constants.json';
-import { auctionManager } from 'src/auctionManager.js';
+import {auctionManager} from 'src/auctionManager.js';
import * as utils from 'src/utils.js';
import {deepClone} from 'src/utils.js';
import {createBid} from '../../../../src/bidfactory.js';
import {hook} from '../../../../src/hook.js';
+import {getHighestCpm} from '../../../../src/utils/reducers.js';
function mkBid(bid, status = CONSTANTS.STATUS.GOOD) {
return Object.assign(createBid(status), bid);
@@ -451,7 +457,7 @@ describe('targeting tests', function () {
}
});
- const bids = getHighestCpmBidsFromBidPool(bidsReceived, utils.getHighestCpm, 2);
+ const bids = getHighestCpmBidsFromBidPool(bidsReceived, getHighestCpm, 2);
expect(bids.length).to.equal(3);
expect(bids[0].adId).to.equal('8383838');
@@ -467,7 +473,7 @@ describe('targeting tests', function () {
}
});
- const bids = getHighestCpmBidsFromBidPool(bidsReceived, utils.getHighestCpm, 2);
+ const bids = getHighestCpmBidsFromBidPool(bidsReceived, getHighestCpm, 2);
expect(bids.length).to.equal(3);
expect(bids[0].adId).to.equal('8383838');
@@ -949,6 +955,7 @@ describe('targeting tests', function () {
expect(bids.length).to.equal(1);
expect(bids[0].adId).to.equal('adid-1');
+ expect(bids[0].latestTargetedAuctionId).to.equal(2);
useBidCache = false;
@@ -956,6 +963,7 @@ describe('targeting tests', function () {
expect(bids.length).to.equal(1);
expect(bids[0].adId).to.equal('adid-2');
+ expect(bids[0].latestTargetedAuctionId).to.equal(2);
});
it('should use bidCacheFilterFunction', function() {
@@ -983,9 +991,13 @@ describe('targeting tests', function () {
expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-1');
+ expect(bids[0].latestTargetedAuctionId).to.equal(2);
expect(bids[1].adId).to.equal('adid-4');
+ expect(bids[1].latestTargetedAuctionId).to.equal(2);
expect(bids[2].adId).to.equal('adid-5');
+ expect(bids[2].latestTargetedAuctionId).to.equal(2);
expect(bids[3].adId).to.equal('adid-8');
+ expect(bids[3].latestTargetedAuctionId).to.equal(2);
// Bid Caching Off, No Filter Function
useBidCache = false;
@@ -994,9 +1006,13 @@ describe('targeting tests', function () {
expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-2');
+ expect(bids[0].latestTargetedAuctionId).to.equal(2);
expect(bids[1].adId).to.equal('adid-4');
+ expect(bids[1].latestTargetedAuctionId).to.equal(2);
expect(bids[2].adId).to.equal('adid-6');
+ expect(bids[2].latestTargetedAuctionId).to.equal(2);
expect(bids[3].adId).to.equal('adid-8');
+ expect(bids[3].latestTargetedAuctionId).to.equal(2);
// Bid Caching On AGAIN, No Filter Function (should be same as first time)
useBidCache = true;
@@ -1005,9 +1021,13 @@ describe('targeting tests', function () {
expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-1');
+ expect(bids[0].latestTargetedAuctionId).to.equal(2);
expect(bids[1].adId).to.equal('adid-4');
+ expect(bids[1].latestTargetedAuctionId).to.equal(2);
expect(bids[2].adId).to.equal('adid-5');
+ expect(bids[2].latestTargetedAuctionId).to.equal(2);
expect(bids[3].adId).to.equal('adid-8');
+ expect(bids[3].latestTargetedAuctionId).to.equal(2);
// Bid Caching On, with Filter Function to Exclude video
useBidCache = true;
@@ -1020,9 +1040,13 @@ describe('targeting tests', function () {
expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-1');
+ expect(bids[0].latestTargetedAuctionId).to.equal(2);
expect(bids[1].adId).to.equal('adid-4');
+ expect(bids[1].latestTargetedAuctionId).to.equal(2);
expect(bids[2].adId).to.equal('adid-6');
+ expect(bids[2].latestTargetedAuctionId).to.equal(2);
expect(bids[3].adId).to.equal('adid-8');
+ expect(bids[3].latestTargetedAuctionId).to.equal(2);
// filter function should have been called for each cached bid (4 times)
expect(bcffCalled).to.equal(4);
@@ -1038,9 +1062,13 @@ describe('targeting tests', function () {
expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-2');
+ expect(bids[0].latestTargetedAuctionId).to.equal(2);
expect(bids[1].adId).to.equal('adid-4');
+ expect(bids[1].latestTargetedAuctionId).to.equal(2);
expect(bids[2].adId).to.equal('adid-6');
+ expect(bids[2].latestTargetedAuctionId).to.equal(2);
expect(bids[3].adId).to.equal('adid-8');
+ expect(bids[3].latestTargetedAuctionId).to.equal(2);
// filter function should not have been called
expect(bcffCalled).to.equal(0);
});
diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js
index 5c361d186c0..39123d4aa41 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';
@@ -25,7 +25,7 @@ import {stubAuctionIndex} from '../../helpers/indexStub.js';
import {createBid} from '../../../src/bidfactory.js';
import {enrichFPD} from '../../../src/fpd/enrichment.js';
import {mockFpdEnrichments} from '../../helpers/fpd.js';
-
+import {generateUUID} from '../../../src/utils.js';
var assert = require('chai').assert;
var expect = require('chai').expect;
@@ -43,13 +43,13 @@ var adUnits = getAdUnits();
var adUnitCodes = getAdUnits().map(unit => unit.code);
var bidsBackHandler = function() {};
const timeout = 2000;
-var auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout: timeout});
-auction.getBidRequests = getBidRequests;
-auction.getBidsReceived = getBidResponses;
-auction.getAdUnits = getAdUnits;
-auction.getAuctionStatus = function() { return auctionModule.AUCTION_COMPLETED }
+const auctionId = generateUUID();
+let auction;
function resetAuction() {
+ if (auction == null) {
+ auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout: timeout, labels: undefined, auctionId: auctionId});
+ }
$$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: false });
auction.getBidRequests = getBidRequests;
auction.getBidsReceived = getBidResponses;
@@ -1104,7 +1104,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 +1233,8 @@ describe('Unit: Prebid Module', function () {
}
},
getElementsByTagName: sinon.stub(),
- querySelector: sinon.stub()
+ querySelector: sinon.stub(),
+ createElement: sinon.stub(),
};
elStub = {
@@ -1264,7 +1265,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 +1290,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 +1305,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 +1326,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 +1345,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({
@@ -2736,6 +2728,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;
@@ -3304,16 +3303,20 @@ describe('Unit: Prebid Module', function () {
const highestBid = $$PREBID_GLOBAL$$.getHighestUnusedBidResponseForAdUnitCode('/19968336/header-bid-tag-0');
expect(highestBid).to.deep.equal(_bidsReceived[2])
})
- })
+ });
- describe('getHighestCpm', () => {
+ describe('getHighestCpmBids', () => {
after(() => {
resetAuction();
});
it('returns an array containing the highest bid object for the given adUnitCode', function () {
- const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0');
+ const adUnitcode = '/19968336/header-bid-tag-0';
+ targeting.setLatestAuctionForAdUnit(adUnitcode, auctionId)
+ const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids(adUnitcode);
expect(highestCpmBids.length).to.equal(1);
- expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]);
+ const expectedBid = auctionManager.getBidsReceived()[1];
+ expectedBid.latestTargetedAuctionId = auctionId;
+ expect(highestCpmBids[0]).to.deep.equal(expectedBid);
});
it('returns an empty array when the given adUnit is not found', function () {
diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js
index 7d5f9af35dd..895bf03165a 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,10 +6,11 @@ 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');
@@ -54,37 +53,45 @@ 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();
+ it('does not invoke renderFn, but the renderer instead, if the ad has one', () => {
+ const renderer = {
+ url: 'some-custom-renderer',
+ render: sinon.spy()
+ }
+ handleRender(renderFn, {bidResponse: {renderer}});
+ sinon.assert.notCalled(renderFn);
+ sinon.assert.called(renderer.render);
});
- 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/reducers_spec.js b/test/spec/unit/utils/reducers_spec.js
new file mode 100644
index 00000000000..95bf3b74041
--- /dev/null
+++ b/test/spec/unit/utils/reducers_spec.js
@@ -0,0 +1,124 @@
+import {
+ tiebreakCompare,
+ keyCompare,
+ simpleCompare,
+ minimum,
+ maximum,
+ getHighestCpm,
+ getOldestHighestCpmBid, getLatestHighestCpmBid, reverseCompare
+} from '../../../../src/utils/reducers.js';
+import assert from 'assert';
+
+describe('reducers', () => {
+ describe('simpleCompare', () => {
+ Object.entries({
+ '<': [10, 20, -1],
+ '===': [123, 123, 0],
+ '>': [30, -10, 1]
+ }).forEach(([t, [a, b, expected]]) => {
+ it(`returns ${expected} when a ${t} b`, () => {
+ expect(simpleCompare(a, b)).to.equal(expected);
+ })
+ })
+ });
+
+ describe('keyCompare', () => {
+ Object.entries({
+ '<': [{k: -123}, {k: 0}, -1],
+ '===': [{k: 0}, {k: 0}, 0],
+ '>': [{k: 2}, {k: 1}, 1]
+ }).forEach(([t, [a, b, expected]]) => {
+ it(`returns ${expected} when key(a) ${t} key(b)`, () => {
+ expect(keyCompare(item => item.k)(a, b)).to.equal(expected);
+ })
+ })
+ });
+
+ describe('tiebreakCompare', () => {
+ Object.entries({
+ 'first compare says a < b': [{main: 1, tie: 2}, {main: 2, tie: 1}, -1],
+ 'first compare says a > b': [{main: 2, tie: 1}, {main: 1, tie: 2}, 1],
+ 'first compare ties, second says a < b': [{main: 0, tie: 1}, {main: 0, tie: 2}, -1],
+ 'first compare ties, second says a > b': [{main: 0, tie: 2}, {main: 0, tie: 1}, 1],
+ 'all compares tie': [{main: 0, tie: 0}, {main: 0, tie: 0}, 0]
+ }).forEach(([t, [a, b, expected]]) => {
+ it(`should return ${expected} when ${t}`, () => {
+ const cmp = tiebreakCompare(keyCompare(item => item.main), keyCompare(item => item.tie));
+ expect(cmp(a, b)).to.equal(expected);
+ })
+ })
+ });
+
+ const SAMPLE_ARR = [-10, 20, 20, 123, 400];
+
+ Object.entries({
+ 'minimum': [minimum, ['minimum', -10], ['maximum', 400]],
+ 'maximum': [maximum, ['maximum', 400], ['minimum', -10]]
+ }).forEach(([t, [fn, simple, reversed]]) => {
+ describe(t, () => {
+ it(`should find ${simple[0]} using simple compare`, () => {
+ expect(SAMPLE_ARR.reduce(fn(simpleCompare))).to.equal(simple[1]);
+ });
+ it(`should find ${reversed[0]} using reverse compare`, () => {
+ expect(SAMPLE_ARR.reduce(fn(reverseCompare()))).to.equal(reversed[1]);
+ });
+ })
+ });
+
+ describe('getHighestCpm', function () {
+ it('should pick the highest cpm', function () {
+ let a = {
+ cpm: 2,
+ timeToRespond: 100
+ };
+ let b = {
+ cpm: 1,
+ timeToRespond: 100
+ };
+ expect(getHighestCpm(a, b)).to.eql(a);
+ expect(getHighestCpm(b, a)).to.eql(a);
+ });
+
+ it('should pick the lowest timeToRespond cpm in case of tie', function () {
+ let a = {
+ cpm: 1,
+ timeToRespond: 100
+ };
+ let b = {
+ cpm: 1,
+ timeToRespond: 50
+ };
+ expect(getHighestCpm(a, b)).to.eql(b);
+ expect(getHighestCpm(b, a)).to.eql(b);
+ });
+ });
+
+ describe('getOldestHighestCpmBid', () => {
+ it('should pick the oldest in case of tie using responseTimeStamp', function () {
+ let a = {
+ cpm: 1,
+ responseTimestamp: 1000
+ };
+ let b = {
+ cpm: 1,
+ responseTimestamp: 2000
+ };
+ expect(getOldestHighestCpmBid(a, b)).to.eql(a);
+ expect(getOldestHighestCpmBid(b, a)).to.eql(a);
+ });
+ });
+ describe('getLatestHighestCpmBid', () => {
+ it('should pick the latest in case of tie using responseTimeStamp', function () {
+ let a = {
+ cpm: 1,
+ responseTimestamp: 1000
+ };
+ let b = {
+ cpm: 1,
+ responseTimestamp: 2000
+ };
+ expect(getLatestHighestCpmBid(a, b)).to.eql(b);
+ expect(getLatestHighestCpmBid(b, a)).to.eql(b);
+ });
+ });
+})
diff --git a/test/spec/unit/utils/ttlCollection_spec.js b/test/spec/unit/utils/ttlCollection_spec.js
new file mode 100644
index 00000000000..29c6c438855
--- /dev/null
+++ b/test/spec/unit/utils/ttlCollection_spec.js
@@ -0,0 +1,180 @@
+import {ttlCollection} from '../../../../src/utils/ttlCollection.js';
+
+describe('ttlCollection', () => {
+ it('can add & retrieve items', () => {
+ const coll = ttlCollection();
+ expect(coll.toArray()).to.eql([]);
+ coll.add(1);
+ coll.add(2);
+ expect(coll.toArray()).to.eql([1, 2]);
+ });
+
+ it('can clear', () => {
+ const coll = ttlCollection();
+ coll.add('item');
+ coll.clear();
+ expect(coll.toArray()).to.eql([]);
+ });
+
+ it('can be iterated over', () => {
+ const coll = ttlCollection();
+ coll.add('1');
+ coll.add('2');
+ expect(Array.from(coll)).to.eql(['1', '2']);
+ })
+
+ describe('autopurge', () => {
+ let clock, pms, waitForPromises;
+ const SLACK = 2000;
+ beforeEach(() => {
+ clock = sinon.useFakeTimers();
+ pms = [];
+ waitForPromises = () => Promise.all(pms);
+ });
+ afterEach(() => {
+ clock.restore();
+ });
+
+ Object.entries({
+ 'defer': (value) => {
+ const pm = Promise.resolve(value);
+ pms.push(pm);
+ return pm;
+ },
+ 'do not defer': (value) => value,
+ }).forEach(([t, resolve]) => {
+ describe(`when ttl/startTime ${t}`, () => {
+ let coll;
+ beforeEach(() => {
+ coll = ttlCollection({
+ startTime: (item) => resolve(item.start == null ? new Date().getTime() : item.start),
+ ttl: (item) => resolve(item.ttl),
+ slack: SLACK
+ })
+ });
+
+ it('should clear items after enough time has passed', () => {
+ coll.add({no: 'ttl'});
+ coll.add({ttl: 1000});
+ coll.add({ttl: 4000});
+ return waitForPromises().then(() => {
+ clock.tick(500);
+ expect(coll.toArray()).to.eql([{no: 'ttl'}, {ttl: 1000}, {ttl: 4000}]);
+ clock.tick(SLACK + 500);
+ expect(coll.toArray()).to.eql([{no: 'ttl'}, {ttl: 4000}]);
+ clock.tick(3000);
+ expect(coll.toArray()).to.eql([{no: 'ttl'}]);
+ });
+ });
+
+ it('should not wait too long if a shorter ttl shows up', () => {
+ coll.add({ttl: 4000});
+ coll.add({ttl: 1000});
+ return waitForPromises().then(() => {
+ clock.tick(1000 + SLACK);
+ expect(coll.toArray()).to.eql([
+ {ttl: 4000}
+ ]);
+ });
+ });
+
+ it('should not wait more if later ttls are within slack', () => {
+ coll.add({start: 0, ttl: 4000});
+ return waitForPromises().then(() => {
+ clock.tick(4000);
+ coll.add({start: 0, ttl: 5000});
+ return waitForPromises().then(() => {
+ clock.tick(SLACK);
+ expect(coll.toArray()).to.eql([]);
+ });
+ });
+ });
+
+ it('should clear items ASAP if they expire in the past', () => {
+ clock.tick(10000);
+ coll.add({start: 0, ttl: 1000});
+ return waitForPromises().then(() => {
+ clock.tick(SLACK);
+ expect(coll.toArray()).to.eql([]);
+ });
+ });
+
+ it('should clear items ASAP if they have ttl = 0', () => {
+ coll.add({ttl: 0});
+ return waitForPromises().then(() => {
+ clock.tick(SLACK);
+ expect(coll.toArray()).to.eql([]);
+ });
+ });
+
+ describe('refresh', () => {
+ it('should refresh missing TTLs', () => {
+ const item = {};
+ coll.add(item);
+ return waitForPromises().then(() => {
+ item.ttl = 1000;
+ return waitForPromises().then(() => {
+ clock.tick(1000 + SLACK);
+ expect(coll.toArray()).to.eql([item]);
+ coll.refresh();
+ return waitForPromises().then(() => {
+ clock.tick(1);
+ expect(coll.toArray()).to.eql([]);
+ });
+ });
+ });
+ });
+
+ it('should refresh existing TTLs', () => {
+ const item = {
+ ttl: 1000
+ };
+ coll.add(item);
+ return waitForPromises().then(() => {
+ clock.tick(1000);
+ item.ttl = 4000;
+ coll.refresh();
+ return waitForPromises().then(() => {
+ clock.tick(SLACK);
+ expect(coll.toArray()).to.eql([item]);
+ clock.tick(3000);
+ expect(coll.toArray()).to.eql([]);
+ });
+ });
+ });
+
+ it('should discard initial TTL if it does not resolve before a refresh', () => {
+ let resolveTTL;
+ const item = {
+ ttl: new Promise((resolve) => {
+ resolveTTL = resolve;
+ })
+ };
+ coll.add(item);
+ item.ttl = null;
+ coll.refresh();
+ resolveTTL(1000);
+ return waitForPromises().then(() => {
+ clock.tick(1000 + SLACK + 1000);
+ expect(coll.toArray()).to.eql([item]);
+ });
+ });
+
+ it('should discard TTLs on clear', () => {
+ const item = {
+ ttl: 1000
+ };
+ coll.add(item);
+ coll.clear();
+ item.ttl = null;
+ coll.add(item);
+ return waitForPromises().then(() => {
+ clock.tick(1000 + SLACK + 1000);
+ expect(coll.toArray()).to.eql([item]);
+ });
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js
index e26683074c8..098582c0af6 100644
--- a/test/spec/utils_spec.js
+++ b/test/spec/utils_spec.js
@@ -2,7 +2,9 @@ import {getAdServerTargeting} from 'test/fixtures/fixtures.js';
import {expect} from 'chai';
import CONSTANTS from 'src/constants.json';
import * as utils from 'src/utils.js';
-import {deepEqual, memoize, waitForElementToLoad} from 'src/utils.js';
+import {getHighestCpm, getLatestHighestCpmBid, getOldestHighestCpmBid} from '../../src/utils/reducers.js';
+import {binarySearch, deepEqual, memoize, waitForElementToLoad} from 'src/utils.js';
+import {convertCamelToUnderscore} from '../../libraries/appnexusUtils/anUtils.js';
var assert = require('assert');
@@ -39,28 +41,6 @@ describe('Utils', function () {
});
});
- describe('tryAppendQueryString', function () {
- it('should append query string to existing url', function () {
- var url = 'www.a.com?';
- var key = 'b';
- var value = 'c';
-
- var output = utils.tryAppendQueryString(url, key, value);
-
- var expectedResult = url + key + '=' + encodeURIComponent(value) + '&';
- assert.equal(output, expectedResult);
- });
-
- it('should return existing url, if the value is empty', function () {
- var url = 'www.a.com?';
- var key = 'b';
- var value = '';
-
- var output = utils.tryAppendQueryString(url, key, value);
- assert.equal(output, url);
- });
- });
-
describe('parseQueryStringParameters', function () {
it('should append query string to existing using the input obj', function () {
var obj = {
@@ -538,72 +518,6 @@ describe('Utils', function () {
});
});
- describe('getHighestCpm', function () {
- it('should pick the existing highest cpm', function () {
- let previous = {
- cpm: 2,
- timeToRespond: 100
- };
- let current = {
- cpm: 1,
- timeToRespond: 100
- };
- assert.equal(utils.getHighestCpm(previous, current), previous);
- });
-
- it('should pick the new highest cpm', function () {
- let previous = {
- cpm: 1,
- timeToRespond: 100
- };
- let current = {
- cpm: 2,
- timeToRespond: 100
- };
- assert.equal(utils.getHighestCpm(previous, current), current);
- });
-
- it('should pick the fastest cpm in case of tie', function () {
- let previous = {
- cpm: 1,
- timeToRespond: 100
- };
- let current = {
- cpm: 1,
- timeToRespond: 50
- };
- assert.equal(utils.getHighestCpm(previous, current), current);
- });
-
- it('should pick the oldest in case of tie using responseTimeStamp', function () {
- let previous = {
- cpm: 1,
- timeToRespond: 100,
- responseTimestamp: 1000
- };
- let current = {
- cpm: 1,
- timeToRespond: 50,
- responseTimestamp: 2000
- };
- assert.equal(utils.getOldestHighestCpmBid(previous, current), previous);
- });
-
- it('should pick the latest in case of tie using responseTimeStamp', function () {
- let previous = {
- cpm: 1,
- timeToRespond: 100,
- responseTimestamp: 1000
- };
- let current = {
- cpm: 1,
- timeToRespond: 50,
- responseTimestamp: 2000
- };
- assert.equal(utils.getLatestHighestCpmBid(previous, current), current);
- });
- });
-
describe('polyfill test', function () {
it('should not add polyfill to array', function() {
var arr = ['hello', 'world'];
@@ -765,43 +679,15 @@ describe('Utils', function () {
describe('convertCamelToUnderscore', function () {
it('returns converted string value using underscore syntax instead of camelCase', function () {
let var1 = 'placementIdTest';
- let test1 = utils.convertCamelToUnderscore(var1);
+ let test1 = convertCamelToUnderscore(var1);
expect(test1).to.equal('placement_id_test');
let var2 = 'my_test_value';
- let test2 = utils.convertCamelToUnderscore(var2);
+ let test2 = convertCamelToUnderscore(var2);
expect(test2).to.equal(var2);
});
});
- describe('getAdUnitSizes', function () {
- it('returns an empty response when adUnits is undefined', function () {
- let sizes = utils.getAdUnitSizes();
- expect(sizes).to.be.undefined;
- });
-
- it('returns an empty array when invalid data is present in adUnit object', function () {
- let sizes = utils.getAdUnitSizes({ sizes: 300 });
- expect(sizes).to.deep.equal([]);
- });
-
- it('retuns an array of arrays when reading from adUnit.sizes', function () {
- let sizes = utils.getAdUnitSizes({ sizes: [300, 250] });
- expect(sizes).to.deep.equal([[300, 250]]);
-
- sizes = utils.getAdUnitSizes({ sizes: [[300, 250], [300, 600]] });
- expect(sizes).to.deep.equal([[300, 250], [300, 600]]);
- });
-
- it('returns an array of arrays when reading from adUnit.mediaTypes.banner.sizes', function () {
- let sizes = utils.getAdUnitSizes({ mediaTypes: { banner: { sizes: [300, 250] } } });
- expect(sizes).to.deep.equal([[300, 250]]);
-
- sizes = utils.getAdUnitSizes({ mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] } } });
- expect(sizes).to.deep.equal([[300, 250], [300, 600]]);
- });
- });
-
describe('URL helpers', function () {
describe('parseUrl()', function () {
let parsed;
@@ -1233,5 +1119,44 @@ describe('memoize', () => {
mem('one', 'three');
expect(mem('one', 'three')).to.eql(['one', 'three']);
expect(fn.callCount).to.eql(2);
- })
+ });
+
+ describe('binarySearch', () => {
+ [
+ {
+ arr: [],
+ tests: [
+ ['any', 0]
+ ]
+ },
+ {
+ arr: [10],
+ tests: [
+ [5, 0],
+ [10, 0],
+ [20, 1],
+ ],
+ },
+ {
+ arr: [10, 20, 30, 30, 40],
+ tests: [
+ [5, 0],
+ [15, 1],
+ [10, 0],
+ [30, 2],
+ [35, 4],
+ [40, 4],
+ [100, 5]
+ ]
+ }
+ ].forEach(({arr, tests}) => {
+ describe(`on ${arr}`, () => {
+ tests.forEach(([el, pos]) => {
+ it(`finds index for ${el} => ${pos}`, () => {
+ expect(binarySearch(arr, el)).to.equal(pos);
+ });
+ });
+ });
+ })
+ });
})
diff --git a/test/spec/video_spec.js b/test/spec/video_spec.js
index 61621c7ec42..35d0a4fef24 100644
--- a/test/spec/video_spec.js
+++ b/test/spec/video_spec.js
@@ -1,4 +1,4 @@
-import { isValidVideoBid } from 'src/video.js';
+import {fillVideoDefaults, isValidVideoBid} from 'src/video.js';
import {hook} from '../../src/hook.js';
import {stubAuctionIndex} from '../helpers/indexStub.js';
@@ -7,97 +7,169 @@ describe('video.js', function () {
hook.ready();
});
- it('validates valid instream bids', function () {
- const bid = {
- adId: '456xyz',
- vastUrl: 'http://www.example.com/vastUrl',
- transactionId: 'au'
- };
- const adUnits = [{
- transactionId: 'au',
- mediaTypes: {
- video: {context: 'instream'}
- }
- }];
- const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
- expect(valid).to.equal(true);
- });
+ describe('fillVideoDefaults', () => {
+ function fillDefaults(videoMediaType = {}) {
+ const adUnit = {mediaTypes: {video: videoMediaType}};
+ fillVideoDefaults(adUnit);
+ return adUnit.mediaTypes.video;
+ }
- it('catches invalid instream bids', function () {
- const bid = {
- transactionId: 'au'
- };
- const adUnits = [{
- transactionId: 'au',
- mediaTypes: {
- video: {context: 'instream'}
- }
- }];
- const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
- expect(valid).to.equal(false);
- });
+ describe('should set plcmt = 4 when', () => {
+ it('context is "outstream"', () => {
+ expect(fillDefaults({context: 'outstream'})).to.eql({
+ context: 'outstream',
+ plcmt: 4
+ })
+ });
+ [2, 3, 4].forEach(placement => {
+ it(`placemement is "${placement}"`, () => {
+ expect(fillDefaults({placement})).to.eql({
+ placement,
+ plcmt: 4
+ });
+ })
+ });
+ });
+ describe('should set plcmt = 2 when', () => {
+ [2, 6].forEach(playbackmethod => {
+ it(`playbackmethod is "${playbackmethod}"`, () => {
+ expect(fillDefaults({playbackmethod})).to.eql({
+ playbackmethod,
+ plcmt: 2,
+ });
+ });
+ });
+ });
+ describe('should not set plcmt when', () => {
+ Object.entries({
+ 'it was set by pub (context=outstream)': {
+ expected: 1,
+ video: {
+ context: 'outstream',
+ plcmt: 1
+ }
+ },
+ 'it was set by pub (placement=2)': {
+ expected: 1,
+ video: {
+ placement: 2,
+ plcmt: 1
+ }
+ },
+ 'placement not in 2, 3, 4': {
+ expected: undefined,
+ video: {
+ placement: 1
+ }
+ },
+ 'it was set by pub (playbackmethod=2)': {
+ expected: 1,
+ video: {
+ plcmt: 1,
+ playbackmethod: 2
+ }
+ }
+ }).forEach(([t, {expected, video}]) => {
+ it(t, () => {
+ expect(fillDefaults(video).plcmt).to.eql(expected);
+ })
+ })
+ })
+ })
- it('catches invalid bids when prebid-cache is disabled', function () {
- const adUnits = [{
- transactionId: 'au',
- bidder: 'vastOnlyVideoBidder',
- mediaTypes: {video: {}},
- }];
+ describe('isValidVideoBid', () => {
+ it('validates valid instream bids', function () {
+ const bid = {
+ adId: '456xyz',
+ vastUrl: 'http://www.example.com/vastUrl',
+ transactionId: 'au'
+ };
+ const adUnits = [{
+ transactionId: 'au',
+ mediaTypes: {
+ video: {context: 'instream'}
+ }
+ }];
+ const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
+ expect(valid).to.equal(true);
+ });
- const valid = isValidVideoBid({ transactionId: 'au', vastXml: 'vast' }, {index: stubAuctionIndex({adUnits})});
+ it('catches invalid instream bids', function () {
+ const bid = {
+ transactionId: 'au'
+ };
+ const adUnits = [{
+ transactionId: 'au',
+ mediaTypes: {
+ video: {context: 'instream'}
+ }
+ }];
+ const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
+ expect(valid).to.equal(false);
+ });
- expect(valid).to.equal(false);
- });
+ it('catches invalid bids when prebid-cache is disabled', function () {
+ const adUnits = [{
+ transactionId: 'au',
+ bidder: 'vastOnlyVideoBidder',
+ mediaTypes: {video: {}},
+ }];
- it('validates valid outstream bids', function () {
- const bid = {
- transactionId: 'au',
- renderer: {
- url: 'render.url',
- render: () => true,
- }
- };
- const adUnits = [{
- transactionId: 'au',
- mediaTypes: {
- video: {context: 'outstream'}
- }
- }];
- const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
- expect(valid).to.equal(true);
- });
+ const valid = isValidVideoBid({ transactionId: 'au', vastXml: 'vast' }, {index: stubAuctionIndex({adUnits})});
- it('validates valid outstream bids with a publisher defined renderer', function () {
- const bid = {
- transactionId: 'au',
- };
- const adUnits = [{
- transactionId: 'au',
- mediaTypes: {
- video: {
- context: 'outstream',
+ expect(valid).to.equal(false);
+ });
+
+ it('validates valid outstream bids', function () {
+ const bid = {
+ transactionId: 'au',
+ renderer: {
+ url: 'render.url',
+ render: () => true,
}
- },
- renderer: {
- url: 'render.url',
- render: () => true,
- }
- }];
- const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
- expect(valid).to.equal(true);
- });
+ };
+ const adUnits = [{
+ transactionId: 'au',
+ mediaTypes: {
+ video: {context: 'outstream'}
+ }
+ }];
+ const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
+ expect(valid).to.equal(true);
+ });
- it('catches invalid outstream bids', function () {
- const bid = {
- transactionId: 'au',
- };
- const adUnits = [{
- transactionId: 'au',
- mediaTypes: {
- video: {context: 'outstream'}
- }
- }];
- const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
- expect(valid).to.equal(false);
- });
+ it('validates valid outstream bids with a publisher defined renderer', function () {
+ const bid = {
+ transactionId: 'au',
+ };
+ const adUnits = [{
+ transactionId: 'au',
+ mediaTypes: {
+ video: {
+ context: 'outstream',
+ }
+ },
+ renderer: {
+ url: 'render.url',
+ render: () => true,
+ }
+ }];
+ const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
+ expect(valid).to.equal(true);
+ });
+
+ it('catches invalid outstream bids', function () {
+ const bid = {
+ transactionId: 'au',
+ };
+ const adUnits = [{
+ transactionId: 'au',
+ mediaTypes: {
+ video: {context: 'outstream'}
+ }
+ }];
+ const valid = isValidVideoBid(bid, {index: stubAuctionIndex({adUnits})});
+ expect(valid).to.equal(false);
+ });
+ })
});
diff --git a/test/test_deps.js b/test/test_deps.js
index 35713106f8c..c8a3bcc9426 100644
--- a/test/test_deps.js
+++ b/test/test_deps.js
@@ -4,6 +4,16 @@ window.process = {
}
};
+window.addEventListener('error', function (ev) {
+ // eslint-disable-next-line no-console
+ console.error('Uncaught exception:', ev.error, ev.error?.stack);
+})
+
+window.addEventListener('unhandledrejection', function (ev) {
+ // eslint-disable-next-line no-console
+ console.error('Unhandled rejection:', ev.reason);
+})
+
require('test/helpers/consentData.js');
require('test/helpers/prebidGlobal.js');
require('test/mocks/adloaderStub.js');
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'),
+ },
+}