Percy PDF testing
Learn how to visually test PDF documents from within your automated tests using Percy.
Percy turns a PDF document into one snapshot per page. Pass the document to Percy from inside your test. Each page is compared against its baseline like any other Percy snapshot.
Use it to catch layout and rendering changes in generated documents, such as invoices, receipts, policy documents, and statements.
PDF testing is now built into the Percy CLI. The standalone percy-pdf repository required a separate Node.js project and a folder-based configuration. It is no longer the recommended approach and will not receive further updates. See Migrate from the percy-pdf repository.
Prerequisites
- A Percy account with a Percy Web project. If you do not have one, create a project and note its
PERCY_TOKEN. - Percy CLI version 1.32.10 or later.
- For C#, percy-selenium-dotnet version 2.1.6 or later.
- For JavaScript, @percy/sdk-utils version 1.32.10 or later.
Take a PDF snapshot
Step 1: Set your Percy token
Set the PERCY_TOKEN environment variable for your project:
export PERCY_TOKEN=<your-project-token>
Step 2: Call the PDF snapshot method from your test
Read the PDF and pass its contents to Percy along with a snapshot name. No WebDriver is involved, because a PDF is a document rather than a rendered page.
using PercyIO.Selenium;
byte[] pdf = File.ReadAllBytes("payment-receipt.pdf");
Percy.PdfSnapshot("Payment receipt", pdf);
Step 3: Run your tests with percy exec
PDF snapshots are only available while the Percy CLI is running:
percy exec -- <your-test-command>
Percy creates one snapshot per page, named <name> | Page N. A three-page document named Payment receipt produces Payment receipt | Page 1, Payment receipt | Page 2, and Payment receipt | Page 3.
Assert on results within your test
By default, Percy queues the PDF snapshots and your test continues without waiting for comparison results. Set sync to true to block the call until every page has been compared. You can then assert on the returned per-page results.
using PercyIO.Selenium;
using Newtonsoft.Json.Linq;
byte[] pdf = File.ReadAllBytes("payment-receipt.pdf");
JObject? result = Percy.PdfSnapshot("Payment receipt", pdf, new { sync = true });
Assert.NotNull(result);
foreach (JToken page in result!["pages"]!)
{
double diffRatio = (double)page["screenshots"]![0]!["diff-info"]!["diff-ratio"]!;
Assert.Equal(0, diffRatio);
}
PdfSnapshot returns null when Percy is disabled or the call fails, rather than throwing. Check the result before you read the per-page data.
The response reports a diff-info for each page. A change confined to one page of a long document is identified by page, not by the whole file.
If a page fails to compare, that page reports an error while the remaining pages still return their results. Check each page’s result rather than assuming the whole document succeeded or failed together.
Select the pages to compare
Use pages to limit the comparison to specific pages, and excludePages to omit pages. Both accept a single page number, an array of page numbers, or a string range. excludePages is applied after pages.
| Form | Example | Meaning |
|---|---|---|
| Single page | 3 |
Page 3 only |
| List of pages | [1, 2, 5] |
Pages 1, 2, and 5 |
| Range | "1-5" |
Pages 1 through 5 |
| Comma-separated | "1,3,8" |
Pages 1, 3, and 8 |
| Open-ended range | "2-" |
Page 2 through the last page |
For example, to snapshot pages 2 through 10 while skipping page 2:
Percy.PdfSnapshot("Payment receipt", pdf, new {
pages = "2-10",
excludePages = new[] { 2 }
});
Options
Pass these options alongside the snapshot name and document.
| Option | Description | Default |
|---|---|---|
pages |
The pages to snapshot. Accepts a page number, an array of page numbers, or a range string. | All pages |
excludePages |
The pages to omit, applied after pages. Accepts the same forms as pages. |
None |
scale |
The rasterization scale, greater than 0 and up to 5. Reduced automatically if a page would exceed 2000 px. | 2 |
sync |
Whether to wait for comparison results and return them, so you can assert on them in your test. | false |
Standard Percy snapshot options, such as widths and percyCSS, are also accepted.
Migrate from the percy-pdf repository
If you previously used the percy-pdf repository, the following changes apply:
-
Snapshot names are unchanged. Pages are still named
<name> | Page N. If you pass the same base name, Percy matches the new snapshots to your existing approved baselines. -
Regenerate your baselines. Pages captured by the CLI render differently from pages captured with
percy-pdf. Your first CLI build therefore shows diffs against old baselines. Run a baseline build on your default base branch before you rely on comparison results. -
Excluding page 1 and the second-to-last page now works.
percy-pdfcould not exclude either of them. -
No folder structure or config file. The
projects/<project>/<release>/convention and the YAML run-info file are no longer used. You pass documents directly from your test, and Percy manages the baselines.
Things to know
- PDF snapshots require the Percy CLI to be running, so your tests must be started with
percy exec. - A document can be at most 50 MB.
- A single call can snapshot at most 250 pages. For longer documents, narrow the selection with
pagesand make more than one call. - Percy lowers the
scalefor any page that would render larger than 2000 px on a side. At the default scale this affects A3 and legal-size pages. - Percy validates that the data you pass is a PDF document and reports an error if it is not.
Need more support? Contact BrowserStack.
We're sorry to hear that. Please share your feedback so we can do better
Contact our Support team for immediate help while we work on improving our docs.
We're continuously improving our docs. We'd love to know what you liked
We're sorry to hear that. Please share your feedback so we can do better
Contact our Support team for immediate help while we work on improving our docs.
We're continuously improving our docs. We'd love to know what you liked
Thank you for your valuable feedback!