[karma-server]: TypeError: Cannot read property 'range' of undefined - Angular Unit Testing in CI environment

13,168

Solution 1

Was able to figure it out. We were using node:latest in our .gitlab-ci.yml file and whatever that was pulling down was causing an issue. (It looked to be version 15). So instead of node:latest, we set it to node:14.

Solution 2

I had similar issue after migration to ESLint my project.

I got rid of tsconfig.app.json and tsconfig.spec.json.

Neither of the Node.JS version didn't solve the problem but somehow I found this post https://ievgen.de/2020/11/17/angular-tests-fail-docker/ which is basically saying to add the following line into your karma.conf.js:

proxies: {
  '/assets/': '/base/src/assets/'
},

This solve my problem :-)

Solution 3

It's indeed an issue with karma on node v15. Looks like (for now) it will not be fixed, so downgrading to v14 is the solution: https://github.com/karma-runner/karma/issues/3571

Solution 4

TL;DR

  • In html use relative paths starting with assets/.... In component based CSS use relative paths going one level up: ../assets/...
  • Never, and I mean never use asset paths starting with a slash like /assets this will break your code in some cases
  • Follow the advice below for configuring karma.conf.js because karma does not serve assets and currently karma 5.1.1 with webpack 4.44.2 or some plugin of it crashes with OPs error above

Post Mortem (3)

I deleted my first post mortem twice now, because it was broken and lead me to a post mortem (3) :D

Two things are important: You need to tweak the karma.conf.js as explained in the this SO thread.

Add

    proxies: {
      '/assets/': '/base/src/assets/'
      '/Every-single-image-from-css.png': '/base/src/assets/what-ever-the-path-is/Every-single-image-from-css.png'
    },
    files: [
      { pattern: './src/assets/**', watched: false, included: false, nocache: false, served: true }
    ],

in the config.set({ part, and yes, keep /base/src/assets even if base is nowhere to be found. The second part is the file pattern you need to currently make things work with relative paths. The third part is actually the second entry in the proxies array: List every single resource accessed from css individually :/

Important

ng preprocesses paths somehow strange, the code above will result in your assets referenced from CSS will be duplicated and lying around in root once ng build completes. Very ugly but I don't know a solution to this except using images only from html, which gets processed correctly. The thing I noticed ng serve flattens all urls. So even a css file looking like this

.my-img{
  background: url('../assets/deeply/nested/logo.png');
}

will be served as /logo.png from the built-in webserver. I checked this while looking at the website produced by ng serve and inspecting network calls.

What ever this behaviour is, ng test will die because of this unless you do specify every single image in the proxies part. Using the first proxies entry, e.g. /assets/ is fun but works only when you would use absolute paths from assets, which you should not but is also used, when you reference images from within html, so keep it!

As the ng compilation flattens the urls, this proxy wont work for css references since even in ng test the images from css will be requested from root as /logo.png (stripped of their path). Unfortunately proxies does not support wildcards, otherwise one could write things like /*.png` to something. But currently listing all entries separately seems to be the solution.

Why using absolute paths in assets is a stupid idea

My first result was to actually recommend to use path like /assets/foo.png. Doing this, only the mentioned proxies entry is necessary (but it had to look a bit different). Now I thought i was ok, because ng serve worked, ng test worked and even ng build worked.

But things went south when I wanted to deploy my angular app into a subdirectory. If you do this, I was unable to find any way, meddling around with ng build --base-href '..' and mixing also some --deploy-url into it to make things work.

When you use absolute paths to your assets, never expect to make things work in a subdirectory.

So you might be lucky using my "broken" approach in some instances but I kid you not, you are very likely to save some time following the excellent advise from @programmerinprogress which I repeated above.

Solution 5

If you do not want to change your global node version, you can install a local version and run that instead. This way you will get absolute control over what you are running, regardless of the system you are running on.

yarn add node@^14.15.0 --dev
// package.json
{
  "scripts": {
    "test": "node_modules/node/bin/node node_modules/.bin/ng test"
  }
}

Hope this helps a little! 🙂

Share:
13,168
mvorisek
Author by

mvorisek

Updated on July 06, 2022

Comments

  • mvorisek
    mvorisek almost 2 years

    Our CI/CD pipelines stopped working on the "ng test" job and fails with the following error message:

    [karma-server]: TypeError: Cannot read property 'range' of undefined
        at handleRangeHeaders (/builds/......../node_modules/webpack-dev-middleware/lib/util.js:131:21)
        at processRequest (/builds/......../node_modules/webpack-dev-middleware/lib/middleware.js:98:19)
        at ready (/builds/......./node_modules/webpack-dev-middleware/lib/util.js:53:12)
        at handleRequest (/builds/........../node_modules/webpack-dev-middleware/lib/util.js:182:5)
        at /builds/............/node_modules/webpack-dev-middleware/lib/middleware.js:64:7
        at new Promise (<anonymous>)
        at middleware (/builds/........../node_modules/webpack-dev-middleware/lib/middleware.js:63:12)
    

    Added periods to sub out some specific repo names

    We've never had this error before and it worked fine previously. Also oddly enough, it works perfectly when I run it locally. But when the GitLab runners execute it, it fails. Any help would be appreciated. Thanks!