diff --git a/src/Playwright.Tests/PageAriaSnapshotTests.cs b/src/Playwright.Tests/PageAriaSnapshotTests.cs
index c2d1eb443..0aca8b6f7 100644
--- a/src/Playwright.Tests/PageAriaSnapshotTests.cs
+++ b/src/Playwright.Tests/PageAriaSnapshotTests.cs
@@ -26,6 +26,39 @@ namespace Microsoft.Playwright.Tests;
public class PageAriaSnapshotTests : PageTestEx
{
+ [PlaywrightTest]
+ [TestCase(AriaSnapshotMode.Default)]
+ [TestCase(AriaSnapshotMode.Ai)]
+ public async Task ShouldIncludeBoundingBoxesInPageSnapshot(AriaSnapshotMode mode)
+ {
+ await Page.SetContentAsync("");
+
+ var snapshot = await Page.AriaSnapshotAsync(new() { Mode = mode });
+ StringAssert.DoesNotContain("[box=", snapshot);
+ Assert.AreEqual(snapshot, await Page.AriaSnapshotAsync(new() { Mode = mode, Boxes = false }));
+
+ var snapshotWithBoxes = await Page.AriaSnapshotAsync(new() { Mode = mode, Boxes = true });
+ StringAssert.Contains("[box=20,30,100,40]", snapshotWithBoxes);
+ Assert.AreEqual(snapshot, await Page.AriaSnapshotAsync(new() { Mode = mode }));
+ }
+
+ [PlaywrightTest]
+ [TestCase(AriaSnapshotMode.Default)]
+ [TestCase(AriaSnapshotMode.Ai)]
+ public async Task ShouldIncludeBoundingBoxesInLocatorSnapshot(AriaSnapshotMode mode)
+ {
+ await Page.SetContentAsync("");
+ var locator = Page.GetByRole(AriaRole.Button);
+
+ var snapshot = await locator.AriaSnapshotAsync(new() { Mode = mode });
+ StringAssert.DoesNotContain("[box=", snapshot);
+ Assert.AreEqual(snapshot, await locator.AriaSnapshotAsync(new() { Mode = mode, Boxes = false }));
+
+ var snapshotWithBoxes = await locator.AriaSnapshotAsync(new() { Mode = mode, Boxes = true });
+ StringAssert.Contains("[box=20,30,100,40]", snapshotWithBoxes);
+ Assert.AreEqual(snapshot, await locator.AriaSnapshotAsync(new() { Mode = mode }));
+ }
+
private string _unshift(string snapshot)
{
var lines = snapshot.Split('\n');
diff --git a/src/Playwright/Core/Locator.cs b/src/Playwright/Core/Locator.cs
index 10be5e4f8..0451c9fec 100644
--- a/src/Playwright/Core/Locator.cs
+++ b/src/Playwright/Core/Locator.cs
@@ -674,6 +674,7 @@ public async Task AriaSnapshotAsync(LocatorAriaSnapshotOptions? options
["selector"] = _selector,
["mode"] = options?.Mode,
["depth"] = options?.Depth,
+ ["boxes"] = options?.Boxes,
},
timeout: _frame.Timeout(options?.Timeout)).ConfigureAwait(false);
return result!.Value.GetProperty("snapshot").ToString();
diff --git a/src/Playwright/Core/Page.cs b/src/Playwright/Core/Page.cs
index a395384f0..c4aa49e6f 100644
--- a/src/Playwright/Core/Page.cs
+++ b/src/Playwright/Core/Page.cs
@@ -1572,6 +1572,7 @@ public async Task AriaSnapshotAsync(PageAriaSnapshotOptions? options = d
{
["mode"] = options?.Mode,
["depth"] = options?.Depth,
+ ["boxes"] = options?.Boxes,
},
timeout: MainFrame.Timeout(options?.Timeout)).ConfigureAwait(false);
return result!.Value.GetProperty("snapshot").ToString();
diff --git a/src/tools/Playwright.Tooling/DriverDownloader.cs b/src/tools/Playwright.Tooling/DriverDownloader.cs
index 2df90abea..a711f0ed7 100644
--- a/src/tools/Playwright.Tooling/DriverDownloader.cs
+++ b/src/tools/Playwright.Tooling/DriverDownloader.cs
@@ -144,6 +144,24 @@ private static async Task WithRetriesAsync(string url, Func action)
}
}
+ private static string ResolveNpmExecutable()
+ {
+ string name = OperatingSystem.IsWindows() ? "npm.cmd" : "npm";
+ // On Windows npm.cmd must be started by its full path: launched by bare name,
+ // the script's %~dp0 expands to the working directory instead of its own
+ // directory and it fails to find node_modules/npm/bin/npm-cli.js.
+ string path = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
+ foreach (string directory in path.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries))
+ {
+ string candidate = Path.Combine(directory.Trim('"'), name);
+ if (File.Exists(candidate))
+ {
+ return candidate;
+ }
+ }
+ return name;
+ }
+
private async Task ExecuteAsync()
{
var driversDirectory = new DirectoryInfo(Path.Combine(BasePath, "src", "Playwright", ".drivers"));
@@ -186,24 +204,6 @@ private async Task ExecuteAsync()
return true;
}
- private static string ResolveNpmExecutable()
- {
- string name = OperatingSystem.IsWindows() ? "npm.cmd" : "npm";
- // On Windows npm.cmd must be started by its full path: launched by bare name,
- // the script's %~dp0 expands to the working directory instead of its own
- // directory and it fails to find node_modules/npm/bin/npm-cli.js.
- string path = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
- foreach (string directory in path.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries))
- {
- string candidate = Path.Combine(directory.Trim('"'), name);
- if (File.Exists(candidate))
- {
- return candidate;
- }
- }
- return name;
- }
-
private async Task DownloadPlaywrightPackageAsync(string driversDirectory)
{
// Fetched with `npm pack` rather than a hard-coded registry URL so that the