UNPKG

@makerx/ts-dossier

Version:

A support library to facilitate the easy creation of builders for use with an Object-Mother test pattern in TypeScript

89 lines (86 loc) 2.79 kB
import { deepClone } from './deep-clone.mjs'; /** * Data builder is an abstract class builders can inherit to make working with the {@linkplain dossierProxy} easier. * * ```typescript * export class ShapeBuilder extends DataBuilder<Shape> { * constructor() { * super({ * name: randomString(10, 20), * sides: randomNumberBetween(1, 4), * colour: randomElement(['Blue', 'Red', 'Yellow', 'Green']), * }) * } * * public withName(name: string) { * return this.with('name', name + ' Intercepted') * } * } * * export const shapeBuilder = dossierProxy<ShapeBuilder, Shape>(ShapeBuilder) * ``` */ class DataBuilder { thing; constructor(thing) { this.thing = thing; this.thing = thing; } with(key, value) { this.thing[key] = value; return this; } build() { return deepClone(this.thing); } clone() { return new Proxy(deepClone(this), proxyHandler); } } const proxyHandler = { // eslint-disable-next-line @typescript-eslint/no-explicit-any get: function (target, prop, receiver) { if (!target[prop] && prop.startsWith('with')) { const propertyName = prop[4].toLocaleLowerCase() + prop.substring(5); // eslint-disable-next-line @typescript-eslint/no-explicit-any return (value) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any target.with(propertyName, value); return receiver; }; } return Reflect.get(target, prop, receiver); }, }; /** * The proxy builder allows one to easily create a builder and have a [proxy]{@link https://developer.mozilla.org/en-US/docs/web/javascript/reference/global_objects/proxy/proxy} * instance handle any with* methods not specifically declared by the builder itself. * * ```typescript * class ShapeBuilder extends DataBuilder<Shape> { * constructor() { * super({ * name: randomString(10, 20), * sides: randomNumberBetween(1, 4), * colour: randomElement(['Blue', 'Red', 'Yellow', 'Green']), * }) * } * * public withName(name: string) { * return this.with('name', name + ' Intercepted') * } * } * * const shapeBuilder = dossierProxy<ShapeBuilder, Shape>(ShapeBuilder) * * const shape = shapeBuilder().withName('Square').withSides(4).withColour('Red').build() * * console.log(shape) // Outputs { name: 'Square Intercepted', sides: 4, colour: 'Red' } * ``` * @param builder The constructor to call to create a new instance of the builder. */ function dossierProxy(builder) { return () => new Proxy(new builder(), proxyHandler); } export { DataBuilder, dossierProxy }; //# sourceMappingURL=data-builder.mjs.map