- AUTH-014: Fix theme storage key (jarvis-theme -> mosaic-theme) - AUTH-016: Create AuthDivider component with customizable text - AUTH-019: Create SessionExpiryWarning floating banner (PDA-friendly, blue) - Fix lint errors in LoginForm, OAuthButton from parallel agents - Sync pnpm-lock.yaml for recharts dependency Refs #415 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
90 lines
3.2 KiB
TypeScript
90 lines
3.2 KiB
TypeScript
import { describe, it, expect, vi } from "vitest";
|
|
import { render, screen } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { OAuthButton } from "./OAuthButton";
|
|
|
|
describe("OAuthButton", (): void => {
|
|
const defaultProps = {
|
|
providerName: "Authentik",
|
|
providerId: "authentik",
|
|
onClick: vi.fn(),
|
|
};
|
|
|
|
it("should render with provider name", (): void => {
|
|
render(<OAuthButton {...defaultProps} />);
|
|
expect(screen.getByText("Continue with Authentik")).toBeInTheDocument();
|
|
});
|
|
|
|
it("should have full width styling", (): void => {
|
|
render(<OAuthButton {...defaultProps} />);
|
|
const button = screen.getByRole("button");
|
|
expect(button.className).toContain("w-full");
|
|
});
|
|
|
|
it("should call onClick when clicked", async (): Promise<void> => {
|
|
const user = userEvent.setup();
|
|
const onClick = vi.fn();
|
|
render(<OAuthButton {...defaultProps} onClick={onClick} />);
|
|
|
|
const button = screen.getByRole("button");
|
|
await user.click(button);
|
|
|
|
expect(onClick).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("should show loading state with spinner and Connecting text", (): void => {
|
|
render(<OAuthButton {...defaultProps} isLoading={true} />);
|
|
expect(screen.getByText("Connecting...")).toBeInTheDocument();
|
|
expect(screen.queryByText("Continue with Authentik")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("should be disabled when isLoading is true", (): void => {
|
|
render(<OAuthButton {...defaultProps} isLoading={true} />);
|
|
const button = screen.getByRole("button");
|
|
expect(button).toBeDisabled();
|
|
});
|
|
|
|
it("should be disabled when disabled prop is true", (): void => {
|
|
render(<OAuthButton {...defaultProps} disabled={true} />);
|
|
const button = screen.getByRole("button");
|
|
expect(button).toBeDisabled();
|
|
});
|
|
|
|
it("should have reduced opacity when disabled", (): void => {
|
|
render(<OAuthButton {...defaultProps} disabled={true} />);
|
|
const button = screen.getByRole("button");
|
|
expect(button.className).toContain("opacity-50");
|
|
expect(button.className).toContain("pointer-events-none");
|
|
});
|
|
|
|
it("should have aria-label with provider name", (): void => {
|
|
render(<OAuthButton {...defaultProps} />);
|
|
const button = screen.getByRole("button");
|
|
expect(button).toHaveAttribute("aria-label", "Continue with Authentik");
|
|
});
|
|
|
|
it("should have aria-label Connecting when loading", (): void => {
|
|
render(<OAuthButton {...defaultProps} isLoading={true} />);
|
|
const button = screen.getByRole("button");
|
|
expect(button).toHaveAttribute("aria-label", "Connecting");
|
|
});
|
|
|
|
it("should render a spinner SVG when loading", (): void => {
|
|
const { container } = render(<OAuthButton {...defaultProps} isLoading={true} />);
|
|
const spinner = container.querySelector("svg");
|
|
expect(spinner).toBeInTheDocument();
|
|
expect(spinner?.getAttribute("class")).toContain("animate-spin");
|
|
});
|
|
|
|
it("should not call onClick when disabled", async (): Promise<void> => {
|
|
const user = userEvent.setup();
|
|
const onClick = vi.fn();
|
|
render(<OAuthButton {...defaultProps} onClick={onClick} disabled={true} />);
|
|
|
|
const button = screen.getByRole("button");
|
|
await user.click(button);
|
|
|
|
expect(onClick).not.toHaveBeenCalled();
|
|
});
|
|
});
|