Files
orca/config/scripts/check-changed-task-runner.test.mjs
T
OrcaWinandOrcaWin 0866cb1b08 fix: bound local iteration checks and show live progress (#34700)
* fix: bound local iteration checks and show live progress

* fix: harden check lifecycles and cached test evidence

* fix: preserve process instrumentation and fixture lifecycles

* fix: give fixture unref spy a portable function type

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 23:04:23 -07:00

114 lines
3.2 KiB
JavaScript

import { afterEach, expect, it, vi } from 'vitest'
import { runProcess } from '@orca/process-host'
import { runPool, runTask } from './check-changed-task-runner.mjs'
afterEach(() => {
vi.useRealTimers()
vi.restoreAllMocks()
})
it('reports live progress, bounds the failure tail, and stops a task on timeout', async () => {
vi.useFakeTimers()
const logs = vi.fn()
const output = { log: logs, stdout: vi.fn(), stderr: vi.fn() }
let finish
const task = {
name: 'unit tests',
steps: [
{ program: 'test-runner', args: ['run'], liveOutput: true },
{ program: 'must-not-run', args: [] }
]
}
const launch = vi.fn(
() =>
new Promise((resolve) => {
finish = resolve
})
)
const pending = runTask(task, {
root: '.',
env: {},
runProcess: launch,
stepTimeoutMs: 30_000,
output
})
await vi.advanceTimersByTimeAsync(15_000)
expect(logs.mock.calls.flat().join('\n')).toContain('still running')
expect(launch.mock.calls[0][0]).toMatchObject({
timeoutMs: 30_000,
terminationBarrier: true,
detached: process.platform !== 'win32',
stdio: ['ignore', 'pipe', 'pipe'],
onStdout: expect.any(Function)
})
finish({
code: 0,
signal: null,
timedOut: true,
stdout: `${'old\n'.repeat(500)}last diagnostic\n`,
stderr: ''
})
const result = await pending
expect(result.ok).toBe(false)
expect(result.output).toContain('last diagnostic')
expect(result.output).toContain('Timed out after 30s')
expect(result.output).toContain('Command: "test-runner" "run"')
expect(result.output.split('\n').length).toBeLessThan(210)
expect(launch).toHaveBeenCalledTimes(1)
expect(vi.getTimerCount()).toBe(0)
})
it('cancels a real process and never starts subsequent steps', async () => {
vi.spyOn(console, 'log').mockImplementation(() => {})
const abort = new AbortController()
const task = {
name: 'cancel',
steps: [
{
program: process.execPath,
args: ['-e', 'process.stderr.write("ready"); setInterval(() => {}, 1000)'],
liveOutput: true
},
{ program: 'must-not-run', args: [] }
]
}
const launch = (spec, capture) => runProcess({ ...spec, onStderr: () => abort.abort() }, capture)
const result = await runTask(task, {
root: process.cwd(),
env: process.env,
runProcess: launch,
stepTimeoutMs: 10_000,
signal: abort.signal
})
expect(result.ok).toBe(false)
expect(result.output).toContain('ready')
expect(result.output).toContain('Cancelled.')
})
it('caps concurrency while continuing independent checks after a failure', async () => {
let active = 0
let peak = 0
const releases = []
const pending = runPool([0, 1, 2], 2, async (task) => {
active += 1
peak = Math.max(peak, active)
await new Promise((resolve) => releases.push(resolve))
active -= 1
return { task, ok: task !== 0 }
})
expect(releases).toHaveLength(2)
releases[0]()
await vi.waitFor(() => expect(releases).toHaveLength(3))
releases[1]()
releases[2]()
const results = await pending
expect(peak).toBe(2)
expect(results).toEqual(
expect.arrayContaining([
{ task: 0, ok: false },
{ task: 1, ok: true },
{ task: 2, ok: true }
])
)
})