/** * Allowed Domains E2E Tests * * Tests self-signup domain management in admin settings. * Available at /settings/allowed-domains. * * Uses API to add/remove domains as needed, verifies UI reflects changes. */ import { test, expect } from "../fixtures"; // API helper function apiHeaders(token: string, baseUrl: string) { return { "Content-Type": "application/json", Authorization: `Bearer ${token}`, "X-EmDash-Request": "1", Origin: baseUrl, }; } test.describe("Allowed Domains Settings", () => { let headers: Record; let baseUrl: string; test.beforeEach(async ({ admin, serverInfo }) => { await admin.devBypassAuth(); baseUrl = serverInfo.baseUrl; headers = apiHeaders(serverInfo.token, baseUrl); // Clean up any leftover test domains from previous runs const res = await fetch(`${baseUrl}/_emdash/api/admin/allowed-domains`, { headers }); if (res.ok) { const data: any = await res.json(); const domains = data.data?.domains ?? []; for (const d of domains) { if (d.domain.includes("e2e-test")) { await fetch( `${baseUrl}/_emdash/api/admin/allowed-domains/${encodeURIComponent(d.domain)}`, { method: "DELETE", headers }, ).catch(() => {}); } } } }); test("renders the allowed domains settings page", async ({ admin, page }) => { await admin.goto("/settings/allowed-domains"); await admin.waitForShell(); await admin.waitForLoading(); // Should show the page title await expect(page.locator("h1").first()).toContainText("Self-Signup Domains"); // Should show the "Allowed Domains" section heading await expect(page.locator("h2", { hasText: "Allowed Domains" })).toBeVisible({ timeout: 10000, }); // Should have an "Add Domain" button await expect(page.getByRole("button", { name: "Add Domain" })).toBeVisible(); }); test("shows empty state when no domains configured", async ({ admin, page }) => { await admin.goto("/settings/allowed-domains"); await admin.waitForShell(); await admin.waitForLoading(); // Should show empty state message (unless domains were pre-configured) const emptyState = page.locator("text=No domains configured"); // Check if there's already domain data or empty state const hasEmptyState = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmptyState) { await expect(emptyState).toBeVisible(); } // Either way, the Add Domain button should be there await expect(page.getByRole("button", { name: "Add Domain" })).toBeVisible(); }); test("adds a new domain via the UI", async ({ admin, page }) => { await admin.goto("/settings/allowed-domains"); await admin.waitForShell(); await admin.waitForLoading(); const testDomain = `e2e-test-${Date.now()}.example.com`; // Click "Add Domain" to open the inline form await page.getByRole("button", { name: "Add Domain" }).click(); // The add form should appear with a domain input const domainInput = page.getByLabel("Domain"); await expect(domainInput).toBeVisible({ timeout: 5000 }); // Fill in the domain await domainInput.fill(testDomain); // Click "Add Domain" submit button (different from the trigger button) const submitButton = page.getByRole("button", { name: "Add Domain" }); await submitButton.click(); // Wait for the domain to appear in the list await expect(page.locator(`.font-medium`, { hasText: testDomain })).toBeVisible({ timeout: 10000, }); // Should show a success status message const successMsg = page.locator("text=Domain added successfully"); await expect(successMsg).toBeVisible({ timeout: 5000 }); // Clean up via API await fetch( `${baseUrl}/_emdash/api/admin/allowed-domains/${encodeURIComponent(testDomain)}`, { method: "DELETE", headers }, ).catch(() => {}); }); test("removes a domain via the UI", async ({ admin, page }) => { const testDomain = `e2e-test-delete-${Date.now()}.example.com`; // Create domain via API first await fetch(`${baseUrl}/_emdash/api/admin/allowed-domains`, { method: "POST", headers, body: JSON.stringify({ domain: testDomain, defaultRole: 30 }), }); // Navigate to the page await admin.goto("/settings/allowed-domains"); await admin.waitForShell(); await admin.waitForLoading(); // Verify the domain is visible await expect(page.locator(`.font-medium`, { hasText: testDomain })).toBeVisible({ timeout: 10000, }); // Click the delete button for this domain const deleteButton = page.getByRole("button", { name: `Delete ${testDomain}` }); await deleteButton.click(); // The confirmation dialog should appear const dialog = page.locator('[role="dialog"]'); await expect(dialog).toBeVisible({ timeout: 5000 }); await expect(dialog.getByRole("heading", { name: "Remove Domain" })).toBeVisible(); // Confirm deletion await dialog.getByRole("button", { name: "Remove Domain" }).click(); // Domain should disappear from the list await expect(page.locator(`.font-medium`, { hasText: testDomain })).not.toBeVisible({ timeout: 10000, }); // Should show a success status message const successMsg = page.locator("text=Domain removed"); await expect(successMsg).toBeVisible({ timeout: 5000 }); }); test("cancel delete keeps the domain", async ({ admin, page }) => { const testDomain = `e2e-test-keep-${Date.now()}.example.com`; // Create domain via API await fetch(`${baseUrl}/_emdash/api/admin/allowed-domains`, { method: "POST", headers, body: JSON.stringify({ domain: testDomain, defaultRole: 30 }), }); await admin.goto("/settings/allowed-domains"); await admin.waitForShell(); await admin.waitForLoading(); // Verify domain is visible await expect(page.locator(`.font-medium`, { hasText: testDomain })).toBeVisible({ timeout: 10000, }); // Click delete await page.getByRole("button", { name: `Delete ${testDomain}` }).click(); // Dialog appears const dialog = page.locator('[role="dialog"]'); await expect(dialog).toBeVisible({ timeout: 5000 }); // Cancel await dialog.getByRole("button", { name: "Cancel" }).click(); // Dialog should close await expect(dialog).not.toBeVisible({ timeout: 5000 }); // Domain should still be there await expect(page.locator(`.font-medium`, { hasText: testDomain })).toBeVisible(); // Clean up await fetch( `${baseUrl}/_emdash/api/admin/allowed-domains/${encodeURIComponent(testDomain)}`, { method: "DELETE", headers }, ).catch(() => {}); }); test("toggling enabled/disabled updates the domain", async ({ admin, page }) => { const testDomain = `e2e-test-toggle-${Date.now()}.example.com`; // Create domain via API await fetch(`${baseUrl}/_emdash/api/admin/allowed-domains`, { method: "POST", headers, body: JSON.stringify({ domain: testDomain, defaultRole: 30 }), }); await admin.goto("/settings/allowed-domains"); await admin.waitForShell(); await admin.waitForLoading(); // Find the domain row const domainRow = page.locator("div.flex.items-center.justify-between").filter({ hasText: testDomain, }); await expect(domainRow).toBeVisible({ timeout: 10000 }); // Find the switch toggle in the row and click it const toggle = domainRow.locator("button[role='switch']"); await toggle.click(); // Wait for the update to complete -- success message should appear const statusMsg = page.locator("text=Domain updated"); await expect(statusMsg).toBeVisible({ timeout: 5000 }); // Clean up await fetch( `${baseUrl}/_emdash/api/admin/allowed-domains/${encodeURIComponent(testDomain)}`, { method: "DELETE", headers }, ).catch(() => {}); }); });