Accessibility fixes (aria-labels, color contrast, html lang, inline link underlines), atomic dev login endpoints, and E2E test hardening.
69 lines
2.3 KiB
JavaScript
69 lines
2.3 KiB
JavaScript
import { test, expect } from "./helpers/fixtures.js";
|
|
|
|
test.describe("Admin members page", () => {
|
|
test("members list loads for admin", async ({ adminPage }) => {
|
|
await adminPage.goto("/admin/members");
|
|
|
|
await expect(adminPage.locator("h1")).toHaveText("Members");
|
|
await expect(
|
|
adminPage.getByText("Manage members, contributions, and access"),
|
|
).toBeVisible();
|
|
});
|
|
|
|
test("search bar works", async ({ adminPage }) => {
|
|
await adminPage.goto("/admin/members");
|
|
|
|
const searchInput = adminPage.getByPlaceholder("Search members...");
|
|
await expect(searchInput).toBeVisible({ timeout: 10000 });
|
|
|
|
// Wait for the initial member list to load before searching
|
|
await expect(
|
|
adminPage
|
|
.locator("table")
|
|
.or(adminPage.getByText("No members found matching your criteria")),
|
|
).toBeVisible({ timeout: 15000 });
|
|
|
|
await searchInput.fill("nonexistent-query-xyz");
|
|
|
|
// Page should not crash -- either shows filtered results or the empty state
|
|
await expect(
|
|
adminPage
|
|
.locator("table")
|
|
.or(adminPage.getByText("No members found matching your criteria")),
|
|
).toBeVisible({ timeout: 10000 });
|
|
});
|
|
|
|
test("non-admin redirect", async ({ browser }) => {
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
|
|
await page.goto("/admin/members");
|
|
|
|
// Admin middleware redirects non-admin users to / or /members
|
|
await page.waitForURL((url) => !url.pathname.startsWith("/admin"));
|
|
expect(page.url()).not.toContain("/admin/members");
|
|
|
|
await context.close();
|
|
});
|
|
|
|
test("add member button opens modal", async ({ adminPage }) => {
|
|
await adminPage.goto("/admin/members");
|
|
await adminPage.waitForLoadState("networkidle"); // ensure Vue hydration is complete
|
|
|
|
// Wait for page to fully load and hydrate
|
|
await expect(adminPage.locator("h1")).toHaveText("Members");
|
|
await adminPage.waitForLoadState("networkidle");
|
|
|
|
const addBtn = adminPage.getByRole("button", { name: "Add Member" });
|
|
await expect(addBtn).toBeVisible({ timeout: 10000 });
|
|
await addBtn.click();
|
|
|
|
// Modal should appear with the form heading and fields
|
|
await expect(adminPage.getByPlaceholder("Full name")).toBeVisible({
|
|
timeout: 10000,
|
|
});
|
|
await expect(
|
|
adminPage.getByPlaceholder("email@example.com"),
|
|
).toBeVisible();
|
|
});
|
|
});
|