Skip to content

Commit

Permalink
Merge pull request #113 from jonreding2010/AllReportCombos
Browse files Browse the repository at this point in the history
Select Result Type to be in the Html Report
  • Loading branch information
TroyWalshProf committed Jan 27, 2021
2 parents 095506e + 67613a0 commit b943062
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 45 deletions.
117 changes: 92 additions & 25 deletions Selenium.Axe/Selenium.Axe.Test/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public virtual void TearDown()
_webDriver?.Quit();
_webDriver?.Dispose();
}

[TestMethod]
[DataRow("Chrome")]
[DataRow("Firefox")]
Expand Down Expand Up @@ -70,7 +70,7 @@ public void RunScanOnGivenElement(string browser)
InitDriver(browser);
LoadSimpleTestPage();

var mainElement = _wait.Until(drv => drv.FindElement(By.TagName("main")));
var mainElement = _wait.Until(drv => drv.FindElement(By.TagName(mainElementSelector)));

AxeResult results = _webDriver.Analyze(mainElement);
results.Violations.Should().HaveCount(3);
Expand All @@ -85,12 +85,46 @@ public void ReportFullPage(string browser)
InitDriver(browser);
LoadSimpleTestPage();

var mainElement = _wait.Until(drv => drv.FindElement(By.TagName("main")));
_wait.Until(drv => drv.FindElement(By.TagName(mainElementSelector)));

_webDriver.CreateAxeHtmlReport(path);

ValidateReport(path, 4, 28, 0, 63);
}

[TestMethod]
[DataRow("Chrome")]
[DataRow("FireFox")]
public void ReportFullPageViolationsOnly(string browser)
{
string path = CreateReportPath();
InitDriver(browser);
LoadSimpleTestPage();

_wait.Until(drv => drv.FindElement(By.TagName(mainElementSelector)));

_webDriver.CreateAxeHtmlReport(path, ReportTypes.Violations);

ValidateReport(path, 4, 0);
ValidateResultNotWritten(path, ReportTypes.Passes | ReportTypes.Incomplete | ReportTypes.Inapplicable);
}

[TestMethod]
[DataRow("Chrome")]
[DataRow("FireFox")]
public void ReportFullPagePassesInapplicableViolationsOnly(string browser)
{
string path = CreateReportPath();
InitDriver(browser);
LoadSimpleTestPage();

_wait.Until(drv => drv.FindElement(By.TagName(mainElementSelector)));
_webDriver.CreateAxeHtmlReport(path, ReportTypes.Passes | ReportTypes.Inapplicable | ReportTypes.Violations);

ValidateReport(path, 4, 28, 0, 63);
ValidateResultNotWritten(path, ReportTypes.Incomplete);
}

[TestMethod]
[DataRow("Chrome")]
[DataRow("Firefox")]
Expand All @@ -100,7 +134,7 @@ public void ReportOnElement(string browser)
InitDriver(browser);
LoadSimpleTestPage();

var mainElement = _wait.Until(drv => drv.FindElement(By.CssSelector("main")));
var mainElement = _wait.Until(drv => drv.FindElement(By.CssSelector(mainElementSelector)));
_webDriver.CreateAxeHtmlReport(mainElement, path);

ValidateReport(path, 3, 16, 0, 69);
Expand All @@ -114,11 +148,11 @@ public void ReportOnElementEventFiring(string browser)
string path = CreateReportPath();
InitDriver(browser);
LoadSimpleTestPage();

_webDriver = new EventFiringWebDriver(_webDriver);
_wait = new WebDriverWait(_webDriver, TimeSpan.FromSeconds(20));

var mainElement = _wait.Until(drv => drv.FindElement(By.CssSelector("main")));
var mainElement = _wait.Until(drv => drv.FindElement(By.CssSelector(mainElementSelector)));
_webDriver.CreateAxeHtmlReport(mainElement, path);

ValidateReport(path, 3, 16, 0, 69);
Expand All @@ -132,7 +166,7 @@ public void ReportRespectRules(string browser)
string path = CreateReportPath();
InitDriver(browser);
LoadSimpleTestPage();
var mainElement = _wait.Until(drv => drv.FindElement(By.CssSelector("main")));
_wait.Until(drv => drv.FindElement(By.CssSelector(mainElementSelector)));

