tests/e2e/sandbox-manual-pause.spec.ts
Rama main · réplica de lectura del repositorio original.
import { expect, test } from "@playwright/test";
import {
buildRoutes,
withDatabase,
} from "../support/sandbox-pause-race-harness";
import {
withResumeDatabase,
legacyMissingVmWrite,
} from "../support/sandbox-resume-race-harness";
import { enableScopedE2EAuth, scopedPath } from "./helpers/auth";
import {
initializeTrackedEvents,
mockActivationFlow,
syncedRepo,
} from "./helpers/activation-fixtures";
test("pause and resume preserve the saved workspace across concurrent provider-status reads", async ({
page,
}) => {
await initializeTrackedEvents(page);
await enableScopedE2EAuth(page);
const harness = await mockActivationFlow(page, {
initialRepos: [syncedRepo],
});
const recordId = "sandbox-record-repo-1";
harness.seedSandbox("repo-1", { status: "running" });
let pausedSandbox: { runtime_summary: { status: string } } | undefined;
await page.route(`**/api/sandbox/${recordId}/health`, async (route) => {
if (!pausedSandbox) return route.fallback();
// Health reads the same saved record, including persistence/snapshot
// metadata. The generic activation fixture models a legacy sandbox.
await route.fulfill({
json: {
health: { status: pausedSandbox.runtime_summary.status },
sandbox: pausedSandbox,
},
});
});
await page.route(`**/api/sandbox/${recordId}/pause`, async (route) => {
await withDatabase(async (pg) => {
const routes = buildRoutes(
pg,
async () => {
await routes.detail();
},
async () => "stopped",
recordId
);
const result = await routes.pause();
const payload = await result.json();
pausedSandbox = payload.sandbox;
await route.fulfill({
status: result.status,
contentType: "application/json",
body: JSON.stringify(payload),
});
}, recordId);
});
await page.goto(scopedPath("projects/workspace"));
await page.getByTestId("home-open-workspace-repo-1").click();
const pauseResponse = page.waitForResponse((response) =>
new URL(response.url()).pathname.endsWith("/pause")
);
await page.getByRole("button", { name: "Pause", exact: true }).click();
const response = await pauseResponse;
const payload = await response.json();
expect(response.status(), JSON.stringify(payload)).toBe(200);
expect(payload.sandbox.id).toBe(recordId);
expect(payload.sandbox.runtime_summary.status).toBe("paused");
await expect(
page.getByRole("button", { name: "Resume", exact: true })
).toBeVisible();
await expect(page.getByText("Sandbox paused", { exact: true })).toBeVisible();
await page.route(`**/api/sandbox/${recordId}/resume`, async (route) => {
await withResumeDatabase(
async ({ resume }) => {
const resumed = await resume();
const body = await resumed.text();
const ready = body
.split("\n\n")
.filter((frame) => frame.startsWith("data: "))
.map((frame) => JSON.parse(frame.slice(6)))
.find((event) => event.type === "ready");
expect(ready?.sandbox.id).toBe(recordId);
expect(ready?.sandbox.working_branch).toBe("saved-work");
expect(ready?.sandbox.snapshot_id).toBe("snap_saved");
pausedSandbox = ready.sandbox;
harness.setSandboxState("repo-1", {
status: "running",
health_status: "running",
});
await route.fulfill({
status: resumed.status,
contentType: "text/event-stream",
body,
});
},
recordId,
legacyMissingVmWrite
);
});
await page.getByRole("button", { name: "Resume", exact: true }).click();
await expect(
page.getByRole("button", { name: "Pause", exact: true })
).toBeVisible();
await expect(
page.getByText("Sandbox paused", { exact: true })
).not.toBeVisible();
});