diff --git a/frontend-modern/src/pages/Docker.tsx b/frontend-modern/src/pages/Docker.tsx index c66819f17..47f4919b6 100644 --- a/frontend-modern/src/pages/Docker.tsx +++ b/frontend-modern/src/pages/Docker.tsx @@ -1,4 +1,5 @@ import { Navigate, useLocation } from '@solidjs/router'; +import { Show } from 'solid-js'; import { DockerPageSurface } from '@/features/docker/DockerPageSurface'; import { buildDockerPath, DOCKER_PATH } from '@/routing/resourceLinks'; @@ -6,11 +7,14 @@ export function Docker() { const location = useLocation(); const pathname = () => location.pathname.replace(/\/+$/, ''); - if (pathname() === `${DOCKER_PATH}/workloads`) { - return ; - } - - return ; + return ( + } + > + + + ); } export default Docker; diff --git a/tests/integration/tests/01-core-e2e.spec.ts b/tests/integration/tests/01-core-e2e.spec.ts index 293cb6e5a..37a80bbc6 100644 --- a/tests/integration/tests/01-core-e2e.spec.ts +++ b/tests/integration/tests/01-core-e2e.spec.ts @@ -1,6 +1,7 @@ import { test, expect, type Locator } from '@playwright/test'; import { E2E_CREDENTIALS, + apiRequest, ensureAuthenticated, getMockMode, login, @@ -81,7 +82,7 @@ test.describe.serial('Core E2E flows', () => { test.skip(true, `Unable to read CPU default threshold (value="${cpuDefaultValueRaw}")`); } - const configResBeforeCreate = await page.request.get('/api/alerts/config'); + const configResBeforeCreate = await apiRequest(page, '/api/alerts/config'); expect(configResBeforeCreate.ok()).toBeTruthy(); const configBeforeCreate = (await configResBeforeCreate.json()) as { overrides?: Record; @@ -166,7 +167,7 @@ test.describe.serial('Core E2E flows', () => { }); await expect(revertOverride).toBeVisible(); - const configResAfterCreate = await page.request.get('/api/alerts/config'); + const configResAfterCreate = await apiRequest(page, '/api/alerts/config'); expect(configResAfterCreate.ok()).toBeTruthy(); const configAfterCreate = (await configResAfterCreate.json()) as { overrides?: Record }; const previousOverrideIds = new Set(Object.keys(configBeforeCreate.overrides ?? {})); @@ -181,7 +182,7 @@ test.describe.serial('Core E2E flows', () => { await page.getByRole('button', { name: 'Save Changes' }).click(); await expect(unsaved).not.toBeVisible(); - const configResAfterDelete = await page.request.get('/api/alerts/config'); + const configResAfterDelete = await apiRequest(page, '/api/alerts/config'); expect(configResAfterDelete.ok()).toBeTruthy(); const configAfterDelete = (await configResAfterDelete.json()) as { overrides?: Record }; expect( diff --git a/tests/integration/tests/11-first-session.spec.ts b/tests/integration/tests/11-first-session.spec.ts index 78f0df8a7..4a2ef3100 100644 --- a/tests/integration/tests/11-first-session.spec.ts +++ b/tests/integration/tests/11-first-session.spec.ts @@ -279,21 +279,29 @@ test.describe.serial("First-session experience", () => { route: "/settings/support/reporting", expectedURL: /\/settings\/support\/reporting/, feature: "advanced_reporting", + paywallIndicator: /Advanced Reporting/i, }, { route: "/settings/security-webhooks", expectedURL: /\/settings\/security-webhooks/, feature: "audit_logging", + paywallIndicator: /Audit (Logging|Webhooks)/i, }, { route: "/settings/system-relay", expectedURL: /\/settings\/system-relay/, feature: "relay", + paywallIndicator: /Remote Access \(Relay\)/i, }, ] as const; try { - for (const { route, expectedURL, feature } of gatedRoutes) { + for (const { + route, + expectedURL, + feature, + paywallIndicator: paywallPattern, + } of gatedRoutes) { const hasFeature = features.has(feature); if (!hasFeature) { @@ -346,9 +354,8 @@ test.describe.serial("First-session experience", () => { // Paywall indicator should be visible. const paywallIndicator = page - .locator( - "text=/Upgrade|Pro Feature|Requires Pro|Requires Relay|Start.*Trial|Advanced Reporting|Audit Logging|Audit Webhooks|Pulse Relay/i", - ) + .getByRole("main") + .getByText(paywallPattern) .first(); const isPaywallVisible = await paywallIndicator .isVisible({ timeout: 5_000 }) diff --git a/tests/integration/tests/38-vmware-ai-chat-mentions.spec.ts b/tests/integration/tests/38-vmware-ai-chat-mentions.spec.ts index 0aabe6350..7f848e3b1 100644 --- a/tests/integration/tests/38-vmware-ai-chat-mentions.spec.ts +++ b/tests/integration/tests/38-vmware-ai-chat-mentions.spec.ts @@ -78,7 +78,7 @@ test.describe('VMware AI chat mentions', () => { .filter({ hasText: /esxi-01\.lab\.local/ }) .first(); await expect(hostOption).toBeVisible({ timeout: 30_000 }); - await hostOption.click(); + await textarea.press('Enter'); await expect(textarea).toHaveValue('@esxi-01.lab.local '); // API-backed vSphere VMs use the same shared mention contract, carrying @@ -91,7 +91,7 @@ test.describe('VMware AI chat mentions', () => { .filter({ hasText: /warehouse-api-01/ }) .first(); await expect(vmOption).toBeVisible({ timeout: 30_000 }); - await vmOption.click(); + await textarea.press('Enter'); await expect(textarea).toHaveValue('@warehouse-api-01 '); expect(unexpectedVMwareRequests).toEqual([]); diff --git a/tests/integration/tests/42-vmware-ai-chat-read-recovery.spec.ts b/tests/integration/tests/42-vmware-ai-chat-read-recovery.spec.ts index 3c1e5efd8..e80d99f6c 100644 --- a/tests/integration/tests/42-vmware-ai-chat-read-recovery.spec.ts +++ b/tests/integration/tests/42-vmware-ai-chat-read-recovery.spec.ts @@ -65,15 +65,16 @@ test.describe('VMware AI chat read recovery', () => { await expect(textarea).toBeVisible(); // First websocket state frame can lag on a freshly booted backend. - await textarea.click(); - await textarea.pressSequentially('@warehouse'); + await textarea.focus(); + await textarea.fill('@warehouse'); const mentionListbox = page.getByRole('listbox', { name: 'Assistant resources' }); await expect(mentionListbox).toBeVisible({ timeout: 30_000 }); - await mentionListbox + const vmOption = mentionListbox .getByRole('option') .filter({ hasText: /warehouse-api-01/ }) - .first() - .click(); + .first(); + await expect(vmOption).toBeVisible({ timeout: 30_000 }); + await textarea.press('Enter'); await expect(textarea).toHaveValue('@warehouse-api-01 '); await textarea.fill('@warehouse-api-01 show me recent status'); diff --git a/tests/integration/tests/helpers.ts b/tests/integration/tests/helpers.ts index a8e5422cf..d96c3baed 100644 --- a/tests/integration/tests/helpers.ts +++ b/tests/integration/tests/helpers.ts @@ -1161,7 +1161,7 @@ async function waitForDefaultMockRuntimeReady(page: Page): Promise { await expect .poll( async () => { - const response = await page.request.get("/api/state").catch(() => null); + const response = await apiRequest(page, "/api/state").catch(() => null); if (!response?.ok()) { return false; } @@ -1272,7 +1272,11 @@ export async function setMockMode(page: Page, enabled: boolean) { } if (res.ok()) { - return (await res.json()) as { enabled: boolean }; + const result = (await res.json()) as { enabled: boolean }; + if (enabled) { + await waitForDefaultMockRuntimeReady(page); + } + return result; } lastError = new Error(`HTTP ${res.status()}: ${await res.text()}`);