diff --git a/Frontend/CO.CDP.OrganisationApp.Tests/FormsEngineTests.cs b/Frontend/CO.CDP.OrganisationApp.Tests/FormsEngineTests.cs index 258f5e287..3d33f68d2 100644 --- a/Frontend/CO.CDP.OrganisationApp.Tests/FormsEngineTests.cs +++ b/Frontend/CO.CDP.OrganisationApp.Tests/FormsEngineTests.cs @@ -1,6 +1,7 @@ using CO.CDP.OrganisationApp.Models; using FluentAssertions; using Moq; +using DataShareWebApiClient = CO.CDP.DataSharing.WebApiClient; using WebApiClient = CO.CDP.Forms.WebApiClient; namespace CO.CDP.OrganisationApp.Tests; @@ -8,14 +9,16 @@ namespace CO.CDP.OrganisationApp.Tests; public class FormsEngineTests { private readonly Mock _formsApiClientMock; + private readonly Mock _dataSharingClientMock; private readonly Mock _tempDataServiceMock; private readonly FormsEngine _formsEngine; public FormsEngineTests() { _formsApiClientMock = new Mock(); + _dataSharingClientMock = new Mock(); _tempDataServiceMock = new Mock(); - _formsEngine = new FormsEngine(_formsApiClientMock.Object, _tempDataServiceMock.Object); + _formsEngine = new FormsEngine(_formsApiClientMock.Object, _tempDataServiceMock.Object, _dataSharingClientMock.Object); } private static (Guid organisationId, Guid formId, Guid sectionId, string sessionKey) CreateTestGuids() @@ -294,6 +297,44 @@ public async Task SaveUpdateAnswers_ShouldThrowException_WhenApiCallFails() await act.Should().ThrowAsync().WithMessage("API call failed"); } + [Fact] + public async Task CreateShareCodeAsync_ShouldReturnShareCode_WhenApiCallSucceeds() + { + var formId = Guid.NewGuid(); + var organisationId = Guid.NewGuid(); + var expectedShareCode = "HDJ2123F"; + + _dataSharingClientMock.Setup(client => client.CreateSharedDataAsync( + It.Is(sr => + sr.FormId == formId && sr.OrganisationId == organisationId))) + .ReturnsAsync(new DataShareWebApiClient.ShareReceipt(formId, null, expectedShareCode)); + + var result = await _formsEngine.CreateShareCodeAsync(formId, organisationId); + + result.Should().Be(expectedShareCode); + _dataSharingClientMock.Verify(client => client.CreateSharedDataAsync( + It.Is(sr => + sr.FormId == formId && sr.OrganisationId == organisationId)), Times.Once); + } + + [Fact] + public async Task CreateShareCodeAsync_ShouldThrowException_WhenApiCallFails() + { + var formId = Guid.NewGuid(); + var organisationId = Guid.NewGuid(); + + _dataSharingClientMock.Setup(client => client.CreateSharedDataAsync( + It.IsAny())) + .ThrowsAsync(new Exception("API call failed")); + + Func act = async () => await _formsEngine.CreateShareCodeAsync(formId, organisationId); + + await act.Should().ThrowAsync().WithMessage("API call failed"); + _dataSharingClientMock.Verify(client => client.CreateSharedDataAsync( + It.Is(sr => + sr.FormId == formId && sr.OrganisationId == organisationId)), Times.Once); + } + private (Guid formId, Guid sectionId, Guid organisationId, FormQuestionAnswerState answerSet, FormAnswer expectedAnswer) SetupTestData() { var formId = Guid.NewGuid(); diff --git a/Frontend/CO.CDP.OrganisationApp.Tests/Pages/Forms/DynamicFormsPageModelTest.cs b/Frontend/CO.CDP.OrganisationApp.Tests/Pages/Forms/DynamicFormsPageModelTest.cs index b3e45cf50..f962144e1 100644 --- a/Frontend/CO.CDP.OrganisationApp.Tests/Pages/Forms/DynamicFormsPageModelTest.cs +++ b/Frontend/CO.CDP.OrganisationApp.Tests/Pages/Forms/DynamicFormsPageModelTest.cs @@ -172,4 +172,41 @@ public async Task OnPostAsync_ShouldRedirectToShareCodeConfirmation_WhenSectionT result.Should().BeOfType() .Which.PageName.Should().Be("/ShareInformation/ShareCodeConfirmation"); } -} + + [Fact] + public async Task OnPostAsync_ShouldRedirectToShareCodeConfirmation_WithGeneratedShareCode_WhenSectionIsDeclaration() + { + var shareCode = "HDJ2123F"; + _pageModel.FormSectionType = FormSectionType.Declaration; + _pageModel.CurrentQuestionId = Guid.NewGuid(); + + var formResponse = new SectionQuestionsResponse + { + Section = new FormSection { Type = FormSectionType.Declaration, Title = "Test Section" }, + Questions = new List + { + new FormQuestion { Id = _pageModel.CurrentQuestionId.Value, Type = FormQuestionType.CheckYourAnswers } + } + }; + + _formsEngineMock.Setup(f => f.GetCurrentQuestion(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(new FormQuestion { Id = _pageModel.CurrentQuestionId.Value, Type = FormQuestionType.CheckYourAnswers }); + + _formsEngineMock.Setup(f => f.GetFormSectionAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(formResponse); + + _formsEngineMock.Setup(f => f.CreateShareCodeAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(shareCode); + + _tempDataServiceMock.Setup(t => t.PeekOrDefault(It.IsAny())) + .Returns(new FormQuestionAnswerState()); + + var result = await _pageModel.OnPostAsync(); + + _formsEngineMock.Verify(f => f.CreateShareCodeAsync(_pageModel.FormId, _pageModel.OrganisationId), Times.Once); + + result.Should().BeOfType() + .Which.PageName.Should().Be("/ShareInformation/ShareCodeConfirmation"); + (result as RedirectToPageResult)!.RouteValues?["shareCode"].Should().Be(shareCode); + } +} \ No newline at end of file diff --git a/Frontend/CO.CDP.OrganisationApp.Tests/Pages/ShareInformation/ShareCodeConfirmationTests.cs b/Frontend/CO.CDP.OrganisationApp.Tests/Pages/ShareInformation/ShareCodeConfirmationTests.cs index f82373453..d1dac76c1 100644 --- a/Frontend/CO.CDP.OrganisationApp.Tests/Pages/ShareInformation/ShareCodeConfirmationTests.cs +++ b/Frontend/CO.CDP.OrganisationApp.Tests/Pages/ShareInformation/ShareCodeConfirmationTests.cs @@ -1,81 +1,29 @@ using CO.CDP.OrganisationApp.Pages.ShareInformation; using FluentAssertions; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Moq; -using WebApiClient = CO.CDP.DataSharing.WebApiClient; + namespace CO.CDP.OrganisationApp.Tests.Pages.ShareInformation; public class ShareCodeConfirmationTests { - private readonly Mock _dataSharingApiClientMock; - private readonly ShareCodeConfirmationModel _pageModel; - - public ShareCodeConfirmationTests() - { - _dataSharingApiClientMock = new Mock(); - _pageModel = new ShareCodeConfirmationModel(_dataSharingApiClientMock.Object); - } - [Fact] - public async Task OnGetAsync_ShouldReturnPageResult_WhenShareCodeIsGeneratedSuccessfully() + public void ShareCodeConfirmationModel_ShouldInitializePropertiesCorrectly() { - var formId = Guid.NewGuid(); var organisationId = Guid.NewGuid(); - var sectionId = Guid.NewGuid(); - var shareCode = "HDJ2123F"; - - _pageModel.FormId = formId; - _pageModel.OrganisationId = organisationId; - _pageModel.SectionId = sectionId; - - _dataSharingApiClientMock - .Setup(x => x.CreateSharedDataAsync(It.Is(sr => - sr.FormId == formId && sr.OrganisationId == organisationId))) - .ReturnsAsync(new WebApiClient.ShareReceipt(formId, null, shareCode)); - - var result = await _pageModel.OnGetAsync(); - - result.Should().BeOfType(); - _pageModel.ShareCode.Should().Be(shareCode); - } - - [Fact] - public async Task OnGetAsync_ShouldRedirectToNotFound_WhenApiExceptionOccursWith404() - { var formId = Guid.NewGuid(); - var organisationId = Guid.NewGuid(); var sectionId = Guid.NewGuid(); + var shareCode = "HDJ2123F"; - _pageModel.FormId = formId; - _pageModel.OrganisationId = organisationId; - _pageModel.SectionId = sectionId; - - _dataSharingApiClientMock - .Setup(x => x.CreateSharedDataAsync(It.IsAny())) - .ThrowsAsync(new WebApiClient.ApiException(string.Empty, 404, string.Empty, null, null)); - - var result = await _pageModel.OnGetAsync(); - - result.Should().BeOfType().Which.Url.Should().Be("/page-not-found"); - _pageModel.ShareCode.Should().BeNull(); - } - - [Fact] - public async Task OnGetAsync_ShouldAllowMiddlewareToHandle500Error() - { - var formId = Guid.NewGuid(); - var organisationId = Guid.NewGuid(); - var sectionId = Guid.NewGuid(); - - _pageModel.FormId = formId; - _pageModel.OrganisationId = organisationId; - _pageModel.SectionId = sectionId; - - _dataSharingApiClientMock - .Setup(x => x.CreateSharedDataAsync(It.IsAny())) - .ThrowsAsync(new WebApiClient.ApiException("Internal Server Error", 500, string.Empty, null, null)); - - await Assert.ThrowsAsync(async () => await _pageModel.OnGetAsync()); + var model = new ShareCodeConfirmationModel + { + OrganisationId = organisationId, + FormId = formId, + SectionId = sectionId, + ShareCode = shareCode + }; + + model.OrganisationId.Should().Be(organisationId); + model.FormId.Should().Be(formId); + model.SectionId.Should().Be(sectionId); + model.ShareCode.Should().Be(shareCode); } } \ No newline at end of file diff --git a/Frontend/CO.CDP.OrganisationApp/FormsEngine.cs b/Frontend/CO.CDP.OrganisationApp/FormsEngine.cs index b5388ef7d..5e8e1c7dc 100644 --- a/Frontend/CO.CDP.OrganisationApp/FormsEngine.cs +++ b/Frontend/CO.CDP.OrganisationApp/FormsEngine.cs @@ -1,10 +1,13 @@ using CO.CDP.Forms.WebApiClient; using CO.CDP.OrganisationApp.Models; +using DataShareWebApiClient = CO.CDP.DataSharing.WebApiClient; using SectionQuestionsResponse = CO.CDP.OrganisationApp.Models.SectionQuestionsResponse; - namespace CO.CDP.OrganisationApp; -public class FormsEngine(IFormsClient formsApiClient, ITempDataService tempDataService) : IFormsEngine +public class FormsEngine( + IFormsClient formsApiClient, + ITempDataService tempDataService, + DataShareWebApiClient.IDataSharingClient dataSharingClient) : IFormsEngine { public const string OrganisationSupplierInfoFormId = "0618b13e-eaf2-46e3-a7d2-6f2c44be7022"; @@ -119,9 +122,17 @@ await formsApiClient.PutFormSectionAnswersAsync( answersPayload); } + public async Task CreateShareCodeAsync(Guid formId, Guid organisationId) + { + var sharingDataDetails = await dataSharingClient.CreateSharedDataAsync( + new DataShareWebApiClient.ShareRequest(formId, organisationId)); + + return sharingDataDetails.ShareCode; + } private static FormAddress? MapAddress(Address? formAdddress) { - if (formAdddress == null) return null; + if (formAdddress == null) + return null; return new FormAddress( streetAddress: formAdddress.AddressLine1, locality: formAdddress.TownOrCity, diff --git a/Frontend/CO.CDP.OrganisationApp/IFormsEngine.cs b/Frontend/CO.CDP.OrganisationApp/IFormsEngine.cs index 344b590ea..26e217567 100644 --- a/Frontend/CO.CDP.OrganisationApp/IFormsEngine.cs +++ b/Frontend/CO.CDP.OrganisationApp/IFormsEngine.cs @@ -13,4 +13,5 @@ public interface IFormsEngine Task GetCurrentQuestion(Guid organisationId, Guid formId, Guid sectionId, Guid? questionId); Task SaveUpdateAnswers(Guid formId, Guid sectionId, Guid organisationId, FormQuestionAnswerState answerSet); + Task CreateShareCodeAsync(Guid formId, Guid organisationId); } \ No newline at end of file diff --git a/Frontend/CO.CDP.OrganisationApp/Pages/Forms/DynamicFormsPage.cshtml.cs b/Frontend/CO.CDP.OrganisationApp/Pages/Forms/DynamicFormsPage.cshtml.cs index ee487cee0..b60744972 100644 --- a/Frontend/CO.CDP.OrganisationApp/Pages/Forms/DynamicFormsPage.cshtml.cs +++ b/Frontend/CO.CDP.OrganisationApp/Pages/Forms/DynamicFormsPage.cshtml.cs @@ -106,9 +106,15 @@ public async Task OnPostAsync() tempDataService.Remove(FormQuestionAnswerStateKey); - return RedirectToPage(FormSectionType == Models.FormSectionType.Declaration ? - "/ShareInformation/ShareCodeConfirmation" : "FormsAddAnotherAnswerSet", - new { OrganisationId, FormId, SectionId }); + if (FormSectionType == Models.FormSectionType.Declaration) + { + var shareCode = await formsEngine.CreateShareCodeAsync(FormId, OrganisationId); + + return RedirectToPage("/ShareInformation/ShareCodeConfirmation", + new { OrganisationId, FormId, SectionId, shareCode }); + } + + return RedirectToPage("FormsAddAnotherAnswerSet", new { OrganisationId, FormId, SectionId }); } Guid? nextQuestionId; diff --git a/Frontend/CO.CDP.OrganisationApp/Pages/ShareInformation/ShareCodeConfirmation.cshtml.cs b/Frontend/CO.CDP.OrganisationApp/Pages/ShareInformation/ShareCodeConfirmation.cshtml.cs index d315916bc..130dd25a7 100644 --- a/Frontend/CO.CDP.OrganisationApp/Pages/ShareInformation/ShareCodeConfirmation.cshtml.cs +++ b/Frontend/CO.CDP.OrganisationApp/Pages/ShareInformation/ShareCodeConfirmation.cshtml.cs @@ -1,11 +1,9 @@ -using CO.CDP.DataSharing.WebApiClient; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace CO.CDP.OrganisationApp.Pages.ShareInformation; -public class ShareCodeConfirmationModel( - IDataSharingClient dataSharingClient) : PageModel +public class ShareCodeConfirmationModel() : PageModel { [BindProperty(SupportsGet = true)] public Guid OrganisationId { get; set; } @@ -16,19 +14,7 @@ public class ShareCodeConfirmationModel( [BindProperty(SupportsGet = true)] public Guid SectionId { get; set; } + [BindProperty(SupportsGet = true)] public string? ShareCode { get; set; } - public async Task OnGetAsync() - { - try - { - var sharingDataDetails = await dataSharingClient.CreateSharedDataAsync(new ShareRequest(FormId, OrganisationId)); - ShareCode = sharingDataDetails.ShareCode; - } - catch (ApiException ex) when (ex.StatusCode == 404) - { - return Redirect("/page-not-found"); - } - return Page(); - } } \ No newline at end of file