Hone logo
Hone
Problems

Implementing toMatchSnapshot in Jest: A Custom Snapshot Matcher

This challenge focuses on building a custom Jest snapshot matcher. Snapshot testing is a powerful technique for verifying that the output of a component or function remains consistent over time, and creating custom matchers extends Jest's capabilities to handle specific testing needs. You'll implement a basic toMatchSnapshot matcher that captures and compares snapshots.

Problem Description

Your task is to create a Jest custom matcher called toMatchSnapshot. This matcher should take a value as input and compare it against a previously saved snapshot. If the value doesn't match the snapshot, the test should fail with a descriptive error message. If the value matches, the test should pass. The matcher should also handle the creation of a new snapshot when one doesn't exist.

Key Requirements:

  • Snapshot Creation: If a snapshot for the given test case doesn't exist, the matcher should create one and mark the test as "snapshot saved."
  • Snapshot Comparison: If a snapshot exists, the matcher should compare the input value against the snapshot.
  • Failure Message: If the values don't match, the matcher should provide a clear error message indicating the mismatch, including the previous snapshot and the current value.
  • TypeScript Compatibility: The solution must be written in TypeScript.
  • Jest Integration: The matcher should seamlessly integrate with Jest's testing framework.

Expected Behavior:

  • When a test runs for the first time, the toMatchSnapshot matcher should create a snapshot file.
  • Subsequent runs of the same test should compare the current value against the saved snapshot.
  • If the values are identical, the test should pass.
  • If the values differ, the test should fail, displaying the previous snapshot and the current value in the error message.
  • The matcher should handle different data types (strings, numbers, objects, arrays) correctly.

Edge Cases to Consider:

  • Snapshot File Not Found: Handle the case where the snapshot file is unexpectedly missing.
  • Data Type Mismatch: Consider how to handle cases where the data type of the input value changes between tests.
  • Large Snapshots: While not a primary focus, be mindful of potential performance implications with very large snapshots.

Examples

Example 1:

Input: "Hello, world!"
Output: (First run) Snapshot saved. (Subsequent runs) Pass
Explanation: The first time the test runs, a snapshot file containing "Hello, world!" is created. Subsequent runs compare the input string to the snapshot and pass if they match.

Example 2:

Input: { name: "John", age: 30 }
Output: (First run) Snapshot saved. (Subsequent runs) Pass
Explanation: Similar to Example 1, but with a JavaScript object. The object is stringified for snapshot comparison.

Example 3:

Input: [1, 2, 3]
Output: (First run) Snapshot saved. (Subsequent runs) Fail (if the array is changed to [1, 2, 4])
Explanation: Demonstrates the failure case when the input array differs from the saved snapshot.

Constraints

  • The matcher must be implemented as a Jest custom matcher.
  • Snapshot files should be stored in a designated directory (e.g., __snapshots__).
  • The matcher should use jest.snapshot() to create and compare snapshots.
  • The matcher should handle potential errors gracefully.
  • The solution should be well-documented and easy to understand.

Notes

  • You'll need to use Jest's expect function to call your custom matcher.
  • Consider using JSON.stringify to serialize complex data structures (objects, arrays) for snapshot comparison. Be aware that the order of keys in objects can affect the snapshot, so consider sorting keys if order is not important.
  • Think about how to provide a meaningful error message when a snapshot mismatch occurs. Include both the previous snapshot and the current value in the message.
  • This is a simplified implementation. Real-world snapshot matchers often include features like diffing tools and options for pruning outdated snapshots. This challenge focuses on the core functionality.
Loading editor...
typescript