Unable to locate the source maps for the combination of Karma, Jasmine, TypeScript, and Webpack

In an attempt to test my TypeScript application thoroughly using Karma, Jasmine, and Webpack with code coverage, I have encountered some challenges. While I can successfully run tests, generating coverage seems to be a hurdle. The usage of karma-remap-coverage (https://github.com/sshev/karma-remap-coverage) appears straightforward at first glance.

The process seems promising as some coverage report is generated, but minor adjustments often result in drastic changes in the numbers, preventing the loading of sourcemaps.

Here's a brief overview of the setup:

The src directory consists of 10 .ts files, where only one has an associated .spec file currently.

The contents of the simple spec file are sufficient for testing purposes:

import ComponentToTest from './componentToTest';

describe('ComponentToTest', () => {

  it('should run a test', () => {
      expect(1+1).toBe(2);
  });

  it('should be able to invoke the a method', () => {
      spyOn(ComponentToTest, 'foo').and.callThrough();
      ComponentToTest.foo('testing foo');
      expect(ComponentToTest.foo).toHaveBeenCalled();
  });

});

When paired with my tsconfig.json file, everything works seamlessly:

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6",
    "noImplicitAny": false,
    "sourceMap": true,
    "lib": ["es6", "dom"],
    "experimentalDecorators": true
  },
  "exclude": [
    "node_modules"
  ]
}

and karma.conf.js file:

module.exports = config => config.set({

    frameworks: ['jasmine'],

    mime: { 'text/x-typescript': ['ts','tsx'] },

    // if I make this a generic './src/**/*.ts' it seems to freeze up
    // without throwing any errors or running any tests, but that seems
    // like a separate issue...
    files: [
        './src/lib/componentToTest.ts',
        './src/lib/componentToTest.spec.ts'
    ],

    preprocessors: {
        './src/**/*.spec.ts': ['webpack'],
        './src/**/*.ts': ['webpack', 'sourcemap', 'coverage']
    },

    webpack: {
        devtool: "source-map",
        module: {
            rules: [
                {
                    test: /\.ts?$/,
                    loader: 'ts-loader',
                    exclude: /node_modules/
                }
            ]
        },
        resolve: {
            extensions: [".ts", ".js"]
        }
    },

    webpackMiddleware: {
        quiet: true,
        stats: {
            colors: true
        }
    },

    // add both "karma-coverage" and "karma-remap-coverage" reporters
    reporters: ['progress', 'coverage', 'remap-coverage'],

    // save interim raw coverage report in memory
    coverageReporter: {
        type: 'in-memory'
    },

    // define where to save final remaped coverage reports
    remapCoverageReporter: {
        'text-summary': null,
        html: './coverage/html',
        cobertura: './coverage/cobertura.xml'
    },

    colors: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true

});

To initiate the tests, I use a simple Gulp task:

gulp.task('test', function (done) {
  new Server({
    configFile: __dirname + '/karma.conf.js',
    singleRun: true
  }, (exitCode) => {
     done();
     process.exit(exitCode);
  }).start();
});

Upon execution, the results seem optimistic:

Chrome 58.0.3029 (Mac OS X 10.12.3): Executed 1 of 2 SUCCESS (0 secs / 0.002 secs)
Chrome 58.0.3029 (Mac OS X 10.12.3): Executed 2 of 2 SUCCESS (0.026 secs / 0.004 secs)
[Error: Could not find source map for: "app/src/lib/componentToTest.ts"]
[Error: Could not find source map for: "app/src/lib/componentToTest.spec.ts"]

========================= Coverage summary =========================
Statements   : 43.69% ( 322/737 )
Branches     : 15.7% ( 38/242 )
Functions    : 35.47% ( 61/172 )
Lines        : 44.91% ( 322/717 )
====================================================================

