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

lancedikson / bowser / #676

31 Jan 2026 05:08PM UTC coverage: 89.113%. Remained the same
#676

push

github

naorpeled
Merge branch 'master' of github.com:bowser-js/bowser

369 of 490 branches covered (75.31%)

Branch coverage included in aggregate %.

6 of 6 new or added lines in 2 files covered. (100.0%)

3 existing lines in 2 files now uncovered.

736 of 750 relevant lines covered (98.13%)

354.56 hits per line

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

97.44
/src/parser-platforms.js
1
import Utils from './utils.js';
2
import { PLATFORMS_MAP } from './constants.js';
3

4
/*
5
 * Tablets go first since usually they have more specific
6
 * signs to detect.
7
 */
8

9
export default [
10
  /* Googlebot */
11
  {
12
    test: [/googlebot/i],
13
    describe() {
14
      return {
6✔
15
        type: PLATFORMS_MAP.bot,
16
        vendor: 'Google',
17
      };
18
    },
19
  },
20

21
  /* AmazonBot */
22
  {
23
    test: [/amazonbot/i],
24
    describe() {
25
      return {
2✔
26
        type: PLATFORMS_MAP.bot,
27
        vendor: 'Amazon',
28
      };
29
    },
30
  },
31

32
  /* GPTBot */
33
  {
34
    test: [/gptbot/i],
35
    describe() {
36
      return {
2✔
37
        type: PLATFORMS_MAP.bot,
38
        vendor: 'OpenAI',
39
      };
40
    },
41
  },
42

43
  /* ChatGPT-User */
44
  {
45
    test: [/chatgpt-user/i],
46
    describe() {
47
      return {
2✔
48
        type: PLATFORMS_MAP.bot,
49
        vendor: 'OpenAI',
50
      };
51
    },
52
  },
53

54
  /* OAI-SearchBot */
55
  {
56
    test: [/oai-searchbot/i],
57
    describe() {
58
      return {
2✔
59
        type: PLATFORMS_MAP.bot,
60
        vendor: 'OpenAI',
61
      };
62
    },
63
  },
64

65
  /* Baidu */
66
  {
67
    test: [/baiduspider/i],
68
    describe() {
69
      return {
2✔
70
        type: PLATFORMS_MAP.bot,
71
        vendor: 'Baidu',
72
      };
73
    },
74
  },
75

76
  /* Bingbot */
77
  {
78
    test: [/bingbot/i],
79
    describe() {
80
      return {
6✔
81
        type: PLATFORMS_MAP.bot,
82
        vendor: 'Bing',
83
      };
84
    },
85
  },
86

87
  /* DuckDuckBot */
88
  {
89
    test: [/duckduckbot/i],
90
    describe() {
91
      return {
2✔
92
        type: PLATFORMS_MAP.bot,
93
        vendor: 'DuckDuckGo',
94
      };
95
    },
96
  },
97

98
  /* ClaudeBot */
99
  {
100
    test: [/claudebot/i, /claude-web/i, /claude-user/i, /claude-searchbot/i],
101
    describe() {
102
      return {
2✔
103
        type: PLATFORMS_MAP.bot,
104
        vendor: 'Anthropic',
105
      };
106
    },
107
  },
108

109
  /* Omgilibot */
110
  {
111
    test: [/omgilibot/i, /webzio-extended/i],
112
    describe() {
113
      return {
2✔
114
        type: PLATFORMS_MAP.bot,
115
        vendor: 'Webz.io',
116
      };
117
    },
118
  },
119

120
  /* Diffbot */
121
  {
122
    test: [/diffbot/i],
123
    describe() {
124
      return {
2✔
125
        type: PLATFORMS_MAP.bot,
126
        vendor: 'Diffbot',
127
      };
128
    },
129
  },
130

131
  /* PerplexityBot */
132
  {
133
    test: [/perplexitybot/i],
134
    describe() {
135
      return {
2✔
136
        type: PLATFORMS_MAP.bot,
137
        vendor: 'Perplexity AI',
138
      };
139
    },
140
  },
141

142
  /* Perplexity-User */
143
  {
144
    test: [/perplexity-user/i],
145
    describe() {
146
      return {
2✔
147
        type: PLATFORMS_MAP.bot,
148
        vendor: 'Perplexity AI',
149
      };
150
    },
151
  },
152

153
  /* YouBot */
154
  {
155
    test: [/youbot/i],
156
    describe() {
157
      return {
2✔
158
        type: PLATFORMS_MAP.bot,
159
        vendor: 'You.com',
160
      };
161
    },
162
  },
163

164
  /* Internet Archive Crawler */
165
  {
166
    test: [/ia_archiver/i],
167
    describe() {
168
      return {
2✔
169
        type: PLATFORMS_MAP.bot,
170
        vendor: 'Internet Archive',
171
      };
172
    },
173
  },
174

175
  /* Meta-WebIndexer */
176
  {
177
    test: [/meta-webindexer/i],
178
    describe() {
179
      return {
4✔
180
        type: PLATFORMS_MAP.bot,
181
        vendor: 'Meta',
182
      };
183
    },
184
  },
185

186
  /* Meta-ExternalAds */
187
  {
188
    test: [/meta-externalads/i],
189
    describe() {
190
      return {
4✔
191
        type: PLATFORMS_MAP.bot,
192
        vendor: 'Meta',
193
      };
194
    },
195
  },
196

197
  /* Meta-ExternalAgent */
198
  {
199
    test: [/meta-externalagent/i],
200
    describe() {
201
      return {
4✔
202
        type: PLATFORMS_MAP.bot,
203
        vendor: 'Meta',
204
      };
205
    },
206
  },
207

208
  /* Meta-ExternalFetcher */
209
  {
210
    test: [/meta-externalfetcher/i],
211
    describe() {
212
      return {
4✔
213
        type: PLATFORMS_MAP.bot,
214
        vendor: 'Meta',
215
      };
216
    },
217
  },
218

219
  /* Meta Web Crawler */
220
  {
221
    test: [/facebookexternalhit/i, /facebookcatalog/i],
222
    describe() {
223
      return {
6✔
224
        type: PLATFORMS_MAP.bot,
225
        vendor: 'Meta',
226
      };
227
    },
228
  },
229

230
  /* SlackBot */
231
  {
232
    test: [/slackbot/i, /slack-imgProxy/i],
233
    describe() {
234
      return {
6✔
235
        type: PLATFORMS_MAP.bot,
236
        vendor: 'Slack',
237
      };
238
    },
239
  },
240

241
  /* Yahoo! Slurp */
242
  {
243
    test: [/yahoo/i],
244
    describe() {
245
      return {
2✔
246
        type: PLATFORMS_MAP.bot,
247
        vendor: 'Yahoo',
248
      };
249
    },
250
  },
251

252
  /* Yandex */
253
  {
254
    test: [/yandexbot/i, /yandexmobilebot/i],
255
    describe() {
256
      return {
4✔
257
        type: PLATFORMS_MAP.bot,
258
        vendor: 'Yandex',
259
      };
260
    },
261
  },
262

263
  /* Pingdom */
264
  {
265
    test: [/pingdom/i],
266
    describe() {
267
      return {
2✔
268
        type: PLATFORMS_MAP.bot,
269
        vendor: 'Pingdom',
270
      };
271
    },
272
  },
273

274
  /* Huawei */
275
  {
276
    test: [/huawei/i],
277
    describe(ua) {
278
      const model = Utils.getFirstMatch(/(can-l01)/i, ua) && 'Nova';
6✔
279
      const platform = {
6✔
280
        type: PLATFORMS_MAP.mobile,
281
        vendor: 'Huawei',
282
      };
283
      if (model) {
6✔
284
        platform.model = model;
2✔
285
      }
286
      return platform;
6✔
287
    },
288
  },
289

290
  /* Nexus Tablet */
291
  {
292
    test: [/nexus\s*(?:7|8|9|10).*/i],
293
    describe() {
294
      return {
10✔
295
        type: PLATFORMS_MAP.tablet,
296
        vendor: 'Nexus',
297
      };
298
    },
299
  },
300

301
  /* iPad */
302
  {
303
    test: [/ipad/i],
304
    describe() {
305
      return {
16✔
306
        type: PLATFORMS_MAP.tablet,
307
        vendor: 'Apple',
308
        model: 'iPad',
309
      };
310
    },
311
  },
312

313
  /* Firefox on iPad */
314
  {
315
    test: [/Macintosh(.*?) FxiOS(.*?)\//],
316
    describe() {
317
      return {
4✔
318
        type: PLATFORMS_MAP.tablet,
319
        vendor: 'Apple',
320
        model: 'iPad',
321
      };
322
    },
323
  },
324

325
  /* Amazon Kindle Fire */
326
  {
327
    test: [/kftt build/i],
328
    describe() {
329
      return {
4✔
330
        type: PLATFORMS_MAP.tablet,
331
        vendor: 'Amazon',
332
        model: 'Kindle Fire HD 7',
333
      };
334
    },
335
  },
336

337
  /* Another Amazon Tablet with Silk */
338
  {
339
    test: [/silk/i],
340
    describe() {
341
      return {
4✔
342
        type: PLATFORMS_MAP.tablet,
343
        vendor: 'Amazon',
344
      };
345
    },
346
  },
347

348
  /* Tablet */
349
  {
350
    test: [/tablet(?! pc)/i],
351
    describe() {
352
      return {
16✔
353
        type: PLATFORMS_MAP.tablet,
354
      };
355
    },
356
  },
357

358
  /* iPod/iPhone */
359
  {
360
    test(parser) {
361
      const iDevice = parser.test(/ipod|iphone/i);
388✔
362
      const likeIDevice = parser.test(/like (ipod|iphone)/i);
388✔
363
      return iDevice && !likeIDevice;
388✔
364
    },
365
    describe(ua) {
366
      const model = Utils.getFirstMatch(/(ipod|iphone)/i, ua);
52✔
367
      return {
52✔
368
        type: PLATFORMS_MAP.mobile,
369
        vendor: 'Apple',
370
        model,
371
      };
372
    },
373
  },
374

375
  /* Nexus Mobile */
376
  {
377
    test: [/nexus\s*[0-6].*/i, /galaxy nexus/i],
378
    describe() {
379
      return {
14✔
380
        type: PLATFORMS_MAP.mobile,
381
        vendor: 'Nexus',
382
      };
383
    },
384
  },
385

386
  /* Nokia */
387
  {
388
    test: [/Nokia/i],
389
    describe(ua) {
390
      const model = Utils.getFirstMatch(/Nokia\s+([0-9]+(\.[0-9]+)?)/i, ua);
8✔
391
      const platform = {
8✔
392
        type: PLATFORMS_MAP.mobile,
393
        vendor: 'Nokia',
394
      };
395
      if (model) {
8✔
396
        platform.model = model;
2✔
397
      }
398
      return platform;
8✔
399
    },
400
  },
401

402
  /* Mobile */
403
  {
404
    test: [/[^-]mobi/i],
405
    describe() {
406
      return {
74✔
407
        type: PLATFORMS_MAP.mobile,
408
      };
409
    },
410
  },
411

412
  /* BlackBerry */
413
  {
414
    test(parser) {
415
      return parser.getBrowserName(true) === 'blackberry';
240✔
416
    },
417
    describe() {
418
      return {
6✔
419
        type: PLATFORMS_MAP.mobile,
420
        vendor: 'BlackBerry',
421
      };
422
    },
423
  },
424

425
  /* Bada */
426
  {
427
    test(parser) {
428
      return parser.getBrowserName(true) === 'bada';
234✔
429
    },
430
    describe() {
431
      return {
2✔
432
        type: PLATFORMS_MAP.mobile,
433
      };
434
    },
435
  },
436

437
  /* Windows Phone */
438
  {
439
    test(parser) {
440
      return parser.getBrowserName() === 'windows phone';
232✔
441
    },
442
    describe() {
UNCOV
443
      return {
×
444
        type: PLATFORMS_MAP.mobile,
445
        vendor: 'Microsoft',
446
      };
447
    },
448
  },
449

450
  /* Android Tablet */
451
  {
452
    test(parser) {
453
      const osMajorVersion = Number(String(parser.getOSVersion()).split('.')[0]);
232✔
454
      return parser.getOSName(true) === 'android' && (osMajorVersion >= 3);
232✔
455
    },
456
    describe() {
457
      return {
14✔
458
        type: PLATFORMS_MAP.tablet,
459
      };
460
    },
461
  },
462

463
  /* Android Mobile */
464
  {
465
    test(parser) {
466
      return parser.getOSName(true) === 'android';
218✔
467
    },
468
    describe() {
UNCOV
469
      return {
×
470
        type: PLATFORMS_MAP.mobile,
471
      };
472
    },
473
  },
474

475
  /* desktop */
476
  {
477
    test(parser) {
478
      return parser.getOSName(true) === 'macos';
218✔
479
    },
480
    describe() {
481
      return {
62✔
482
        type: PLATFORMS_MAP.desktop,
483
        vendor: 'Apple',
484
      };
485
    },
486
  },
487

488
  /* Windows */
489
  {
490
    test(parser) {
491
      return parser.getOSName(true) === 'windows';
156✔
492
    },
493
    describe() {
494
      return {
98✔
495
        type: PLATFORMS_MAP.desktop,
496
      };
497
    },
498
  },
499

500
  /* Linux */
501
  {
502
    test(parser) {
503
      return parser.getOSName(true) === 'linux';
58✔
504
    },
505
    describe() {
506
      return {
40✔
507
        type: PLATFORMS_MAP.desktop,
508
      };
509
    },
510
  },
511

512
  /* PlayStation 4 */
513
  {
514
    test(parser) {
515
      return parser.getOSName(true) === 'playstation 4';
18✔
516
    },
517
    describe() {
518
      return {
2✔
519
        type: PLATFORMS_MAP.tv,
520
      };
521
    },
522
  },
523

524
  /* Roku */
525
  {
526
    test(parser) {
527
      return parser.getOSName(true) === 'roku';
16✔
528
    },
529
    describe() {
530
      return {
4✔
531
        type: PLATFORMS_MAP.tv,
532
      };
533
    },
534
  },
535
];
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