Fluent Test Data Builder With Overrides
Create readable fixtures with layered overrides, per-item variation and reset support, keeping tests free of duplicated object literals.
Code
export function createBuilder(defaults) {
if (defaults === null || typeof defaults !== "object" || Array.isArray(defaults)) {
throw new TypeError("defaults must be a plain object");
}
const layers = [];
const build = (overrides = {}) => Object.assign({}, defaults, ...layers, overrides);
const assertOverrides = (overrides) => {
if (overrides === null || typeof overrides !== "object" || Array.isArray(overrides)) {
throw new TypeError("overrides must be a plain object");
}
};
const api = {
with(overrides) {
assertOverrides(overrides);
layers.push(overrides);
return api;
},
reset() {
layers.length = 0;
return api;
},
build,
buildList(count, overrides = () => ({})) {
if (!Number.isInteger(count) || count < 0) {
throw new RangeError("count must be a non-negative integer");
}
if (typeof overrides !== "function") throw new TypeError("overrides must be a function");
return Array.from({ length: count }, (_, index) => build(overrides(index)));
},
};
return api;
}
const user = createBuilder({ role: "member", active: true });
console.log(user.with({ role: "admin" }).build({ name: "Ada" }));
console.log(user.reset().buildList(2, (index) => ({ id: index + 1 })));Report a problem with this exampleOpens a pre-filled issue on GitHub.