webdriverio/packages/wdio-utils/tests/node/utils.test.ts
Christian Bromann 37b4536580
fix(security): address multiple security vulnerabilities across codebase (#14570)
* fix(security): address multiple security vulnerabilities across codebase

* further improvements

* fix unit tests

* Potential fix for code scanning alert no. 65: Incomplete multi-character sanitization

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for code scanning alert no. 69: Incomplete multi-character sanitization

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* properly escape regexp

* minor formatting

* improvements

* Potential fix for code scanning alert no. 72: Bad HTML filtering regexp

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for code scanning alert no. 76: Incomplete multi-character sanitization

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* more stable comment removal implementation

* fix tests

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-07-16 11:18:01 -07:00

216 lines
8.1 KiB
TypeScript

import os from 'node:os'
import path from 'node:path'
import url from 'node:url'
import cp from 'node:child_process'
import fs from 'node:fs'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { canDownload, resolveBuildId, detectBrowserPlatform } from '@puppeteer/browsers'
import { locateChrome, locateApp } from 'locate-app'
import {
parseParams, getBuildIdByChromePath, getBuildIdByFirefoxPath, setupPuppeteerBrowser,
canAccess
} from '../../src/node/utils.js'
const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
vi.mock('fs', () => import(path.join(process.cwd(), '__mocks__', 'fs')))
vi.mock('node:os', () => ({
default: {
tmpdir: vi.fn().mockReturnValue('/tmp'),
platform: vi.fn().mockReturnValue('darwin')
}
}))
vi.mock('locate-app', () => ({
locateChrome: vi.fn().mockResolvedValue('/path/to/chrome'),
locateFirefox: vi.fn().mockResolvedValue('/path/to/firefox'),
locateApp: vi.fn().mockResolvedValue('/path/to/chromium')
}))
vi.mock('node:fs', () => ({
default: {
accessSync: vi.fn(),
readdirSync: vi.fn().mockReturnValue([
'114.0.5735.199',
'115.0.5790.110',
'chrome.exe',
'chrome.VisualElementsManifest.xml',
'chrome_proxy.exe',
'master_preferences',
'new_chrome.exe',
'new_chrome_proxy.exe',
'SetupMetrics'
])
}
}))
vi.mock('node:fs/promises', () => ({
default: {
mkdir: vi.fn().mockResolvedValue({}),
access: vi.fn().mockResolvedValue({}),
readFile: vi.fn(async () => {
const { readFileSync } = await vi.importActual<typeof fs>('node:fs')
return readFileSync(path.resolve(__dirname, '__fixtures__', 'application.ini'))
})
}
}))
vi.mock('node:child_process', () => ({
default: {
execSync: vi.fn(),
spawnSync: vi.fn()
}
}))
vi.mock('@puppeteer/browsers', () => ({
Browser: { CHROME: 'chrome', FIREFOX: 'firefox', CHROMIUM: 'chromium' },
ChromeReleaseChannel: { STABLE: 'stable' },
detectBrowserPlatform: vi.fn(),
resolveBuildId: vi.fn().mockReturnValue('116.0.5845.110'),
canDownload: vi.fn().mockResolvedValue(true),
computeExecutablePath: vi.fn().mockReturnValue('/foo/bar/executable'),
install: vi.fn().mockResolvedValue({})
}))
describe('driver utils', () => {
beforeEach(() => {
vi.mocked(cp.spawnSync).mockReturnValue({
pid: 123,
output: [],
stdout: 'Google Chrome 116.0.5845.110 \n',
stderr: '',
status: 0,
signal: null
})
})
it('should parse params', () => {
expect(parseParams({ baseUrl: 'foobar', silent: true, verbose: false, allowedIps: ['123', '321'] }))
.toMatchSnapshot()
})
it('getBuildIdByChromePath', () => {
expect(getBuildIdByChromePath()).toBe(undefined)
expect(getBuildIdByChromePath('/foo/bar')).toBe('116.0.5845.110')
expect(cp.spawnSync).toBeCalledWith('/foo/bar', ['--version', '--no-sandbox'], expect.any(Object))
vi.mocked(cp.spawnSync).mockReturnValue({
pid: 123,
output: [],
stdout: 'Chromium 117.0.5938.88 Fedora Project \n',
stderr: '',
status: 0,
signal: null
})
expect(getBuildIdByChromePath('/foo/bar')).toBe('117.0.5938.88')
vi.mocked(cp.spawnSync).mockReturnValue({
pid: 123,
output: [],
stdout: 'Chromium 117.0.5938.92 snap \n',
stderr: '',
status: 0,
signal: null
})
expect(getBuildIdByChromePath('/foo/bar')).toBe('117.0.5938.92')
vi.mocked(os.platform).mockReturnValueOnce('win32')
expect(getBuildIdByChromePath('/foo/bar')).toBe('115.0.5790.110')
})
it('getBuildIdByFirefoxPath', async () => {
expect(await getBuildIdByFirefoxPath()).toBe(undefined)
expect(await getBuildIdByFirefoxPath('/foo/bar')).toBe('116.0.5845.110')
vi.mocked(os.platform).mockReturnValueOnce('win32')
expect(await getBuildIdByFirefoxPath('/foo/bar')).toBe('116.0.3')
})
describe('setupPuppeteerBrowser', () => {
beforeEach(() => {
vi.mocked(resolveBuildId).mockClear()
})
it('should throw if platform is not supported', async () => {
vi.mocked(detectBrowserPlatform).mockReturnValueOnce(undefined)
await expect(setupPuppeteerBrowser('/foo/bar', { browserName: 'chrome' })).rejects.toThrow('The current platform is not supported.')
})
it('should run setup for local chrome if browser version is omitted', async () => {
vi.mocked(detectBrowserPlatform).mockReturnValueOnce('mac' as any)
await expect(setupPuppeteerBrowser('/foo/bar', {})).resolves.toEqual({
browserVersion: '116.0.5845.110',
executablePath: '/path/to/chrome'
})
})
it('should do nothing if browser binary is defined within caps', async () => {
await expect(setupPuppeteerBrowser('/foo/bar', {
'goog:chromeOptions': { binary: '/my/chrome' }
})).resolves.toEqual({
browserVersion: '116.0.5845.110',
executablePath: '/my/chrome'
})
await expect(setupPuppeteerBrowser('/foo/bar', {
browserVersion: '1.2.3',
'goog:chromeOptions': { binary: '/my/chrome' }
})).resolves.toEqual({
browserVersion: '1.2.3',
executablePath: '/my/chrome'
})
})
it('should install chrome stable if browser is not found', async () => {
vi.mocked(detectBrowserPlatform).mockReturnValueOnce('windows' as any)
vi.mocked(locateChrome).mockResolvedValue('/path/to/stable')
await expect(setupPuppeteerBrowser('/foo/bar', {})).resolves.toEqual({
browserVersion: '116.0.5845.110',
executablePath: '/path/to/stable'
})
expect(resolveBuildId).toBeCalledTimes(0)
})
it('should look for Chromium browser if defined as browser name', async () => {
vi.mocked(detectBrowserPlatform).mockReturnValueOnce('windows' as any)
vi.mocked(locateApp).mockResolvedValue('')
const caps = { browserName: 'chromium' }
await expect(setupPuppeteerBrowser('/foo/bar', caps)).resolves.toEqual( {
browserVersion: '116.0.5845.110',
executablePath: '/foo/bar/executable'
})
expect(caps.browserName).toBe('chrome')
expect(resolveBuildId).toBeCalledTimes(2)
expect(resolveBuildId).toBeCalledWith('chromium', 'windows', 'latest')
expect(resolveBuildId).toBeCalledWith('chrome', 'windows', 'latest')
})
it('should throw if browser version is not found', async () => {
vi.mocked(detectBrowserPlatform).mockReturnValueOnce('windows' as any)
vi.mocked(canDownload).mockResolvedValueOnce(false)
vi.mocked(locateChrome).mockRejectedValueOnce(new Error('not found'))
await expect(setupPuppeteerBrowser('/foo/bar', { browserName: 'chrome' }))
.rejects.toThrow(/Couldn't find a matching chrome browser/)
})
it('should install chrome browser with specific version provided', async () => {
vi.mocked(detectBrowserPlatform).mockReturnValueOnce('windows' as any)
await expect(setupPuppeteerBrowser('/foo/bar', { browserVersion: '1.2.3' })).resolves.toEqual({
browserVersion: '116.0.5845.110',
executablePath: '/foo/bar/executable',
})
expect(resolveBuildId).toBeCalledWith('chrome', 'windows', '1.2.3')
})
})
})
describe('utils:canAccess', () => {
it('canAccess', () => {
expect(canAccess('/foobar')).toBe(true)
expect(fs.accessSync).toBeCalledWith('/foobar')
// @ts-ignore
fs.accessSync.mockImplementation(() => {
throw new Error('upps')
})
expect(canAccess('/foobar')).toBe(false)
})
})