Jest: "Syntax Error: Invalid or unexpected token" with .png

Created on 21 Jan 2017  ·  33Comments  ·  Source: facebook/jest

I'm trying to test a simple module, but I'm getting this error:

Test suite failed to run

    /home/matheusml/Projects/react-completo/src/assets/images/dribble-logo.png:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){�PNG
                                                                                             ^
    SyntaxError: Invalid or unexpected token

      at transformAndBuildScript (node_modules/jest-runtime/build/transform.js:320:12)
      at Object.<anonymous> (src/components/container/Container.js:4:46)
      at Object.<anonymous> (src/components/App.js:4:44)

This is the test:

import React from 'react';
import renderer from 'react-test-renderer';
import { Router } from 'react-router';

import App from './App';

test('App', () => {
  const component = renderer.create(
    <App />
  );
  let tree = component.toJSON();
  expect(tree).toMatchSnapshot();
});

This is my package.json:

"jest": {
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|svg)$": "./src/config/fileMock.js",
      "\\.(css|scss)$": "identity-obj-proxy"
    }
  }

And this is the fileMock.js:

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

Thanks!

Most helpful comment

I had the same error and resolved it by creating a assetsTransformer.js:

const path = require('path');

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

Then add this to your jest configuration in package.json:
"jest": { "moduleNameMapper": { "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/assetsTransformer.js", "\\.(css|less)$": "<rootDir>/assetsTransformer.js" } },

Source: https://facebook.github.io/jest/docs/webpack.html#content

All 33 comments

@matheusml did you solve this at all? @cpojer I can confirm I'm having this issue too. I have static assets outside my source. i.e. My directory structure looks like:

|-fonts
|-img
\_styles
src
|-components
|-pages
...

My jest config looks similar to the example given in the link:

"jest": {
    "collectCoverageFrom": [ "src/**/*.{js,jsx}" ],
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "tests/__mocks__/fileMock.js"
    }
  }

My test fails when it tries to import the image:

import thumbnail from 'img/thumbnail.png'

I guess its important to note that if I don't include the public directory in moduleDirectories, then i get the error: Cannot find module 'img/thumbnail.png' from 'MyModule.js'

Is this expected? Should it really validate the existence of an import event though the module mapping is already setup? Otherwise I get the same error as above. I haven't tried any other type of import in the name mapper.

I am facing the same issue, I am trying to have reactjs server rendering implemented. Any fix for this.

I have put this in my babelrc and things seem to be working:

{
"presets": ["es2015", "react"]
}

Same type error

SyntaxError: Unexpected token <
      /media/sibin/F_WORK/<path>/<icon-name>.svg:1
      ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<?xml version="1.0" encoding="UTF-8"?>
                                                                                               ^
      SyntaxError: Unexpected token <

I also seem to be having this issue as well. It only happens when I require the png.

({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){�PNG
                                                                                             ^
    SyntaxError: Invalid or unexpected token

Same error as well. Does someone fix it?

Have the same error with .mp3, Nothing helps

Errors like this may also be a result of using a preset with absolute paths set in module name mapper for example. This case however will be fixed in the next release

I had the same error and resolved it by creating a assetsTransformer.js:

const path = require('path');

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

Then add this to your jest configuration in package.json:
"jest": { "moduleNameMapper": { "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/assetsTransformer.js", "\\.(css|less)$": "<rootDir>/assetsTransformer.js" } },

Source: https://facebook.github.io/jest/docs/webpack.html#content

In my case, I didn't realize that <rootDir> is a token supplied by Jest, and assumed it was something I needed to replace. Adding it to the moduleNameMapper entries solved the issue.

I added the assetTransformer.js mentioned by @bombellos. Also followed instructions on Using with webpack. But i still get the same errors.

PNG:

 FAIL  components/__tests__/List.js
  ● Test suite failed to run

    /assets/images/logo-header.png:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){�PNG
                                                                                             ^

    SyntaxError: Invalid or unexpected token

      at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:305:17)
      at Object.<anonymous> (components/PageHeader.js:15:19)
      at Object.<anonymous> (components/Main.js:10:436)

SVG:

 FAIL  ui/Button/__tests__/snapshot.test.js
  ● fixture 'TextAndIcon' snapshots are rendered correctly

    /assets/icons/fontawesome/regular.svg:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                                                                                             ^

    SyntaxError: Unexpected token <

      at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:305:17)
      at Icon (ui/Icon.js:31:17)
      at resolve (node_modules/react-dom/cjs/react-dom-server.node.development.js:2599:14)
      at ReactDOMServerRenderer.render (node_modules/react-dom/cjs/react-dom-server.node.development.js:2746:22)
      at ReactDOMServerRenderer.read (node_modules/react-dom/cjs/react-dom-server.node.development.js:2722:19)
      at Object.renderToStaticMarkup (node_modules/react-dom/cjs/react-dom-server.node.development.js:2991:25)

