Skip to content

Commit 45cefe2

Browse files
authored
Merge pull request #1073 from TechnologyEnhancedLearning/RC
Merge RC changes to master
2 parents 0188dd0 + 1f3026d commit 45cefe2

File tree

296 files changed

+39065
-660
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

296 files changed

+39065
-660
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,4 @@ obj
5252
/OpenAPI/LearningHub.Nhs.OpenApi/web.config
5353
/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj.user
5454
/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj.user
55+
/ReportAPI/LearningHub.Nhs.ReportApi/web.config

AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
<PackageReference Include="HtmlSanitizer" Version="6.0.453" />
9090
<PackageReference Include="IdentityModel" Version="4.6.0" />
9191
<PackageReference Include="LearningHub.Nhs.Caching" Version="2.0.2" />
92-
<PackageReference Include="LearningHub.Nhs.Models" Version="3.0.47" />
92+
<PackageReference Include="LearningHub.Nhs.Models" Version="3.0.48" />
9393
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.19.0" />
9494
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.36" />
9595
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.36" />

AdminUI/LearningHub.Nhs.AdminUI/Scripts/vuesrc/mkiomediaplayer.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ interface PlayerConfig {
2222
}
2323

2424
interface SourceConfig {
25+
enableLowLatency: boolean;
2526
hls: string;
2627
drm: {
2728
clearkey: ClearKeyConfig;
@@ -57,6 +58,7 @@ function getSourceConfig(
5758
authenticationToken: string
5859
): SourceConfig {
5960
return {
61+
enableLowLatency: true,
6062
hls: locatorUri,
6163
drm: {
6264
clearkey: {
@@ -81,6 +83,7 @@ function initializePlayer(videoContainer: HTMLElement, playerConfig: MKPlayerCon
8183
};
8284

8385
const sourceConfig: SourceConfig = {
86+
enableLowLatency: true,
8487
hls: playBackUrl,
8588
drm: {
8689
clearkey: clearKeyConfig

AdminUI/LearningHub.Nhs.AdminUI/Services/MKIOMediaService.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,21 @@ public async Task<string> CreateMediaInputAsset(IFormFile file)
9191
/// <returns>.</returns>
9292
public async Task<BlobDownloadResult> DownloadMediaInputAsset(string inputAssetName, string fileName)
9393
{
94-
IAzureMediaServicesClient client = await this.CreateMediaServicesClientAsync();
94+
var client = this.GetMKIOServicesClientAsync();
95+
var assets = client.Assets.Get(inputAssetName);
96+
97+
BlobServiceClient blobServiceClient = new BlobServiceClient(this.settings.MediaKindSettings.MediaKindStorageConnectionString);
9598

96-
AssetContainerSas assetContainerSas = await client.Assets.ListContainerSasAsync(
97-
this.settings.AzureMediaResourceGroup,
98-
this.settings.AzureMediaAccountName,
99-
inputAssetName,
100-
permissions: AssetContainerPermission.Read,
101-
expiryTime: DateTime.UtcNow.AddHours(1).ToUniversalTime());
99+
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(assets.Properties.Container);
100+
if (!await containerClient.ExistsAsync().ConfigureAwait(false))
101+
{
102+
await containerClient.CreateIfNotExistsAsync().ConfigureAwait(false);
103+
}
102104

103-
string sasUri = assetContainerSas.AssetContainerSasUrls.First();
105+
var filename1 = Regex.Replace(fileName, "[^a-zA-Z0-9.]", string.Empty);
106+
filename1 = string.IsNullOrEmpty(filename1) ? "file.txt" : filename1;
104107

105-
var blobServiceClient = new BlobContainerClient(new Uri(sasUri));
106-
var blobClient = blobServiceClient.GetBlockBlobClient(fileName);
108+
BlobClient blobClient = containerClient.GetBlobClient(filename1);
107109
var fileContent = await blobClient.DownloadContentAsync();
108110

109111
return fileContent;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests
2+
{
3+
using FluentAssertions;
4+
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures;
5+
using LearningHub.Nhs.WebUI.Startup;
6+
using OpenQA.Selenium;
7+
using Selenium.Axe;
8+
using Xunit;
9+
10+
/// <summary>
11+
/// Accessibility Tests Base.
12+
/// </summary>
13+
[Collection("Selenium test collection")]
14+
public class AccessibilityTestsBase
15+
{
16+
/// <summary>
17+
/// Gets the base URL for the tests.
18+
/// </summary>
19+
internal readonly string BaseUrl;
20+
21+
/// <summary>
22+
/// Gets the WebDriver used for the tests.
23+
/// </summary>
24+
internal readonly IWebDriver Driver;
25+
26+
/// <summary>
27+
/// Initializes a new instance of the <see cref="AccessibilityTestsBase"/> class.
28+
/// </summary>
29+
/// <param name="fixture">fixture.</param>
30+
public AccessibilityTestsBase(AccessibilityTestsFixture fixture)
31+
{
32+
this.BaseUrl = fixture.BaseUrl;
33+
this.Driver = fixture.Driver;
34+
}
35+
36+
/// <summary>
37+
/// Analyze Page Heading And Accessibility.
38+
/// </summary>
39+
/// <param name="pageTitle">Page Title.</param>
40+
public void AnalyzePageHeadingAndAccessibility(string pageTitle)
41+
{
42+
this.ValidatePageHeading(pageTitle);
43+
44+
// then
45+
// Exclude conditional radios, see: https://github.com/alphagov/govuk-frontend/issues/979#issuecomment-872300557
46+
var axeResult = new AxeBuilder(this.Driver).Exclude("div.nhsuk-radios--conditional div.nhsuk-radios__item input.nhsuk-radios__input").Analyze();
47+
axeResult.Violations.Where(v => !v.Tags.Contains("best-practice")).Should().BeEmpty();
48+
}
49+
50+
/// <summary>
51+
/// ValidatePageHeading.
52+
/// </summary>
53+
/// <param name="pageTitle">Page Title.</param>
54+
public void ValidatePageHeading(string pageTitle)
55+
{
56+
var h1Element = this.Driver.FindElement(By.TagName("h1"));
57+
h1Element.Text.Should().BeEquivalentTo(pageTitle);
58+
}
59+
}
60+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests
2+
{
3+
using FluentAssertions;
4+
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures;
5+
using Selenium.Axe;
6+
using Xunit;
7+
8+
/// <summary>
9+
/// BasicAccessibilityTests.
10+
/// </summary>
11+
public class BasicAccessibilityTests : AccessibilityTestsBase, IClassFixture<AccessibilityTestsFixture>
12+
{
13+
/// <summary>
14+
/// Initializes a new instance of the <see cref="BasicAccessibilityTests"/> class.
15+
/// BasicAccessibilityTests.
16+
/// </summary>
17+
/// <param name="fixture">fixture.</param>
18+
public BasicAccessibilityTests(AccessibilityTestsFixture fixture)
19+
: base(fixture)
20+
{
21+
}
22+
23+
/// <summary>
24+
/// PageHasNoAccessibilityErrors.
25+
/// </summary>
26+
/// <param name="url">url to the page.</param>
27+
/// <param name="pageTitle">title of the page.</param>
28+
[Theory]
29+
[InlineData("/forgotten-password", "Forgotten your username or password")]
30+
[InlineData("/Login", "Access your Learning Hub account")]
31+
[InlineData("/Home/Contactus", "Contact us")]
32+
[InlineData("/Home/Aboutus", "About us")]
33+
[InlineData("/Updates", "Service updates and releases")]
34+
[InlineData("/Policies", "Our policies")]
35+
[InlineData("/Home/Accessibility", "Accessibility Statement for the NHS England Learning Hub")]
36+
[InlineData("/Home/NHSsites", "NHS sites")]
37+
[InlineData("/policies/terms-and-conditions", "NHS England Learning Hub Terms and Conditions of Use (‘Terms’)")]
38+
[InlineData("/policies/content-policy", "NHS England Learning Hub Content Policy")]
39+
[InlineData("/policies/privacy-policy", "PRIVACY NOTICE")]
40+
[InlineData("/policies/cookie-policy", "Cookie policy")]
41+
[InlineData("/policies/acceptable-use-policy", "ACCEPTABLE USE POLICY")]
42+
43+
public void PageHasNoAccessibilityErrors(string url, string pageTitle)
44+
{
45+
// when
46+
this.Driver.Navigate().GoToUrl(this.BaseUrl + url);
47+
48+
// then
49+
this.AnalyzePageHeadingAndAccessibility(pageTitle);
50+
51+
////this.Driver.Dispose();
52+
}
53+
}
54+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests
2+
{
3+
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures;
4+
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestHelpers;
5+
using Microsoft.Azure.Management.Media.Models;
6+
using OpenQA.Selenium;
7+
using Xunit;
8+
9+
/// <summary>
10+
/// BasicAuthenticatedAccessibilityTests.
11+
/// </summary>
12+
public class BasicAuthenticatedAccessibilityTests : AccessibilityTestsBase,
13+
IClassFixture<AuthenticatedAccessibilityTestsFixture>
14+
{
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="BasicAuthenticatedAccessibilityTests"/> class.
17+
/// BasicAuthenticatedAccessibilityTests.
18+
/// </summary>
19+
/// <param name="fixture">fixture.</param>
20+
public BasicAuthenticatedAccessibilityTests(AuthenticatedAccessibilityTestsFixture fixture)
21+
: base(fixture)
22+
{
23+
}
24+
25+
/// <summary>
26+
/// Authenticated Page Has no Accessibility Errors.
27+
/// </summary>
28+
/// <param name="url">url.</param>
29+
/// <param name="pageTitle">pageTitle.</param>
30+
[Theory]
31+
[InlineData("/myaccount", "My account details")]
32+
[InlineData("/MyLearning", "My learning")]
33+
[InlineData("/allcatalogue", "A-Z of catalogues")]
34+
[InlineData("/allcataloguesearch?term=primary#searchTab", "Search results for primary")]
35+
public void AuthenticatedPageHasNoAccessibilityErrors(string url, string pageTitle)
36+
{
37+
// when
38+
this.Driver.Navigate().GoToUrl(this.BaseUrl + url);
39+
40+
// then
41+
this.AnalyzePageHeadingAndAccessibility(pageTitle);
42+
43+
// Dispose driver
44+
////this.Driver.LogOutUser(this.BaseUrl);
45+
}
46+
}
47+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests
2+
{
3+
using FluentAssertions;
4+
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures;
5+
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestHelpers;
6+
using Microsoft.AspNetCore.Components.Web;
7+
using OpenQA.Selenium;
8+
using Selenium.Axe;
9+
using Xunit;
10+
11+
/// <summary>
12+
/// Bookmarks Tests.
13+
/// </summary>
14+
public class BookmarksTests : AccessibilityTestsBase,
15+
IClassFixture<AuthenticatedAccessibilityTestsFixture>
16+
{
17+
/// <summary>
18+
/// Initializes a new instance of the <see cref="BookmarksTests"/> class.
19+
/// </summary>
20+
/// <param name="fixture">fixture.</param>
21+
public BookmarksTests(AuthenticatedAccessibilityTestsFixture fixture)
22+
: base(fixture)
23+
{
24+
}
25+
26+
/// <summary>
27+
/// BookmarksPageHasNoAccessibilityErrors.
28+
/// </summary>
29+
[Fact]
30+
public void BookmarksPageHasNoAccessibilityErrors()
31+
{
32+
// given
33+
const string resourceUrl = "/Resource/17844/Item";
34+
const string resourceProdUrl = "/Resource/48180/Item";
35+
const string addBookmarkPageUrl = "/bookmark/resource?bookmarked=False&title=Understanding%20and%20managing%20conflict%20in%20children%27s%20healthcare&rri=16593&returnUrl=%2FResource%2F16593%2FItem";
36+
const string myBookmarksPage = "/bookmark";
37+
const string bookmarkname = "Primary care clinicians";
38+
IWebElement renameBookmarkElement = null;
39+
IWebElement addBookmarkElement = null;
40+
IWebElement moveBookmarkElement = null;
41+
AxeResult addBookmarkPageResult = null;
42+
43+
// when
44+
this.Driver.Navigate().GoToUrl(this.BaseUrl + resourceProdUrl);
45+
46+
var h1Element = this.Driver.FindElement(By.TagName("h1"));
47+
if (h1Element.Text == "Unknown error" || h1Element.Text != bookmarkname)
48+
{
49+
this.Driver.Navigate().GoToUrl(this.BaseUrl + resourceUrl);
50+
}
51+
52+
try
53+
{
54+
addBookmarkElement = this.Driver.FindElement(By.XPath("//a[contains(text(),'Add to my bookmarks')]"));
55+
if (addBookmarkElement.Displayed)
56+
{
57+
this.Driver.ClickLinkContainingText("Add to my bookmarks");
58+
this.ValidatePageHeading("Add bookmark");
59+
addBookmarkPageResult = new AxeBuilder(this.Driver).Exclude("div.nhsuk-radios--conditional div.nhsuk-radios__item input.nhsuk-radios__input").Analyze();
60+
this.Driver.ClickButtonByText("Continue");
61+
}
62+
}
63+
catch (NoSuchElementException)
64+
{
65+
this.Driver.Navigate().GoToUrl(this.BaseUrl + addBookmarkPageUrl);
66+
this.ValidatePageHeading("Add bookmark");
67+
addBookmarkPageResult = new AxeBuilder(this.Driver).Exclude("div.nhsuk-radios--conditional div.nhsuk-radios__item input.nhsuk-radios__input").Analyze();
68+
this.Driver.ClickLinkContainingText("Cancel");
69+
}
70+
71+
this.Driver.Navigate().GoToUrl(this.BaseUrl + myBookmarksPage);
72+
this.ValidatePageHeading("Bookmarked learning");
73+
var myBookmarksPageResult = new AxeBuilder(this.Driver).Exclude("div.nhsuk-radios--conditional div.nhsuk-radios__item input.nhsuk-radios__input").Analyze();
74+
75+
this.Driver.ClickLinkContainingText("Add a folder");
76+
this.ValidatePageHeading("Add a folder");
77+
var addBookmarkFolderPageResult = new AxeBuilder(this.Driver).Exclude("div.nhsuk-radios--conditional div.nhsuk-radios__item input.nhsuk-radios__input").Analyze();
78+
this.Driver.ClickLinkContainingText("Cancel");
79+
80+
renameBookmarkElement = this.Driver.FindElement(By.XPath($"//tr[td//span[contains(text(), '{bookmarkname}')]]//td//div//form//span//button[contains(text(), 'Rename')]"));
81+
renameBookmarkElement.Click();
82+
this.ValidatePageHeading("Rename bookmark");
83+
var renameBookmarkPageResult = new AxeBuilder(this.Driver).Exclude("div.nhsuk-radios--conditional div.nhsuk-radios__item input.nhsuk-radios__input").Analyze();
84+
this.Driver.ClickLinkContainingText("Cancel");
85+
86+
moveBookmarkElement = this.Driver.FindElement(By.XPath($"//tr[td//span[contains(text(), '{bookmarkname}')]]//td//div//form//span//button[contains(text(), 'Move')]"));
87+
moveBookmarkElement.Click();
88+
this.ValidatePageHeading("Move your bookmark");
89+
var moveBookmarkPageResult = new AxeBuilder(this.Driver).Exclude("div.nhsuk-radios--conditional div.nhsuk-radios__item input.nhsuk-radios__input").Analyze();
90+
this.Driver.ClickLinkContainingText("Cancel");
91+
92+
// then
93+
addBookmarkPageResult.Violations.Where(v => !v.Tags.Contains("best-practice")).Should().BeEmpty();
94+
myBookmarksPageResult.Violations.Where(v => !v.Tags.Contains("best-practice")).Should().BeEmpty();
95+
addBookmarkFolderPageResult.Violations.Where(v => !v.Tags.Contains("best-practice")).Should().BeEmpty();
96+
renameBookmarkPageResult.Violations.Where(v => !v.Tags.Contains("best-practice")).Should().BeEmpty();
97+
moveBookmarkPageResult.Violations.Where(v => !v.Tags.Contains("best-practice")).Should().BeEmpty();
98+
}
99+
}
100+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
namespace LearningHub.Nhs.WebUI.AutomatedUiTests.AccessibilityTests
2+
{
3+
using FluentAssertions;
4+
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestFixtures;
5+
using LearningHub.Nhs.WebUI.AutomatedUiTests.TestHelpers;
6+
using Selenium.Axe;
7+
using Xunit;
8+
9+
/// <summary>
10+
/// Catalogue Folder Content Tests.
11+
/// </summary>
12+
public class CatalogueFolderContentTests : AccessibilityTestsBase,
13+
IClassFixture<AuthenticatedAccessibilityTestsFixture>
14+
{
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="CatalogueFolderContentTests"/> class.
17+
/// </summary>
18+
/// <param name="fixture">fixture.</param>
19+
public CatalogueFolderContentTests(AuthenticatedAccessibilityTestsFixture fixture)
20+
: base(fixture)
21+
{
22+
}
23+
24+
/// <summary>
25+
/// DashboardPageHasNoAccessibilityErrors.
26+
/// </summary>
27+
[Fact]
28+
public void CatalogueFolderContentPageHasNoAccessibilityErrors()
29+
{
30+
// given
31+
const string catalogueUrl = "/catalogue/Neonatal-AHP";
32+
33+
// when
34+
this.Driver.Navigate().GoToUrl(this.BaseUrl + catalogueUrl);
35+
this.ValidatePageHeading("Enhanced Modules for Allied Health Professionals Working in Neonatal Care");
36+
var cataloguePageResult = new AxeBuilder(this.Driver).Exclude("div.nhsuk-radios--conditional div.nhsuk-radios__item input.nhsuk-radios__input").Analyze();
37+
38+
////this.Driver.ClickLinkContainingText("Manage this catalogue");
39+
////this.ValidatePageHeading("Catalogue Management");
40+
////var catalogueManagementPageResult = new AxeBuilder(this.Driver).Exclude("div.nhsuk-radios--conditional div.nhsuk-radios__item input.nhsuk-radios__input").Analyze();
41+
42+
// then
43+
cataloguePageResult.Violations.Where(v => !v.Tags.Contains("best-practice")).Should().BeEmpty();
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)