如何使用 Jest 测试 Puppeteer `page` 中的任意 es6 模块?
How to test an arbitrary es6 module in Puppeteer `page` with Jest?
我有一个像这样的 es6 模块
// MyModulue.js
import MySubModule from '../my-sub-module';
const MyFunction => {
// accesses various DOM elements
const element = document.querySelector("#whatever");
// accesses various DOM api's
const styles = window.getComputedStyle(element)
// uses some other imported module
const result = MySubModule.someMethod(styles)
// a ton of other business logic
// ...
return someResult;
}
export default MyFunction;
我想在 Puppeteer page
(即浏览器选项卡)的上下文中测试 MyModule.js
。
这是我的:
await page.setContent(input);
await page.addScriptTag({
path: 'path/to/function/MyModule.js',
type: 'module',
});
const actualFieldLabel = await page.evaluate(async (selector) => {
const field = document.querySelector(selector);
const result = await MyFunction(field); // <=== How can I do this??
return result;
}
expect(actualFieldType).toBe(output);
我怎样才能让它工作?无论我尝试过什么,结果都是 undefined
或抛出异常。
您遇到了一些问题,只是不想让任何其他人遭受这些问题。对我来说,这是其中之一。下面是我的情况的解决方法希望对你也有帮助:
Puppeteer 不是在开玩笑 in their documentation 当他们说 pageFunction
回调是在页面上下文 中执行时 。但是,更有用的说法是 pageFunction
在当前 HTML 文档中执行,并且在 window
/ 全局范围内包含您添加的任何内容 - 因此缺少您未提供的任何内容.
需要进行两个修复:
// MyModulue.js
import MySubModule from '../my-sub-module';
const MyFunction => {
// accesses various DOM elements
const element = document.querySelector("#whatever");
// accesses various DOM api's
const styles = window.getComputedStyle(element)
// uses some other imported module
const result = MySubModule.someMethod(styles)
// a ton of other business logic
// ...
return someResult;
}
export default MyFunction;
// Problem #1: export default didn't expose MyFunction to the global
// scope so it was not accessible from the page.evaluate(() => {...})
// You can fix this by exposing it on the window global like so:
window.MyFunction = MyFunction;
第二个问题是 MyModule.js
依赖于另一个模块,MySubModule.js
,它在 page
中根本不存在,因为我有只叫
await page.addScriptTag({
path: 'path/to/function/MyModule.js',
type: 'module',
});
而不是像这样:
await page.addScriptTag({
path: 'path/to/function/MyModule.js',
type: 'module',
});
await page.addScriptTag({
path: 'path/to/function/my-sub-module.js',
type: 'module',
});
但是,我必须说在我的例子中 MyModule.js
有一个巨大的依赖树,其中包含许多导入的模块,并且其中许多模块导入其他模块。结果,我不得不借助现有的 webpack.config
来添加另一个入口点和输出块。所以我最终的解决方案是为 MyModule
的整个依赖树导入一个 webpack 包,类似于 my-module.bundle.js
,见下文:
await page.setContent(input);
await page.addScriptTag({
type: 'module',
// this is the output of webpack creating a bundle of the dependency tree
// starting at MyBundle.js
path: 'build/my-module.bundle.js',
});
const actualFieldLabel = await page.evaluate(async (selector) => {
const field = document.querySelector(selector);
const result = await MyFunction(field); // <=== How can I do this??
return result;
}
expect(actualFieldType).toBe(output);
这很有效,因为捆绑包具有所有依赖项并且 page.addScriptTag
将它们直接插入 page
!
非常感谢 jest-puppeteer
与 jest
开箱即用!
我有一个像这样的 es6 模块
// MyModulue.js
import MySubModule from '../my-sub-module';
const MyFunction => {
// accesses various DOM elements
const element = document.querySelector("#whatever");
// accesses various DOM api's
const styles = window.getComputedStyle(element)
// uses some other imported module
const result = MySubModule.someMethod(styles)
// a ton of other business logic
// ...
return someResult;
}
export default MyFunction;
我想在 Puppeteer page
(即浏览器选项卡)的上下文中测试 MyModule.js
。
这是我的:
await page.setContent(input);
await page.addScriptTag({
path: 'path/to/function/MyModule.js',
type: 'module',
});
const actualFieldLabel = await page.evaluate(async (selector) => {
const field = document.querySelector(selector);
const result = await MyFunction(field); // <=== How can I do this??
return result;
}
expect(actualFieldType).toBe(output);
我怎样才能让它工作?无论我尝试过什么,结果都是 undefined
或抛出异常。
您遇到了一些问题,只是不想让任何其他人遭受这些问题。对我来说,这是其中之一。下面是我的情况的解决方法希望对你也有帮助:
Puppeteer 不是在开玩笑 in their documentation 当他们说 pageFunction
回调是在页面上下文 中执行时 。但是,更有用的说法是 pageFunction
在当前 HTML 文档中执行,并且在 window
/ 全局范围内包含您添加的任何内容 - 因此缺少您未提供的任何内容.
需要进行两个修复:
// MyModulue.js
import MySubModule from '../my-sub-module';
const MyFunction => {
// accesses various DOM elements
const element = document.querySelector("#whatever");
// accesses various DOM api's
const styles = window.getComputedStyle(element)
// uses some other imported module
const result = MySubModule.someMethod(styles)
// a ton of other business logic
// ...
return someResult;
}
export default MyFunction;
// Problem #1: export default didn't expose MyFunction to the global
// scope so it was not accessible from the page.evaluate(() => {...})
// You can fix this by exposing it on the window global like so:
window.MyFunction = MyFunction;
第二个问题是 MyModule.js
依赖于另一个模块,MySubModule.js
,它在 page
中根本不存在,因为我有只叫
await page.addScriptTag({
path: 'path/to/function/MyModule.js',
type: 'module',
});
而不是像这样:
await page.addScriptTag({
path: 'path/to/function/MyModule.js',
type: 'module',
});
await page.addScriptTag({
path: 'path/to/function/my-sub-module.js',
type: 'module',
});
但是,我必须说在我的例子中 MyModule.js
有一个巨大的依赖树,其中包含许多导入的模块,并且其中许多模块导入其他模块。结果,我不得不借助现有的 webpack.config
来添加另一个入口点和输出块。所以我最终的解决方案是为 MyModule
的整个依赖树导入一个 webpack 包,类似于 my-module.bundle.js
,见下文:
await page.setContent(input);
await page.addScriptTag({
type: 'module',
// this is the output of webpack creating a bundle of the dependency tree
// starting at MyBundle.js
path: 'build/my-module.bundle.js',
});
const actualFieldLabel = await page.evaluate(async (selector) => {
const field = document.querySelector(selector);
const result = await MyFunction(field); // <=== How can I do this??
return result;
}
expect(actualFieldType).toBe(output);
这很有效,因为捆绑包具有所有依赖项并且 page.addScriptTag
将它们直接插入 page
!
非常感谢 jest-puppeteer
与 jest
开箱即用!