var builder = new AxeBuilder(_webDriver).DisableRules("color-contrast");
_webDriver.CreateAxeHtmlReport(builder.Analyze(), path);
Expand All @@ -148,7 +182,7 @@ public void ReportSampleResults(string browser)
string path = CreateReportPath();
InitDriver(browser);
LoadSimpleTestPage();
var mainElement = _wait.Until(drv => drv.FindElement(By.CssSelector("main")));
_wait.Until(drv => drv.FindElement(By.CssSelector(mainElementSelector)));
JObject jResult = JObject.Parse(File.ReadAllText(IntegrationTestJsonResultFile));
var results = new AxeResult(jResult);
_webDriver.CreateAxeHtmlReport(results, path);
Expand Down Expand Up @@ -181,19 +215,19 @@ public void RunSiteThatReturnsMultipleTargets(string browser)
var axeResult = new AxeBuilder(_webDriver)
.WithOutputFile(@".\raw-axe-results.json")
.Analyze();

var colorContrast = axeResult
.Violations
.FirstOrDefault(x => x.Id == "color-contrast");

Assert.IsNotNull(colorContrast);
var complexTargetNode = colorContrast
.Nodes
.Where(x => x.Target.Any(node => node.Selectors.Any()))
.Select(x => x.Target.Last())
.First();
Assert.IsNotNull(complexTargetNode);
Assert.IsTrue(complexTargetNode.Selectors.Count() == 2);
Assert.IsTrue(complexTargetNode.Selectors.Count == 2);
}

private string CreateReportPath()
Expand All @@ -203,7 +237,7 @@ private string CreateReportPath()
string path = Uri.UnescapeDataString(uri.Path);
return Path.Combine(Path.GetDirectoryName(path), Guid.NewGuid() + ".html");
}

private void ValidateReport(string path, int violationCount, int passCount, int incompleteCount = 0, int inapplicableCount = 0)
{
string text = File.ReadAllText(path);
Expand All @@ -212,30 +246,63 @@ private void ValidateReport(string path, int violationCount, int passCount, int

// Check violations
string xpath = ".//*[@id=\"ViolationsSection\"]//*[contains(concat(\" \",normalize-space(@class),\" \"),\"htmlTable\")]";
HtmlNodeCollection liNodes = doc.DocumentNode.SelectNodes(xpath) ?? new HtmlNodeCollection(null);
Assert.AreEqual(violationCount, liNodes.Count, $"Expected {violationCount} violations");
ValidateElementCount(doc, violationCount, xpath, ResultType.Violations);

// Check passes
xpath = ".//*[@id=\"PassesSection\"]//*[contains(concat(\" \",normalize-space(@class),\" \"),\"htmlTable\")]";
liNodes = doc.DocumentNode.SelectNodes(xpath) ?? new HtmlNodeCollection(null);
Assert.AreEqual(passCount, liNodes.Count, $"Expected {passCount} passess");
ValidateElementCount(doc, passCount, xpath, ResultType.Passes);

// Check inapplicables
xpath = ".//*[@id=\"InapplicableSection\"]//*[contains(concat(\" \",normalize-space(@class),\" \"),\"findings\")]";
liNodes = doc.DocumentNode.SelectNodes(xpath) ?? new HtmlNodeCollection(null);
Assert.AreEqual(inapplicableCount, liNodes.Count, $"Expected {inapplicableCount} inapplicables");
ValidateElementCount(doc, inapplicableCount, xpath, ResultType.Inapplicable);

// Check incompletes
xpath = ".//*[@id=\"IncompleteSection\"]//*[contains(concat(\" \",normalize-space(@class),\" \"),\"htmlTable\")]";
liNodes = doc.DocumentNode.SelectNodes(xpath) ?? new HtmlNodeCollection(null);
Assert.AreEqual(incompleteCount, liNodes.Count, $"Expected {incompleteCount} incompletes");
ValidateElementCount(doc, incompleteCount, xpath, ResultType.Incomplete);

// Check header data
Assert.IsTrue(text.Contains("Using: axe-core"), "Expected to find 'Using: axe-core'");
Assert.IsTrue(text.Contains($"Violation: {violationCount}"), $"Expected to find 'Violation: {violationCount}'");
Assert.IsTrue(text.Contains($"Incomplete: {incompleteCount}"), $"Expected to find 'Incomplete: {incompleteCount}'");
Assert.IsTrue(text.Contains($"Pass: {passCount}"), $"Expected to find 'Pass: {passCount}'");
Assert.IsTrue(text.Contains($"Inapplicable: {inapplicableCount}"), $"Expected to find 'Inapplicable: {inapplicableCount}'");

if (!violationCount.Equals(0))
{
ValidateResultCount(text, violationCount, ResultType.Violations);
}

if (!passCount.Equals(0))
{
ValidateResultCount(text, passCount, ResultType.Passes);
}

if (!inapplicableCount.Equals(0))
{
ValidateResultCount(text, inapplicableCount, ResultType.Inapplicable);
}

if (!incompleteCount.Equals(0))
{
ValidateResultCount(text, incompleteCount, ResultType.Incomplete);
}
}

private void ValidateElementCount(HtmlDocument doc, int count, string xpath, ResultType resultType)
{
HtmlNodeCollection liNodes = doc.DocumentNode.SelectNodes(xpath) ?? new HtmlNodeCollection(null);
Assert.AreEqual(liNodes.Count, count, $"Expected {count} {resultType}");
}

private void ValidateResultCount(string text, int count, ResultType resultType)
{
Assert.IsTrue(text.Contains($"{resultType}: {count}"), $"Expected to find '{resultType}: {count}'");
}

private void ValidateResultNotWritten(string path, ReportTypes ReportType)
{
string text = File.ReadAllText(path);

foreach (string resultType in ReportType.ToString().Split(','))
{
Assert.IsFalse(text.Contains($"{resultType}: "), $"Expected to not find '{resultType}: '");
}
}

private void LoadSimpleTestPage()
Expand Down Expand Up @@ -281,4 +348,4 @@ private void InitDriver(string browser)
_webDriver.Manage().Window.Maximize();
}
}
}
}
84 changes: 64 additions & 20 deletions Selenium.Axe/Selenium.Axe/HtmlReport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@

