prebid.js 7.52.0 → 7.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/dist/1plusXRtdProvider.js +1 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/adagioBidAdapter.js +1 -1
  5. package/dist/adbookpspBidAdapter.js +1 -1
  6. package/dist/adgenerationBidAdapter.js +1 -1
  7. package/dist/adhashBidAdapter.js +1 -1
  8. package/dist/adkernelBidAdapter.js +1 -1
  9. package/dist/adqueryBidAdapter.js +1 -1
  10. package/dist/adrelevantisBidAdapter.js +1 -1
  11. package/dist/adtrgtmeBidAdapter.js +1 -1
  12. package/dist/adxcgBidAdapter.js +1 -1
  13. package/dist/adyoulikeBidAdapter.js +1 -1
  14. package/dist/airgridRtdProvider.js +1 -1
  15. package/dist/ajaBidAdapter.js +1 -1
  16. package/dist/amxBidAdapter.js +1 -1
  17. package/dist/amxIdSystem.js +1 -1
  18. package/dist/appierAnalyticsAdapter.js +1 -1
  19. package/dist/appnexusBidAdapter.js +1 -1
  20. package/dist/asoBidAdapter.js +1 -1
  21. package/dist/axonixBidAdapter.js +1 -1
  22. package/dist/beopBidAdapter.js +1 -1
  23. package/dist/bidglassBidAdapter.js +1 -1
  24. package/dist/big-richmediaBidAdapter.js +1 -1
  25. package/dist/bridgewellBidAdapter.js +1 -1
  26. package/dist/brightMountainMediaBidAdapter.js +1 -1
  27. package/dist/carodaBidAdapter.js +1 -1
  28. package/dist/chtnwBidAdapter.js +1 -1
  29. package/dist/conceptxBidAdapter.js +1 -0
  30. package/dist/concertBidAdapter.js +1 -1
  31. package/dist/connectadBidAdapter.js +1 -1
  32. package/dist/consumableBidAdapter.js +1 -1
  33. package/dist/conversantAnalyticsAdapter.js +1 -1
  34. package/dist/conversantBidAdapter.js +1 -1
  35. package/dist/craftBidAdapter.js +1 -1
  36. package/dist/criteoBidAdapter.js +1 -1
  37. package/dist/cwireBidAdapter.js +1 -1
  38. package/dist/dspxBidAdapter.js +1 -1
  39. package/dist/eplanningBidAdapter.js +1 -1
  40. package/dist/eskimiBidAdapter.js +1 -1
  41. package/dist/euidIdSystem.js +1 -0
  42. package/dist/feedadBidAdapter.js +1 -1
  43. package/dist/finativeBidAdapter.js +1 -1
  44. package/dist/freepassIdSystem.js +1 -0
  45. package/dist/freewheel-sspBidAdapter.js +1 -1
  46. package/dist/glimpseBidAdapter.js +1 -1
  47. package/dist/gmosspBidAdapter.js +1 -1
  48. package/dist/goldbachBidAdapter.js +1 -1
  49. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  50. package/dist/greenbidsRtdProvider.js +1 -1
  51. package/dist/gridBidAdapter.js +1 -1
  52. package/dist/gumgumBidAdapter.js +1 -1
  53. package/dist/h12mediaBidAdapter.js +1 -1
  54. package/dist/hypelabBidAdapter.js +1 -0
  55. package/dist/id5IdSystem.js +1 -1
  56. package/dist/improvedigitalBidAdapter.js +1 -1
  57. package/dist/inmarBidAdapter.js +1 -1
  58. package/dist/insticatorBidAdapter.js +1 -1
  59. package/dist/ixBidAdapter.js +1 -1
  60. package/dist/justpremiumBidAdapter.js +1 -1
  61. package/dist/kargoBidAdapter.js +1 -1
  62. package/dist/konduitAnalyticsAdapter.js +1 -1
  63. package/dist/kueezBidAdapter.js +1 -1
  64. package/dist/kueezRtbBidAdapter.js +1 -1
  65. package/dist/kulturemediaBidAdapter.js +1 -1
  66. package/dist/lassoBidAdapter.js +1 -1
  67. package/dist/lifestreetBidAdapter.js +1 -1
  68. package/dist/limelightDigitalBidAdapter.js +1 -1
  69. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  70. package/dist/logicadBidAdapter.js +1 -1
  71. package/dist/loglyliftBidAdapter.js +1 -1
  72. package/dist/magniteAnalyticsAdapter.js +1 -1
  73. package/dist/malltvAnalyticsAdapter.js +1 -1
  74. package/dist/marsmediaBidAdapter.js +1 -1
  75. package/dist/mediafuseBidAdapter.js +1 -1
  76. package/dist/mediasquareBidAdapter.js +1 -1
  77. package/dist/mgidBidAdapter.js +1 -1
  78. package/dist/minutemediaBidAdapter.js +1 -1
  79. package/dist/minutemediaplusBidAdapter.js +1 -1
  80. package/dist/nexx360BidAdapter.js +1 -1
  81. package/dist/not-for-prod/prebid.js +153 -148
  82. package/dist/oguryBidAdapter.js +1 -1
  83. package/dist/onetagBidAdapter.js +1 -1
  84. package/dist/ooloAnalyticsAdapter.js +1 -1
  85. package/dist/optidigitalBidAdapter.js +1 -1
  86. package/dist/outbrainBidAdapter.js +1 -1
  87. package/dist/oxxionRtdProvider.js +1 -1
  88. package/dist/pairIdSystem.js +1 -1
  89. package/dist/parrableIdSystem.js +1 -1
  90. package/dist/pixfutureBidAdapter.js +1 -1
  91. package/dist/prebid-core.js +1 -1
  92. package/dist/proxistoreBidAdapter.js +1 -1
  93. package/dist/publinkIdSystem.js +1 -1
  94. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  95. package/dist/pubmaticBidAdapter.js +1 -1
  96. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  97. package/dist/pxyzBidAdapter.js +1 -1
  98. package/dist/quantcastBidAdapter.js +1 -1
  99. package/dist/readpeakBidAdapter.js +1 -1
  100. package/dist/relaidoBidAdapter.js +1 -1
  101. package/dist/retailspotBidAdapter.js +1 -1
  102. package/dist/rhythmoneBidAdapter.js +1 -1
  103. package/dist/richaudienceBidAdapter.js +1 -1
  104. package/dist/riseBidAdapter.js +1 -1
  105. package/dist/rubiconAnalyticsAdapter.js +1 -1
  106. package/dist/rubiconBidAdapter.js +1 -1
  107. package/dist/schain.js +1 -1
  108. package/dist/seedingAllianceBidAdapter.js +1 -1
  109. package/dist/seedtagBidAdapter.js +1 -1
  110. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  111. package/dist/sharethroughBidAdapter.js +1 -1
  112. package/dist/shinezBidAdapter.js +1 -1
  113. package/dist/sirdataRtdProvider.js +1 -1
  114. package/dist/smaatoBidAdapter.js +1 -1
  115. package/dist/smartadserverBidAdapter.js +1 -1
  116. package/dist/smartxBidAdapter.js +1 -1
  117. package/dist/smilewantedBidAdapter.js +1 -1
  118. package/dist/sonobiBidAdapter.js +1 -1
  119. package/dist/sovrnAnalyticsAdapter.js +1 -1
  120. package/dist/sovrnBidAdapter.js +1 -1
  121. package/dist/sspBCBidAdapter.js +1 -1
  122. package/dist/stroeerCoreBidAdapter.js +1 -1
  123. package/dist/stvBidAdapter.js +1 -1
  124. package/dist/sublimeBidAdapter.js +1 -1
  125. package/dist/synacormediaBidAdapter.js +1 -1
  126. package/dist/targetVideoBidAdapter.js +1 -1
  127. package/dist/teadsBidAdapter.js +1 -1
  128. package/dist/topicsFpdModule.js +1 -1
  129. package/dist/trionBidAdapter.js +1 -1
  130. package/dist/tripleliftBidAdapter.js +1 -1
  131. package/dist/ttdBidAdapter.js +1 -1
  132. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  133. package/dist/uid2IdSystem.js +1 -1
  134. package/dist/uid2IdSystem_shared.js +1 -0
  135. package/dist/underdogmediaBidAdapter.js +1 -1
  136. package/dist/undertoneBidAdapter.js +1 -1
  137. package/dist/userId.js +1 -1
  138. package/dist/vidazooBidAdapter.js +1 -1
  139. package/dist/videobyteBidAdapter.js +1 -1
  140. package/dist/videojsVideoProvider.js +1 -1
  141. package/dist/viouslyBidAdapter.js +1 -1
  142. package/dist/visxBidAdapter.js +1 -1
  143. package/dist/vrtcalBidAdapter.js +1 -1
  144. package/dist/vuukleBidAdapter.js +1 -1
  145. package/dist/weboramaRtdProvider.js +1 -1
  146. package/dist/widespaceBidAdapter.js +1 -1
  147. package/dist/winrBidAdapter.js +1 -1
  148. package/dist/yahoosspBidAdapter.js +1 -1
  149. package/dist/yieldlabBidAdapter.js +1 -1
  150. package/dist/yieldmoBidAdapter.js +1 -1
  151. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  152. package/dist/zeta_global_sspBidAdapter.js +1 -1
  153. package/integrationExamples/gpt/userId_example.html +20 -6
  154. package/modules/.submodules.json +3 -1
  155. package/modules/1plusXRtdProvider.js +31 -60
  156. package/modules/adagioBidAdapter.js +86 -24
  157. package/modules/adhashBidAdapter.js +56 -34
  158. package/modules/adkernelBidAdapter.js +2 -2
  159. package/modules/airgridRtdProvider.js +11 -12
  160. package/modules/asoBidAdapter.js +2 -1
  161. package/modules/beopBidAdapter.js +6 -0
  162. package/modules/conceptxBidAdapter.js +70 -0
  163. package/modules/conceptxBidAdapter.md +36 -0
  164. package/modules/criteoBidAdapter.js +9 -2
  165. package/modules/eskimiBidAdapter.js +171 -41
  166. package/modules/eskimiBidAdapter.md +35 -16
  167. package/modules/euidIdSystem.js +121 -0
  168. package/modules/euidIdSystem.md +131 -0
  169. package/modules/freepassIdSystem.js +61 -0
  170. package/modules/freepassIdSystem.md +47 -0
  171. package/modules/greenbidsAnalyticsAdapter.js +1 -1
  172. package/modules/hypelabBidAdapter.js +153 -0
  173. package/modules/hypelabBidAdapter.md +38 -0
  174. package/modules/id5IdSystem.js +3 -5
  175. package/modules/ixBidAdapter.js +12 -1
  176. package/modules/limelightDigitalBidAdapter.js +1 -1
  177. package/modules/logicadBidAdapter.js +14 -1
  178. package/modules/mediasquareBidAdapter.js +13 -5
  179. package/modules/nexx360BidAdapter.js +1 -0
  180. package/modules/oxxionRtdProvider.js +7 -29
  181. package/modules/pairIdSystem.js +10 -5
  182. package/modules/proxistoreBidAdapter.js +11 -14
  183. package/modules/pubmaticAnalyticsAdapter.js +31 -8
  184. package/modules/richaudienceBidAdapter.js +10 -1
  185. package/modules/riseBidAdapter.js +1 -1
  186. package/modules/schain.js +2 -2
  187. package/modules/sirdataRtdProvider.js +73 -146
  188. package/modules/sovrnBidAdapter.js +4 -1
  189. package/modules/stroeerCoreBidAdapter.js +55 -6
  190. package/modules/teadsBidAdapter.js +0 -1
  191. package/modules/topicsFpdModule.js +4 -1
  192. package/modules/uid2IdSystem.js +27 -210
  193. package/modules/uid2IdSystem.md +104 -23
  194. package/modules/uid2IdSystem_shared.js +232 -0
  195. package/modules/userId/eids.js +8 -0
  196. package/modules/userId/userId.md +2 -1
  197. package/modules/videojsVideoProvider.js +2 -0
  198. package/modules/viouslyBidAdapter.js +2 -2
  199. package/modules/vrtcalBidAdapter.js +5 -0
  200. package/modules/weboramaRtdProvider.js +25 -95
  201. package/modules/weboramaRtdProvider.md +4 -4
  202. package/modules/yieldlabBidAdapter.js +23 -14
  203. package/modules/zeta_global_sspBidAdapter.js +27 -22
  204. package/package.json +1 -1
  205. package/src/adloader.js +1 -0
  206. package/test/spec/modules/1plusXRtdProvider_spec.js +98 -149
  207. package/test/spec/modules/adagioBidAdapter_spec.js +46 -17
  208. package/test/spec/modules/adhashBidAdapter_spec.js +18 -2
  209. package/test/spec/modules/airgridRtdProvider_spec.js +2 -0
  210. package/test/spec/modules/beopBidAdapter_spec.js +24 -0
  211. package/test/spec/modules/conceptxBidAdapter_spec.js +136 -0
  212. package/test/spec/modules/criteoBidAdapter_spec.js +1 -1
  213. package/test/spec/modules/eids_spec.js +15 -0
  214. package/test/spec/modules/eskimiBidAdapter_spec.js +264 -112
  215. package/test/spec/modules/euidIdSystem_spec.js +130 -0
  216. package/test/spec/modules/freepassIdSystem_spec.js +186 -0
  217. package/test/spec/modules/hypelabBidAdapter_spec.js +281 -0
  218. package/test/spec/modules/id5IdSystem_spec.js +10 -3
  219. package/test/spec/modules/ixBidAdapter_spec.js +30 -0
  220. package/test/spec/modules/logicadBidAdapter_spec.js +122 -2
  221. package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -0
  222. package/test/spec/modules/oxxionRtdProvider_spec.js +3 -2
  223. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +7 -0
  224. package/test/spec/modules/richaudienceBidAdapter_spec.js +44 -0
  225. package/test/spec/modules/schain_spec.js +9 -0
  226. package/test/spec/modules/sirdataRtdProvider_spec.js +110 -17
  227. package/test/spec/modules/sovrnBidAdapter_spec.js +13 -0
  228. package/test/spec/modules/stroeerCoreBidAdapter_spec.js +151 -6
  229. package/test/spec/modules/teadsBidAdapter_spec.js +7 -0
  230. package/test/spec/modules/uid2IdSystem_helpers.js +70 -0
  231. package/test/spec/modules/uid2IdSystem_spec.js +131 -86
  232. package/test/spec/modules/userId_spec.js +16 -12
  233. package/test/spec/modules/vrtcalBidAdapter_spec.js +9 -2
  234. package/test/spec/modules/weboramaRtdProvider_spec.js +331 -205
  235. package/test/spec/modules/yieldlabBidAdapter_spec.js +42 -2
  236. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +200 -4
