ReportForge.Playwright.Pdf
0.33.2
dotnet add package ReportForge.Playwright.Pdf --version 0.33.2
NuGet\Install-Package ReportForge.Playwright.Pdf -Version 0.33.2
<PackageReference Include="ReportForge.Playwright.Pdf" Version="0.33.2" />
<PackageVersion Include="ReportForge.Playwright.Pdf" Version="0.33.2" />
<PackageReference Include="ReportForge.Playwright.Pdf" />
paket add ReportForge.Playwright.Pdf --version 0.33.2
#r "nuget: ReportForge.Playwright.Pdf, 0.33.2"
#:package ReportForge.Playwright.Pdf@0.33.2
#addin nuget:?package=ReportForge.Playwright.Pdf&version=0.33.2
#tool nuget:?package=ReportForge.Playwright.Pdf&version=0.33.2
ReportForge.Playwright.Pdf
Designed PDF reports for Playwright .NET test runs. One vstest logger covers NUnit, MSTest, and xUnit; three templates cover three audiences: minimal for PR checks, detailed for QA deep dives, executive for stakeholder reviews.
Same product as the npm reporter @reportforge/playwright-pdf, the Python plugin reportforge-playwright-pdf, and the Cypress plugin @reportforge/cypress-pdf. One subscription issues a key for each runner, so .NET gets its own RFNT-… key and its own allowance of 25 machines, separate from the ones your other suites use.
Install
dotnet add package ReportForge.Playwright.Pdf
That is the whole setup. The logger reuses the Node runtime that Microsoft.Playwright already places in your test output directory, and the Chromium that playwright install manages, so there is no npm install and no separate browser download.
Quick start
set RF_LICENSE_KEY=RFNT-XXXX-XXXX-XXXX-XXXX
dotnet test --logger "reportforge;output=reports/run.pdf;template=detailed"
The run summary prints the PDF path when it is written.
Your tests always run in full. A licensing problem, a missing runtime, or an engine error never fails the run: the logger writes one warning and skips the PDF. The dotnet test exit code is decided by your tests alone.
Configuration
Options use the reporter's camelCase names, unchanged. They are passed to the report engine and validated there by the same schema the npm reporter uses, so the two ecosystems cannot drift on what an option means.
Precedence
Lowest to highest, so an inline parameter always wins:
optionsFileJSON: the full options object- Individual logger parameters: this run only
Logger parameters
| Parameter | Effect |
|---|---|
output |
Output path; {date}, {branch}, {status} tokens are expanded |
template |
minimal, detailed, or executive; comma-separate to emit several reports |
optionsFile |
Path to a JSON file holding the full options object |
engine |
Point at a different engine build (development and CI; also RF_ENGINE_PATH) |
dotnet test --logger "reportforge;output=reports/run.pdf;template=executive,detailed"
A missing or malformed optionsFile is reported and ignored rather than failing the run.
Options file
dotnet test --logger "reportforge;optionsFile=rf-options.json"
{
"template": "detailed",
"outputFile": "reports/{date}-{branch}-report.pdf",
"projectName": "Checkout suite",
"watermark": "CONFIDENTIAL",
"slowTestThreshold": 5000,
"live": { "enabled": true },
"notify": {
"slack": { "webhookUrl": "https://hooks.slack.com/services/..." }
}
}
Full option reference: reportforge.org/docs/configuration. .NET specifics: reportforge.org/docs/dotnet.
How your results are reported
| vstest outcome | Report status | Notes |
|---|---|---|
| Passed | passed | |
| Failed | failed | |
| Failed with a framework timeout | timed out | |
| Skipped, None, NotFound | skipped |
Timeouts are matched narrowly, on purpose. Only the test-budget wording that NUnit, MSTest, and xUnit themselves emit counts as a timeout. A Playwright locator that gives up ("Timeout 30000ms exceeded") stays failed, because that is a test failure rather than the framework killing the test. A broad match would misclassify a large share of ordinary failures.
Retries become flaky, with history. Several TestResult events for the same test case are grouped into one entry with ordered attempts. Earlier-failed-then-passed renders as flaky with its full attempt history, matching the Node.js and Python bindings.
Traits become tags. [Category("smoke")] and [Property] traits show as tags in the report, so you can see at a glance which slice of the suite is failing.
Attachments ride the last attempt. For a retried test, the final screenshot is the one the failure card shows, which is the one that reflects the outcome you are reading.
What you get
- Pass, fail, flaky, timeout and skip KPIs, suite breakdown, charts, and a release recommendation
- Failure deep dive with error text, on-device ML failure clustering that groups failures by likely root cause, and embedded screenshot attachments
- Trace archives and videos attached via
TestContext.AddTestAttachmentfeed the defect log's evidence links; pair withevidenceUrlTemplatefor clickable CI links - Standard output and standard error captured per test
- Run history trend and a run-over-run diff showing what newly failed, what was fixed, and what is still failing
- Notifications to Slack, Teams, Discord, or email after the run
- Display redaction and AES-256 PDF encryption when you need them
A dotnet test run drives one browser, so the cross-browser comparison section stays hidden here.
Live runs
Add "live": { "enabled": true } to the options file and the run streams to a shareable watch page as tests finish, the same page the Node.js reporter produces. Rows appear as each test completes.
Streaming is best-effort by design: if the relay is unreachable the run continues and the PDF renders exactly as it would have. Step trees stay Node.js-only today.
CI
- run: dotnet test --logger "reportforge;output=reports/run.pdf;template=detailed"
env:
RF_LICENSE_KEY: ${{ secrets.RF_LICENSE_KEY_DOTNET }}
Store the RFNT-… key as a secret. Every CI machine that runs the suite takes one of the licence's 25 machine slots; a slot frees itself automatically after 30 days without a run, so ephemeral runners recycle on their own.
Troubleshooting
No PDF and one warning about the licence. Expected behaviour when the key is missing, wrong for this runner, or the subscription is inactive. Check that RF_LICENSE_KEY holds the RFNT-… key: a key for another runner is refused with a message naming both sides.
The logger never runs. Confirm the package is referenced by the test project, and that the logger name is spelled reportforge in the --logger string.
Node cannot be found. The logger looks for the runtime Microsoft.Playwright places under your test output (.playwright/node/<rid>/node), then falls back to PATH. Set RF_NODE_PATH if your environment relocates it.
Chromium cannot be found. Set PUPPETEER_EXECUTABLE_PATH to a Chrome or Chromium already on the machine.
License
Elastic License 2.0. A paid subscription is required to generate PDFs: reportforge.org/pricing.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.