Files
emdash-patch-imageupload/e2e/tests/allowed-domains.spec.ts
kunthawat 2d1be52177 Emdash source with visual editor image upload fix
Fixes:
1. media.ts: wrap placeholder generation in try-catch
2. toolbar.ts: check r.ok, display error message in popover
2026-05-03 10:44:54 +07:00

237 lines
7.5 KiB
TypeScript

/**
* 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<string, string>;
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(() => {});
});
});