Although progress is evident, there are still a couple of issues hindering complete success:

  1. The inclusion of the .spec.ts file in the coverage report, which should ideally be excluded as it pertains to testing.
  2. The failure to properly generate sourcemaps, indicated by console errors and the inability to access specific file coverage reports.

Despite being on the brink of success, there appear to be some missing links. Any suggestions or simpler solutions would be greatly appreciated!

Update:

An upgrade to Node version 6.11.0 did not yield significant improvements apart from providing additional insights into the situation:

The errors originating from remap-istanbul, such as:

CoverageTransformer.addFileCoverage (/app/node_modules/remap-istanbul/lib/CoverageTransformer.js:148:17)

Furthermore, versions being utilized include Webpack 2.6.1 and TypeScript 2.3.2

Answer №1

After numerous attempts and experimentation over several days, I have finally stumbled upon a solution that seems to work like a charm. While the root cause of the issue from my initial post remains unknown, here is where I stand now. For anyone seeking a straightforward setup involving TypeScript, Karma, Jasmine, and Webpack with coverage, this might prove invaluable.

  • My directory structure and `spec` files have remained unchanged.
  • I made adjustments to my `tsconfig.json` as follows:

    {
      "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "noImplicitAny": false,
        "inlineSourceMap": true, // specified line
        "sourceMap": false, // as well as this one
        "experimentalDecorators": true,
        "lib": ["es6", "dom"]
      },
      "exclude": [
          "node_modules"
      ]
    }
    
  • I transitioned to using `awesome-typescript-loader` instead of `ts-loader`.

  • Finally, my `karma.conf.js` file now appears as below:

    // Code snippet for karma configuration goes here...
    

Key package versions utilized in this setup are:

  • Node 4.2.6 (Although it also functioned with a newer version of Node, staying at this version for other requirements)
  • awesome-typescript-loader 3.1.2
  • istanbul-instrumenter-loader 2.0.0
  • jasmine-core 2.5.2
  • karma 1.6.0
  • karma-chrome-launcher 2.0.0
  • karma-coverage 1.1.1
  • karma-jasmine 1.1.0
  • karma-remap-coverage 0.1.4
  • karma-webpack 2.0.3
  • typescript 2.3.2
  • webpack 2.6.1

Thanks to those who contributed to this setup! It played a significant role in guiding me towards my final resolution: https://github.com/AngularClass/angular-starter/tree/master/config

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I am unable to get JQuery UI Dialog to open on my end

Coding in HTML: <button type="button" class="btn btn-success" style="margin-bottom:14px" id="btnAdd" onclick="modaladdedit('URLToMyController')"><i class="fa fa-plus"> Add New</i></button> HEAD Tag Setup: <link rel=" ...

How is it that the identical group is unable to produce an accurate line chart and its corresponding range chart?

Check out my code snippet on JSFiddle here: https://jsfiddle.net/8yf7j3k6/11/ I am currently working on replicating a similar visualization of my data for a range chart, allowing me to scrub through the chart while utilizing tooltips in the line chart rep ...

Leverage variables in Ajax to retrieve the data of an HTML element

