Skip to content
This repository was archived by the owner on Mar 21, 2026. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions frontend/e2e/specs/container-logs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,5 +273,38 @@ test.describe("Container Logs", () => {

// Verify inputs reset (Search is empty)
await expect(page.getByPlaceholder("Search logs...")).toBeEmpty();

});

test("displays error card when observability service is unreachable", async ({ page }) => {
const projectsPage = new ProjectsPage(page);
await projectsPage.open();
await projectsPage.expectLoaded();

const projectCell = page.getByRole("cell", { name: projectName, exact: true });
await projectCell.click();

const detailPage = new ProjectDetailPage(page);
await detailPage.expectLoaded();
await detailPage.expectRunningContainersSection();
await detailPage.expectContainerExists(containerName);

// Intercept logs API and mock 500 error
await page.route("**/api/v1/systems/logs/project-containers", route => {
route.fulfill({ status: 500, contentType: "application/json", body: JSON.stringify({}) });
});

await detailPage.clickViewLogs(containerName);
await detailPage.expectLogsSheetOpen(containerName);

// Wait for fetch to complete
await page.waitForTimeout(2000);

// Assert error card is visible
await expect(page.getByText(/network issue/i)).toBeVisible();
Comment on lines +300 to +304
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The page.waitForTimeout(2000) on line 301 is a fixed-duration sleep used to wait for the mocked 500 response to propagate and the error UI to render. This is a flaky testing pattern β€” if the network or UI is slower than 2 seconds, the subsequent assertions will fail, and if it's much faster, the wait is wasteful.

A more deterministic approach is to use page.waitForResponse to wait for the intercepted request to be fulfilled before asserting on the UI. For example, you could capture the response promise before clicking "View Logs" and await it before proceeding to assertions. Alternatively, since the error UI is ultimately what you're checking, await expect(page.getByText(/network issue/i)).toBeVisible({ timeout: 10_000 }) without the fixed sleep is more reliable. The existing test on line 137 uses the same pattern and has the same concern.

Suggested change
// Wait for fetch to complete
await page.waitForTimeout(2000);
// Assert error card is visible
await expect(page.getByText(/network issue/i)).toBeVisible();
// Assert error card is visible (Playwright will auto-wait for this state)
await expect(page.getByText(/network issue/i)).toBeVisible({ timeout: 10_000 });

Copilot uses AI. Check for mistakes.
await expect(page.getByRole("button", { name: /try again/i })).toBeVisible();

// Clean up route mock
await page.unroute("**/api/v1/systems/logs/project-containers");
});
});
Loading