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:
-
userFactoryFunction:- This function should create and return a
Userobject. - The
Userobject 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 tofalse.createdAt: aDateobject, defaulting to the current date and time.
- The factory function should accept an optional argument, an object containing properties to override the default values.
- This function should create and return a
-
productFactoryFunction:- This function should create and return a
Productobject. - The
Productobject should have the following properties:id: a unique string identifier (e.g., UUID).name: a string, defaulting to"Unnamed Product".price: a number, defaulting to0.00.inStock: a boolean, defaulting tofalse.
- The factory function should accept an optional argument, an object containing properties to override the default values.
- This function should create and return a
-
Jest Testing:
- Write unit tests for both
userFactoryandproductFactoryusing Jest. - Tests should cover:
- Creating default instances.
- Creating instances with overridden properties.
- Verifying the types of all properties.
- Ensuring
idis always unique. - Ensuring
createdAtis correctly set for default users.
- Write unit tests for both
Expected Behavior:
- Calling
userFactory()without arguments should produce aUserobject with all default values. - Calling
userFactory({ username: "alice", isActive: true })should produce aUserobject withusernameas"alice",isActiveastrue, and other properties as defaults. - Calling
productFactory()without arguments should produce aProductobject with all default values. - Calling
productFactory({ name: "Laptop", price: 1200.50, inStock: true })should produce aProductobject with these specified values and a defaultid.
Edge Cases:
- Ensure that even when overriding all default properties, the
idis 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
idfor bothUserandProductobjects must be a valid UUID string. You can use a library likeuuidor mock its behavior in tests if necessary. - The
createdAtproperty forUsermust be aDateobject. - The
priceproperty forProductmust 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
UserandProductinterfaces/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
Dateobjects 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.