Update terminal activity E2E for finished attention

This commit is contained in:
Mohamed Boudra
2026-06-15 21:07:07 +07:00
parent 1c9e78616f
commit af0437e6df
2 changed files with 23 additions and 7 deletions
+12 -3
View File
@@ -1,5 +1,5 @@
import type { Page } from "@playwright/test"; import type { Page } from "@playwright/test";
import type { TerminalActivityState } from "@getpaseo/protocol/terminal-activity"; import type { TerminalActivity, TerminalActivityState } from "@getpaseo/protocol/terminal-activity";
import { createTempGitRepo } from "./workspace"; import { createTempGitRepo } from "./workspace";
import { navigateToTerminal, setupDeterministicPrompt } from "./terminal-perf"; import { navigateToTerminal, setupDeterministicPrompt } from "./terminal-perf";
import { connectSeedClient, type SeedDaemonClient } from "./seed-client"; import { connectSeedClient, type SeedDaemonClient } from "./seed-client";
@@ -84,6 +84,7 @@ export class TerminalE2EHarness {
async waitForTerminalActivity(input: { async waitForTerminalActivity(input: {
terminalId: string; terminalId: string;
state: TerminalActivityState | null; state: TerminalActivityState | null;
attentionReason?: TerminalActivity["attentionReason"] | null;
timeoutMs?: number; timeoutMs?: number;
}): Promise<void> { }): Promise<void> {
const timeoutMs = input.timeoutMs ?? 10_000; const timeoutMs = input.timeoutMs ?? 10_000;
@@ -91,13 +92,21 @@ export class TerminalE2EHarness {
while (Date.now() < deadline) { while (Date.now() < deadline) {
const result = await this.client.listTerminals(this.tempRepo.path); const result = await this.client.listTerminals(this.tempRepo.path);
const terminal = result.terminals.find((entry) => entry.id === input.terminalId); const terminal = result.terminals.find((entry) => entry.id === input.terminalId);
if ((terminal?.activity?.state ?? null) === input.state) { const activity = terminal?.activity ?? null;
const attentionMatches =
input.attentionReason === undefined ||
(activity?.attentionReason ?? null) === input.attentionReason;
if ((activity?.state ?? null) === input.state && attentionMatches) {
return; return;
} }
await sleep(50); await sleep(50);
} }
const attentionSuffix =
input.attentionReason === undefined
? ""
: ` with attention ${input.attentionReason ?? "none"}`;
throw new Error( throw new Error(
`Timed out waiting for terminal ${input.terminalId} activity state ${input.state ?? "unknown"}`, `Timed out waiting for terminal ${input.terminalId} activity state ${input.state ?? "unknown"}${attentionSuffix}`,
); );
} }
@@ -4,7 +4,7 @@ import { test, expect, type Page } from "./fixtures";
import { TerminalE2EHarness, type TerminalInstance } from "./helpers/terminal-dsl"; import { TerminalE2EHarness, type TerminalInstance } from "./helpers/terminal-dsl";
type HookActivityState = "running" | "idle" | "needs-input"; type HookActivityState = "running" | "idle" | "needs-input";
type TabStatusBucket = "running" | "needs_input" | "none"; type TabStatusBucket = "running" | "needs_input" | "attention" | "none";
const TERMINAL_ACTIVITY_REPORTER_SCRIPT = ` const TERMINAL_ACTIVITY_REPORTER_SCRIPT = `
const fs = require("node:fs"); const fs = require("node:fs");
@@ -52,16 +52,21 @@ async function reportActivity(state) {
}); });
`; `;
function internalActivityState(state: HookActivityState): "working" | "idle" | "attention" { function internalActivityState(state: HookActivityState): "working" | "idle" {
if (state === "running") return "working"; if (state === "running") return "working";
if (state === "needs-input") return "attention";
return "idle"; return "idle";
} }
function tabStatusBucket(state: HookActivityState): TabStatusBucket { function tabStatusBucket(state: HookActivityState): TabStatusBucket {
if (state === "running") return "running"; if (state === "running") return "running";
if (state === "needs-input") return "needs_input"; if (state === "needs-input") return "needs_input";
return "none"; return "attention";
}
function expectedAttentionReason(state: HookActivityState): "finished" | "needs_input" | null {
if (state === "idle") return "finished";
if (state === "needs-input") return "needs_input";
return null;
} }
function terminalTab(page: Page, terminalId: string) { function terminalTab(page: Page, terminalId: string) {
@@ -96,6 +101,7 @@ class ControlledActivityTerminal {
await this.harness.waitForTerminalActivity({ await this.harness.waitForTerminalActivity({
terminalId: this.terminal.id, terminalId: this.terminal.id,
state: internalActivityState(state), state: internalActivityState(state),
attentionReason: expectedAttentionReason(state),
timeoutMs: 15_000, timeoutMs: 15_000,
}); });
} }
@@ -166,6 +172,7 @@ test.describe("Terminal activity indicators", () => {
await harness.waitForTerminalActivity({ await harness.waitForTerminalActivity({
terminalId: activityTerminal.terminal.id, terminalId: activityTerminal.terminal.id,
state: "idle", state: "idle",
attentionReason: null,
timeoutMs: 15_000, timeoutMs: 15_000,
}); });
await expectTerminalTabStatus(page, activityTerminal.terminal.id, "none"); await expectTerminalTabStatus(page, activityTerminal.terminal.id, "none");