mockthis
TypeScript icon, indicating that this package has built-in type declarations

2.1.19 • Public • Published

MockThis

A powerful data generation library.

Introduction

MockThis is a powerful tool for generating mock data for testing and development purposes, built with extensibility in mind. With its flexible schema definitions, variety of built-in generators, and the ability to extend functionality through plugins and custom generators, it can greatly simplify the process of creating realistic test data. With a fluid and intuitive API, MockThis allows you to easily define and generate complex data structures.

Installation

You can install MockThis using npm:

npm install mockthis

Usage

Basic Example

Here is a basic example of how to use MockThis to generate mock data:

import { MockThis, FirstName, LastName, Email, Sequence, DecimalRange, DateTime, Address, City, Country, Id, PhoneNumber, ZipCode } from "mockthis";

// Define the schema for the mock data
const schema = {
  id: Id,
  person: {
    first: FirstName,
    last: LastName,
    emails: [Email]
    phoneNumber: PhoneNumber,
  },
  address: {
    address: Address,
    city: City,
    state: State,
    zipCode: ZipCode
    country: Country
  },
  stats: {
    score: DecimalRange(0, 100),
    lastLogin: DateTime
  },
};

// Create and configure the MockThis instance
MockThis(schema)
  .setTotal(1, 5)
  .setArrayRange(1, 5)
  .setNullValueChance(0.1)
  .setFormats({
    date: "YYYY-MM-DD",
    time: "HH:mm:ss"
  })
  .asJson()
  .then((data) => {
    console.log(data);
  });

Nesting Example

MockThis supports complex nesting of schemas and allows you to set array lengths directly within your schema declaration. This flexibility enables you to generate intricate and deeply nested mock data structures according to your specific requirements. The length of generated arrays can also be set in combination with the setArrayRange method.

Here is a basic example:

const schema = {
    nested: {
        values: {
            singleValue: Constant("Nested Value"),
            arrayValues: [Animal, 1, 5], // This array will have between 1 and 5 values.
        },
        arrayception: [[Sequence(colors), 5], 5],
        arrayOfObjects: [{
            prop1: Word,
            prop2: Sentence,
            prop3: Paragraph
        }] // This array will use the global array range defined in setArrayRange.
    }
};

MockThis(schema)
  .setTotal(5)
  .setArrayRange(1, 10) // This range will apply to all generated arrays unless they have a range defined inline.
  .asJson()
  .then((data) => {
    console.log(data);
  });

Methods and Their Usage

MockThis<G>(schema: object, plugins?: MockThisPlugin[], generator?: G): MockThisInstance

Creates a new MockThisInstance with the provided schema.

  • Parameters:
    • schema: An object defining the structure and data types of the mock data.
    • plugins: An optional array of MockThisPlugin objects.
    • generator: An optional data generator of any type. This generator will be passed to all TypeFunc generator functions. The default value is an instance of Faker. NOTE: If you provide a custom generator object, only the built-in utility TypeFunc generators will continue to work as the rest rely on the default Faker instance to provide fake data. This functionality is primarily for custom TypeFunc packages that wish to use a data generator other than Faker.
  • Returns:
    • MockThisInstance: A new MockThisInstance.

Usage:

const mockThis = MockThis(schema);

setTotal(min: number, max?: number): this

Sets the total number of top-level mock data objects to generate.

  • Parameters:
    • min: The minimum number of items to generate.
    • max?: Optional. The maximum number of items to generate. If not provided, min is used.
  • Returns:
    • MockThisInstance: The current MockThisInstance. This allows chaining of methods.

Usage:

mockThis.setTotal(10); // Generates exactly 10 items
mockThis.setTotal(5, 15); // Generates between 5 and 15 items

setArrayRange(min: number, max?: number): this

Sets the range for lengths of arrays within the data.

  • Parameters:
    • min: The minimum length of arrays.
    • max?: Optional. The maximum length of arrays. If not provided, min is used.
  • Returns:
    • MockThisInstance: The current MockThisInstance. This allows chaining of methods.

Usage:

mockThis.setArrayRange(2); // Arrays will have a length of 2
mockThis.setArrayRange(2, 5); // Arrays will have lengths between 2 and 5

setFormat<K extends keyof Formats>(key: K, value: Formats[K]): this

Sets format for provided key.

  • Parameters:
    • key: The key of the format.
    • value: The value of the format.
  • Returns:
    • MockThisInstance: The current MockThisInstance. This allows chaining of methods.

Usage:

mockThis.setFormat("date", "DD/MM/YYYY");

