user3624334
user3624334

Reputation: 619

Jest toMatchSnapshot not throwing an exception

Most of Jest's expect(arg1).xxxx() methods will throw an exception if the comparison fails to match expectations. One exception to this pattern seems to be the toMatchSnapshot() method. It seems to never throw an exception and instead stores the failure information for later Jest code to process.

How can we cause toMatchSnapshot() to throw an exception? If that's not possible, is there another way that our tests can detect when the snapshot comparison failed?

Upvotes: 2

Views: 2331

Answers (3)

Jeremy
Jeremy

Reputation: 1845

This will work! After running your toMatchSnapshot assertion, check the global state: expect(global[GLOBAL_STATE].state.snapshotState.matched).toEqual(1);

Just spent the last hour trying to figure it out for our own tests. This doesn't feel hacky to me either, though a maintainer of Jest may be able to tell me whether accessing Symbol.for('$$jest-matchers-object') is a good idea or not. Here's a full code snippet for context:

const GLOBAL_STATE = Symbol.for('$$jest-matchers-object');

describe('Describe test', () => {
  it('should test something', () => {
    try {
      expect({}).toMatchSnapshot(); // replace with whatever you're trying to test
      expect(global[GLOBAL_STATE].state.snapshotState.matched).toEqual(1);
    } catch (e) {
      console.log(`\x1b[31mWARNING!!! Catch snapshot failure here and print some message about it...`);
      throw e;
    }
  });
});

Upvotes: 5

user3624334
user3624334

Reputation: 619

One, less than ideal, way to cause toMatchSnapshot to throw an exception when there is a snapshot mismatch is to edit the implementation of toMatchSnapshot. Experienced Node developers will consider this to be bad practice, but if you are very strongly motivated to have that method throw an exception, this approach is actually easy and depending on how you periodically update your tooling, only somewhat error-prone.

The file of interest will be named something like "node_modules/jest-snapshot/build/index.js".

The line of interest is the first line in the method:

const toMatchSnapshot = function (received, testName) {
    this.dontThrow && this.dontThrow();   const

    currentTestName = ....

You'll want to split that first line and omit the calling of this.dontThrow(). The resulting code should look similar to this:

const toMatchSnapshot = function (received, testName) {
    //this.dontThrow && this.dontThrow();
    const

    currentTestName = ....

A final step you might want to take is to send a feature request to the Jest team or support an existing feature request that is of your liking like the following: link

Upvotes: 0

Dman
Dman

Reputation: 33

If you run a test (e.g. /Foobar.test.js) which contains a toMatchSnapshot matcher jest by default will create a snapshot file on the first run (e.g. /__snapshots__/Foobar.test.js.snap). This first run that creates the snapshot will pass.

If you want the test to fail you need to commit the snapshot alongside with your test. The next test builds will compare the changes you make to the committed snapshot and if they differ the test will fail.

Here is the official link to the Documentation on 'Snapshot Testing' with Jest.

Upvotes: 0

Related Questions