mirror of
https://github.com/stablyai/orca.git
synced 2026-09-21 16:02:20 +00:00
Use runner Node executable and platform quoting in terminal E2E tests (#5890)
Ensure terminal E2E probes run reliably on Windows CI, where the shell does not always inherit setup-node's PATH. - Add `nodeTerminalCommand` helper to resolve and quote `process.execPath` for either POSIX shells or PowerShell depending on the platform. - Update terminal tests and probes to use the new helper instead of hardcoded `node` invocations.
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
waitForPtyPaneMounted,
|
||||
waitForPtyShellEcho
|
||||
} from './terminal-pty-readiness'
|
||||
import { nodeTerminalCommand } from './terminal-node-command'
|
||||
|
||||
type TerminalColumnProbeWindow = Window & {
|
||||
__store?: {
|
||||
@@ -87,7 +88,10 @@ export async function waitForPtyColumnsAtMost(
|
||||
await sendToTerminal(
|
||||
page,
|
||||
ptyId,
|
||||
`node -e ${JSON.stringify(`console.log('${marker}:' + (process.stdout.columns || 0))`)}\r`
|
||||
`${nodeTerminalCommand([
|
||||
'-e',
|
||||
`console.log('${marker}:' + (process.stdout.columns || 0))`
|
||||
])}\r`
|
||||
)
|
||||
const probeDeadline = Date.now() + Math.min(5_000, Math.max(0, deadline - Date.now()))
|
||||
while (Date.now() < probeDeadline) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
waitForPtyColumnsAtMost,
|
||||
waitForRenderedTerminalColumnsAtMost
|
||||
} from './terminal-column-probes'
|
||||
import { nodeTerminalCommand } from './terminal-node-command'
|
||||
import { waitForPtyShellEcho } from './terminal-pty-readiness'
|
||||
|
||||
type TerminalRenderDiagnostics = {
|
||||
@@ -620,7 +621,7 @@ test.describe('Terminal long table scroll restore repro', () => {
|
||||
writeFileSync(scriptPath, longMarkdownTableScript(runId))
|
||||
|
||||
try {
|
||||
await sendToTerminal(orcaPage, ptyId, `node ${JSON.stringify(scriptPath)}\r`)
|
||||
await sendToTerminal(orcaPage, ptyId, `${nodeTerminalCommand([scriptPath])}\r`)
|
||||
await orcaPage.waitForTimeout(80)
|
||||
await switchToWorktree(orcaPage, secondWorktreeId)
|
||||
await waitForActiveTerminalManager(orcaPage, 30_000)
|
||||
@@ -689,7 +690,7 @@ test.describe('Terminal long table scroll restore repro', () => {
|
||||
writeFileSync(scriptPath, narrowSignerMarkdownTableScript(runId))
|
||||
|
||||
try {
|
||||
await sendToTerminal(orcaPage, ptyId, `node ${JSON.stringify(scriptPath)}\r`)
|
||||
await sendToTerminal(orcaPage, ptyId, `${nodeTerminalCommand([scriptPath])}\r`)
|
||||
await orcaPage.waitForTimeout(80)
|
||||
await switchToWorktree(orcaPage, secondWorktreeId)
|
||||
await waitForActiveTerminalManager(orcaPage, 30_000)
|
||||
@@ -770,7 +771,7 @@ test.describe('Terminal long table scroll restore repro', () => {
|
||||
writeFileSync(scriptPath, emojiFixtureMarkdownTableScript(EMOJI_TABLE_FIXTURE, runId))
|
||||
|
||||
try {
|
||||
await sendToTerminal(orcaPage, ptyId, `node ${JSON.stringify(scriptPath)}\r`)
|
||||
await sendToTerminal(orcaPage, ptyId, `${nodeTerminalCommand([scriptPath])}\r`)
|
||||
await orcaPage.waitForTimeout(80)
|
||||
await switchToWorktree(orcaPage, secondWorktreeId)
|
||||
await waitForActiveTerminalManager(orcaPage, 30_000)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
function quotePosixShellArg(value: string): string {
|
||||
return `'${value.replaceAll("'", "'\\''")}'`
|
||||
}
|
||||
|
||||
function quotePowerShellArg(value: string): string {
|
||||
return `'${value.replaceAll("'", "''")}'`
|
||||
}
|
||||
|
||||
function quoteTerminalArg(value: string): string {
|
||||
return process.platform === 'win32' ? quotePowerShellArg(value) : quotePosixShellArg(value)
|
||||
}
|
||||
|
||||
export function nodeTerminalCommand(args: readonly string[]): string {
|
||||
const nodeExecutable = quoteTerminalArg(process.execPath)
|
||||
const executable = process.platform === 'win32' ? `& ${nodeExecutable}` : nodeExecutable
|
||||
|
||||
// Why: Windows CI shells do not always inherit setup-node's PATH, so E2E
|
||||
// terminal probes must invoke the runner's Node executable directly.
|
||||
return [executable, ...args.map(quoteTerminalArg)].join(' ')
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
analyzeRasterCursorCells,
|
||||
type TerminalRasterProbeTarget
|
||||
} from './terminal-cursor-raster-probe'
|
||||
import { nodeTerminalCommand } from './terminal-node-command'
|
||||
|
||||
type TerminalRenderState = {
|
||||
coreCursorHidden: boolean | null
|
||||
@@ -270,7 +271,7 @@ test.describe('OpenCode emoji table terminal rendering', () => {
|
||||
const scriptPath = path.join(testRepoPath, `.orca-opencode-emoji-table-${runId}.mjs`)
|
||||
writeFileSync(scriptPath, emojiTableScript(marker))
|
||||
try {
|
||||
await sendToTerminal(orcaPage, ptyId, `node ${JSON.stringify(scriptPath)}\r`)
|
||||
await sendToTerminal(orcaPage, ptyId, `${nodeTerminalCommand([scriptPath])}\r`)
|
||||
await waitForTerminalOutput(orcaPage, marker, 10_000)
|
||||
await orcaPage.waitForTimeout(250)
|
||||
await forceCursorProbeTheme(orcaPage)
|
||||
|
||||
@@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto'
|
||||
import type { Page } from '@stablyai/playwright-test'
|
||||
import { expect } from '@stablyai/playwright-test'
|
||||
import { sendToTerminal } from './helpers/terminal'
|
||||
import { nodeTerminalCommand } from './terminal-node-command'
|
||||
|
||||
type TerminalPtyReadinessWindow = Window & {
|
||||
__paneManagers?: Map<
|
||||
@@ -67,9 +68,10 @@ export async function waitForPtyPaneMounted(
|
||||
|
||||
function encodedMarkerCommand(marker: string): string {
|
||||
const encoded = Buffer.from(marker, 'utf8').toString('base64')
|
||||
return `node -e ${JSON.stringify(
|
||||
return `${nodeTerminalCommand([
|
||||
'-e',
|
||||
`console.log(Buffer.from('${encoded}', 'base64').toString('utf8'))`
|
||||
)}\r`
|
||||
])}\r`
|
||||
}
|
||||
|
||||
export async function waitForPtyShellEcho(
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
waitForTerminalOutput
|
||||
} from './helpers/terminal'
|
||||
import { scrollActiveTerminalToText } from './artificial-opencode-active-terminal-scroll'
|
||||
import { nodeTerminalCommand } from './terminal-node-command'
|
||||
|
||||
type BrowserTerminalPane = {
|
||||
terminal: {
|
||||
@@ -522,7 +523,7 @@ test.describe('Terminal raw emoji table scroll restore repro', () => {
|
||||
const frameTailMarker = rawEmojiFixtureFrameTailMarker(runId)
|
||||
// Why: the fixture marker is the shell-readiness signal here; an extra
|
||||
// Ctrl+C/Ctrl+U preflight can race Windows ConPTY startup and eat input.
|
||||
await sendToTerminal(orcaPage, ptyId, `node ${JSON.stringify(scriptPath)}\r`)
|
||||
await sendToTerminal(orcaPage, ptyId, `${nodeTerminalCommand([scriptPath])}\r`)
|
||||
// Why: Windows ConPTY can return the PowerShell prompt while xterm is
|
||||
// still flushing synchronized output if the pane is hidden immediately.
|
||||
// This golden is about restored table geometry, not shell-flush timing.
|
||||
|
||||
Reference in New Issue
Block a user