Files
test/frontend/__tests__/components/ui/form/utils.spec.ts
Benjamin Falch 2bc741fb78
Some checks failed
Mark Stale PRs / stale (push) Has been cancelled
adding monkeytype
2026-04-23 13:53:44 +02:00

134 lines
3.8 KiB
TypeScript

import { describe, it, expect, vi } from "vitest";
import { z } from "zod";
import {
fromSchema,
handleResult,
allFieldsMandatory,
fieldMandatory,
type ValidationResult,
} from "../../../../src/ts/components/ui/form/utils";
describe("fromSchema", () => {
const schema = z.string().min(3, "too short").max(10, "too long");
const validate = fromSchema(schema);
it("returns undefined for valid value", () => {
expect(validate({ value: "hello" })).toBeUndefined();
});
it("returns error messages for invalid value", () => {
expect(validate({ value: "ab" })).toEqual(["too short"]);
});
it("returns multiple error messages", () => {
const numSchema = z.number().min(5, "too small").max(3, "too big");
const v = fromSchema(numSchema);
const result = v({ value: 4 });
// 4 fails min(5) but passes max(3)? Actually 4 > 3, so both fail
// number 4: min(5) fails, max(3) fails
expect(result).toEqual(["too small", "too big"]);
});
});
describe("handleResult", () => {
const mockSetMeta = vi.fn();
function makeField() {
mockSetMeta.mockClear();
return { setMeta: mockSetMeta } as any;
}
it("returns undefined for undefined results", () => {
expect(handleResult(makeField(), undefined)).toBeUndefined();
});
it("returns undefined for empty results", () => {
expect(handleResult(makeField(), [])).toBeUndefined();
});
it("returns error messages and ignores warnings", () => {
const results: ValidationResult[] = [
{ type: "error", message: "bad email" },
{ type: "error", message: "too short" },
];
expect(handleResult(makeField(), results)).toEqual([
"bad email",
"too short",
]);
});
it("sets warning meta on field", () => {
const results: ValidationResult[] = [
{ type: "warning", message: "weak password" },
];
const field = makeField();
const result = handleResult(field, results);
expect(result).toBeUndefined();
expect(mockSetMeta).toHaveBeenCalledOnce();
const updater = mockSetMeta.mock.calls[0]![0];
const newMeta = updater({ existing: true });
expect(newMeta).toEqual({
existing: true,
hasWarning: true,
warnings: ["weak password"],
});
});
it("handles both errors and warnings", () => {
const results: ValidationResult[] = [
{ type: "warning", message: "not recommended" },
{ type: "error", message: "invalid" },
];
const field = makeField();
const result = handleResult(field, results);
expect(mockSetMeta).toHaveBeenCalledOnce();
expect(result).toEqual(["invalid"]);
});
});
describe("allFieldsMandatory", () => {
const validate = allFieldsMandatory<{ a: string; b: string }>();
it("returns undefined when all fields have values", () => {
expect(validate({ value: { a: "x", b: "y" } })).toBeUndefined();
});
it("returns error when a field is empty string", () => {
expect(validate({ value: { a: "x", b: "" } })).toBe(
"all fields are mandatory",
);
});
it("returns error when a field is undefined", () => {
expect(validate({ value: { a: "x", b: undefined } as any })).toBe(
"all fields are mandatory",
);
});
});
describe("fieldMandatory", () => {
it("returns undefined for non-empty value", () => {
const validate = fieldMandatory();
expect(validate({ value: "hello" })).toBeUndefined();
});
it("returns default message for empty string", () => {
const validate = fieldMandatory();
expect(validate({ value: "" })).toBe("mandatory");
});
it("returns default message for undefined", () => {
const validate = fieldMandatory();
expect(validate({ value: undefined })).toBe("mandatory");
});
it("returns custom message", () => {
const validate = fieldMandatory("required field");
expect(validate({ value: "" })).toBe("required field");
});
});