Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I'd like to have my image filenames / paths when using Jest Snapshots

I've started using Jest a lot in a new project, and I am now using the Snapshot functionality of Jest.

In a nutshell, what it does is render your components in a string, store that on disk (as a snapshot, that you can check-in in your repo), and when you run your tests later on it will compare that the snapshot didn't change.

My issue is to do with importing images:

The usual way to deal with that with Jest is to specify a handler for importing those, to mock them and return a random string. That way, your tests won't have to actually load the image, it will just be mocked (otherwise you'll get exceptions, as Node doesn't know how to handle import img from './image.png, only Webpack does via a loader).

In the Jest configuration, you would do something like that:

"jest": {
    "moduleNameMapper": {
      "^.+\\.(png|jpg|jpeg|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/app/__mocks__/fileMock.js",
      "^.+\\.(css|less|scss)$": "identity-obj-proxy"
    },
    [...]
}

As you can see, images (png, jpeg, etc.) are all "resolved" using fileMock, which is simply this:

module.exports = 'test-file-stub';

My issue here is that the mocking goes a bit too far: it always return the same string, which means my snapshots for a component that renders flag look like:

exports[`components - Flag should match the snapshot 1`] = `
<img
    alt="Flag"
    className="image"
    src="test-file-stub" />
`;

(the input was something like <Flag country="fr" />)

What I would like is my snapshot to be rendered as such:

exports[`components - Flag should match the snapshot 1`] = `
<img
    alt="Flag"
    className="image"
    src="/some/path/fr.png" />
`;

I don't believe I'm the only one facing this issue, but on the other hand I couldn't find any resource anywhere solving this.

Thanks!

like image 636
Antoine Jaussoin Avatar asked Oct 20 '16 15:10

Antoine Jaussoin


People also ask

Should you use Jest snapshots?

Using Jest snapshots will help you ensure that your UI changes are deterministic and that you are aware when changes are made. Using that information, you can determine whether the changes were intended or not. You will be using the snapshots you create with Jest to simulate changes in a React application.

What is .snap file in React?

What are Snapshots: A snapshot is nothing but a configuration file defining your component style, UI, and props. The test case will look something like this: __tests__/someComponent.component.test.js. import React from 'react'; import renderer from 'react-test-renderer'; import SomeComponent from '../SomeComponent.

How do I create a snapshot in Jest?

When writing snapshot tests for a React component, you first need to have code in a working state. Then, generate a snapshot of its expected output given certain data. The snapshot tests are committed alongside the component. Jest, a testing framework, will compare the snapshot to the rendered output for the test.

What is the point of snapshot testing?

In snapshot testing, the output of a function is saved in a file (the “snapshot”), and when the test runs, it compares this saved output with the output of the function when it is run each time in the test suite.


2 Answers

Instead of relying on moduleNameMapper you can specify a custom transform where you return the image path instead of its source. A working example can be found under Mocking CSS Modules, pasting it below to make things easier.

// fileTransformer.js
const path = require('path');

module.exports = {
  process(src, filename, config, options) {
    return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
  },
};

and

// package.json (for custom transformers and CSS Modules)
{
  "jest": {
    "moduleNameMapper": {
      "\\.(css|less)$": "identity-obj-proxy"
    },
    "transform": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js"
    }
  }
}
like image 125
Valentin Avatar answered Oct 17 '22 02:10

Valentin


Those having issues with Valentin's suggestion and shallow rendering can try including this line within transform:

\\.(js|jsx)$": "babel-jest"

so that it becomes:

// package.json
{
  "jest": {
    "moduleNameMapper": {
      "\\.(css|less)$": "identity-obj-proxy"
    },
    "transform": {
      "\\.(js|jsx)$": "babel-jest",
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js"
    }
  }
}

The file fileTransformer.js remains the same!

Note: Couldn't comment on his answer as I lack the 50 reputation to comment; this is my first answer here!

like image 41
chiragrtr Avatar answered Oct 17 '22 00:10

chiragrtr