data-mock-builder
Version:
🧰 A fluent, type-safe mock object generator for test data creation, seeding, and API mocking.
216 lines (214 loc) • 7.89 kB
TypeScript
type ValueOrFactory<T> = T | ((obj?: any, index?: number, options?: {
deepCopy?: boolean;
skipValidation?: boolean;
}) => T);
type FieldValidator = (value: any, fieldName: string) => {
success: boolean;
errorMsg?: string;
};
/**
* MockBuilder provides a fluent API to construct mock objects for testing purposes.
*
* Features:
* - Define fields with static values or value factories (functions).
* - Support for string, number, boolean, array, and incrementing number fields.
* - Repeat object creation to generate arrays of mocks.
* - Extend builder with templates or presets for reusable field sets.
* - Define and use named presets for common mock structures.
*
* Example usage:
* ```
* const builder = new MockBuilder()
* .field("id").increment(1)
* .field("name").string("Alice")
* .repeat(2);
* const result = builder.build();
* // result: [{ id: 1, name: "Alice" }, { id: 2, name: "Alice" }]
* ```
*/
declare class MockBuilder {
private fields;
private repeatCount;
private static presets;
private deepCopyEnabled;
private defaultSkipValidation;
private currentFieldName;
/**
* Creates a new MockBuilder instance.
* @param options Optional. { deepCopy?: boolean; skipValidation?: boolean }
*/
constructor(options?: {
deepCopy?: boolean;
skipValidation?: boolean;
});
/**
* Enable or disable deep copy of field values in build().
* By default, deep copy is enabled to prevent mutation between builds.
* @param enabled true to enable deep copy, false to disable
* @returns The builder instance for chaining.
*/
deepCopy(enabled: boolean): this;
/**
* Adds a field to the mock object.
* Overloads:
* - field(name: string): returns an object with type methods (string, number, etc.)
* - field(name: string, value: any | (() => any)): adds the field directly and returns the builder instance.
*
* @param name The name of the field to add.
* @param value (optional) The value or factory for the field.
* @returns The builder instance or the type API.
*/
field<T>(name: string): {
string: (val?: ValueOrFactory<string>) => MockBuilder;
number: (val?: ValueOrFactory<number>) => MockBuilder;
boolean: (val?: ValueOrFactory<boolean>) => MockBuilder;
array: <T = any>(val: ValueOrFactory<T[]>) => MockBuilder;
object: <T = Record<string, any>>(val: ValueOrFactory<T>) => MockBuilder;
/**
* Sets an incrementing number for the field, starting from `start` and incrementing by `step`.
* @param start The starting value for the increment (default: 1).
* @param step The increment step (default: 1).
* @returns The builder instance for chaining.
*/
increment: (start?: number, step?: number) => MockBuilder;
/**
* Sets a field validator function that will be used to validate the field's value
* during build.
*
* @param validator A function that validates the field value.
* Should return an object with { success: boolean, errorMsg?: string }.
* @returns The builder instance for chaining.
*/
validator: (validator: FieldValidator) => MockBuilder;
};
field<T>(name: string, value: ValueOrFactory<T>): MockBuilder;
/**
* Adds a validator to the last defined field.
*
* @param name The field name.
* @param validator The validator function.
* @returns The builder instance for chaining.
* @private
*/
private addValidator;
/**
* Adds a field definition to the builder.
*
* @param name The field name.
* @param val The value or value factory for the field.
* @returns The builder instance for chaining.
* @private
*/
private addField;
/**
* Sets the number of objects to generate when build() is called.
*
* @param n The number of objects to build.
* @returns The builder instance for chaining.
*
* Example:
* ```
* builder.repeat(5).build(); // returns an array of 5 objects
* ```
*/
repeat(n: number): this;
/**
* Extends the builder with fields from a template object.
* Each key-value pair in the template becomes a field.
*
* @param template An object whose properties are added as fields.
* @returns The builder instance for chaining.
*
* Example:
* ```
* builder.extend({ foo: "bar", count: 42 });
* ```
*/
extend(template: Record<string, any>): this;
/**
* Defines a named preset template for reuse in multiple builders.
*
* Presets are global and can be used in any MockBuilder instance via the `preset` method.
* A preset is simply a named object template that can be reused and extended.
*
* Example:
* ```
* // Define a preset named "user"
* MockBuilder.definePreset("user", { name: "Alice", age: 30 });
*
* // Use the preset in a builder
* const builder = new MockBuilder().preset("user");
* const result = builder.build();
* // result: { name: "Alice", age: 30 }
*
* // You can override fields after applying a preset
* const builder2 = new MockBuilder().preset("user").field("age").number(40);
* const result2 = builder2.build();
* // result2: { name: "Alice", age: 40 }
* ```
*
* @param name The name of the preset.
* @param template The template object to associate with the preset.
*/
static definePreset(name: string, template: Record<string, any>): void;
/**
* Applies a preset template by name to the builder.
* Throws an error if the preset does not exist.
*
* @param name The name of the preset to apply.
* @returns The builder instance for chaining.
* @throws Error if the preset is not found.
*
* Example:
* ```
* builder.preset("user");
* ```
*/
preset(name: string): this;
/**
* Sets a custom validator for a field.
* The validator function should return an object with { success: boolean, errorMsg?: string }.
*
* @param fieldName The name of the field to validate.
* @param validator The validator function.
* @returns The builder instance for chaining.
*
* Example:
* ```
* builder
* .field("age").number(25)
* .validator("age", (value) => ({
* success: value >= 18,
* errorMsg: value >= 18 ? undefined : "Age must be at least 18"
* }))
* .field("email").string("user@example.com")
* .validator("email", (value) => ({
* success: /^.+@.+\..+$/.test(value),
* errorMsg: /^.+@.+\..+$/.test(value) ? undefined : "Invalid email format"
* }));
* ```
*/
validator(fieldName: string, validator: FieldValidator): this;
/**
* Builds the mock object(s) according to the defined fields and repeat count.
* If repeat() was not called or set to 1, returns a single object.
* If repeat() was set to n > 1, returns an array of n objects.
*
* @param options Optional. Options object:
* - deepCopy: boolean (overrides the builder's deep copy setting for this build)
* - skipValidation: boolean (if true, skips field validation for required fields; default: true)
* @returns The built object or array of objects, optionally cast to type T.
*
* Example:
* ```
* interface User { id: number; name: string }
* const user = builder.build<User>();
* const users = builder.repeat(2).build<User[]>();
* ```
*/
build<T extends object = any>(options?: {
deepCopy?: boolean;
skipValidation?: boolean;
}): T;
}
export { MockBuilder };