笑话找不到“bota”和“atob”

Eri*_*rik 4 javascript built-in jestjs

创建一个笑话测试,例如:

test("btoa", () => {
  expect(btoa("aaa")).toStrictEqual("YWFh");
});
Run Code Online (Sandbox Code Playgroud)

失败了

ReferenceError: btoa is not defined
Run Code Online (Sandbox Code Playgroud)

但是,node确实从节点 16 开始定义btoa,因此如下:

console.log(bota("aaa"))
Run Code Online (Sandbox Code Playgroud)

正确输出YWFh.

我如何配置 jest 才能通过此测试?显然,玩笑测试运行程序中发生了一些事情,无法在当前节点环境中执行,或者正在剥离特定的内置程序,只是我似乎找不到任何有关如何调试或调整它的文档。

更新

有一些解决方法可以通过在“纯js”中手动编写编码或依赖于类似的东西来解决,但我特别感兴趣的是为什么笑话执行结束时无法找到似乎存在于其他环境中的内置函数。

这在其他测试框架(如 mocha)中也运行良好,因此它显然与 jest runner 特别相关。

Rya*_*ale 5

更新

经过大量搜索和绞尽脑汁为什么 btoa/atob节点中可用但在节点中运行的笑话中不可用,我终于弄清楚了。Jest 在vm一个隔离的沙箱环境中运行所有测试。这些btoa/atob方法不会自动暴露在global虚拟机内部的对象上。最好通过例子来解释:

const vm = require('vm');

// this works outside the vm - but for legacy reasons only
// you shouldn't be doing this in the first place
btoa('aaa'); // -> "YWFh"

const context = vm.createContext({});
const code = 'btoa("aaa")';
vm.runInContext(code, context); //-> Uncaught ReferenceError: btoa is not defined
Run Code Online (Sandbox Code Playgroud)

注意:下面描述的答案仍然是“解决方案” - 您需要定义这些方法以在节点中使用,然后需要使用 jest 的globalSetup.


原答案

问题的根源在于 NodeJS 和 Web 浏览器具有不同的 API。例如,当我尝试btoa在节点应用程序中使用时,我收到此弃用通知。

btoa 弃用消息

解决方案的第一部分是您需要提供自己的atob/btoa方法以在 NodeJs 中使用(请参阅此处的示例)。然后你需要使用 jest 的globalSetup配置来使这些可用:

/** Encodes a string as base64 format */
global.btoa = (str: string) => Buffer.from(str, 'binary').toString('base64');

/** Decodes a base64 encoded string */
global.atob = (str: string) => Buffer.from(str, 'base64').toString('binary');
Run Code Online (Sandbox Code Playgroud)

如果您自己做这件事感觉不舒服,可以使用一些库和工具来为您做这件事(jsdom、phantomjs、testing-library)。这些库本质上是在节点环境中复制浏览器 API,以执行运行测试、服务器端渲染等操作。我建议阅读有关测试 Web 框架的代码示例和技术。

  • 我找到了原因 - 请参阅更新的答案。 (2认同)
  • 非常感谢您的回答!我一直在寻找为什么我的一些 Jest 测试失败,实际上互联网上没有任何正确的答案来真正描述根本原因 (2认同)