setFormats(formats: { [K in keyof Formats]?: Formats[K] }): this

Sets formats for all provided keys.

  • Parameters:
    • formats: An object specifying format strings for date and time.
  • Returns:
    • MockThisInstance: The current MockThisInstance. This allows chaining of methods.

Usage:

mockThis.setFormats({
  date: "DD/MM/YYYY",
  time: "HH:mm",
});

setNullValueChance(chance: number): this

Sets the probability that fields can be null.

  • Parameters:
    • chance: A number between 0 and 1 representing the probability.
  • Returns:
    • MockThisInstance: The current MockThisInstance. This allows chaining of methods.

Usage:

mockThis.setNullValueChance(0.2); // 20% chance of null values

setRequired(requiredFields: string[]): this

Specifies fields that must not be null.

  • Parameters:
    • requiredFields: An array of field names that are required.
  • Returns:
    • MockThisInstance: The current MockThisInstance. This allows chaining of methods.

Usage:

mockThis.setRequired(["id", "name"]);

setUserDefinedBlueprint<T>(blueprint: T): this

Adds user-defined values to the blueprint. These can be used in custom TypeFunc functions by accessing the the userDefined property on the Blueprint param.

  • Parameters:
    • blueprint: An object containing custom fields.
  • Returns:
    • MockThisInstance: The current MockThisInstance. This allows chaining of methods.

Usage:

mockThis.setUserDefinedBlueprint({
  customField: "Custom Value",
});

asJson(replacer?: Function, space?: string | number): Promise<string>

Generates the mock data as a JSON string.

  • Parameters:

    • replacer?: Optional. A function that alters the behavior of the stringification process.
    • space?: Optional. A string or number that's used to insert white space into the output JSON string.
  • Returns:

    • Promise<string>: A promise that resolves to the JSON string.

Usage:

const data = await mockThis.asJson(null, 2);

asObject(): Promise<object[]>

Generates the mock data as a JavaScript object or array of objects.

  • Returns:
    • Promise<object[]>: A promise that resolves to the generated object(s).

Usage:

const data = await mockThis.asObject()

Built-in TypeFuncs

MockThis includes a variety of built-in data generators:

  • Basic Types:

    • Integer: Random integer between -500 and 500.
    • IntegerRange(min: number, max: number): Random integer between specified min and max.
    • Decimal: Random decimal number.
    • DecimalRange(min: number, max: number): Random decimal between specified min and max.
    • Bool: Random boolean value.
    • Constant<T>(value: T): Constant value.
  • Date and Time:

    • DateTime: Random datetime.
    • DateOnly: Random date.
    • TimeOnly: Random time.
    • DateTimeFormatted(format: string): Random datetime in a custom format.
    • Birthdate: Random birthdate for an adult between 18 and 80 years old.
  • Lorem Ipsum

    • Letter: Random letter.
    • Word: Random word.
    • Sentence: Random sentence.
    • Paragraph: Random paragraph.
  • Person:

    • FirstName: Random first name.
    • LastName: Random last name.
    • Email: Random email address.
    • PhoneNumber: Random phone number.
    • SocialSecurityNumber: Random social security number.
  • Location:

    • Address: Random street address.
    • City: Random city name.
    • Country: Random country name.
    • State: Random state or region.
    • ZipCode: Random postal code.
    • Coordinates: Random geographical coordinates.
  • Financial:

    • Currency: Random currency code.
    • Dollar: Random dollar amount.
    • Euro: Random euro amount.
  • Web:

    • Url: Random url.
    • AvatarUrl: Random avatar URL.
  • Company:

    • CompanyName: Random company name.
    • CatchPhrase: Random company catchphrase.
    • CatchPhraseAdjective: Random adjective for a catchphrase.
    • CatchPhraseDescriptor: Random descriptor for a catchphrase.
    • CatchPhraseNoun: Random noun for a catchphrase.
    • BuzzAdjective: Random buzzword adjective.
    • BuzzNoun: Random buzzword noun.
    • BuzzPhrase: Random buzzword phrase.
    • BuzzVerb: Random buzzword verb.
  • Vehicle:

    • Vehicle: Random vehicle.
    • VehicleManufacturer: Random vehicle manufacturer.
    • VehicleModel: Random vehicle model.
    • VehicleType: Random vehicle type.
    • VehicleFuelType: Random vehicle fuel type.
  • Music:

    • MusicAlbum: Random music album name.
    • MusicArtist: Random music artist name.
    • MusicGenre: Random music genre.
    • MusicSong: Random song name.
  • Book

    • BookTitle: Random book title.
    • BookAuthor: Random book author.
    • BookGenre: Random book genre.
    • BookPublisher: Random book publisher.
    • BookFormat: Random book format.
    • BookSeries: Random book series.
  • Food:

    • FoodAdjective: Random food-related adjective.
    • FoodDescription: Random food description.
    • FoodDish: Random dish name.
    • FoodEthnicCategory: Random ethnic food category.
    • FoodFruit: Random fruit name.
    • FoodIngredient: Random ingredient name.
    • FoodMeat: Random meat name.
    • FoodSpice: Random spice name.
    • FoodVegetable: Random vegetable name.
  • Airline:

    • AircraftType: Random aircraft type.
    • Airline: Random airline name.
    • Airplane: Random airplane name.
    • Airport: Random airport name.
    • FlightNumber: Random flight number.
    • RecordLocator: Random record locator.
    • Seat: Random seat assignment.
  • Misc:

    • Animal: Random animal type.
    • Url: Random url.
    • Color: Random color.
    • Element: Random chemical element.
  • Utility:

    • Random<T>(items: T[]): Random value from an array of values.
    • Sequence<T>(items: T[]): Value from an array. The returned index is incremented each time this TypeFunc returns a value.
    • Id(max?: number): A new number id from a sequence. max defaults to 10000.
    • Uuid: A UUID (Universally Unique Identifier).
    • EnumRandom(enumType): Random enum value.
    • EnumSequence(enumType): Value from an enum. The returned index is incremented each time this TypeFunc returns a value.
    • MapValue<T, U>(typeFunc: TypeFunc<T>, mapCallback: (value: T) => U) => TypeFunc<U>: The value of the provided TypeFunc modified using the mapCallback function.
    • ReduceValues<T>(typeFuncs: TypeFunc<any>[], reduceCallback: (values: any[]) => T) => TypeFunc<T>: Combines the returned values of multiple TypeFuncs using the reduceCallback function.
    • Async<T>(generator: () => Promise<T>): Async value.
    • Dep<T>(dependencies: string[], (dependencies: any[], getValue: (type: TypeFunc) => any) => T): The Dep function creates a custom generator that allows a field's value to be dependent on other fields in your schema. It's useful for generating values that are calculated based on other fields and where data consistency is desired. The second parameter getValue is a helper function to generate values from other TypeFunc generators if needed.

