question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Are literal values deliberately allowed as property matchers in toMatchSnapshot()?

See original GitHub issue

The docs say here:

For these cases, Jest allows providing an asymmetric matcher for any property. These matchers are checked before the snapshot is written or tested, and then saved to the snapshot file instead of the received value:

and here:

The optional propertyMatchers argument allows you to specify asymmetric matchers which are verified instead of the exact values.

Both only refers to asymmetric matchers. But if I do this everything works:

expect({ p: 'hi' }).toMatchSnapshot({ p: 'hi' });

Even if I’m not using an asymmetric matcher, but using a literal value, the expectation passes and the snapshot is written correctly.

So the question is: Is the fact that the value of a property matcher works with a literal value instead of an asymmetric matcher planned, even if the docs doesn’t say anything about, or is it a coincidence and my code could be suddenly break and destroy all life as we know it?

I am asking this here because I think this is a design question or perhaps it shows that docs are incomplete. If this was not appropriate I apologize and understand if it gets closed.

Here a little context. Similar to #6455 (and maybe until #6528), it is not straightforward to put an asymmetric matcher on a nested property of an object or on an object inside and array. The workaround I’m using is something like this:

test('foo', () => {
    // The `anArray` property could be very large. Every object inside
    // has an `id` property with an autogenerated value.
    const obj = { anArray: [{ id: 'autogenerated', p: 1 }] };

    expect(obj).toMatchSnapshot({
        anArray: obj.anArray.map(a => ({
            ...a, // this "copies" every other property so will be written
                  // in the snapshot and compared the next time.
            id: expect.any(String),
        })),
    });
});

In that example the anArray property is using a literal value (the array returned from map) and the spreading of every property of every element in ...a. Nonetheless, and beyond this particular example, the question holds in general.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:7 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
rickhanloniicommented, Jul 30, 2018

Is the fact that the value of a property matcher works with a literal value instead of an asymmetric matcher planned

Great question @InExtremaRes. The short answer is yes and we should update the docs.

For some background, the proposal was that only the property matchers would be checked, but the whole object would be merged. This would allow you to specify overrides for certain values in the object, as in:

const user = {
  id: '58e2a3fc05649b0f00497fed',
  name: 'Mike',
};

expect(user).toMatchSnapshot({ id: 'generated-id' });

exports[`something 1`] = `
Object {
  "id": "generated-id",
  "name": "Mike",
}
`;

During implementation we realized this was confusing/unexpected behavior and that if you want to override what’s in the snapshot you should use a matcher:

expect(user).toMatchSnapshot({ id: expect.any(String) });

exports[`something 1`] = `
Object {
  "id": Any<String>,
  "name": "Mike",
}
`;

When it came to what to do for non-matcher properties (if they weren’t going to override) it seemed to make sense to match them exactly, (also much easier to implement) so the docs should be updated to say:

values will be matched exactly if not provided as a matcher

By the way, using custom asymmetric matchers, the above example can be written as:

expect(user).toMatchSnapshot({ id: expect.objectId() });

exports[`something 1`] = `
Object {
  "id": Any<ObjectID>,
  "name": "Mike",
}
`;

Which is probably the best case in terms of both readability and asserting values.

0reactions
github-actions[bot]commented, May 12, 2021

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Use property matchers in snapshot tests with Jest - Egghead.io
In this lesson, we'll see an example of an object with non-deterministic values, and use property matchers in .toMatchSnapshot() to verify types ...
Read more >
Expect - Jest
Instead of literal property values in the expected object, you can use matchers, expect.anything() , and so on. For example, let's say that...
Read more >
what is the expect statements in assertions? - Personal Injury Solicitor
toMatchSnapshot() assertions in the test file, 'does not drink something ... of literal property values in the expected object, you can use matchers, ......
Read more >
Hashrocket - Today I Learned - TIL @ Hashrocket
You can deliberately create an object with no properties by making sure ... There is a built-in value which happens to match what...
Read more >
Creating snapshots in Jest for testing React applications
toMatchSnapshot() creates a snapshot if it does not exist, saves it, ... exports[`Jest Snapshot testing suite matches snapshot 1`] = ` <div ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found