Files
SnapOtter/tests/e2e/settings.spec.ts
T
SnapOtterandGitHub 63a03d26f2 feat: pipeline templates, analytics opt-out, 83 conversion presets, positioning + e2e modernization
Lands five integrated branches: pipeline templates (#355), analytics opt-out (#354), 83 conversion presets bringing the catalog to 240 tools (#356), self-hosted positioning (#353), and e2e modernization (#351).

Integration fixes: aligned stale web analytics tests with the opt-out/allow-list model, closed 3 CodeQL incomplete-sanitization alerts in the i18n generator, resolved settings/index/docs/format-matrix conflicts, and corrected tool counts to 240.
2026-06-28 18:57:53 +08:00

112 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { authFile } from "../../playwright.config";
import { expect, openSettings, test } from "./helpers";
test.describe("Settings Dialog", () => {
test("opens from the avatar menu", async ({ loggedInPage: page }) => {
// 2.0 removed the desktop sidebar; openSettings drives the avatar dropdown.
await openSettings(page);
// Settings dialog should appear with sections
await expect(page.getByText("General").first()).toBeVisible();
});
test("General section shows user info", async ({ loggedInPage: page }) => {
await openSettings(page);
// Should show username and version info
await expect(page.getByText(/admin/i).first()).toBeVisible();
await expect(page.getByText(/2\.0\.0|version/i).first()).toBeVisible();
});
test("General section has logout button", async ({ loggedInPage: page }) => {
await openSettings(page);
const logoutBtn = page.getByRole("button", { name: /logout|log out/i });
await expect(logoutBtn).toBeVisible();
});
test("Security section has change password form", async ({ loggedInPage: page }) => {
await openSettings(page);
// Navigate to Security section via the dialog nav button (the section
// heading reuses the same label, so scope to the button to avoid strict-mode
// ambiguity).
await page.getByRole("button", { name: "Security", exact: true }).click();
// Should show password change fields
await expect(page.getByText(/change password|current password/i).first()).toBeVisible();
});
test("People section shows user list", async ({ loggedInPage: page }) => {
await openSettings(page);
// Navigate to People section via the dialog nav button
await page.getByRole("button", { name: "People", exact: true }).click();
// Should show admin user
await expect(page.getByText("admin").first()).toBeVisible();
});
// TODO: This test is flaky due to dialog state isolation — the API keys
// endpoint is verified via the API test suite (api.spec.ts)
test.skip("API Keys section has generate button", async ({ browser }) => {
// Use a fresh context to avoid dialog state from previous tests
const context = await browser.newContext({
storageState: authFile,
});
const page = await context.newPage();
await page.goto("/");
await page.waitForLoadState("networkidle");
await openSettings(page);
await page.waitForTimeout(500);
const apiKeysBtn = page.getByRole("button", { name: /api keys/i });
await expect(apiKeysBtn).toBeVisible({ timeout: 5_000 });
await apiKeysBtn.click();
await page.waitForTimeout(500);
await expect(page.getByRole("button", { name: /generate api key/i })).toBeVisible({
timeout: 5_000,
});
await context.close();
});
test("About section shows app info", async ({ loggedInPage: page }) => {
await openSettings(page);
// Navigate to About section via the dialog nav button
await page.getByRole("button", { name: "About", exact: true }).click();
// Should show app description
await expect(page.getByText(/snapotter|privacy|self-hosted/i).first()).toBeVisible();
});
test("System Settings section has configuration", async ({ loggedInPage: page }) => {
await openSettings(page);
// Navigate to System Settings section via the dialog nav button
await page.getByRole("button", { name: "System Settings", exact: true }).click();
// Should show system configuration options
await expect(page.getByText(/app name|upload limit|theme/i).first()).toBeVisible();
});
test("settings dialog can be closed", async ({ loggedInPage: page }) => {
await openSettings(page);
await expect(page.getByText("General").first()).toBeVisible();
// Close by clicking X or outside
const closeBtn = page.getByRole("button", { name: /close|×/i }).first();
if (await closeBtn.isVisible()) {
await closeBtn.click();
} else {
await page.keyboard.press("Escape");
}
// Dialog should be gone
await page.waitForTimeout(300);
});
});