如何使用茉莉花节点对非模块进行单元测试? (与关闭 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 方法。
我有点进退两难
我为 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 方法。