如何使用茉莉花节点对非模块进行单元测试? (与关闭 Electron 中的节点集成有关)

How to unit test a non-module with jasmine-node? (related to turning off node integration in Electron)

我有点进退两难

我为 BrowserWindow 打开了 contextIsolation 并关闭了 nodeIntegration,并加载了本地 html 页面。 (正如 Electron 所推荐的那样)。

这个本地 html 页面需要一个节点模块,这会导致崩溃,因为 Electron 无法在 window 中加载节点模块,因为节点已禁用:

main.ts:

import { app, BrowserWindow } from "electron";
import * as path from "path";

function createWindow() {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, "preload.js"),
    },
  });

  mainWindow.loadFile(path.join(__dirname, "../index.html"));
  mainWindow.webContents.openDevTools();
}

(async () => {
  await app.whenReady();
  createWindow();
})();

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
  }
});

index.html:

<body>
  <h1>Hello World!</h1>
  <script src="./renderer.js"></script>
</body>

renderer.js:

export interface A { }

Uncaught ReferenceError: exports is not defined at renderer.js:2

具体崩溃的行是这样的:

Object.defineProperty(exports, "__esModule", { value: true }); 由于 export 语句而存在。

在这种情况下我可以删除导出(并在需要它的其他模块中重新定义接口),但是我无法对我的脚本进行单元测试。

我目前正在使用 jasmine-node 进行单元测试,并且我一直要求我要在顶部测试的模块:

import * as Renderer from "./renderer"

这在 VSCode 中出现了一些关于 Renderer 不是模块的错误。

似乎需要工作(我猜 Node 可以 require 非模块?),但这会导致 IIFE 运行 在我的间谍设置​​之前。

如果Renderer是一个模块,我会这样做:

<script>
   require("renderer.js").main();
</script>

然后我的单元测试会在调用 main 方法之前在模块上设置间谍。但是因为我禁用了 Node,所以我不能在我的 index.html 中 require,我必须内联加载脚本,所以我需要某种 IIFE 来替换主要方法:

(async () => {
   await doSomething();
})();

然后如何使用 Jasmine 对这个非模块进行单元测试?

我的解决方案最终变得很糟糕。

首先,我必须将我的非模块变成一个模块,这样我才能将它导入到我的规范中。

我导出了我的界面并添加了一个主要方法:

export interface A { }
export async function main(): Promise<void> {
    await doSomething();
}

为了避免我之前在禁用 Node 的情况下加载脚本时遇到的崩溃,我将这个 hack 添加到我的 html 页面:

<script>var exports = {};</script> // mutes the "exports not defined" error
<script src="./renderer.js"></script>

然后如果 jasmine 不是 运行,我让我的 IIFE 调用我的主要方法 运行。

(async () => {
    if (!window.jasmine) {
        main();
    }
})();

我的单元测试同时设置间谍并调用导出的 main 方法。