Advanced Built-in TypeFuncs

You can create more complex generators that depend on other fields in the data, use external data sources, asynchronous operations, or other advanced logic.

Example: Dependency TypeFunc

// Define a custom generator that depends on other fields
const FullNameGenerator = Dep(
  ["firstName", "lastName"],
  ([firstName, lastName], getValue) => {
    const middleName = getValue(FirstName);
    return `${firstName} ${middleName} ${lastName}`;
  }
);

const schema = {
  firstName: FirstName,
  lastName: LastName,
  fullName: FullNameGenerator,
};

MockThis(schema)
  .asObject()
  .then((data) => {
    console.log(data);
  });

Explanation

  • Dep: The Dep function allows you to create a custom generator that depends on the values of other fields.
  • Dependencies: You specify an array of dependency field names as the first argument to Dep. The values can be dot delimited to access nested properties.
  • Callback: The second argument is a callback function that receives the values of the dependencies as well as a getValue helper function that can be used to generate values using other TypeFuncs.
  • Example: In this example, fullName depends on firstName and lastName and combines them, along with another value generated as the middle name, to create the full name.

NOTE: Dep cannot be nested within another Dep function.

Example: Async TypeFunc

// Define an asynchronous custom generator
const AsyncGenerator = Async(async () => {
  const response = await fetch("https://api.example.com/data");
  const data = await response.json();
  return data.value;
});

const schema = {
  asyncField: AsyncGenerator,
};

MockThis(schema)
  .asObject()
  .then((data) => {
    console.log(data);
  });

Explanation

  • Async: Wrap your async function with Async to create an asynchronous generator.

Example: MapValue TypeFunc

// Map Decimal TypeFunc to 2 decimal places
const PrecisionDecimal = MapValue(Decimal, (value) => parseInt(value.toFixed(2)));

const schema = {
  precisionDecimal: PrecisionDecimal,
};

MockThis(schema)
  .asObject()
  .then((data) => {
    console.log(data);
  });

Explanation

  • MapValue: Transforms the returned value of the provided TypeFunc using the mapCallback function.

Example: ReduceValues TypeFunc

