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

prebid / Prebid.js / 18136225893

30 Sep 2025 04:07PM UTC coverage: 96.245% (+0.006%) from 96.239%
18136225893

push

github

web-flow
Advertising Bid Adapter: Update the regex while parsing bid.impid to support the change to UUID format for bid ids (#13879)

51890 of 63472 branches covered (81.75%)

1 of 1 new or added line in 1 file covered. (100.0%)

70 existing lines in 12 files now uncovered.

198517 of 206262 relevant lines covered (96.25%)

125.12 hits per line

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

82.59
/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
import {getExtraWinDimensions} from '../libraries/extraWinDimensions/extraWinDimensions.js';
10
import {isWebdriverEnabled} from '../libraries/webdriver/webdriver.js';
11

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

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

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

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

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

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

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

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

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

124
    return stored;
2✔
125
  },
126

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

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

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

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

152
      return true;
1✔
153
    }
154
  },
155

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

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

176
      // RESET PREVIOUS TIMER
177
      if (this.db_obj.metrics_timer) {
×
UNCOV
178
        clearTimeout(this.db_obj.metrics_timer);
×
179
      }
180

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

UNCOV
187
      return true;
×
188
    } else {
UNCOV
189
      return false;
×
190
    }
191
  },
192

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

198
    // RESET THE QUEUE OF METRIC DATA
UNCOV
199
    this.db_obj.metrics = [];
×
200

UNCOV
201
    return true;
×
202
  },
203

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

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

234
      // ADD GPT EVENT LISTENERS
235
      const scope = this;
1✔
236
      if (isGptPubadsDefined()) {
1✔
237
        if (typeof window['googletag'].pubads().addEventListener === 'function') {
1✔
238
          // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781
239
          window['googletag'].pubads().addEventListener('impressionViewable', function(event) {
1✔
UNCOV
240
            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()});
×
241
          });
242
          window['googletag'].pubads().addEventListener('slotRenderEnded', function(event) {
1✔
UNCOV
243
            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()});
×
244
          })
245
        }
246
      }
247
    }
248
  },
249

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

258
    return !!(bid.params.source_id && bid.mediaTypes && (bid.mediaTypes.banner || bid.mediaTypes.native));
3!
259
  },
260

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

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

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

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

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

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

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

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

373
    // ADD REF URL IF FOUND
374
    if (self === top && document.referrer) {
1!
UNCOV
375
      site.ref = document.referrer;
×
376
    }
377

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

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

402
    const sourceId = validRequests[0].params.source_id || 0;
1!
403
    const host = validRequests[0].params.host || 'prebid.dblks.net';
1!
404

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

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

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

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

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

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

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

477
        // APPLY EXTRA VARS
478
        urlParams.gdpr = gdprData.gdpr;
2✔
479
        urlParams.gdprConsent = gdprData.gdprConsent;
2✔
480
        urlParams.bidid = bidResponse.bidid;
2✔
481
        urlParams.id = bidResponse.id;
2✔
482
        urlParams.uid = dbBuyerId;
2✔
483

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

488
      // RETURN THE REBUILT URL
489
      return sync;
2✔
490
    }
491

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

509
  // DATABLOCKS WON THE AUCTION - REPORT SUCCESS
510
  onBidWon: function(bid) {
511
    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✔
512
  },
513

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

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

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

550
      return result;
1✔
551
    }
552

553
    const bids = [];
1✔
554
    const resBids = deepAccess(rtbResponse, 'body.seatbid') || [];
1!
555
    resBids.forEach(bid => {
1✔
556
      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✔
557

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

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

569
        default:
UNCOV
570
          break;
×
571
      }
572
    })
573

574
    return bids;
1✔
575
  }
576
};
577

578
// DETECT BOTS
579
export class BotClientTests {
580
  constructor() {
581
    this.tests = {
3✔
582
      headless_chrome: function() {
583
        // Warning: accessing navigator.webdriver may impact fingerprinting scores when this API is included in the built script.
584
        return isWebdriverEnabled();
3✔
585
      },
586

587
      selenium: function () {
588
        let response = false;
3✔
589

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

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

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

633
// INIT OUR BIDDER WITH PREBID
634
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