Ctrl K
ComunidadGuías…

tests/e2e/automation-control-plane-health.spec.ts

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

Archivo original ↗Preguntar a KiBot
import { expect, test } from "@playwright/test";
import { enableScopedE2EAuth, scopedPath } from "./helpers/auth";
import { emptyAutomationFailuresResponse } from "./helpers/activation-fixtures";
import {
  fulfillJson,
  mockBaseChrome,
  modelId,
} from "./helpers/automation-control-plane-fixtures";

for (const failedRuns of [0, 12]) {
  test(`automation history does not request user action (${failedRuns} failed runs)`, async ({
    page,
  }, testInfo) => {
    await enableScopedE2EAuth(page);
    await mockBaseChrome(page);

    await page.route("**/api/observability/stats*", (route) =>
      fulfillJson(route, {
        summary: {
          total_calls: 4,
          total_tokens: 12000,
          total_cost: 0.32,
          cost_today: 0.08,
          reconciliation_pending: 0,
          avg_duration_ms: 1820,
          success_rate: 100,
          calls_today: 2,
          tokens_today: 4000,
          sandbox_time_ms: 600000,
          sandbox_active: 0,
          sandbox_total: 2,
          job_runs_total: 7626,
          job_runs_running: 0,
          job_runs_pending: 0,
          job_runs_stale_pending: 0,
          job_runs_failed_in_range: failedRuns,
          job_runs_repaired_in_range: 19,
          job_runs_concluded_in_range: 804,
          job_runs_success_rate_in_range: failedRuns > 0 ? 75 : 100,
          suppressed_in_range: 5,
          deferred_in_range: 3,
          start_failed_in_range: 2,
          limit_allowed_in_range: 0,
          limit_denied_in_range: 0,
          oldest_pending_age_ms: 0,
        },
        by_model: [],
        by_type: [],
      })
    );
    await page.route("**/api/observability/jobs?*", (route) =>
      fulfillJson(route, { jobs: [], total: 0, page: 1, limit: 25 })
    );
    await page.route("**/api/observability/calls?*", (route) =>
      fulfillJson(route, { calls: [], total: 0, page: 1, limit: 50 })
    );
    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.goto(scopedPath("observability"));
    await page.waitForLoadState("networkidle");

    const health = page.getByRole("region", { name: "Automation health" });
    await expect(
      health.getByText(failedRuns > 0 ? "Issues recorded" : "Healthy", {
        exact: true,
      })
    ).toBeVisible();
    await expect(
      health.getByText("Needs attention", { exact: true })
    ).toHaveCount(0);
    await expect(
      health.getByText("Action required", { exact: true })
    ).toHaveCount(0);
    await expect(
      health.getByText("Run history", { exact: true })
    ).toBeVisible();
    await expect(
      health.getByText(
        "0 running runs · 0 pending runs · 7626 tracked all time"
      )
    ).toBeVisible();
    await expect(
      page.getByText("Recent pressure", { exact: true })
    ).toHaveCount(0);
    if (failedRuns > 0) {
      await expect(health.getByText("12 runs remain failed")).toBeVisible();
      await health.screenshot({
        path: testInfo.outputPath("automation-health.png"),
      });
    } else {
      await expect(page.getByText("No failed or delayed runs")).toBeVisible();
      await expect(
        page.getByText("Start failures", { exact: true })
      ).toBeVisible();
      await expect(page.getByText("2 failed start attempts")).toBeVisible();
      await expect(
        page.getByText("3 delayed start attempts retried automatically.")
      ).toBeVisible();
    }
  });
}

test("assignments show last run health inline and triggers surface loads", async ({
  page,
}) => {
  let requeueCount = 0;

  await enableScopedE2EAuth(page);
  await mockBaseChrome(page);

  await page.route("**/api/repos**", (route) =>
    fulfillJson(route, [{ id: "repo-1", full_name: "acme/demo-app" }])
  );
  await page.route("**/api/agents", (route) =>
    fulfillJson(route, [
      {
        id: "agent-1",
        name: "Refactor Bot",
        slug: "refactor-bot",
        model: modelId,
      },
    ])
  );
  await page.route("**/api/github/installations", (route) =>
    fulfillJson(route, [])
  );
  await page.route("**/api/assignments", (route) =>
    fulfillJson(route, [
      {
        id: "assignment-1",
        repo_id: "repo-1",
        agent_id: "agent-1",
        type: "cron_refactor",
        cron_schedule: "0 * * * *",
        skill_id: null,
        enabled: true,
        created_at: "2026-03-20T10:00:00.000Z",
        last_job_run_id: "job-failed",
        last_run_status: "failed",
        last_run_started_at: "2026-03-21T19:00:10.000Z",
        last_run_error: "lint failed",
        running_count: 0,
        pending_count: 1,
        failed_24h: 1,
        suppressed_24h: 2,
        deferred_24h: 1,
        start_failed_24h: 0,
        last_pressure_reason: "REPO_PENDING_LIMIT",
        last_pressure_at: "2026-03-21T19:05:00.000Z",
        last_run_repairable: false,
        last_run_requeueable: true,
      },
    ])
  );
  await page.route("**/api/triggers", (route) => fulfillJson(route, []));
  await page.route(
    "**/api/observability/jobs/job-failed/requeue",
    async (route) => {
      requeueCount += 1;
      await fulfillJson(route, {
        ok: true,
        started: true,
        status: "pending",
        runtimeProvider: "workflow",
        runtimeRunId: "wf_retry",
        workflowRunId: "wf_retry",
        jobRunId: "job-retry",
      });
    }
  );

  await page.goto(scopedPath("assignments"));
  await page.waitForLoadState("networkidle");

  await expect(page.getByText("Last run: failed")).toBeVisible();
  await expect(page.getByRole("button", { name: "Requeue" })).toBeVisible();
  await page.getByRole("button", { name: "Requeue" }).click();
  expect(requeueCount).toBe(1);

  await page.goto(scopedPath("triggers"));
  await page.waitForLoadState("networkidle");
  await expect(page.getByTestId("triggers-empty-state")).toBeVisible();
});