My folder structure is basically:

<rootDir>
  assets
    *.png, *.svg, ...
  components
    *.js
  ui
    *.js

Apparently, the files are still loaded instead of mocked away, but i have no clue how to debug this.

.babelrc:

{
  "presets": [
    ["es2015", {"modules": false}],
    "react",
    "stage-1",
    ["env", {
      "targets": {
        "browsers": [
          "last 3 versions",
          "> 1%",
          "Firefox ESR",
          "iOS 9"
        ]
      }
    }]

  ],
  "plugins": [
    "react-hot-loader/babel",
    "transform-class-properties",
    "transform-react-jsx-source",
    "glamorous-displayname",
    "wildcard"
  ],
  "env": {
    "development": {
      "plugins": [
        ["transform-runtime", {
          "polyfill": true
        }]
      ]
    },
    "test": {
      "plugins": ["transform-es2015-modules-commonjs"]
    }
  }
}

package.json:

  "jest": {
    "snapshotSerializers": [
      "jest-glamor-react",
      "enzyme-to-json/serializer"
    ],
    "moduleFileExtensions": ["js"],
    "moduleDirectories": ["node_modules"],
    "transform": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/config/jest/assetsTransformer.js"
    }
  },

I am dumb, i had another jest.config.js in my root folder which overwrote the settings in package.json. Although it's not runnning yet, i don't get this particular error anymore.

Got it working. Here are the important bits (please note that i have some additional config due to enzyme 3 with react 16):

.babelrc

{
  "presets": [
    "es2015",
    "react",
    "stage-1",
    "env"

  ],
  "plugins": [
    "react-hot-loader/babel",
    "transform-class-properties",
    "transform-react-jsx-source",
    "glamorous-displayname",
    "wildcard"
  ],
  "env": {
    "development": {
      "plugins": [
        ["transform-runtime", {
          "polyfill": true
        }]
      ]
    }
  }
}

jest.config.js

// this helps: https://github.com/facebook/jest/issues/2081#issuecomment-332406033
module.exports = {
  verbose: true,
  setupFiles: ['./jest.setup.js'],
  snapshotSerializers: ['jest-glamor-react', 'enzyme-to-json/serializer'],
  moduleFileExtensions: ['js', 'jsx'],
  transform: {
    '^.+\\.jsx?$': 'babel-jest',
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
      '<rootDir>/config/jest/assetsTransformer.js',
  },
};

jest.setup.js

import 'raf/polyfill';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

Hope that helps someone.

I was having issues with a svg file. I realized I could mock it with identity-obj-proxy:

    "moduleNameMapper": {
      "\\.(css|scss|svg)$": "identity-obj-proxy"
    },

For anyone looking into this issue @timgivois way works beautifully for me. You have to do install npm install --save-dev identity-obj-proxy to get the necessary dependencies.

  "jest": {
    "moduleNameMapper": {
      ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy"
    }
  }

While the solution by @mbaranovski works, I don't know if his intention was to use it as a transformer. It produces the following output (pay attention to the src attribute):

