Verify Headless Browsers
April 9, 2026 ยท View on GitHub
Extends Verify to allow verification of Web UIs using headless browsers.
See Milestones for release notes.
Sponsors
Entity Framework Extensions
Entity Framework Extensions is a major sponsor and is proud to contribute to the development this project.
Developed using JetBrains IDEs
NuGet
- https://nuget.org/packages/Verify.Playwright
- https://nuget.org/packages/Verify.Puppeteer
- https://nuget.org/packages/Verify.Selenium
Playwright Usage
Verification of Web UIs via Playwright.
Enable
Enable VerifyPlaywright once at assembly load time:
[ModuleInitializer]
public static void InitPlaywright() =>
VerifyPlaywright.Initialize(installPlaywright: true);
Instantiate browser
// wait for target server to start
await SocketWaiter.Wait(port: 5000);
playwright = await Playwright.CreateAsync();
browser = await playwright.Chromium.LaunchAsync();
Page test
The current page state can be verified as follows:
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
await Verify(page);
With the state of the element being rendered as a verified files:
<!DOCTYPE html><html lang="en"><head>
<meta charset="utf-8">
<title>The Title</title>
<link href="https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="jumbotron">
<h1 class="display-4">The Awareness Of Relative Idealism</h1>
<p class="lead">
One hears it stated that a factor within the logical radical priority embodies the
key principles behind the best practice marginalised certification project. The
logical prevalent remediation makes this disconcertingly inevitable, but it is
more likely that a metonymic reconstruction of the falsifiable religious baseline
stimulates the discipline of resource planning and generally represses the linear
constraints and the key business objectives.
</p>
<a id="someId" class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>
</div>
</body></html>
PlaywrightTests.PageUsage.01.verified.png:
PageScreenshotOptions
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
await Verify(page)
.PageScreenshotOptions(
new()
{
Quality = 50,
Type = ScreenshotType.Jpeg
});
Page screenshot only option
Passing true to screenshotOnly will avoid producing HTML, instead only producing the Page image
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
await Verify(page)
.PageScreenshotOptions(
new()
{
Quality = 50,
Type = ScreenshotType.Jpeg
},
screenshotOnly: true);
Element test
An element can be verified as follows:
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
var element = await page.QuerySelectorAsync("#someId");
await Verify(element!);
With the state of the element being rendered as a verified files:
Learn more
PlaywrightTests.ElementUsage.01.verified.png:
ElementScreenshotOptions
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
var element = await page.QuerySelectorAsync("#someId");
await Verify(element!)
.ElementScreenshotOptions(
new()
{
Quality = 50,
Type = ScreenshotType.Jpeg
});
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
var element = await page.QuerySelectorAsync("#someId");
await Verify(element!)
.ElementScreenshotOptions(
new()
{
Quality = 50,
Type = ScreenshotType.Jpeg
},
screenshotOnly: true);
Element test using ILocator
An element can be verified as follows:
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
var element = page.Locator("#someId");
await Verify(element);
With the state of the element being rendered as a verified files:
Learn more
PlaywrightTests.LocatorUsage.01.verified.png:
LocatorScreenshotOptions
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
var element = page.Locator("#someId");
await Verify(element)
.LocatorScreenshotOptions(
new()
{
Quality = 50,
Type = ScreenshotType.Jpeg
});
Locator screenshot only option
Passing true to screenshotOnly will avoid producing HTML, instead only producing the Locator image
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
var element = page.Locator("#someId");
await Verify(element)
.LocatorScreenshotOptions(
new()
{
Quality = 50,
Type = ScreenshotType.Jpeg
},
screenshotOnly: true);
Puppeteer Usage
Verification of Web UIs via Puppeteer
Enable
Enable VerifyPuppeteer once at assembly load time:
[ModuleInitializer]
public static void InitPuppeteer() =>
VerifyPuppeteer.Initialize();
Instantiate browser
// wait for target server to start
await SocketWaiter.Wait(port: 5000);
var fetcher = new BrowserFetcher(SupportedBrowser.Chrome);
await fetcher.DownloadAsync();
browser = await Puppeteer.LaunchAsync(
new()
{
Headless = true
});
Page test
The current page state can be verified as follows:
var page = await browser.NewPageAsync();
page.Viewport.Width = 1024;
page.Viewport.Height = 768;
await page.GoToAsync("http://localhost:5000");
await Verify(page);
With the state of the element being rendered as a verified files:
<!DOCTYPE html><html lang="en"><head>
<meta charset="utf-8">
<title>The Title</title>
<link href="https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="jumbotron">
<h1 class="display-4">The Awareness Of Relative Idealism</h1>
<p class="lead">
One hears it stated that a factor within the logical radical priority embodies the
key principles behind the best practice marginalised certification project. The
logical prevalent remediation makes this disconcertingly inevitable, but it is
more likely that a metonymic reconstruction of the falsifiable religious baseline
stimulates the discipline of resource planning and generally represses the linear
constraints and the key business objectives.
</p>
<a id="someId" class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>
</div>
</body></html>
PuppeteerTests.PageUsage.01.verified.png:
Element test
An element can be verified as follows:
var page = await browser.NewPageAsync();
await page.GoToAsync("http://localhost:5000");
var element = await page.QuerySelectorAsync("#someId");
await Verify(element);
With the state of the element being rendered as a verified files:
Learn more
PuppeteerTests.ElementUsage.01.verified.png:
Selenium Usage
Verification of Web UIs via Selenium.
Enable
Enable VerifySelenium once at assembly load time:
[ModuleInitializer]
public static void InitSelenium() =>
VerifySelenium.Initialize();
Instantiate browser
// wait for target server to start
await SocketWaiter.Wait(port: 5000);
var options = new ChromeOptions();
options.AddArgument("--no-sandbox");
options.AddArgument("--headless");
driver = new(options);
driver.Manage().Window.Size = new(1024, 768);
await driver.Navigate().GoToUrlAsync("http://localhost:5000");
Page test
The current page state can be verified as follows:
await Verify(driver);
With the state of the element being rendered as a verified files:
<html lang="en"><head>
<meta charset="utf-8">
<title>The Title</title>
<link href="https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="jumbotron">
<h1 class="display-4">The Awareness Of Relative Idealism</h1>
<p class="lead">
One hears it stated that a factor within the logical radical priority embodies the
key principles behind the best practice marginalised certification project. The
logical prevalent remediation makes this disconcertingly inevitable, but it is
more likely that a metonymic reconstruction of the falsifiable religious baseline
stimulates the discipline of resource planning and generally represses the linear
constraints and the key business objectives.
</p>
<a id="someId" class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>
</div>
</body></html>
SeleniumTests.PageUsage.01.verified.png:
Element test
An element can be verified as follows:
var element = driver.FindElement(By.Id("someId"));
await Verify(element);
With the state of the element being rendered as a verified files:
<a id="someId" class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>
SeleniumTests.ElementUsage.01.verified.png:
OS specific rendering
The rendering can very slightly between different OS versions. This can make verification on different machines (eg CI) problematic. A custom comparer can to mitigate this.
Compatibility with other Verify plugins
This projects is designed to be compatible with other Verify plugins. One common scenario for combining plugins is using Verify.AngleSharp to manipulate the verified html.
For example using the Verify.AngleSharp Pretty Print extension.
var page = await browser.NewPageAsync();
await page.GotoAsync("http://localhost:5000");
await Verify(page)
.PrettyPrintHtml();
Without the .PrettyPrintHtml() the result is:
<!DOCTYPE html><html lang="en"><head>
<meta charset="utf-8">
<title>The Title</title>
<link href="https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="jumbotron">
<h1 class="display-4">The Awareness Of Relative Idealism</h1>
<p class="lead">
One hears it stated that a factor within the logical radical priority embodies the
key principles behind the best practice marginalised certification project. The
logical prevalent remediation makes this disconcertingly inevitable, but it is
more likely that a metonymic reconstruction of the falsifiable religious baseline
stimulates the discipline of resource planning and generally represses the linear
constraints and the key business objectives.
</p>
<a id="someId" class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>
</div>
</body></html>
but with it added, the result is:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>The Title</title>
<link href="https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="jumbotron">
<h1 class="display-4">The Awareness Of Relative Idealism</h1>
<p class="lead">
One hears it stated that a factor within the logical radical priority embodies the key principles behind the best practice marginalised certification project. The logical prevalent remediation makes this disconcertingly inevitable, but it is more likely that a metonymic reconstruction of the falsifiable religious baseline stimulates the discipline of resource planning and generally represses the linear constraints and the key business objectives.
</p>
<a id="someId" class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>
</div>
</body>
</html>
Icon
Crystal designed by Monjin Friends from The Noun Project.

