@makerx/ts-dossier
Version:
A support library to facilitate the easy creation of builders for use with an Object-Mother test pattern in TypeScript
92 lines (88 loc) • 2.85 kB
JavaScript
;
var deepClone = require('./deep-clone.js');
/**
* 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.deepClone(this.thing);
}
clone() {
return new Proxy(deepClone.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);
}
exports.DataBuilder = DataBuilder;
exports.dossierProxy = dossierProxy;
//# sourceMappingURL=data-builder.js.map