Files
2026-05-27 23:29:53 +01:00

60 lines
2.0 KiB
TypeScript

import { describe, expect, it } from "@suaveplan/testing/runner";
import fc from "fast-check";
import { PrincipalSchema } from "../src/schemas/principal.js";
const principalArb = fc.record(
{
id: fc.string({ minLength: 1, maxLength: 64 }),
email: fc.option(
fc
.tuple(
fc.string({ minLength: 1, maxLength: 16 }),
fc.string({ minLength: 1, maxLength: 16 })
)
.map(
([l, r]) =>
`${l.replace(/[^A-Za-z0-9]/g, "a")}@${r.replace(
/[^A-Za-z0-9]/g,
"a"
)}.test`
),
{ nil: undefined }
),
emailVerified: fc.boolean(),
roles: fc.array(fc.string({ minLength: 1, maxLength: 16 }), {
maxLength: 5,
}),
tenantId: fc.option(fc.string({ minLength: 1, maxLength: 32 }), {
nil: undefined,
}),
metadata: fc.option(
fc.dictionary(
fc.string({ minLength: 1, maxLength: 8 }),
fc.oneof(fc.string(), fc.integer(), fc.boolean())
),
{ nil: undefined }
),
},
{ requiredKeys: ["id", "emailVerified", "roles"] }
);
describe("PrincipalSchema fast-check round-trip", () => {
it("accepts arbitrary valid principals (200 runs)", {
timeout: 30_000,
}, () => {
fc.assert(
fc.property(principalArb, (sample) => {
const result = PrincipalSchema.safeParse(sample);
if (!result.success) {
throw new Error(
`unexpected reject: ${JSON.stringify(result.error.issues)}`
);
}
expect(result.data.id).toBe(sample.id);
expect(result.data.emailVerified).toBe(sample.emailVerified);
}),
{ numRuns: 200 }
);
});
});