@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
JavaScript
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