perf(test): consolidate TUI PTY session coverage (#126185)

This commit is contained in:
Peter Steinberger
2026-08-18 21:42:01 -07:00
committed by GitHub
parent 41ed3c3460
commit caebee321d
4 changed files with 38 additions and 59 deletions
@@ -428,7 +428,7 @@ function hasStatusFrame(
);
}
async function exerciseSelectorOutputSafety(
export async function exerciseSelectorOutputSafety(
startFixture: StartTuiPtyFixture,
startupTimeoutMs: number,
) {
@@ -555,7 +555,7 @@ export async function exerciseNarrowTerminalRendering(
}
}
async function exerciseGatewayOutputSafety(
export async function exerciseGatewayOutputSafety(
startFixture: StartTuiPtyFixture,
startupTimeoutMs: number,
) {
@@ -591,6 +591,13 @@ async function exerciseGatewayOutputSafety(
expect(hasStatusFrame(fixture.run.output(), idlePayload.markers, /\| idle/u, fixture.run)).toBe(
true,
);
await waitForSynchronizedFrameRows(
fixture.run,
(rows) =>
rows.some((row) => row.includes("gateway reconnected after transport loss")) &&
rows.some((row) => row.includes("local ready | idle")),
startupTimeoutMs,
);
const helpOffset = fixture.run.visibleOutput().length;
await fixture.run.write("/help\r", { delay: false });
@@ -604,7 +611,7 @@ async function exerciseGatewayOutputSafety(
}
}
async function exerciseMarkdownAndAutocompleteOutputSafety(
export async function exerciseMarkdownAndAutocompleteOutputSafety(
startFixture: StartTuiPtyFixture,
startupTimeoutMs: number,
) {
@@ -660,7 +667,7 @@ async function exerciseMarkdownAndAutocompleteOutputSafety(
}
}
async function exerciseInteractiveOutputSafety(
export async function exerciseInteractiveOutputSafety(
startFixture: StartTuiPtyFixture,
startupTimeoutMs: number,
) {
@@ -698,18 +705,6 @@ async function exerciseInteractiveOutputSafety(
}
}
export async function exerciseTerminalOutputSafety(
startFixture: StartTuiPtyFixture,
startupTimeoutMs: number,
) {
await Promise.all([
exerciseGatewayOutputSafety(startFixture, startupTimeoutMs),
exerciseInteractiveOutputSafety(startFixture, startupTimeoutMs),
exerciseMarkdownAndAutocompleteOutputSafety(startFixture, startupTimeoutMs),
exerciseSelectorOutputSafety(startFixture, startupTimeoutMs),
]);
}
/** Proves fixture-local fragmentation preserves a Unicode prompt through the real TUI loop. */
export async function exerciseFragmentedUnicodePrompt(
startFixture: StartTuiPtyFixture,
+1 -1
View File
@@ -8,7 +8,6 @@ import {
disposeActiveTuiFixtures,
exerciseFragmentedUnicodePrompt,
exerciseNarrowTerminalRendering,
exerciseTerminalOutputSafety,
objectFieldEquals,
readFixtureLog,
startTuiFixture,
@@ -22,6 +21,7 @@ import {
streamingPrefixFrame,
toolFrame,
} from "./tui-pty-rendering-test-support.js";
import { exerciseTerminalOutputSafety } from "./tui-pty-terminal-output-safety-test-support.js";
const STARTUP_TIMEOUT_MS = 20_000;
const TEST_TIMEOUT_MS = 5_000;
const STARTUP_TEST_TIMEOUT_MS = 25_000;
@@ -0,0 +1,20 @@
// Groups the terminal-output safety exercises behind one PTY harness entry point.
import {
exerciseGatewayOutputSafety,
exerciseInteractiveOutputSafety,
exerciseMarkdownAndAutocompleteOutputSafety,
exerciseSelectorOutputSafety,
type StartTuiPtyFixture,
} from "./tui-pty-harness-assertion-test-support.js";
export async function exerciseTerminalOutputSafety(
startFixture: StartTuiPtyFixture,
startupTimeoutMs: number,
) {
await Promise.all([
exerciseGatewayOutputSafety(startFixture, startupTimeoutMs),
exerciseInteractiveOutputSafety(startFixture, startupTimeoutMs),
exerciseMarkdownAndAutocompleteOutputSafety(startFixture, startupTimeoutMs),
exerciseSelectorOutputSafety(startFixture, startupTimeoutMs),
]);
}
+6 -42
View File
@@ -109,15 +109,16 @@ it("hides a stale approval when startup restores the remembered session", async
}
}, 65_000);
it("restores a remembered global session before startup admits the first send", async () => {
const stateDir = tempDirs.make("openclaw-tui-global-session-");
const marker = "global startup session proof";
it("restores a remembered global session while keeping pre-ready input editable", async () => {
const stateDir = tempDirs.make("openclaw-tui-startup-session-");
const marker = "startup remembered session proof";
await seedRememberedSession(stateDir, "global");
const fixture = await startTuiFixture({
env: {
OPENCLAW_STATE_DIR: stateDir,
OPENCLAW_TUI_PTY_PICKER_FIXTURE: "1",
OPENCLAW_TUI_PTY_PICKER_SESSION_KEY: "global",
OPENCLAW_TUI_PTY_RESTORE_DELAY_MS: "400",
},
});
@@ -132,43 +133,6 @@ it("restores a remembered global session before startup admits the first send",
includeUnknown: false,
agentId: "main",
});
await fixture.run.waitForOutput("local ready", STARTUP_TIMEOUT_MS);
await fixture.run.write(`${marker}\r`, { delay: false });
await fixture.waitForLogEntry(
(entry) => entry.method === "sendChat" && objectFieldEquals(entry, "message", marker),
STARTUP_TIMEOUT_MS,
);
const sends = (await readFixtureLog(fixture.logPath)).filter(
(entry) => entry.method === "sendChat",
);
expect(sends).toHaveLength(1);
expect(sends[0]?.payload).toMatchObject({ sessionKey: "global", agentId: "main" });
} finally {
await fixture.cleanup();
}
}, 65_000);
it("keeps startup input editable until the remembered session and history are stable", async () => {
const stateDir = tempDirs.make("openclaw-tui-startup-session-");
const marker = "startup remembered session proof";
await seedRememberedSession(stateDir);
const fixture = await startTuiFixture({
env: {
OPENCLAW_STATE_DIR: stateDir,
OPENCLAW_TUI_PTY_PICKER_FIXTURE: "1",
OPENCLAW_TUI_PTY_RESTORE_DELAY_MS: "400",
},
});
try {
await fixture.waitForLogEntry(
(entry) =>
entry.method === "listSessions" &&
objectFieldEquals(entry, "search", REMEMBERED_SESSION_KEY),
STARTUP_TIMEOUT_MS,
);
const outputOffset = fixture.run.visibleOutput().length;
await fixture.run.write(`${marker}\r`, { delay: false });
const decision = await waitForSubmitDecision({ fixture, marker, outputOffset });
@@ -177,7 +141,7 @@ it("keeps startup input editable until the remembered session and history are st
const rows = await waitForSynchronizedFrameRows(
fixture.run,
(frame) =>
frame.some((row) => row.includes("session picker-target")) &&
frame.some((row) => row.includes("session global")) &&
frame.some((row) => row.includes("local ready")) &&
frame.some((row) => row.includes(marker)),
STARTUP_TIMEOUT_MS,
@@ -190,7 +154,7 @@ it("keeps startup input editable until the remembered session and history are st
(entry) => entry.method === "sendChat" && objectFieldEquals(entry, "message", marker),
STARTUP_TIMEOUT_MS,
);
expect(sent.payload).toMatchObject({ sessionKey: REMEMBERED_SESSION_KEY });
expect(sent.payload).toMatchObject({ sessionKey: "global", agentId: "main" });
expect(markerSends(await readFixtureLog(fixture.logPath), marker)).toHaveLength(1);
} finally {
await fixture.cleanup();