Hone logo
Hone
Problems

Mastering Test Data Generation with Jest Builders

When writing tests, especially for complex applications, creating consistent and realistic test data can be a tedious and repetitive task. Test builders offer a powerful pattern to streamline this process, allowing you to construct objects with default values and easily customize them for specific test scenarios. This challenge will guide you through implementing test builders in TypeScript with Jest.

Problem Description

Your task is to create a UserBuilder class in TypeScript that facilitates the creation of User objects for testing purposes. This builder should allow you to instantiate User objects with default values and selectively override specific properties. You will then use this builder within Jest tests to generate varied User data for different testing needs.

Key Requirements:

  1. User Interface: Define a TypeScript interface named User with at least the following properties:

    • id: string (unique identifier)
    • name: string
    • email: string
    • isActive: boolean
    • createdAt: Date
  2. UserBuilder Class: Create a UserBuilder class that:

    • Has a build() method that returns a fully constructed User object.
    • Provides default values for all properties of the User interface.
    • Offers methods to override individual properties. For example, withId(id: string), withName(name: string), etc. These methods should return the UserBuilder instance itself to allow for chaining.
  3. Jest Tests: Write Jest tests using the UserBuilder to demonstrate its functionality. You should include tests that:

    • Create a default User.
    • Create a User with a specific name and email.
    • Create a User with all properties explicitly set.
    • Test that default values are correctly applied when properties are not overridden.

Expected Behavior:

  • Calling new UserBuilder().build() should produce a User object with sensible default values (e.g., unique ID, placeholder name/email, isActive: true, current date).
  • Calling methods like withName('John Doe').withId('123').build() should produce a User object with the specified name and ID, and default values for other properties.

Edge Cases to Consider:

  • Ensure the generated id is unique for each default User created.
  • The createdAt date should reflect the time the build() method is called.

Examples

Example 1: Creating a default user

// Assume User and UserBuilder are defined elsewhere
const defaultUser = new UserBuilder().build();

// Expected Output (values will vary for id and createdAt):
// {
//   id: 'some-unique-id-1',
//   name: 'Default User',
//   email: 'default@example.com',
//   isActive: true,
//   createdAt: <current Date object>
// }

Example 2: Creating a user with specific properties

const specificUser = new UserBuilder()
  .withName('Jane Doe')
  .withEmail('jane.doe@example.com')
  .build();

// Expected Output (values will vary for id and createdAt):
// {
//   id: 'some-unique-id-2',
//   name: 'Jane Doe',
//   email: 'jane.doe@example.com',
//   isActive: true,
//   createdAt: <current Date object>
// }

Example 3: Creating a user with all properties explicitly set

const allPropertiesUser = new UserBuilder()
  .withId('user-456')
  .withName('Peter Pan')
  .withEmail('peter.pan@neverland.com')
  .withIsActive(false)
  .withCreatedAt(new Date('2020-01-01T10:00:00Z'))
  .build();

// Expected Output:
// {
//   id: 'user-456',
//   name: 'Peter Pan',
//   email: 'peter.pan@neverland.com',
//   isActive: false,
//   createdAt: <Date object for 2020-01-01T10:00:00Z>
// }

Constraints

  • The UserBuilder must be implemented in TypeScript.
  • Jest should be used for writing the tests.
  • The id generation for default users should ensure uniqueness across different builder instantiations within the same test suite run.

Notes

  • Consider using a simple counter or a library like uuid for generating unique IDs. For this challenge, a simple counter is sufficient.
  • Think about how to manage the state within the UserBuilder class to hold the properties being built.
  • The withIsActive and withCreatedAt methods are implied by the requirement to override individual properties and should be implemented similarly to withName.
  • Success is defined by a UserBuilder that is robust, easy to use for creating diverse test data, and well-tested with Jest.
Loading editor...
typescript