Skip to content

Commit

Permalink
Cover test for each finders and utils
Browse files Browse the repository at this point in the history
  • Loading branch information
yhatt committed Sep 22, 2024
1 parent 4108fe9 commit 415cee6
Show file tree
Hide file tree
Showing 11 changed files with 992 additions and 54 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"@types/node": "~16.18.108",
"@types/pug": "^2.0.10",
"@types/supertest": "^6.0.2",
"@types/which": "^3.0.4",
"@types/ws": "^8.5.12",
"@types/yargs": "^17.0.33",
"@typescript-eslint/eslint-plugin": "^8.5.0",
Expand Down Expand Up @@ -149,6 +150,7 @@
"typed-emitter": "^2.1.0",
"typescript": "^5.6.2",
"vhtml": "^2.2.0",
"which": "^4.0.0",
"wrap-ansi": "^9.0.0",
"yauzl": "^3.1.3",
"zip-stream": "^6.0.1"
Expand Down
3 changes: 0 additions & 3 deletions src/browser/finders/chrome.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,10 @@ export const chromeFinder: BrowserFinder = async ({ preferredPath } = {}) => {
return linux()[0]
case 'win32':
return win32()[0]
// CI cannot test against WSL environment
/* c8 ignore start */
case 'wsl1':
return wsl()[0]
}
return await fallback()
/* c8 ignore stop */
})()

if (installation) return chrome(installation)
Expand Down
23 changes: 11 additions & 12 deletions src/browser/finders/edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,10 @@ export const edgeFinder: BrowserFinder = async ({ preferredPath } = {}) => {
return await edgeFinderLinux()
case 'win32':
return await edgeFinderWin32()
// CI cannot test against WSL environment
/* c8 ignore start */
case 'wsl1':
return await edgeFinderWSL1()
}
return undefined
/* c8 ignore stop */
})()

