While upgrading Node from v12 to v16, I came across a problem with Angular unit tests where an exception would stop the test run with error Cannot read property 'range' of undefined
.
In this post, I’ll explain the steps I took to identify the root cause of issue and propose potential solutions.
Table of contents
Identifying the root cause
The exception stack trace hints at the root cause of this issue:
(Windows 8.1.0.0): Executed 9 of 846 SUCCESS (0 secs / 1.912 secs)
15 12 2022 15:14:23.895:ERROR [karma-server]: TypeError: Cannot read properties of undefined (reading 'range')
at handleRangeHeaders (D:\Agents\1\_work\424\s\MyApp.Web\node_modules\webpack-dev-middleware\lib\util.js:134:21)
at processRequest (D:\Agents\1\_work\424\s\MyApp.Web\node_modules\webpack-dev-middleware\lib\middleware.js:98:19)
at ready (D:\Agents\1\_work\424\s\MyApp.Web\node_modules\webpack-dev-middleware\lib\util.js:54:12)
at handleRequest (D:\Agents\1\_work\424\s\MyApp.Web\node_modules\webpack-dev-middleware\lib\util.js:185:5)
at D:\Agents\1\_work\424\s\MyApp.Web\node_modules\webpack-dev-middleware\lib\middleware.js:64:7
at new Promise (<anonymous>)
Code language: JavaScript (javascript)
Let’s dig deeper and find out what’s going on the line of code throwing this exception:
// node_modules\webpack-dev-middleware\lib\util.js:134
handleRangeHeaders(content, req, res) {
// assumes express API. For other servers, need to add logic to access
// alternative header APIs
res.setHeader('Accept-Ranges', 'bytes');
if (req.headers.range) {
const ranges = parseRange(content.length, req.headers.range);
Code language: JavaScript (javascript)
It looks like webpack-dev-middleware
is handling requests as part of the test run. When it comes to handling headers on the request, it is falling over with:
Cannot read properties of undefined (reading 'range')
Code language: JavaScript (javascript)
Clearly, Accept-Ranges
headers are not present in some requests performed during our test run.
In order to pinpoint which request is causing this error, let’s output the name of each file during the test run:
// node_modules\webpack-dev-middleware\lib\util.js:134
handleRangeHeaders(content, req, res) {
console.log(req.url);
Code language: JavaScript (javascript)
Run tests again with ng test
and see the file name causing this issue:
/_karma_webpack_/assets/icons/icon-library.svg
15 12 2022 15:14:23.895:ERROR [karma-server]: TypeError: Cannot read properties of undefined (reading 'range')
Code language: JavaScript (javascript)
At this point, we can see the file name and this should hopefully be familiar to you. The chances are your project is somehow trying to load this file from the assets folder using a relative path.
Let’s look at what we can do to fix this issue.
Fix #1 – Configure karma to use proxy
The very first thing I tried to fix this issue was to follow the advice of Ievgen, who had the same problem within an Angular project inside a docker container.
Simply add the following code in karma.conf.js after config.set({
proxies: {
'/assets/': '/base/src/assets/'
},
Code language: JavaScript (javascript)
Ievgen suggests this new rule in karma configuration will point all requests matching /assets/
to the base folder of the project. Unfortunately, this did not work for me even after adjusting the path to match the setup of my project.
Although Ievgen’s solution did not work for me, it put me in the right direction and helped identify the following fixes.
Fix #2 – Stop using relative paths
The first thing I did was to find all the usages of assets
folder in the entire source code.
It turned out some css
files were using relative paths to load some images from the assets folder:
content: url(../../../assets/icons/back-icon.png);
The fix is to define the path from the src folder:
content: url("/src/assets/icons/back-icon.png");
Code language: JavaScript (javascript)
Repeat this for all references of assets folder to ensure all paths correctly identify a file.
Fix #3 – Exclude 3rd party stylesheets during test run
There may be external packages included in the test configuration within angular.json
that are using relative path to assets folder.
// angular.json
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"codeCoverage": true,
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"styles": [
"src/styles.css"
"node_modules/@my-company/web-styles/sass/main.scss"
],
"scripts": [],
"assets": [
"src/assets",
"src/Web.config",
"src/auth.config"
]
}
Code language: JSON / JSON with Comments (json)
As you can see in the above snippet, the test configuration is loading styles from an external package.
Since this package is internally using relative paths to assets, folder the exception is thrown. The solution is to remove this line of code to exclude 3rd party stylesheets during the test run.
I hope you found this post useful, drop a comment below to let me know what you think!