tests/e2e/activation-reliability-preview.spec.ts
Rama main · réplica de lectura del repositorio original.
import { expect, test } from "@playwright/test";
import { enableScopedE2EAuth, scopedPath } from "./helpers/auth";
import {
initializeTrackedEvents,
mockActivationFlow,
} from "./helpers/activation-fixtures";
import { buildSandboxBackedCall } from "./helpers/sandbox-fixtures";
test("preview app errors surface recovery UI and clear live chrome", async ({
page,
}) => {
await initializeTrackedEvents(page);
await enableScopedE2EAuth(page);
const harness = await mockActivationFlow(page);
await page.goto(scopedPath("projects/workspace"));
await page.waitForLoadState("networkidle");
await page.getByTestId("home-sync-repos").click();
await page.getByTestId("home-open-workspace-repo-1").click();
const readyBadges = page.getByText("ready", { exact: true });
await expect(readyBadges.first()).toBeVisible();
harness.setSandboxState("repo-1", {
status: "running",
health_status: "app_error",
last_preview_http_status: 500,
last_preview_error: "HTTP 500 at preview",
});
await page.evaluate(() => {
window.dispatchEvent(new Event("focus"));
document.dispatchEvent(new Event("visibilitychange"));
});
await expect(
page.getByText("Preview returned an application error")
).toBeVisible();
await expect(
page.getByRole("button", { name: "Restart preview" })
).toBeVisible();
await expect(readyBadges).toHaveCount(0);
});
test("preview build failures surface Vercel deployment diagnostics in preview and health", async ({
page,
}) => {
await initializeTrackedEvents(page);
await enableScopedE2EAuth(page);
const harness = await mockActivationFlow(page);
await page.goto(scopedPath("projects/workspace"));
await page.waitForLoadState("networkidle");
await page.getByTestId("home-sync-repos").click();
await page.getByTestId("home-open-workspace-repo-1").click();
harness.setSandboxState("repo-1", {
status: "running",
health_status: "app_error",
last_preview_http_status: 503,
last_preview_error: "Service unavailable while deployment booted",
vercel_diagnostics: {
state: "build_failed",
deploymentId: "dpl_build_fail",
deploymentUrl: "https://failed-app.vercel.app",
deploymentStatus: "ERROR",
buildSummary: "Error: Missing NEXT_PUBLIC_API_URL",
detectedAt: "2026-04-01T12:05:00.000Z",
},
});
await page.evaluate(() => {
window.dispatchEvent(new Event("focus"));
document.dispatchEvent(new Event("visibilitychange"));
});
await expect(
page.getByText("Latest Vercel deployment failed to build")
).toBeVisible();
await expect(
page.getByText("Error: Missing NEXT_PUBLIC_API_URL")
).toBeVisible();
await page.getByRole("button", { name: "Open health" }).click();
await expect(page.getByText("Vercel Diagnostics")).toBeVisible();
await expect(page.getByText("Build failed")).toBeVisible();
await expect(
page.getByRole("link", { name: "open deployment" })
).toHaveAttribute("href", "https://failed-app.vercel.app");
});
test("preview building state surfaces Vercel deployment progress", async ({
page,
}) => {
await initializeTrackedEvents(page);
await enableScopedE2EAuth(page);
const harness = await mockActivationFlow(page);
await page.goto(scopedPath("projects/workspace"));
await page.waitForLoadState("networkidle");
await page.getByTestId("home-sync-repos").click();
await page.getByTestId("home-open-workspace-repo-1").click();
harness.setSandboxState("repo-1", {
status: "running",
health_status: "starting",
last_preview_http_status: 503,
last_preview_error: "Preview is still starting",
vercel_diagnostics: {
state: "building",
deploymentId: "dpl_building",
deploymentUrl: "https://building-app.vercel.app",
deploymentStatus: "BUILDING",
buildSummary: "Queued on build machine",
detectedAt: "2026-04-01T12:05:00.000Z",
},
});
await page.evaluate(() => {
window.dispatchEvent(new Event("focus"));
document.dispatchEvent(new Event("visibilitychange"));
});
await expect(
page.getByText("Vercel deployment is still building")
).toBeVisible();
await expect(page.getByText("Queued on build machine")).toBeVisible();
});
test("running VM with a non-listening dev server labels the chip as starting", async ({
page,
}) => {
await initializeTrackedEvents(page);
await enableScopedE2EAuth(page);
const harness = await mockActivationFlow(page);
await page.goto(scopedPath("projects/workspace"));
await page.waitForLoadState("networkidle");
await page.getByTestId("home-sync-repos").click();
await page.getByTestId("home-open-workspace-repo-1").click();
const readyBadges = page.getByText("ready", { exact: true });
await expect(readyBadges.first()).toBeVisible();
harness.setSandboxState("repo-1", {
status: "running",
health_status: "starting",
last_preview_http_status: 502,
last_preview_error: "SANDBOX_NOT_LISTENING",
});
await page.evaluate(() => {
window.dispatchEvent(new Event("focus"));
document.dispatchEvent(new Event("visibilitychange"));
});
await expect(page.getByText("starting dev server").first()).toBeVisible();
await expect(readyBadges).toHaveCount(0);
await expect(page.getByText(/sandbox live/i)).toHaveCount(0);
});
test("user-billed sandbox errors stay aligned across preview, health, and observability", async ({
page,
}) => {
await initializeTrackedEvents(page);
await enableScopedE2EAuth(page);
const previewUrl = "http://127.0.0.1:3000/__e2e/preview/repo-1";
const harness = await mockActivationFlow(page, {
observabilityCalls: [
buildSandboxBackedCall({
repoId: "repo-1",
sandboxRecordId: "sandbox-record-repo-1",
sandboxId: "sandbox-runtime-repo-1",
previewUrl,
computeBillingSource: "user_vercel_project",
billingProjectId: "proj_user_123",
billingTeamId: "team-acme",
aiBillingSource: "user_ai_gateway",
}),
],
});
harness.seedSandbox("repo-1", {
preview_url: previewUrl,
billing_source: "user_vercel_project",
billing_project_id: "proj_user_123",
billing_team_id: "team-acme",
vercel_project_id: "proj_user_123",
vercel_team_id: "team-acme",
health_status: "app_error",
last_preview_http_status: 500,
last_preview_error: "HTTP 500 at preview",
});
await page.goto(scopedPath("projects/workspace"));
await page.waitForLoadState("networkidle");
await page.getByTestId("home-sync-repos").click();
await page.getByTestId("home-open-workspace-repo-1").click();
await expect(
page.getByText("Preview returned an application error")
).toBeVisible();
await expect(
page.getByRole("button", { name: "Restart preview" })
).toBeVisible();
await page.getByRole("button", { name: "Open health" }).click();
await expect(page.getByText("Sandbox Health")).toBeVisible();
await expect(page.getByText("status: running")).toBeVisible();
await expect(page.getByText("health: app_error")).toBeVisible();
await expect(page.getByText("preview: HTTP 500")).toBeVisible();
await expect(page.getByText("Your Vercel project")).toBeVisible();
await expect(page.getByText("Project: proj_user_123")).toBeVisible();
await expect(page.getByText("Team: team-acme")).toBeVisible();
await expect(page.getByText("HTTP 500 at preview")).toBeVisible();
await page.goto(scopedPath("observability"));
await page.waitForLoadState("networkidle");
await expect(
page.getByRole("heading", { name: "Observability" })
).toBeVisible();
await page.getByRole("tab", { name: /^Usage/ }).click();
const callsSection = page.getByRole("tabpanel");
await callsSection.locator("tbody tr").first().click();
await expect(callsSection.getByText("Sandbox Billing")).toBeVisible();
await expect(callsSection.getByText("Compute Billing")).toBeVisible();
await expect(callsSection.getByText("user billing")).toBeVisible();
await expect(callsSection.getByText("AI Billing Source")).toBeVisible();
await expect(callsSection.getByText("user ai gateway")).toBeVisible();
await expect(callsSection.getByText("proj_user_123")).toBeVisible();
await expect(callsSection.getByText("team-acme")).toBeVisible();
await expect(
callsSection.getByText("sandbox-record-repo-1", { exact: true })
).toBeVisible();
await expect(
callsSection.getByText("sandbox-runtime-repo-1", { exact: true })
).toBeVisible();
});
test("preview unreachable state surfaces warning UI and clears live chrome", async ({
page,
}) => {
await initializeTrackedEvents(page);
await enableScopedE2EAuth(page);
const harness = await mockActivationFlow(page);
await page.goto(scopedPath("projects/workspace"));
await page.waitForLoadState("networkidle");
await page.getByTestId("home-sync-repos").click();
await page.getByTestId("home-open-workspace-repo-1").click();
const readyBadges = page.getByText("ready", { exact: true });
await expect(readyBadges.first()).toBeVisible();
harness.setSandboxState("repo-1", {
status: "running",
health_status: "unreachable",
last_preview_error: "Connection refused at preview",
});
await page.evaluate(() => {
window.dispatchEvent(new Event("focus"));
document.dispatchEvent(new Event("visibilitychange"));
});
await expect(page.getByText("Preview is unreachable")).toBeVisible();
await expect(
page.getByRole("button", { name: "Restart preview" })
).toBeVisible();
await expect(page.getByRole("button", { name: "Open health" })).toBeVisible();
await expect(readyBadges).toHaveCount(0);
});