Hone logo
Hone
Problems

Mastering Factory Functions with Jest in TypeScript

This challenge focuses on creating and testing factory functions in TypeScript. Factory functions are a powerful design pattern for generating objects, promoting code reusability and maintainability. You'll leverage Jest to write robust tests that ensure your factory functions produce objects with the expected structure and behavior.

Problem Description

You are tasked with creating a set of factory functions for generating User and Product objects. These factory functions should allow for creating default instances as well as instances with specific custom properties. You will then use Jest to write comprehensive unit tests for these factory functions, ensuring they meet all specified requirements.

Key Requirements:

  1. userFactory Function:

    • This function should create and return a User object.
    • The User object should have the following properties:
      • id: a unique string identifier (e.g., UUID).
      • username: a string, defaulting to "guest".
      • email: a string, defaulting to "anonymous@example.com".
      • isActive: a boolean, defaulting to false.
      • createdAt: a Date object, defaulting to the current date and time.
    • The factory function should accept an optional argument, an object containing properties to override the default values.
  2. productFactory Function:

    • This function should create and return a Product object.
    • The Product object should have the following properties:
      • id: a unique string identifier (e.g., UUID).
      • name: a string, defaulting to "Unnamed Product".
      • price: a number, defaulting to 0.00.
      • inStock: a boolean, defaulting to false.
    • The factory function should accept an optional argument, an object containing properties to override the default values.
  3. Jest Testing:

    • Write unit tests for both userFactory and productFactory using Jest.
    • Tests should cover:
      • Creating default instances.
      • Creating instances with overridden properties.
      • Verifying the types of all properties.
      • Ensuring id is always unique.
      • Ensuring createdAt is correctly set for default users.

Expected Behavior:

  • Calling userFactory() without arguments should produce a User object with all default values.
  • Calling userFactory({ username: "alice", isActive: true }) should produce a User object with username as "alice", isActive as true, and other properties as defaults.
  • Calling productFactory() without arguments should produce a Product object with all default values.
  • Calling productFactory({ name: "Laptop", price: 1200.50, inStock: true }) should produce a Product object with these specified values and a default id.

Edge Cases:

  • Ensure that even when overriding all default properties, the id is still generated uniquely.
  • Consider the precision of floating-point numbers for product prices.

Examples

Example 1: userFactory Default

// Assuming userFactory is defined elsewhere
const defaultUser = userFactory();

// Expected Output (simplified, ID will be a UUID):
/*
{
  id: "a1b2c3d4-e5f6-7890-1234-567890abcdef",
  username: "guest",
  email: "anonymous@example.com",
  isActive: false,
  createdAt: <current Date object>
}
*/

Example 2: userFactory with Overrides

// Assuming userFactory is defined elsewhere
const customUser = userFactory({
  username: "bob_smith",
  email: "bob.smith@example.com",
  isActive: true
});

// Expected Output (simplified, ID will be a UUID):
/*
{
  id: "fedcba09-8765-4321-0987-abcdef012345",
  username: "bob_smith",
  email: "bob.smith@example.com",
  isActive: true,
  createdAt: <original Date object from default>
}
*/

Example 3: productFactory with Overrides

// Assuming productFactory is defined elsewhere
const gamingMouse = productFactory({
  name: "ErgoGaming Mouse",
  price: 75.99,
  inStock: true
});

// Expected Output (simplified, ID will be a UUID):
/*
{
  id: "11223344-5566-7788-9900-aabbccddeeff",
  name: "ErgoGaming Mouse",
  price: 75.99,
  inStock: true
}
*/

Constraints

  • The id for both User and Product objects must be a valid UUID string. You can use a library like uuid or mock its behavior in tests if necessary.
  • The createdAt property for User must be a Date object.
  • The price property for Product must be a number.
  • All generated objects must adhere strictly to the defined types.
  • Jest tests should be well-organized and cover all specified scenarios.

Notes

  • You will need to define the User and Product interfaces/types.
  • Consider how you will generate unique IDs. For testing purposes, you might mock a UUID generation function to ensure predictability and determinism.
  • Pay attention to how Date objects behave when passed by reference or value.
  • Think about how to test that default values are applied correctly when only some properties are overridden.
  • The goal is to demonstrate your understanding of factory patterns and effective unit testing with Jest in TypeScript.
Loading editor...
typescript