Files
orca/config/scripts/headless-serve-shutdown-matrix.test.mjs
T
Neil 22ce8d69a1 fix(lint): enable anti-slop/no-module-mocking (#20783)
The rule rejects `vi.mock` / `vi.doMock` / `vi.unstable_mockModule` and the
`jest` equivalents, on the argument that a test which rewrites the module graph
asserts against a stand-in the production code never sees. It is already off for
`**/*.test.{ts,tsx}`, `**/*.spec.{ts,tsx}`, `tests/**` and `**/__mocks__/**` via
the existing override in config/oxlint-anti-slop.json; that override is
unchanged here. What the rule actually catches is module mocking that has drifted
out of a spec and into a first-party `.ts` support module, where nothing marks it
as test-only.

73 violations at baseline, all of them in test-support code. 9 were relocated
back into spec files the override already exempts; the remaining 64 sit in 10
files that are test-only but do not match the override globs, and carry a
file-level disable naming the rule and the reason.

Relocated:
- terminal-hydration-store-test-bootstrap.ts: the sonner / sync-runtime-graph /
  pty-transport `vi.mock` calls moved into the two specs that import it
  (terminals-hydration-canonical-rows, terminals-hydration-canonical-pty-overlap).
  Vitest hoists `vi.mock` inside a test file, so registration is strictly earlier
  than the previous module-eval-time call; the bootstrap keeps only the preload
  API proxy. Both importers were updated.
- ipc-events-ssh-authority-test-fixtures.ts: the 6 direct-ssh `vi.doMock` calls
  moved into useIpcEvents-agent-status-ssh-authority.test.ts as a local
  `stubDirectSshModules()` helper, which also de-duplicates the three copies the
  spec already had inline. The fixture now returns the store state and coordinator
  doubles it builds, typed via the exported DirectSshReconnectCoordinatorDouble.

Suppressed, with justification (each is `/* oxlint-disable
anti-slop/no-module-mocking -- ... */`, rule named, no blanket disable):
- config/scripts/headless-serve-shutdown-matrix.test.mjs (1) - a genuine Vitest
  spec that the override misses only because its globs say {ts,tsx}. The script
  under test is a top-level CLI module; the alternative is spawning real docker.
- src/main/codex-accounts/runtime-home-service-test-harness.ts (1) - stubs one
  probe predicate in ../pty/shell-startup-env, imported directly by several
  main-process readers; 17 specs share it.
- src/main/computer/desktop-script-provider-test-harness.ts (2) - stubs
  child_process/fs-promises for a provider that shells out; 8 specs share it.
- src/main/github/work-item-search-test-harness.ts (4) - one consumer lives in
  tests/e2e, where the relative mock ids resolve differently, so moving the calls
  into the specs would silently stop mocking there.
- src/renderer/src/components/automations/automations-page-test-harness.tsx (14)
  - the mount rig for 10 AutomationsPage specs.
- src/renderer/src/components/terminal-pane/remote-runtime-pty-transport-test-harness.ts
  (1) - stubs refreshWebRuntimeSessionTabsSnapshot, imported directly by several
  renderer runtime modules; 18 specs share it.
- src/renderer/src/hooks/ipc-events-agent-status-window-test-fixtures.ts (7) -
  stubReactSyncEffect/stubAuxiliaryModules, shared by 11 specs.
- src/renderer/src/hooks/ipc-events-close-routing-test-harness.ts (11) - stubs
  and hook invocation are one unit; 4 specs share it.
- src/renderer/src/hooks/ipc-events-terminal-create-test-harness.ts (13) - its
  only spec is at 799 of an 800 max-lines budget.
- src/renderer/src/hooks/ipc-events-test-harness.ts (10) - shared by 8 specs.

No violation was converted to real dependency injection, and no max-lines disable
was added.

Verified: the audit command exits 0 with no output (and reports errors on a
planted probe, so the rule is live); node config/scripts/run-typecheck-projects-in-parallel.mjs
exits 0; 354 spec files / 2506 tests covering every importer of every touched
file pass. No mobile/ file was touched.

The changed-code quality gate's root Oxlint scan runs without --config so it never
loads the anti-slop JS plugin, which made all 10 of those file-level suppressions
read as "Unused oxlint-disable directive". check-changed-code-quality.mjs now
exempts directives naming an anti-slop rule from that unused-directive warning,
the same carve-out isCastingDirectiveUnusedWarning already makes for the casting
suppressions the casting config enforces. Such a directive can never suppress a
root-config rule, so nothing the root scan would otherwise report is hidden;
audit:anti-slop remains the scan that enforces the rule.
2026-09-15 00:41:17 -07:00

145 lines
5.4 KiB
JavaScript

/* oxlint-disable anti-slop/no-module-mocking -- This IS the Vitest spec for run-headless-serve-shutdown-docker.mjs, but the rule's test-file
override globs only .ts/.tsx, so a .test.mjs spec slips through. The script under test is a
top-level CLI module driven via vi.resetModules() + await import(); the only other way to observe
its docker argv is to spawn real docker. */
import { createHash } from 'node:crypto'
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
const { spawnSync } = vi.hoisted(() => ({ spawnSync: vi.fn() }))
vi.mock('node:child_process', () => ({ spawnSync }))
let directory
let artifact
let originalArgv
let originalExitCode
const commands = () => spawnSync.mock.calls.map(([, args]) => args)
const signalRuns = () => commands().filter((args) => ['INT', 'TERM'].includes(args.at(-1)))
const succeeded = { status: 0, stdout: '', stderr: '' }
async function run(...options) {
process.argv = ['node', 'runner', '--appimage', artifact, ...options]
await import('./run-headless-serve-shutdown-docker.mjs')
}
beforeEach(() => {
vi.resetModules()
spawnSync.mockReset().mockReturnValue(succeeded)
vi.spyOn(console, 'log').mockImplementation(() => {})
vi.spyOn(console, 'error').mockImplementation(() => {})
directory = mkdtempSync(join(tmpdir(), 'orca-shutdown-matrix-'))
artifact = join(directory, 'original.AppImage')
writeFileSync(artifact, 'original package bytes')
originalArgv = process.argv
originalExitCode = process.exitCode
})
afterEach(() => {
process.argv = originalArgv
process.exitCode = originalExitCode
rmSync(directory, { recursive: true, force: true })
vi.restoreAllMocks()
})
describe('packaged shutdown matrix', () => {
it('shares extraction but isolates every entrypoint and signal', async () => {
await run('--all-entrypoints')
expect(commands().filter((args) => args[0] === 'build')).toHaveLength(1)
const startup = commands().filter((args) =>
args.includes('/usr/local/bin/run-appimage-desktop-startup-case')
)
const extraction = commands().filter((args) =>
args.some((arg) => arg.includes('120s /input/orca.AppImage --appimage-extract'))
)
expect(startup).toHaveLength(1)
expect(extraction).toHaveLength(1)
expect(commands().indexOf(startup[0])).toBeLessThan(commands().indexOf(extraction[0]))
expect(signalRuns()).toHaveLength(6)
const names = new Set()
for (const [index, args] of signalRuns().entries()) {
const entrypoint = ['app', 'launcher', 'appimage'][Math.floor(index / 2)]
expect(args).toContain(`ORCA_TEST_ENTRYPOINT=${entrypoint}`)
expect(args).toContain(
`ORCA_SIGNAL_TARGET=${entrypoint === 'appimage' ? 'serving-electron' : 'app'}`
)
expect(args).toContain(
`ORCA_INT_DELIVERY=${entrypoint === 'appimage' ? 'pid' : 'foreground-process-group'}`
)
expect(args.at(-1)).toBe(index % 2 === 0 ? 'INT' : 'TERM')
expect(args).toContain(`${artifact}:/input/orca.AppImage:ro`)
expect(args.some((arg) => arg.endsWith(':/artifacts:ro'))).toBe(true)
expect(args).toContain('--rm')
names.add(args[args.indexOf('--name') + 1])
}
expect(names.size).toBe(6)
const evidence = console.log.mock.calls
.map(([line]) => line)
.filter((line) => line.startsWith('{'))
.map(JSON.parse)
expect(evidence).toHaveLength(3)
expect(
evidence.every(
(entry) =>
entry.sha256 === createHash('sha256').update('original package bytes').digest('hex')
)
).toBe(true)
expect(
commands()
.slice(-2)
.map((args) => args.slice(0, 2))
).toEqual([
['volume', 'rm'],
['image', 'rm']
])
})
it('attributes failures and still attempts later cases before cleanup', async () => {
spawnSync.mockImplementation((_, args) =>
args.at(-1) === 'INT' ? { ...succeeded, status: 7 } : succeeded
)
await expect(run('--all-entrypoints')).rejects.toThrow(
'app:INT:7, launcher:INT:7, appimage:INT:7'
)
expect(signalRuns()).toHaveLength(6)
expect(commands().at(-2).slice(0, 2)).toEqual(['volume', 'rm'])
})
it('cleans setup resources without running cases after failed extraction', async () => {
spawnSync.mockImplementation((_, args) =>
args.some((arg) => arg.includes('120s /input/orca.AppImage --appimage-extract'))
? { ...succeeded, status: 9 }
: succeeded
)
await expect(run('--all-entrypoints')).rejects.toThrow('docker run failed')
expect(signalRuns()).toHaveLength(0)
expect(
commands()
.slice(-2)
.map((args) => args.slice(0, 2))
).toEqual([
['volume', 'rm'],
['image', 'rm']
])
})
it('preserves individual launcher overlay invocations', async () => {
await run('--entrypoint', 'launcher', '--launcher-exec-overlay')
expect(signalRuns()).toHaveLength(2)
expect(signalRuns().every((args) => args.includes('ORCA_TEST_ENTRYPOINT=launcher'))).toBe(true)
expect(
commands().some((args) =>
args.some((arg) => arg.includes("sed -i 's/^ELECTRON_RUN_AS_NODE=1"))
)
).toBe(true)
})
it('rejects ambiguous matrix overrides before invoking Docker', async () => {
await expect(run('--all-entrypoints', '--entrypoint', 'launcher')).rejects.toThrow(
'cannot be combined'
)
expect(spawnSync).not.toHaveBeenCalled()
})
})