import { describe, expect, it } from "@suaveplan/testing/runner"; import { ValidationError } from "../errors/errors.js"; import { number } from "../schemas/number/number.js"; import { string } from "../schemas/string/string.js"; import { mergeResults, pipe } from "./compose.js"; describe("mergeResults", () => { it("merges all successes", { timeout: 5000 }, () => { const r = mergeResults([ { success: true as const, data: 1 }, { success: true as const, data: 2 }, ]); expect(r.success).toBe(true); if (r.success) expect(r.data).toEqual([1, 2]); }); it("merges failures", { timeout: 5000 }, () => { const err1 = new ValidationError([ { code: "VALIDATION.REQUIRED", path: ["a"], message: "a required" }, ]); const err2 = new ValidationError([ { code: "VALIDATION.REQUIRED", path: ["b"], message: "b required" }, ]); const r = mergeResults([ { success: false as const, error: err1 }, { success: false as const, error: err2 }, ]); expect(r.success).toBe(false); if (!r.success) expect(r.error.issues).toHaveLength(2); }); it("fails if any result is failure", { timeout: 5000 }, () => { const err = new ValidationError([ { code: "VALIDATION.REQUIRED", path: [], message: "required" }, ]); const r = mergeResults([ { success: true as const, data: 1 }, { success: false as const, error: err }, ]); expect(r.success).toBe(false); }); it("handles empty array", { timeout: 5000 }, () => { const r = mergeResults([]); expect(r.success).toBe(true); if (r.success) expect(r.data).toEqual([]); }); }); describe("pipe", () => { it("applies single transform", { timeout: 5000 }, () => { const s = pipe( string(), (v: unknown) => (v as string).length ); expect(s.parse("hello")).toBe(5); }); it("applies multiple transforms in order", { timeout: 5000 }, () => { const s = pipe( number(), (v: unknown) => (v as number) * 2, (v: unknown) => String(v as number) ); expect(s.parse(5)).toBe("10"); }); it("propagates parse failure", { timeout: 5000 }, () => { const s = pipe( string(), (v: unknown) => (v as string).length ); expect(() => s.parse(42)).toThrow(ValidationError); }); });