Mastering Jest Assertions: Building a Custom Matcher
This challenge focuses on understanding and extending Jest's powerful assertion capabilities. You will learn how to create your own custom Jest matchers, allowing you to define specific ways of asserting conditions within your tests. This is a fundamental skill for writing expressive and maintainable tests in TypeScript.
Problem Description
Your task is to create a custom Jest matcher named toBeWithinRange. This matcher should assert that a given number falls within a specified minimum and maximum range (inclusive).
Key Requirements:
- Custom Matcher Creation: Implement a Jest custom matcher function.
- Range Check: The matcher should accept two arguments:
minandmax. - Inclusive Range: The assertion should consider the
minandmaxvalues as part of the valid range. - Clear Failure Messages: Provide informative error messages when the assertion fails, indicating the expected range and the actual value.
- TypeScript Support: The solution should be written in TypeScript, leveraging type safety.
Expected Behavior:
expect(5).toBeWithinRange(1, 10)should pass.expect(1).toBeWithinRange(1, 10)should pass.expect(10).toBeWithinRange(1, 10)should pass.expect(0).toBeWithinRange(1, 10)should fail with a message like: "Expected 0 to be within range [1, 10]."expect(11).toBeWithinRange(1, 10)should fail with a message like: "Expected 11 to be within range [1, 10]."
Edge Cases to Consider:
- What happens if
minis greater thanmax? (For this challenge, assumeminwill always be less than or equal tomaxfor valid inputs, but consider how your matcher might behave or if you'd want to add a validation for this). - Non-numeric inputs for the value or range parameters. (Jest's built-in type checking for matchers will help here, but think about how your custom logic handles unexpected types if it were to bypass initial checks).
Examples
Example 1:
// In your test file:
expect(7).toBeWithinRange(5, 10);
Explanation: The number 7 is between 5 and 10 (inclusive), so the assertion passes.
Example 2:
// In your test file:
expect(3).toBeWithinRange(1, 5);
Explanation: The number 3 is between 1 and 5 (inclusive), so the assertion passes.
Example 3:
// In your test file:
expect(15).toBeWithinRange(1, 10);
Output: Jest will report a test failure with an output similar to:
expect(received).toBeWithinRange(expectedMin, expectedMax)
Expected: <number> 15 to be within range [1, 10].
Received: 15
Explanation: The number 15 is not within the range of 1 to 10 (inclusive), so the assertion fails and provides a descriptive error message.
Constraints
- The
toBeWithinRangematcher must be registered with Jest. - The
minandmaxparameters for the range will be numbers. - The value being tested will be a number.
- The implementation should be idiomatic TypeScript.
Notes
To create custom Jest matchers, you'll need to use Jest's expect.extend API. This API allows you to add new methods to the expect object. Your custom matcher function will receive the received value as its first argument and any additional arguments passed to the matcher as subsequent arguments. You should return an object with pass (boolean) and message (function that returns a string) properties.
Consider how you will define the types for your custom matcher to ensure type safety within your tests. You might need to declare an augmentation for the Jest namespace.