karma-webpack: Some of my webpack app assets (images, workers) are not being loaded which leads to broken tests

  • Operating System: macOS Big Sur v11.2.1
  • Node Version: 15.10.0
  • NPM Version: 7.5.3
  • webpack Version: 5.24.2
  • karma-webpack Version: 5.0.0

Expected Behavior

I have a number of SVG, PDF, JS workers, and other files in my webpack app. Obviously, it works all good while running the app normally, but when I get to run my mocha test with karma-webpack some of my tests fail due to failures with loading those mentioned asset-like files

Code

  // webpack.config.js

      {
        test: /\.(png|svg)$/,
        include: [resolve(__dirname, 'app', 'assets')],
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]',
        },
      },

So when I run via command line I see errors like:

404: /absolute/var/folders/qm/dx__qpt10rnd8rg2st400l200000gp/T/_karma_webpack_117318/f2462e1d0c87e9b2fd42.worker.js
404: /absolute/var/folders/qm/dx__qpt10rnd8rg2st400l200000gp/T/_karma_webpack_117318/images/logo-black-trademark.svg

I run it using browser to see what’s going on in Dev Tools, and see the same results: Dev Tools

So when I got curious to see what’s in the _karma_webpack_117318 folder, where I assumed it keeps my webpack assets. I found it in my macOS and indeed files are there:

Finder

So these files commons.js and runtime.js are loaded just fine, but not my files. This makes me think that when the browser does GET http://localhost:9876/absolute/var/folders/qm/dx__qpt10rnd8rg2st400l200000gp/T/_karma_webpack_117318/runtime.js it does not directly point to the disk folder. I made a test, by adding few lines of code into runtime.js to see if it will show up in the browser. It didn’t. So I guess there is another memory cache or storage is used to serve the browser.

Maybe the state of _karma_webpack_117318 folder was cached before webpack finished the build, so my assets weren’t cached in time and hence aren’t served to browser?

The general question is… Is this a karma-webpack bug? Or did I miss some config?

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 7
  • Comments: 16 (3 by maintainers)

Commits related to this issue

Most upvoted comments

Oh man, I tried the wildest assumption and it worked out, which is great and also bad because it looks so dirty. So taking my latest approach by owning the webpack {output: {path}} parameter, essentially using the same expression as if karma-webpack would do. I just pass that path into karma files property:

const output = {
  path: join(tmpdir(), '_karma_webpack_') + Math.floor(Math.random() * 1000000),
}

module.exports = config =>
  config.set({
    ....
    webpack: {...webpackDevConfig, output},
    files: [
      {pattern: 'app/index.spec.js'},
      {
        pattern: `${output.path}/**/*`,
        watched: false,
        included: false,
      },
    ],
  })
        

it warns me in the console but it works!

03 03 2021 12:33:18.113:WARN [filelist]: All files matched by "/var/folders/qm/dx__qpt10rnd8rg2st400l200000gp/T/_karma_webpack_852561/**/*" were excluded or matched by prior matchers.

@codymikol this seems like something could be dealt with at the default behavior of this repo. So I guess my bug request is valid. Would it be possible to ensure that by default karma files config get the path to karma-webpack tmp dir where all webpack assets are being stored?

Quick note on this: this currently breaks all usage of wasm + webpack v5 + karma.

Wasm files get included bundled automatically by webpack nowadays, and get copied to the output directory (just like the images discussed here) but karma refuses to serve them with a 404, so the import reliably fails & no tests can run.

The workaround above (pass the webpack output path into to files) works for me too, but it throws an annoying warning before the build (Pattern "/.../*.wasm" does not match any file. and it’s definitely messy.

My project is actually a testing library often used with karma & webpack downstream, so I’m going to have to pass this workaround onwards to all my users too. It’d be amazing if the karma-webpack output files could all be added to files automatically 👍👍👍

O scratch that @eugenet8k , I did just try your solution and it DID work. I had a misconfiguration where the publicPath was temporarily off. This is actually working.

@eugenet8k Thank you for sharing your solution. It helped me. I went further in investigation and now I use Karma plugin to get webpack output and put it into files array. So maybe it can be useful

function KarmaWebpackOutputFramework(config) {
    // This controller is instantiated and set during the preprocessor phase.
    const controller = config.__karmaWebpackController;

    // only if webpack has instantiated its controller
    if (!controller) {
        console.warn(
            "Webpack has not instantiated controller yet.\n" +
            "Check if you have enabled webpack preprocessor and framework before this framework"
        )
        return
    }

    config.files.push({
        pattern: `${controller.outputPath}/**/*`,
        included: false,
        served: true,
        watched: false
    })
}

const KarmaWebpackOutputPlugin = {
    'framework:webpack-output': ['factory', KarmaWebpackOutputFramework],
};

config.plugins.push(KarmaWebpackOutputPlugin);
config.frameworks.push("webpack-output");

The way karma-webpack currently works is that it maps the bundled files created by the webpack build process back to the files specified in the files property of the karma configuration.

At this time I don’t believe there is a way to modify the original list of files (specified in files) that karma is aware of (passed in the karma configuration).

What I’d like to work on for a v6 of this plugin is to make the initial webpack step be the provider of the files to karma. This will require some kind of hook in karma that allows files to be defined by a plugin rather than explicitly. I saw this was in the works https://github.com/karma-runner/karma/pull/3638 , but I haven’t had much time to look it over and I’m not entirely sure that will make this possible.

Hopefully I’ll have some time this week and I can see if there is some simple workaround for making assets work that won’t require pointing back to the temporary build.