• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

prebid / Prebid.js / 16197995703

10 Jul 2025 02:32PM UTC coverage: 96.232% (+0.003%) from 96.229%
16197995703

push

github

web-flow
Linting: remove exception (#13518)

* bump coveralls

* remove exceptions

* results

* eslint fix

* Update package-lock.json

* Update package-lock.json

* Core: remove codex comments and unused lint rule (#13520)

---------

Co-authored-by: Demetrio Girardi <dgirardi@prebid.org>

39174 of 48116 branches covered (81.42%)

9842 of 9975 new or added lines in 861 files covered. (98.67%)

15 existing lines in 8 files now uncovered.

192483 of 200020 relevant lines covered (96.23%)

88.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.27
/modules/datablocksBidAdapter.js
1
import {deepAccess, getWinDimensions, getWindowTop, isEmpty, isGptPubadsDefined} from '../src/utils.js';
1✔
2
import {registerBidder} from '../src/adapters/bidderFactory.js';
3
import {config} from '../src/config.js';
4
import {BANNER, NATIVE} from '../src/mediaTypes.js';
5
import {getStorageManager} from '../src/storageManager.js';
6
import {ajax} from '../src/ajax.js';
7
import {convertOrtbRequestToProprietaryNative} from '../src/native.js';
8
import {getAdUnitSizes} from '../libraries/sizeUtils/sizeUtils.js';
9

10
export const storage = getStorageManager({bidderCode: 'datablocks'});
1✔
11

12
const NATIVE_ID_MAP = {};
1✔
13
const NATIVE_PARAMS = {
1✔
14
  title: {
15
    id: 1,
16
    name: 'title'
17
  },
18
  icon: {
19
    id: 2,
20
    type: 1,
21
    name: 'img'
22
  },
23
  image: {
24
    id: 3,
25
    type: 3,
26
    name: 'img'
27
  },
28
  body: {
29
    id: 4,
30
    name: 'data',
31
    type: 2
32
  },
33
  sponsoredBy: {
34
    id: 5,
35
    name: 'data',
36
    type: 1
37
  },
38
  cta: {
39
    id: 6,
40
    type: 12,
41
    name: 'data'
42
  },
43
  body2: {
44
    id: 7,
45
    name: 'data',
46
    type: 10
47
  },
48
  rating: {
49
    id: 8,
50
    name: 'data',
51
    type: 3
52
  },
53
  likes: {
54
    id: 9,
55
    name: 'data',
56
    type: 4
57
  },
58
  downloads: {
59
    id: 10,
60
    name: 'data',
61
    type: 5
62
  },
63
  displayUrl: {
64
    id: 11,
65
    name: 'data',
66
    type: 11
67
  },
68
  price: {
69
    id: 12,
70
    name: 'data',
71
    type: 6
72
  },
73
  salePrice: {
74
    id: 13,
75
    name: 'data',
76
    type: 7
77
  },
78
  address: {
79
    id: 14,
80
    name: 'data',
81
    type: 9
82
  },
83
  phone: {
84
    id: 15,
85
    name: 'data',
86
    type: 8
87
  }
88
};
89

90
Object.keys(NATIVE_PARAMS).forEach((key) => {
1✔
91
  NATIVE_ID_MAP[NATIVE_PARAMS[key].id] = key;
15✔
92
});
93

94
// DEFINE THE PREBID BIDDER SPEC
95
export const spec = {
1✔
96
  supportedMediaTypes: [BANNER, NATIVE],
97
  code: 'datablocks',
98

99
  // DATABLOCKS SCOPED OBJECT
100
  db_obj: {metrics_host: 'prebid.dblks.net', metrics: [], metrics_timer: null, metrics_queue_time: 1000, vis_optout: false, source_id: 0},
101

102
  // STORE THE DATABLOCKS BUYERID IN STORAGE
103
  store_dbid: function(dbid) {
104
    let stored = false;
2✔
105

106
    // CREATE 1 YEAR EXPIRY DATE
107
    const d = new Date();
2✔
108
    d.setTime(Date.now() + (365 * 24 * 60 * 60 * 1000));
2✔
109

110
    // TRY TO STORE IN COOKIE
111
    if (storage.cookiesAreEnabled) {
2✔
112
      storage.setCookie('_db_dbid', dbid, d.toUTCString(), 'None', null);
2✔
113
      stored = true;
2✔
114
    }
115

116
    // TRY TO STORE IN LOCAL STORAGE
117
    if (storage.localStorageIsEnabled) {
2✔
118
      storage.setDataInLocalStorage('_db_dbid', dbid);
2✔
119
      stored = true;
2✔
120
    }
121

122
    return stored;
2✔
123
  },
124

125
  // FETCH DATABLOCKS BUYERID FROM STORAGE
126
  get_dbid: function() {
127
    let dbId = '';
3✔
128
    if (storage.cookiesAreEnabled) {
3✔
129
      dbId = storage.getCookie('_db_dbid') || '';
3✔
130
    }
131

132
    if (!dbId && storage.localStorageIsEnabled) {
3✔
133
      dbId = storage.getDataFromLocalStorage('_db_dbid') || '';
3✔
134
    }
135
    return dbId;
3✔
136
  },
137

138
  // STORE SYNCS IN STORAGE
139
  store_syncs: function(syncs) {
140
    if (storage.localStorageIsEnabled) {
1✔
141
      const syncObj = {};
1✔
142
      syncs.forEach(sync => {
1✔
143
        syncObj[sync.id] = sync.uid;
1✔
144
      });
145

146
      // FETCH EXISTING SYNCS AND MERGE NEW INTO STORAGE
147
      const storedSyncs = this.get_syncs();
1✔
148
      storage.setDataInLocalStorage('_db_syncs', JSON.stringify(Object.assign(storedSyncs, syncObj)));
1✔
149

150
      return true;
1✔
151
    }
152
  },
153

154
  // GET SYNCS FROM STORAGE
155
  get_syncs: function() {
156
    if (storage.localStorageIsEnabled) {
3!
157
      const syncData = storage.getDataFromLocalStorage('_db_syncs');
3✔
158
      if (syncData) {
3!
159
        return JSON.parse(syncData);
×
160
      } else {
161
        return {};
3✔
162
      }
163
    } else {
164
      return {};
×
165
    }
166
  },
167

168
  // ADD METRIC DATA TO THE METRICS RESPONSE QUEUE
169
  queue_metric: function(metric) {
170
    if (typeof metric === 'object') {
×
171
      // PUT METRICS IN THE QUEUE
172
      this.db_obj.metrics.push(metric);
×
173

174
      // RESET PREVIOUS TIMER
175
      if (this.db_obj.metrics_timer) {
×
176
        clearTimeout(this.db_obj.metrics_timer);
×
177
      }
178

179
      // SETUP THE TIMER TO FIRE BACK THE DATA
NEW
180
      const scope = this;
×
181
      this.db_obj.metrics_timer = setTimeout(function() {
×
182
        scope.send_metrics();
×
183
      }, this.db_obj.metrics_queue_time);
184

185
      return true;
×
186
    } else {
187
      return false;
×
188
    }
189
  },
190

191
  // POST CONSOLIDATED METRICS BACK TO SERVER
192
  send_metrics: function() {
193
    // POST TO SERVER
194
    ajax(`https://${this.db_obj.metrics_host}/a/pb/`, null, JSON.stringify(this.db_obj.metrics), {method: 'POST', withCredentials: true});
×
195

196
    // RESET THE QUEUE OF METRIC DATA
197
    this.db_obj.metrics = [];
×
198

199
    return true;
×
200
  },
201

202
  // GET BASIC CLIENT INFORMATION
203
  get_client_info: function () {
204
    const botTest = new BotClientTests();
2✔
205
    const win = getWindowTop();
2✔
206
    const windowDimensions = getWinDimensions();
2✔
207
    return {
2✔
208
      'wiw': windowDimensions.innerWidth,
209
      'wih': windowDimensions.innerHeight,
210
      'saw': windowDimensions.screen.availWidth,
211
      'sah': windowDimensions.screen.availHeight,
212
      'scd': screen ? screen.colorDepth : null,
2!
213
      'sw': windowDimensions.screen.width,
214
      'sh': windowDimensions.screen.height,
215
      'whl': win.history.length,
216
      'wxo': win.pageXOffset,
217
      'wyo': win.pageYOffset,
218
      'wpr': win.devicePixelRatio,
219
      'is_bot': botTest.doTests(),
220
      'is_hid': win.document.hidden,
221
      'vs': win.document.visibilityState
222
    };
223
  },
224

225
  // LISTEN FOR GPT VIEWABILITY EVENTS
226
  get_viewability: function(bid) {
227
    // ONLY RUN ONCE IF PUBLISHER HAS OPTED IN
228
    if (!this.db_obj.vis_optout && !this.db_obj.vis_run) {
2✔
229
      this.db_obj.vis_run = true;
1✔
230

231
      // ADD GPT EVENT LISTENERS
232
      const scope = this;
1✔
233
      if (isGptPubadsDefined()) {
1✔
234
        if (typeof window['googletag'].pubads().addEventListener == 'function') {
1✔
235
          // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781
236
          window['googletag'].pubads().addEventListener('impressionViewable', function(event) {
1✔
237
            scope.queue_metric({type: 'slot_view', source_id: scope.db_obj.source_id, auction_id: bid.auctionId, div_id: event.slot.getSlotElementId(), slot_id: event.slot.getSlotId().getAdUnitPath()});
×
238
          });
239
          window['googletag'].pubads().addEventListener('slotRenderEnded', function(event) {
1✔
240
            scope.queue_metric({type: 'slot_render', source_id: scope.db_obj.source_id, auction_id: bid.auctionId, div_id: event.slot.getSlotElementId(), slot_id: event.slot.getSlotId().getAdUnitPath()});
×
241
          })
242
        }
243
      }
244
    }
245
  },
246

247
  // VALIDATE THE BID REQUEST
248
  isBidRequestValid: function(bid) {
249
    // SET GLOBAL VARS FROM BIDDER CONFIG
250
    this.db_obj.source_id = bid.params.source_id;
3✔
251
    if (bid.params.vis_optout) {
3✔
252
      this.db_obj.vis_optout = true;
1✔
253
    }
254

255
    return !!(bid.params.source_id && bid.mediaTypes && (bid.mediaTypes.banner || bid.mediaTypes.native));
3!
256
  },
257

258
  // GENERATE THE RTB REQUEST
259
  buildRequests: function(validRequests, bidderRequest) {
260
    // convert Native ORTB definition to old-style prebid native definition
261
    validRequests = convertOrtbRequestToProprietaryNative(validRequests);
2✔
262

263
    // RETURN EMPTY IF THERE ARE NO VALID REQUESTS
264
    if (!validRequests.length) {
2✔
265
      return [];
1✔
266
    }
267

268
    // CONVERT PREBID NATIVE REQUEST OBJ INTO RTB OBJ
269
    function createNativeRequest(bid) {
270
      const assets = [];
1✔
271
      if (bid.nativeParams) {
1✔
272
        Object.keys(bid.nativeParams).forEach((key) => {
1✔
273
          if (NATIVE_PARAMS[key]) {
3✔
274
            const {name, type, id} = NATIVE_PARAMS[key];
3✔
275
            const assetObj = type ? {type} : {};
3✔
276
            let {len, sizes, required, aspect_ratios: aRatios} = bid.nativeParams[key];
3✔
277
            if (len) {
3!
278
              assetObj.len = len;
×
279
            }
280
            if (aRatios && aRatios[0]) {
3!
281
              aRatios = aRatios[0];
×
NEW
282
              const wmin = aRatios.min_width || 0;
×
NEW
283
              const hmin = aRatios.ratio_height * wmin / aRatios.ratio_width | 0;
×
284
              assetObj.wmin = wmin;
×
285
              assetObj.hmin = hmin;
×
286
            }
287
            if (sizes && sizes.length) {
3✔
288
              sizes = [].concat(...sizes);
1✔
289
              assetObj.w = sizes[0];
1✔
290
              assetObj.h = sizes[1];
1✔
291
            }
292
            const asset = {required: required ? 1 : 0, id};
3!
293
            asset[name] = assetObj;
3✔
294
            assets.push(asset);
3✔
295
          }
296
        });
297
      }
298
      return {
1✔
299
        ver: '1.2',
300
        request: {
301
          assets: assets,
302
          context: 1,
303
          plcmttype: 1,
304
          ver: '1.2'
305
        }
306
      }
307
    }
308
    const imps = [];
1✔
309
    // ITERATE THE VALID REQUESTS AND GENERATE IMP OBJECT
310
    validRequests.forEach(bidRequest => {
1✔
311
      // BUILD THE IMP OBJECT
312
      const imp = {
3✔
313
        id: bidRequest.bidId,
314
        tagid: bidRequest.params.tagid || bidRequest.adUnitCode,
6✔
315
        placement_id: bidRequest.params.placement_id || 0,
6✔
316
        secure: window.location.protocol == 'https:',
317
        ortb2: deepAccess(bidRequest, `ortb2Imp`) || {},
6✔
318
        floor: {}
319
      }
320

321
      // CHECK FOR FLOORS
322
      if (typeof bidRequest.getFloor === 'function') {
3!
323
        imp.floor = bidRequest.getFloor({
×
324
          currency: 'USD',
325
          mediaType: '*',
326
          size: '*'
327
        });
328
      }
329

330
      // BUILD THE SIZES
331
      if (deepAccess(bidRequest, `mediaTypes.banner`)) {
3✔
332
        const sizes = getAdUnitSizes(bidRequest);
2✔
333
        if (sizes.length) {
2✔
334
          imp.banner = {
2✔
335
            w: sizes[0][0],
336
            h: sizes[0][1],
337
            format: sizes.map(size => ({ w: size[0], h: size[1] }))
2✔
338
          };
339

340
          // ADD TO THE LIST OF IMP REQUESTS
341
          imps.push(imp);
2✔
342
        }
343
      } else if (deepAccess(bidRequest, `mediaTypes.native`)) {
1✔
344
        // ADD TO THE LIST OF IMP REQUESTS
345
        imp.native = createNativeRequest(bidRequest);
1✔
346
        imps.push(imp);
1✔
347
      }
348
    });
349

350
    // RETURN EMPTY IF THERE WERE NO PROPER ADUNIT REQUESTS TO BE MADE
351
    if (!imps.length) {
1!
352
      return [];
×
353
    }
354

355
    // GENERATE SITE OBJECT
356
    const site = {
1✔
357
      domain: window.location.host,
358
      // TODO: is 'page' the right value here?
359
      page: bidderRequest.refererInfo.page,
360
      schain: validRequests[0]?.ortb2?.source?.ext?.schain || {},
2✔
361
      ext: {
362
        p_domain: bidderRequest.refererInfo.domain,
363
        rt: bidderRequest.refererInfo.reachedTop,
364
        frames: bidderRequest.refererInfo.numIframes,
365
        stack: bidderRequest.refererInfo.stack,
366
        timeout: config.getConfig('bidderTimeout')
367
      },
368
    };
369

370
    // ADD REF URL IF FOUND
371
    if (self === top && document.referrer) {
1!
372
      site.ref = document.referrer;
×
373
    }
374

375
    // ADD META KEYWORDS IF FOUND
376
    const keywords = document.getElementsByTagName('meta')['keywords'];
1✔
377
    if (keywords && keywords.content) {
1!
378
      site.keywords = keywords.content;
×
379
    }
380

381
    // GENERATE DEVICE OBJECT
382
    const device = {
1✔
383
      ip: 'peer',
384
      ua: window.navigator.userAgent,
385
      js: 1,
386
      language: ((navigator.language || navigator.userLanguage || '').split('-'))[0] || 'en',
2!
387
      buyerid: this.get_dbid() || 0,
2✔
388
      ext: {
389
        pb_eids: validRequests[0].userIdAsEids || {},
2✔
390
        syncs: this.get_syncs() || {},
1!
391
        coppa: config.getConfig('coppa') || 0,
2✔
392
        gdpr: bidderRequest.gdprConsent || {},
2✔
393
        usp: bidderRequest.uspConsent || {},
2✔
394
        client_info: this.get_client_info(),
395
        ortb2: bidderRequest.ortb2 || {}
2✔
396
      }
397
    };
398

399
    const sourceId = validRequests[0].params.source_id || 0;
1!
400
    const host = validRequests[0].params.host || 'prebid.dblks.net';
1!
401

402
    // RETURN WITH THE REQUEST AND PAYLOAD
403
    return {
1✔
404
      method: 'POST',
405
      url: `https://${host}/openrtb/?sid=${sourceId}`,
406
      data: {
407
        id: bidderRequest.bidderRequestId,
408
        imp: imps,
409
        site: site,
410
        device: device
411
      },
412
      options: {
413
        withCredentials: true
414
      }
415
    };
416
  },
417

418
  // INITIATE USER SYNCING
419
  getUserSyncs: function(options, rtbResponse, gdprConsent) {
420
    const syncs = [];
1✔
421
    const bidResponse = rtbResponse?.[0]?.body ?? null;
1!
422
    const scope = this;
1✔
423

424
    // LISTEN FOR SYNC DATA FROM IFRAME TYPE SYNC
425
    window.addEventListener('message', function (event) {
1✔
426
      if (event.data.sentinel && event.data.sentinel === 'dblks_syncData') {
2!
427
        // STORE FOUND SYNCS
428
        if (event.data.syncs) {
×
429
          scope.store_syncs(event.data.syncs);
×
430
        }
431
      }
432
    });
433

434
    // POPULATE GDPR INFORMATION
435
    const gdprData = {
1✔
436
      gdpr: 0,
437
      gdprConsent: ''
438
    }
439
    if (typeof gdprConsent === 'object') {
1✔
440
      if (typeof gdprConsent.gdprApplies === 'boolean') {
1!
441
        gdprData.gdpr = Number(gdprConsent.gdprApplies);
1✔
442
        gdprData.gdprConsent = gdprConsent.consentString;
1✔
443
      } else {
444
        gdprData.gdprConsent = gdprConsent.consentString;
×
445
      }
446
    }
447

448
    // EXTRACT BUYERID COOKIE VALUE FROM BID RESPONSE AND PUT INTO STORAGE
449
    let dbBuyerId = this.get_dbid() || '';
1✔
450
    if (bidResponse.ext && bidResponse.ext.buyerid) {
1✔
451
      dbBuyerId = bidResponse.ext.buyerid;
1✔
452
      this.store_dbid(dbBuyerId);
1✔
453
    }
454

455
    // EXTRACT USERSYNCS FROM BID RESPONSE
456
    if (bidResponse.ext && bidResponse.ext.syncs) {
1✔
457
      bidResponse.ext.syncs.forEach(sync => {
1✔
458
        if (checkValid(sync)) {
2✔
459
          syncs.push(addParams(sync));
2✔
460
        }
461
      })
462
    }
463

464
    // APPEND PARAMS TO SYNC URL
465
    function addParams(sync) {
466
      // PARSE THE URL
467
      try {
2✔
468
        const url = new URL(sync.url);
2✔
469
        const urlParams = {};
2✔
470
        for (const [key, value] of url.searchParams.entries()) {
2✔
471
          urlParams[key] = value;
×
472
        };
473

474
        // APPLY EXTRA VARS
475
        urlParams.gdpr = gdprData.gdpr;
2✔
476
        urlParams.gdprConsent = gdprData.gdprConsent;
2✔
477
        urlParams.bidid = bidResponse.bidid;
2✔
478
        urlParams.id = bidResponse.id;
2✔
479
        urlParams.uid = dbBuyerId;
2✔
480

481
        // REBUILD URL
482
        sync.url = `${url.origin}${url.pathname}?${Object.keys(urlParams).map(key => key + '=' + encodeURIComponent(urlParams[key])).join('&')}`;
10✔
483
      } catch (e) {};
484

485
      // RETURN THE REBUILT URL
486
      return sync;
2✔
487
    }
488

489
    // ENSURE THAT THE SYNC TYPE IS VALID AND HAS PERMISSION
490
    function checkValid(sync) {
491
      if (!sync.type || !sync.url) {
2!
492
        return false;
×
493
      }
494
      switch (sync.type) {
2!
495
        case 'iframe':
496
          return options.iframeEnabled;
1✔
497
        case 'image':
498
          return options.pixelEnabled;
1✔
499
        default:
500
          return false;
×
501
      }
502
    }
503
    return syncs;
1✔
504
  },
505

506
  // DATABLOCKS WON THE AUCTION - REPORT SUCCESS
507
  onBidWon: function(bid) {
508
    this.queue_metric({type: 'bid_won', source_id: bid.params[0].source_id, req_id: bid.requestId, slot_id: bid.adUnitCode, auction_id: bid.auctionId, size: bid.size, cpm: bid.cpm, pb: bid.adserverTargeting.hb_pb, rt: bid.timeToRespond, ttl: bid.ttl});
1✔
509
  },
510

511
  // TARGETING HAS BEEN SET
512
  onSetTargeting: function(bid) {
513
    // LISTEN FOR VIEWABILITY EVENTS
514
    this.get_viewability(bid);
1✔
515
  },
516

517
  // PARSE THE RTB RESPONSE AND RETURN FINAL RESULTS
518
  interpretResponse: function(rtbResponse, bidRequest) {
519
    // CONVERT NATIVE RTB RESPONSE INTO PREBID RESPONSE
520
    function parseNative(native) {
521
      const {assets, link, imptrackers, jstracker} = native;
1✔
522
      const result = {
1✔
523
        clickUrl: link.url,
524
        clickTrackers: link.clicktrackers || [],
2✔
525
        impressionTrackers: imptrackers || [],
1!
526
        javascriptTrackers: jstracker ? [jstracker] : []
1!
527
      };
528

529
      (assets || []).forEach((asset) => {
1!
530
        const {id, img, data, title} = asset;
3✔
531
        const key = NATIVE_ID_MAP[id];
3✔
532
        if (key) {
3✔
533
          if (!isEmpty(title)) {
3✔
534
            result.title = title.text
1✔
535
          } else if (!isEmpty(img)) {
2✔
536
            result[key] = {
1✔
537
              url: img.url,
538
              height: img.h,
539
              width: img.w
540
            }
541
          } else if (!isEmpty(data)) {
1✔
542
            result[key] = data.value;
1✔
543
          }
544
        }
545
      });
546

547
      return result;
1✔
548
    }
549

550
    const bids = [];
1✔
551
    const resBids = deepAccess(rtbResponse, 'body.seatbid') || [];
1!
552
    resBids.forEach(bid => {
1✔
553
      const resultItem = {requestId: bid.id, cpm: bid.price, creativeId: bid.crid, currency: bid.currency || 'USD', netRevenue: true, ttl: bid.ttl || 360, meta: {advertiserDomains: bid.adomain}};
3✔
554

555
      const mediaType = deepAccess(bid, 'ext.mtype') || '';
3!
556
      switch (mediaType) {
3!
557
        case 'banner':
558
          bids.push(Object.assign({}, resultItem, {mediaType: BANNER, width: bid.w, height: bid.h, ad: bid.adm}));
2✔
559
          break;
2✔
560

561
        case 'native':
562
          const nativeResult = JSON.parse(bid.adm);
1✔
563
          bids.push(Object.assign({}, resultItem, {mediaType: NATIVE, native: parseNative(nativeResult.native)}));
1✔
564
          break;
1✔
565

566
        default:
567
          break;
×
568
      }
569
    })
570

571
    return bids;
1✔
572
  }
573
};
574

575
// DETECT BOTS
576
export class BotClientTests {
577
  constructor() {
578
    this.tests = {
3✔
579
      headless_chrome: function() {
580
        if (self.navigator) {
3✔
581
          if (self.navigator.webdriver) {
3!
582
            return true;
×
583
          }
584
        }
585

586
        return false;
3✔
587
      },
588

589
      selenium: function () {
590
        let response = false;
3✔
591

592
        if (window && document) {
3✔
593
          const results = [
3✔
594
            'webdriver' in window,
595
            '_Selenium_IDE_Recorder' in window,
596
            'callSelenium' in window,
597
            '_selenium' in window,
598
            '__webdriver_script_fn' in document,
599
            '__driver_evaluate' in document,
600
            '__webdriver_evaluate' in document,
601
            '__selenium_evaluate' in document,
602
            '__fxdriver_evaluate' in document,
603
            '__driver_unwrapped' in document,
604
            '__webdriver_unwrapped' in document,
605
            '__selenium_unwrapped' in document,
606
            '__fxdriver_unwrapped' in document,
607
            '__webdriver_script_func' in document,
608
            document.documentElement.getAttribute('selenium') !== null,
609
            document.documentElement.getAttribute('webdriver') !== null,
610
            document.documentElement.getAttribute('driver') !== null
611
          ];
612

613
          results.forEach(result => {
3✔
614
            if (result === true) {
51!
615
              response = true;
×
616
            }
617
          })
618
        }
619

620
        return response;
3✔
621
      },
622
    }
623
  }
624
  doTests() {
625
    let response = false;
3✔
626
    for (const i of Object.keys(this.tests)) {
3✔
627
      if (this.tests[i]() === true) {
6!
628
        response = true;
×
629
      }
630
    }
631
    return response;
3✔
632
  }
633
}
634

635
// INIT OUR BIDDER WITH PREBID
636
registerBidder(spec);
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc