82 lines
3.2 KiB
JavaScript
82 lines
3.2 KiB
JavaScript
|
|
import { test, expect } from "@playwright/test";
|
||
|
|
|
||
|
|
async function loginViaUi(page, username, password) {
|
||
|
|
await page.goto("/login");
|
||
|
|
await page.locator("#username").fill(username);
|
||
|
|
await page.locator("#password").fill(password);
|
||
|
|
await Promise.all([
|
||
|
|
page.waitForURL((url) => !url.pathname.endsWith("/login"), {
|
||
|
|
timeout: 15_000,
|
||
|
|
}),
|
||
|
|
page.locator('form button[type="submit"]').click(),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
test("Schedule: Edit toggle hides editing affordances by default and reveals them when on", async ({
|
||
|
|
page,
|
||
|
|
}) => {
|
||
|
|
await page.addInitScript(() => {
|
||
|
|
try {
|
||
|
|
window.localStorage.setItem("tx-lang", "en");
|
||
|
|
} catch {
|
||
|
|
/* localStorage may not be ready before navigation */
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
await loginViaUi(page, "admin", "admin123");
|
||
|
|
// Make sure we always start the test in view mode regardless of any
|
||
|
|
// previously-persisted toggle state from another run. We clear AFTER
|
||
|
|
// login so the cleanup isn't undone by the initScript on every nav.
|
||
|
|
await page.goto("/executive-meetings");
|
||
|
|
// The toggle's storage key is namespaced per-user
|
||
|
|
// (`em-schedule-edit-mode-v1:<userId>`), so we wipe every entry that
|
||
|
|
// starts with the base key to make sure we begin in view mode no
|
||
|
|
// matter who admin's userId resolves to in this run.
|
||
|
|
await page.evaluate(() => {
|
||
|
|
try {
|
||
|
|
const keys = Object.keys(window.localStorage);
|
||
|
|
for (const k of keys) {
|
||
|
|
if (k.startsWith("em-schedule-edit-mode-v1")) {
|
||
|
|
window.localStorage.removeItem(k);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
/* ignore */
|
||
|
|
}
|
||
|
|
});
|
||
|
|
await page.reload();
|
||
|
|
|
||
|
|
// Toggle is rendered (admin has edit permission), and starts in
|
||
|
|
// pressed=false / view mode.
|
||
|
|
const toggle = page.getByTestId("em-edit-mode-toggle");
|
||
|
|
await expect(toggle).toBeVisible();
|
||
|
|
await expect(toggle).toHaveAttribute("aria-pressed", "false");
|
||
|
|
|
||
|
|
// In view mode the row-level "Add meeting" button must be hidden.
|
||
|
|
await expect(page.getByTestId("em-add-row-button")).toHaveCount(0);
|
||
|
|
// And no row-level overlays (delete, color picker, merge trigger,
|
||
|
|
// grip handle) should exist anywhere in the table.
|
||
|
|
await expect(page.locator('[data-testid^="em-delete-row-"]')).toHaveCount(0);
|
||
|
|
await expect(page.getByTestId("em-row-color-trigger")).toHaveCount(0);
|
||
|
|
await expect(page.locator('[data-testid^="em-merge-trigger-"]')).toHaveCount(0);
|
||
|
|
await expect(page.locator('[data-testid^="em-row-grip-"]')).toHaveCount(0);
|
||
|
|
|
||
|
|
// Flip toggle on. aria-pressed becomes true and the affordances appear.
|
||
|
|
await toggle.click();
|
||
|
|
await expect(toggle).toHaveAttribute("aria-pressed", "true");
|
||
|
|
|
||
|
|
// The "+ Add meeting" row button is back.
|
||
|
|
await expect(page.getByTestId("em-add-row-button")).toBeVisible();
|
||
|
|
|
||
|
|
// Persist + survive a reload: the toggle should still be on.
|
||
|
|
await page.reload();
|
||
|
|
const toggleAfterReload = page.getByTestId("em-edit-mode-toggle");
|
||
|
|
await expect(toggleAfterReload).toHaveAttribute("aria-pressed", "true");
|
||
|
|
await expect(page.getByTestId("em-add-row-button")).toBeVisible();
|
||
|
|
|
||
|
|
// Toggle back off — affordances disappear again.
|
||
|
|
await toggleAfterReload.click();
|
||
|
|
await expect(toggleAfterReload).toHaveAttribute("aria-pressed", "false");
|
||
|
|
await expect(page.getByTestId("em-add-row-button")).toHaveCount(0);
|
||
|
|
});
|