namespace Selenium.Axe
{
/// <summary>
/// Findings to include in your HTML
/// </summary>
[Flags]
public enum ReportTypes
{
Violations = 1,
Incomplete = 2,
Inapplicable = 4,
Passes = 8,
All = 15
}

public static class HtmlReport
{
private const string js = @"var buttons = document.getElementsByClassName(""sectionbutton"");
Expand Down Expand Up @@ -52,18 +65,25 @@ public static class HtmlReport
modalimg.alt = thumbnail.alt;
})";

public static void CreateAxeHtmlReport(this IWebDriver webDriver, string destination)
public static void CreateAxeHtmlReport(this IWebDriver webDriver, string destination, ReportTypes requestedResults = ReportTypes.All)
{
var axeBuilder = new AxeBuilder(webDriver);
webDriver.CreateAxeHtmlReport(axeBuilder.Analyze(), destination);
webDriver.CreateAxeHtmlReport(axeBuilder.Analyze(), destination, requestedResults);
}

public static void CreateAxeHtmlReport(this IWebDriver webDriver, IWebElement context, string destination)
public static void CreateAxeHtmlReport(this IWebDriver webDriver, IWebElement context, string destination, ReportTypes requestedResults = ReportTypes.All)
{
var axeBuilder = new AxeBuilder(webDriver);
context.CreateAxeHtmlReport(axeBuilder.Analyze(context), destination);
context.CreateAxeHtmlReportFile(axeBuilder.Analyze(context), destination, requestedResults);
}


public static void CreateAxeHtmlReport(this IWebDriver webdriver, AxeResult results, string destination, ReportTypes requestedResults = ReportTypes.All)
{
webdriver.CreateAxeHtmlReportFile(results, destination, requestedResults);
}
public static void CreateAxeHtmlReport(this ISearchContext context, AxeResult results, string destination)

