tape-testing / tape

tap-producing test harness for node and browsers
MIT License
5.77k stars 307 forks source link

How do I mock an image import? #566

Closed jbhoot closed 2 years ago

jbhoot commented 2 years ago

In my React project, one of the tests has to import an ESM module, which, in turn, imports an image like:

import img from '../static/images/img.png';

tape of course fails to parse this import.

jest's approach is to replace such assets with empty stubs:

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

where fileMock.js looks like:

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

Does tape have a similar solution?

ljharb commented 2 years ago

Jest has a bespoke approach, as does webpack and other bundlers. The node way to do it for require is to add a require.extensions patch, like babel-register or ts-node do.

You'd do something like tape --require=img-loader path/to/file to achieve this.

However, if you're using native ESM, it completely lacks this capability (ESM loaders are still experimental), so you have no recourse.

Another alternative is not to abuse imports to bring in image paths, and to use a helper function instead, but this is a larger change to your codebase.

jbhoot commented 2 years ago

Another alternative is not to abuse imports to bring in image paths, and to use a helper function instead, but this is a larger change to your codebase.

Yeah. I've got to work with what I got.

jbhoot commented 2 years ago

Okay. I never expected the ESM and CommonJS interop to be so hairy.

After spending hours only to fail at making ts-node + tape work with my frontend (=> ESM) project, I have a newfound respect for the bundlers.

Then I changed my approach to pre-compile typescript files and feed those to tape. So I ditched ts-node. While I made some progress with standalone tape, I'm stuck here now.

May be, I should try to run browserified tests with tape in a (headless) browser instead of on node. I wonder if that would work.

ljharb commented 2 years ago

That wouldn't work either, unless you used a bundler that handled the image imports.

Since you're transpiling - and the tests are thus CJS - an approach like this one https://unpkg.com/images-require-hook@2.1.18/src/index.js would work (in --require, so it's installed before tape tries to run your files)

jbhoot commented 2 years ago

Thank you. That's for next week. I'm closing this issue as you have given enough alternatives.