Files
emdash-patch-imageupload/packages/admin/tests/components/LoginPage.test.tsx
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

144 lines
4.2 KiB
TypeScript

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import * as React from "react";
import { describe, it, expect, vi, beforeEach } from "vitest";
import { render } from "../utils/render.tsx";
// Mock router
vi.mock("@tanstack/react-router", async () => {
const actual = await vi.importActual("@tanstack/react-router");
return {
...actual,
Link: ({ children, to, ...props }: any) => (
<a href={to} {...props}>
{children}
</a>
),
useNavigate: () => vi.fn(),
};
});
// Mock API — keep a reference so tests can override fetchAuthMode
const mockFetchAuthMode = vi.fn().mockResolvedValue({
authMode: "passkey",
});
vi.mock("../../src/lib/api", async () => {
const actual = await vi.importActual("../../src/lib/api");
return {
...actual,
fetchAuthMode: (...args: unknown[]) => mockFetchAuthMode(...args),
apiFetch: vi
.fn()
.mockResolvedValue(new Response(JSON.stringify({ success: true }), { status: 200 })),
};
});
// Mock WebAuthn APIs so PasskeyLogin doesn't bail out
Object.defineProperty(window, "PublicKeyCredential", {
value: function PublicKeyCredential() {},
writable: true,
});
// Import after mocks
const { LoginPage } = await import("../../src/components/LoginPage");
function QueryWrapper({ children }: { children: React.ReactNode }) {
const qc = new QueryClient({
defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
});
return <QueryClientProvider client={qc}>{children}</QueryClientProvider>;
}
describe("LoginPage", () => {
beforeEach(() => {
// Clean URL params
window.history.replaceState({}, "", window.location.pathname);
});
it("shows passkey login button when authMode is passkey", async () => {
const screen = await render(
<QueryWrapper>
<LoginPage />
</QueryWrapper>,
);
await expect.element(screen.getByText("Sign in with Passkey")).toBeInTheDocument();
});
it("shows 'Sign in with email link' button", async () => {
const screen = await render(
<QueryWrapper>
<LoginPage />
</QueryWrapper>,
);
await expect.element(screen.getByText("Sign in with email link")).toBeInTheDocument();
});
it("clicking email link button switches to magic link form", async () => {
const screen = await render(
<QueryWrapper>
<LoginPage />
</QueryWrapper>,
);
const emailButton = screen.getByText("Sign in with email link");
await emailButton.click();
// Heading should change
await expect.element(screen.getByText("Sign in with email")).toBeInTheDocument();
});
it("magic link form has email input and submit button", async () => {
const screen = await render(
<QueryWrapper>
<LoginPage />
</QueryWrapper>,
);
// Switch to magic link
await screen.getByText("Sign in with email link").click();
// Check for email input (by placeholder)
await expect.element(screen.getByPlaceholder("you@example.com")).toBeInTheDocument();
// Check for submit button
await expect.element(screen.getByText("Send magic link")).toBeInTheDocument();
});
it("'Back to login' from magic link returns to passkey view", async () => {
const screen = await render(
<QueryWrapper>
<LoginPage />
</QueryWrapper>,
);
// Switch to magic link
await screen.getByText("Sign in with email link").click();
await expect.element(screen.getByText("Sign in with email")).toBeInTheDocument();
// Click back
await screen.getByText("Back to login").click();
// Should see passkey button again
await expect.element(screen.getByText("Sign in with Passkey")).toBeInTheDocument();
});
it("hides sign up link when signup is not enabled", async () => {
const screen = await render(
<QueryWrapper>
<LoginPage />
</QueryWrapper>,
);
// Wait for manifest to load (passkey button appears)
await expect.element(screen.getByText("Sign in with Passkey")).toBeInTheDocument();
// Sign up link should NOT be present
expect(screen.getByText("Sign up").query()).toBeNull();
});
it("shows sign up link when signup is enabled", async () => {
mockFetchAuthMode.mockResolvedValueOnce({
authMode: "passkey",
signupEnabled: true,
});
const screen = await render(
<QueryWrapper>
<LoginPage />
</QueryWrapper>,
);
await expect.element(screen.getByText("Sign up")).toBeInTheDocument();
});
});