Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ obj
/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.jfm
/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Database/LearningHub.Nhs.Migration.Staging.Database.dbmdl
/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Database/LearningHub.Nhs.Migration.Staging.Database.jfm
/LearningHub.Nhs.WebUI.AutomatedUiTests/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests
{
using FluentAssertions;
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures;
using LearningHub.Nhs.WebUI.Startup;
using OpenQA.Selenium;
using Selenium.Axe;
using Xunit;

/// <summary>
/// Accessibility Tests Base.
/// </summary>
[Collection("Selenium test collection")]
public class AccessibilityTestsBase
{
/// <summary>
/// Gets the base URL for the tests.
/// </summary>
internal readonly string BaseUrl;

/// <summary>
/// Gets the WebDriver used for the tests.
/// </summary>
internal readonly IWebDriver Driver;

/// <summary>
/// Initializes a new instance of the <see cref="AccessibilityTestsBase"/> class.
/// </summary>
/// <param name="fixture">fixture.</param>
public AccessibilityTestsBase(AccessibilityTestsFixture fixture)
{
this.BaseUrl = fixture.BaseUrl;
this.Driver = fixture.Driver;
}

/// <summary>
/// Analyze Page Heading And Accessibility.
/// </summary>
/// <param name="pageTitle">Page Title.</param>
public void AnalyzePageHeadingAndAccessibility(string pageTitle)
{
this.ValidatePageHeading(pageTitle);

// then
var axeResult = new AxeBuilder(this.Driver).Analyze();
axeResult.Violations.Should().BeEmpty();
}

/// <summary>
/// ValidatePageHeading.
/// </summary>
/// <param name="pageTitle">Page Title.</param>
public void ValidatePageHeading(string pageTitle)
{
var h1Element = this.Driver.FindElement(By.TagName("h1"));
h1Element.Text.Should().BeEquivalentTo(pageTitle);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests
{
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures;
using Xunit;

/// <summary>
/// BasicAccessibilityTests.
/// </summary>
public class BasicAccessibilityTests : AccessibilityTestsBase, IClassFixture<AccessibilityTestsFixture>
{
/// <summary>
/// Initializes a new instance of the <see cref="BasicAccessibilityTests"/> class.
/// BasicAccessibilityTests.
/// </summary>
/// <param name="fixture">fixture.</param>
public BasicAccessibilityTests(AccessibilityTestsFixture fixture)
: base(fixture)
{
}

[Theory]
[InlineData("/Home/Index", "A platform for learning and sharing resources")]

public void PageHasNoAccessibilityErrors(string url, string pageTitle)
{
// when
this.Driver.Navigate().GoToUrl(this.BaseUrl + url);

// then
this.AnalyzePageHeadingAndAccessibility(pageTitle);

this.Driver.Dispose();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests
{
using FluentAssertions;
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures;
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestHelpers;
using Selenium.Axe;
using Xunit;

/// <summary>
/// MyAccountAccessibiltyTests.
/// </summary>
public class MyAccountAccessibiltyTests : AccessibilityTestsBase,
IClassFixture<AuthenticatedAccessibilityTestsFixture>
{
/// <summary>
/// Initializes a new instance of the <see cref="MyAccountAccessibiltyTests"/> class.
/// MyAccountAccessibiltyTests.
/// </summary>
/// <param name="fixture">fixture.</param>
public MyAccountAccessibiltyTests(AuthenticatedAccessibilityTestsFixture fixture)
: base(fixture)
{
}

/// <summary>
/// MyAccount Page Has Accessibility Errors.
/// </summary>
[Fact]
public void MyAccountPageHasAccessibilityErrors()
{
// given
const string myaccountsUrl = "/myaccount";

// when
this.Driver.Navigate().GoToUrl(this.BaseUrl + myaccountsUrl);
var result = new AxeBuilder(this.Driver).Analyze();

// then
CheckAccessibilityResult(result);

// Dispose driver
this.Driver.LogOutUser(this.BaseUrl);
}

private static void CheckAccessibilityResult(AxeResult result)
{
// Expect axe violation
result.Violations.Should().HaveCount(6);

var violation = result.Violations[1];

violation.Id.Should().Be("landmark-contentinfo-is-top-level");
violation.Nodes.Should().HaveCount(1);
violation.Nodes[0].Target.Should().HaveCount(1);
violation.Nodes[0].Target[0].Selector.Should().Be("footer > footer");
}
}
}
13 changes: 13 additions & 0 deletions LearningHub.Nhs.WebUI.AutomatedUiTests/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.

using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Allowed", Scope = "member", Target = "~F:LearningHub.Nhs.WebUI.AutomatedUiTests.SeleniumServerFactory.RootUri")]
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Allowed", Scope = "member", Target = "~F:LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures.AccessibilityTestsFixture.Driver")]
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Allowed", Scope = "member", Target = "~F:LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures.AccessibilityTestsFixture.BaseUrl")]
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Allowed", Scope = "member", Target = "~F:LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests.AccessibilityTestsBase.BaseUrl")]
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Allowed", Scope = "member", Target = "~F:LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests.AccessibilityTestsBase.Driver")]
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Regions allowed", Scope = "member", Target = "~M:LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests.BasicAccessibilityTests.PageHasNoAccessibilityErrors(System.String,System.String)")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>

<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<None Remove="appsettings.Development.json" />
<None Remove="appsettings.json" />
</ItemGroup>

<ItemGroup>
<Content Include="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.13" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="Selenium.Axe" Version="4.0.16" />
<PackageReference Include="Selenium.Support" Version="4.17.0" />
<PackageReference Include="Selenium.WebDriver" Version="4.17.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="121.0.6167.18400" />
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.3.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\LearningHub.Nhs.WebUI\LearningHub.Nhs.WebUI.csproj" />
</ItemGroup>

</Project>
41 changes: 41 additions & 0 deletions LearningHub.Nhs.WebUI.AutomatedUiTests/SeleniumServerFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace LearningHub.Nhs.WebUI.AutomatedUiTests
{
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestHelpers;
using LearningHub.Nhs.WebUI.Startup;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using Serilog;

/// <summary>
/// SeleniumServerFactory.
/// </summary>
public class SeleniumServerFactory
{
/// <summary>
/// Root Uri.
/// </summary>
public string RootUri;

/// <summary>
/// Initializes a new instance of the <see cref="SeleniumServerFactory"/> class.
/// </summary>
public SeleniumServerFactory()
{
IConfiguration configuration = ConfigurationHelper.GetConfiguration();
this.RootUri = configuration["LearningHubWebUiUrl"];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures
{
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestHelpers;
using OpenQA.Selenium;

/// <summary>
/// Represents a fixture for accessibility tests.
/// </summary>
public class AccessibilityTestsFixture
{
/// <summary>
/// Gets the base URL for the tests.
/// </summary>
internal readonly string BaseUrl;

/// <summary>
/// Gets the WebDriver used for the tests.
/// </summary>
internal readonly IWebDriver Driver;

private readonly SeleniumServerFactory factory;

/// <summary>
/// Initializes a new instance of the <see cref="AccessibilityTestsFixture"/> class.
/// </summary>
public AccessibilityTestsFixture()
{
this.factory = new SeleniumServerFactory();
this.BaseUrl = this.factory.RootUri;
this.Driver = DriverHelper.CreateHeadlessChromeDriver();
}

/// <summary>
/// Dispose.
/// </summary>
public void Dispose()
{
this.Driver.Quit();
this.Driver.Dispose();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures
{
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestHelpers;
using Microsoft.Extensions.Configuration;

/// <summary>
/// AuthenticatedAccessibilityTestsFixture.
/// </summary>
/// <typeparam name="TStartup">TStartup.</typeparam>
public class AuthenticatedAccessibilityTestsFixture : AccessibilityTestsFixture
{
/// <summary>
/// Initializes a new instance of the <see cref="AuthenticatedAccessibilityTestsFixture"/> class.
/// </summary>
public AuthenticatedAccessibilityTestsFixture()
{
IConfiguration configuration = ConfigurationHelper.GetConfiguration();
string adminUsername = configuration["AdminUser:Username"];
string adminPassword = configuration["AdminUser:Password"];
this.Driver.LogUserInAsAdmin(this.BaseUrl, adminUsername, adminPassword);
}

/// <summary>
/// Dispose.
/// </summary>
public new void Dispose()
{
this.Driver.LogOutUser(this.BaseUrl);
base.Dispose();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.TestHelpers
{
using Microsoft.Extensions.Configuration;

/// <summary>
/// ConfigurationHelper.
/// </summary>
public static class ConfigurationHelper
{
/// <summary>
/// GetConfiguration.
/// </summary>
/// <returns>IConfiguration.</returns>
public static IConfiguration GetConfiguration()
{
return new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.Development.json")
.Build();
}
}
}
Loading