Ctrl K
ComunidadGuías…

tests/e2e/sandbox-billing-observability.spec.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { expect, test } from "@playwright/test";
import { scopedPath } from "./helpers/auth";
import { emptyAutomationFailuresResponse } from "./helpers/activation-fixtures";
import {
  buildObservabilitySummary,
  buildSandboxBackedCall,
} from "./helpers/sandbox-fixtures";
import {
  createBillingState,
  installBaseMocks,
  fulfillJson,
} from "./helpers/sandbox-billing-fixtures";
import type { Page } from "@playwright/test";

async function installObservabilityMocks(page: Page) {
  const call = buildSandboxBackedCall({
    repoId: "repo-1",
    sandboxRecordId: "sandbox-record-1",
    sandboxId: "sandbox-runtime-1",
    previewUrl: "https://preview.mogplex.test",
    computeBillingSource: "user_vercel_project",
    billingProjectId: "proj_user_123",
    billingTeamId: "team-acme",
    aiBillingSource: "user_ai_gateway",
  });

  await page.route("**/api/observability/stats*", (route) =>
    fulfillJson(route, buildObservabilitySummary([call]))
  );
  await page.route(/\/api\/observability\/jobs(?:\?.*)?$/, (route) =>
    fulfillJson(route, { jobs: [], total: 0, page: 1, limit: 25 })
  );
  await page.route(
    /\/api\/observability\/automation-events(?:\?.*)?$/,
    (route) => fulfillJson(route, { events: [], total: 0, page: 1, limit: 25 })
  );
  await page.route(
    /\/api\/observability\/automation-failures(?:\?.*)?$/,
    (route) => fulfillJson(route, emptyAutomationFailuresResponse)
  );
  await page.route(/\/api\/observability\/calls(?:\?.*)?$/, (route) => {
    const url = new URL(route.request().url());
    const liveOnly = url.searchParams.get("live_only") === "true";
    return fulfillJson(route, {
      calls: [call],
      total: 1,
      page: 1,
      limit: liveOnly ? 100 : 50,
    });
  });
  await page.route(/\/api\/observability\/call-events(?:\?.*)?$/, (route) =>
    fulfillJson(route, { events: [] })
  );
}

test("observability surfaces sandbox compute and AI billing details", async ({
  page,
}) => {
  const state = createBillingState({
    workspace: {
      sandbox_billing_mode: "user_vercel_project",
      sandbox_vercel_team_id: "team-acme",
      sandbox_vercel_project_id: "workspace-app",
    },
  });
  await installBaseMocks(page, state);
  await page.route("**/api/realtime/events?*", (route) =>
    route.fulfill({ status: 204 })
  );
  await installObservabilityMocks(page);

  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 activitySection = page.getByRole("tabpanel");
  await activitySection.locator("tbody tr").first().click();

  await expect(activitySection.getByText("Sandbox Billing")).toBeVisible();
  await expect(activitySection.getByText("Compute Billing")).toBeVisible();
  await expect(activitySection.getByText("user billing")).toBeVisible();
  await expect(activitySection.getByText("AI Billing Source")).toBeVisible();
  await expect(activitySection.getByText("user ai gateway")).toBeVisible();
  await expect(activitySection.getByText("proj_user_123")).toBeVisible();
  await expect(activitySection.getByText("team-acme")).toBeVisible();
  await expect(
    activitySection.getByText("sandbox-record-1", { exact: true })
  ).toBeVisible();
  await expect(
    activitySection.getByText("sandbox-runtime-1", { exact: true })
  ).toBeVisible();
});