if (installation) return edge(installation)
Expand Down Expand Up @@ -67,15 +64,17 @@ const edgeFinderWin32 = async ({
} = {}): Promise<string | undefined> => {
const paths: string[] = []

for (const prefix of [programFiles, programFilesX86, localAppData]) {
if (!prefix) continue
const suffixes = [
['Microsoft', 'Edge SxS', 'Application', 'msedge.exe'],
['Microsoft', 'Edge Dev', 'Application', 'msedge.exe'],
['Microsoft', 'Edge Beta', 'Application', 'msedge.exe'],
['Microsoft', 'Edge', 'Application', 'msedge.exe'],
]

paths.push(
path.join(prefix, 'Microsoft', 'Edge SxS', 'Application', 'msedge.exe'),
path.join(prefix, 'Microsoft', 'Edge Dev', 'Application', 'msedge.exe'),
path.join(prefix, 'Microsoft', 'Edge Beta', 'Application', 'msedge.exe'),
path.join(prefix, 'Microsoft', 'Edge', 'Application', 'msedge.exe')
)
for (const suffix of suffixes) {
for (const prefix of [localAppData, programFiles, programFilesX86]) {
if (prefix) paths.push(path.join(prefix, ...suffix))
}
}

return await findExecutable(paths)
Expand All @@ -87,6 +86,6 @@ const edgeFinderWSL1 = async () => {
return await edgeFinderWin32({
programFiles: '/mnt/c/Program Files',
programFilesX86: '/mnt/c/Program Files (x86)',
localAppData: localAppData ? resolveWSLPathToGuestSync(localAppData) : '',
localAppData: localAppData && resolveWSLPathToGuestSync(localAppData),
})
}
44 changes: 25 additions & 19 deletions src/browser/finders/firefox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ const firefox = (path: string): BrowserFinderResult => ({
acceptedBrowsers: [FirefoxBrowser],
})

const winFirefoxNightly = ['Nightly', 'firefox.exe']
const winFirefoxNightlyAlt = ['Firefox Nightly', 'firefox.exe']
const winFirefoxDevEdition = ['Firefox Developer Edition', 'firefox.exe']
const winFirefoxDefault = ['Mozilla Firefox', 'firefox.exe'] // Firefox stable, ESR, and beta

export const firefoxFinder: BrowserFinder = async ({ preferredPath } = {}) => {
if (preferredPath) return firefox(preferredPath)

Expand All @@ -19,11 +24,8 @@ export const firefoxFinder: BrowserFinder = async ({ preferredPath } = {}) => {
return await firefoxFinderDarwin()
case 'win32':
return await firefoxFinderWin32()
// CI cannot test against WSL environment
/* c8 ignore start */
case 'wsl1':
return await firefoxFinderWSL1()
/* c8 ignore stop */
}
return await firefoxFinderFallback()
})()
Expand All @@ -45,8 +47,8 @@ const firefoxFinderWin32 = async () => {

const winDriveMatcher = /^[a-z]:\\/i
const winPossibleDrives = () => {
const possibleDriveSet = new Set<string>()
const pathEnvs = process.env.PATH?.split(';') ?? ['c:\\']
const possibleDriveSet = new Set<string>(['c'])
const pathEnvs = process.env.PATH?.split(';') ?? []

for (const pathEnv of pathEnvs) {
if (winDriveMatcher.test(pathEnv)) {
Expand All @@ -68,12 +70,14 @@ const firefoxFinderWin32 = async () => {
}

return await findExecutable(
prefixes.flatMap((prefix) => [
path.join(prefix, 'Nightly', 'firefox.exe'),
path.join(prefix, 'Firefox Nightly', 'firefox.exe'),
path.join(prefix, 'Firefox Developer Edition', 'firefox.exe'),
path.join(prefix, 'Mozilla Firefox', 'firefox.exe'), // Firefox stable, ESR, and beta
])
[
winFirefoxNightly,
winFirefoxNightlyAlt,
winFirefoxDevEdition,
winFirefoxDefault,
].flatMap((suffix) =>
prefixes.map((prefix) => path.join(prefix, ...suffix))
)
)
}

Expand All @@ -82,8 +86,8 @@ const firefoxFinderWSL1 = async () => {

const winDriveMatcher = /^\/mnt\/[a-z]\//i
const winPossibleDrives = () => {
const possibleDriveSet = new Set<string>()
const pathEnvs = process.env.PATH?.split(':') ?? ['/mnt/c/']
const possibleDriveSet = new Set<string>(['c'])
const pathEnvs = process.env.PATH?.split(':') ?? []

for (const pathEnv of pathEnvs) {
if (winDriveMatcher.test(pathEnv)) {
Expand All @@ -100,12 +104,14 @@ const firefoxFinderWSL1 = async () => {
}

return await findExecutable(
prefixes.flatMap((prefix) => [
path.join(prefix, 'Nightly', 'firefox.exe'),
path.join(prefix, 'Firefox Nightly', 'firefox.exe'),
path.join(prefix, 'Firefox Developer Edition', 'firefox.exe'),
path.join(prefix, 'Mozilla Firefox', 'firefox.exe'), // Firefox stable, ESR, and beta
])
[
winFirefoxNightly,
winFirefoxNightlyAlt,
winFirefoxDevEdition,
winFirefoxDefault,
].flatMap((suffix) =>
prefixes.map((prefix) => path.join(prefix, ...suffix))
)
)
}

Expand Down
24 changes: 4 additions & 20 deletions src/browser/finders/utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { execFile } from 'node:child_process'
import fs from 'node:fs'
import path from 'node:path'
import { promisify } from 'node:util'
import { parse as parsePlist } from 'fast-plist'
import nodeWhich from 'which'
import { debugBrowserFinder } from '../../utils/debug'
import { isWSL } from '../../utils/wsl'

const execFilePromise = promisify(execFile)

export const getPlatform = async () =>
(await isWSL()) === 1 ? 'wsl1' : process.platform

Expand All @@ -28,6 +25,7 @@ const findFirst = async <T>(
predicate: (path: string) => Promise<T>
) => {
const pathsCount = paths.length
if (pathsCount === 0) return undefined

return new Promise<T | undefined>((resolve) => {
const result = Array<T | undefined>(pathsCount)
Expand Down Expand Up @@ -106,22 +104,8 @@ export const findExecutableBinary = async (binaries: string[]) =>
return undefined
})

const which = async (command: string) => {
if (process.platform === 'win32') {
debugBrowserFinder(
'"which %s" command is not available on Windows.',
command
)
return undefined
}

try {
const { stdout } = await execFilePromise('which', [command])
return stdout.split(/\r?\n/)[0]
} catch {
return undefined
}
}
export const which = async (command: string) =>
(await nodeWhich(command, { nothrow: true })) ?? undefined

// Darwin
const darwinAppDirectoryMatcher = /.app\/?$/
Expand Down
58 changes: 58 additions & 0 deletions test/browser/finder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,64 @@ describe('Browser finder', () => {
})
})

it('resolves a secondary browser if the first finder throws an error', async () => {
let $findBrowser!: typeof findBrowser
let $ChromeBrowser!: typeof ChromeBrowser
let $ChromeCdpBrowser!: typeof ChromeCdpBrowser

await jest.isolateModulesAsync(async () => {
jest
.spyOn(
await import('../../src/browser/finders/firefox'),
'firefoxFinder'
)
.mockRejectedValue(new Error('Test error'))

$findBrowser = await import('../../src/browser/finder').then(
(m) => m.findBrowser
)

$ChromeBrowser = await import('../../src/browser/browsers/chrome').then(
(m) => m.ChromeBrowser
)

$ChromeCdpBrowser = await import(
'../../src/browser/browsers/chrome-cdp'
).then((m) => m.ChromeCdpBrowser)
})

const browser = await $findBrowser(['firefox', 'chrome'], {
preferredPath: executableMock('empty'),
})

expect(browser).toStrictEqual<typeof browser>({
path: expect.stringMatching(/\bempty$/),
acceptedBrowsers: [$ChromeBrowser, $ChromeCdpBrowser],
})
})

it('rejects when finders are rejected', async () => {
let $findBrowser!: typeof findBrowser
let $CLIError!: typeof CLIError

await jest.isolateModulesAsync(async () => {
jest
.spyOn(
await import('../../src/browser/finders/chrome'),
'chromeFinder'
)
.mockRejectedValue(new Error('Test error'))

$findBrowser = await import('../../src/browser/finder').then(
(m) => m.findBrowser
)

$CLIError = await import('../../src/error').then((m) => m.CLIError)
})

await expect($findBrowser(['chrome'])).rejects.toThrow($CLIError)
})

describe('with macOS', () => {
let originalPlatform: string | undefined

Expand Down
Loading

0 comments on commit 415cee6

Please sign in to comment.