prebid.js 7.29.0 → 7.31.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 (173) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/33acrossIdSystem.js +1 -1
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adkernelBidAdapter.js +1 -1
  7. package/dist/adrelevantisBidAdapter.js +1 -1
  8. package/dist/adtrgtmeBidAdapter.js +1 -1
  9. package/dist/adxcgBidAdapter.js +1 -1
  10. package/dist/ajaBidAdapter.js +1 -1
  11. package/dist/amxBidAdapter.js +1 -1
  12. package/dist/amxIdSystem.js +1 -1
  13. package/dist/appierAnalyticsAdapter.js +1 -1
  14. package/dist/appnexusBidAdapter.js +1 -1
  15. package/dist/asoBidAdapter.js +1 -1
  16. package/dist/axonixBidAdapter.js +1 -1
  17. package/dist/bidViewability.js +1 -1
  18. package/dist/bidglassBidAdapter.js +1 -1
  19. package/dist/big-richmediaBidAdapter.js +1 -1
  20. package/dist/bridgewellBidAdapter.js +1 -1
  21. package/dist/brightMountainMediaBidAdapter.js +1 -1
  22. package/dist/byDataAnalyticsAdapter.js +1 -1
  23. package/dist/carodaBidAdapter.js +1 -1
  24. package/dist/ccxBidAdapter.js +1 -1
  25. package/dist/chtnwBidAdapter.js +1 -1
  26. package/dist/colossussspBidAdapter.js +1 -1
  27. package/dist/concertBidAdapter.js +1 -1
  28. package/dist/confiantRtdProvider.js +1 -0
  29. package/dist/connectadBidAdapter.js +1 -1
  30. package/dist/consentManagement.js +1 -1
  31. package/dist/consentManagementGpp.js +1 -0
  32. package/dist/consumableBidAdapter.js +1 -1
  33. package/dist/conversantBidAdapter.js +1 -1
  34. package/dist/craftBidAdapter.js +1 -1
  35. package/dist/criteoBidAdapter.js +1 -1
  36. package/dist/datawrkzBidAdapter.js +1 -1
  37. package/dist/dfpAdServerVideo.js +1 -1
  38. package/dist/dspxBidAdapter.js +1 -1
  39. package/dist/eplanningBidAdapter.js +1 -1
  40. package/dist/feedadBidAdapter.js +1 -1
  41. package/dist/finativeBidAdapter.js +1 -1
  42. package/dist/glimpseBidAdapter.js +1 -1
  43. package/dist/gmosspBidAdapter.js +1 -1
  44. package/dist/goldbachBidAdapter.js +1 -1
  45. package/dist/gridBidAdapter.js +1 -1
  46. package/dist/gridNMBidAdapter.js +1 -1
  47. package/dist/gumgumBidAdapter.js +1 -1
  48. package/dist/h12mediaBidAdapter.js +1 -1
  49. package/dist/id5IdSystem.js +1 -1
  50. package/dist/improvedigitalBidAdapter.js +1 -1
  51. package/dist/inmarBidAdapter.js +1 -1
  52. package/dist/insticatorBidAdapter.js +1 -1
  53. package/dist/ixBidAdapter.js +1 -1
  54. package/dist/justpremiumBidAdapter.js +1 -1
  55. package/dist/konduitAnalyticsAdapter.js +1 -1
  56. package/dist/kueezBidAdapter.js +1 -1
  57. package/dist/kueezRtbBidAdapter.js +1 -1
  58. package/dist/lassoBidAdapter.js +1 -1
  59. package/dist/lifestreetBidAdapter.js +1 -1
  60. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  61. package/dist/logicadBidAdapter.js +1 -1
  62. package/dist/loglyliftBidAdapter.js +1 -1
  63. package/dist/magniteAnalyticsAdapter.js +1 -1
  64. package/dist/malltvAnalyticsAdapter.js +1 -1
  65. package/dist/marsmediaBidAdapter.js +1 -1
  66. package/dist/mediafuseBidAdapter.js +1 -1
  67. package/dist/mediasquareBidAdapter.js +1 -1
  68. package/dist/mgidBidAdapter.js +1 -1
  69. package/dist/minutemediaBidAdapter.js +1 -1
  70. package/dist/nexx360BidAdapter.js +1 -1
  71. package/dist/not-for-prod/prebid.js +127 -124
  72. package/dist/oguryBidAdapter.js +1 -1
  73. package/dist/onetagBidAdapter.js +1 -1
  74. package/dist/ooloAnalyticsAdapter.js +1 -1
  75. package/dist/outbrainBidAdapter.js +1 -1
  76. package/dist/parrableIdSystem.js +1 -1
  77. package/dist/pbsExtensions.js +1 -1
  78. package/dist/pixfutureBidAdapter.js +1 -1
  79. package/dist/prebid-core.js +1 -1
  80. package/dist/prebidServerBidAdapter.js +1 -1
  81. package/dist/publinkIdSystem.js +1 -1
  82. package/dist/pubmaticBidAdapter.js +1 -1
  83. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  84. package/dist/pxyzBidAdapter.js +1 -1
  85. package/dist/quantcastBidAdapter.js +1 -1
  86. package/dist/readpeakBidAdapter.js +1 -1
  87. package/dist/relaidoBidAdapter.js +1 -1
  88. package/dist/rhythmoneBidAdapter.js +1 -1
  89. package/dist/riseBidAdapter.js +1 -1
  90. package/dist/rtdModule.js +1 -1
  91. package/dist/rubiconAnalyticsAdapter.js +1 -1
  92. package/dist/rubiconBidAdapter.js +1 -1
  93. package/dist/seedingAllianceBidAdapter.js +1 -1
  94. package/dist/seedtagBidAdapter.js +1 -1
  95. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  96. package/dist/sharethroughBidAdapter.js +1 -1
  97. package/dist/shinezBidAdapter.js +1 -1
  98. package/dist/smaatoBidAdapter.js +1 -1
  99. package/dist/smartadserverBidAdapter.js +1 -1
  100. package/dist/smartxBidAdapter.js +1 -1
  101. package/dist/smilewantedBidAdapter.js +1 -1
  102. package/dist/sonobiBidAdapter.js +1 -1
  103. package/dist/sovrnAnalyticsAdapter.js +1 -1
  104. package/dist/sovrnBidAdapter.js +1 -1
  105. package/dist/sspBCBidAdapter.js +1 -1
  106. package/dist/sublimeBidAdapter.js +1 -1
  107. package/dist/synacormediaBidAdapter.js +1 -1
  108. package/dist/targetVideoBidAdapter.js +1 -1
  109. package/dist/teadsBidAdapter.js +1 -1
  110. package/dist/trionBidAdapter.js +1 -1
  111. package/dist/tripleliftBidAdapter.js +1 -1
  112. package/dist/ttdBidAdapter.js +1 -1
  113. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  114. package/dist/uid2IdSystem.js +1 -1
  115. package/dist/underdogmediaBidAdapter.js +1 -1
  116. package/dist/undertoneBidAdapter.js +1 -1
  117. package/dist/vidazooBidAdapter.js +1 -1
  118. package/dist/videobyteBidAdapter.js +1 -1
  119. package/dist/viouslyBidAdapter.js +1 -0
  120. package/dist/visxBidAdapter.js +1 -1
  121. package/dist/vuukleBidAdapter.js +1 -1
  122. package/dist/widespaceBidAdapter.js +1 -1
  123. package/dist/winrBidAdapter.js +1 -1
  124. package/dist/yahoosspBidAdapter.js +1 -1
  125. package/dist/yieldmoBidAdapter.js +1 -1
  126. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  127. package/integrationExamples/gpt/gpp_us_hello_world.html +124 -0
  128. package/integrationExamples/gpt/gpp_us_hello_world_iframe.html +12 -0
  129. package/integrationExamples/gpt/gpp_us_hello_world_iframe_subpage.html +140 -0
  130. package/karma.conf.maker.js +1 -1
  131. package/libraries/pbsExtensions/processors/adUnitCode.js +13 -0
  132. package/libraries/pbsExtensions/processors/pbs.js +5 -0
  133. package/modules/.submodules.json +1 -0
  134. package/modules/adkernelBidAdapter.js +2 -1
  135. package/modules/appnexusBidAdapter.js +23 -2
  136. package/modules/bidViewability.js +6 -1
  137. package/modules/ccxBidAdapter.js +3 -2
  138. package/modules/colossussspBidAdapter.js +8 -0
  139. package/modules/confiantRtdProvider.js +128 -0
  140. package/modules/confiantRtdProvider.md +45 -0
  141. package/modules/consentManagement.js +4 -4
  142. package/modules/consentManagementGpp.js +386 -0
  143. package/modules/datawrkzBidAdapter.js +24 -4
  144. package/modules/dfpAdServerVideo.js +6 -1
  145. package/modules/feedadBidAdapter.js +11 -3
  146. package/modules/gridBidAdapter.js +1 -2
  147. package/modules/lassoBidAdapter.js +2 -2
  148. package/modules/magniteAnalyticsAdapter.js +9 -1
  149. package/modules/onetagBidAdapter.js +20 -29
  150. package/modules/prebidServerBidAdapter/index.js +19 -8
  151. package/modules/prebidServerBidAdapter/ortbConverter.js +1 -0
  152. package/modules/rtdModule/index.js +2 -1
  153. package/modules/viouslyBidAdapter.js +209 -0
  154. package/modules/viouslyBidAdapter.md +35 -0
  155. package/package.json +1 -1
  156. package/src/adapterManager.js +11 -10
  157. package/src/adapters/bidderFactory.js +5 -5
  158. package/src/adloader.js +2 -1
  159. package/src/consentHandler.js +11 -0
  160. package/src/prebid.js +9 -9
  161. package/test/helpers/hookSetup.js +5 -0
  162. package/test/spec/modules/ViouslyBidAdapter_spec.js +378 -0
  163. package/test/spec/modules/appnexusBidAdapter_spec.js +46 -0
  164. package/test/spec/modules/colossussspBidAdapter_spec.js +89 -2
  165. package/test/spec/modules/confiantRtdProvider_spec.js +107 -0
  166. package/test/spec/modules/consentManagementGpp_spec.js +577 -0
  167. package/test/spec/modules/feedadBidAdapter_spec.js +38 -13
  168. package/test/spec/modules/gridBidAdapter_spec.js +0 -18
  169. package/test/spec/modules/magniteAnalyticsAdapter_spec.js +36 -14
  170. package/test/spec/modules/onetagBidAdapter_spec.js +29 -23
  171. package/test/spec/modules/topicsFpdModule_spec.js +41 -22
  172. package/test/spec/ortbConverter/pbsExtensions/adUnitCode_spec.js +23 -0
  173. package/test/spec/unit/pbjs_api_spec.js +11 -0
