import { expect, test, type Page } from "@playwright/test"; const FIXED_BROWSER_NOW = "2026-04-01T12:00:00.000Z"; async function freezeBrowserTime(page: Page) { await page.addInitScript((fixedIso) => { const fixedTime = new Date(fixedIso).valueOf(); const RealDate = Date; class MockDate extends RealDate { constructor(...args: ConstructorParameters) { if ((args as unknown[]).length === 0) { super(fixedTime); return; } super(...args); } static now() { return fixedTime; } } MockDate.UTC = RealDate.UTC; MockDate.parse = RealDate.parse; MockDate.prototype = RealDate.prototype; // @ts-expect-error override Date in the browser for deterministic client-side filtering window.Date = MockDate; }, FIXED_BROWSER_NOW); } async function signIn(page: Page, email: string, password: string) { await page.goto("/auth/signin"); await page.fill('input[type="email"]', email); await page.fill('input[type="password"]', password); await page.click('button[type="submit"]'); await expect(page).toHaveURL(/\/(dashboard|resources)/); } test.describe("Allocations", () => { test.beforeEach(async ({ page }) => { await freezeBrowserTime(page); await signIn(page, "admin@capakraken.dev", "admin123"); await page.goto("/allocations"); }); test("seeded assignments stay visibly rendered on first load", async ({ page }) => { await page.waitForLoadState("networkidle"); await expect( page.locator("h1").filter({ hasText: /Allocations|Planning/i }), ).toBeVisible({ timeout: 10000 }); await expect(page.getByTestId("allocations-table")).toBeVisible({ timeout: 10000 }); await expect(page.getByTestId("allocations-empty-state")).toHaveCount(0); await expect(page.getByTestId("allocation-group-header").first()).toBeVisible({ timeout: 10000 }); await expect(page.getByTestId("allocation-row").first()).toBeVisible({ timeout: 10000 }); expect(await page.getByTestId("allocation-row").count()).toBeGreaterThan(0); }); test("explicitly restrictive filters show a visible empty state and can be reset", async ({ page }) => { await page.waitForLoadState("networkidle"); const projectFilter = page.getByPlaceholder("Filter by project…"); await projectFilter.click(); await projectFilter.fill("PAG25G"); await page.getByRole("button", { name: /PAG25G/i }).click(); await expect(page.getByTestId("allocations-empty-state")).toBeVisible({ timeout: 10000 }); await expect(page.getByText(/hidden by the active project filters/i)).toBeVisible(); const resetButton = page.getByRole("button", { name: "Show all assignments" }); await expect(resetButton).toBeVisible(); await resetButton.click(); await expect(projectFilter).toHaveValue(""); await expect(page.getByTestId("allocations-empty-state")).toHaveCount(0); await expect(page.getByTestId("allocation-row").first()).toBeVisible({ timeout: 10000 }); }); test("new planning entry modal opens", async ({ page }) => { await page.waitForLoadState("networkidle"); const newBtn = page.locator("button", { hasText: /New Planning Entry/i }); await expect(newBtn).toBeVisible({ timeout: 10000 }); await newBtn.click(); await expect(page.getByTestId("allocation-modal")).toBeVisible({ timeout: 5000 }); await expect(page.getByRole("heading", { name: /New (Assignment|Open Demand)/i })).toBeVisible(); await page.keyboard.press("Escape"); }); test("filter by status works", async ({ page }) => { await page.waitForLoadState("networkidle"); // Look for status filter chips or dropdown const statusFilter = page.locator("button", { hasText: /Proposed|Confirmed|Active|Status/i }).first(); if ((await statusFilter.count()) > 0) { await statusFilter.click(); await page.waitForTimeout(300); // After clicking a status filter, the page should still show the table await expect( page.locator("table").or(page.locator("text=No allocations")), ).toBeVisible(); } }); test("column toggle panel works", async ({ page }) => { await page.waitForLoadState("networkidle"); const colToggle = page.locator("button", { hasText: /Columns/i }); if ((await colToggle.count()) > 0) { await colToggle.click(); await page.waitForTimeout(300); // A panel or dropdown with column checkboxes should appear await expect( page.locator("input[type='checkbox']").first(), ).toBeVisible({ timeout: 3000 }); await page.keyboard.press("Escape"); } }); test("viewer sees a visible access error instead of an empty allocations page", async ({ browser }) => { const page = await browser.newPage(); await freezeBrowserTime(page); await signIn(page, "viewer@capakraken.dev", "viewer123"); await page.goto("/allocations"); await page.waitForLoadState("networkidle"); const accessError = page.getByTestId("allocations-access-error"); await expect(accessError).toBeVisible({ timeout: 10000 }); await expect(accessError).toContainText(/do not have permission to view allocations/i); await expect(page.getByTestId("allocation-row")).toHaveCount(0); await expect(page.getByTestId("allocations-empty-state")).toHaveCount(0); await page.close(); }); });