Seeking assistance in converting multiple lines into a single for loop. var optie1 = ""; if($('#form #optie1_check').is(':checked')) { optie1 = $('#form #optie1_naam').val(); } var optie2 = ""; if($('#form #optie2_ch ...

Deserializing concrete types from an abstract list in TypeScript (serialized in JSON.NET)

I'm working with an API that returns an object containing a list of various concrete types that share a common base. Is there a way to automate the process of mapping these items to a specific Typescript interface model-type without having to manually ...

Changing the class name in HTML depending on the size of the screen

I'm attempting to dynamically change the class tag's name when a user visits the page based on the screen size. Below is the code snippet I've used: <!DOCTYPE html> <html> <body onload="changeClass()"> <section class=" ...

Having trouble with npm start causing webpack issues?

I have a small React mini app that I am trying to start with the command npm start - package.json - "scripts": { "start": "node server.js" Everything works fine on Windows, but when I try to start it on Ubuntu, the console throws an error. /var/www/r ...

Chatting with a Discord bot

I am currently working on a Discord bot that will execute specific functions based on the questions asked, most of which are yes or no queries. Upon responding with "yes," a particular function should be performed, while answering "no" would terminate t ...

Having trouble using the Aceternity interface as it keeps giving me a type error

I am facing an issue when trying to integrate the Acternity UI component library with nextjs. The error message I keep encountering is: "Property 'pathLengths' is missing in type '{}' but required in type '{ pathLengths: MotionValu ...

Cannot use a 'string' type expression to index a 'Request<ParamsDictionary, any, any, Query>' type

Currently, my goal is to develop a middleware that can validate the input data in a request. export function validator(schema: Joi.ObjectSchema, key: string) { return function (req: Request, res: Response, next: NextFunction): void { try { Joi ...

The module '...' is encountering an error with the imported value '...'. To resolve this issue, please include a @NgModule annotation

Implementing Angular. Process: Cloned a straightforward UI library to showcase the Angular package standards: https://github.com/jasonaden/simple-ui-lib Developed a new test application with ng new testApp npm link to the simple-ui-lib/dist Lin ...

What is the best way to implement smooth scrolling to an anchor tag from a different page in NextJS?

In my NextJS project, I have two main pages - the Home page and the Leaderboard page. The navigation bar code looks like this: <div className={styles.navItem}> <Link href="/"> <a className={styles.navLinks} onClic ...

Enable button functionality when radio button is selected

Recently, I developed a view that showcases the following code: <ion-view view-title="Training Detail"> <ion-content class="padding"> <ul class="list"> <ion-item class="item item-checkbox item-button ...

Incorporating z-index into weekly rows within the FullCalendar interface

I'm facing an issue where my detail dropdowns on events are being cropped by the following row. Is there a solution to adjust the z-index of each week row (.fc-row) in the monthly view, arranging them in descending order? For example, setting the z-i ...

Uninstalling an Element Using jQuery

There is a requirement to dynamically insert city names into the input field with the ID citiesList. If the value of the input field is empty and the user clicks on the cancel button, then the input should be deleted. However, upon clicking the edit but ...

What is the best way to incorporate React hooks into a for loop?

I am looking to dynamically append a container with a specified number of div elements based on the data in a JSON file. I attempted to include the logic within a for loop, but encountered errors in the process. If you're interested in checking out t ...

The newDragSource() function is not functioning properly within golden-layout version 2.6.0

We are currently in the process of migrating from golden-layout version 1.5.9 to version 2.6.0 within a large Angular 16 production application, albeit slowly and somewhat painfully. Within our application, there exists a dropdown menu that displays the n ...

Utilizing a function within a loop that is nested within another loop

//Exercise 3a: for (var a=1; a<12; a++) { for (var b=00; b<60; b++) { for (var c=00; c<60; c++) { console.log(a + ':' + b + ':' + c + 'AM'); } } } for (var alpha=12; alpha<13; al ...

How can I handle moving to button code-behind when validation fails without relying on Page.IsValid?

Recently, I encountered a challenge with an ASP.NET page that contains both ASP.NET validators and JavaScript checks. As I delved into the button code behind the scenes: protected void Button2_Click(object sender, EventArgs e) { if (Page.IsVal ...

Tips for iterating through a nested JSON response using Vue.js

Recently, I started exploring Vue JS and encountered a challenge while looping through API responses using v-for. Below is the snippet from my code: Get Coins Data <div v-for="coin in coinsData">{{coinsData.data.coins.name}}</div> T ...

Learn how to implement console-like Tail functionality in a web application using the MaterialUI TextField component as the console interface

Issue with Component: Scroll not Updating as new content is added to TextField: https://i.sstatic.net/lgOtn.png I am currently in the process of developing a live console feature within a React application and I wanted to utilize MaterialUI's TextFie ...