Files
Kordant/web/src/components/auth/auth.test.tsx

150 lines
4.5 KiB
TypeScript

import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { render } from "solid-js/web";
import type { JSX } from "solid-js";
import PasswordInput from "./PasswordInput";
import SocialAuthButtons from "./SocialAuthButtons";
import AuthLayout from "./AuthLayout";
import { Input, Button } from "~/components/ui";
function mount(comp: () => JSX.Element): HTMLDivElement {
const container = document.createElement("div");
document.body.appendChild(container);
render(() => comp(), container);
return container;
}
beforeEach(() => {
document.body.innerHTML = "";
if (!globalThis.crypto) {
Object.defineProperty(globalThis, "crypto", { value: {} });
}
(globalThis.crypto as unknown as Record<string, unknown>).randomUUID = vi.fn(
() => "test-uuid-1234",
);
});
afterEach(() => {
document.body.innerHTML = "";
});
describe("PasswordInput", () => {
it("renders with label", () => {
mount(() => <PasswordInput label="Password" />);
expect(document.body.textContent).toContain("Password");
expect(document.querySelector("label")).toBeTruthy();
});
it("renders password type by default", () => {
mount(() => <PasswordInput label="Password" />);
const input = document.querySelector("input")!;
expect(input.getAttribute("type")).toBe("password");
});
it("toggles visibility when eye icon is clicked", () => {
mount(() => <PasswordInput label="Password" />);
const input = document.querySelector("input")!;
const toggle = document.querySelector("button[aria-label]")!;
expect(input.getAttribute("type")).toBe("password");
expect(toggle.getAttribute("aria-label")).toBe("Show password");
toggle.dispatchEvent(new MouseEvent("click", { bubbles: true }));
expect(input.getAttribute("type")).toBe("text");
expect(toggle.getAttribute("aria-label")).toBe("Hide password");
toggle.dispatchEvent(new MouseEvent("click", { bubbles: true }));
expect(input.getAttribute("type")).toBe("password");
});
it("shows error message", () => {
mount(() => (
<PasswordInput label="Password" error="Password is required" />
));
expect(document.body.textContent).toContain("Password is required");
});
it("shows helper text when no error", () => {
mount(() => (
<PasswordInput label="Password" helperText="At least 8 characters" />
));
expect(document.body.textContent).toContain("At least 8 characters");
});
it("hides helper text when error is present", () => {
mount(() => (
<PasswordInput
label="Password"
error="Required"
helperText="Helper text"
/>
));
expect(document.body.textContent).toContain("Required");
expect(document.body.textContent).not.toContain("Helper text");
});
it("forwards onInput handler", () => {
const onInput = vi.fn();
mount(() => <PasswordInput onInput={onInput} />);
const input = document.querySelector("input")!;
input.dispatchEvent(new InputEvent("input", { bubbles: true }));
expect(onInput).toHaveBeenCalled();
});
});
describe("SocialAuthButtons", () => {
it("renders Google and Apple buttons", () => {
mount(() => <SocialAuthButtons />);
const buttons = document.querySelectorAll("button");
expect(buttons.length).toBe(2);
expect(buttons[0].textContent).toContain("Google");
expect(buttons[1].textContent).toContain("Apple");
});
it("renders SVG icons in each button", () => {
mount(() => <SocialAuthButtons />);
const buttons = document.querySelectorAll("button");
expect(buttons[0].querySelector("svg")).toBeTruthy();
expect(buttons[1].querySelector("svg")).toBeTruthy();
});
});
describe("AuthLayout", () => {
it("renders children inside the form card", () => {
mount(() => (
<AuthLayout>
<p>Form content</p>
</AuthLayout>
));
expect(document.body.textContent).toContain("Form content");
});
it("renders Kordant branding", () => {
mount(() => (
<AuthLayout>
<p>Content</p>
</AuthLayout>
));
expect(document.body.textContent).toContain("Kordant");
});
it("renders gradient-card wrapper", () => {
mount(() => (
<AuthLayout>
<p>Content</p>
</AuthLayout>
));
expect(document.querySelector(".gradient-card")).toBeTruthy();
});
it("renders testimonial text", () => {
mount(() => (
<AuthLayout>
<p>Content</p>
</AuthLayout>
));
expect(document.body.textContent).toContain("Kordant");
expect(document.body.textContent).toContain("AI-Powered Identity Protection");
});
});