karma-runner / karma

Spectacular Test Runner for JavaScript
http://karma-runner.github.io
MIT License
11.93k stars 1.71k forks source link

Karma do not execute unit test if Automerge package (WebAssembly) is used #3836

Closed kheniparth closed 11 months ago

kheniparth commented 1 year ago

[CONTEXT]: I have listed all the findings in the StackOverflow question if someone would like to learn about the history/context: https://stackoverflow.com/questions/75563118/karma-jasmine-do-not-identify-all-angular-unit-tests-when-using-automerge-packag

[PROBLEM]: If I directly use the Automerge package in a component then its respective test won't get executed.

[REPRODUCE]: Here is the stackblitz URL: https://stackblitz.com/edit/node-mcrcay?file=my-workspace%2Fsrc%2Fapp%2Fapp.component.ts

To reproduce the issue uncomment this code in the app.component.ts and run ng test command.

const test = from({
  test: 'test',
});

You will not notice any unit tests getting executed/listed in the Karma runner like this: image

But if you want to see the working unit tests then keep the code commented in the app.comment.ts and then run ng test, you will see 3 unit tests for the AppCompoennt in the Karma runner. image

Any help is much appreciated :)

iamsank8 commented 11 months ago

Can you try to execute the code in ngOnInit instead of constructor?

abdojulari commented 11 months ago

To address this issue, we will use a polyfill. A polyfill is a piece of code that implements a feature on web browsers that do not natively support it.

To add the necessary code in your polyfills.ts file, include the following:

import '@automerge/automerge';
import '@automerge/automerge-wasm' // this solves it all

This addition resolves the problem with browsers not being able to handle .wasm files. However, if you need to handle complex requirements such as processing time, you can set up a preprocessor. You can achieve this by using a custom webpack configuration. In an Angular project, webpack runs under the hood without the need to create it, but you can create a webpack.config.js file for customization purposes:

Create a file webpack.config.js

module.exports = {
  devtool: 'inline-source-map',
  experiments: {
    asyncWebAssembly: true,
  },
  target: "web",
  mode: "development", // or production
  performance: {
    hints: false,
    maxEntrypointSize: 512000,
    maxAssetSize: 512000,
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader',
      },
      {
        test: /\.html$/,
        loader: 'raw-loader',
        exclude: /\.async\.(html|css)$/
      },
      {
        test: /\.wasm$/,
        type: 'webassembly/experimental', // Ensure the Wasm files are handled correctly
        use: [
          {
            loader: 'wasm-loader',
            options: {
              esModule: true,
            },
          },
        ],
      },
      {
        test: require.resolve('./src/main.ts'),
        use: 'imports-loader?wrapper=window',
      }
    ],
  },
  resolve: {
    extensions: ['.ts', '.js', '.wasm'],
  },
};

In the above code, I enhanced the performance and handling of execution time by defining a custom webpack configuration. If you are not dealing with specific performance requirements, the default polyfill.ts file with addition of imports should work perfectly fine.

In your karma.conf.js file, make the following changes:

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular','webpack'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-webpack'),
      require('@angular-devkit/build-angular/plugins/karma'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage'),     
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    jasmineHtmlReporter: {
      suppressAll: true // removes the duplicated traces
    },
    coverageReporter: {
      dir: require('path').join(__dirname, './coverage/automerge-example'),
      reporters: [
        { type: 'html' },
        { type: 'text-summary' }
      ]
    },
    preprocessors: {
      'src/**/*.spec.ts': ['webpack'],
    },
    webpack: require('./webpack.config.js'),
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    restartOnFileChange: true,
  });
};

Note: When requiring webpack.config.js, I instructed Karma to use webpack for preprocessing, specifically for the spec.ts extension. Additionally, make sure to install karma-webpack and wasm-loader if you need to handle performance and other related aspects.

kheniparth commented 11 months ago

Closing this issue because the solution suggested by @abdojulari works perfectly.