How to use imported function inside page.evaluate in Puppeteer with Jest?

后端 未结 3 923
走了就别回头了
走了就别回头了 2021-02-20 02:30

I have a TypeScript project that uses Jest for unit tests and have just added Puppeteer to the mix with the intention to run some tests on the client. It works fine, unless I tr

相关标签:
3条回答
  • 2021-02-20 02:41

    The solution suggested by Meni Roytenburd is correct. If you don't like the fact that every function needs to be exposed to the browser separately, the only idea that comes to mind is transpiling your project to a single JavaScript file first and then injecting it as a <script> tag — just like you would in real life.

    The first step would be to generate a single JavaScript file with your bundle. Sometimes this can be accomplished with the TypeScript compiler alone, but a tool like Webpack can be used, too.

    Once it's done, you can move your bundle to the client from within Puppeteer:

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

    Keep in mind this still may expose your functions to the global scope, hence accessing them via window.

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

    Another downside to this approach to having to deal with the warnings generated by TypeScript — at this point it doesn't know that createHdpiCanvas exists on window, so accessing window.createHdpiCanvas will cause an error.

    0 讨论(0)
  • 2021-02-20 02:53

    As you may have figured it out already, the reason why page.evaluate fails is because the function is evaluated in a different context and the current scope (where createHdpiCanvas is available outside of the function) is lost.

    I’m not familiar with pupeteer at all but by looking at the documentation for that function, there may be something you can try. It’s not pretty but perhaps it’s worth trying:

    You could pass createHdpiCanvas as a parameter, however a function is not serialisable so you would have to do it yourself:

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

    However, you would have to inject your dependencies in the same way.

    0 讨论(0)
  • 2021-02-20 03:06

    you can do like this before you invoke the evaluate function :

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

    and now your window will recognize these functions

    0 讨论(0)
提交回复
热议问题