From 5f221941c75145b5b6e409aa6b869a0221292e9b Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 8 Jul 2026 17:23:04 +0100 Subject: [PATCH] Retire Patrol specs pinned to presentation the workbench simplified The finding-links spec asserted Open related links into the retired standalone routes from the pre-workbench findings list; those cross-link affordances were removed deliberately with platform-first navigation, and the monitor-first workbench feeds findings through a different pipeline its stubs never reach. The run-history breakdown spec pinned per-run type counts that the workbench simplified to plain totals; the underlying count-separation contract (truenas_checked distinct from agent hosts) lives in the investigation context model and is unit covered there. --- .../29-truenas-patrol-finding-links.spec.ts | 376 ------------------ ...4-truenas-patrol-history-breakdown.spec.ts | 268 ------------- 2 files changed, 644 deletions(-) delete mode 100644 tests/integration/tests/29-truenas-patrol-finding-links.spec.ts delete mode 100644 tests/integration/tests/34-truenas-patrol-history-breakdown.spec.ts diff --git a/tests/integration/tests/29-truenas-patrol-finding-links.spec.ts b/tests/integration/tests/29-truenas-patrol-finding-links.spec.ts deleted file mode 100644 index 4532c4b3e..000000000 --- a/tests/integration/tests/29-truenas-patrol-finding-links.spec.ts +++ /dev/null @@ -1,376 +0,0 @@ -import fs from "node:fs"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; -import { test as base, expect } from "@playwright/test"; - -import { createAuthenticatedStorageState } from "./helpers"; -import { PATROL_ROUTE } from "./routes"; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -type WorkerFixtures = { - authStorageStatePath: string; -}; - -const SCREENSHOT_PATH = "/tmp/truenas-patrol-finding-links.png"; - -const test = base.extend<{}, WorkerFixtures>({ - storageState: async ({ authStorageStatePath }, use) => { - await use(authStorageStatePath); - }, - authStorageStatePath: [ - async ({ browser }, use, workerInfo) => { - const storageStatePath = path.resolve( - __dirname, - "..", - "..", - "tmp", - "playwright-auth", - `truenas-patrol-finding-links-${workerInfo.project.name}.json`, - ); - fs.mkdirSync(path.dirname(storageStatePath), { recursive: true }); - await createAuthenticatedStorageState(browser, storageStatePath); - try { - await use(storageStatePath); - } finally { - fs.rmSync(storageStatePath, { force: true }); - } - }, - { scope: "worker" }, - ], -}); - -test.describe("TrueNAS patrol finding links", () => { - test.setTimeout(180_000); - - test("keeps TrueNAS Patrol findings on canonical surface handoff routes", async ({ - page, - }) => { - await page.route("**/api/resources**", async (route) => { - const requestUrl = new URL(route.request().url()); - if (requestUrl.pathname !== "/api/resources") { - await route.continue(); - return; - } - - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - data: [ - { - id: "truenas-main", - type: "agent", - name: "truenas-main", - displayName: "TrueNAS Main", - platformId: "truenas-main", - platformType: "truenas", - sourceType: "hybrid", - sources: ["agent", "truenas"], - status: "online", - lastSeen: "2026-03-30T10:00:00Z", - canonicalIdentity: { - displayName: "TrueNAS Main", - hostname: "truenas-main", - platformId: "truenas-main", - }, - platformData: { - sources: ["agent", "truenas"], - }, - }, - { - id: "app-container:truenas-main:nextcloud", - type: "app-container", - name: "nextcloud", - displayName: "Nextcloud", - parentId: "truenas-main", - parentName: "TrueNAS Main", - platformId: "truenas-main", - platformType: "truenas", - sourceType: "api", - sources: ["truenas"], - status: "running", - lastSeen: "2026-03-30T10:00:00Z", - platformData: { - sources: ["truenas"], - }, - }, - ], - meta: { - page: 1, - limit: 200, - total: 2, - totalPages: 1, - }, - }), - }); - }); - - await page.route("**/api/ai/patrol/status", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - runtime_state: "active", - running: false, - enabled: true, - last_patrol_at: "2026-03-30T09:00:00Z", - last_activity_at: "2026-03-30T10:05:00Z", - next_patrol_at: "2026-03-30T15:00:00Z", - last_duration_ms: 180000, - resources_checked: 42, - findings_count: 2, - error_count: 0, - healthy: false, - interval_ms: 21600000, - fixed_count: 0, - blocked_reason: "", - blocked_at: "", - license_required: false, - license_status: "active", - summary: { - critical: 1, - warning: 1, - watch: 0, - info: 0, - }, - }), - }); - }); - - await page.route("**/api/ai/patrol/runs*", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify([ - { - id: "run-truenas-links", - started_at: "2026-03-30T09:00:00Z", - completed_at: "2026-03-30T09:03:00Z", - duration_ms: 180000, - type: "full", - trigger_reason: "scheduled", - resources_checked: 42, - findings_summary: "2 findings", - finding_ids: ["finding-truenas-system", "finding-truenas-app"], - error_count: 0, - status: "warning", - triage_flags: 0, - tool_call_count: 0, - }, - ]), - }); - }); - - await page.route("**/api/ai/patrol/autonomy", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - autonomy_level: "monitor", - full_mode_unlocked: false, - investigation_budget: 15, - investigation_timeout_sec: 300, - }), - }); - }); - - await page.route("**/api/ai/models", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ models: [] }), - }); - }); - - await page.route("**/api/settings/ai", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - patrol_enabled: true, - patrol_interval_minutes: 360, - patrol_model: "", - model: "", - alert_triggered_analysis: true, - patrol_alert_triggers_enabled: true, - patrol_anomaly_triggers_enabled: true, - patrol_event_triggers_enabled: true, - patrol_auto_fix: false, - auto_fix_model: "", - }), - }); - }); - - await page.route("**/api/ai/unified/findings*", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - findings: [ - { - id: "finding-truenas-system", - severity: "critical", - category: "availability", - resource_id: "truenas-main", - resource_name: "TrueNAS Main", - resource_type: "agent", - title: "TrueNAS system offline", - description: - "Pulse Patrol detected that the TrueNAS appliance stopped reporting.", - detected_at: "2026-03-30T09:10:00Z", - last_seen_at: "2026-03-30T10:05:00Z", - auto_resolved: false, - times_raised: 1, - suppressed: false, - investigation_attempts: 0, - }, - { - id: "finding-truenas-app", - severity: "warning", - category: "reliability", - resource_id: "app-container:truenas-main:nextcloud", - resource_name: "Nextcloud", - resource_type: "app-container", - title: "Nextcloud failed readiness checks", - description: - "Pulse Patrol detected repeated readiness probe failures.", - detected_at: "2026-03-30T09:20:00Z", - last_seen_at: "2026-03-30T10:05:00Z", - auto_resolved: false, - times_raised: 1, - suppressed: false, - investigation_attempts: 0, - }, - ], - count: 2, - active_count: 2, - }), - }); - }); - - await page.route("**/api/ai/intelligence/correlations*", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ correlations: [], count: 0 }), - }); - }); - - await page.route("**/api/ai/intelligence", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - timestamp: "2026-03-30T10:05:00Z", - overall_health: { - score: 71, - grade: "C", - trend: "stable", - factors: [], - prediction: "TrueNAS resources need attention.", - }, - findings_count: { - critical: 1, - warning: 1, - watch: 0, - info: 0, - total: 2, - }, - predictions_count: 0, - recent_changes_count: 0, - recent_changes: [], - learning: { - resources_with_knowledge: 0, - total_notes: 0, - resources_with_baselines: 0, - patterns_detected: 0, - correlations_learned: 0, - incidents_tracked: 0, - }, - }), - }); - }); - - await page.route("**/api/ai/circuit/status", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - state: "closed", - can_patrol: true, - consecutive_failures: 0, - total_successes: 42, - total_failures: 0, - }), - }); - }); - - await page.route("**/api/ai/approvals", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ approvals: [] }), - }); - }); - - await page.route("**/api/ai/remediation/plans", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ plans: [] }), - }); - }); - - await page.goto(PATROL_ROUTE, { waitUntil: "domcontentloaded" }); - - await expect(page.getByRole("button", { name: "Findings" })).toBeVisible(); - - await page.getByText("TrueNAS system offline").click(); - const systemFinding = page.locator("#finding-finding-truenas-system"); - await expect( - systemFinding.getByRole("link", { - name: "Open related infrastructure for TrueNAS Main", - }), - ).toHaveAttribute("href", "/infrastructure?resource=truenas-main"); - await expect( - systemFinding.getByRole("link", { - name: "Open related workloads for TrueNAS Main", - }), - ).toHaveAttribute( - "href", - "/workloads?type=app-container&platform=truenas&agent=truenas-main", - ); - await expect( - systemFinding.getByRole("link", { - name: "Open related storage for TrueNAS Main", - }), - ).toHaveAttribute("href", "/storage?source=truenas&node=truenas-main"); - await expect( - systemFinding.getByRole("link", { - name: "Open related recovery for TrueNAS Main", - }), - ).toHaveAttribute("href", "/recovery?platform=truenas&node=truenas-main"); - - await page.getByText("Nextcloud failed readiness checks").click(); - const appFinding = page.locator("#finding-finding-truenas-app"); - await expect( - appFinding.getByRole("link", { - name: "Open related infrastructure for Nextcloud", - }), - ).toHaveAttribute( - "href", - "/infrastructure?resource=app-container%3Atruenas-main%3Anextcloud", - ); - await expect( - appFinding.getByRole("link", { - name: "Open related workloads for Nextcloud", - }), - ).toHaveAttribute( - "href", - "/workloads?type=app-container&platform=truenas&agent=truenas-main&resource=app-container%3Atruenas-main%3Anextcloud", - ); - - await page.screenshot({ path: SCREENSHOT_PATH, fullPage: true }); - }); -}); diff --git a/tests/integration/tests/34-truenas-patrol-history-breakdown.spec.ts b/tests/integration/tests/34-truenas-patrol-history-breakdown.spec.ts deleted file mode 100644 index 2c919663d..000000000 --- a/tests/integration/tests/34-truenas-patrol-history-breakdown.spec.ts +++ /dev/null @@ -1,268 +0,0 @@ -import fs from "node:fs"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; -import { test as base, expect } from "@playwright/test"; - -import { createAuthenticatedStorageState } from "./helpers"; -import { PATROL_ROUTE } from "./routes"; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -type WorkerFixtures = { - authStorageStatePath: string; -}; - -const SCREENSHOT_PATH = "/tmp/truenas-patrol-run-history.png"; - -const test = base.extend<{}, WorkerFixtures>({ - storageState: async ({ authStorageStatePath }, use) => { - await use(authStorageStatePath); - }, - authStorageStatePath: [ - async ({ browser }, use, workerInfo) => { - const storageStatePath = path.resolve( - __dirname, - "..", - "..", - "tmp", - "playwright-auth", - `truenas-patrol-history-breakdown-${workerInfo.project.name}.json`, - ); - fs.mkdirSync(path.dirname(storageStatePath), { recursive: true }); - await createAuthenticatedStorageState(browser, storageStatePath); - try { - await use(storageStatePath); - } finally { - fs.rmSync(storageStatePath, { force: true }); - } - }, - { scope: "worker" }, - ], -}); - -test.describe("TrueNAS patrol run history", () => { - test.setTimeout(180_000); - - test("keeps TrueNAS patrol counts separate from agent hosts in run history", async ({ - page, - }) => { - await page.route("**/api/resources**", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - data: [], - meta: { page: 1, limit: 200, total: 0, totalPages: 0 }, - }), - }); - }); - - await page.route("**/api/ai/patrol/status", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - runtime_state: "active", - running: false, - enabled: true, - last_patrol_at: "2026-03-30T09:00:00Z", - last_activity_at: "2026-03-30T09:03:00Z", - next_patrol_at: "2026-03-30T15:00:00Z", - last_duration_ms: 180000, - resources_checked: 2, - findings_count: 0, - error_count: 0, - healthy: true, - interval_ms: 21600000, - fixed_count: 0, - blocked_reason: "", - blocked_at: "", - license_required: false, - license_status: "active", - summary: { - critical: 0, - warning: 0, - watch: 0, - info: 0, - }, - }), - }); - }); - - await page.route("**/api/ai/patrol/runs*", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify([ - { - id: "run-truenas-breakdown", - started_at: "2026-03-30T09:00:00Z", - completed_at: "2026-03-30T09:03:00Z", - duration_ms: 180000, - type: "full", - trigger_reason: "scheduled", - resources_checked: 2, - nodes_checked: 0, - guests_checked: 0, - docker_checked: 1, - storage_checked: 0, - hosts_checked: 0, - truenas_checked: 1, - pbs_checked: 0, - pmg_checked: 0, - kubernetes_checked: 0, - new_findings: 0, - existing_findings: 0, - rejected_findings: 0, - resolved_findings: 0, - auto_fix_count: 0, - findings_summary: "TrueNAS patrol complete", - finding_ids: [], - error_count: 0, - status: "healthy", - triage_flags: 0, - tool_call_count: 0, - }, - ]), - }); - }); - - await page.route("**/api/ai/patrol/autonomy", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - autonomy_level: "monitor", - full_mode_unlocked: false, - investigation_budget: 15, - investigation_timeout_sec: 300, - }), - }); - }); - - await page.route("**/api/ai/models", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ models: [] }), - }); - }); - - await page.route("**/api/settings/ai", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - patrol_enabled: true, - patrol_interval_minutes: 360, - patrol_model: "", - model: "", - alert_triggered_analysis: true, - patrol_alert_triggers_enabled: true, - patrol_anomaly_triggers_enabled: true, - patrol_event_triggers_enabled: true, - patrol_auto_fix: false, - auto_fix_model: "", - }), - }); - }); - - await page.route("**/api/ai/unified/findings*", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - findings: [], - count: 0, - active_count: 0, - }), - }); - }); - - await page.route("**/api/ai/intelligence/correlations*", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ correlations: [], count: 0 }), - }); - }); - - await page.route("**/api/ai/intelligence", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - timestamp: "2026-03-30T09:03:00Z", - overall_health: { - score: 100, - grade: "A", - trend: "stable", - factors: [], - prediction: - "Infrastructure is healthy with no significant issues detected.", - }, - findings_count: { - critical: 0, - warning: 0, - watch: 0, - info: 0, - total: 0, - }, - predictions_count: 0, - recent_changes_count: 0, - recent_changes: [], - learning: { - resources_with_knowledge: 0, - total_notes: 0, - resources_with_baselines: 0, - patterns_detected: 0, - correlations_learned: 0, - incidents_tracked: 0, - }, - }), - }); - }); - - await page.route("**/api/ai/circuit/status", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ - state: "closed", - can_patrol: true, - consecutive_failures: 0, - total_successes: 1, - total_failures: 0, - }), - }); - }); - - await page.route("**/api/ai/approvals", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ approvals: [] }), - }); - }); - - await page.route("**/api/ai/remediation/plans", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify({ plans: [] }), - }); - }); - - await page.goto(PATROL_ROUTE, { waitUntil: "domcontentloaded" }); - - await expect(page.getByRole("button", { name: "Findings" })).toBeVisible(); - await page.getByRole("button", { name: "Runs" }).click(); - await page.getByRole("button", { name: /Checked 2 resources/i }).click(); - - await expect(page.getByText("1 container")).toBeVisible(); - await expect(page.getByText("1 TrueNAS system")).toBeVisible(); - await expect(page.getByText(/1 agent/)).toHaveCount(0); - - await page.screenshot({ path: SCREENSHOT_PATH, fullPage: true }); - }); -});