Testing Factory Functions in TypeScript with Jest
Factory functions are a powerful pattern for creating objects with configurable properties, promoting code reusability and encapsulation. This challenge focuses on writing unit tests for TypeScript factory functions using Jest, ensuring they produce the expected objects with the correct configurations. Successfully completing this challenge demonstrates understanding of factory function design and robust testing practices.
Problem Description
You are tasked with creating and testing factory functions in TypeScript. These factory functions will be responsible for creating different types of Product objects based on provided configurations. You need to write Jest tests to verify that these factory functions correctly instantiate Product objects with the specified properties.
What needs to be achieved:
- Define a
Productinterface with propertiesid: string,name: string, andprice: number. - Create two factory functions:
createStandardProductandcreateDiscountedProduct.createStandardProductshould acceptid: string,name: string, andprice: numberas arguments and return aProductobject with these values.createDiscountedProductshould acceptid: string,name: string, andprice: numberas arguments. It should return aProductobject with the same values, but also with an additional propertydiscountApplied: booleanset totrue.
- Write Jest tests to verify that both factory functions:
- Return a
Productobject that conforms to theProductinterface. - Set the
id,name, andpriceproperties correctly based on the input arguments. createDiscountedProductcorrectly setsdiscountAppliedtotrue.
- Return a
Key Requirements:
- Use TypeScript for both the factory functions and the tests.
- Utilize Jest for unit testing.
- Ensure the tests cover both factory functions and their expected behavior.
- Adhere to good testing practices (e.g., clear test descriptions, assertions).
Expected Behavior:
The tests should pass if the factory functions correctly create Product objects with the specified properties and values. Any discrepancies between the expected and actual object properties should result in test failures.
Edge Cases to Consider:
- While not explicitly required, consider how you might handle invalid input (e.g., negative prices) in a real-world scenario. For this challenge, assume the input will always be valid.
Examples
Example 1:
Input: createStandardProduct("123", "Laptop", 1200)
Output: { id: "123", name: "Laptop", price: 1200 }
Explanation: The factory function creates a standard product with the provided ID, name, and price.
Example 2:
Input: createDiscountedProduct("456", "Mouse", 25)
Output: { id: "456", name: "Mouse", price: 25, discountApplied: true }
Explanation: The factory function creates a discounted product with the provided ID, name, and price, and sets the discountApplied flag to true.
Example 3: (Edge Case - Testing for the presence of discountApplied)
Input: createDiscountedProduct("789", "Keyboard", 75)
Output: { id: "789", name: "Keyboard", price: 75, discountApplied: true }
Explanation: Verifies that the `discountApplied` property is present and set to `true` when using the `createDiscountedProduct` factory.
Constraints
- The
Productinterface must be defined. - The factory functions must accept string and number arguments.
- The tests must use Jest assertions to verify the object properties.
- The solution must be written in TypeScript.
Notes
- Think about how to structure your tests to be readable and maintainable.
- Consider using Jest's
expectobject to make assertions about the created objects. - Focus on testing the behavior of the factory functions, not the internal implementation details. This promotes flexibility and allows for future refactoring without breaking the tests.
- You can use
toEqualortoStrictEqualfor comparing objects in your tests.toEqualperforms a deep comparison, whiletoStrictEqualalso checks for the same object identity.