private static void CreateAxeHtmlReportFile(this ISearchContext context, AxeResult results, string destination, ReportTypes requestedResults)
{
// Get the unwrapped element if we are using a wrapped element
context = context is IWrapsElement ? (context as IWrapsElement).WrappedElement : context;
Expand Down Expand Up @@ -133,13 +153,9 @@ public static void CreateAxeHtmlReport(this ISearchContext context, AxeResult re

var countsContent = doc.CreateElement("div");
countsContent.SetAttributeValue("class", "emOne");
var countsString = new StringBuilder()
.AppendLine($" Violation: {violationCount}<br>")
.AppendLine($" Incomplete: {incompleteCount}<br>")
.AppendLine($" Pass: {passCount}<br>")
.AppendLine($" Inapplicable: {inapplicableCount}")
.ToString();
countsContent.InnerHtml = countsString;
var countsString = GetCountContent(violationCount, incompleteCount, passCount, inapplicableCount, requestedResults);

countsContent.InnerHtml = countsString.ToString();
countsGroup.AppendChild(countsContent);

var resultsFlex = doc.CreateElement("div");
Expand All @@ -158,25 +174,27 @@ public static void CreateAxeHtmlReport(this ISearchContext context, AxeResult re
contentArea.AppendChild(errorContent);
}

if (violationCount > 0)

if (violationCount > 0 && requestedResults.HasFlag(ReportTypes.Violations))
{
GetReadableAxeResults(results.Violations, "Violations", doc, resultsFlex);
GetReadableAxeResults(results.Violations, ResultType.Violations.ToString(), doc, resultsFlex);
}

if (incompleteCount > 0)
if (incompleteCount > 0 && requestedResults.HasFlag(ReportTypes.Incomplete))
{
GetReadableAxeResults(results.Incomplete, "Incomplete", doc, resultsFlex);
GetReadableAxeResults(results.Incomplete, ResultType.Incomplete.ToString(), doc, resultsFlex);
}

if (passCount > 0)
if (passCount > 0 && requestedResults.HasFlag(ReportTypes.Passes))
{
GetReadableAxeResults(results.Passes, "Passes", doc, resultsFlex);
GetReadableAxeResults(results.Passes, ResultType.Passes.ToString(), doc, resultsFlex);
}

if (inapplicableCount > 0)
if (inapplicableCount > 0 && requestedResults.HasFlag(ReportTypes.Inapplicable))
{
GetReadableAxeResults(results.Inapplicable, "Inapplicable", doc, resultsFlex);
GetReadableAxeResults(results.Inapplicable, ResultType.Inapplicable.ToString(), doc, resultsFlex);
}


var modal = doc.CreateElement("div");
modal.SetAttributeValue("id", "modal");
Expand Down Expand Up @@ -282,6 +300,32 @@ private static int GetCount(AxeResultItem[] results, ref HashSet<string> uniqueL
return count;
}

private static string GetCountContent(int violationCount, int incompleteCount, int passCount, int inapplicableCount, ReportTypes requestedResults) {
StringBuilder countString = new StringBuilder();

if (requestedResults.HasFlag(ReportTypes.Violations))
{
countString.AppendLine($" Violation: {violationCount}<br>");
}

if (requestedResults.HasFlag(ReportTypes.Incomplete))
{
countString.AppendLine($" Incomplete: {incompleteCount}<br>");
}

if (requestedResults.HasFlag(ReportTypes.Passes))
{
countString.AppendLine($" Pass: {passCount}<br>");
}

if (requestedResults.HasFlag(ReportTypes.Inapplicable))
{
countString.AppendLine($" Inapplicable: {inapplicableCount}");
}

return countString.ToString();
}

private static void GetReadableAxeResults(AxeResultItem[] results, string type, HtmlDocument doc, HtmlNode body)
{
var selectors = new HashSet<string>();
Expand Down
11 changes: 11 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,17 @@ var builder = new AxeBuilder(webDriver).DisableRules("color-contrast");
webDriver.CreateAxeHtmlReport(builder.Analyze(), path);
```

Report with only violations and passes:

```csharp
IWebDriver webDriver = new ChromeDriver();
// Navigate to page
AxeResult results = new AxeBuilder(webDriver).Analyze();
string path = Path.Combine(GetDestFolder(), "AxeReport.html");
```

webDriver.CreateAxeHtmlReport(path, ReportTypes.Violations | ReportTypes.Passes);

## Contributing

*Please note that this project is released with a [Contributor Code of Conduct](https://github.com/TroyWalshProf/SeleniumAxeDotnet/blob/master/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.*
Expand Down

0 comments on commit b943062

Please sign in to comment.