Skip to content

Commit

Permalink
refactor: split the main file into 3 (#514)
Browse files Browse the repository at this point in the history
* refactor: split the file into 3

* test: add vscode test runner config

* chore: remove unused var
  • Loading branch information
pure-js committed Aug 23, 2023
1 parent c2516f4 commit cb89f91
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 84 deletions.
19 changes: 19 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Current Test File",
"autoAttachChildProcesses": true,
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
"program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
"args": ["run", "${relativeFile}"],
"smartStep": true,
"console": "integratedTerminal"
}
]
}
13 changes: 0 additions & 13 deletions src/browser-detection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { describe, expect, test } from 'vitest';

import {
detectBrowserName,
detectBrowserVersion,
detectBrowserNameAndVersion,
} from './browser-detection';

Expand Down Expand Up @@ -211,15 +210,3 @@ describe('Should correctly detect name of', () => {
expect(detectBrowserName(chrome)).toEqual('Chrome');
});
});

describe('Should correctly detect version of', () => {
test('UC Browser', () => {
const ucBrowser = {
userAgent: `UCWEB/2.0 (Java; U; MIDP-2.0; Nokia203/20.37)
U2/1.0.0 UCBrowser/8.7.0.218 U2/1.0.0 Mobile`,
};
const name = 'UC Browser';

expect(detectBrowserVersion(ucBrowser, name)).toEqual(8.7);
});
});
56 changes: 2 additions & 54 deletions src/browser-detection.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { retrieveVersion } from './retrieve-version';

