Hone logo
Hone
Problems

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: min and max.
  • Inclusive Range: The assertion should consider the min and max values 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 min is greater than max? (For this challenge, assume min will always be less than or equal to max for 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 toBeWithinRange matcher must be registered with Jest.
  • The min and max parameters 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.

Loading editor...
typescript