Custom Jest Matcher: Resolves for Promises
This challenge asks you to create a custom Jest matcher specifically designed to test asynchronous functions that return Promises. Testing Promises directly with standard Jest matchers can be cumbersome; a dedicated resolves matcher simplifies this process, making your tests more readable and maintainable. This is a common need in modern JavaScript development, especially when working with asynchronous operations like API calls or database interactions.
Problem Description
You need to implement a custom Jest matcher named resolves. This matcher will take a Promise as input and verify that it resolves with a specific value. The matcher should behave similarly to Jest's resolves matcher, but you'll be building it from scratch.
What needs to be achieved:
- Create a Jest custom matcher named
resolves. - The matcher should accept a Promise and a
expectedValueas arguments. - The matcher should resolve when the Promise resolves with the
expectedValue. - The matcher should fail when the Promise rejects or resolves with a different value.
- The matcher should provide a clear error message when it fails, indicating the expected and actual values.
Key Requirements:
- The matcher must be asynchronous to handle the Promise resolution.
- The matcher must use
expect(promise).resolvesinternally to verify the promise resolves. - The matcher must handle both successful resolution and rejection of the Promise.
- The matcher should provide a descriptive failure message.
Expected Behavior:
- If the Promise resolves with the
expectedValue, the matcher should pass. - If the Promise rejects, the matcher should fail with a message indicating rejection.
- If the Promise resolves with a value different from the
expectedValue, the matcher should fail with a message indicating the mismatch.
Edge Cases to Consider:
- Promises that resolve immediately.
- Promises that reject immediately.
- Promises that resolve after a delay.
- Promises that never resolve (though Jest should eventually time out).
expectedValuebeing a primitive type (string, number, boolean, etc.).expectedValuebeing an object (consider deep equality checks if needed, though for simplicity, a strict equality check is acceptable).
Examples
Example 1:
Input: promiseThatResolvesWithValue(5)
Output: resolves.with(5) passes
Explanation: The promise resolves with the value 5, which matches the expected value.
Example 2:
Input: promiseThatResolvesWithValue("hello")
Output: resolves.with("world") fails
Explanation: The promise resolves with "hello", but the expected value is "world". The matcher fails with a descriptive error message.
Example 3:
Input: promiseThatRejects()
Output: resolves.with(10) fails
Explanation: The promise rejects, so the matcher fails, indicating that the promise did not resolve.
Constraints
- The matcher must be implemented in TypeScript.
- The matcher should not introduce any external dependencies beyond Jest itself.
- The matcher should be reasonably performant; avoid unnecessary computations.
- The matcher should be compatible with Jest's standard error reporting.
Notes
- You'll need to use Jest's
expectfunction to create the matcher. - Consider using
async/awaitto handle the asynchronous nature of Promises. - Think about how to provide a clear and informative error message when the matcher fails.
- The
promiseThatResolvesWithValueandpromiseThatRejectsfunctions are assumed to be defined elsewhere and return Promises as described in the examples. You don't need to implement them. They are for testing purposes. - Focus on the core logic of the
resolvesmatcher. Error handling and edge case coverage are important, but prioritize a functional and understandable implementation.