import { detectBrowserVersion } from './detect-browser-version';
/**
* Detects Chrome browser
*/
Expand Down Expand Up @@ -154,7 +153,7 @@ export type UaBrowserName =
/**
* Returns Association
*/
function getBrowserUaName(
export function getBrowserUaName(
name: BrowserName | undefined,
): UaBrowserName | undefined {
if (name) {
Expand All @@ -173,57 +172,6 @@ function getBrowserUaName(
}
}

/**
* Detects browser version
*/
function detectBrowserVersion(
nav: {
userAgent: string;
appName?: string;
appVersion?: string;
},
name: BrowserName | undefined,
): number | undefined {
const { userAgent } = nav;

if (name) {
// eslint-disable-next-line default-case, @typescript-eslint/switch-exhaustiveness-check
switch (name) {
case 'Edge': {
const temp = /\b(Edge)\/(\d+)/.exec(userAgent);
return temp ? Number(temp[2]) : undefined;
}

case 'IE': {
const temp = /\brv[ :]+(\d+)/g.exec(userAgent) ?? [];
return Number(temp[1]) || undefined;
}
}
}

const browserName = getBrowserUaName(name);

if (browserName) {
return retrieveVersion(browserName, userAgent);
}

let found =
/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i.exec(
userAgent,
) ?? [];

// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error
// @ts-ignore
found = found[2] ? [found[1], found[2]] : [nav.appName, nav.appVersion, '-?'];

let temp;
if ((temp = /version\/(\d+)/i.exec(userAgent)) !== null) {
found.splice(1, 1, temp[1]);
}

return found[1] ? Number(found[1]) : undefined;
}

/**
* Detects browser name & version
*/
Expand Down
185 changes: 185 additions & 0 deletions src/detect-browser-version.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/* eslint-disable no-warning-comments */
import { describe, expect, test } from 'vitest';

import { detectBrowserVersion } from './detect-browser-version';

describe('Should correctly detect name & version of', () => {
test('Chrome', () => {
const chrome = {
userAgent: `Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/62.0.3202.94 Safari/537.36`,
};

expect(detectBrowserVersion(chrome, 'Chrome')).toStrictEqual(62);

const chromeMobile = {
userAgent: `Mozilla/5.0 (Linux; Android 6.0;
Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/62.0.3202.94 Mobile Safari/537.36`,
};

expect(detectBrowserVersion(chromeMobile, 'Chrome')).toStrictEqual(62);
});

test('Safari 17', () => {
const safari = {
userAgent: `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15`,
};

expect(detectBrowserVersion(safari, 'Safari')).toStrictEqual(17);
});

test('Safari', () => {
const safari = {
userAgent: `Mozilla/5.0 (Macintosh;
Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko)
Version/11.0.1 Safari/604.3.5`,
};

expect(detectBrowserVersion(safari, 'Safari')).toStrictEqual(11);
});

test('Safari iPad', () => {
const safari = {
userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15',
};
expect(detectBrowserVersion(safari, 'Safari')).toStrictEqual(17);
});

test('Samsung Internet', () => {
const samsung = {
userAgent: `Mozilla/5.0 (Linux; Android 5.1.1;
SAMSUNG SM-G360T1 Build/LMY47X)
AppleWebKit/537.36 (KHTML, like Gecko)
SamsungBrowser/3.3 Chrome/38.0.2125.102 Mobile Safari/537.36`,
};

expect(detectBrowserVersion(samsung, 'Samsung Internet')).toStrictEqual(3);
});

test('UC Browser', () => {
const ucBrowser = {
userAgent: `UCWEB/2.0 (Java; U; MIDP-2.0; Nokia203/20.37)
U2/1.0.0 UCBrowser/8.7.0.218 U2/1.0.0 Mobile`,
};

expect(detectBrowserVersion(ucBrowser, 'UC Browser')).toStrictEqual(8.7);

const ucBrowser11 = {
userAgent: `Mozilla/5.0 (Linux; U; Android 4.2.2; en-US;
Micromax A102 Build/MicromaxA102) AppleWebKit/534.30
(KHTML, like Gecko) Version/4.0 UCBrowser/11.1.0.882 U3/0.8.0
Mobile Safari/534.30`,
};

expect(detectBrowserVersion(ucBrowser11, 'UC Browser')).toStrictEqual(11);
});

test('Firefox', () => {
const firefox = {
userAgent: `Mozilla/5.0
(Windows NT 10.0; Win64; x64; rv:57.0)
Gecko/20100101 Firefox/57.0`,
};

expect(detectBrowserVersion(firefox, 'Firefox')).toStrictEqual(57);
});

test('QQ Browser', () => {
const qqbrowser = {
userAgent: `Mozilla/5.0 (Linux; U; Android 11; zh-cn; 21091116UC Build/RP1A.200720.011)
AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0
Chrome/66.0.3359.126 MQQBrowser/10.8 Mobile Safari/537.36`,
};
// TODO: change from 10 to 10.8
expect(detectBrowserVersion(qqbrowser, 'QQ Browser')).toStrictEqual(10);
});

describe('Opera', () => {
test('Blink-based', () => {
const opera = {
userAgent: `Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/62.0.3202.89 Safari/537.36 OPR/49.0.2725.39`,
};

expect(detectBrowserVersion(opera, 'Opera')).toStrictEqual(49);
});
});

test('Android browser', () => {
const android = {
userAgent: `Mozilla/5.0 (Linux; U; Android 4.0.4;
pt-br; MZ608 Build/7.7.1-141-7-FLEM-UMTS-LA)
AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30`,
};

expect(detectBrowserVersion(android, 'Android Browser')).toStrictEqual(4);
});

test('Edge', () => {
const edge = {
userAgent: `Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063`,
};

expect(detectBrowserVersion(edge, 'Edge')).toStrictEqual(15);
});

test('Internet Explorer', () => {
const ie = {
userAgent: `Mozilla/5.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; rv:11.0) like Gecko`,
};

expect(detectBrowserVersion(ie, 'IE')).toStrictEqual(11);
});
});

describe('Should not fail', () => {
test('If can not find a version', () => {
const ieWithoutVersion = {
userAgent: `Mozilla/5.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) like Gecko`,
};

expect(detectBrowserVersion(ieWithoutVersion, 'IE')).toEqual(undefined);
});

test('if user agent is invalid', () => {
const emptyUserAgent = {
userAgent: '',
};

expect(detectBrowserVersion(emptyUserAgent, undefined)).toEqual(undefined);
});
});

describe('Should correctly detect name of', () => {
test('Chrome', () => {
const chrome = {
userAgent: `Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/62.0.3202.94 Safari/537.36`,
};

expect(detectBrowserVersion(chrome, 'Chrome')).toEqual(62);
});
});

describe('Should correctly detect version of', () => {
test('UC Browser', () => {
const ucBrowser = {
userAgent: `UCWEB/2.0 (Java; U; MIDP-2.0; Nokia203/20.37)
U2/1.0.0 UCBrowser/8.7.0.218 U2/1.0.0 Mobile`,
};

expect(detectBrowserVersion(ucBrowser, 'UC Browser')).toEqual(8.7);
});
});
55 changes: 55 additions & 0 deletions src/detect-browser-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { retrieveVersion } from './retrieve-version';
import { getBrowserUaName } from './browser-detection';

import type { BrowserName } from './browser-detection';

/**
* Detects browser version
*/
export function detectBrowserVersion(
nav: {
userAgent: string;
appName?: string;
appVersion?: string;
},
name: BrowserName | undefined,
): number | undefined {
const { userAgent } = nav;

if (name) {
// eslint-disable-next-line default-case, @typescript-eslint/switch-exhaustiveness-check
switch (name) {
case 'Edge': {
const temp = /\b(Edge)\/(\d+)/.exec(userAgent);
return temp ? Number(temp[2]) : undefined;
}

case 'IE': {
const temp = /\brv[ :]+(\d+)/g.exec(userAgent) ?? [];
return Number(temp[1]) || undefined;
}
}
}

const browserName = getBrowserUaName(name);

if (browserName) {
return retrieveVersion(browserName, userAgent);
}

let found =
/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i.exec(
userAgent,
) ?? [];

// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error
// @ts-ignore
found = found[2] ? [found[1], found[2]] : [nav.appName, nav.appVersion, '-?'];

let temp;
if ((temp = /version\/(\d+)/i.exec(userAgent)) !== null) {
found.splice(1, 1, temp[1]);
}

return found[1] ? Number(found[1]) : undefined;
}
12 changes: 12 additions & 0 deletions src/retrieve-version.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { describe, expect, test } from 'vitest';

import { retrieveVersion } from './retrieve-version';

describe('Should correctly eject browser version from string', () => {
test('Opera', () => {
const userAgent = `Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/62.0.3202.89 Safari/537.36 OPR/49.0.2725.39`;
expect(retrieveVersion('OPR', userAgent)).toEqual(49);
});
});

0 comments on commit cb89f91

Please sign in to comment.