Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Puppeteer in headless mode takes empty screenshot of Canvas element, working fine in headfull mode #5352

Closed
anurasin opened this issue Jan 28, 2020 · 8 comments

Comments

@anurasin
Copy link

A clear and concise description of what the bug is.

Puppeteer in headless mode is not able to take the screenshot of a canvas element in my test app. Though while using puppeteer in non-headless mode, it's working perfectly fine.

This is my test scenario,

Press some button, it will invoke WebGL rendering on the canvas element.
(As soon as the rendering is finished source code update a div element value on the web page.)
Test code wait for the div element value to get changed
Take the screenshot of canvas element.
Repeat step 1-3 for some 'n' number of times (each time code will render something on the canvas)
On taking the screenshot, I see that sometimes the first screenshot if blank other times second. It's showing intermittent behavior. It's working fine with headful mode though.

To Reproduce
// My function to take a screenshot
async function captureScreenshotAndCompare(element: ElementHandle, fileName: string, shouldCompare: boolean = true) {
const testFile = Path.resolve(testFolder, ${fileName}.png);

// capture screenshot
const image = await element.screenshot({ path: testFile });

// compare with baseline
if(!shouldCompare) return;

expect(image).toMatchImageSnapshot({
failureThreshold: 0.1,
failureThresholdType: 'percent',
customSnapshotsDir: baselineFolder,
customDiffConfig: { threshold: 0.1 },
customSnapshotIdentifier: () => {
return fileName;
},
});
}

const canvas = await page.$('canvas[id="webgl-canvas"]');
expect(canvas).not.toBeNull();
if(!canvas) return;

await captureScreenshotAndCompare(canvas, 'Image_1', true);
let index: number = 2;

while (index <= maxCount) {
// move to next step
await nextBtn.click();
await page.waitFor(() => document.querySelector('#eventName')!.innerHTML === "rendered" );
await captureScreenshotAndCompare(canvas, Image_${index});
index += 1;
}

Steps to reproduce the behavior:

Expected behavior
The screenshot should be correct both in headless and headful mode.

A clear and concise description of what you expected to happen.

These are all the versions exist in my package.json file.
"puppeteer": "^2.0.0",
"jest-puppeteer": "4.3.0",
"jest-image-snapshot": "2.11.0"
"@types/puppeteer": "^1.19.1",
"@types/jest-environment-puppeteer": "4.3.1",
"@types/expect-puppeteer": "3.3.1",

@anurasin anurasin changed the title Puppeteer in headless mode takes empty screenshot of Canvas element on first render Puppeteer in headless mode takes empty screenshot of Canvas element Jan 28, 2020
@anurasin anurasin changed the title Puppeteer in headless mode takes empty screenshot of Canvas element Puppeteer in headless mode takes empty screenshot of Canvas element, working fine in headfull mode Jan 28, 2020
@leiyu-97
Copy link

leiyu-97 commented May 8, 2021

Same problem, I solved this by replace all <canvas> with <img>

  await page.evaluate(() => {
    function canvasToImage(element: HTMLCanvasElement) {
      const dataUrl = element.toDataURL();
      const image = document.createElement('img');
      image.src = dataUrl;

      const properties = ['width', 'height', 'position', 'left', 'top'] as const;
      properties.forEach(key => image.style[key] = element.style[key])
      image.className = element.className;

      element.parentNode?.insertBefore(image, element);
      element.parentNode?.removeChild(element);
    }

    [].forEach.call(document.getElementsByTagName('canvas'), canvasToImage)
  })
  await page.screenshot({
    path: path.resolve(__dirname, './temp/dashboardPage.png'),
    type: 'png',
  });

@victorcopque
Copy link

@Demonly Thanks, bro!!! You save me 🎉

@yxiong20
Copy link

yxiong20 commented Jan 4, 2022

I tried this workaround and didn't work for me.

First of all I got some simple js errors from node:

`function canvasToImage(element: HTMLCanvasElement) {`
                               ^

SyntaxError: Unexpected token ':'

 `const properties = ['width', 'height', 'position', 'left', 'top'] as const;`
                                                                    ^^

SyntaxError: Unexpected identifier

I'm not familiar with js nor node, maybe just some version issue. I commented out the problematic parts, run it and still it did not capture image from site https://www.kathabineider.de/.

@leiyu-97
Copy link

leiyu-97 commented Jan 5, 2022

@yxiong20 I'm using typescript in the above excample, you can try this instead.

  await page.evaluate(() => {
    function canvasToImage(element) {
      const dataUrl = element.toDataURL();
      const image = document.createElement('img');
      image.src = dataUrl;

      const properties = ['width', 'height', 'position', 'left', 'top'];
      properties.forEach(key => image.style[key] = element.style[key])
      image.className = element.className;

      element.parentNode && element.parentNode.insertBefore(image, element);
      element.parentNode && element.parentNode.removeChild(element);
    }

    [].forEach.call(document.getElementsByTagName('canvas'), canvasToImage)
  })
  await page.screenshot({
    path: path.resolve(__dirname, './temp/dashboardPage.png'),
    type: 'png',
  });

@yxiong20
Copy link

yxiong20 commented Jan 5, 2022

Thanks @Demonly.

In my case I solved the problem by adding "--use-gl=egl" to the args pass to Chrome which seems to work in headless mode.

@stale
Copy link

stale bot commented Jun 23, 2022

We're marking this issue as unconfirmed because it has not had recent activity and we weren't able to confirm it yet. It will be closed if no further activity occurs within the next 30 days.

@stale stale bot added the unconfirmed label Jun 23, 2022
@stale
Copy link

stale bot commented Jul 23, 2022

We are closing this issue. If the issue still persists in the latest version of Puppeteer, please reopen the issue and update the description. We will try our best to accomodate it!

1 similar comment
@stale
Copy link

stale bot commented Aug 30, 2022

We are closing this issue. If the issue still persists in the latest version of Puppeteer, please reopen the issue and update the description. We will try our best to accomodate it!

@stale stale bot closed this as completed Aug 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants