将 html-loader 与 angularJS (v1) 模板和 Jest 一起使用失败

Using html-loader with angularJS (v1) templates and Jest is failing

我有一个由 Rails 提供的 AngularJS (v.1.7) 应用程序。我刚从 Sprockets 转移到 Webpack。 在尝试将我的 Jasmine 测试迁移到 Jest 时。我 运行 遇到了 html-loader 的问题,我正在使用它来将我的指令模板导入到指令中。

对于我导入模板的一个简单指令,Jest 无法加载测试,因为 html-loader 失败并显示错误

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)

我正在遵循建议 in this SO post and from this npm package html-loader-jest。在我的 package.json 中,我添加了以下 jest 配置

  "jest": {
    "moduleFileExtensions": [
      "js",
      "html"
    ],
    "transform": {
      "^.+\.js$": "babel-jest",
      "^.+\.html$": "<rootDir>/jest/support/html_loader.js"
    },
    ...
  }

和支持文件

// jest/support/html_loader.js
const htmlLoader = require("html-loader");
module.exports = {
  process: (src) => htmlLoader(src) 
};

堆栈跟踪将我指向 html-loader(来自 node_modules)

// node_modules/html-loader/node_modules/loader-utils/lib/getOptions.js
function getOptions(loaderContext) {
  const query = loaderContext.query;
...

如果我在 Jest 运行 期间跟踪到此处,我发现此 loaderContext 未定义(如错误报告所示)。

我的问题是...这是使用 htmlLoader 的正确方法吗?如果是这样,我应该期望 loaderContext 是什么?有没有办法让 jest 提供这种价值?或者这不是应该在实际 Webpack 管道之外调用 htmlLoader 的方式。

只有当我通过 jest 运行 时才会出现此问题。 webpack 正确编译应用程序的所有资产。

库版本

html-loader: 1.0.0
webpack: 4.42.1
jest: 25.2.4

代码(为清楚起见)

// 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();
  })
});

好吧,我明白了。似乎当 jest 运行时,它没有传递正确的上下文(正如我上面怀疑的那样)导致 getOptions 调用失败。

解决方案是只为 jest 编写一个非常简单的加载程序,而不会打扰 getOptions。我能够用以下内容替换我的 jest/support/html_loader.js 代码(基本上抄袭自 webpack-contrib/raw-loader.

// jest/support/html-loader.js
module.exports = {
  process: (content, _path) => {
    // escape newlines
    const json = JSON.stringify(content)
          .replace(/\u2028/g, '\u2028')
          .replace(/\u2029/g, '\u2029');
    return `module.exports = ${json};`
  }
};

这基本上是 returns 模板作为导出模板的 js 模块。 replace 似乎在处理换行符。

我希望这可以为其他人节省一些挖掘工作。