Deque.AxeCore.Playwright
4.10.0
Prefix Reserved
dotnet add package Deque.AxeCore.Playwright --version 4.10.0
NuGet\Install-Package Deque.AxeCore.Playwright -Version 4.10.0
<PackageReference Include="Deque.AxeCore.Playwright" Version="4.10.0" />
paket add Deque.AxeCore.Playwright --version 4.10.0
#r "nuget: Deque.AxeCore.Playwright, 4.10.0"
// Install Deque.AxeCore.Playwright as a Cake Addin #addin nuget:?package=Deque.AxeCore.Playwright&version=4.10.0 // Install Deque.AxeCore.Playwright as a Cake Tool #tool nuget:?package=Deque.AxeCore.Playwright&version=4.10.0
Deque.AxeCore.Playwright
Automated web accessibility testing with .NET, C#, and Playwright. Wraps the axe-core accessibility scanning engine and the Playwright browser automation framework.
Compatible with .NET Standard 2.1.
Getting Started
Install via NuGet:
PM> Install-Package Deque.AxeCore.Playwright
# or, use the Visual Studio "Manage NuGet Packages" UI
Ensure you have Playwright browsers installed. For reference, see https://playwright.dev/dotnet/docs/browsers
Example usage with Playwright's NUnit integration:
using System.Threading.Tasks;
using NUnit.Framework;
using Microsoft.Playwright.NUnit;
using Deque.AxeCore.Commons;
using Deque.AxeCore.Playwright;
[TestFixture]
class MyPlaywrightTests : PageTest
{
[Test]
public async Task CheckAxeClean()
{
const string expectedViolationId = "color-contrast";
await Page!.GotoAsync("https://playwright.dev/dotnet");
AxeResult axeResults = await Page!.RunAxe();
Assert.That(axeResults.Violations, Is.Null.Or.Empty);
}
}
API Reference
This library essentially wraps the axe-core library. Currently the two supported functions are for rule retrieval and for running.
GetAxeRules
This method retrieves metadata about the rules that axe is capable of running.
IList<AxeRuleMetadata> axeRules = await page.GetAxeRules();
foreach(var rule in axeRules)
{
Console.WriteLine($"Rule name: {rule.RuleId} Help: {rule.Help} HelpUrl: {rule.HelpUrl}");
Console.WriteLine($"Tags: {string.Join(", ", rule.Tags)}");
}
It is also possible to run this only selecting for rules with particular tags. Tags are considered in a disjunctive fashion.
// Only take rules which are wcag2aa or wcag2a.
IList<string> tags = new List<string>() { "wcag2aa", "wcag2a"}
IList<AxeRuleMetadata> axeRules = await page.GetAxeRules(tags);
foreach(var rule in axeRules)
{
Console.WriteLine($"Rule name: {rule.RuleId} Help: {rule.Help} HelpUrl: {rule.HelpUrl}");
Console.WriteLine($"Tags: {string.Join(", ", rule.Tags)}");
}
RunAxe
This method executes the axe.run API, which will run rules against the current state of the page.
AxeResult axeResults = await page.RunAxe();
Console.WriteLine($"Axe ran against {axeResults.Url} on {axeResults.Timestamp}.");
Console.WriteLine($"Rules that failed:");
foreach(var violation in axeResults.Violations)
{
Console.WriteLine($"Rule Id: {violation.Id} Impact: {violation.Impact} HelpUrl: {violation.HelpUrl}.");
foreach(var node in violation.Nodes)
{
Console.WriteLine($"\tViolation found at: {node.Target}");
Console.WriteLine($"\t...with HTML: {node.Html}");
}
}
Console.WriteLine($"Rules that passed successfully:");
foreach(var pass in axeResults.Passes)
{
Console.WriteLine($"Rule Id: {pass.Id} Impact: {pass.Impact} HelpUrl: {pass.HelpUrl}.");
}
Console.WriteLine($"Rules that did not fully run:");
foreach(var incomplete in axeResults.Incomplete)
{
Console.WriteLine($"Rule Id: {incomplete.Id}.");
}
Console.WriteLine($"Rules that were not applicable:");
foreach(var inapplicable in axeResults.Inapplicable)
{
Console.WriteLine($"Rule Id: {inapplicable.Id}.");
}
RunAxe
is supported on both Playwright Page
s and Playwright Locator
s. Locator
s are the easiest way to run axe against only part of a page:
ILocator locator = page.Locator("text=Sign In");
AxeResult axeResults = await locator.RunAxe();
Alternately, when used on a Page
, RunAxe
supports an AxeRunContext
parameter which supports more complex rules for deciding which parts of a page to scan (or exclude from a scan). This corresponds to the axe.run Context parameter:
AxeRunContext runContext = new AxeRunContext()
{
// Only run on this #my-id.
Include = new List<AxeSelector>() { new AxeSelector("#my-id") }
};
runContext = new AxeRunContext()
{
// Run on everything except #my-id and #second-id.
Exclude = new List<AxeSelector>()
{
new AxeSelector("#my-id"),
new AxeSelector("#second-id"),
}
};
runContext = new AxeRunContext()
{
// Run on every button except #my-id.
Include = new List<AxeSelector>() { new AxeSelector("button") },
Exclude = new List<AxeSelector>() { new AxeSelector("#my-id") }
};
runContext = new AxeRunContext()
{
// Run on everything, except for #my-id within the iframe #my-frame.
Exclude = new List<AxeSelector>()
{
new AxeSelector("#my-id", new List<string>() { "#my-frame" })
}
};
AxeResult axeResults = await page.RunAxe(runContext);
All RunAxe
methods also support an AxeRunOptions
parameter.
This corresponds to the axe.run Options parameter.
AxeRunOptions options = new AxeRunOptions()
{
// Run only tags that are wcag2aa.
RunOnly = new RunOnlyOptions { Type = "tag", Values = new List<string> { "wcag2aa" } },
// Specify rules.
Rules = new Dictionary<string, RuleOptions>()
{
// Don't run color-contrast.
{ "color-contrast", new RuleOptions() { Enabled = false } }
},
// Limit result types to Violations.
ResultTypes = new HashSet<ResultType>()
{
ResultType.Violations
},
// Don't return css selectors in results.
Selectors = false,
// Return CSS selector for elements, with all the element's ancestors.
Ancestry = true,
// Don't return xpath selectors for elements.
XPath = false,
// Don't run axe on iframes inside the document.
Iframes = false
};
AxeResult axeResults = await page.RunAxe(options);
axeResults = await page.RunAxe(context, options);
axeResults = await locator.RunAxe(options);
RunAxeLegacy
Set the frame testing method to "legacy mode". In this mode, axe will not open a blank page in which to aggregate its results. This can be used in an environment where opening a blank page causes issues.
With legacy mode turned on, axe will fall back to its test solution prior to the 4.3 release, but with cross-origin frame testing disabled. The frame-tested rule will report which frames were untested.
Important: Use of .RunAxeLegacy()
is a last resort. If you find there is no other solution, please report this as an issue. It will be removed in a future release.
AxeResult axeResults = await page.RunAxeLegacy();
Migrating from Playwright.Axe
(PlaywrightAxeDotnet)
This project acts as a drop-in replacement for most of the functionality from Playwright.Axe
. (PlaywrightAxeDotnet). To migrate:
- Update your test
.csproj
file's<PackageReference>
forPlaywright.Axe
toDeque.AxeCore.Playwright
- Add a new
<PackageReference>
toDeque.AxeCore.Commons
at the same version number asDeque.AxeCore.Playwright
- Update all
using Playwright.Axe;
statements in your tests tousing Deque.AxeCore.Playwright;
and/orusing Deque.AxeCore.Commons;
In a move to standardize, we migrated this package away from Playwright specific typings, instead opting to use the typings from the Deque.AxeCore.Commons
package instead. The result is several minor breaking changes that may require updates to your code:
Replacements/Renamings
AxeResults
has now been renamed toAxeResult
; the previously usedAxeResult
for this package will now beAxeResultItem
.AxeNodeResult
has been replaced withAxeResultNode
AxeCheckResult
has been replaced withAxeResultCheck
AxeResultGroup
has been replaced withResultType
AxeRuleObjectValue
has been replaced withRuleOptions
AxeRunOnly
has been replaced withRunOnlyOptions
AxeRelatedNode
has been replaced withAxeResultRelatedNode
. With this type, the Targets property is changed from aIList<string>
to aList<AxeResultTarget>
; users should expect to modify usages of the Targets property to include a.ToString()
method call.AxeRunSerialContext
has been replaced byAxeRunContext
andAxeSelector
types. Here are some examples of how to use the new types:
// Finding a single element using the Playwright Locator API.
ILocator locator = page.GetByRole("menu").RunAxe();
// Including/excluding elements in the main frame.
new AxeRunContext()
{
Include = new List<AxeSelector> { new AxeSelector("#foo") },
Exclude = new List<AxeSelector> {},
};
// Including/excluding an element in a child frame.
new AxeRunContext()
{
Include = new List<AxeSelector> { new AxeSelector("#element-in-child-frame", new List<string> { "#iframe-in-main-frame" })},
Exclude = new List<AxeSelector> {},
};
Type Modifications
- The Timestamp type in
AxeResult
changed from System.DateTime to System.DateTimeOffset - The url type in
AxeResult
changed from Uri to string - The
OrientationAngle
type inAxeTestEnvironment
changed from int to double - The
HelpUrl
inAxeResultItem
changed from Uri to string
Removals
- Removed
AxeEnvironmentData
interface and using the existing environment data info inDeque.AxeCore.Commons.AxeResult
- Removed
AxeImpactValue
andAxeRunOnlyType
enums in favor of usingstring
in the Commons typings (AxeResultItem.cs
andAxeRunOptions.cs
, respectively) FailureSummary
was removed fromAxeResultNode
(formerlyAxeNodeResult
)ElementRef
andPerformanceTimer
were removed fromAxeRunOptions
AxeRunOptions
andRunOnlyOptions
now use named object-initializer syntax instead of constructor parameters.
Contributing
Refer to the general axe-core-nuget CONTRIBUTING.md.
License
This package is distributed under the terms of the MIT License.
However, note that it has a dependency on the (MPL licensed) Deque.AxeCore.Commons
NuGet package.
Acknowledgements
This package builds on past work from the PlaywrightAxeDotnet project (see NOTICE.txt). We @IsaacWalker for his work on that project.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Deque.AxeCore.Commons (>= 4.10.0)
- Microsoft.Playwright (>= 1.20.2)
- System.IO.Abstractions (>= 17.0.24)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
4.10.0 | 1,762 | 9/3/2024 |
4.10.0-alpha.88 | 32 | 10/29/2024 |
4.10.0-alpha.82 | 54 | 8/7/2024 |
4.9.1 | 10,397 | 5/13/2024 |
4.9.1-alpha.81 | 45 | 7/30/2024 |
4.9.1-alpha.80 | 56 | 5/15/2024 |
4.9.1-alpha.78 | 69 | 5/8/2024 |
4.9.0 | 3,814 | 3/29/2024 |
4.9.0-alpha.79 | 63 | 5/9/2024 |
4.9.0-alpha.77 | 64 | 5/7/2024 |
4.9.0-alpha.76 | 44 | 3/29/2024 |
4.9.0-alpha.75 | 60 | 3/26/2024 |
4.8.2 | 3,703 | 2/14/2024 |
4.8.2-alpha.74 | 57 | 3/26/2024 |
4.8.2-alpha.73 | 68 | 2/14/2024 |
4.8.2-alpha.72 | 59 | 2/14/2024 |
4.8.2-alpha.71 | 62 | 2/14/2024 |
4.8.2-alpha.70 | 63 | 2/8/2024 |
4.8.1 | 1,450 | 1/11/2024 |
4.8.1-alpha.69 | 50 | 2/8/2024 |
4.8.1-alpha.68 | 60 | 2/8/2024 |
4.8.1-alpha.65 | 68 | 1/9/2024 |
4.8.0 | 14,958 | 10/2/2023 |
4.8.0-alpha.67 | 55 | 2/7/2024 |
4.8.0-alpha.64 | 64 | 1/9/2024 |
4.8.0-alpha.63 | 67 | 1/9/2024 |
4.8.0-alpha.62 | 71 | 1/9/2024 |
4.7.2 | 1,971 | 8/30/2023 |
4.7.2-alpha.61 | 63 | 12/21/2023 |
4.7.2-alpha.59 | 62 | 11/21/2023 |
4.7.2-alpha.58 | 73 | 11/2/2023 |
4.7.2-alpha.57 | 76 | 11/1/2023 |
4.7.2-alpha.56 | 67 | 10/30/2023 |
4.7.2-alpha.55 | 67 | 10/19/2023 |
4.7.2-alpha.54 | 76 | 10/16/2023 |
4.7.2-alpha.53 | 69 | 10/16/2023 |
4.7.2-alpha.52 | 71 | 10/5/2023 |
4.7.2-alpha.51 | 82 | 10/3/2023 |
4.7.2-alpha.50 | 65 | 10/3/2023 |
4.7.2-alpha.49 | 79 | 9/27/2023 |
4.7.1-alpha.48 | 71 | 9/27/2023 |
4.7.1-alpha.47 | 79 | 9/27/2023 |
4.7.1-alpha.46 | 93 | 9/14/2023 |
4.7.1-alpha.45 | 79 | 9/13/2023 |
4.7.1-alpha.44 | 79 | 9/8/2023 |
4.7.1-alpha.43 | 102 | 8/30/2023 |
4.7.1-alpha.42 | 90 | 8/30/2023 |
4.4.0-alpha.c9651f2c2284967... | 18,067 | 11/10/2022 |
4.4.0-alpha.41 | 88 | 8/30/2023 |
4.4.0-alpha.40 | 92 | 8/30/2023 |