<img alt="ImgName" height="28" src={ Object { "process": [Function], } } width="112" />

Essentially, it is mapping everything from that module to the place where I required an SVG. Thus, you could get away with that module simply being:

module.exports = {}

The other work-around as stated above is to use identity-obj-proxy.

@magnusart

"jest": {
    "moduleNameMapper": {
      ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy"
    }
  }

it saves my day. Thanks!!.

@mbaranovski It worked just fine when I ran only jest for test. Sadly when I try to run through the react-scripts from create-react-app I get

Out of the box, Create React App only supports overriding these Jest options

Is there a workaround for this ? Or the only solution is to eject create-react-app?

I don't think CRA supports that option. I'm not sure why it wants to close down options, probably a good reason 🙂

/cc @gaearon

Another workaround:

npm i --save-dev jest-transform-stub
"jest": {
  "transform": {
    ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub"
  }
}

I have a react native module has images. I have tried assetsTransformer, identity-obj-proxy and jest-transform-stub. Only assetsTransformer works.

Hi @sibinx7 I fixed that issue by: https://github.com/facebook/jest/issues/2663/#issuecomment-317109798

I solved this by using the jest-react-native package, as all solutions here did not work out for me. Maybe my problem is a different one, because I got problems with PNG files sitting inside the react-native-router-flux-package.

Here some fragment of my package.json file:

{
  // ... 
  "devDependencies": {
    // ...
    "jest": "^23.4.1",
    "jest-react-native": "^18.0.0",
  },
  "jest": {
    "preset": "jest-react-native",
    "verbose": true,
    "modulePathIgnorePatterns": [
      "<rootDir>/node_modules/react-native/Libraries/react-native/",
      "<rootDir>/node_modules/react-native/packager/"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!((jest-)?react-native|react-clone-referenced-element|react-navigation|react-native-router-flux))"
    ]
  },
  // ...
}

Slight modification for handling xml files, in this case using the transform option:

jest.config.js

module.exports = {
    transform: {
        ".+.(xml|bpmn)": "<rootDir>/src/__tests__/transformers/xmlTransformer.ts"
    },
}

/src/__tests__/transformers/xmlTransformer.ts ( may need to modify to your path, is a helper that represents the root directory of the project ).

module.exports = {
    process() {
        return 'module.exports = {};';
    },
    getCacheKey() {
        // The output is always the same.
        return 'xmlTransform';
    },
};

See here for more details.

@magnusart

"jest": {
    "moduleNameMapper": {
      ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy"
    }
  }

it saves my day. Thanks!!.

I took a cue from this and installed babel-jest then I replace identity-obj-proxy with babel-jest

only @eddyerburgh 's solution worked for me.

@magnusart
you save my day, it works fine

I had this png problem after adding ./node_modules/react-native-gesture-handler/jestSetup.js to setupFiles (that was my attempt to resolve the jest issue with react-native-gesture-handler).

I tried https://github.com/facebook/jest/issues/2663#issuecomment-341384494 (@magnusart using identity-obj-proxy), but it broke enzyme for whatever reason (it made enzyme's mock into a symbol rather than a function). Then I tried https://github.com/facebook/jest/issues/2663#issuecomment-369040789 (@eddyerburgh
using jest-transform-stub), but it didn't do anything.

Eventually, I tried https://github.com/facebook/jest/issues/2663#issuecomment-274270387 (@cpojer the webpack solution at the beginning), and that was the only one working for me.

If anyone is getting this error with SVG, probably can use this lib, it worked really well for me https://www.npmjs.com/package/jest-svg-transformer

I only added on my jest.config.ts file this code

transform: { '^.+\\.tsx?$': 'babel-jest', '^.+\\.svg$': 'jest-svg-transformer', },

And the code on this file is this
Captura de Tela 2020-11-09 às 13 17 01

you guys can ignore moduleNameMapper, is just because I'm using custom import with babel

Was this page helpful?
0 / 5 - 0 ratings