-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
[Feature] PDF snapshot tests #19253
Comments
The PDF generally falls outside of the web platform, and Playwright focuses on Web (as of 2022).
As far as I can tell, that's unlikely since these's still a lot to be done for web testing. In general, the suggested work-around would be to use something like PDF.js to render PDF and then test it as a regular website. Hope this helps! |
Thanks! I didn't know about // print.spec.ts
import test, { expect } from '@playwright/test';
test.describe('Print', () => {
let numberOfPages: number;
test.beforeEach(async ({ page, browserName }) => {
test.skip(browserName !== 'chromium', 'Print pdf is only validated in chromium');
await page.goto('http://localhost:15005/print.html');
await page.waitForFunction(() => typeof print=== 'object');
numberOfPages = await page.evaluate(async () => print.numPages);
});
test('no visual regressions of the example slides', async ({ page }) => {
const theCanvas = page.locator('#the-canvas');
for (let i = 0; i < numberOfPages; i++) {
expect(await theCanvas.screenshot()).toMatchSnapshot({ name: `page-${i}.png` });
await page.evaluate(() => print.nextPage());
}
});
}); <!-- print.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<canvas id="the-canvas"></canvas>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/pdf.min.js"></script>
<script type="module">
const pdf = await pdfjsLib.getDocument("./example.pdf").promise;
let currentPage = 1;
await renderPage();
window.print= {
nextPage: async () => {
if (currentPage < pdf.numPages) {
currentPage++;
await renderPage();
}
},
numPages: pdf.numPages,
};
async function renderPage() {
const page = await pdf.getPage(currentPage);
const scale = 1.5;
const viewport = page.getViewport({ scale: scale });
// Support HiDPI-screens.
const outputScale = window.devicePixelRatio || 1;
const canvas = document.getElementById("the-canvas");
const canvasContext = canvas.getContext("2d");
canvas.width = Math.floor(viewport.width * outputScale);
canvas.height = Math.floor(viewport.height * outputScale);
canvas.style.width = Math.floor(viewport.width) + "px";
canvas.style.height = Math.floor(viewport.height) + "px";
const transform =
outputScale !== 1
? [outputScale, 0, 0, outputScale, 0, 0]
: null;
await page.render({ canvasContext, transform, viewport })
.promise;
}
</script>
</body>
</html> |
I found this easier to use: - |
@codeami how did you use it in your Playwright tests? It would be great to get a canonical example and official Playwright team recommendation of PDF snapshot testing with Playwright, using PDFs from URLs. The version that we currently have uses Ideally, we could just use the built-in PDF viewer in Chrome, but it appears that this is not a path that the Playwright team wants to invest in. |
Here's my version of screenshot / snapshot testing with PDF.js, based on the PDF.js docs Hello World example: // HTML template string no-op for VS Code highlighting / formatting
function html(strings: TemplateStringsArray, ...values: unknown[]) {
return strings.reduce((result, string, i) => {
return result + string + (values[i] ?? '');
}, '');
}
test('PDF has screenshot', async ({ page }) => {
// Go to page without Content-Security-Policy header, to avoid CSP
// prevention of script loading from https://mozilla.github.io
await page.goto('about:blank');
await page.setContent(html`
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<canvas></canvas>
<script src="https://mozilla.github.io/pdf.js/build/pdf.mjs" type="module"></script>
<script type="module">
pdfjsLib.GlobalWorkerOptions.workerSrc =
'https://mozilla.github.io/pdf.js/build/pdf.worker.mjs';
try {
const pdf = await pdfjsLib.getDocument(
'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf',
).promise;
const page = await pdf.getPage(1);
const viewport = page.getViewport({ scale: 1.5 });
const canvas = document.querySelector('canvas');
canvas.height = viewport.height;
canvas.width = viewport.width;
await page.render({
canvasContext: canvas.getContext('2d'),
viewport,
}).promise;
} catch (error) {
console.error('Error loading PDF:', error);
}
</script>
</body>
</html>
`);
await page.waitForTimeout(1000);
await expect(page).toHaveScreenshot({ fullPage: true });
}); Also added to |
Oh, it seems like Playwright 1.49.0 introduced rendering of PDFs in page (at least in Chromium), as @dgozman mentions in Changes in Chromium headless in Playwright v1.49 (#33566):
I can confirm that Although I need to figure out how to make it so that it shows the entire PDF and is not cut off... π€ (and no gray background) This is an example snapshot, showing the unfortunate cropping: |
@karlhorky I actually wasted 2 days with the above, the default chrome pdf viewer sets a shadow dom to closed, so you can't interact with anything on the page such as setting the bounding box to capture the whole page as a screenshot, as fullPage: true doesn't work because it's inside an iframe I got as far as injecting JS to set the shadow-root to open theoretically playwright still can't interact with it, and returns a pretty limited DOM when i query it. But when I pause the test and inspect the page I see shadow-dom set to open so unsure what's really going on, feel free to go down the rabbit whole with this... Going to implement the solutions shared above instead of wasting more time.
|
Hi friends πββοΈ. Thanks for creating this valuable project!
I'm looking for ways to test my generated PDF file with decktape using snapshot tests. I would expect such a thing to be possible with playwright since underlying browsers generally support displaying PDF files.
However, I ran into this issue: #6091, which is closed as out-of-scope. I have two questions:
The text was updated successfully, but these errors were encountered: