Skip to content

Commit ce47b9c

Browse files
authored
feat: add WebDriverIO support and tests (#8)
* feat: add WebDriverIO support and tests * docs: update readme test section * docs: .
1 parent e988383 commit ce47b9c

File tree

5 files changed

+59
-74
lines changed

5 files changed

+59
-74
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,21 @@ const { detect } = require('detect-browser-es')
3939
## New Features
4040

4141
- Detect [Happy DOM](https://github.com/capricorn86/happy-dom) and [JSDOM](https://github.com/jsdom/jsdom) when using test environments like [Vitest](https://github.com/vitest-dev/vitest) (check the [test](https://github.com/userquin/detect-browser-es/tree/main/test) folder).
42+
- Detect [WebDriverIO](https://github.com/webdriverio/webdriverio) when using WebDriverIO tests or test environments like [Vitest](https://github.com/vitest-dev/vitest).
4243
- ServerInfo via [std-env](https://github.com/unjs/std-env) with [provider](https://github.com/unjs/std-env#provider-detection) and [runtime](https://github.com/unjs/std-env#runtime-detection) detection.
4344

45+
## Testing
46+
47+
To run the tests, from root folder run `nr test`, the script will run:
48+
- the original tests from `detect-browser`
49+
- Happy DOM and JSDOM tests, except WebDriverIO detection
50+
51+
To test WebDriverIO detection, run one of the following commands (requires Vitest v1.0.0-beta.2, not yet released, tests will not work):
52+
- `nr wdio-chrome`: Chrome must be installed
53+
- `nr wdio-edge`: Edge must be installed
54+
- `nr wdio-firefox`: Firefox must be installed
55+
- `nr wdio-safari`: Safari must be installed and only on macOS machine.
56+
4457
## License
4558

4659
[MIT](./LICENSE)

browser-test/browser.test.ts

Lines changed: 7 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,23 @@ import { detect } from '../src'
44

55
// TODO: update to vitest 1.beta.2: will not work with 1.beta.1
66

7-
const provider = env.VITE_PROVIDER
87
const browser = env.VITE_BROWSER
98

10-
describe(`Browser Detection test: ${provider}`, () => {
11-
describe.skipIf(platform !== 'win32')('Windows', () => {
12-
test('User Agent found', () => {
13-
expect(typeof navigator).toBeDefined()
14-
expect(typeof navigator?.userAgent).toBeDefined()
15-
})
16-
test.skipIf(browser !== 'chrome')('Chrome', () => {
17-
expect(detect()).toBe('chrome')
18-
})
19-
test.skipIf(provider === 'webdriverio' || browser !== 'chromium')('Chromium', () => {
20-
expect(detect()).toBe('chromium')
21-
})
22-
test.skipIf(browser !== 'edge')('Edge', () => {
23-
expect(detect()).toBe('edge')
24-
})
25-
test.skipIf(browser !== 'firefox')('FireFox', () => {
26-
expect(detect()).toBe('firefox')
27-
})
28-
})
29-
/*
30-
describe.skipIf(platform !== 'darwin')('MacOS', () => {
31-
test('User Agent found', () => {
32-
expect(typeof navigator).toBeDefined()
33-
expect(typeof navigator?.userAgent).toBeDefined()
34-
})
35-
test.skipIf(browser !== 'chrome')('Chrome', () => {
36-
expect(detect()).toBe('chrome')
37-
})
38-
test.skipIf(provider === 'webdriverio' || browser !== 'chromium')('Chromium', () => {
39-
expect(detect()).toBe('chromium')
40-
})
41-
test.skipIf(browser !== 'firefox')('FireFox', () => {
42-
expect(detect()).toBe('firefox')
43-
})
44-
})
9+
describe('Browser Detection test', () => {
4510
test('User Agent found', () => {
4611
expect(typeof navigator).toBeDefined()
4712
expect(typeof navigator?.userAgent).toBeDefined()
4813
})
4914
test.skipIf(browser !== 'chrome')('Chrome', () => {
50-
expect(detect()).toBe('chrome')
51-
})
52-
test.skipIf(provider === 'webdriverio' || browser !== 'chromium')('Chromium', () => {
53-
expect(detect()).toBe('chromium')
15+
expect(detect()?.name).toBe('chrome')
5416
})
5517
test.skipIf(browser !== 'edge')('Edge', () => {
56-
expect(detect()).toBe('edge')
18+
expect(detect()?.name).toBe('edge')
5719
})
5820
test.skipIf(browser !== 'firefox')('FireFox', () => {
59-
expect(detect()).toBe('firefox')
21+
expect(detect()?.name).toBe('firefox')
22+
})
23+
test.skipIf(platform !== 'darwin' || browser !== 'safari')('FireFox', () => {
24+
expect(detect()?.name).toBe('safari')
6025
})
61-
*/
6226
})

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"wdio-chrome": "BROWSER=chrome vitest --c vitest-browser.config.mts",
3838
"wdio-edge": "BROWSER=edge vitest --c vitest-browser.config.mts",
3939
"wdio-firefox": "BROWSER=firefox vitest --c vitest-browser.config.mts",
40+
"wdio-safari": "BROWSER=safari vitest --c vitest-browser.config.mts",
4041
"wdio-test": "pnpm run wdio-chrome && pnpm run wdio-edge && pnpm run wdio-firefox"
4142
},
4243
"dependencies": {

src/index.ts

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type DetectedInfoType =
1313
| 'node'
1414
| 'jsdom'
1515
| 'happy-dom'
16+
| 'webdriverio'
1617
| 'bot-device'
1718
| 'bot'
1819
| 'react-native'
@@ -105,6 +106,16 @@ implements DetectedInfo<'happy-dom', Browser, OperatingSystem | null, string> {
105106
) {}
106107
}
107108

109+
export class WebDriverIOInfo
110+
implements DetectedInfo<'webdriverio', Browser, OperatingSystem | null, string> {
111+
public readonly type = 'webdriverio'
112+
constructor(
113+
public readonly name: Browser,
114+
public readonly version: string,
115+
public readonly os: OperatingSystem | null,
116+
) {}
117+
}
118+
108119
export type Browser =
109120
| 'aol'
110121
| 'edge'
@@ -138,6 +149,7 @@ export type Browser =
138149
| 'searchbot'
139150
| 'jsdom'
140151
| 'happy-dom'
152+
| 'webdriverio'
141153
export type OperatingSystem =
142154
| 'iOS'
143155
| 'Android OS'
@@ -247,17 +259,7 @@ const operatingSystemRules: OperatingSystemRule[] = [
247259
['OS/2', /OS\/2/],
248260
]
249261

250-
export function detect(
251-
userAgent?: string,
252-
):
253-
| BrowserInfo
254-
| SearchBotDeviceInfo
255-
| BotInfo
256-
| ServerInfo
257-
| ReactNativeInfo
258-
| JSDOMInfo
259-
| HappyDomInfo
260-
| null {
262+
export function detect(userAgent?: string) {
261263
if (userAgent)
262264
return parseUserAgent(userAgent)
263265

@@ -274,13 +276,21 @@ export function detect(
274276
return new JSDOMInfo(browser.name, browser.version, browser.os)
275277
}
276278

277-
if (typeof window !== 'undefined' && 'happyDOM' in window) {
278-
const happyDOM: HappyDOMOptions | undefined = window.happyDOM as unknown as any
279-
const ua = happyDOM?.settings?.navigator?.userAgent
280-
if (ua) {
281-
const browser = parseUserAgent(ua)
279+
if (typeof window !== 'undefined') {
280+
if ('happyDOM' in window) {
281+
const happyDOM: HappyDOMOptions | undefined = window.happyDOM as unknown as any
282+
const ua = happyDOM?.settings?.navigator?.userAgent
283+
if (ua) {
284+
const browser = parseUserAgent(ua)
285+
if (browser instanceof BrowserInfo)
286+
return new HappyDomInfo(browser.name, browser.version, browser.os)
287+
}
288+
}
289+
290+
if ('__wdioSpec__' in window) {
291+
const browser = parseUserAgent(navigator.userAgent)
282292
if (browser instanceof BrowserInfo)
283-
return new HappyDomInfo(browser.name, browser.version, browser.os)
293+
return new WebDriverIOInfo(browser.name, browser.version, browser.os)
284294
}
285295
}
286296

@@ -290,7 +300,7 @@ export function detect(
290300
return getServerVersion()
291301
}
292302

293-
function matchUserAgent(ua: string): UserAgentMatch {
303+
function matchUserAgent(ua: string) {
294304
// opted for using reduce here rather than Array#first with a regex.test call
295305
// this is primarily because using the reduce we only perform the regex
296306
// execution once rather than once for the test and for the exec again below
@@ -310,14 +320,12 @@ function matchUserAgent(ua: string): UserAgentMatch {
310320
)
311321
}
312322

313-
export function browserName(ua: string): Browser | null {
323+
export function browserName(ua: string) {
314324
const data = matchUserAgent(ua)
315325
return data ? data[0] : null
316326
}
317327

318-
export function parseUserAgent(
319-
ua: string,
320-
): BrowserInfo | SearchBotDeviceInfo | BotInfo | null {
328+
export function parseUserAgent(ua: string) {
321329
const matchedRule: UserAgentMatch = matchUserAgent(ua)
322330

323331
if (!matchedRule)
@@ -346,13 +354,13 @@ export function parseUserAgent(
346354
const os = detectOS(ua)
347355
const searchBotMatch = SEARCHBOT_OS_REGEX.exec(ua)
348356

349-
if (searchBotMatch && searchBotMatch[1])
357+
if (searchBotMatch?.[1])
350358
return new SearchBotDeviceInfo(name, version, os, searchBotMatch[1])
351359

352360
return new BrowserInfo(name, version, os)
353361
}
354362

355-
export function detectOS(ua: string): OperatingSystem | null {
363+
export function detectOS(ua: string) {
356364
for (let ii = 0, count = operatingSystemRules.length; ii < count; ii++) {
357365
const [os, regex] = operatingSystemRules[ii]
358366
const match = regex.exec(ua)
@@ -363,12 +371,12 @@ export function detectOS(ua: string): OperatingSystem | null {
363371
return null
364372
}
365373

366-
export function getServerVersion(): ServerInfo | null {
374+
export function getServerVersion() {
367375
return nodeVersion ? new ServerInfo(`${nodeVersion}`) : null
368376
}
369377

370-
function createVersionParts(count: number): string[] {
371-
const output = []
378+
function createVersionParts(count: number) {
379+
const output: string[] = []
372380
for (let ii = 0; ii < count; ii++)
373381
output.push('0')
374382

vitest-browser.config.mts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
import process from 'node:process'
22
import { defineConfig } from 'vitest/config'
33

4-
const provider = process.env.PROVIDER ?? 'webdriverio'
5-
const name = process.env.BROWSER ?? 'chromium'
4+
const name = process.env.BROWSER ?? 'chrome'
65

76
export default defineConfig({
87
define: {
9-
'process.env.VITE_PROVIDER': JSON.stringify(provider),
108
'process.env.VITE_BROWSER': JSON.stringify(name),
119
},
1210
test: {
1311
globals: true,
1412
include: ['browser-test/*.test.ts'],
1513
browser: {
1614
enabled: true,
17-
provider,
15+
provider: 'webdriverio',
1816
name,
17+
headless: true,
1918
},
2019
},
2120
})

0 commit comments

Comments
 (0)