mirror of
https://github.com/faisalman/ua-parser-js.git
synced 2025-11-15 22:52:16 +03:00
[test] Add tests for the new submodules
This commit is contained in:
42
test/unit/submodules/bot-detection.spec.js
Normal file
42
test/unit/submodules/bot-detection.spec.js
Normal file
@@ -0,0 +1,42 @@
|
||||
const assert = require('assert');
|
||||
const { UAParser } = require('../../../src/main/ua-parser');
|
||||
const { isAICrawler, isBot } = require('../../../src/bot-detection/bot-detection');
|
||||
const { Bots, Emails } = require('../../../src/extensions/ua-parser-extensions');
|
||||
|
||||
describe('isAICrawler()', () => {
|
||||
it('Can detect AI Crawlers', () => {
|
||||
|
||||
// AI Crawlers
|
||||
const claudeBot = 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)';
|
||||
const searchGPT = 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; OAI-SearchBot/1.0; +https://openai.com/searchbot';
|
||||
const semrushAI = 'Mozilla/5.0 (compatible; SemrushBot-OCOB/1; +https://www.semrush.com/bot/)';
|
||||
|
||||
assert.equal(isAICrawler(claudeBot), true);
|
||||
assert.equal(isAICrawler(searchGPT), true);
|
||||
assert.equal(isAICrawler(semrushAI), true);
|
||||
|
||||
// Non-AI Crawlers
|
||||
const firefox = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0';
|
||||
|
||||
assert.equal(isAICrawler(firefox), false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isBot()', () => {
|
||||
it('Can detect general Bots', () => {
|
||||
|
||||
// Bots
|
||||
const ahrefsBot = 'Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)';
|
||||
const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)';
|
||||
|
||||
assert.equal(isBot(ahrefsBot), true);
|
||||
assert.equal(isBot(scrapy), true);
|
||||
|
||||
// Non-bots
|
||||
const firefox = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0';
|
||||
const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0';
|
||||
|
||||
assert.equal(isBot(firefox), false);
|
||||
assert.equal(isBot(thunderbird), false);
|
||||
});
|
||||
});
|
||||
16
test/unit/submodules/browser-detection.spec.js
Normal file
16
test/unit/submodules/browser-detection.spec.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const assert = require('assert');
|
||||
const { UAParser } = require('../../../src/main/ua-parser');
|
||||
const { isChromeFamily } = require('../../../src/browser-detection/browser-detection');
|
||||
|
||||
describe('isChromeFamily()', () => {
|
||||
it('Can detect Chromium-based browser', () => {
|
||||
|
||||
const edge = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.2151.58';
|
||||
const firefox = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0';
|
||||
|
||||
assert.equal(isChromeFamily(UAParser(edge)), true);
|
||||
assert.equal(isChromeFamily(edge), true);
|
||||
assert.equal(isChromeFamily(UAParser(firefox)), false);
|
||||
assert.equal(isChromeFamily(firefox), false);
|
||||
});
|
||||
});
|
||||
32
test/unit/submodules/device-detection.spec.js
Normal file
32
test/unit/submodules/device-detection.spec.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const assert = require('assert');
|
||||
const { UAParser } = require('../../../src/main/ua-parser');
|
||||
const { getDeviceVendor, isAppleSilicon } = require('../../../src/device-detection/device-detection');
|
||||
const { DeviceVendor } = require('../../../src/enums/ua-parser-enums');
|
||||
|
||||
describe('getDeviceVendor()', () => {
|
||||
it('Can guess the device vendor from a model name', () => {
|
||||
|
||||
const sm = 'SM-A605G';
|
||||
const redmi = 'Redmi Note 8';
|
||||
const nexus = 'Nexus 6P';
|
||||
const aquos = 'AQUOS-TVX19B';
|
||||
|
||||
assert.equal(getDeviceVendor(sm), DeviceVendor.SAMSUNG);
|
||||
assert.equal(getDeviceVendor(redmi), DeviceVendor.XIAOMI);
|
||||
assert.equal(getDeviceVendor(nexus), DeviceVendor.HUAWEI);
|
||||
assert.equal(getDeviceVendor(aquos), DeviceVendor.SHARP);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAppleSilicon()', () => {
|
||||
it('Can detect Apple Silicon device', () => {
|
||||
|
||||
const macARM = 'Mozilla/5.0 (Macintosh; ARM; Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0';
|
||||
const macIntel = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0';
|
||||
|
||||
assert.equal(isAppleSilicon(UAParser(macIntel)), false);
|
||||
assert.equal(isAppleSilicon(macIntel), false);
|
||||
assert.equal(isAppleSilicon(UAParser(macARM)), true);
|
||||
assert.equal(isAppleSilicon(macARM), true);
|
||||
});
|
||||
});
|
||||
116
test/unit/submodules/extensions.spec.js
Normal file
116
test/unit/submodules/extensions.spec.js
Normal file
@@ -0,0 +1,116 @@
|
||||
const fs = require('fs');
|
||||
const assert = require('assert');
|
||||
const parseJS = require('@babel/parser').parse;
|
||||
const traverse = require('@babel/traverse').default;
|
||||
const safe = require('safe-regex');
|
||||
const { UAParser } = require('../../../src/main/ua-parser');
|
||||
const { Bots, CLIs, Crawlers, Emails, Fetchers, InApps, Libraries, Vehicles } = require('../../../src/extensions/ua-parser-extensions');
|
||||
const { BrowserType, OSName, Extension } = require('../../../src/enums/ua-parser-enums');
|
||||
const { CLI, Crawler, Email, Fetcher, Library } = Extension.BrowserName;
|
||||
|
||||
describe('Extensions', () => {
|
||||
[
|
||||
['CLIs', 'cli', CLIs],
|
||||
['Crawlers', 'crawler', Crawlers],
|
||||
['Emails', 'email', Emails],
|
||||
['Fetchers', 'fetcher', Fetchers],
|
||||
['InApps', 'inapp', InApps],
|
||||
['Libraries', 'library', Libraries],
|
||||
['Vehicles', 'vehicle', Vehicles]
|
||||
]
|
||||
.forEach(([desc, path, ext]) => {
|
||||
const tests = require(`../data/ua/extension/${path}.json`);
|
||||
describe(desc, () => {
|
||||
tests.forEach((test) => {
|
||||
it(`Can detect ${test.desc}: "${test.ua}"`, () => {
|
||||
const { browser, device } = UAParser(test.ua, ext);
|
||||
if ('browser' in ext) {
|
||||
assert.strictEqual(String(browser.name), test.expect.name);
|
||||
assert.strictEqual(String(browser.version), test.expect.version);
|
||||
assert.strictEqual(String(browser.type), test.expect.type);
|
||||
} else if ('device' in ext) {
|
||||
assert.strictEqual(String(device.vendor), test.expect.vendor);
|
||||
assert.strictEqual(String(device.model), test.expect.model);
|
||||
assert.strictEqual(String(device.type), test.expect.type);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const outlook = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.9126; Microsoft Outlook 16.0.9126; ms-office; MSOffice 16)';
|
||||
const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0';
|
||||
const axios = 'axios/1.3.5';
|
||||
const jsdom = 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3';
|
||||
const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)';
|
||||
|
||||
assert.equal(UAParser(scrapy, Bots).browser.name, Library.SCRAPY);
|
||||
|
||||
const emailParser = new UAParser(Emails);
|
||||
assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: Email.MICROSOFT_OUTLOOK, version: "16.0.9126", major: "16", type: BrowserType.EMAIL});
|
||||
assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: Email.THUNDERBIRD, version: "78.13.0", major: "78", type: BrowserType.EMAIL});
|
||||
|
||||
const libraryParser = new UAParser(Libraries);
|
||||
assert.deepEqual(libraryParser.setUA(axios).getBrowser(), {name: Library.AXIOS, version: "1.3.5", major: "1", type: BrowserType.LIBRARY});
|
||||
assert.deepEqual(libraryParser.setUA(jsdom).getBrowser(), {name: Library.JSDOM, version: "20.0.3", major: "20", type: BrowserType.LIBRARY});
|
||||
assert.deepEqual(libraryParser.setUA(scrapy).getBrowser(), {name: Library.SCRAPY, version: "1.5.0", major: "1", type: BrowserType.LIBRARY});
|
||||
|
||||
// Bluesky
|
||||
const bluesky = 'Mozilla/5.0 (compatible; Bluesky Cardyb/1.1; +mailto:support@bsky.app)';
|
||||
assert.deepEqual(new UAParser(bluesky, Bots).getBrowser(), {
|
||||
name: Fetcher.BLUESKY,
|
||||
version: '1.1',
|
||||
major: '1',
|
||||
type: BrowserType.FETCHER
|
||||
});
|
||||
|
||||
const whatsapp = "WhatsApp/2.0 A";
|
||||
assert.deepEqual(new UAParser(whatsapp, Fetchers).getOS(), {
|
||||
name : OSName.ANDROID,
|
||||
version : undefined
|
||||
});
|
||||
});
|
||||
|
||||
describe('Merge', () => {
|
||||
it('Can merge multiple extensions', () => {
|
||||
const wget = 'Wget/1.21.1';
|
||||
const facebookBot = 'Mozilla/5.0 (compatible; FacebookBot/1.0; +https://developers.facebook.com/docs/sharing/webmasters/facebookbot/)';
|
||||
|
||||
// try merging crawlers & CLIs
|
||||
const crawlersAndCLIs = { browser : [...Crawlers.browser, ...CLIs.browser]};
|
||||
const crawlersAndCLIsParser = new UAParser(crawlersAndCLIs);
|
||||
assert.deepEqual(crawlersAndCLIsParser.setUA(wget).getBrowser(), {name: CLI.WGET, version: "1.21.1", major: "1", type: BrowserType.CLI});
|
||||
assert.deepEqual(crawlersAndCLIsParser.setUA(facebookBot).getBrowser(), {name: Crawler.META_FACEBOOKBOT, version: "1.0", major: "1", type: BrowserType.CRAWLER});
|
||||
|
||||
// alternative merge options
|
||||
const crawlersAndCLIsParser2 = new UAParser([Crawlers, CLIs]);
|
||||
const crawlersAndCLIsParser3 = new UAParser(facebookBot, [Crawlers, CLIs]);
|
||||
assert.deepEqual(crawlersAndCLIsParser2.setUA(wget).getBrowser(), {name: CLI.WGET, version: "1.21.1", major: "1", type: BrowserType.CLI});
|
||||
assert.deepEqual(crawlersAndCLIsParser3.getBrowser(), {name: Crawler.META_FACEBOOKBOT, version: "1.0", major: "1", type: BrowserType.CRAWLER});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing the safety of regexes', () => {
|
||||
|
||||
let regexes;
|
||||
let code = fs.readFileSync('src/extensions/ua-parser-extensions.js', 'utf8').toString();
|
||||
let ast = parseJS(code, { sourceType: 'script' });
|
||||
regexes = [];
|
||||
traverse(ast, {
|
||||
RegExpLiteral: (path) => {
|
||||
regexes.push(path.node.pattern);
|
||||
}
|
||||
});
|
||||
|
||||
if (regexes.length === 0) {
|
||||
throw new Error('Regexes cannot be empty!');
|
||||
}
|
||||
|
||||
describe('Checking for potentially vulnerable regex', () => {
|
||||
for (let regex of regexes) {
|
||||
it('Test against `safe-regex` : ' + regex, () => {
|
||||
assert.strictEqual(safe(regex), true);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
13
test/unit/submodules/helpers.spec.js
Normal file
13
test/unit/submodules/helpers.spec.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const assert = require('assert');
|
||||
const { isFrozenUA } = require('../../../src/helpers/ua-parser-helpers');
|
||||
|
||||
describe('isFrozenUA()', () => {
|
||||
it('matches supplied user-agent string with known frozen user-agent pattern', () => {
|
||||
|
||||
const regularMobileUA = "Mozilla/5.0 (Linux; Android 9; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.1234.56 Mobile Safari/537.36";
|
||||
const frozenMobileUA = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Mobile Safari/537.36";
|
||||
|
||||
assert.equal(isFrozenUA(regularMobileUA), false);
|
||||
assert.equal(isFrozenUA(frozenMobileUA), true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user