mirror of
https://github.com/Gitlawb/openclaude.git
synced 2026-11-06 20:58:14 -04:00
test: stabilize timing-sensitive tests (#2316)
This commit is contained in:
@@ -72,6 +72,7 @@ describe('openclaude launcher heap guard', () => {
|
||||
expect(source).not.toMatch(/import\s*\{[^}]*enableCompileCache[^}]*\}\s*from\s*['"]node:module['"]/s)
|
||||
})
|
||||
|
||||
// Real CLI startup has an 8s child deadline; allow time to assert its result.
|
||||
test('strips launcher-only percentage before Commander when native heap and expose-gc are present', () => {
|
||||
const env = {
|
||||
...process.env,
|
||||
@@ -98,8 +99,9 @@ describe('openclaude launcher heap guard', () => {
|
||||
expect(output).not.toContain(
|
||||
"unknown option '--max-old-space-size-percentage=50'",
|
||||
)
|
||||
})
|
||||
}, 10_000)
|
||||
|
||||
// Real CLI startup has an 8s child deadline; allow time to assert its result.
|
||||
test('strips launcher-only percentage before Commander when heap relaunch is disabled', () => {
|
||||
const env = {
|
||||
...process.env,
|
||||
@@ -120,8 +122,9 @@ describe('openclaude launcher heap guard', () => {
|
||||
expect(output).not.toContain(
|
||||
"unknown option '--max-old-space-size-percentage=50'",
|
||||
)
|
||||
})
|
||||
}, 10_000)
|
||||
|
||||
// Real CLI startup has an 8s child deadline; allow time to assert its result.
|
||||
test('strips launcher-only percentage when OPENCLAUDE_HEAP_RELAUNCHED is already set', () => {
|
||||
const env = {
|
||||
...process.env,
|
||||
@@ -142,7 +145,7 @@ describe('openclaude launcher heap guard', () => {
|
||||
expect(output).not.toContain(
|
||||
"unknown option '--max-old-space-size-percentage=50'",
|
||||
)
|
||||
})
|
||||
}, 10_000)
|
||||
})
|
||||
|
||||
describe('heap-limit percentage resolution', () => {
|
||||
|
||||
@@ -633,8 +633,8 @@ describe('background session finalizer', () => {
|
||||
return { id, child, readyPath }
|
||||
}
|
||||
|
||||
async function waitForFile(path: string): Promise<void> {
|
||||
for (let attempt = 0; attempt < 500; attempt += 1) {
|
||||
async function waitForFile(path: string, attempts: number = 500): Promise<void> {
|
||||
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
||||
if (await Bun.file(path).exists()) return
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
}
|
||||
@@ -967,6 +967,7 @@ describe('background session finalizer', () => {
|
||||
async function runWaitingDetachedLaunch(
|
||||
name: string,
|
||||
fixtureEnv: NodeJS.ProcessEnv = {},
|
||||
readinessAttempts?: number,
|
||||
): Promise<{ id: string; childPid: number; readyPath: string }> {
|
||||
const readyPath = join(configDir, `${name}.ready`)
|
||||
const launcher = spawn(
|
||||
@@ -1017,7 +1018,7 @@ describe('background session finalizer', () => {
|
||||
if (!id || childPid === undefined) {
|
||||
throw new Error('detached wait launch omitted its session identity')
|
||||
}
|
||||
await waitForFile(readyPath)
|
||||
await waitForFile(readyPath, readinessAttempts)
|
||||
ownershipTransferred = true
|
||||
return { id, childPid, readyPath }
|
||||
} finally {
|
||||
@@ -1044,6 +1045,9 @@ describe('background session finalizer', () => {
|
||||
env: {
|
||||
OPENCLAUDE_BG_FINALIZER_FIXTURE_SKIP_READY: '1',
|
||||
},
|
||||
// Readiness is deliberately suppressed; only exercise the failure path.
|
||||
readinessAttempts: 25,
|
||||
expectedError: 'fixture readiness file was not created',
|
||||
},
|
||||
]) {
|
||||
it(
|
||||
@@ -1051,8 +1055,8 @@ describe('background session finalizer', () => {
|
||||
async () => {
|
||||
const name = `failed-handoff-${scenario.label.replaceAll(' ', '-')}`
|
||||
await expect(
|
||||
runWaitingDetachedLaunch(name, scenario.env),
|
||||
).rejects.toThrow()
|
||||
runWaitingDetachedLaunch(name, scenario.env, scenario.readinessAttempts),
|
||||
).rejects.toThrow(scenario.expectedError)
|
||||
const session = (await listBackgroundSessions()).find(
|
||||
candidate => candidate.name === name,
|
||||
)
|
||||
|
||||
@@ -135,18 +135,6 @@ function createHeadlessRunOptions(maxTurns: number | undefined) {
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForAskCall(
|
||||
askSpy: ReturnType<typeof spyOn<typeof queryEngineModule, 'ask'>>,
|
||||
): Promise<void> {
|
||||
const deadline = Date.now() + 15_000
|
||||
while (askSpy.mock.calls.length === 0) {
|
||||
if (Date.now() >= deadline) {
|
||||
throw new Error('Timed out waiting for runHeadless to call ask()')
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 25))
|
||||
}
|
||||
}
|
||||
|
||||
describe('headless --print max-turns', () => {
|
||||
const savedSimple = process.env.CLAUDE_CODE_SIMPLE
|
||||
|
||||
@@ -213,9 +201,8 @@ describe('headless --print max-turns', () => {
|
||||
createHeadlessRunOptions(0),
|
||||
)
|
||||
|
||||
await waitForAskCall(askSpy)
|
||||
expect(askSpy.mock.calls[0]?.[0]?.maxTurns).toBe(0)
|
||||
await runPromise
|
||||
expect(askSpy.mock.calls[0]?.[0]?.maxTurns).toBe(0)
|
||||
expect(shutdownSpy).toHaveBeenCalledWith(0)
|
||||
} finally {
|
||||
await runPromise?.catch(() => {})
|
||||
|
||||
@@ -119,7 +119,7 @@ test.each([
|
||||
/** Observes the real hook after mounting its AppState provider. */
|
||||
function HookProbe() {
|
||||
observedBanner = useSwarmBanner()
|
||||
React.useEffect(() => { notifyRendered() }, [])
|
||||
React.useLayoutEffect(() => { notifyRendered() }, [])
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user