Implementing toHaveLength in Jest
Jest's built-in matchers are powerful, but sometimes you need to extend them to handle specific data types or validation scenarios. This challenge asks you to implement a custom Jest matcher called toHaveLength that verifies if an array or string has a specific length. This is a common validation task, and creating custom matchers allows you to make your tests more readable and maintainable.
Problem Description
You need to create a Jest custom matcher named toHaveLength. This matcher should accept a single argument, representing the expected length. The matcher should then compare the length of the input value (which is expected to be either an array or a string) with the expected length. The matcher should return a result indicating whether the actual length matches the expected length.
Key Requirements:
- Type Handling: The matcher must correctly handle both arrays and strings as input.
- Length Calculation: The matcher must accurately determine the length of the input value using the appropriate method (
.lengthfor arrays and strings). - Clear Error Messages: When the assertion fails, the matcher should provide a clear and informative error message indicating the expected length and the actual length.
- Pass/Fail Logic: The matcher should return
trueif the actual length matches the expected length andfalseotherwise.
Expected Behavior:
- When the input value's length matches the expected length, the matcher should pass.
- When the input value’s length does not match the expected length, the matcher should fail, displaying a message like: "Expected array/string to have length ${expectedLength}, but got ${actualLength}".
Edge Cases to Consider:
- Null or Undefined Input: The matcher should handle cases where the input value is
nullorundefinedgracefully, ideally by failing the assertion with a descriptive error message. - Non-Array/String Input: The matcher should handle cases where the input is neither an array nor a string. A failure with a descriptive error message is appropriate.
- Negative Expected Length: While less common, consider how the matcher should behave if a negative expected length is provided. Failing the assertion is a reasonable approach.
Examples
Example 1:
Input: [1, 2, 3, 4] and 4
Output: true
Explanation: The array has a length of 4, which matches the expected length of 4.
Example 2:
Input: "hello" and 5
Output: true
Explanation: The string "hello" has a length of 5, which matches the expected length of 5.
Example 3:
Input: [1, 2, 3] and 5
Output: false
Explanation: The array has a length of 3, which does not match the expected length of 5. The error message should indicate this discrepancy.
Example 4: (Edge Case)
Input: null and 0
Output: false
Explanation: The input is null. The matcher should fail with an appropriate error message.
Constraints
- The matcher must be implemented using TypeScript.
- The matcher should be compatible with Jest's assertion API.
- The matcher should provide clear and helpful error messages.
- The matcher should handle both arrays and strings.
- The matcher should not introduce any performance regressions.
Notes
- You'll need to create a Jest custom matcher factory function.
- Within the factory function, you'll define the matcher logic.
- Use
expect.extendto register your custom matcher with Jest. - Consider using template literals to construct the error messages for better readability.
- Think about how to handle different input types and edge cases to make your matcher robust.