test(spec): cover fluent value generators determinism and chaining

This commit is contained in:
pj committed 2026-06-01 21:02:26 +05:30
1 parent d65c0cd448
commit 9a2cb61561
1 file changed
+75
+75
View File
@@ -0,0 +1,75 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { Pcg } from "../src/pcg.ts";
import { setSamplerRng } from "../src/sampler-rng.ts";
import { edgeCaseText, emails, integers, strings } from "../src/values.ts";
import { INPUT_CORPUS } from "../src/corpus.ts";
import type { Sampler } from "../src/types.ts";
function withRng<T>(seed: bigint, body: () => T): T {
setSamplerRng(new Pcg(seed, 0n));
try {
return body();
} finally {
setSamplerRng(null);
}
}
test("same seed yields an identical draw sequence", () => {
const drawAll = () => [
strings().generate(),
integers().between(0, 999).generate(),
emails().domain("folio.app").generate(),
edgeCaseText().generate(),
];
assert.deepEqual(withRng(7n, drawAll), withRng(7n, drawAll));
});
test("a different seed yields a different sequence", () => {
const drawAll = () => [strings().generate(), integers().generate()];
assert.notDeepEqual(withRng(1n, drawAll), withRng(2n, drawAll));
});
test("integers().between constrains the output range", () => {
withRng(42n, () => {
for (let i = 0; i < 200; i++) {
const value = integers().between(5, 9).generate();
assert.ok(Number.isInteger(value));
assert.ok(value >= 5 && value <= 9, `out of range: ${value}`);
}
});
});
test("strings().length(min, max).alpha() constrains length and charset", () => {
withRng(99n, () => {
for (let i = 0; i < 200; i++) {
const value = strings().length(3, 6).alpha().generate();
assert.ok(value.length >= 3 && value.length <= 6, `bad length: ${value}`);
assert.match(value, /^[A-Za-z]*$/);
}
});
});
test("emails().domain sets the host and edgeCaseText draws from the corpus", () => {
withRng(3n, () => {
const email = emails().domain("folio.app").generate();
assert.match(email, /^[A-Za-z]+@folio\.app$/);
assert.ok(INPUT_CORPUS.includes(edgeCaseText().generate()));
});
});
test("a builder is itself a Sampler<T>", () => {
withRng(11n, () => {
const sampler: Sampler<number> = integers().between(0, 9);
const value = sampler.generate();
assert.ok(value >= 0 && value <= 9);
});
});
test("outside a walk generators return a fixed deterministic default", () => {
setSamplerRng(null);
assert.equal(integers().between(10, 20).generate(), 10);
assert.equal(strings().length(4, 8).alpha().generate(), "aaaa");
assert.equal(emails().domain("folio.app").generate(), "[email protected]");
assert.equal(edgeCaseText().generate(), INPUT_CORPUS[0]);
});