Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest snapshot test failing due to react navigation generated key

My Jest test is failing because of the timestamp in the key being different every time the test is run:

 FAIL  ./App.test.js
  ✕ renders without crashing (72ms)

  ● renders without crashing

expect(value).toMatchSnapshot()

Received value does not match stored snapshot 1.

- Snapshot
+ Received

@@ -347,11 +347,11 @@
              "index": 0,
              "isTransitioning": false,
              "key": "StackRouterRoot",
              "routes": Array [
                Object {
-                 "key": "id-1519567169760-0",
+                 "key": "id-1519567814666-0",
                  "routeName": "Menu",
                },
              ],
            },
          }

Here is my App.js file:

import React from 'react';
import { StackNavigator } from 'react-navigation';
import Menu from './components/Menu';
import List from './components/List';

const RootStack = StackNavigator(
  {
    Menu: {
      screen: Menu,
    },
    List: {
      screen: List,
    },
  },
  {
    initialRouteName: 'Menu',
  }
);

export default class App extends React.Component {
   render() {
     return <RootStack />;
   }
}

Here is my test file:

import React from 'react';
import App from './App';

import renderer from 'react-test-renderer';

test('renders without crashing', () => {
  const rendered = renderer.create(<App />).toJSON();
  expect(rendered).toBeTruthy();
  expect(rendered).toMatchSnapshot();
});

Is it possible override the key value or is there a way to ignore key when the test runs?

like image 962
Graeme MacFarlane Avatar asked Jan 28 '23 14:01

Graeme MacFarlane


2 Answers

Newer versions of jest also support property matchers which allow certain parts of the snapshot to be evaluated using a matcher instead of requiring the entire snapshot to be identical.

Here is an example showing a few different approaches to using this feature to solve OP's question:

it('Should ignore route keys in snapshot', () => {
  const testObject = {
    index: 0,
    isTransitioning: false,
    key: 'StackRouterRoot',
    routes: [
      {
        key: `id-${Date.now()}-0`,
        routeName: 'Menu',
      },
      {
        key: `id-${Date.now()}-1`,
        routeName: 'Splash',
      },
    ],
  };

  expect(testObject).toMatchSnapshot({
    routes: [
      {
        key: expect.stringMatching(/id-\d+?-\d/),
        routeName: 'Menu',
      },
      {
        key: expect.stringMatching(/id-\d+?-\d/),
        routeName: 'Splash',
      },
    ],
  }, 'Explicitly list all routes');

  expect(testObject).toMatchSnapshot({
    routes: expect.arrayContaining([
      expect.objectContaining({
        key: expect.stringMatching(/id-\d+?-\d/),
      }),
    ]),
  }, 'Match any route');
});

Which produces the following snapshots:

exports[`<App /> Should ignore route keys in snapshot: Explicitly list all routes 1`] = `
Object {
  "index": 0,
  "isTransitioning": false,
  "key": "StackRouterRoot",
  "routes": Array [
    Object {
      "key": StringMatching /id-\\\\d\\+\\?-\\\\d/,
      "routeName": "Menu",
    },
    Object {
      "key": StringMatching /id-\\\\d\\+\\?-\\\\d/,
      "routeName": "Splash",
    },
  ],
}
`;

exports[`<App /> Should ignore route keys in snapshot: Match any route 1`] = `
Object {
  "index": 0,
  "isTransitioning": false,
  "key": "StackRouterRoot",
  "routes": ArrayContaining [
    ObjectContaining {
      "key": StringMatching /id-\\\\d\\+\\?-\\\\d/,
    },
  ],
}
`;

Another jest feature I came across recently that might help here is custom snapshot serializers. Using this feature I think you could add a serializer for route objects that would remove the key or replace it with a static value before it is serialized. I can't provide an example right now as I have not yet used this feature, but it seemed worth mentioning.

like image 91
Eliot Avatar answered Apr 30 '23 07:04

Eliot


You can mock the data that is non-deterministic. https://facebook.github.io/jest/docs/en/snapshot-testing.html#tests-should-be-deterministic

For example, if you have a Clock component that uses Date.now(), the snapshot generated from this component will be different every time the test case is run. In this case we can mock the Date.now() method to return a consistent value every time the test is run:

Date.now = jest.fn(() => 1482363367071);

Now, every time the snapshot test case runs, Date.now() will return 1482363367071 consistently. This will result in the same snapshot being generated for this component regardless of when the test is run.

like image 23
sme Avatar answered Apr 30 '23 05:04

sme