如何使用Jest在Puppeteer中的page.evaluate内部使用导入的函数?

时间:2018-12-07 20:30:57

标签: typescript import module jestjs puppeteer

我有一个TypeScript项目,该项目使用Jest进行单元测试,并且刚刚将Puppeteer添加到组合中,目的是在客户端上运行一些测试。除非我尝试在page.evaluate中使用导入的函数,否则它会很好地工作。

例如,我在HdpiCanvas.test.ts中具有以下内容:

import { createHdpiCanvas } from "./HdpiCanvas";

test("createHdpiCanvas", async () => {
    await page.setViewport({ width: 800, height: 600, deviceScaleFactor: 2 });
    let size = await page.evaluate(() => {
        const canvas = createHdpiCanvas(); // document.createElement('canvas');
        return [canvas.width, canvas.height];
    });
    console.log(size); // [600, 300] for HDPI canvas and [ 300, 150 ] for a regular one
});

在注释为document.createElement('canvas')的情况下,测试运行良好,并记录了[ 300, 150 ]。但是,使用createHdpiCanvas()时,page.evaluate函数会引发以下错误:

Error: Evaluation failed: ReferenceError: HdpiCanvas_1 is not defined
    at __puppeteer_evaluation_script__:2:24

createHdpiCanvas内部的实际HdpiCanvas.ts定义如下:

export function createHdpiCanvas(width = 300, height = 150): HTMLCanvasElement {
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    applyHdpiOverrides(canvas);
    return canvas;
}

及其本身取决于HdpiCanvas.ts中定义的其他功能,例如applyHdpiOverrides

3 个答案:

答案 0 :(得分:2)

您可以在调用evaluate函数之前这样做:

await page.exposeFunction("applyHdpiOverrides",applyHdpiOverrides);
await page.exposeFunction("createHdpiCanvas",createHdpiCanvas);

现在您的窗口将识别这些功能

答案 1 :(得分:2)

Meni Roytenburd建议的解决方案是正确的。如果您不喜欢每个功能都需要单独显示给浏览器的事实,那么想到的唯一想法是,将项目首先转换为单个JavaScript文件,然后将其作为<script>标记注入-就像您在现实生活中一样。

第一步是使用您的软件包生成一个JavaScript文件。有时,这可以单独使用TypeScript编译器来完成,但是也可以使用Webpack之类的工具。

完成后,您可以将捆绑包从Puppeteer中移至客户端:

await page.addScriptTag({ path: 'path/to/the/bundle' });

请记住,这仍然可能会将您的函数公开给全局范围,因此可以通过window访问它们。

  let size = await page.evaluate(() => {
      const canvas = window.createHdpiCanvas();
      return [canvas.width, canvas.height];
  });

  console.log(size); // [ 300, 150 ]

该方法必须处理TypeScript生成的警告的另一个缺点-目前尚不知道createHdpiCanvas上存在window,因此访问window.createHdpiCanvas会导致错误。

答案 2 :(得分:1)

您可能已经发现,page.evaluate失败的原因是因为该函数是在不同的上下文中求值的,并且当前作用域(其中createHdpiCanvas在该函数之外可用)是迷路了。

我一点都不熟悉pupeteer,但是通过查看该函数的文档,您可以尝试一下。它虽然不漂亮,但也许值得尝试:

您可以将createHdpiCanvas作为参数传递,但是函数不能序列化,因此您必须自己做:

page.evaluate((createHdpiCanvasCode) => {
  const createHdpiCanvas = new Function(`return ${createHdpiCanvasCode}`)();
  const canvas = createHdpiCanvas();
  return [canvas.width, canvas.height];
}, createHdpiCanvas.toString());

但是,您必须以相同的方式注入依赖项。