I've got an AngularJS (v.1.7) app served by Rails. I just moved from Sprockets to Webpack.
While trying to migrate my Jasmine tests to Jest. I ran into an issue with html-loader
which I'm using to import my directive templates into the directive.
For one simple directive where I import the template, Jest fails to load the test because the html-loader
fails with the error
TypeError: Cannot read property 'query' of undefined
1 | const htmlLoader = require("html-loader");
2 | module.exports = {
> 3 | process: (src) => htmlLoader(src)
| ^
4 | };
5 |
at getOptions (node_modules/html-loader/node_modules/loader-utils/lib/getOptions.js:6:31)
I was following recommendations in this SO post and from this npm package html-loader-jest. In my package.json
, I've added the following jest
config
"jest": {
"moduleFileExtensions": [
"js",
"html"
],
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.html$": "<rootDir>/jest/support/html_loader.js"
},
...
}
And the support file
// jest/support/html_loader.js
const htmlLoader = require("html-loader");
module.exports = {
process: (src) => htmlLoader(src)
};
The stacktrace points me to html-loader
(from node_modules)
// node_modules/html-loader/node_modules/loader-utils/lib/getOptions.js
function getOptions(loaderContext) {
const query = loaderContext.query;
...
If I trace into here during the Jest run, I find this loaderContext
undefined (as the error reports).
My question is... is this the correct way to use this htmlLoader
? If so, what should I expect loaderContext
to be? Is there a way to get jest to provide that value? Or is this not the way the htmlLoader
is supposed to be called outside of the actual Webpack pipeline.
This problem only happens when I'm running via jest
. webpack
properly compiles the all assets for the app.
library versions
html-loader: 1.0.0
webpack: 4.42.1
jest: 25.2.4
code (for clarity)
// mailer.js
import angular from "angular";
import ngInject from "@js/ng-inject";
import template from "./index.html";
const mailer = ngInject(function () {
return {
restrict: "E",
scope: {
text: "@",
},
template: template,
};
});
angular.module("app-directives").directive("mailer", mailer);
<!-- index.html -->
<a>{{text}}</a>
// mailer.test.js
import expect from "expect";
import "./mailer";
describe("app-directives.mailer", function () {
it("works", () => {
expect(true).toBeTruthy();
})
});