mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-05 23:32:06 +00:00
76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
|
|
import { useState } from "react";
|
||
|
|
import { render, screen, within } from "@testing-library/react";
|
||
|
|
import userEvent from "@testing-library/user-event";
|
||
|
|
import { describe, expect, it } from "vitest";
|
||
|
|
|
||
|
|
import { PasswordChecklist } from "@/components/auth/password-checklist";
|
||
|
|
|
||
|
|
function ChecklistHarness() {
|
||
|
|
const [password, setPassword] = useState("");
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<label htmlFor="pw">Password</label>
|
||
|
|
<input id="pw" value={password} onChange={(event) => setPassword(event.target.value)} />
|
||
|
|
<PasswordChecklist password={password} />
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function ruleStates(): Record<string, string | null> {
|
||
|
|
const list = screen.getByRole("list", { name: "Password requirements" });
|
||
|
|
return Object.fromEntries(
|
||
|
|
within(list)
|
||
|
|
.getAllByRole("listitem")
|
||
|
|
.map((item) => [item.getAttribute("data-rule") ?? "", item.getAttribute("data-met")]),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
describe("PasswordChecklist", () => {
|
||
|
|
it("starts with every rule unmet", () => {
|
||
|
|
render(<ChecklistHarness />);
|
||
|
|
|
||
|
|
expect(ruleStates()).toEqual({
|
||
|
|
length: "false",
|
||
|
|
uppercase: "false",
|
||
|
|
number: "false",
|
||
|
|
special: "false",
|
||
|
|
});
|
||
|
|
expect(screen.getAllByText("requirement not met")).toHaveLength(4);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("marks each rule met live as the user types", async () => {
|
||
|
|
const user = userEvent.setup();
|
||
|
|
render(<ChecklistHarness />);
|
||
|
|
const input = screen.getByLabelText("Password");
|
||
|
|
|
||
|
|
await user.type(input, "A");
|
||
|
|
expect(ruleStates()).toMatchObject({ uppercase: "true", number: "false", special: "false" });
|
||
|
|
|
||
|
|
await user.type(input, "1");
|
||
|
|
expect(ruleStates()).toMatchObject({ uppercase: "true", number: "true", special: "false" });
|
||
|
|
|
||
|
|
await user.type(input, "!");
|
||
|
|
expect(ruleStates()).toMatchObject({ special: "true", length: "false" });
|
||
|
|
|
||
|
|
await user.type(input, "xyz");
|
||
|
|
expect(ruleStates()).toEqual({
|
||
|
|
length: "true",
|
||
|
|
uppercase: "true",
|
||
|
|
number: "true",
|
||
|
|
special: "true",
|
||
|
|
});
|
||
|
|
expect(screen.getAllByText("requirement met")).toHaveLength(4);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("marks a rule unmet again when the user deletes the character that satisfied it", async () => {
|
||
|
|
const user = userEvent.setup();
|
||
|
|
render(<ChecklistHarness />);
|
||
|
|
const input = screen.getByLabelText("Password");
|
||
|
|
|
||
|
|
await user.type(input, "Abcde1!");
|
||
|
|
await user.type(input, "{Backspace}");
|
||
|
|
|
||
|
|
expect(ruleStates()).toMatchObject({ special: "false", length: "true", number: "true" });
|
||
|
|
});
|
||
|
|
});
|