From 3968558d5641ab90718aba5f9724156c1a8e2b21 Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Wed, 20 Nov 2024 13:37:00 +0000 Subject: [PATCH 01/21] add contact link to error message --- .../Controllers/QuestionsController.cs | 12 +++++++++++- src/Dfe.PlanTech.Web/Views/Pages/Page.cshtml | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index 843755849..012041bb9 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -3,6 +3,7 @@ using Dfe.PlanTech.Domain.Persistence.Models; using Dfe.PlanTech.Domain.Questionnaire.Interfaces; using Dfe.PlanTech.Domain.Questionnaire.Models; +using Dfe.PlanTech.Domain.Content.Models; using Dfe.PlanTech.Domain.Submissions.Interfaces; using Dfe.PlanTech.Domain.Users.Interfaces; using Dfe.PlanTech.Web.Helpers; @@ -97,7 +98,16 @@ public async Task GetNextUnansweredQuestion(string sectionSlug, { // Remove the current invalid submission and redirect to self-assessment page await deleteCurrentSubmissionCommand.DeleteCurrentSubmission(section, cancellationToken); - TempData["SubtopicError"] = configuration["ErrorMessages:ConcurrentUsersOrContentChange"]; + + var contactLink = await _getEntityFromContentfulQuery.GetEntityById(configuration["ContactUs:LinkId"]); + var errorMessage = configuration["ErrorMessages:ConcurrentUsersOrContentChange"]; + + if (contactLink != null && !string.IsNullOrEmpty(contactLink.Href)) + { + errorMessage = errorMessage.Replace("contact us", $"contact us"); + } + + TempData["SubtopicError"] = errorMessage; return RedirectToAction( PagesController.GetPageByRouteAction, PagesController.ControllerName, diff --git a/src/Dfe.PlanTech.Web/Views/Pages/Page.cshtml b/src/Dfe.PlanTech.Web/Views/Pages/Page.cshtml index 4bd9fbde3..faafaf9ec 100644 --- a/src/Dfe.PlanTech.Web/Views/Pages/Page.cshtml +++ b/src/Dfe.PlanTech.Web/Views/Pages/Page.cshtml @@ -21,7 +21,7 @@ @if (!string.IsNullOrEmpty(error)) { -
@error
+
@Html.Raw(error)
} From cb0a481dfe815b7eb17c4b1306339e649bb1e917 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:44:09 +0000 Subject: [PATCH 02/21] chore: Linted code for plan-technology-for-your-school.sln solution --- src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index 012041bb9..aeccb8cbc 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -1,9 +1,9 @@ using Dfe.PlanTech.Application.Exceptions; using Dfe.PlanTech.Domain.Content.Interfaces; +using Dfe.PlanTech.Domain.Content.Models; using Dfe.PlanTech.Domain.Persistence.Models; using Dfe.PlanTech.Domain.Questionnaire.Interfaces; using Dfe.PlanTech.Domain.Questionnaire.Models; -using Dfe.PlanTech.Domain.Content.Models; using Dfe.PlanTech.Domain.Submissions.Interfaces; using Dfe.PlanTech.Domain.Users.Interfaces; using Dfe.PlanTech.Web.Helpers; From 291d34901204b31c03c2b41c4dbb65ab8b9c9f7d Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Wed, 20 Nov 2024 16:14:03 +0000 Subject: [PATCH 03/21] add private method --- .../Controllers/QuestionsController.cs | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index aeccb8cbc..22aeddf97 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -99,15 +99,7 @@ public async Task GetNextUnansweredQuestion(string sectionSlug, // Remove the current invalid submission and redirect to self-assessment page await deleteCurrentSubmissionCommand.DeleteCurrentSubmission(section, cancellationToken); - var contactLink = await _getEntityFromContentfulQuery.GetEntityById(configuration["ContactUs:LinkId"]); - var errorMessage = configuration["ErrorMessages:ConcurrentUsersOrContentChange"]; - - if (contactLink != null && !string.IsNullOrEmpty(contactLink.Href)) - { - errorMessage = errorMessage.Replace("contact us", $"contact us"); - } - - TempData["SubtopicError"] = errorMessage; + TempData["SubtopicError"] = await BuildErrorMessage(configuration); return RedirectToAction( PagesController.GetPageByRouteAction, PagesController.ControllerName, @@ -115,6 +107,19 @@ public async Task GetNextUnansweredQuestion(string sectionSlug, } } + private async Task BuildErrorMessage(IConfiguration configuration) + { + var contactLink = await _getEntityFromContentfulQuery.GetEntityById(configuration["ContactUs:LinkId"]); + var errorMessage = configuration["ErrorMessages:ConcurrentUsersOrContentChange"]; + + if (contactLink != null && !string.IsNullOrEmpty(contactLink.Href)) + { + errorMessage = errorMessage.Replace("contact us", $"contact us"); + } + + return errorMessage; + } + [HttpPost("{sectionSlug}/{questionSlug}")] public async Task SubmitAnswer( string sectionSlug, From 7ab8ad8babbe2167cfe5faf0228d7c3ee2c851f7 Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Thu, 21 Nov 2024 10:09:17 +0000 Subject: [PATCH 04/21] add class for config error mesage --- src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs | 4 ++++ .../Controllers/QuestionsController.cs | 8 ++++++-- src/Dfe.PlanTech.Web/Program.cs | 1 + .../Controllers/QuestionsControllerTests.cs | 13 ++++++++++++- .../Routing/GetQuestionBySlugRouterTests.cs | 4 +++- 5 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs diff --git a/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs new file mode 100644 index 000000000..2b09df2ef --- /dev/null +++ b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs @@ -0,0 +1,4 @@ +public class ErrorMessages +{ + public string ConcurrentUsersOrContentChange { get; set; } +} \ No newline at end of file diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index 22aeddf97..39072ea22 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -11,6 +11,7 @@ using Dfe.PlanTech.Web.Routing; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; namespace Dfe.PlanTech.Web.Controllers; @@ -25,17 +26,20 @@ public class QuestionsController : BaseController private readonly IGetLatestResponsesQuery _getResponseQuery; private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery; private readonly IUser _user; + private readonly ErrorMessages _errorMessages; public QuestionsController(ILogger logger, IGetSectionQuery getSectionQuery, IGetLatestResponsesQuery getResponseQuery, IGetEntityFromContentfulQuery getEntityByIdQuery, - IUser user) : base(logger) + IUser user, + IOptions errorMessages) : base(logger) { _getResponseQuery = getResponseQuery; _getSectionQuery = getSectionQuery; _getEntityFromContentfulQuery = getEntityByIdQuery; _user = user; + _errorMessages = errorMessages.Value; } [LogInvalidModelState] @@ -110,7 +114,7 @@ public async Task GetNextUnansweredQuestion(string sectionSlug, private async Task BuildErrorMessage(IConfiguration configuration) { var contactLink = await _getEntityFromContentfulQuery.GetEntityById(configuration["ContactUs:LinkId"]); - var errorMessage = configuration["ErrorMessages:ConcurrentUsersOrContentChange"]; + var errorMessage = _errorMessages.ConcurrentUsersOrContentChange; if (contactLink != null && !string.IsNullOrEmpty(contactLink.Href)) { diff --git a/src/Dfe.PlanTech.Web/Program.cs b/src/Dfe.PlanTech.Web/Program.cs index 937afb28a..daaa11855 100644 --- a/src/Dfe.PlanTech.Web/Program.cs +++ b/src/Dfe.PlanTech.Web/Program.cs @@ -27,6 +27,7 @@ } builder.Services.AddCustomTelemetry(); +builder.Services.Configure(builder.Configuration.GetSection("ErrorMessages")); builder.AddContentAndSupportServices() .AddAuthorisationServices() diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs index cf720648f..ca9c5d253 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using NSubstitute; using Xunit; @@ -28,6 +29,7 @@ public class QuestionsControllerTests private readonly IDeleteCurrentSubmissionCommand _deleteCurrentSubmissionCommand; private readonly IGetQuestionBySlugRouter _getQuestionBySlugRouter; private readonly IUser _user; + private readonly IOptions _errorMessages; private readonly QuestionsController _controller; private readonly IConfiguration _configuration; @@ -94,6 +96,13 @@ public QuestionsControllerTests() return null; }); + var message = new ErrorMessages + { + ConcurrentUsersOrContentChange = "An error occurred. Please contact us." + }; + + _errorMessages = Options.Create(message); + _getResponseQuery = Substitute.For(); _getQuestionBySlugRouter = Substitute.For(); _getNextUnansweredQuestionQuery = Substitute.For(); @@ -102,7 +111,7 @@ public QuestionsControllerTests() _user = Substitute.For(); _user.GetEstablishmentId().Returns(EstablishmentId); - _controller = new QuestionsController(_logger, _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user); + _controller = new QuestionsController(_logger, _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user, _errorMessages); } [Fact] @@ -200,10 +209,12 @@ public async Task GetNextUnansweredQuestion_Should_Redirect_To_SelfAssessmentPag var result = await _controller.GetNextUnansweredQuestion(SectionSlug, _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand, _configuration); + var errorMessage = _controller.TempData["SubtopicError"] as string; var redirectResult = result as RedirectToActionResult; Assert.NotNull(redirectResult); Assert.Equal(PagesController.ControllerName, redirectResult.ControllerName); Assert.Equal(PagesController.GetPageByRouteAction, redirectResult.ActionName); + Assert.Contains("Please contact us.", errorMessage); } [Fact] diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs index 9c9931758..a5c268e74 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs @@ -12,6 +12,7 @@ using Dfe.PlanTech.Web.Routing; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using NSubstitute; using Xunit; @@ -23,6 +24,7 @@ public class GetQuestionBySlugRouterTests private readonly ISubmissionStatusProcessor _submissionStatusProcessor = Substitute.For(); private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery = Substitute.For(); private readonly IUser _user = Substitute.For(); + private readonly IOptions _errorMessages = Substitute.For>(); private readonly IGetSectionQuery _getSectionQuery = Substitute.For(); private readonly QuestionsController _controller; @@ -35,7 +37,7 @@ public class GetQuestionBySlugRouterTests public GetQuestionBySlugRouterTests() { - _controller = new QuestionsController(new NullLogger(), _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user); + _controller = new QuestionsController(new NullLogger(), _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user, _errorMessages); _user.GetEstablishmentId().Returns(1); var secondQuestion = new Question() From 2ea1f2f777a1d95d42c6a9799769dd206905848e Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Thu, 21 Nov 2024 10:46:17 +0000 Subject: [PATCH 05/21] add class for config contact information --- src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs | 5 +++++ src/Dfe.PlanTech.Web/Controllers/PagesController.cs | 11 ++++++----- .../Controllers/QuestionsController.cs | 7 +++++-- src/Dfe.PlanTech.Web/Program.cs | 1 + .../Controllers/PagesControllerTests.cs | 10 +++++++++- .../Controllers/QuestionsControllerTests.cs | 11 +++++++++-- .../Routing/GetQuestionBySlugRouterTests.cs | 3 ++- 7 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs diff --git a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs new file mode 100644 index 000000000..a8de1a0cc --- /dev/null +++ b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs @@ -0,0 +1,5 @@ +public class ContactOptions +{ + public string? Email { get; set; } + public string LinkId { get; set; } +} \ No newline at end of file diff --git a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs index 906a63c90..fd61288b2 100644 --- a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs @@ -9,15 +9,17 @@ using Dfe.PlanTech.Web.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; namespace Dfe.PlanTech.Web.Controllers; [LogInvalidModelState] [Route("/")] -public class PagesController(ILogger logger, IGetEntityFromContentfulQuery getEntityByIdQuery) : BaseController(logger) +public class PagesController(ILogger logger, IGetEntityFromContentfulQuery getEntityByIdQuery, IOptions contactOptions) : BaseController(logger) { private readonly ILogger _logger = logger; private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery = getEntityByIdQuery; + private readonly ContactOptions _contactOptions = contactOptions.Value; public const string ControllerName = "Pages"; public const string GetPageByRouteAction = nameof(GetByRoute); public const string NotFoundPage = "NotFoundError"; @@ -44,7 +46,7 @@ public IActionResult Error() [HttpGet(UrlConstants.ServiceUnavailable, Name = UrlConstants.ServiceUnavailable)] public async Task ServiceUnavailable([FromServices] IConfiguration configuration) { - var contactLink = await _getEntityFromContentfulQuery.GetEntityById(configuration["ContactUs:LinkId"]); + var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId); var viewModel = new ServiceUnavailableViewModel { @@ -57,9 +59,8 @@ public async Task ServiceUnavailable([FromServices] IConfiguratio [HttpGet(UrlConstants.NotFound, Name = UrlConstants.NotFound)] public async Task NotFoundError([FromServices] IConfiguration configuration) { - var contentId = configuration["ContactUs:LinkId"]; - var contactLink = await _getEntityFromContentfulQuery.GetEntityById(contentId) ?? - throw new KeyNotFoundException($"Could not find navigation link with Id {contentId}"); + var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId) ?? + throw new KeyNotFoundException($"Could not find navigation link with Id {_contactOptions.LinkId}"); var viewModel = new NotFoundViewModel { diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index 39072ea22..1c7a8d77a 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -27,19 +27,22 @@ public class QuestionsController : BaseController private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery; private readonly IUser _user; private readonly ErrorMessages _errorMessages; + private readonly ContactOptions _contactOptions; public QuestionsController(ILogger logger, IGetSectionQuery getSectionQuery, IGetLatestResponsesQuery getResponseQuery, IGetEntityFromContentfulQuery getEntityByIdQuery, IUser user, - IOptions errorMessages) : base(logger) + IOptions errorMessages, + IOptions contactOptions) : base(logger) { _getResponseQuery = getResponseQuery; _getSectionQuery = getSectionQuery; _getEntityFromContentfulQuery = getEntityByIdQuery; _user = user; _errorMessages = errorMessages.Value; + _contactOptions = contactOptions.Value; } [LogInvalidModelState] @@ -113,7 +116,7 @@ public async Task GetNextUnansweredQuestion(string sectionSlug, private async Task BuildErrorMessage(IConfiguration configuration) { - var contactLink = await _getEntityFromContentfulQuery.GetEntityById(configuration["ContactUs:LinkId"]); + var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId); var errorMessage = _errorMessages.ConcurrentUsersOrContentChange; if (contactLink != null && !string.IsNullOrEmpty(contactLink.Href)) diff --git a/src/Dfe.PlanTech.Web/Program.cs b/src/Dfe.PlanTech.Web/Program.cs index daaa11855..8f99029d0 100644 --- a/src/Dfe.PlanTech.Web/Program.cs +++ b/src/Dfe.PlanTech.Web/Program.cs @@ -28,6 +28,7 @@ builder.Services.AddCustomTelemetry(); builder.Services.Configure(builder.Configuration.GetSection("ErrorMessages")); +builder.Services.Configure(builder.Configuration.GetSection("ContactUs")); builder.AddContentAndSupportServices() .AddAuthorisationServices() diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs index 7e2ea9541..ae56a7cc9 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using NSubstitute; using Xunit; @@ -29,6 +30,7 @@ public class PagesControllerTests private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery; private readonly PagesController _controller; private readonly ControllerContext _controllerContext; + private readonly IOptions _contactOptions; public PagesControllerTests() { @@ -39,7 +41,13 @@ public PagesControllerTests() _getEntityFromContentfulQuery = Substitute.For(); _getEntityFromContentfulQuery.GetEntityById(Arg.Any()).Returns(new NavigationLink { DisplayText = "contact us", Href = "/contact-us", OpenInNewTab = true }); - _controller = new PagesController(Logger, _getEntityFromContentfulQuery) + var contactUs = new ContactOptions + { + LinkId = "LinkId" + }; + _contactOptions = Options.Create(contactUs); + + _controller = new PagesController(Logger, _getEntityFromContentfulQuery, _contactOptions) { ControllerContext = _controllerContext, TempData = Substitute.For() diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs index ca9c5d253..7d973c57f 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs @@ -30,6 +30,7 @@ public class QuestionsControllerTests private readonly IGetQuestionBySlugRouter _getQuestionBySlugRouter; private readonly IUser _user; private readonly IOptions _errorMessages; + private readonly IOptions _contactOptions; private readonly QuestionsController _controller; private readonly IConfiguration _configuration; @@ -100,9 +101,15 @@ public QuestionsControllerTests() { ConcurrentUsersOrContentChange = "An error occurred. Please contact us." }; - _errorMessages = Options.Create(message); + + var contactUs = new ContactOptions + { + LinkId = "LinkId" + }; + _contactOptions = Options.Create(contactUs); + _getResponseQuery = Substitute.For(); _getQuestionBySlugRouter = Substitute.For(); _getNextUnansweredQuestionQuery = Substitute.For(); @@ -111,7 +118,7 @@ public QuestionsControllerTests() _user = Substitute.For(); _user.GetEstablishmentId().Returns(EstablishmentId); - _controller = new QuestionsController(_logger, _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user, _errorMessages); + _controller = new QuestionsController(_logger, _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user, _errorMessages, _contactOptions); } [Fact] diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs index a5c268e74..62b72d8ac 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs @@ -25,6 +25,7 @@ public class GetQuestionBySlugRouterTests private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery = Substitute.For(); private readonly IUser _user = Substitute.For(); private readonly IOptions _errorMessages = Substitute.For>(); + private readonly IOptions _contactOptions = Substitute.For>(); private readonly IGetSectionQuery _getSectionQuery = Substitute.For(); private readonly QuestionsController _controller; @@ -37,7 +38,7 @@ public class GetQuestionBySlugRouterTests public GetQuestionBySlugRouterTests() { - _controller = new QuestionsController(new NullLogger(), _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user, _errorMessages); + _controller = new QuestionsController(new NullLogger(), _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user, _errorMessages, _contactOptions); _user.GetEstablishmentId().Returns(1); var secondQuestion = new Question() From 030c7148669f59cfde7cebed884e2f869bf9f8bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:47:53 +0000 Subject: [PATCH 06/21] chore: Linted code for plan-technology-for-your-school.sln solution --- src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs | 2 +- src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs index a8de1a0cc..266842bdb 100644 --- a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs +++ b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs @@ -2,4 +2,4 @@ public class ContactOptions { public string? Email { get; set; } public string LinkId { get; set; } -} \ No newline at end of file +} diff --git a/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs index 2b09df2ef..e5500e4ec 100644 --- a/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs +++ b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs @@ -1,4 +1,4 @@ public class ErrorMessages { public string ConcurrentUsersOrContentChange { get; set; } -} \ No newline at end of file +} From bc6fd63ab7f2cb90beff5ece67cb399eae6ae60b Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Thu, 21 Nov 2024 11:00:14 +0000 Subject: [PATCH 07/21] add missing namespace --- src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs | 2 ++ src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs | 2 ++ src/Dfe.PlanTech.Web/Controllers/PagesController.cs | 1 + src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs | 1 + src/Dfe.PlanTech.Web/Program.cs | 1 + .../Controllers/PagesControllerTests.cs | 1 + .../Controllers/QuestionsControllerTests.cs | 1 + .../Routing/GetQuestionBySlugRouterTests.cs | 1 + 8 files changed, 10 insertions(+) diff --git a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs index 266842bdb..8f620b64b 100644 --- a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs +++ b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs @@ -1,3 +1,5 @@ +namespace Dfe.PlanTech.Web.Configuration; + public class ContactOptions { public string? Email { get; set; } diff --git a/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs index e5500e4ec..848702e65 100644 --- a/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs +++ b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs @@ -1,3 +1,5 @@ +namespace Dfe.PlanTech.Web.Configuration; + public class ErrorMessages { public string ConcurrentUsersOrContentChange { get; set; } diff --git a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs index fd61288b2..f09ae6819 100644 --- a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs @@ -7,6 +7,7 @@ using Dfe.PlanTech.Web.Binders; using Dfe.PlanTech.Web.Helpers; using Dfe.PlanTech.Web.Models; +using Dfe.PlanTech.Web.Configuration; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index 1c7a8d77a..5d91e06ac 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -9,6 +9,7 @@ using Dfe.PlanTech.Web.Helpers; using Dfe.PlanTech.Web.Models; using Dfe.PlanTech.Web.Routing; +using Dfe.PlanTech.Web.Configuration; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; diff --git a/src/Dfe.PlanTech.Web/Program.cs b/src/Dfe.PlanTech.Web/Program.cs index 8f99029d0..b2bbe10d8 100644 --- a/src/Dfe.PlanTech.Web/Program.cs +++ b/src/Dfe.PlanTech.Web/Program.cs @@ -3,6 +3,7 @@ using Dfe.PlanTech.Domain.Interfaces; using Dfe.PlanTech.Infrastructure.ServiceBus; using Dfe.PlanTech.Infrastructure.SignIns; +using Dfe.PlanTech.Web.Configuration; using Dfe.PlanTech.Web; using Dfe.PlanTech.Web.Middleware; using GovUk.Frontend.AspNetCore; diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs index ae56a7cc9..d6a59d926 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs @@ -5,6 +5,7 @@ using Dfe.PlanTech.Domain.Cookie.Interfaces; using Dfe.PlanTech.Domain.Establishments.Models; using Dfe.PlanTech.Domain.Users.Interfaces; +using Dfe.PlanTech.Web.Configuration; using Dfe.PlanTech.Web.Controllers; using Dfe.PlanTech.Web.Models; using Microsoft.AspNetCore.Authentication.Cookies; diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs index 7d973c57f..8dc873c43 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs @@ -6,6 +6,7 @@ using Dfe.PlanTech.Domain.Questionnaire.Models; using Dfe.PlanTech.Domain.Submissions.Interfaces; using Dfe.PlanTech.Domain.Users.Interfaces; +using Dfe.PlanTech.Web.Configuration; using Dfe.PlanTech.Web.Controllers; using Dfe.PlanTech.Web.Models; using Dfe.PlanTech.Web.Routing; diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs index 62b72d8ac..b713df3c3 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs @@ -7,6 +7,7 @@ using Dfe.PlanTech.Domain.Submissions.Interfaces; using Dfe.PlanTech.Domain.Submissions.Models; using Dfe.PlanTech.Domain.Users.Interfaces; +using Dfe.PlanTech.Web.Configuration; using Dfe.PlanTech.Web.Controllers; using Dfe.PlanTech.Web.Models; using Dfe.PlanTech.Web.Routing; From ad84ca5bd5ef2bb9ccaed896fa6e6fc97888fda8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:01:48 +0000 Subject: [PATCH 08/21] chore: Linted code for plan-technology-for-your-school.sln solution --- src/Dfe.PlanTech.Web/Controllers/PagesController.cs | 2 +- src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs | 2 +- src/Dfe.PlanTech.Web/Program.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs index f09ae6819..9e85b229c 100644 --- a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs @@ -5,9 +5,9 @@ using Dfe.PlanTech.Domain.Users.Interfaces; using Dfe.PlanTech.Web.Authorisation; using Dfe.PlanTech.Web.Binders; +using Dfe.PlanTech.Web.Configuration; using Dfe.PlanTech.Web.Helpers; using Dfe.PlanTech.Web.Models; -using Dfe.PlanTech.Web.Configuration; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index 5d91e06ac..9af6758ed 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -6,10 +6,10 @@ using Dfe.PlanTech.Domain.Questionnaire.Models; using Dfe.PlanTech.Domain.Submissions.Interfaces; using Dfe.PlanTech.Domain.Users.Interfaces; +using Dfe.PlanTech.Web.Configuration; using Dfe.PlanTech.Web.Helpers; using Dfe.PlanTech.Web.Models; using Dfe.PlanTech.Web.Routing; -using Dfe.PlanTech.Web.Configuration; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; diff --git a/src/Dfe.PlanTech.Web/Program.cs b/src/Dfe.PlanTech.Web/Program.cs index b2bbe10d8..b3ce9dcf6 100644 --- a/src/Dfe.PlanTech.Web/Program.cs +++ b/src/Dfe.PlanTech.Web/Program.cs @@ -3,8 +3,8 @@ using Dfe.PlanTech.Domain.Interfaces; using Dfe.PlanTech.Infrastructure.ServiceBus; using Dfe.PlanTech.Infrastructure.SignIns; -using Dfe.PlanTech.Web.Configuration; using Dfe.PlanTech.Web; +using Dfe.PlanTech.Web.Configuration; using Dfe.PlanTech.Web.Middleware; using GovUk.Frontend.AspNetCore; From fa6bea903a98cbc45f9d1abdbbb92b3bd731d212 Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Thu, 21 Nov 2024 11:11:38 +0000 Subject: [PATCH 09/21] fix sonarcloud issues --- src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs | 2 +- src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs | 2 +- src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs index 8f620b64b..47d9137b3 100644 --- a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs +++ b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs @@ -3,5 +3,5 @@ namespace Dfe.PlanTech.Web.Configuration; public class ContactOptions { public string? Email { get; set; } - public string LinkId { get; set; } + public string LinkId { get; set; } = ""; } diff --git a/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs index 848702e65..64251217a 100644 --- a/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs +++ b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs @@ -2,5 +2,5 @@ namespace Dfe.PlanTech.Web.Configuration; public class ErrorMessages { - public string ConcurrentUsersOrContentChange { get; set; } + public string ConcurrentUsersOrContentChange { get; set; } = ""; } diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index 9af6758ed..aa5633a14 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -107,7 +107,7 @@ public async Task GetNextUnansweredQuestion(string sectionSlug, // Remove the current invalid submission and redirect to self-assessment page await deleteCurrentSubmissionCommand.DeleteCurrentSubmission(section, cancellationToken); - TempData["SubtopicError"] = await BuildErrorMessage(configuration); + TempData["SubtopicError"] = await BuildErrorMessage(); return RedirectToAction( PagesController.GetPageByRouteAction, PagesController.ControllerName, @@ -115,7 +115,7 @@ public async Task GetNextUnansweredQuestion(string sectionSlug, } } - private async Task BuildErrorMessage(IConfiguration configuration) + private async Task BuildErrorMessage() { var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId); var errorMessage = _errorMessages.ConcurrentUsersOrContentChange; From 6eca68c14473ef99918b358126107b5c27bf7e59 Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Thu, 21 Nov 2024 11:51:59 +0000 Subject: [PATCH 10/21] remove unused configuration arg --- src/Dfe.PlanTech.Web/Controllers/PagesController.cs | 7 ++++--- .../Controllers/QuestionsController.cs | 1 - .../Controllers/PagesControllerTests.cs | 4 ++-- .../Controllers/QuestionsControllerTests.cs | 10 +++++----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs index 9e85b229c..920bf6698 100644 --- a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs @@ -45,9 +45,10 @@ public IActionResult Error() => View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); [HttpGet(UrlConstants.ServiceUnavailable, Name = UrlConstants.ServiceUnavailable)] - public async Task ServiceUnavailable([FromServices] IConfiguration configuration) + public async Task ServiceUnavailable() { - var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId); + var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId) ?? + throw new KeyNotFoundException($"Could not find navigation link with Id {_contactOptions.LinkId}"); var viewModel = new ServiceUnavailableViewModel { @@ -58,7 +59,7 @@ public async Task ServiceUnavailable([FromServices] IConfiguratio } [HttpGet(UrlConstants.NotFound, Name = UrlConstants.NotFound)] - public async Task NotFoundError([FromServices] IConfiguration configuration) + public async Task NotFoundError() { var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId) ?? throw new KeyNotFoundException($"Could not find navigation link with Id {_contactOptions.LinkId}"); diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index aa5633a14..875c0739d 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -83,7 +83,6 @@ public async Task GetQuestionPreviewById(string questionId, public async Task GetNextUnansweredQuestion(string sectionSlug, [FromServices] IGetNextUnansweredQuestionQuery getQuestionQuery, [FromServices] IDeleteCurrentSubmissionCommand deleteCurrentSubmissionCommand, - [FromServices] IConfiguration configuration, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(sectionSlug)) diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs index d6a59d926..770c6e4f3 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs @@ -220,7 +220,7 @@ public async Task Should_Render_Service_Unavailable_Page() _controller.ControllerContext = controllerContext; - var result = _controller.ServiceUnavailable(_configuration); + var result = _controller.ServiceUnavailable(); var viewResult = await result as ViewResult; @@ -260,7 +260,7 @@ public async Task Should_Render_NotFound_Page() HttpContext = httpContextSubstitute }; _controller.ControllerContext = controllerContext; - var result = _controller.NotFoundError(_configuration); + var result = _controller.NotFoundError(); var viewResult = await result as ViewResult; Assert.NotNull(viewResult); } diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs index 8dc873c43..df81135ab 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs @@ -164,19 +164,19 @@ public async Task GetQuestionBySlug_Should_Call_Router_When_Args_Valid() [Fact] public async Task GetNextUnansweredQuestion_Should_Error_When_SectionSlug_Null() { - await Assert.ThrowsAnyAsync(() => _controller.GetNextUnansweredQuestion(null!, _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand, _configuration)); + await Assert.ThrowsAnyAsync(() => _controller.GetNextUnansweredQuestion(null!, _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand)); } [Fact] public async Task GetNextUnansweredQuestion_Should_Error_When_SectionSlug_NotFound() { - await Assert.ThrowsAnyAsync(() => _controller.GetNextUnansweredQuestion("Not a real section", _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand, _configuration)); + await Assert.ThrowsAnyAsync(() => _controller.GetNextUnansweredQuestion("Not a real section", _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand)); } [Fact] public async Task GetNextUnansweredQuestion_Should_Redirect_To_CheckAnswersPage_When_No_Question_Returned() { - var result = await _controller.GetNextUnansweredQuestion(SectionSlug, _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand, _configuration); + var result = await _controller.GetNextUnansweredQuestion(SectionSlug, _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand); var redirectResult = result as RedirectToActionResult; Assert.NotNull(redirectResult); @@ -190,7 +190,7 @@ public async Task GetNextUnansweredQuestion_Should_Redirect_To_GetQuestionBySlug _getNextUnansweredQuestionQuery.GetNextUnansweredQuestion(EstablishmentId, _validSection, Arg.Any()) .Returns((callinfo) => _validQuestion); - var result = await _controller.GetNextUnansweredQuestion(SectionSlug, _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand, _configuration); + var result = await _controller.GetNextUnansweredQuestion(SectionSlug, _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand); var redirectResult = result as RedirectToActionResult; Assert.NotNull(redirectResult); @@ -215,7 +215,7 @@ public async Task GetNextUnansweredQuestion_Should_Redirect_To_SelfAssessmentPag _controller.TempData = Substitute.For(); - var result = await _controller.GetNextUnansweredQuestion(SectionSlug, _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand, _configuration); + var result = await _controller.GetNextUnansweredQuestion(SectionSlug, _getNextUnansweredQuestionQuery, _deleteCurrentSubmissionCommand); var errorMessage = _controller.TempData["SubtopicError"] as string; var redirectResult = result as RedirectToActionResult; From 39442ca7e39931b061b19db5e20c5ef635bdeaea Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Thu, 21 Nov 2024 15:27:42 +0000 Subject: [PATCH 11/21] add method to fetch nav links by id --- .../Content/Queries/GetNavigationQuery.cs | 13 +++++++++++++ .../Content/Interfaces/IGetNavigationQuery.cs | 6 ++++++ .../Controllers/PagesController.cs | 15 +++++++++------ .../Controllers/QuestionsController.cs | 5 ++++- .../Controllers/PagesControllerTests.cs | 9 ++++----- .../Controllers/QuestionsControllerTests.cs | 4 +++- .../Routing/GetQuestionBySlugRouterTests.cs | 3 ++- 7 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs index d3b4df675..8ff114c5b 100644 --- a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs +++ b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs @@ -37,4 +37,17 @@ public async Task> GetNavigationLinks(CancellationT return []; } } + + public async Task GetLinkById(string contentId, CancellationToken cancellationToken = default) + { + try + { + return await _cache.GetOrCreateAsync("NavigationLink", () => repository.GetEntityById(contentId, cancellationToken: cancellationToken)); + } + catch (Exception ex) + { + _logger.LogError(ex, ExceptionMessageContentful); + return null; + } + } } diff --git a/src/Dfe.PlanTech.Domain/Content/Interfaces/IGetNavigationQuery.cs b/src/Dfe.PlanTech.Domain/Content/Interfaces/IGetNavigationQuery.cs index 9c37da7d3..d91c5bceb 100644 --- a/src/Dfe.PlanTech.Domain/Content/Interfaces/IGetNavigationQuery.cs +++ b/src/Dfe.PlanTech.Domain/Content/Interfaces/IGetNavigationQuery.cs @@ -10,4 +10,10 @@ public interface IGetNavigationQuery /// /// Found navigation links Task> GetNavigationLinks(CancellationToken cancellationToken = default); + + /// + /// Retrieve link by id + /// + /// Found navigation link + Task GetLinkById(string contentId, CancellationToken cancellationToken = default); } diff --git a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs index 920bf6698..0b3afbd87 100644 --- a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs @@ -16,10 +16,10 @@ namespace Dfe.PlanTech.Web.Controllers; [LogInvalidModelState] [Route("/")] -public class PagesController(ILogger logger, IGetEntityFromContentfulQuery getEntityByIdQuery, IOptions contactOptions) : BaseController(logger) +public class PagesController(ILogger logger, IGetNavigationQuery getNavigationQuery, IOptions contactOptions) : BaseController(logger) { private readonly ILogger _logger = logger; - private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery = getEntityByIdQuery; + private readonly IGetNavigationQuery _getNavigationQuery = getNavigationQuery; private readonly ContactOptions _contactOptions = contactOptions.Value; public const string ControllerName = "Pages"; public const string GetPageByRouteAction = nameof(GetByRoute); @@ -47,8 +47,7 @@ public IActionResult Error() [HttpGet(UrlConstants.ServiceUnavailable, Name = UrlConstants.ServiceUnavailable)] public async Task ServiceUnavailable() { - var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId) ?? - throw new KeyNotFoundException($"Could not find navigation link with Id {_contactOptions.LinkId}"); + var contactLink = await GetContactLinkAsync(); var viewModel = new ServiceUnavailableViewModel { @@ -61,8 +60,7 @@ public async Task ServiceUnavailable() [HttpGet(UrlConstants.NotFound, Name = UrlConstants.NotFound)] public async Task NotFoundError() { - var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId) ?? - throw new KeyNotFoundException($"Could not find navigation link with Id {_contactOptions.LinkId}"); + var contactLink = await GetContactLinkAsync(); var viewModel = new NotFoundViewModel { @@ -71,4 +69,9 @@ public async Task NotFoundError() return View(viewModel); } + + private async Task GetContactLinkAsync() + { + return await _getNavigationQuery.GetLinkById(_contactOptions.LinkId); + } } diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index 875c0739d..becccb2ac 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -26,6 +26,7 @@ public class QuestionsController : BaseController private readonly IGetSectionQuery _getSectionQuery; private readonly IGetLatestResponsesQuery _getResponseQuery; private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery; + private readonly IGetNavigationQuery _getNavigationQuery; private readonly IUser _user; private readonly ErrorMessages _errorMessages; private readonly ContactOptions _contactOptions; @@ -34,6 +35,7 @@ public QuestionsController(ILogger logger, IGetSectionQuery getSectionQuery, IGetLatestResponsesQuery getResponseQuery, IGetEntityFromContentfulQuery getEntityByIdQuery, + IGetNavigationQuery getNavigationQuery, IUser user, IOptions errorMessages, IOptions contactOptions) : base(logger) @@ -41,6 +43,7 @@ public QuestionsController(ILogger logger, _getResponseQuery = getResponseQuery; _getSectionQuery = getSectionQuery; _getEntityFromContentfulQuery = getEntityByIdQuery; + _getNavigationQuery = getNavigationQuery; _user = user; _errorMessages = errorMessages.Value; _contactOptions = contactOptions.Value; @@ -116,7 +119,7 @@ public async Task GetNextUnansweredQuestion(string sectionSlug, private async Task BuildErrorMessage() { - var contactLink = await _getEntityFromContentfulQuery.GetEntityById(_contactOptions.LinkId); + var contactLink = await _getNavigationQuery.GetLinkById(_contactOptions.LinkId); var errorMessage = _errorMessages.ConcurrentUsersOrContentChange; if (contactLink != null && !string.IsNullOrEmpty(contactLink.Href)) diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs index 770c6e4f3..1d809cad3 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs @@ -27,8 +27,7 @@ public class PagesControllerTests private const string SELF_ASSESSMENT_SLUG = "self-assessment"; readonly ICookieService cookiesSubstitute = Substitute.For(); readonly IUser userSubstitute = Substitute.For(); - private readonly IConfiguration _configuration = Substitute.For(); - private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery; + private readonly IGetNavigationQuery _getNavigationQuery; private readonly PagesController _controller; private readonly ControllerContext _controllerContext; private readonly IOptions _contactOptions; @@ -39,8 +38,8 @@ public PagesControllerTests() _controllerContext = ControllerHelpers.SubstituteControllerContext(); - _getEntityFromContentfulQuery = Substitute.For(); - _getEntityFromContentfulQuery.GetEntityById(Arg.Any()).Returns(new NavigationLink { DisplayText = "contact us", Href = "/contact-us", OpenInNewTab = true }); + _getNavigationQuery = Substitute.For(); + _getNavigationQuery.GetLinkById(Arg.Any()).Returns(new NavigationLink { DisplayText = "contact us", Href = "/contact-us", OpenInNewTab = true }); var contactUs = new ContactOptions { @@ -48,7 +47,7 @@ public PagesControllerTests() }; _contactOptions = Options.Create(contactUs); - _controller = new PagesController(Logger, _getEntityFromContentfulQuery, _contactOptions) + _controller = new PagesController(Logger, _getNavigationQuery, _contactOptions) { ControllerContext = _controllerContext, TempData = Substitute.For() diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs index df81135ab..9a9f1c0ff 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/QuestionsControllerTests.cs @@ -27,6 +27,7 @@ public class QuestionsControllerTests private readonly IGetSectionQuery _getSectionQuery; private readonly IGetLatestResponsesQuery _getResponseQuery; private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery; + private readonly IGetNavigationQuery _getNavigationQuery; private readonly IDeleteCurrentSubmissionCommand _deleteCurrentSubmissionCommand; private readonly IGetQuestionBySlugRouter _getQuestionBySlugRouter; private readonly IUser _user; @@ -72,6 +73,7 @@ public QuestionsControllerTests() _getSectionQuery = Substitute.For(); _getEntityFromContentfulQuery = Substitute.For(); + _getNavigationQuery = Substitute.For(); _getEntityFromContentfulQuery.GetEntityById(Arg.Any(), Arg.Any()) .Returns((callinfo) => @@ -119,7 +121,7 @@ public QuestionsControllerTests() _user = Substitute.For(); _user.GetEstablishmentId().Returns(EstablishmentId); - _controller = new QuestionsController(_logger, _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user, _errorMessages, _contactOptions); + _controller = new QuestionsController(_logger, _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _getNavigationQuery, _user, _errorMessages, _contactOptions); } [Fact] diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs index b713df3c3..9015a5d72 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Routing/GetQuestionBySlugRouterTests.cs @@ -24,6 +24,7 @@ public class GetQuestionBySlugRouterTests private readonly IGetLatestResponsesQuery _getResponseQuery = Substitute.For(); private readonly ISubmissionStatusProcessor _submissionStatusProcessor = Substitute.For(); private readonly IGetEntityFromContentfulQuery _getEntityFromContentfulQuery = Substitute.For(); + private readonly IGetNavigationQuery _getNavigationQuery = Substitute.For(); private readonly IUser _user = Substitute.For(); private readonly IOptions _errorMessages = Substitute.For>(); private readonly IOptions _contactOptions = Substitute.For>(); @@ -39,7 +40,7 @@ public class GetQuestionBySlugRouterTests public GetQuestionBySlugRouterTests() { - _controller = new QuestionsController(new NullLogger(), _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _user, _errorMessages, _contactOptions); + _controller = new QuestionsController(new NullLogger(), _getSectionQuery, _getResponseQuery, _getEntityFromContentfulQuery, _getNavigationQuery, _user, _errorMessages, _contactOptions); _user.GetEstablishmentId().Returns(1); var secondQuestion = new Question() From b45d97821ae8dd68fc6589ad33dd479b6c61f572 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:29:22 +0000 Subject: [PATCH 12/21] chore: Linted code for plan-technology-for-your-school.sln solution --- .../Content/Queries/GetNavigationQuery.cs | 2 +- src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs | 3 +-- .../Controllers/PagesControllerTests.cs | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs index 8ff114c5b..4fed40311 100644 --- a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs +++ b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs @@ -38,7 +38,7 @@ public async Task> GetNavigationLinks(CancellationT } } - public async Task GetLinkById(string contentId, CancellationToken cancellationToken = default) + public async Task GetLinkById(string contentId, CancellationToken cancellationToken = default) { try { diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index becccb2ac..4eb655512 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -1,6 +1,5 @@ using Dfe.PlanTech.Application.Exceptions; using Dfe.PlanTech.Domain.Content.Interfaces; -using Dfe.PlanTech.Domain.Content.Models; using Dfe.PlanTech.Domain.Persistence.Models; using Dfe.PlanTech.Domain.Questionnaire.Interfaces; using Dfe.PlanTech.Domain.Questionnaire.Models; @@ -119,7 +118,7 @@ public async Task GetNextUnansweredQuestion(string sectionSlug, private async Task BuildErrorMessage() { - var contactLink = await _getNavigationQuery.GetLinkById(_contactOptions.LinkId); + var contactLink = await _getNavigationQuery.GetLinkById(_contactOptions.LinkId); var errorMessage = _errorMessages.ConcurrentUsersOrContentChange; if (contactLink != null && !string.IsNullOrEmpty(contactLink.Href)) diff --git a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs index 1d809cad3..8593039f1 100644 --- a/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs +++ b/tests/Dfe.PlanTech.Web.UnitTests/Controllers/PagesControllerTests.cs @@ -12,7 +12,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ViewFeatures; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using NSubstitute; From da65749ff16daf04247e641e1dd567071293a142 Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Fri, 22 Nov 2024 12:27:04 +0000 Subject: [PATCH 13/21] wip add unit tests for navigation query --- .../Content/Queries/GetNavigationQuery.cs | 4 +- .../Queries/GetNavigationQueryTests.cs | 41 +++++++++++++++---- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs index 4fed40311..a808bb51a 100644 --- a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs +++ b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs @@ -38,11 +38,11 @@ public async Task> GetNavigationLinks(CancellationT } } - public async Task GetLinkById(string contentId, CancellationToken cancellationToken = default) + public async Task GetLinkById(string contentId, CancellationToken cancellationToken = default) { try { - return await _cache.GetOrCreateAsync("NavigationLink", () => repository.GetEntityById(contentId, cancellationToken: cancellationToken)); + return await _cache.GetOrCreateAsync($"NavigationLink:{contentId}", () => repository.GetEntityById(contentId, cancellationToken: cancellationToken)); } catch (Exception ex) { diff --git a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs index 27472511d..199351150 100644 --- a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs +++ b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs @@ -1,5 +1,6 @@ using Dfe.PlanTech.Application.Caching.Interfaces; using Dfe.PlanTech.Application.Content.Queries; +using Dfe.PlanTech.Domain.Content.Interfaces; using Dfe.PlanTech.Application.Persistence.Interfaces; using Dfe.PlanTech.Domain.Content.Models; using Microsoft.Extensions.Logging; @@ -13,25 +14,26 @@ public class GetNavigationQueryTests private readonly IContentRepository _contentRepository = Substitute.For(); private readonly ICmsCache _cache = Substitute.For(); - private readonly IList _contentfulLinks = new List() + private readonly NavigationLink _contentfulLink = new NavigationLink { - new() - { - Href = "ContentfulHref", - DisplayText = "ContentfulDisplayText" - } + Href = "ContentfulHref", + DisplayText = "ContentfulDisplayText" }; + private readonly IList _contentfulLinks; + private readonly ILogger _logger = Substitute.For>(); public GetNavigationQueryTests() { + _contentfulLinks = new List { _contentfulLink }; + _cache.GetOrCreateAsync(Arg.Any(), Arg.Any>>>()) .Returns(callInfo => { var func = callInfo.ArgAt>>>(1); return func(); - }); + }); } [Fact] @@ -60,4 +62,29 @@ public async Task Should_LogError_When_Contentful_Exception() Assert.Single(receivedLoggerMessages); Assert.Empty(result); } + + [Fact] + public async Task Should_Retrieve_Nav_Link_By_Id_When_Exists() + { + _contentRepository.GetEntityById(Arg.Any(), Arg.Any(), Arg.Any()).Returns(_contentfulLink); + + var navQuery = new GetNavigationQuery(_logger, _contentRepository, _cache); + var result = await navQuery.GetLinkById("contentId"); + + Assert.NotNull(result); + Assert.Equal(_contentfulLink.Href, result.Href); + Assert.Equal(_contentfulLink.DisplayText, result.DisplayText); + } + + [Fact] + public async Task Should_Return_Null_When_Nav_Link_Does_Not_Exist() + { + _contentRepository.GetEntityById(Arg.Any(), Arg.Any(), cancellationToken: CancellationToken.None).Returns((NavigationLink)null); + + var navQuery = new GetNavigationQuery(_logger, _contentRepository, _cache); + + var result = await navQuery.GetLinkById("NonExistentId"); + + Assert.Null(result); + } } From bd7584a93382e1c5d02605141a010442e544a510 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:29:56 +0000 Subject: [PATCH 14/21] chore: Linted code for plan-technology-for-your-school.sln solution --- .../Content/Queries/GetNavigationQuery.cs | 2 +- .../Content/Queries/GetNavigationQueryTests.cs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs index a808bb51a..3a351ffa7 100644 --- a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs +++ b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs @@ -38,7 +38,7 @@ public async Task> GetNavigationLinks(CancellationT } } - public async Task GetLinkById(string contentId, CancellationToken cancellationToken = default) + public async Task GetLinkById(string contentId, CancellationToken cancellationToken = default) { try { diff --git a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs index 199351150..e22580b4a 100644 --- a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs +++ b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs @@ -1,6 +1,5 @@ using Dfe.PlanTech.Application.Caching.Interfaces; using Dfe.PlanTech.Application.Content.Queries; -using Dfe.PlanTech.Domain.Content.Interfaces; using Dfe.PlanTech.Application.Persistence.Interfaces; using Dfe.PlanTech.Domain.Content.Models; using Microsoft.Extensions.Logging; @@ -33,7 +32,7 @@ public GetNavigationQueryTests() { var func = callInfo.ArgAt>>>(1); return func(); - }); + }); } [Fact] @@ -63,7 +62,7 @@ public async Task Should_LogError_When_Contentful_Exception() Assert.Empty(result); } - [Fact] + [Fact] public async Task Should_Retrieve_Nav_Link_By_Id_When_Exists() { _contentRepository.GetEntityById(Arg.Any(), Arg.Any(), Arg.Any()).Returns(_contentfulLink); From c15d35cdee36e0924eb5e3158f31a8dfa07677a0 Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Fri, 22 Nov 2024 13:09:23 +0000 Subject: [PATCH 15/21] fix unit tests --- .../Content/Queries/GetNavigationQueryTests.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs index e22580b4a..f0ab3c1f4 100644 --- a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs +++ b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs @@ -32,6 +32,15 @@ public GetNavigationQueryTests() { var func = callInfo.ArgAt>>>(1); return func(); + }); + + _cache.GetOrCreateAsync( + Arg.Any(), + Arg.Any>>()) + .Returns(callInfo => + { + var func = callInfo.ArgAt>>(1); + return func(); }); } @@ -66,7 +75,6 @@ public async Task Should_LogError_When_Contentful_Exception() public async Task Should_Retrieve_Nav_Link_By_Id_When_Exists() { _contentRepository.GetEntityById(Arg.Any(), Arg.Any(), Arg.Any()).Returns(_contentfulLink); - var navQuery = new GetNavigationQuery(_logger, _contentRepository, _cache); var result = await navQuery.GetLinkById("contentId"); From ac8434453364e9f10dd192b497a3f485e8c625f5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:10:58 +0000 Subject: [PATCH 16/21] chore: Linted code for plan-technology-for-your-school.sln solution --- .../Content/Queries/GetNavigationQueryTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs index f0ab3c1f4..49bbfe03f 100644 --- a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs +++ b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs @@ -32,7 +32,7 @@ public GetNavigationQueryTests() { var func = callInfo.ArgAt>>>(1); return func(); - }); + }); _cache.GetOrCreateAsync( Arg.Any(), From 275b9898208f09cc9440a2901fbdbb822b9f4e0b Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Fri, 22 Nov 2024 13:22:13 +0000 Subject: [PATCH 17/21] update unit tests --- .../Content/Queries/GetNavigationQuery.cs | 2 +- .../Content/Queries/GetNavigationQueryTests.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs index 3a351ffa7..c3d1e6cd7 100644 --- a/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs +++ b/src/Dfe.PlanTech.Application/Content/Queries/GetNavigationQuery.cs @@ -42,7 +42,7 @@ public async Task> GetNavigationLinks(CancellationT { try { - return await _cache.GetOrCreateAsync($"NavigationLink:{contentId}", () => repository.GetEntityById(contentId, cancellationToken: cancellationToken)); + return await _cache.GetOrCreateAsync($"NavigationLink:{contentId}", () => repository.GetEntityById(contentId, cancellationToken: cancellationToken)); } catch (Exception ex) { diff --git a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs index 49bbfe03f..7b6b14adf 100644 --- a/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs +++ b/tests/Dfe.PlanTech.Application.UnitTests/Content/Queries/GetNavigationQueryTests.cs @@ -34,12 +34,12 @@ public GetNavigationQueryTests() return func(); }); - _cache.GetOrCreateAsync( + _cache.GetOrCreateAsync( Arg.Any(), - Arg.Any>>()) + Arg.Any>>()) .Returns(callInfo => { - var func = callInfo.ArgAt>>(1); + var func = callInfo.ArgAt>>(1); return func(); }); } @@ -86,7 +86,7 @@ public async Task Should_Retrieve_Nav_Link_By_Id_When_Exists() [Fact] public async Task Should_Return_Null_When_Nav_Link_Does_Not_Exist() { - _contentRepository.GetEntityById(Arg.Any(), Arg.Any(), cancellationToken: CancellationToken.None).Returns((NavigationLink)null); + _contentRepository.GetEntityById(Arg.Any(), Arg.Any(), cancellationToken: CancellationToken.None).Returns((NavigationLink?)null); var navQuery = new GetNavigationQuery(_logger, _contentRepository, _cache); From dfbf54c7ba5d10b64b0719f686c9a93de61762dc Mon Sep 17 00:00:00 2001 From: jack-coggin <119428483+jack-coggin@users.noreply.github.com> Date: Tue, 26 Nov 2024 08:34:22 +0000 Subject: [PATCH 18/21] Update src/Dfe.PlanTech.Web/Controllers/PagesController.cs Co-authored-by: jimwashbrook <131891854+jimwashbrook@users.noreply.github.com> --- src/Dfe.PlanTech.Web/Controllers/PagesController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs index 0b3afbd87..9fac3cb34 100644 --- a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs @@ -72,6 +72,6 @@ public async Task NotFoundError() private async Task GetContactLinkAsync() { - return await _getNavigationQuery.GetLinkById(_contactOptions.LinkId); + return await _getNavigationQuery.GetLinkById(_contactOptions.Value.LinkId); } } From 2a2828c35e603da507850e8d3deef5a50e1bf4ce Mon Sep 17 00:00:00 2001 From: jack-coggin <119428483+jack-coggin@users.noreply.github.com> Date: Tue, 26 Nov 2024 08:34:34 +0000 Subject: [PATCH 19/21] Update src/Dfe.PlanTech.Domain/Content/Interfaces/IGetNavigationQuery.cs Co-authored-by: jimwashbrook <131891854+jimwashbrook@users.noreply.github.com> --- .../Content/Interfaces/IGetNavigationQuery.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Dfe.PlanTech.Domain/Content/Interfaces/IGetNavigationQuery.cs b/src/Dfe.PlanTech.Domain/Content/Interfaces/IGetNavigationQuery.cs index d91c5bceb..ce792d7c8 100644 --- a/src/Dfe.PlanTech.Domain/Content/Interfaces/IGetNavigationQuery.cs +++ b/src/Dfe.PlanTech.Domain/Content/Interfaces/IGetNavigationQuery.cs @@ -15,5 +15,5 @@ public interface IGetNavigationQuery /// Retrieve link by id /// /// Found navigation link - Task GetLinkById(string contentId, CancellationToken cancellationToken = default); + Task GetLinkById(string contentId, CancellationToken cancellationToken = default); } From cc656ae1ad7d66161c8fb8a38fff1cd9528f1561 Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Tue, 26 Nov 2024 09:05:05 +0000 Subject: [PATCH 20/21] remove contact email from app settings --- src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs | 1 - src/Dfe.PlanTech.Web/Controllers/PagesController.cs | 2 +- src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs | 4 ++-- src/Dfe.PlanTech.Web/appsettings.json | 1 - 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs index 47d9137b3..5deb507cf 100644 --- a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs +++ b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs @@ -2,6 +2,5 @@ namespace Dfe.PlanTech.Web.Configuration; public class ContactOptions { - public string? Email { get; set; } public string LinkId { get; set; } = ""; } diff --git a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs index 9fac3cb34..0b3afbd87 100644 --- a/src/Dfe.PlanTech.Web/Controllers/PagesController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/PagesController.cs @@ -72,6 +72,6 @@ public async Task NotFoundError() private async Task GetContactLinkAsync() { - return await _getNavigationQuery.GetLinkById(_contactOptions.Value.LinkId); + return await _getNavigationQuery.GetLinkById(_contactOptions.LinkId); } } diff --git a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs index 4eb655512..d122cbd6b 100644 --- a/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs +++ b/src/Dfe.PlanTech.Web/Controllers/QuestionsController.cs @@ -36,7 +36,7 @@ public QuestionsController(ILogger logger, IGetEntityFromContentfulQuery getEntityByIdQuery, IGetNavigationQuery getNavigationQuery, IUser user, - IOptions errorMessages, + IOptions errorMessageOptions, IOptions contactOptions) : base(logger) { _getResponseQuery = getResponseQuery; @@ -44,7 +44,7 @@ public QuestionsController(ILogger logger, _getEntityFromContentfulQuery = getEntityByIdQuery; _getNavigationQuery = getNavigationQuery; _user = user; - _errorMessages = errorMessages.Value; + _errorMessages = errorMessageOptions.Value; _contactOptions = contactOptions.Value; } diff --git a/src/Dfe.PlanTech.Web/appsettings.json b/src/Dfe.PlanTech.Web/appsettings.json index f0ed79f74..45215a7e9 100644 --- a/src/Dfe.PlanTech.Web/appsettings.json +++ b/src/Dfe.PlanTech.Web/appsettings.json @@ -60,7 +60,6 @@ }, "CacheTimeOutMs": 30000, "ContactUs": { - "Email": "technology.planning@education.gov.uk", "LinkId": "7ezhOgrTAdhP4NeGiNj8VY" }, "ErrorMessages": { From 54c9c1a4e677ace699020c9f0b43c97543224a8c Mon Sep 17 00:00:00 2001 From: "jack.coggin" Date: Tue, 26 Nov 2024 09:18:00 +0000 Subject: [PATCH 21/21] update config options to records --- src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs | 2 +- src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs index 5deb507cf..11bbf552a 100644 --- a/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs +++ b/src/Dfe.PlanTech.Web/Configuration/ContactOptions.cs @@ -1,6 +1,6 @@ namespace Dfe.PlanTech.Web.Configuration; -public class ContactOptions +public record ContactOptions { public string LinkId { get; set; } = ""; } diff --git a/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs index 64251217a..bab914bab 100644 --- a/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs +++ b/src/Dfe.PlanTech.Web/Configuration/ErrorMessages.cs @@ -1,6 +1,6 @@ namespace Dfe.PlanTech.Web.Configuration; -public class ErrorMessages +public record ErrorMessages { public string ConcurrentUsersOrContentChange { get; set; } = ""; }