@@ -0,0 +1,107 @@
1
+ import * as utils from '../../../src/utils.js';
2
+ import * as hook from '../../../src/hook.js'
3
+ import * as events from '../../../src/events.js';
4
+ import CONSTANTS from '../../../src/constants.json';
5
+
6
+ import confiantModule from '../../../modules/confiantRtdProvider.js';
7
+
8
+ const {
9
+ injectConfigScript,
10
+ setupPage,
11
+ subscribeToConfiantCommFrame,
12
+ registerConfiantSubmodule
13
+ } = confiantModule;
14
+
15
+ describe('Confiant RTD module', function () {
16
+ describe('setupPage()', function() {
17
+ it('should return false if propertId is not present in config', function() {
18
+ expect(setupPage({})).to.be.false;
19
+ expect(setupPage({ params: {} })).to.be.false;
20
+ expect(setupPage({ params: { propertyId: '' } })).to.be.false;
21
+ });
22
+
23
+ it('should return true if expected parameters are present', function() {
24
+ expect(setupPage({ params: { propertyId: 'clientId' } })).to.be.true;
25
+ });
26
+ });
27
+
28
+ describe('Module initialization', function() {
29
+ let insertElementStub;
30
+ beforeEach(function() {
31
+ insertElementStub = sinon.stub(utils, 'insertElement');
32
+ });
33
+ afterEach(function() {
34
+ utils.insertElement.restore();
35
+ });
36
+
37
+ it('should subscribe to rovided Window object', function () {
38
+ const mockWindow = { addEventListener: sinon.spy() };
39
+
40
+ subscribeToConfiantCommFrame(mockWindow);
41
+
42
+ sinon.assert.calledOnce(mockWindow.addEventListener);
43
+ });
44
+
45
+ it('should fire BillableEvent as a result for message in comm window', function() {
46
+ let listenerCallback;
47
+ const mockWindow = { addEventListener: (a, cb) => (listenerCallback = cb) };
48
+ let billableEventsCounter = 0;
49
+
50
+ events.on(CONSTANTS.EVENTS.BILLABLE_EVENT, (e) => {
51
+ if (e.vendor === 'confiant') {
52
+ billableEventsCounter++;
53
+ expect(e.type).to.equal('impression');
54
+ expect(e.billingId).to.be.a('number');
55
+ expect(e.auctionId).to.equal('auctionId');
56
+ expect(e.transactionId).to.equal('transactionId');
57
+ }
58
+ });
59
+
60
+ subscribeToConfiantCommFrame(mockWindow);
61
+ listenerCallback({
62
+ data: {
63
+ auctionId: 'auctionId',
64
+ transactionId: 'transactionId'
65
+ }
66
+ });
67
+ listenerCallback({
68
+ data: {
69
+ auctionId: 'auctionId',
70
+ transactionId: 'transactionId'
71
+ }
72
+ });
73
+
74
+ expect(billableEventsCounter).to.equal(2);
75
+ });
76
+ });
77
+
78
+ describe('Sumbodule execution', function() {
79
+ let submoduleStub;
80
+ let insertElementStub;
81
+ beforeEach(function () {
82
+ submoduleStub = sinon.stub(hook, 'submodule');
83
+ insertElementStub = sinon.stub(utils, 'insertElement');
84
+ });
85
+ afterEach(function () {
86
+ utils.insertElement.restore();
87
+ submoduleStub.restore();
88
+ });
89
+
90
+ function initModule() {
91
+ registerConfiantSubmodule();
92
+
93
+ expect(submoduleStub.calledOnceWith('realTimeData')).to.equal(true);
94
+
95
+ const registeredSubmoduleDefinition = submoduleStub.getCall(0).args[1];
96
+ expect(registeredSubmoduleDefinition).to.be.an('object');
97
+ expect(registeredSubmoduleDefinition).to.have.own.property('name', 'confiant');
98
+ expect(registeredSubmoduleDefinition).to.have.own.property('init').that.is.a('function');
99
+
100
+ return registeredSubmoduleDefinition;
101
+ }
102
+
103
+ it('should register Confiant submodule', function () {
104
+ initModule();
105
+ });
106
+ });
107
+ });
@@ -0,0 +1,577 @@
1
+ import { setConsentConfig, requestBidsHook, resetConsentData, userCMP, consentTimeout, staticConsentData } from 'modules/consentManagementGpp.js';
2
+ import { gppDataHandler } from 'src/adapterManager.js';
3
+ import * as utils from 'src/utils.js';
4
+ import { config } from 'src/config.js';
5
+ import 'src/prebid.js';
6
+
7
+ let expect = require('chai').expect;
8
+
9
+ describe('consentManagementGpp', function () {
10
+ describe('setConsentConfig tests:', function () {
11
+ describe('empty setConsentConfig value', function () {
12
+ beforeEach(function () {
13
+ sinon.stub(utils, 'logInfo');
14
+ sinon.stub(utils, 'logWarn');
15
+ });
16
+
17
+ afterEach(function () {
18
+ utils.logInfo.restore();
19
+ utils.logWarn.restore();
20
+ config.resetConfig();
21
+ resetConsentData();
22
+ });
23
+
24
+ it('should use system default values', function () {
25
+ setConsentConfig({
26
+ gpp: {}
27
+ });
28
+ expect(userCMP).to.be.equal('iab');
29
+ expect(consentTimeout).to.be.equal(10000);
30
+ sinon.assert.callCount(utils.logInfo, 3);
31
+ });
32
+
33
+ it('should exit consent manager if config is not an object', function () {
34
+ setConsentConfig('');
35
+ expect(userCMP).to.be.undefined;
36
+ sinon.assert.calledOnce(utils.logWarn);
37
+ });
38
+
39
+ it('should exit consentManagement module if config is "undefined"', function () {
40
+ setConsentConfig(undefined);
41
+ expect(userCMP).to.be.undefined;
42
+ sinon.assert.calledOnce(utils.logWarn);
43
+ });
44
+
45
+ it('should not produce any consent metadata', function () {
46
+ setConsentConfig(undefined)
47
+ let consentMetadata = gppDataHandler.getConsentMeta();
48
+ expect(consentMetadata).to.be.undefined;
49
+ sinon.assert.calledOnce(utils.logWarn);
50
+ })
51
+
52
+ it('should immediately look up consent data', () => {
53
+ setConsentConfig({
54
+ gpp: {
55
+ cmpApi: 'invalid'
56
+ }
57
+ });
58
+ expect(gppDataHandler.ready).to.be.true;
59
+ })
60
+ });
61
+
62
+ describe('valid setConsentConfig value', function () {
63
+ afterEach(function () {
64
+ config.resetConfig();
65
+ });
66
+
67
+ it('results in all user settings overriding system defaults', function () {
68
+ let allConfig = {
69
+ gpp: {
70
+ cmpApi: 'iab',
71
+ timeout: 7500
72
+ }
73
+ };
74
+
75
+ setConsentConfig(allConfig);
76
+ expect(userCMP).to.be.equal('iab');
77
+ expect(consentTimeout).to.be.equal(7500);
78
+ });
79
+
80
+ it('should recognize config.gpp, with default cmpApi and timeout', function () {
81
+ setConsentConfig({
82
+ gpp: {}
83
+ });
84
+
85
+ expect(userCMP).to.be.equal('iab');
86
+ expect(consentTimeout).to.be.equal(10000);
87
+ });
88
+
89
+ it('should enable gppDataHandler', () => {
90
+ setConsentConfig({
91
+ gpp: {}
92
+ });
93
+ expect(gppDataHandler.enabled).to.be.true;
94
+ });
95
+ });
96
+
97
+ describe('static consent string setConsentConfig value', () => {
98
+ afterEach(() => {
99
+ config.resetConfig();
100
+ });
101
+
102
+ it('results in user settings overriding system defaults for v2 spec', () => {
103
+ let staticConfig = {
104
+ gpp: {
105
+ cmpApi: 'static',
106
+ timeout: 7500,
107
+ consentData: {
108
+ applicableSections: [7],
109
+ gppString: 'ABCDEFG1234',
110
+ gppVersion: 1,
111
+ sectionId: 3,
112
+ sectionList: []
113
+ }
114
+ }
115
+ };
116
+
117
+ setConsentConfig(staticConfig);
118
+ expect(userCMP).to.be.equal('static');
119
+ expect(consentTimeout).to.be.equal(0); // should always return without a timeout when config is used
120
+ const consent = gppDataHandler.getConsentData();
121
+ expect(consent.gppString).to.eql(staticConfig.gpp.consentData.gppString);
122
+ expect(consent.fullGppData).to.eql(staticConfig.gpp.consentData);
123
+ expect(staticConsentData).to.be.equal(staticConfig.gpp.consentData);
124
+ });
125
+ });
126
+ });
127
+
128
+ describe('requestBidsHook tests:', function () {
129
+ let goodConfig = {
130
+ gpp: {
131
+ cmpApi: 'iab',
132
+ timeout: 7500,
133
+ }
134
+ };
135
+
136
+ const staticConfig = {
137
+ gpp: {
138
+ cmpApi: 'static',
139
+ timeout: 7500,
140
+ consentData: {
141
+ gppString: 'abc12345',
142
+ applicableSections: [7]
143
+ }
144
+ }
145
+ }
146
+
147
+ let didHookReturn;
148
+
149
+ beforeEach(resetConsentData);
150
+ after(resetConsentData);
151
+
152
+ describe('error checks:', function () {
153
+ beforeEach(function () {
154
+ didHookReturn = false;
155
+ sinon.stub(utils, 'logWarn');
156
+ sinon.stub(utils, 'logError');
157
+ });
158
+
159
+ afterEach(function () {
160
+ utils.logWarn.restore();
161
+ utils.logError.restore();
162
+ config.resetConfig();
163
+ });
164
+
165
+ it('should throw a warning and return to hooked function when an unknown CMP framework ID is used', function () {
166
+ let badCMPConfig = {
167
+ gpp: {
168
+ cmpApi: 'bad'
169
+ }
170
+ };
171
+ setConsentConfig(badCMPConfig);
172
+ expect(userCMP).to.be.equal(badCMPConfig.gpp.cmpApi);
173
+
174
+ requestBidsHook(() => {
175
+ didHookReturn = true;
176
+ }, {});
177
+ let consent = gppDataHandler.getConsentData();
178
+
179
+ sinon.assert.calledOnce(utils.logWarn);
180
+ expect(didHookReturn).to.be.true;
181
+ expect(consent).to.be.null;
182
+ });
183
+
184
+ it('should call gppDataHandler.setConsentData() when unknown CMP api is used', () => {
185
+ setConsentConfig({
186
+ gpp: {
187
+ cmpApi: 'invalid'
188
+ }
189
+ });
190
+ let hookRan = false;
191
+ requestBidsHook(() => {
192
+ hookRan = true;
193
+ }, {});
194
+ expect(hookRan).to.be.true;
195
+ expect(gppDataHandler.ready).to.be.true;
196
+ })
197
+
198
+ it('should throw proper errors when CMP is not found', function () {
199
+ setConsentConfig(goodConfig);
200
+
201
+ requestBidsHook(() => {
202
+ didHookReturn = true;
203
+ }, {});
204
+ let consent = gppDataHandler.getConsentData();
205
+ // throw 2 errors; one for no bidsBackHandler and for CMP not being found (this is an error due to gdpr config)
206
+ sinon.assert.calledTwice(utils.logError);
207
+ expect(didHookReturn).to.be.false;
208
+ expect(consent).to.be.null;
209
+ expect(gppDataHandler.ready).to.be.true;
210
+ });
211
+
212
+ it('should not trip when adUnits have no size', () => {
213
+ setConsentConfig(staticConfig);
214
+ let ran = false;
215
+ requestBidsHook(() => {
216
+ ran = true;
217
+ }, {
218
+ adUnits: [{
219
+ code: 'test',
220
+ mediaTypes: {
221
+ video: {}
222
+ }
223
+ }]
224
+ });
225
+ return gppDataHandler.promise.then(() => {
226
+ expect(ran).to.be.true;
227
+ });
228
+ });
229
+
230
+ it('should continue the auction immediately, without consent data, if timeout is 0', (done) => {
231
+ setConsentConfig({
232
+ gpp: {
233
+ cmpApi: 'iab',
234
+ timeout: 0
235
+ }
236
+ });
237
+ window.__gpp = function () {};
238
+ try {
239
+ requestBidsHook(() => {
240
+ const consent = gppDataHandler.getConsentData();
241
+ expect(consent.applicableSections).to.deep.equal([]);
242
+ expect(consent.gppString).to.be.undefined;
243
+ done();
244
+ }, {})
245
+ } finally {
246
+ delete window.__gpp;
247
+ }
248
+ });
249
+ });
250
+
251
+ describe('already known consentData:', function () {
252
+ let cmpStub = sinon.stub();
253
+
254
+ function mockCMP(cmpResponse) {
255
+ return function (...args) {
256
+ if (args[0] === 'addEventListener') {
257
+ args[1](({
258
+ eventName: 'sectionChange'
259
+ }));
260
+ } else if (args[0] === 'getGPPData') {
261
+ return cmpResponse;
262
+ }
263
+ }
264
+ }
265
+
266
+ beforeEach(function () {
267
+ didHookReturn = false;
268
+ window.__gpp = function () {};
269
+ });
270
+
271
+ afterEach(function () {
272
+ config.resetConfig();
273
+ cmpStub.restore();
274
+ delete window.__gpp;
275
+ resetConsentData();
276
+ });
277
+
278
+ it('should bypass CMP and simply use previously stored consentData', function () {
279
+ let testConsentData = {
280
+ applicableSections: [7],
281
+ gppString: 'xyz',
282
+ };
283
+
284
+ cmpStub = sinon.stub(window, '__gpp').callsFake(mockCMP(testConsentData));
285
+ setConsentConfig(goodConfig);
286
+ requestBidsHook(() => {}, {});
287
+ cmpStub.reset();
288
+
289
+ requestBidsHook(() => {
290
+ didHookReturn = true;
291
+ }, {});
292
+ let consent = gppDataHandler.getConsentData();
293
+
294
+ expect(didHookReturn).to.be.true;
295
+ expect(consent.gppString).to.equal(testConsentData.gppString);
296
+ expect(consent.applicableSections).to.deep.equal(testConsentData.applicableSections);
297
+ sinon.assert.notCalled(cmpStub);
298
+ });
299
+ });
300
+
301
+ describe('iframe tests', function () {
302
+ let cmpPostMessageCb = () => {};
303
+ let stringifyResponse;
304
+
305
+ function createIFrameMarker(frameName) {
306
+ let ifr = document.createElement('iframe');
307
+ ifr.width = 0;
308
+ ifr.height = 0;
309
+ ifr.name = frameName;
310
+ document.body.appendChild(ifr);
311
+ return ifr;
312
+ }
313
+
314
+ function creatCmpMessageHandler(prefix, returnEvtValue, returnGPPValue) {
315
+ return function (event) {
316
+ if (event && event.data) {
317
+ let data = event.data;
318
+ if (data[`${prefix}Call`]) {
319
+ let callId = data[`${prefix}Call`].callId;
320
+ let response;
321
+ if (data[`${prefix}Call`].command === 'addEventListener') {
322
+ response = {
323
+ [`${prefix}Return`]: {
324
+ callId,
325
+ returnValue: returnEvtValue,
326
+ success: true
327
+ }
328
+ }
329
+ } else if (data[`${prefix}Call`].command === 'getGPPData') {
330
+ response = {
331
+ [`${prefix}Return`]: {
332
+ callId,
333
+ returnValue: returnGPPValue,
334
+ success: true
335
+ }
336
+ }
337
+ }
338
+ event.source.postMessage(stringifyResponse ? JSON.stringify(response) : response, '*');
339
+ }
340
+ }
341
+ }
342
+ }
343
+
344
+ function testIFramedPage(testName, messageFormatString, tarConsentString, tarSections) {
345
+ it(`should return the consent string from a postmessage + addEventListener response - ${testName}`, (done) => {
346
+ stringifyResponse = messageFormatString;
347
+ setConsentConfig(goodConfig);
348
+ requestBidsHook(() => {
349
+ let consent = gppDataHandler.getConsentData();
350
+ sinon.assert.notCalled(utils.logError);
351
+ expect(consent.gppString).to.equal(tarConsentString);
352
+ expect(consent.applicableSections).to.deep.equal(tarSections);
353
+ done();
354
+ }, {});
355
+ });
356
+ }
357
+
358
+ beforeEach(function () {
359
+ sinon.stub(utils, 'logError');
360
+ sinon.stub(utils, 'logWarn');
361
+ });
362
+
363
+ afterEach(function () {
364
+ utils.logError.restore();
365
+ utils.logWarn.restore();
366
+ config.resetConfig();
367
+ resetConsentData();
368
+ });
369
+
370
+ describe('v2 CMP workflow for iframe pages:', function () {
371
+ stringifyResponse = false;
372
+ let ifr2 = null;
373
+
374
+ beforeEach(function () {
375
+ ifr2 = createIFrameMarker('__gppLocator');
376
+ cmpPostMessageCb = creatCmpMessageHandler('__gpp', {
377
+ eventName: 'sectionChange'
378
+ }, {
379
+ gppString: 'abc12345234',
380
+ applicableSections: [7]
381
+ });
382
+ window.addEventListener('message', cmpPostMessageCb, false);
383
+ });
384
+
385
+ afterEach(function () {
386
+ delete window.__gpp; // deletes the local copy made by the postMessage CMP call function
387
+ document.body.removeChild(ifr2);
388
+ window.removeEventListener('message', cmpPostMessageCb);
389
+ });
390
+
391
+ testIFramedPage('with/JSON response', false, 'abc12345234', [7]);
392
+ testIFramedPage('with/String response', true, 'abc12345234', [7]);
393
+ });
394
+ });
395
+
396
+ describe('direct calls to CMP API tests', function () {
397
+ let cmpStub = sinon.stub();
398
+
399
+ beforeEach(function () {
400
+ didHookReturn = false;
401
+ sinon.stub(utils, 'logError');
402
+ sinon.stub(utils, 'logWarn');
403
+ });
404
+
405
+ afterEach(function () {
406
+ config.resetConfig();
407
+ cmpStub.restore();
408
+ utils.logError.restore();
409
+ utils.logWarn.restore();
410
+ resetConsentData();
411
+ });
412
+
413
+ describe('v2 CMP workflow for normal pages:', function () {
414
+ beforeEach(function () {
415
+ window.__gpp = function () {};
416
+ });
417
+
418
+ afterEach(function () {
419
+ delete window.__gpp;
420
+ });
421
+
422
+ it('performs lookup check and stores consentData for a valid existing user', function () {
423
+ let testConsentData = {
424
+ gppString: 'abc12345234',
425
+ applicableSections: [7]
426
+ };
427
+ cmpStub = sinon.stub(window, '__gpp').callsFake((...args) => {
428
+ if (args[0] === 'addEventListener') {
429
+ args[1]({
430
+ eventName: 'sectionChange'
431
+ });
432
+ } else if (args[0] === 'getGPPData') {
433
+ return testConsentData;
434
+ }
435
+ });
436
+
437
+ setConsentConfig(goodConfig);
438
+
439
+ requestBidsHook(() => {
440
+ didHookReturn = true;
441
+ }, {});
442
+ let consent = gppDataHandler.getConsentData();
443
+ sinon.assert.notCalled(utils.logError);
444
+ expect(didHookReturn).to.be.true;
445
+ expect(consent.gppString).to.equal(testConsentData.gppString);
446
+ expect(consent.applicableSections).to.deep.equal(testConsentData.applicableSections);
447
+ });
448
+
449
+ it('produces gdpr metadata', function () {
450
+ let testConsentData = {
451
+ gppString: 'abc12345234',
452
+ applicableSections: [7]
453
+ };
454
+ cmpStub = sinon.stub(window, '__gpp').callsFake((...args) => {
455
+ if (args[0] === 'addEventListener') {
456
+ args[1]({
457
+ eventName: 'sectionChange'
458
+ });
459
+ } else if (args[0] === 'getGPPData') {
460
+ return testConsentData;
461
+ }
462
+ });
463
+
464
+ setConsentConfig(goodConfig);
465
+
466
+ requestBidsHook(() => {
467
+ didHookReturn = true;
468
+ }, {});
469
+ let consentMeta = gppDataHandler.getConsentMeta();
470
+ sinon.assert.notCalled(utils.logError);
471
+ expect(consentMeta.generatedAt).to.be.above(1644367751709);
472
+ });
473
+
474
+ it('throws an error when processCmpData check fails + does not call requestBids callback', function () {
475
+ let testConsentData = {};
476
+ let bidsBackHandlerReturn = false;
477
+
478
+ cmpStub = sinon.stub(window, '__gpp').callsFake((...args) => {
479
+ if (args[0] === 'addEventListener') {
480
+ args[1]({
481
+ eventName: 'sectionChange'
482
+ });
483
+ } else if (args[0] === 'getGPPData') {
484
+ return testConsentData;
485
+ }
486
+ });
487
+
488
+ setConsentConfig(goodConfig);
489
+
490
+ sinon.assert.notCalled(utils.logWarn);
491
+ sinon.assert.notCalled(utils.logError);
492
+
493
+ [utils.logWarn, utils.logError].forEach((stub) => stub.reset());
494
+
495
+ requestBidsHook(() => {
496
+ didHookReturn = true;
497
+ }, {
498
+ bidsBackHandler: () => bidsBackHandlerReturn = true
499
+ });
500
+ let consent = gppDataHandler.getConsentData();
501
+
502
+ sinon.assert.calledOnce(utils.logError);
503
+ sinon.assert.notCalled(utils.logWarn);
504
+ expect(didHookReturn).to.be.false;
505
+ expect(bidsBackHandlerReturn).to.be.true;
506
+ expect(consent).to.be.null;
507
+ expect(gppDataHandler.ready).to.be.true;
508
+ });
509
+
510
+ describe('when proper consent is not available', () => {
511
+ let gppStub;
512
+
513
+ function runAuction() {
514
+ setConsentConfig({
515
+ gpp: {
516
+ cmpApi: 'iab',
517
+ timeout: 10,
518
+ }
519
+ });
520
+ return new Promise((resolve, reject) => {
521
+ requestBidsHook(() => {
522
+ didHookReturn = true;
523
+ }, {});
524
+ setTimeout(() => didHookReturn ? resolve() : reject(new Error('Auction did not run')), 20);
525
+ })
526
+ }
527
+
528
+ function mockGppCmp(gppdata) {
529
+ gppStub.callsFake((api, cb) => {
530
+ if (api === 'addEventListener') {
531
+ // eslint-disable-next-line standard/no-callback-literal
532
+ cb({
533
+ pingData: {
534
+ cmpStatus: 'loaded'
535
+ }
536
+ }, true);
537
+ }
538
+ if (api === 'getGPPData') {
539
+ return gppdata;
540
+ }
541
+ });
542
+ }
543
+
544
+ beforeEach(() => {
545
+ gppStub = sinon.stub(window, '__gpp');
546
+ });
547
+
548
+ afterEach(() => {
549
+ gppStub.restore();
550
+ })
551
+
552
+ it('should continue auction with null consent when CMP is unresponsive', () => {
553
+ return runAuction().then(() => {
554
+ const consent = gppDataHandler.getConsentData();
555
+ expect(consent.applicableSections).to.deep.equal([]);
556
+ expect(consent.gppString).to.be.undefined;
557
+ expect(gppDataHandler.ready).to.be.true;
558
+ });
559
+ });
560
+
561
+ it('should use consent provided by events other than sectionChange', () => {
562
+ mockGppCmp({
563
+ gppString: 'mock-consent-string',
564
+ applicableSections: [7]
565
+ });
566
+ return runAuction().then(() => {
567
+ const consent = gppDataHandler.getConsentData();
568
+ expect(consent.applicableSections).to.deep.equal([7]);
569
+ expect(consent.gppString).to.equal('mock-consent-string');
570
+ expect(gppDataHandler.ready).to.be.true;
571
+ });
572
+ });
573
+ });
574
+ });
575
+ });
576
+ });
577
+ });