// Combine the value of FirstName with the value of LastName
const FullName = ReduceValues([FirstName, LastName], ([firstName, lastName]) => `${firstName} ${lastName}`);

const schema = {
  fullName: FullName,
};

MockThis(schema)
  .asObject()
  .then((data) => {
    console.log(data);
  });

Explanation

  • ReduceValues: Combines the returned values of multiple TypeFuncs using the reduceCallback function.

Customs TypeFuncs

In addition to the built in data generators, you can create custom TypeFunc generators to produce new types of data.

Example: Custom TypeFunc

// Define a custom generator function
const CustomType: TypeFunc<string> = (generator, blueprint) => {
  // Custom logic to generate a value
  return "Custom Generated Value";
};

// Use the custom generator in your schema
const schema = {
  customType: CustomType,
};

MockThis(schema)
  .asObject()
  .then((data) => {
    console.log(data);
  });

Explanation

  • TypeFunc: Use TypeFunc to define a custom generator function.
  • Generator: The provided data generator. This defaults to a built-in instance of Faker.
  • Blueprint: The config object used by MockThis in data generation. Contains core config as well as user defined config.
  • Use in Schema: Use your custom generator in the schema like any other generator.

Plugins

Implementing Custom Plugins in MockThis

You can extend the functionality of MockThis by creating custom generators and plugins. This allows you to add new data generation methods or modify existing behavior to suit your specific needs.

Creating a Custom Plugin

To create a custom plugin, you need to implement the MockThisPlugin interface. This interface allows you to register new methods on the MockThisInstance and BlueprintBuilder classes, as well as modify the generated data at various points in the generation process.

Example: ExamplePlugin

Here's an example of a custom plugin called ExamplePlugin:

export class ExamplePlugin implements MockThisPlugin {
    registerMethods(instance: IMockThisInstance, blueprintBuilder: IBlueprintBuilder): void {
        blueprintBuilder.setPluginConfig = (config: Record<string, any>) => {
            blueprintBuilder.getBlueprint().pluginConfig = config;
        };

        instance.setPluginConfig = (config: Record<string, any>) => {
            blueprintBuilder.setPluginConfig(config);
            // Ensure that you return the instance when creating a method on `IMockThisInstance` to enable method chaining
            return instance;
        };
    }
    
    beforeSchemaPrepared(blueprint: IBlueprint, schema: Schema): Schema {
        // Apply transformation logic here
        return schema;
    }   

    afterSchemaPrepared(blueprint: IBlueprint, schemaItems: SchemaItem[]): SchemaItem[] {
        // Apply transformation logic here
        return schemaItems;
    }

    afterDataGenerated(blueprint: IBlueprint, schemas: Schema[]): Schema[] {
        // Apply transformation logic here
        return schemas;
    }
}

declare module 'mockthis' {
    interface IBlueprint {
        pluginConfig: Record<string, any>;
    }
    
    interface IBlueprintBuilder {
        setPluginConfig(config: Record<string, any>): void;
    }

    interface IMockThisInstance {
        setPluginConfig(config: Record<string, any>): this;
    }
}

Explanation

  • registerMethods: This method allows you to add new methods to the MockThisInstance and BlueprintBuilder.
  • afterSchemaPrepared: This method is called after the schema has been processed. You can modify the schema items SchemaItem[].
  • afterDataGenerated: This method is called after the data has been generated. You can modify the data before it is returned.

NOTE: Make sure to extend the necessary interfaces to enable TypeScript support.

Using the Custom Plugin

To use your custom plugin, you need to pass an instance of it to the MockThis function:

const schema = {
  id: Id,
  name: FirstName
};

// Create and configure the MockThis instance with the plugin
MockThis(schema, [new ExamplePlugin()]) // Note: Plugins are applied sequentially, with those defined later in the array having higher precedence.
  .setTotal(1)
  .setPluginConfig({
      prop: "value"
  })
  .asObject()
  .then((data) => {
    console.log(data);
  });

Explanation

  • Pass Plugin to MockThis: When creating the MockThis instance, pass an array of plugins as the second argument.
  • Use New Methods: You can now use the new method added by your plugin (setPluginConfig in this example).

Conclusion

By creating custom plugins and generators, you can extend MockThis to better fit your testing and development needs. Whether you're adding utility methods, modifying generated data, or creating specialized data generators, MockThis provides a flexible framework for mock data generation.

Package Sidebar

Install

npm i mockthis

Weekly Downloads

1,694

Version

2.1.19

License

ISC

Unpacked Size

70 kB

Total Files

4

Last publish

Collaborators

  • tizo