import { describe, it, expect } from "vitest"; import { validatePinForm, pinActionLabel, type PinFormState } from "./pinForm"; function form(overrides: Partial = {}): PinFormState { return { intent: "set", hasPin: false, currentPin: "", newPin: "", confirmPin: "", ...overrides, }; } describe("validatePinForm", () => { it("accepts a well-formed new PIN", () => { expect(validatePinForm(form({ newPin: "1234", confirmPin: "1234" }))).toBeNull(); }); it("requires the current PIN whenever one is set", () => { expect( validatePinForm(form({ intent: "change", hasPin: true, newPin: "5678", confirmPin: "5678" })), ).toBe("Enter your current PIN."); }); it("does not ask for a current PIN when none is set", () => { expect(validatePinForm(form({ hasPin: false, newPin: "1234", confirmPin: "1234" }))).toBeNull(); }); it("rejects non-digits", () => { expect(validatePinForm(form({ newPin: "12a4", confirmPin: "12a4" }))).toBe( "A PIN can only contain digits.", ); }); it("enforces the length range at both ends", () => { expect(validatePinForm(form({ newPin: "123", confirmPin: "123" }))).toBe( "A PIN must be 4–8 digits.", ); expect(validatePinForm(form({ newPin: "123456789", confirmPin: "123456789" }))).toBe( "A PIN must be 4–8 digits.", ); }); it("catches a mistyped confirmation", () => { expect(validatePinForm(form({ newPin: "1234", confirmPin: "1235" }))).toBe( "The two PINs do not match.", ); }); it("asks for confirmation before comparing", () => { expect(validatePinForm(form({ newPin: "1234", confirmPin: "" }))).toBe("Confirm your new PIN."); }); it("rejects a change that changes nothing", () => { expect( validatePinForm( form({ intent: "change", hasPin: true, currentPin: "1234", newPin: "1234", confirmPin: "1234", }), ), ).toBe("The new PIN is the same as the current one."); }); it("needs only the current PIN to turn one off", () => { expect(validatePinForm(form({ intent: "clear", hasPin: true, currentPin: "1234" }))).toBeNull(); }); it("will not turn off a PIN without the current one", () => { expect(validatePinForm(form({ intent: "clear", hasPin: true, currentPin: "" }))).toBe( "Enter your current PIN.", ); }); it("reports one problem at a time, most blocking first", () => { // Both the current PIN is missing *and* the new one is too short; the // current-PIN prompt is the one that comes back. expect( validatePinForm(form({ intent: "change", hasPin: true, newPin: "1", confirmPin: "2" })), ).toBe("Enter your current PIN."); }); }); describe("pinActionLabel", () => { it("names each intent", () => { expect(pinActionLabel("set")).toBe("Set PIN"); expect(pinActionLabel("change")).toBe("Change PIN"); expect(pinActionLabel("clear")).toBe("Turn off PIN"); }); });