Custom toContain Matcher for Jest
Jest's built-in matchers are powerful, but sometimes you need a custom matcher to handle specific scenarios. This challenge asks you to create a custom Jest matcher called toContain that extends Jest's expect to verify if an array or string contains a specific value. This is useful for more readable and maintainable tests when checking for the presence of elements within collections.
Problem Description
You need to implement a custom Jest matcher named toContain. This matcher should work similarly to Jest's built-in toContain but be more flexible and potentially handle different data types gracefully. The matcher should accept a value to search for within the item being tested (which is assumed to be an array or a string).
What needs to be achieved:
- Create a Jest custom matcher named
toContain. - The matcher should accept a single argument: the value to search for.
- The matcher should return
trueif the value is found within the item being tested (array or string). - The matcher should return
falseif the value is not found. - Provide a descriptive failure message when the value is not found.
Key Requirements:
- The matcher must be compatible with Jest's assertion style.
- The matcher should handle both arrays and strings as the item being tested.
- The matcher should perform a strict equality check (
===) for comparison. - The matcher should provide a clear and informative failure message.
Expected Behavior:
When used in a Jest test, the toContain matcher should behave as follows:
expect([1, 2, 3]).toContain(2)should pass.expect([1, 2, 3]).toContain(4)should fail with a message indicating that 4 was not found in the array.expect("hello").toContain("ell")should pass.expect("hello").toContain("world")should fail with a message indicating that "world" was not found in the string.expect([1, "2", 3]).toContain(2)should fail (strict equality).
Edge Cases to Consider:
- The item being tested is not an array or a string. While not strictly required, handling this gracefully (e.g., throwing an error or returning
false) would be good practice. - The value being searched for is
nullorundefined. - Empty arrays or strings.
Examples
Example 1:
Input: expect([1, 2, 3]).toContain(2);
Output: Pass
Explanation: The array [1, 2, 3] contains the value 2.
Example 2:
Input: expect("hello").toContain("world");
Output: Fail
Explanation: The string "hello" does not contain the substring "world". The failure message should indicate this.
Example 3:
Input: expect([1, "2"]).toContain(2);
Output: Fail
Explanation: Strict equality check fails. 2 !== "2".
Constraints
- The matcher must be implemented in TypeScript.
- The matcher should be compatible with Jest versions 25 or higher.
- The matcher should not introduce any external dependencies.
- The matcher should be reasonably performant for typical use cases (e.g., arrays and strings of moderate size).
Notes
- You'll need to create a Jest custom matcher factory function.
- Within the matcher factory, you'll define the matcher's logic and return an object with
match,inverseMatch, and optionallynegateMessagemethods. - The
matchmethod is where the core comparison logic resides. - Consider using template literals to create informative failure messages.
- Think about how to handle cases where the input is not an array or string. A simple check at the beginning of the
matchfunction can prevent unexpected errors.