Add Playwright E2E tests replacing Cypress with MSW integration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
91
tests/e2e/specs/login.spec.ts
Normal file
91
tests/e2e/specs/login.spec.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/22
|
||||
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test.describe("Login Flow", () => {
|
||||
test("renders the login form", async ({ page }) => {
|
||||
await page.goto("/login");
|
||||
await expect(page.getByRole("heading", { name: "LOGIN", exact: true }).first()).toBeVisible();
|
||||
await expect(page.locator("#account")).toBeVisible();
|
||||
await expect(page.locator("#password")).toBeVisible();
|
||||
await expect(page.locator("#login_btn_main_btn")).toBeDisabled();
|
||||
});
|
||||
|
||||
test("login button is disabled when fields are empty", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/login");
|
||||
await expect(page.locator("#login_btn_main_btn")).toBeDisabled();
|
||||
|
||||
// Only username filled - still disabled
|
||||
await page.locator("#account").fill("testuser");
|
||||
await expect(page.locator("#login_btn_main_btn")).toBeDisabled();
|
||||
});
|
||||
|
||||
test("login button enables when both fields are filled", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/login");
|
||||
await page.locator("#account").fill("testadmin");
|
||||
await page.locator("#password").fill("password123");
|
||||
await expect(page.locator("#login_btn_main_btn")).toBeEnabled();
|
||||
});
|
||||
|
||||
test("successful login redirects to /files", async ({ page }) => {
|
||||
await page.goto("/login");
|
||||
await page.locator("#account").fill("testadmin");
|
||||
await page.locator("#password").fill("password123");
|
||||
await page.locator("#login_btn_main_btn").click();
|
||||
|
||||
await expect(page).toHaveURL(/\/files/);
|
||||
});
|
||||
|
||||
test("failed login shows error message", async ({ page }) => {
|
||||
// Visit login first to load app + MSW
|
||||
await page.goto("/login");
|
||||
await expect(page.locator("#login_btn_main_btn")).toBeVisible();
|
||||
// Override the token endpoint to return 401 via MSW
|
||||
await page.evaluate(() => {
|
||||
const { http, HttpResponse } = window.__msw__;
|
||||
window.__mswWorker__.use(
|
||||
http.post("/api/oauth/token", () =>
|
||||
HttpResponse.json(
|
||||
{ detail: "Incorrect username or password" },
|
||||
{ status: 401 },
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
await page.locator("#account").fill("wronguser");
|
||||
await page.locator("#password").fill("wrongpass");
|
||||
await page.locator("#login_btn_main_btn").click();
|
||||
|
||||
await expect(
|
||||
page.getByText("Incorrect account or password"),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("toggles password visibility", async ({ page }) => {
|
||||
await page.goto("/login");
|
||||
await page.locator("#password").fill("secret123");
|
||||
await expect(
|
||||
page.locator("#password"),
|
||||
).toHaveAttribute("type", "password");
|
||||
|
||||
// Click the eye icon to show password
|
||||
await page.locator('label[for="passwordt"] span.cursor-pointer').click();
|
||||
await expect(
|
||||
page.locator("#password"),
|
||||
).toHaveAttribute("type", "text");
|
||||
|
||||
// Click again to hide
|
||||
await page.locator('label[for="passwordt"] span.cursor-pointer').click();
|
||||
await expect(
|
||||
page.locator("#password"),
|
||||
).toHaveAttribute("type", "password");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user