From b1c240fc047255e0d3fdd3c5c3322265fb6d853a Mon Sep 17 00:00:00 2001 From: "Soham Mondal (TATA CONSULTANCY SERVICES LTD)" Date: Tue, 10 Mar 2026 15:29:57 +0530 Subject: [PATCH 1/6] Migrate from Selenium.Axe to Deque.AxeCore.Selenium --- .../CSharpSeleniumWebdriverSample.csproj | 3 ++- .../SamplePageTests.cs | 22 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/csharp-selenium-webdriver-sample/CSharpSeleniumWebdriverSample.csproj b/csharp-selenium-webdriver-sample/CSharpSeleniumWebdriverSample.csproj index 57974bef..637a0e32 100644 --- a/csharp-selenium-webdriver-sample/CSharpSeleniumWebdriverSample.csproj +++ b/csharp-selenium-webdriver-sample/CSharpSeleniumWebdriverSample.csproj @@ -15,7 +15,8 @@ - + + diff --git a/csharp-selenium-webdriver-sample/SamplePageTests.cs b/csharp-selenium-webdriver-sample/SamplePageTests.cs index 11b97ae6..e60d7534 100644 --- a/csharp-selenium-webdriver-sample/SamplePageTests.cs +++ b/csharp-selenium-webdriver-sample/SamplePageTests.cs @@ -4,6 +4,7 @@ // This sample happens to use .NET Core, but you can use whichever .NET version makes sense for your project. // Everything we're demonstrating would also work in .NET Framework 4.5+ with no modifications. using System; +using System.Collections.Generic; using System.IO; // This sample happens to use MSTest, but you can use whichever test framework you like. // Everything we're demonstrating would also work with xUnit, NUnit, or any other test framework. @@ -13,7 +14,8 @@ using OpenQA.Selenium.Support.UI; // These are the important new libraries we're demonstrating. // You'll probably need to add new NuGet package references for these. -using Selenium.Axe; +using Deque.AxeCore.Commons; +using Deque.AxeCore.Selenium; using FluentAssertions; namespace CSharpSeleniumWebdriverSample @@ -51,7 +53,11 @@ public void TestAccessibilityOfPage() // We recommend using FluentAssertions instead; its default behavior gives much better error messages that include // full descriptions of accessibility issues, including links to detailed guidance at https://dequeuniversity.com // and CSS selector paths that exactly identify the element on the page with the issue. - axeResult.Error.Should().BeNull(); + // + // Note: In Deque.AxeCore, the old Selenium.Axe "Error" property no longer exists. + // Instead, "Incomplete" contains rules that could not be fully evaluated (e.g., due to errors + // or needing manual review). We check that here as the closest equivalent. + axeResult.Incomplete.Should().BeEmpty(); // Our PR builds do not change the presence or absence of accessibility issues, so we special case // our PR build tests to expect the errors. This is not recommended for most projects, but since the @@ -83,7 +89,7 @@ public void TestAccessibilityOfIndividualElements() .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(elementUnderTest); - axeResultWithAnalyzeWebElement.Error.Should().BeNull(); + axeResultWithAnalyzeWebElement.Incomplete.Should().BeEmpty(); axeResultWithAnalyzeWebElement.Violations.Should().BeEmpty(); // Option 2: using AxeBuilder.Include @@ -92,11 +98,11 @@ public void TestAccessibilityOfIndividualElements() AxeResult axeResultWithInclude = new AxeBuilder(_webDriver) .Include("#id-of-example-accessible-element") .Include(".class-of-example-accessible-element") - .Include("#id-of-iframe", "#id-of-element-inside-iframe") + .Include(new AxeSelector("#id-of-element-inside-iframe", new List { "#id-of-iframe" })) .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(); - axeResultWithInclude.Error.Should().BeNull(); + axeResultWithInclude.Incomplete.Should().BeEmpty(); axeResultWithInclude.Violations.Should().BeEmpty(); } @@ -113,7 +119,7 @@ public void TestAccessibilityOfPageExcludingKnownIssues() .Exclude("#id-of-example-accessibility-violation-list") .Analyze(); - axeResultExcludingExampleViolationsElement.Error.Should().BeNull(); + axeResultExcludingExampleViolationsElement.Incomplete.Should().BeEmpty(); axeResultExcludingExampleViolationsElement.Violations.Should().BeEmpty(); // You can also use AxeBuilder.DisableRules to exclude certain individual rules from a scan. This is particularly @@ -123,14 +129,14 @@ public void TestAccessibilityOfPageExcludingKnownIssues() .DisableRules("color-contrast", "label", "tabindex") .Analyze(); - axeResultDisablingRulesViolatedByExamples.Error.Should().BeNull(); + axeResultDisablingRulesViolatedByExamples.Incomplete.Should().BeEmpty(); axeResultDisablingRulesViolatedByExamples.Violations.Should().BeEmpty(); // Another option is to assert on the size of the Violations array. This works just fine, but we recommend the // other options above as your first choice instead because when they do find new issues, they will produce error // messages that more clearly identify exactly what the new/unexpected issues are. AxeResult axeResult = new AxeBuilder(_webDriver).Analyze(); - axeResult.Error.Should().BeNull(); + axeResult.Incomplete.Should().BeEmpty(); axeResult.Violations.Should().HaveCount(3); } From 10ea56310ef427bf36501c389cc662324a881c94 Mon Sep 17 00:00:00 2001 From: "Soham Mondal (TATA CONSULTANCY SERVICES LTD)" Date: Tue, 10 Mar 2026 18:22:19 +0530 Subject: [PATCH 2/6] Remove incorrect Incomplete assertions; errors are now thrown as exceptions --- csharp-selenium-webdriver-sample/SamplePageTests.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/csharp-selenium-webdriver-sample/SamplePageTests.cs b/csharp-selenium-webdriver-sample/SamplePageTests.cs index e60d7534..3869ad75 100644 --- a/csharp-selenium-webdriver-sample/SamplePageTests.cs +++ b/csharp-selenium-webdriver-sample/SamplePageTests.cs @@ -54,10 +54,8 @@ public void TestAccessibilityOfPage() // full descriptions of accessibility issues, including links to detailed guidance at https://dequeuniversity.com // and CSS selector paths that exactly identify the element on the page with the issue. // - // Note: In Deque.AxeCore, the old Selenium.Axe "Error" property no longer exists. - // Instead, "Incomplete" contains rules that could not be fully evaluated (e.g., due to errors - // or needing manual review). We check that here as the closest equivalent. - axeResult.Incomplete.Should().BeEmpty(); + // Note: In Deque.AxeCore, the old Selenium.Axe "Error" property was removed; + // any errors that would have appeared there are now reported as exceptions. // Our PR builds do not change the presence or absence of accessibility issues, so we special case // our PR build tests to expect the errors. This is not recommended for most projects, but since the @@ -89,7 +87,6 @@ public void TestAccessibilityOfIndividualElements() .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(elementUnderTest); - axeResultWithAnalyzeWebElement.Incomplete.Should().BeEmpty(); axeResultWithAnalyzeWebElement.Violations.Should().BeEmpty(); // Option 2: using AxeBuilder.Include @@ -102,7 +99,6 @@ public void TestAccessibilityOfIndividualElements() .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(); - axeResultWithInclude.Incomplete.Should().BeEmpty(); axeResultWithInclude.Violations.Should().BeEmpty(); } @@ -119,7 +115,6 @@ public void TestAccessibilityOfPageExcludingKnownIssues() .Exclude("#id-of-example-accessibility-violation-list") .Analyze(); - axeResultExcludingExampleViolationsElement.Incomplete.Should().BeEmpty(); axeResultExcludingExampleViolationsElement.Violations.Should().BeEmpty(); // You can also use AxeBuilder.DisableRules to exclude certain individual rules from a scan. This is particularly @@ -129,14 +124,12 @@ public void TestAccessibilityOfPageExcludingKnownIssues() .DisableRules("color-contrast", "label", "tabindex") .Analyze(); - axeResultDisablingRulesViolatedByExamples.Incomplete.Should().BeEmpty(); axeResultDisablingRulesViolatedByExamples.Violations.Should().BeEmpty(); // Another option is to assert on the size of the Violations array. This works just fine, but we recommend the // other options above as your first choice instead because when they do find new issues, they will produce error // messages that more clearly identify exactly what the new/unexpected issues are. AxeResult axeResult = new AxeBuilder(_webDriver).Analyze(); - axeResult.Incomplete.Should().BeEmpty(); axeResult.Violations.Should().HaveCount(3); } From 7fa17fce85bc29d69211870d9a8b5e758239b7f2 Mon Sep 17 00:00:00 2001 From: "Soham Mondal (TATA CONSULTANCY SERVICES LTD)" Date: Tue, 10 Mar 2026 19:34:13 +0530 Subject: [PATCH 3/6] Replace AxeResult.Error checks with NotBeNull assertions --- csharp-selenium-webdriver-sample/SamplePageTests.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/csharp-selenium-webdriver-sample/SamplePageTests.cs b/csharp-selenium-webdriver-sample/SamplePageTests.cs index 3869ad75..c32c6644 100644 --- a/csharp-selenium-webdriver-sample/SamplePageTests.cs +++ b/csharp-selenium-webdriver-sample/SamplePageTests.cs @@ -30,6 +30,8 @@ public class SamplePageTests [TestCategory("IntentionallyFailsAsAnExample")] public void TestAccessibilityOfPage() { + // In Deque.AxeCore, the old Selenium.Axe "Error" property was removed; + // any errors that would have appeared there are now reported as exceptions. AxeResult axeResult = new AxeBuilder(_webDriver) // This WithTags directive restricts Axe to only run tests that detect known violations of WCAG 2.1 A and AA rules // (similar to what Accessibility Insights reports). If you omit this, Axe will additionally run several "best practice" @@ -40,6 +42,7 @@ public void TestAccessibilityOfPage() // * full reference documentation for each rule: https://dequeuniversity.com/rules/axe .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(); + axeResult.Should().NotBeNull("axe-core analysis should not produce errors"); // axeResult.Violations is an array of all the accessibility violations the scan found; the easiest way to assert // that a scan came back clean is to assert that the Violations array is empty. You can do this with the built in @@ -53,9 +56,6 @@ public void TestAccessibilityOfPage() // We recommend using FluentAssertions instead; its default behavior gives much better error messages that include // full descriptions of accessibility issues, including links to detailed guidance at https://dequeuniversity.com // and CSS selector paths that exactly identify the element on the page with the issue. - // - // Note: In Deque.AxeCore, the old Selenium.Axe "Error" property was removed; - // any errors that would have appeared there are now reported as exceptions. // Our PR builds do not change the presence or absence of accessibility issues, so we special case // our PR build tests to expect the errors. This is not recommended for most projects, but since the @@ -86,6 +86,7 @@ public void TestAccessibilityOfIndividualElements() AxeResult axeResultWithAnalyzeWebElement = new AxeBuilder(_webDriver) .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(elementUnderTest); + axeResultWithAnalyzeWebElement.Should().NotBeNull("axe-core analysis should not produce errors"); axeResultWithAnalyzeWebElement.Violations.Should().BeEmpty(); @@ -98,6 +99,7 @@ public void TestAccessibilityOfIndividualElements() .Include(new AxeSelector("#id-of-element-inside-iframe", new List { "#id-of-iframe" })) .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(); + axeResultWithInclude.Should().NotBeNull("axe-core analysis should not produce errors"); axeResultWithInclude.Violations.Should().BeEmpty(); } @@ -114,6 +116,7 @@ public void TestAccessibilityOfPageExcludingKnownIssues() AxeResult axeResultExcludingExampleViolationsElement = new AxeBuilder(_webDriver) .Exclude("#id-of-example-accessibility-violation-list") .Analyze(); + axeResultExcludingExampleViolationsElement.Should().NotBeNull("axe-core analysis should not produce errors"); axeResultExcludingExampleViolationsElement.Violations.Should().BeEmpty(); @@ -123,6 +126,7 @@ public void TestAccessibilityOfPageExcludingKnownIssues() .Include("#id-of-example-accessibility-violation-list") // Like Exclude(), accepts any CSS selector .DisableRules("color-contrast", "label", "tabindex") .Analyze(); + axeResultDisablingRulesViolatedByExamples.Should().NotBeNull("axe-core analysis should not produce errors"); axeResultDisablingRulesViolatedByExamples.Violations.Should().BeEmpty(); @@ -130,6 +134,7 @@ public void TestAccessibilityOfPageExcludingKnownIssues() // other options above as your first choice instead because when they do find new issues, they will produce error // messages that more clearly identify exactly what the new/unexpected issues are. AxeResult axeResult = new AxeBuilder(_webDriver).Analyze(); + axeResult.Should().NotBeNull("axe-core analysis should not produce errors"); axeResult.Violations.Should().HaveCount(3); } From 9a86f20d7a17870483118e7f97218ee2fa30f1c1 Mon Sep 17 00:00:00 2001 From: "Soham Mondal (TATA CONSULTANCY SERVICES LTD)" Date: Wed, 11 Mar 2026 11:36:20 +0530 Subject: [PATCH 4/6] Update stale Selenium.Axe references in comments to Deque.AxeCore.Selenium --- csharp-selenium-webdriver-sample/SamplePageTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/csharp-selenium-webdriver-sample/SamplePageTests.cs b/csharp-selenium-webdriver-sample/SamplePageTests.cs index c32c6644..e7551847 100644 --- a/csharp-selenium-webdriver-sample/SamplePageTests.cs +++ b/csharp-selenium-webdriver-sample/SamplePageTests.cs @@ -2,7 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // This sample happens to use .NET Core, but you can use whichever .NET version makes sense for your project. -// Everything we're demonstrating would also work in .NET Framework 4.5+ with no modifications. +// Everything we're demonstrating would also work in .NET Framework 4.7.1+ with no modifications. using System; using System.Collections.Generic; using System.IO; @@ -146,7 +146,7 @@ public void TestAccessibilityOfPageExcludingKnownIssues() // navigate to a test page. // // If you're incorporating accessibility testing into an existing body of end to end tests, you can stick with - // however your existing tests are already solving this; you don't need to do anything special to use Selenium.Axe. + // however your existing tests are already solving this; you don't need to do anything special to use Deque.AxeCore.Selenium. // Starting a new browser process is good for keeping tests isolated from one another, but can be slow. Here, we're // using a [ClassInitialize] method so the same browser will be shared between different [TestMethod]s. @@ -155,12 +155,12 @@ public static void StartBrowser(TestContext testContext) { // WebDriverFactory uses environment variables set by azure-pipelines.yml to determine which browser to use; // the test cases we'll write in this file will work regardless of which browser they're running against. // - // This WebDriverFactory is just one example of how you might initialize Selenium; if you're adding Selenium.Axe + // This WebDriverFactory is just one example of how you might initialize Selenium; if you're adding Deque.AxeCore.Selenium // to an existing set of end to end tests that already have their own way of initializing a webdriver, you can // keep using that instead. _webDriver = WebDriverFactory.CreateFromEnvironmentVariableSettings(); - // You *must* set this timeout to use Selenium.Axe. It defaults to "0 seconds", which isn't enough time for + // You *must* set this timeout to use Deque.AxeCore.Selenium. It defaults to "0 seconds", which isn't enough time for // Axe to scan the page. The exact amount of time will depend on the complexity of the page you're testing. _webDriver.Manage().Timeouts().AsynchronousJavaScript = TimeSpan.FromSeconds(20); } From 96227e99340a96cd24e3c0c913e9a31594bc9db5 Mon Sep 17 00:00:00 2001 From: "Soham Mondal (TATA CONSULTANCY SERVICES LTD)" Date: Wed, 11 Mar 2026 11:37:31 +0530 Subject: [PATCH 5/6] Remove redundant NotBeNull assertions; errors are now exceptions --- csharp-selenium-webdriver-sample/SamplePageTests.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/csharp-selenium-webdriver-sample/SamplePageTests.cs b/csharp-selenium-webdriver-sample/SamplePageTests.cs index e7551847..e5d2b947 100644 --- a/csharp-selenium-webdriver-sample/SamplePageTests.cs +++ b/csharp-selenium-webdriver-sample/SamplePageTests.cs @@ -30,8 +30,6 @@ public class SamplePageTests [TestCategory("IntentionallyFailsAsAnExample")] public void TestAccessibilityOfPage() { - // In Deque.AxeCore, the old Selenium.Axe "Error" property was removed; - // any errors that would have appeared there are now reported as exceptions. AxeResult axeResult = new AxeBuilder(_webDriver) // This WithTags directive restricts Axe to only run tests that detect known violations of WCAG 2.1 A and AA rules // (similar to what Accessibility Insights reports). If you omit this, Axe will additionally run several "best practice" @@ -42,7 +40,6 @@ public void TestAccessibilityOfPage() // * full reference documentation for each rule: https://dequeuniversity.com/rules/axe .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(); - axeResult.Should().NotBeNull("axe-core analysis should not produce errors"); // axeResult.Violations is an array of all the accessibility violations the scan found; the easiest way to assert // that a scan came back clean is to assert that the Violations array is empty. You can do this with the built in @@ -86,7 +83,6 @@ public void TestAccessibilityOfIndividualElements() AxeResult axeResultWithAnalyzeWebElement = new AxeBuilder(_webDriver) .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(elementUnderTest); - axeResultWithAnalyzeWebElement.Should().NotBeNull("axe-core analysis should not produce errors"); axeResultWithAnalyzeWebElement.Violations.Should().BeEmpty(); @@ -99,7 +95,6 @@ public void TestAccessibilityOfIndividualElements() .Include(new AxeSelector("#id-of-element-inside-iframe", new List { "#id-of-iframe" })) .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa") .Analyze(); - axeResultWithInclude.Should().NotBeNull("axe-core analysis should not produce errors"); axeResultWithInclude.Violations.Should().BeEmpty(); } @@ -116,8 +111,7 @@ public void TestAccessibilityOfPageExcludingKnownIssues() AxeResult axeResultExcludingExampleViolationsElement = new AxeBuilder(_webDriver) .Exclude("#id-of-example-accessibility-violation-list") .Analyze(); - axeResultExcludingExampleViolationsElement.Should().NotBeNull("axe-core analysis should not produce errors"); - + axeResultExcludingExampleViolationsElement.Violations.Should().BeEmpty(); // You can also use AxeBuilder.DisableRules to exclude certain individual rules from a scan. This is particularly @@ -126,7 +120,6 @@ public void TestAccessibilityOfPageExcludingKnownIssues() .Include("#id-of-example-accessibility-violation-list") // Like Exclude(), accepts any CSS selector .DisableRules("color-contrast", "label", "tabindex") .Analyze(); - axeResultDisablingRulesViolatedByExamples.Should().NotBeNull("axe-core analysis should not produce errors"); axeResultDisablingRulesViolatedByExamples.Violations.Should().BeEmpty(); @@ -134,7 +127,6 @@ public void TestAccessibilityOfPageExcludingKnownIssues() // other options above as your first choice instead because when they do find new issues, they will produce error // messages that more clearly identify exactly what the new/unexpected issues are. AxeResult axeResult = new AxeBuilder(_webDriver).Analyze(); - axeResult.Should().NotBeNull("axe-core analysis should not produce errors"); axeResult.Violations.Should().HaveCount(3); } From 9b5abcc6730d95f4e5b5bd207439e17e612c7948 Mon Sep 17 00:00:00 2001 From: "Soham Mondal (TATA CONSULTANCY SERVICES LTD)" Date: Wed, 11 Mar 2026 11:59:54 +0530 Subject: [PATCH 6/6] Update README references from Selenium.Axe to Deque.AxeCore.Selenium --- csharp-selenium-webdriver-sample/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp-selenium-webdriver-sample/README.md b/csharp-selenium-webdriver-sample/README.md index 6f393995..9596eb12 100644 --- a/csharp-selenium-webdriver-sample/README.md +++ b/csharp-selenium-webdriver-sample/README.md @@ -16,7 +16,7 @@ Some good places to start reading are: The key tools and libraries this sample demonstrates are: * [Selenium.WebDriver](https://www.seleniumhq.org), the .NET library for Selenium, a tool for automating interactions with different web browsers. -* [Selenium.Axe](https://github.com/TroyWalshProf/SeleniumAxeDotnet), a .NET library for running accessibility scans on web pages by using Selenium.WebDriver to run the [axe-core](https://github.com/dequelabs/axe-core) accessibility scanning engine. +* [Deque.AxeCore.Selenium](https://github.com/dequelabs/axe-core-nuget), a .NET library for running accessibility scans on web pages by using Selenium.WebDriver to run the [axe-core](https://github.com/dequelabs/axe-core) accessibility scanning engine. * [Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/) to run the tests in a CI build with every Pull Request. This sample also uses a few other tools and libraries which are less important; if you use a different test framework or a different version of .NET, you can still follow along with most of the sample. @@ -28,7 +28,7 @@ This sample also uses a few other tools and libraries which are less important; * [Chrome](https://google.com/chrome) (with [Selenium.WebDriver.ChromeDriver](https://github.com/jsakamoto/nupkg-selenium-webdriver-chromedriver/)) and [Firefox](https://www.mozilla.org/firefox/) (with [Selenium.WebDriver.GeckoDriver](https://github.com/jsakamoto/nupkg-selenium-webdriver-geckodriver/)) as our test browsers * Selenium supports many different browsers and operating systems; use whichever combination is most important for your product! * [FluentAssertions](https://fluentassertions.com/) to write test assertions - * We like FluentAssertions because it gives great error messages out-of-the-box with Selenium.Axe. But you can still follow the rest of the sample if you prefer a different assertion style! + * We like FluentAssertions because it gives great error messages out-of-the-box with Deque.AxeCore.Selenium. But you can still follow the rest of the sample if you prefer a different assertion style! ## See it in action on your local machine