mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-05 08:23:59 +01:00
* test(browse): failing tests for #3907 (handoff ignores GSTACK_CHROMIUM_PATH; bundled Chromium predates CVE-2026-106378 fix) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(browse): handoff honors GSTACK_CHROMIUM_PATH (#3907) handoff() always launched Playwright's bundled Chromium, so a GSTACK_CHROMIUM_PATH browser dropped back to the bundle at handoff. It now passes executablePath like launch() and launchHeaded(), skips the poisoned-bundle probe and XProtect heal for a custom path, and never loads the extension into a build that bakes it in. Co-authored-by: merit-blake <265362871+merit-blake@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(deps): Playwright 1.64.1 (Chromium 156) for CVE-2026-106378 (#3907) Playwright 1.62.1 bundled Chromium 151.0.7922.34, which lacks the macOS GPU-process TCC fix (Chromium 0c2f3e54b265, crbug.com/507596239). 1.64.1 bundles 156.0.8078.4, which has it. The playwright-core patch is regenerated from our 1.62.1 patch: the launch windowsHide and TcpPortRandomizationWin hunks carry over unchanged; the taskkill hunk is dropped because 1.64 passes windowsHide there upstream. Co-authored-by: merit-blake <265362871+merit-blake@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore(pregate): map patches/** to the playwright-core patch test Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(browse): name the 1.64.1 patch file in the TcpPortRandomizationWin check Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): fragment for Playwright 1.64.1 and handoff GSTACK_CHROMIUM_PATH (#3907) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(troubleshooting): GSTACK_CHROMIUM_PATH covers headed browse and handoff Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(browse): the retired 1.62.1 patch stays deleted Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> Co-authored-by: merit-blake <265362871+merit-blake@users.noreply.github.com>
89 lines
5.1 KiB
TypeScript
89 lines
5.1 KiB
TypeScript
import { afterEach, describe, expect, test } from 'bun:test';
|
|
import { spawnSync } from 'node:child_process';
|
|
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join, resolve } from 'node:path';
|
|
import { runBashScript } from './helpers/bash-script';
|
|
|
|
const ROOT = resolve(import.meta.dir, '..');
|
|
const source = readFileSync(join(ROOT, 'setup'), 'utf8');
|
|
const owned: string[] = [];
|
|
afterEach(() => { for (const dir of owned.splice(0)) rmSync(dir, { recursive: true, force: true }); });
|
|
function temp() { const dir = mkdtempSync(join(tmpdir(), 'gstack-pw-platform-')); owned.push(dir); return dir; }
|
|
function slice(start: string, end: string) {
|
|
const a = source.indexOf(start), b = source.indexOf(end, a);
|
|
if (a < 0 || b < 0) throw new Error('setup anchors missing');
|
|
return source.slice(a, b);
|
|
}
|
|
function fn(name: string) { return slice(`${name}() {`, '\n}\n') + '\n}'; }
|
|
|
|
function platform(id: string, version: string, cpu: string, wholeBlock = false) {
|
|
const dir = temp();
|
|
const osRelease = join(dir, 'os-release');
|
|
writeFileSync(osRelease, `ID=${id}\nVERSION_ID="${version}"\n`);
|
|
const converted = process.platform === 'win32'
|
|
? spawnSync('bash', ['-c', 'cygpath -u "$1"', '_', osRelease], { encoding: 'utf8', timeout: 10_000 })
|
|
: null;
|
|
if (converted && converted.status !== 0) throw new Error(`Cannot resolve Bash fixture path: ${converted.stderr}`);
|
|
const selector = slice("# 2. Ensure Playwright's Chromium is available", wholeBlock ? '# 2b. Ensure a color-emoji font' : '# Chromium is BEST-EFFORT')
|
|
.replaceAll('/etc/os-release', JSON.stringify(converted ? converted.stdout.trim() : osRelease));
|
|
return runBashScript([
|
|
'set -e', `uname() { echo ${JSON.stringify(cpu)}; }`,
|
|
`SOURCE_GSTACK_DIR=${JSON.stringify(dir)}`, `TMPDIR=${JSON.stringify(dir)}`, 'IS_WINDOWS=0',
|
|
'ensure_playwright_browser() { echo PROBED; return 0; }',
|
|
'bunx() { echo INSTALL_ATTEMPTED; return 0; }',
|
|
selector,
|
|
'printf "OVERRIDE=%s\\nUNSUPPORTED=%s\\nREASON=%s\\n" "$_PLAYWRIGHT_PLATFORM_OVERRIDE" "${_PLAYWRIGHT_UNSUPPORTED_ARCH:-}" "${_PW_FAIL_REASON:-}"',
|
|
].join('\n'), { env: { PATH: process.env.PATH, HOME: dir }, timeout: 10_000 });
|
|
}
|
|
|
|
describe('Ubuntu fallback retains CPU architecture', () => {
|
|
for (const [cpu, expected] of [['x86_64', 'x64'], ['aarch64', 'arm64'], ['arm64', 'arm64']]) {
|
|
test(`${cpu} selects the matching real Playwright artifact`, () => {
|
|
const result = platform('ubuntu', '26.04', cpu!);
|
|
expect(result.status, result.stderr).toBe(0);
|
|
const override = result.stdout.match(/^OVERRIDE=(.*)$/m)![1]!;
|
|
expect(override).toBe(`ubuntu24.04-${expected}`);
|
|
const dryRun = spawnSync(process.execPath, [join(ROOT, 'node_modules/playwright/cli.js'), 'install', '--dry-run', 'chromium'], {
|
|
cwd: ROOT, env: { PATH: process.env.PATH, HOME: temp(), PLAYWRIGHT_HOST_PLATFORM_OVERRIDE: override }, encoding: 'utf8', timeout: 20_000,
|
|
});
|
|
expect(dryRun.status, dryRun.stderr).toBe(0);
|
|
expect(dryRun.stdout).toContain(expected === 'arm64' ? 'chrome-linux-arm64.zip' : 'chrome-linux64.zip');
|
|
expect(dryRun.stdout).not.toContain(expected === 'arm64' ? 'chrome-linux64.zip' : 'chrome-linux-arm64.zip');
|
|
}, 30_000);
|
|
}
|
|
for (const cpu of ['riscv64', 'i686', 'unknown']) test(`${cpu} reports unsupported instead of installing x64`, () => {
|
|
const result = platform('ubuntu', '26.04', cpu, true);
|
|
expect(result.status, result.stderr).toBe(0);
|
|
expect(result.stdout).toContain('OVERRIDE=\n');
|
|
expect(result.stdout).toContain(`UNSUPPORTED=${cpu}\n`);
|
|
expect(result.stdout).toContain('REASON=unsupported-platform\n');
|
|
expect(result.stdout).not.toContain('INSTALL_ATTEMPTED');
|
|
expect(result.stderr).toContain(cpu);
|
|
});
|
|
for (const [id, version] of [['ubuntu', '24.04'], ['debian', '13']]) test(`${id} ${version} keeps native detection`, () => {
|
|
const result = platform(id!, version!, 'aarch64');
|
|
expect(result.status, result.stderr).toBe(0);
|
|
expect(result.stdout).toBe('OVERRIDE=\nUNSUPPORTED=\nREASON=\n');
|
|
});
|
|
});
|
|
|
|
describe('actual setup launch probe diagnostics', () => {
|
|
for (const error of ['', 'spawn chromium ENOEXEC: wrong executable architecture', 'Missing shared library: libexample.so']) {
|
|
test(error || 'successful launch is silent', () => {
|
|
const dir = temp();
|
|
mkdirSync(join(dir, 'node_modules/playwright'), { recursive: true });
|
|
writeFileSync(join(dir, 'node_modules/playwright/index.js'), `module.exports = { chromium: { launch: async () => { ${error ? `throw new Error(${JSON.stringify(error)})` : 'return { close: async () => {} }'} } } };\n`);
|
|
const result = runBashScript([
|
|
'set -e', `SOURCE_GSTACK_DIR=${JSON.stringify(dir)}`, 'IS_WINDOWS=0',
|
|
fn('_kill_tree'), fn('_wait_with_deadline'), fn('ensure_playwright_browser'),
|
|
'ensure_playwright_browser',
|
|
].join('\n'), { env: { PATH: process.env.PATH, HOME: dir, TMPDIR: dir }, timeout: 10_000 });
|
|
expect(result.status).toBe(error ? 1 : 0);
|
|
expect(result.stdout).toBe('');
|
|
if (error) expect(result.stderr).toContain(error);
|
|
else expect(result.stderr).toBe('');
|
|
});
|
|
}
|
|
});
|