@@ -0,0 +1,130 @@
1
+ import {coreStorage, init, setSubmoduleRegistry, requestBidsHook} from 'modules/userId/index.js';
2
+ import {config} from 'src/config.js';
3
+ import * as utils from 'src/utils.js';
4
+ import { euidIdSubmodule } from 'modules/euidIdSystem.js';
5
+ import 'modules/consentManagement.js';
6
+ import 'src/prebid.js';
7
+ import { getGlobal } from 'src/prebidGlobal.js';
8
+ import { server } from 'test/mocks/xhr.js';
9
+ import { configureTimerInterceptors } from 'test/mocks/timers.js';
10
+ import { cookieHelpers, runAuction, apiHelpers, setGdprApplies } from './uid2IdSystem_helpers.js';
11
+ import {hook} from 'src/hook.js';
12
+ import {uninstall as uninstallGdprEnforcement} from 'modules/gdprEnforcement.js';
13
+
14
+ let expect = require('chai').expect;
15
+
16
+ // N.B. Most of the EUID code is shared with UID2 - the tests here only cover the happy path.
17
+ // Most of the functionality is covered by the UID2 tests.
18
+
19
+ const moduleCookieName = '__euid_advertising_token';
20
+ const publisherCookieName = '__EUID_SERVER_COOKIE';
21
+ const initialToken = `initial-advertising-token`;
22
+ const legacyToken = 'legacy-advertising-token';
23
+ const refreshedToken = 'refreshed-advertising-token';
24
+ const auctionDelayMs = 10;
25
+
26
+ const makeEuidIdentityContainer = (token) => ({euid: {id: token}});
27
+ const useLocalStorage = true;
28
+ const makePrebidConfig = (params = null, extraSettings = {}, debug = false) => ({
29
+ userSync: { auctionDelay: auctionDelayMs, userIds: [{name: 'euid', params: {storage: useLocalStorage ? 'localStorage' : 'cookie', ...params}, ...extraSettings}] }, debug
30
+ });
31
+
32
+ const apiUrl = 'https://prod.euid.eu/v2/token/refresh';
33
+ const headers = { 'Content-Type': 'application/json' };
34
+ const makeSuccessResponseBody = () => btoa(JSON.stringify({ status: 'success', body: { ...apiHelpers.makeTokenResponse(initialToken), advertising_token: refreshedToken } }));
35
+ const configureEuidResponse = (httpStatus, response) => server.respondWith('POST', apiUrl, (xhr) => xhr.respond(httpStatus, headers, response));
36
+ const expectToken = (bid, token) => expect(bid?.userId ?? {}).to.deep.include(makeEuidIdentityContainer(token));
37
+ const expectNoIdentity = (bid) => expect(bid).to.not.haveOwnProperty('userId');
38
+
39
+ describe('EUID module', function() {
40
+ let suiteSandbox, testSandbox, timerSpy, fullTestTitle, restoreSubtleToUndefined = false;
41
+ before(function() {
42
+ uninstallGdprEnforcement();
43
+ hook.ready();
44
+ suiteSandbox = sinon.sandbox.create();
45
+ if (typeof window.crypto.subtle === 'undefined') {
46
+ restoreSubtleToUndefined = true;
47
+ window.crypto.subtle = { importKey: () => {}, decrypt: () => {} };
48
+ }
49
+ suiteSandbox.stub(window.crypto.subtle, 'importKey').callsFake(() => Promise.resolve());
50
+ suiteSandbox.stub(window.crypto.subtle, 'decrypt').callsFake((settings, key, data) => Promise.resolve(new Uint8Array([...settings.iv, ...data])));
51
+ });
52
+ after(function() {
53
+ suiteSandbox.restore();
54
+ if (restoreSubtleToUndefined) window.crypto.subtle = undefined;
55
+ });
56
+ beforeEach(function() {
57
+ init(config);
58
+ setSubmoduleRegistry([euidIdSubmodule]);
59
+ });
60
+ afterEach(function() {
61
+ $$PREBID_GLOBAL$$.requestBids.removeAll();
62
+ config.resetConfig();
63
+ cookieHelpers.clearCookies(moduleCookieName, publisherCookieName);
64
+ coreStorage.removeDataFromLocalStorage(moduleCookieName);
65
+ });
66
+
67
+ it('When a server-only token value is provided in config but consent is not available, it is not available to the auction.', async function() {
68
+ setGdprApplies();
69
+ config.setConfig(makePrebidConfig(null, {value: makeEuidIdentityContainer(initialToken)}));
70
+ const bid = await runAuction();
71
+ expectNoIdentity(bid);
72
+ });
73
+
74
+ it('When a server-only token value is provided in config, it is available to the auction.', async function() {
75
+ setGdprApplies(true);
76
+ config.setConfig(makePrebidConfig(null, {value: makeEuidIdentityContainer(initialToken)}));
77
+ const bid = await runAuction();
78
+ expectToken(bid, initialToken);
79
+ });
80
+
81
+ it('When a server-only token is provided in the module storage cookie but consent is not available, it is not available to the auction.', async function() {
82
+ setGdprApplies();
83
+ coreStorage.setCookie(moduleCookieName, legacyToken, cookieHelpers.getFutureCookieExpiry());
84
+ config.setConfig({userSync: {auctionDelay: auctionDelayMs, userIds: [{name: 'euid'}]}});
85
+ const bid = await runAuction();
86
+ expectNoIdentity(bid);
87
+ });
88
+
89
+ it('When a server-only token is provided in the module storage cookie, it is available to the auction.', async function() {
90
+ setGdprApplies(true);
91
+ coreStorage.setCookie(moduleCookieName, legacyToken, cookieHelpers.getFutureCookieExpiry());
92
+ config.setConfig({userSync: {auctionDelay: auctionDelayMs, userIds: [{name: 'euid'}]}});
93
+ const bid = await runAuction();
94
+ expectToken(bid, legacyToken);
95
+ })
96
+
97
+ it('When a valid response body is provided in config, it is available to the auction', async function() {
98
+ setGdprApplies(true);
99
+ const euidToken = apiHelpers.makeTokenResponse(initialToken, false, false);
100
+ config.setConfig(makePrebidConfig({euidToken}));
101
+ const bid = await runAuction();
102
+ expectToken(bid, initialToken);
103
+ })
104
+
105
+ it('When a valid response body is provided via cookie, it is available to the auction', async function() {
106
+ setGdprApplies(true);
107
+ const euidToken = apiHelpers.makeTokenResponse(initialToken, false, false);
108
+ cookieHelpers.setPublisherCookie(publisherCookieName, euidToken);
109
+ config.setConfig(makePrebidConfig({euidCookie: publisherCookieName}));
110
+ const bid = await runAuction();
111
+ expectToken(bid, initialToken);
112
+ })
113
+
114
+ it('When an expired token is provided in config, it calls the API.', function() {
115
+ setGdprApplies(true);
116
+ const euidToken = apiHelpers.makeTokenResponse(initialToken, true, true);
117
+ config.setConfig(makePrebidConfig({euidToken}));
118
+ expect(server.requests[0]?.url).to.have.string('https://prod.euid.eu/');
119
+ });
120
+
121
+ it('When an expired token is provided and the API responds in time, the refreshed token is provided to the auction.', async function() {
122
+ setGdprApplies(true);
123
+ const euidToken = apiHelpers.makeTokenResponse(initialToken, true, true);
124
+ configureEuidResponse(200, makeSuccessResponseBody());
125
+ config.setConfig(makePrebidConfig({euidToken}));
126
+ apiHelpers.respondAfterDelay(1);
127
+ const bid = await runAuction();
128
+ expectToken(bid, refreshedToken);
129
+ });
130
+ });
@@ -0,0 +1,186 @@
1
+ import {freepassIdSubmodule} from 'modules/freepassIdSystem';
2
+ import sinon from 'sinon';
3
+ import * as utils from '../../../src/utils';
4
+
5
+ let expect = require('chai').expect;
6
+
7
+ describe('FreePass ID System', function () {
8
+ const UUID = '15fde1dc-1861-4894-afdf-b757272f3568';
9
+
10
+ before(function () {
11
+ sinon.stub(utils, 'generateUUID').returns(UUID);
12
+ sinon.stub(utils, 'logMessage');
13
+ });
14
+
15
+ after(function () {
16
+ utils.generateUUID.restore();
17
+ utils.logMessage.restore();
18
+ });
19
+
20
+ describe('freepassIdSubmodule', function () {
21
+ it('should expose submodule name', function () {
22
+ expect(freepassIdSubmodule.name).to.equal('freepassId');
23
+ });
24
+ });
25
+
26
+ describe('getId', function () {
27
+ const config = {
28
+ storage: {
29
+ name: '_freepassId',
30
+ type: 'cookie',
31
+ expires: 30
32
+ },
33
+ params: {
34
+ freepassData: {
35
+ commonId: 'commonId',
36
+ userIp: '127.0.0.1'
37
+ }
38
+ }
39
+ };
40
+
41
+ it('should return an IdObject with a UUID', function () {
42
+ const objectId = freepassIdSubmodule.getId(config, undefined);
43
+ expect(objectId).to.be.an('object');
44
+ expect(objectId.id).to.be.an('object');
45
+ expect(objectId.id.userId).to.equal(UUID);
46
+ });
47
+
48
+ it('should include userIp in IdObject', function () {
49
+ const objectId = freepassIdSubmodule.getId(config, undefined);
50
+ expect(objectId).to.be.an('object');
51
+ expect(objectId.id).to.be.an('object');
52
+ expect(objectId.id.userIp).to.equal('127.0.0.1');
53
+ });
54
+ it('should skip userIp in IdObject if not available', function () {
55
+ const localConfig = Object.assign({}, config);
56
+ delete localConfig.params.freepassData.userIp;
57
+ const objectId = freepassIdSubmodule.getId(localConfig, undefined);
58
+ expect(objectId).to.be.an('object');
59
+ expect(objectId.id).to.be.an('object');
60
+ expect(objectId.id.userIp).to.be.undefined;
61
+ });
62
+ it('should skip userIp in IdObject if freepassData is not available', function () {
63
+ const localConfig = JSON.parse(JSON.stringify(config));
64
+ delete localConfig.params.freepassData;
65
+ const objectId = freepassIdSubmodule.getId(localConfig, undefined);
66
+ expect(objectId).to.be.an('object');
67
+ expect(objectId.id).to.be.an('object');
68
+ expect(objectId.id.userIp).to.be.undefined;
69
+ });
70
+ it('should skip userIp in IdObject if params is not available', function () {
71
+ const localConfig = JSON.parse(JSON.stringify(config));
72
+ delete localConfig.params;
73
+ const objectId = freepassIdSubmodule.getId(localConfig, undefined);
74
+ expect(objectId).to.be.an('object');
75
+ expect(objectId.id).to.be.an('object');
76
+ expect(objectId.id.userIp).to.be.undefined;
77
+ });
78
+ it('should include commonId in IdObject', function () {
79
+ const objectId = freepassIdSubmodule.getId(config, undefined);
80
+ expect(objectId).to.be.an('object');
81
+ expect(objectId.id).to.be.an('object');
82
+ expect(objectId.id.commonId).to.equal('commonId');
83
+ });
84
+ it('should skip commonId in IdObject if not available', function () {
85
+ const localConfig = Object.assign({}, config);
86
+ delete localConfig.params.freepassData.commonId;
87
+ const objectId = freepassIdSubmodule.getId(localConfig, undefined);
88
+ expect(objectId).to.be.an('object');
89
+ expect(objectId.id).to.be.an('object');
90
+ expect(objectId.id.commonId).to.be.undefined;
91
+ });
92
+ it('should skip commonId in IdObject if freepassData is not available', function () {
93
+ const localConfig = JSON.parse(JSON.stringify(config));
94
+ delete localConfig.params.freepassData;
95
+ const objectId = freepassIdSubmodule.getId(localConfig, undefined);
96
+ expect(objectId).to.be.an('object');
97
+ expect(objectId.id).to.be.an('object');
98
+ expect(objectId.id.commonId).to.be.undefined;
99
+ });
100
+ it('should skip commonId in IdObject if params is not available', function () {
101
+ const localConfig = JSON.parse(JSON.stringify(config));
102
+ delete localConfig.params;
103
+ const objectId = freepassIdSubmodule.getId(localConfig, undefined);
104
+ expect(objectId).to.be.an('object');
105
+ expect(objectId.id).to.be.an('object');
106
+ expect(objectId.id.commonId).to.be.undefined;
107
+ });
108
+ });
109
+
110
+ describe('decode', function () {
111
+ it('should have module name as property', function () {
112
+ const decodedId = freepassIdSubmodule.decode({}, {});
113
+ expect(decodedId).to.be.an('object');
114
+ expect(decodedId).to.have.property('freepassId');
115
+ });
116
+ it('should have IObject as property value', function () {
117
+ const idObject = {
118
+ commonId: 'commonId',
119
+ userIp: '127.0.0.1',
120
+ userId: UUID
121
+ };
122
+ const decodedId = freepassIdSubmodule.decode(idObject, {});
123
+ expect(decodedId).to.be.an('object');
124
+ expect(decodedId.freepassId).to.be.an('object');
125
+ expect(decodedId.freepassId).to.equal(idObject);
126
+ });
127
+ });
128
+
129
+ describe('extendId', function () {
130
+ const config = {
131
+ storage: {
132
+ name: '_freepassId',
133
+ type: 'cookie',
134
+ expires: 30
135
+ },
136
+ params: {
137
+ freepassData: {
138
+ commonId: 'commonId',
139
+ userIp: '127.0.0.1'
140
+ }
141
+ }
142
+ };
143
+
144
+ it('should return cachedIdObject if there are no changes', function () {
145
+ const idObject = freepassIdSubmodule.getId(config, undefined);
146
+ const cachedIdObject = Object.assign({}, idObject.id);
147
+ const extendedIdObject = freepassIdSubmodule.extendId(config, undefined, cachedIdObject);
148
+ expect(extendedIdObject).to.be.an('object');
149
+ expect(extendedIdObject.id).to.be.an('object');
150
+ expect(extendedIdObject.id).to.equal(cachedIdObject);
151
+ });
152
+
153
+ it('should return cachedIdObject if there are no new data', function () {
154
+ const idObject = freepassIdSubmodule.getId(config, undefined);
155
+ const cachedIdObject = Object.assign({}, idObject.id);
156
+ const localConfig = JSON.parse(JSON.stringify(config));
157
+ delete localConfig.params.freepassData;
158
+ const extendedIdObject = freepassIdSubmodule.extendId(localConfig, undefined, cachedIdObject);
159
+ expect(extendedIdObject).to.be.an('object');
160
+ expect(extendedIdObject.id).to.be.an('object');
161
+ expect(extendedIdObject.id).to.equal(cachedIdObject);
162
+ });
163
+
164
+ it('should return new commonId if there are changes', function () {
165
+ const idObject = freepassIdSubmodule.getId(config, undefined);
166
+ const cachedIdObject = Object.assign({}, idObject.id);
167
+ const localConfig = JSON.parse(JSON.stringify(config));
168
+ localConfig.params.freepassData.commonId = 'newCommonId';
169
+ const extendedIdObject = freepassIdSubmodule.extendId(localConfig, undefined, cachedIdObject);
170
+ expect(extendedIdObject).to.be.an('object');
171
+ expect(extendedIdObject.id).to.be.an('object');
172
+ expect(extendedIdObject.id.commonId).to.equal('newCommonId');
173
+ });
174
+
175
+ it('should return new userIp if there are changes', function () {
176
+ const idObject = freepassIdSubmodule.getId(config, undefined);
177
+ const cachedIdObject = Object.assign({}, idObject.id);
178
+ const localConfig = JSON.parse(JSON.stringify(config));
179
+ localConfig.params.freepassData.userIp = '192.168.1.1';
180
+ const extendedIdObject = freepassIdSubmodule.extendId(localConfig, undefined, cachedIdObject);
181
+ expect(extendedIdObject).to.be.an('object');
182
+ expect(extendedIdObject.id).to.be.an('object');
183
+ expect(extendedIdObject.id.userIp).to.equal('192.168.1.1');
184
+ });
185
+ });
186
+ });
@@ -0,0 +1,281 @@
1
+ import { expect } from 'chai';
2
+ import sinon from 'sinon';
3
+ import { server } from '../../mocks/xhr';
4
+
5
+ import {
6
+ mediaSize,
7
+ spec,
8
+ BIDDER_CODE,
9
+ ENDPOINT_URL,
10
+ REQUEST_ROUTE,
11
+ } from 'modules/hypelabBidAdapter.js';
12
+
13
+ import { BANNER } from 'src/mediaTypes.js';
14
+
15
+ const mockValidBidRequest = {
16
+ bidder: 'hypelab',
17
+ params: {
18
+ property_slug: 'prebid',
19
+ placement_slug: 'test_placement',
20
+ uuid: '',
21
+ sdk_version: '0.1.0',
22
+ provider_name: 'react',
23
+ provider_version: '0.3.1',
24
+ },
25
+ userIds: [],
26
+ mediaTypes: {
27
+ banner: {
28
+ sizes: [[728, 90]],
29
+ },
30
+ },
31
+ adUnitCode: 'test-div',
32
+ sizes: [[728, 90]],
33
+ bidId: '24d2b2c86c5e19',
34
+ bidderRequestId: '1d1f40b509f18',
35
+ auctionId: '3bf3b1fb-cb0a-4ee8-90ef-69b8e6e56dbd',
36
+ bidRequestsCount: 1,
37
+ bidderRequestsCount: 1,
38
+ bidderWinsCount: 0,
39
+ };
40
+
41
+ const mockValidBidRequests = [mockValidBidRequest];
42
+
43
+ const mockServerResponse = {
44
+ body: {
45
+ status: 'success',
46
+ data: {
47
+ currency: 'USD',
48
+ campaign_slug: '9dbe230882',
49
+ creative_set_slug: '842984f045',
50
+ creative_set: {
51
+ image: {
52
+ url: 'https://cloudfront.net/up/asset/12345',
53
+ height: 90,
54
+ width: 728,
55
+ },
56
+ },
57
+ cpm: 1.5,
58
+ html: "<!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <title>Ad</title>\n <style>\n html, body {\n margin: 0;\n padding: 0;\n overflow: hidden;\n }\n </style>\n </head>\n <body>\n <a\n id=\"link\"\n href=https://web.hypelab-staging.com/click?campaign_slug=9dbe230882&creative_set_slug=842984f045&placement_slug=test_placement \n target=\"_blank\">\n <img src=\"https://di30gnjrtlisb.cloudfront.net/up/asset/d1d1d65463/8eb7e9065e.jpg?tr=w-728,h-90\">\n </a>\n \n <script>\n function track(type) {\n var request = new XMLHttpRequest();\n request.open('POST', 'https://api.hypelab-staging.com/v1/events');\n request.setRequestHeader('Content-Type', 'application/json');\n\n var event = {\n property_slug: 'prebid',\n placement_slug: 'test_placement',\n campaign_slug: '9dbe230882',\n creative_set_slug: '842984f045',\n type: type,\n uuid: '',\n wids: []\n };\n\n request.send(JSON.stringify(event));\n }\n\n document.getElementById('link').addEventListener('click', function() {\n track('click');\n });\n\n track('impression');\n </script>\n </body>\n </html>\n ",
59
+ advertiser_domains: ['ogx.com'],
60
+ media_type: 'banner',
61
+ ttl: 360,
62
+ },
63
+ },
64
+ };
65
+
66
+ const mockBidderRequest = {
67
+ bidderCode: 'hypelab',
68
+ auctionId: '4462005b-ba06-49a9-a95d-0209c22f4606',
69
+ bidderRequestId: '1bf399761210ad',
70
+ bids: mockValidBidRequests,
71
+ auctionStart: 1684983987435,
72
+ timeout: 2000,
73
+ refererInfo: {
74
+ topmostLocation: 'https://example.com/hello_world.html',
75
+ location: 'https://example.com/hello_world.html',
76
+ canonicalUrl: null,
77
+ page: 'https://example.com/hello_world.html',
78
+ domain: null,
79
+ ref: null,
80
+ },
81
+ };
82
+
83
+ const mockBidRequest = {
84
+ method: 'POST',
85
+ url: 'https://api.hypelab.com/v1/prebid_requests',
86
+ options: {
87
+ contentType: 'application/json',
88
+ withCredentials: false,
89
+ },
90
+ data: {
91
+ property_slug: 'prebid',
92
+ placement_slug: 'test_placement',
93
+ provider_version: '0.0.1',
94
+ provider_name: 'prebid',
95
+ referrer: 'https://example.com',
96
+ sdk_version: '7.51.0-pre',
97
+ sizes: [[728, 90]],
98
+ wids: [],
99
+ uuid: 'tmp_c5abf809-47d6-40b9-8274-372c6d816dd8',
100
+ bidRequestsCount: 1,
101
+ bidderRequestsCount: 1,
102
+ bidderWinsCount: 0,
103
+ },
104
+ bidId: '2e02b562f700ae',
105
+ };
106
+
107
+ describe('hypelabBidAdapter', function () {
108
+ describe('mediaSize', function () {
109
+ describe('when given an invalid media object', function () {
110
+ expect(mediaSize({})).to.eql({ width: 0, height: 0 });
111
+ });
112
+
113
+ describe('when given a valid media object', function () {
114
+ expect(
115
+ mediaSize({ creative_set: { image: { width: 728, height: 90 } } })
116
+ ).to.eql({ width: 728, height: 90 });
117
+ });
118
+ });
119
+
120
+ describe('isBidRequestValid', function () {
121
+ describe('when given an invalid bid request', function () {
122
+ expect(spec.isBidRequestValid({})).to.equal(false);
123
+ });
124
+
125
+ describe('when given a valid bid request', function () {
126
+ expect(spec.isBidRequestValid(mockValidBidRequest)).to.equal(true);
127
+ });
128
+ });
129
+
130
+ describe('Bidder code valid', function () {
131
+ expect(spec.code).to.equal(BIDDER_CODE);
132
+ });
133
+
134
+ describe('Media types valid', function () {
135
+ expect(spec.supportedMediaTypes).to.contain(BANNER);
136
+ });
137
+
138
+ describe('Bid request valid', function () {
139
+ expect(spec.isBidRequestValid(mockValidBidRequest)).to.equal(true);
140
+ });
141
+
142
+ describe('buildRequests', () => {
143
+ describe('returns a valid request', function () {
144
+ const result = spec.buildRequests(
145
+ mockValidBidRequests,
146
+ mockBidderRequest
147
+ );
148
+ expect(result).to.be.an('array');
149
+
150
+ const first = result[0] || {};
151
+ expect(first).to.be.an('object');
152
+ expect(first.method).to.equal('POST');
153
+ expect(first.url).to.be.a('string');
154
+ expect(first.url).to.equal(ENDPOINT_URL + REQUEST_ROUTE);
155
+
156
+ const data = first.data || {};
157
+ expect(data).to.be.an('object');
158
+ expect(data.property_slug).to.be.a('string');
159
+ expect(data.placement_slug).to.be.a('string');
160
+ expect(data.bidRequestsCount).to.be.a('number');
161
+ expect(data.bidderRequestsCount).to.be.a('number');
162
+ expect(data.bidderWinsCount).to.be.a('number');
163
+ });
164
+
165
+ describe('should set uuid to the first id in userIdAsEids', () => {
166
+ mockValidBidRequests[0].userIdAsEids = [
167
+ {
168
+ source: 'pubcid.org',
169
+ uids: [
170
+ {
171
+ id: 'pubcid_id',
172
+ },
173
+ ],
174
+ },
175
+ {
176
+ source: 'criteo.com',
177
+ uids: [
178
+ {
179
+ id: 'criteo_id',
180
+ },
181
+ ],
182
+ },
183
+ ];
184
+
185
+ const result = spec.buildRequests(
186
+ mockValidBidRequests,
187
+ mockBidderRequest
188
+ );
189
+
190
+ const data = result[0].data || {};
191
+ expect(data.uuid).to.be.eq('pubcid_id');
192
+ });
193
+ });
194
+
195
+ describe('interpretResponse', () => {
196
+ describe('successfully interpret a valid response', function () {
197
+ const result = spec.interpretResponse(mockServerResponse, mockBidRequest);
198
+
199
+ expect(result).to.be.an('array');
200
+ const data = result[0] || {};
201
+ expect(data).to.be.an('object');
202
+ expect(data.requestId).to.be.a('string');
203
+ expect(data.cpm).to.be.a('number');
204
+ expect(data.width).to.be.a('number');
205
+ expect(data.height).to.be.a('number');
206
+ expect(data.creativeId).to.be.a('string');
207
+ expect(data.currency).to.be.a('string');
208
+ expect(data.netRevenue).to.be.a('boolean');
209
+ expect(data.referrer).to.be.a('string');
210
+ expect(data.ttl).to.be.a('number');
211
+ expect(data.ad).to.be.a('string');
212
+ expect(data.mediaType).to.be.a('string');
213
+ expect(data.meta.advertiserDomains).to.be.an('array');
214
+ });
215
+
216
+ describe('should return a blank array if cpm is not set', () => {
217
+ mockServerResponse.body.data.cpm = undefined;
218
+ const result = spec.interpretResponse(mockServerResponse, mockBidRequest);
219
+ expect(result).to.eql([]);
220
+ });
221
+ });
222
+
223
+ describe('report', () => {
224
+ it('returns if REPORTING_ROUTE is not set', () => {
225
+ spec.REPORTING_ROUTE = '';
226
+ expect(spec.report('test', {})).to.be.undefined;
227
+ });
228
+
229
+ it('makes a POST request if REPORTING_ROUTE is set', () => {
230
+ spec.report('test', {}, '/v1/events');
231
+
232
+ expect(server.requests[0].url).to.equals(
233
+ 'https://api.hypelab.com/v1/events'
234
+ );
235
+ });
236
+ });
237
+
238
+ describe('callbacks', () => {
239
+ let bid = {};
240
+ let reportStub;
241
+
242
+ beforeEach(() => (reportStub = sinon.stub(spec, 'report')));
243
+ afterEach(() => reportStub.restore());
244
+
245
+ describe('onTimeout', () => {
246
+ it('should call report with the correct data', () => {
247
+ spec.onTimeout(bid);
248
+
249
+ expect(reportStub.calledOnce).to.be.true;
250
+ expect(reportStub.getCall(0).args).to.eql(['timeout', bid]);
251
+ });
252
+ });
253
+
254
+ describe('onSetTargeting', () => {
255
+ it('should call report with the correct data', () => {
256
+ spec.onSetTargeting(bid);
257
+
258
+ expect(reportStub.calledOnce).to.be.true;
259
+ expect(reportStub.getCall(0).args).to.eql(['setTargeting', bid]);
260
+ });
261
+ });
262
+
263
+ describe('onBidWon', () => {
264
+ it('should call report with the correct data', () => {
265
+ spec.onBidWon(bid);
266
+
267
+ expect(reportStub.calledOnce).to.be.true;
268
+ expect(reportStub.getCall(0).args).to.eql(['bidWon', bid]);
269
+ });
270
+ });
271
+
272
+ describe('onBidderError', () => {
273
+ it('should call report with the correct data', () => {
274
+ spec.onBidderError(bid);
275
+
276
+ expect(reportStub.calledOnce).to.be.true;
277
+ expect(reportStub.getCall(0).args).to.eql(['bidderError', bid]);
278
+ });
279
+ });
280
+ });
281
+ });
@@ -42,7 +42,9 @@ describe('ID5 ID System', function () {
42
42
  const ID5_STORED_OBJ = {
43
43
  'universal_uid': ID5_STORED_ID,
44
44
  'signature': ID5_STORED_SIGNATURE,
45
- 'link_type': ID5_STORED_LINK_TYPE
45
+ 'ext': {
46
+ 'linkType': ID5_STORED_LINK_TYPE
47
+ }
46
48
  };
47
49
  const ID5_RESPONSE_ID = 'newid5id';
48
50
  const ID5_RESPONSE_SIGNATURE = 'abcdef';
@@ -50,7 +52,10 @@ describe('ID5 ID System', function () {
50
52
  const ID5_JSON_RESPONSE = {
51
53
  'universal_uid': ID5_RESPONSE_ID,
52
54
  'signature': ID5_RESPONSE_SIGNATURE,
53
- 'link_type': ID5_RESPONSE_LINK_TYPE
55
+ 'link_type': ID5_RESPONSE_LINK_TYPE,
56
+ 'ext': {
57
+ 'linkType': ID5_RESPONSE_LINK_TYPE
58
+ }
54
59
  };
55
60
  const ALLOWED_ID5_VENDOR_DATA = {
56
61
  purpose: {
@@ -958,7 +963,9 @@ describe('ID5 ID System', function () {
958
963
  it('should not expose ID when everyone is in control group', function () {
959
964
  storedObject.ab_testing = {result: 'control'};
960
965
  storedObject.universal_uid = '';
961
- storedObject.link_type = 0;
966
+ storedObject.ext = {
967
+ 'linkType': 0
968
+ };
962
969
  let decoded = id5IdSubmodule.decode(storedObject, testConfig);
963
970
  expect(decoded).is.deep.equal(expectedDecodedObjectWithoutIdAbOn);
964
971
  });
@@ -2570,6 +2570,36 @@ describe('IndexexchangeAdapter', function () {
2570
2570
  expect(impression.video.placement).to.equal(2);
2571
2571
  });
2572
2572
 
2573
+ it('should use plcmt value when set in video.params', function () {
2574
+ const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]);
2575
+ bid.params.video.plcmt = 2;
2576
+ const request = spec.buildRequests([bid], {})[0];
2577
+ const impression = extractPayload(request).imp[0];
2578
+
2579
+ expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId);
2580
+ expect(impression.video.plcmt).to.equal(2);
2581
+ });
2582
+
2583
+ it('invalid plcmt value when set in video.params', function () {
2584
+ const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]);
2585
+ bid.params.video.plcmt = 5;
2586
+ const request = spec.buildRequests([bid], {})[0];
2587
+ const impression = extractPayload(request).imp[0];
2588
+
2589
+ expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId);
2590
+ expect(impression.video.plcmt).to.be.undefined;
2591
+ });
2592
+
2593
+ it('invalid plcmt value string when set in video.params', function () {
2594
+ const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]);
2595
+ bid.params.video.plcmt = '4';
2596
+ const request = spec.buildRequests([bid], {})[0];
2597
+ const impression = extractPayload(request).imp[0];
2598
+
2599
+ expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId);
2600
+ expect(impression.video.plcmt).to.be.undefined;
2601
+ });
2602
+
2573
2603
  it('should set imp.ext.sid for video imps if params.id exists', function () {
2574
2604
  const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]);
2575
2605
  bid.params.id = 50;