* 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>
216 lines
8.1 KiB
TypeScript
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)
|
|
})
|
|
})
|