tests/e2e/control-history-refresh.spec.ts
Rama main · réplica de lectura del repositorio original.
import { expect, test } from "@playwright/test";
import { scopedPath } from "./helpers/auth";
import { fulfillJson } from "./helpers/automation-control-plane-fixtures";
import {
captureRecoveryEvents,
invalidateRecoverySessions,
mockRecoveryChrome,
recoverySession,
} from "./helpers/control-recovery-fixtures";
for (const newChat of [false, true]) {
test(`failed background history refresh keeps loaded chats usable in ${newChat ? "a new chat" : "the current chat"}`, async ({
page,
}) => {
await mockRecoveryChrome(page);
await captureRecoveryEvents(page);
let failed = false;
await page.route("**/api/control/sessions**", (route) => {
const id = new URL(route.request().url()).searchParams.get("id");
return fulfillJson(
route,
id
? recoverySession
: failed
? { error: "Could not refresh chats. Try again." }
: [recoverySession],
!id && failed ? 500 : 200
);
});
await page.goto(`${scopedPath("control")}?mission=${recoverySession.id}`);
await expect(
page.getByText("Saved request", { exact: true })
).toBeVisible();
const sidebar = page.getByRole("complementary", { name: "Sessions" });
const row = sidebar.getByRole("button", { name: /^Saved investigation / });
if (newChat) {
await page
.getByRole("button", { name: "New session", exact: true })
.click();
await page
.getByPlaceholder("Ask anything or run a command...")
.fill("Keep my new draft");
}
failed = true;
await invalidateRecoverySessions(page);
await expect(sidebar.getByRole("alert")).toContainText(
"Could not refresh chats"
);
await expect(row).toBeVisible();
await (newChat
? expect(
page.getByPlaceholder("Ask anything or run a command...")
).toHaveValue("Keep my new draft")
: expect(page.getByText("Saved request", { exact: true })).toBeVisible());
failed = false;
await sidebar.getByRole("button", { name: "Retry", exact: true }).click();
await expect(sidebar.getByRole("alert")).toHaveCount(0);
await expect(row).toBeVisible();
await row.click();
await expect(
page.getByText("Saved request", { exact: true })
).toBeVisible();
});
}
test("failed initial restore waits for explicit Retry after a history refresh", async ({
page,
}) => {
await mockRecoveryChrome(page);
await captureRecoveryEvents(page);
let failSelection = true;
let refreshed = false;
let selections = 0;
await page.route("**/api/control/sessions**", (route) => {
const id = new URL(route.request().url()).searchParams.get("id");
if (id) selections++;
return fulfillJson(
route,
id
? failSelection
? { error: "Could not load this chat. Try again." }
: recoverySession
: [
{
...recoverySession,
title: refreshed ? "Updated history" : recoverySession.title,
},
],
id && failSelection ? 503 : 200
);
});
await page.goto(`${scopedPath("control")}?mission=${recoverySession.id}`);
const banner = page
.getByRole("alert")
.filter({ hasText: "Could not load this chat" });
await expect(banner).toBeVisible();
const composer = page.getByPlaceholder("Ask anything or run a command...");
await composer.fill("Do not discard this new draft");
failSelection = false;
refreshed = true;
await invalidateRecoverySessions(page);
await expect(
page.getByRole("button", { name: /^Updated history / })
).toBeVisible();
await expect(composer).toHaveValue("Do not discard this new draft");
await banner.getByRole("button", { name: "Retry" }).click();
await expect(page.getByText("Saved request", { exact: true })).toBeVisible();
expect(selections).toBe(3); // Initial restore, explicit Retry, current-chat hydration.
});
for (const mutation of ["archive", "delete"] as const) {
test(`${mutation} retires the selected chat failure without a stale Retry`, async ({
page,
}) => {
await mockRecoveryChrome(page);
await captureRecoveryEvents(page);
let failSelection = false;
let removed = false;
await page.route("**/api/control/sessions**", (route) => {
const request = route.request();
if (request.method() === "PUT") {
removed = true;
return fulfillJson(route, {
session: { ...recoverySession, archived: true },
});
}
if (request.method() === "DELETE") {
removed = true;
return fulfillJson(route, { ok: true });
}
const id = new URL(request.url()).searchParams.get("id");
return fulfillJson(
route,
id
? failSelection
? { error: "Could not load this chat. Try again." }
: recoverySession
: removed
? []
: [recoverySession],
id && failSelection ? 503 : 200
);
});
await page.goto(`${scopedPath("control")}?mission=${recoverySession.id}`);
await expect(
page.getByText("Saved request", { exact: true })
).toBeVisible();
failSelection = true;
await invalidateRecoverySessions(page);
const banner = page
.getByRole("alert")
.filter({ hasText: "Could not load this chat" });
await expect(banner).toBeVisible();
if (mutation === "archive") {
await page.getByRole("button", { name: "More options" }).click();
await page
.getByRole("menuitem", { name: "Archive", exact: true })
.click();
} else {
await page
.getByRole("button", { name: "Actions for Saved investigation" })
.click();
await page
.getByRole("menuitem", { name: "Delete chat", exact: true })
.click();
await page
.getByRole("alertdialog", { name: "Delete Saved investigation?" })
.getByRole("button", { name: "Delete chat", exact: true })
.click();
}
await expect(
page.getByPlaceholder("Ask anything or run a command...")
).toBeVisible();
await expect(banner).toHaveCount(0);
expect(removed).toBe(true);
});
}