92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
// 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");
|
|
});
|
|
});
|