diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/BaseTest.cs b/EstateManagementUI.BlazorServer.Tests/Pages/BaseTest.cs index 7fb9d9c6..8bfee122 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/BaseTest.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/BaseTest.cs @@ -34,6 +34,7 @@ protected BaseTest() { this.Services.AddSingleton(this._mockPermissionStore.Object); this.Services.AddSingleton(this.EstateUIService.Object); this.Services.AddSingleton(this.OperatorUIService.Object); + this.Services.AddSingleton(this.ContractUIService.Object); // Add required permission components that render their children @@ -55,6 +56,7 @@ protected BaseTest() { protected readonly FakeNavigationManager _fakeNavigationManager; protected readonly Mock EstateUIService = new Mock(); protected readonly Mock OperatorUIService = new Mock(); + protected readonly Mock ContractUIService = new Mock(); /// /// Minimal test double for NavigationManager. /// Register in DI as NavigationManager so components receive it in tests. diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsEditPageTests.cs b/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsEditPageTests.cs index fb17c4d5..b01c80bb 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsEditPageTests.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsEditPageTests.cs @@ -2,6 +2,7 @@ using Bunit; using EstateManagementUI.BlazorServer.Components.Pages.Contracts; using EstateManagementUI.BlazorServer.Components.Permissions; +using EstateManagementUI.BlazorServer.Models; using EstateManagementUI.BlazorServer.Permissions; using EstateManagementUI.BusinessLogic.Models; using EstateManagementUI.BusinessLogic.Requests; @@ -11,6 +12,7 @@ using Moq; using Shouldly; using SimpleResults; +using TransactionProcessor.DataTransferObjects.Responses.Contract; namespace EstateManagementUI.BlazorServer.Tests.Pages.Contracts; @@ -21,15 +23,15 @@ public void ContractsEdit_RendersCorrectly() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); // Act @@ -45,17 +47,17 @@ public void ContractsEdit_DisplaysContractDetails() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -71,69 +73,42 @@ public void ContractsEdit_HasCorrectPageTitle() { // Arrange var contractId = Guid.NewGuid(); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new ContractModel - { - ContractId = contractId, - Products = new List() - })); - - // Act - var cut = RenderComponent(parameters => parameters - .Add(p => p.ContractId, contractId)); - - // Assert - var pageTitle = cut.FindComponent(); - pageTitle.Instance.ChildContent.ShouldNotBeNull(); - } - - [Fact] - public void ContractsEdit_CancelButton_NavigatesToViewPage() - { - // Arrange - var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); - cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); - - // Find and click Cancel button - IRefreshableElementCollection buttons = cut.FindAll("button"); - IElement? cancelButton = buttons.FirstOrDefault(b => b.TextContent.Contains("Cancel")); - cancelButton.ShouldNotBeNull(); - cancelButton.Click(); // Assert - _fakeNavigationManager.Uri.ShouldContain($"/contracts/{contractId}"); + var pageTitle = cut.FindComponent(); + pageTitle.Instance.ChildContent.ShouldNotBeNull(); } - + [Fact] public void ContractsEdit_UpdateContractButton_CanBeFound() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -152,17 +127,17 @@ public void ContractsEdit_AddProductButton_CanBeFound() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -181,17 +156,17 @@ public void ContractsEdit_AddProductButton_OpensModal() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -212,29 +187,29 @@ public void ContractsEdit_WithProducts_DisplaysProductList() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = Guid.NewGuid(), ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 2, - TransactionFees = new List() + TransactionFees = new List() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -251,29 +226,29 @@ public void ContractsEdit_WithProducts_HasRemoveProductButton() // Arrange var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 0, - TransactionFees = new List() + TransactionFees = new List() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -294,24 +269,24 @@ public void ContractsEdit_WithProductHavingFees_HasAddFeeButton() // Arrange var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 1, - TransactionFees = new List + TransactionFees = new List { - new ContractProductTransactionFeeModel + new ContractModels.ContractProductTransactionFeeModel { TransactionFeeId = Guid.NewGuid(), Description = "Fee 1", @@ -323,10 +298,10 @@ public void ContractsEdit_WithProductHavingFees_HasAddFeeButton() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -347,29 +322,29 @@ public void ContractsEdit_AddFeeButton_OpensModal() // Arrange var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 0, - TransactionFees = new List() + TransactionFees = new List() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -390,17 +365,17 @@ public void ContractsEdit_WithNoProducts_ShowsEmptyState() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -409,56 +384,22 @@ public void ContractsEdit_WithNoProducts_ShowsEmptyState() // Assert cut.Markup.ShouldContain("No products added yet"); } - + [Fact] - public void ContractsEdit_ContractNotFound_ShowsErrorMessage() - { + public void ContractsEdit_BackToListButton_NavigatesToContractsIndex() { // Arrange var contractId = Guid.NewGuid(); - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(null!)); - - // Act - var cut = RenderComponent(parameters => parameters - .Add(p => p.ContractId, contractId)); - cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); - - // Assert - cut.Markup.ShouldContain("Contract not found"); - } + var contract = new ContractModels.ContractModel + { + ContractId = contractId, + Description = "Test Contract", + OperatorName = "Test Operator", + Products = new List() + }; - [Fact] - public void ContractsEdit_ContractNotFound_HasBackToListButton() - { - // Arrange - var contractId = Guid.NewGuid(); - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(null!)); - - // Act - var cut = RenderComponent(parameters => parameters - .Add(p => p.ContractId, contractId)); - cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); - - // Find Back to List button - IRefreshableElementCollection buttons = cut.FindAll("button"); - IElement? backButton = buttons.FirstOrDefault(b => b.TextContent.Contains("Back to List")); - - // Assert - backButton.ShouldNotBeNull(); - } + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(contract)); - [Fact] - public void ContractsEdit_BackToListButton_NavigatesToContractsIndex() - { - // Arrange - var contractId = Guid.NewGuid(); - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(null!)); - // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -479,17 +420,17 @@ public void ContractsEdit_ProductModal_HasCancelButton() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -518,29 +459,29 @@ public void ContractsEdit_FeeModal_HasCancelButton() // Arrange var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 0, - TransactionFees = new List() + TransactionFees = new List() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -570,24 +511,24 @@ public void ContractsEdit_WithTransactionFees_HasRemoveFeeButton() var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); var feeId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 1, - TransactionFees = new List + TransactionFees = new List { - new ContractProductTransactionFeeModel + new ContractModels.ContractProductTransactionFeeModel { TransactionFeeId = feeId, Description = "Fee 1", @@ -599,10 +540,10 @@ public void ContractsEdit_WithTransactionFees_HasRemoveFeeButton() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -622,17 +563,17 @@ public void ContractsEdit_DisplaysOperatorNameAsReadOnly() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -648,17 +589,17 @@ public void ContractsEdit_UpdateContractButton_Exists() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -675,17 +616,17 @@ public void ContractsEdit_AddProductModal_HasRequiredFields() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -717,17 +658,17 @@ public void ContractsEdit_AddProductModal_HasSubmitButton() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -753,17 +694,17 @@ public void ContractsEdit_AddProductModal_HasVariableValueCheckbox() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -789,29 +730,29 @@ public void ContractsEdit_AddFeeModal_HasRequiredFields() // Arrange var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 0, - TransactionFees = new List() + TransactionFees = new List() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -844,29 +785,29 @@ public void ContractsEdit_AddFeeModal_HasSubmitButton() // Arrange var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 0, - TransactionFees = new List() + TransactionFees = new List() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -893,29 +834,29 @@ public void ContractsEdit_RemoveProduct_HasRemoveButton() // Arrange var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 0, - TransactionFees = new List() + TransactionFees = new List() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -935,24 +876,24 @@ public void ContractsEdit_RemoveFee_HasRemoveButton() var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); var feeId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 1, - TransactionFees = new List + TransactionFees = new List { - new ContractProductTransactionFeeModel + new ContractModels.ContractProductTransactionFeeModel { TransactionFeeId = feeId, Description = "Fee 1", @@ -964,10 +905,10 @@ public void ContractsEdit_RemoveFee_HasRemoveButton() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -985,17 +926,17 @@ public void ContractsEdit_ProductModal_HasCancelButtonWithCorrectType() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -1022,29 +963,29 @@ public void ContractsEdit_FeeModal_HasCancelButtonWithCorrectType() // Arrange var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 0, - TransactionFees = new List() + TransactionFees = new List() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -1070,39 +1011,39 @@ public void ContractsEdit_WithMultipleProducts_DisplaysAllProducts() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = Guid.NewGuid(), ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 0, - TransactionFees = new List() + TransactionFees = new List() }, - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = Guid.NewGuid(), ProductName = "Product 2", DisplayText = "Display 2", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "200", NumberOfFees = 0, - TransactionFees = new List() + TransactionFees = new List() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -1121,24 +1062,24 @@ public void ContractsEdit_WithMultipleFees_DisplaysAllFees() // Arrange var contractId = Guid.NewGuid(); var productId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = productId, ProductName = "Product 1", DisplayText = "Display 1", - ProductType = "NotSet", + ProductType = ProductType.NotSet, Value = "100", NumberOfFees = 2, - TransactionFees = new List + TransactionFees = new List { - new ContractProductTransactionFeeModel + new ContractModels.ContractProductTransactionFeeModel { TransactionFeeId = Guid.NewGuid(), Description = "Fee 1", @@ -1146,22 +1087,22 @@ public void ContractsEdit_WithMultipleFees_DisplaysAllFees() CalculationType = 0, FeeType = 0 }, - new ContractProductTransactionFeeModel + new ContractModels.ContractProductTransactionFeeModel { TransactionFeeId = Guid.NewGuid(), Description = "Fee 2", Value = 2.5m, - CalculationType = 1, - FeeType = 1 + CalculationType = CalculationType.Fixed, + FeeType = FeeType.Merchant } } } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsIndexPageTests.cs b/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsIndexPageTests.cs index 4714fc33..5e3388a3 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsIndexPageTests.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsIndexPageTests.cs @@ -5,12 +5,14 @@ using EstateManagementUI.BlazorServer.Tests.Pages.FileProcessing; using EstateManagementUI.BusinessLogic.Models; using EstateManagementUI.BusinessLogic.Requests; +using EstateManagementUI.BlazorServer.Models; using MediatR; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.DependencyInjection; using Moq; using Shouldly; using SimpleResults; +using TransactionProcessor.DataTransferObjects.Responses.Contract; using ContractsIndex = EstateManagementUI.BlazorServer.Components.Pages.Contracts.Index; namespace EstateManagementUI.BlazorServer.Tests.Pages.Contracts; @@ -21,19 +23,19 @@ public class ContractsIndexPageTests : BaseTest public void ContractsIndex_RendersCorrectly() { // Arrange - List contracts = new List + List contracts = new() { - new ContractModel + new ContractModels.ContractModel { ContractId = Guid.NewGuid(), Description = "Test Contract", OperatorName = "Test Operator", OperatorId = Guid.NewGuid(), - Products = new List() + Products = new List() } }; - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + this.ContractUIService.Setup(c => c.GetContracts(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contracts)); // Act @@ -47,10 +49,10 @@ public void ContractsIndex_RendersCorrectly() public void ContractsIndex_WithNoContracts_ShowsEmptyState() { // Arrange - List emptyList = new List(); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + List emptyList = new(); + this.ContractUIService.Setup(c => c.GetContracts(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(emptyList)); - + // Act IRenderedComponent cut = RenderComponent(); @@ -62,29 +64,29 @@ public void ContractsIndex_WithNoContracts_ShowsEmptyState() public void ContractsIndex_WithContracts_DisplaysContractList() { // Arrange - List contracts = new List + List contracts = new() { - new ContractModel + new ContractModels.ContractModel { ContractId = Guid.NewGuid(), Description = "Contract 1", OperatorName = "Operator A", OperatorId = Guid.NewGuid(), - Products = new List() + Products = new List() }, - new ContractModel + new ContractModels.ContractModel { ContractId = Guid.NewGuid(), Description = "Contract 2", OperatorName = "Operator B", OperatorId = Guid.NewGuid(), - Products = new List() + Products = new List() } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContracts(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contracts)); - + // Act IRenderedComponent cut = RenderComponent(); @@ -99,25 +101,24 @@ public void ContractsIndex_WithContracts_DisplaysContractList() public void ContractsIndex_DisplaysProductCount() { // Arrange - List contracts = new List + List contracts = new() { - new ContractModel + new ContractModels.ContractModel { ContractId = Guid.NewGuid(), Description = "Test Contract", OperatorName = "Test Operator", OperatorId = Guid.NewGuid(), - Products = new List - { - new ContractProductModel { ContractProductId = Guid.NewGuid(), ProductName = "Product 1", ProductType = "NotSet"}, - new ContractProductModel { ContractProductId = Guid.NewGuid(), ProductName = "Product 2", ProductType = "NotSet" } - } + Products = [ + new ContractModels.ContractProductModel { ContractProductId = Guid.NewGuid(), ProductName = "Product 1", ProductType = ProductType.NotSet }, + new ContractModels.ContractProductModel { ContractProductId = Guid.NewGuid(), ProductName = "Product 2", ProductType = ProductType.NotSet } + ] } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContracts(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contracts)); - + // Act IRenderedComponent cut = RenderComponent(); @@ -129,9 +130,9 @@ public void ContractsIndex_DisplaysProductCount() public void ContractsIndex_HasCorrectPageTitle() { // Arrange - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - + this.ContractUIService.Setup(c => c.GetContracts(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(new List())); + // Act IRenderedComponent cut = RenderComponent(); @@ -140,13 +141,27 @@ public void ContractsIndex_HasCorrectPageTitle() pageTitle.Instance.ChildContent.ShouldNotBeNull(); } + [Fact] + public void ContractsIndex_LoadContractFails_NavigatesToError() + { + // Arrange + this.ContractUIService.Setup(c => c.GetContracts(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + + // Act + IRenderedComponent cut = RenderComponent(); + + // Assert + _fakeNavigationManager.Uri.ShouldContain("error"); + } + [Fact] public void ContractsIndex_AddNewContractButton_NavigatesToNewContractPage() { // Arrange - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - + this.ContractUIService.Setup(c => c.GetContracts(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(new List())); + IRenderedComponent cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.ShouldContain("Contract Management"), timeout: TimeSpan.FromSeconds(5)); @@ -163,21 +178,21 @@ public void ContractsIndex_ViewButton_NavigatesToContractDetails() { // Arrange Guid contractId = Guid.NewGuid(); - List contracts = new List + List contracts = new() { - new ContractModel + new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", OperatorId = Guid.NewGuid(), - Products = new List() + Products = new List() } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContracts(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contracts)); - + IRenderedComponent cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.ShouldContain("Test Contract"), timeout: TimeSpan.FromSeconds(5)); @@ -196,21 +211,21 @@ public void ContractsIndex_EditButton_NavigatesToEditContractPage() { // Arrange Guid contractId = Guid.NewGuid(); - List contracts = new List + List contracts = new() { - new ContractModel + new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", OperatorId = Guid.NewGuid(), - Products = new List() + Products = new List() } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContracts(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contracts)); - + IRenderedComponent cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.ShouldContain("Test Contract"), timeout: TimeSpan.FromSeconds(5)); diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsNewPageTests.cs b/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsNewPageTests.cs index 9e836983..5799f433 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsNewPageTests.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsNewPageTests.cs @@ -1,5 +1,7 @@ using AngleSharp.Dom; using Bunit; +using EstateManagementUI.BlazorServer.Models; +using EstateManagementUI.BusinessLogic.BackendAPI.DataTransferObjects; using EstateManagementUI.BusinessLogic.Models; using EstateManagementUI.BusinessLogic.Requests; using Moq; @@ -15,8 +17,7 @@ public class ContractsNewPageTests : BaseTest public void ContractsNew_RendersCorrectly() { // Arrange - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(new List())); // Act IRenderedComponent cut = RenderComponent(); @@ -29,8 +30,7 @@ public void ContractsNew_RendersCorrectly() public void ContractsNew_HasCorrectPageTitle() { // Arrange - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(new List())); // Act IRenderedComponent cut = RenderComponent(); @@ -44,8 +44,7 @@ public void ContractsNew_HasCorrectPageTitle() public void ContractsNew_CancelButton_NavigatesToContractsIndex() { // Arrange - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(new List())); IRenderedComponent cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.ShouldContain("Create New Contract"), timeout: TimeSpan.FromSeconds(5)); @@ -64,8 +63,7 @@ public void ContractsNew_CancelButton_NavigatesToContractsIndex() public void ContractsNew_CreateContractButton_IsPresent() { // Arrange - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(new List())); IRenderedComponent cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.ShouldContain("Create New Contract"), timeout: TimeSpan.FromSeconds(5)); @@ -79,22 +77,20 @@ public void ContractsNew_CreateContractButton_IsPresent() public void ContractsNew_LoadsOperatorsSuccessfully() { // Arrange - List operators = new List + List operators = new List { - new OperatorDropDownModel + new OperatorModels.OperatorDropDownModel { OperatorId = Guid.NewGuid(), OperatorName = "Test Operator 1" }, - new OperatorDropDownModel + new OperatorModels.OperatorDropDownModel { OperatorId = Guid.NewGuid(), OperatorName = "Test Operator 2" } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(operators)); + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(operators)); // Act IRenderedComponent cut = RenderComponent(); @@ -104,12 +100,23 @@ public void ContractsNew_LoadsOperatorsSuccessfully() cut.Markup.ShouldContain("Test Operator 2"); } + [Fact] + public void ContractsNew_LoadsOperatorsFailed_NavigateToError() + { + // Arrange + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); + + // Act + IRenderedComponent cut = RenderComponent(); + + _fakeNavigationManager.Uri.ShouldContain("error"); + } + [Fact] public void ContractsNew_WithNoOperators_ShowsNoOperatorsMessage() { // Arrange - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(new List())); // Act IRenderedComponent cut = RenderComponent(); @@ -123,18 +130,17 @@ public void ContractsNew_SuccessfulCreation_NavigatesToContractsIndex() { // Arrange Guid operatorId = Guid.NewGuid(); - List operators = new List + List operators = new List { - new OperatorDropDownModel + new OperatorModels.OperatorDropDownModel { OperatorId = operatorId, OperatorName = "Test Operator" } }; - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(operators)); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(operators)); + this.ContractUIService.Setup(c => c.CreateContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success()); IRenderedComponent cut = RenderComponent(); @@ -153,7 +159,6 @@ public void ContractsNew_SuccessfulCreation_NavigatesToContractsIndex() // Assert cut.WaitForAssertion(() => { - _mockMediator.Verify(x => x.Send(It.IsAny(), default), Times.Once()); _fakeNavigationManager.Uri.ShouldContain("/contracts"); }, timeout: TimeSpan.FromSeconds(5)); } @@ -163,19 +168,18 @@ public void ContractsNew_FailedCreation_ShowsErrorMessage() { // Arrange Guid operatorId = Guid.NewGuid(); - List operators = new List + List operators = new List { - new OperatorDropDownModel + new OperatorModels.OperatorDropDownModel { OperatorId = operatorId, OperatorName = "Test Operator" } }; - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(operators)); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Failure("Failed to create contract")); + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(operators)); + this.ContractUIService.Setup(c => c.CreateContract(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure); IRenderedComponent cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.ShouldContain("Test Operator"), timeout: TimeSpan.FromSeconds(5)); @@ -193,7 +197,6 @@ public void ContractsNew_FailedCreation_ShowsErrorMessage() // Assert cut.WaitForAssertion(() => { - _mockMediator.Verify(x => x.Send(It.IsAny(), default), Times.Once()); cut.Markup.ShouldContain("Failed to create contract"); }, timeout: TimeSpan.FromSeconds(5)); } @@ -203,17 +206,16 @@ public void ContractsNew_FormValidation_RequiresDescription() { // Arrange Guid operatorId = Guid.NewGuid(); - List operators = new List + List operators = new List { - new OperatorDropDownModel + new OperatorModels.OperatorDropDownModel { OperatorId = operatorId, OperatorName = "Test Operator" } }; - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(operators)); + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(operators)); IRenderedComponent cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.ShouldContain("Test Operator"), timeout: TimeSpan.FromSeconds(5)); @@ -229,7 +231,6 @@ public void ContractsNew_FormValidation_RequiresDescription() cut.WaitForAssertion(() => { cut.Markup.ShouldContain("Description is required"); // Should not call the mediator - _mockMediator.Verify(x => x.Send(It.IsAny(), default), Times.Never()); }, timeout: TimeSpan.FromSeconds(5)); } @@ -237,17 +238,16 @@ public void ContractsNew_FormValidation_RequiresDescription() public void ContractsNew_FormValidation_RequiresOperator() { // Arrange - List operators = new List + List operators = new List { - new OperatorDropDownModel + new OperatorModels.OperatorDropDownModel { OperatorId = Guid.NewGuid(), OperatorName = "Test Operator" } }; - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(operators)); + this.OperatorUIService.Setup(o => o.GetOperatorsForDropDown(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(operators)); IRenderedComponent cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.ShouldContain("Test Operator"), timeout: TimeSpan.FromSeconds(5)); @@ -262,8 +262,6 @@ public void ContractsNew_FormValidation_RequiresOperator() // Assert - Validation message should appear cut.WaitForAssertion(() => { cut.Markup.ShouldContain("Operator is required"); - // Should not call the mediator - _mockMediator.Verify(x => x.Send(It.IsAny(), default), Times.Never()); }, timeout: TimeSpan.FromSeconds(5)); } } diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsViewPageTests.cs b/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsViewPageTests.cs index 1888eab5..21712ef1 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsViewPageTests.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/Contracts/ContractsViewPageTests.cs @@ -2,6 +2,7 @@ using Bunit; using EstateManagementUI.BlazorServer.Components.Pages.Contracts; using EstateManagementUI.BlazorServer.Components.Permissions; +using EstateManagementUI.BlazorServer.Models; using EstateManagementUI.BlazorServer.Permissions; using EstateManagementUI.BlazorServer.Tests.Pages.FileProcessing; using EstateManagementUI.BusinessLogic.Models; @@ -12,6 +13,7 @@ using Moq; using Shouldly; using SimpleResults; +using TransactionProcessor.DataTransferObjects.Responses.Contract; namespace EstateManagementUI.BlazorServer.Tests.Pages.Contracts; @@ -22,16 +24,16 @@ public void ContractsView_RendersCorrectly() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator" }; - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -45,16 +47,16 @@ public void ContractsView_DisplaysContractDetails() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator" }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -69,9 +71,15 @@ public void ContractsView_HasCorrectPageTitle() { // Arrange var contractId = Guid.NewGuid(); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new ContractModel { ContractId = contractId })); - + var contract = new ContractModels.ContractModel + { + ContractId = contractId, + Description = "Test Contract", + OperatorName = "Test Operator" + }; + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(contract)); + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -86,16 +94,16 @@ public void ContractsView_HasBackButton() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator" }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -110,16 +118,16 @@ public void ContractsView_BackButton_NavigatesToContractsList() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator" }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -140,28 +148,28 @@ public void ContractsView_DisplaysProducts_WhenPresent() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = Guid.NewGuid(), ProductName = "Test Product", DisplayText = "Test Display", - ProductType = "MobileTopup", + ProductType = ProductType.MobileTopup, Value = "100", NumberOfFees = 2 } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -178,17 +186,17 @@ public void ContractsView_DisplaysNoProducts_WhenEmpty() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List() + Products = new List() }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -203,24 +211,24 @@ public void ContractsView_DisplaysTransactionFees_WhenPresent() { // Arrange var contractId = Guid.NewGuid(); - var contract = new ContractModel + var contract = new ContractModels.ContractModel { ContractId = contractId, Description = "Test Contract", OperatorName = "Test Operator", - Products = new List + Products = new List { - new ContractProductModel + new ContractModels.ContractProductModel { ContractProductId = Guid.NewGuid(), ProductName = "Test Product", DisplayText = "Test Display", - ProductType = "MobileTopup", + ProductType = ProductType.MobileTopup, Value = "100", NumberOfFees = 1, - TransactionFees = new List + TransactionFees = new List { - new ContractProductTransactionFeeModel + new ContractModels.ContractProductTransactionFeeModel { TransactionFeeId = Guid.NewGuid(), Description = "Service Fee", @@ -232,10 +240,10 @@ public void ContractsView_DisplaysTransactionFees_WhenPresent() } } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(contract)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); @@ -252,72 +260,15 @@ public void ContractsView_LoadContract_QueryFails_ShowsNotFoundMessage() { // Arrange var contractId = Guid.NewGuid(); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Failure("Failed to load contract")); - - // Act - var cut = RenderComponent(parameters => parameters - .Add(p => p.ContractId, contractId)); - cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); - - // Assert - cut.Markup.ShouldContain("Contract not found"); - } - - [Fact] - public void ContractsView_LoadContract_ReturnsNull_ShowsNotFoundMessage() - { - // Arrange - var contractId = Guid.NewGuid(); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(null!)); - - // Act - var cut = RenderComponent(parameters => parameters - .Add(p => p.ContractId, contractId)); - cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); - - // Assert - cut.Markup.ShouldContain("Contract not found"); - } + this.ContractUIService.Setup(c => c.GetContract(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); - [Fact] - public void ContractsView_ContractNotFound_HasBackButton() - { - // Arrange - var contractId = Guid.NewGuid(); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(null!)); - // Act var cut = RenderComponent(parameters => parameters .Add(p => p.ContractId, contractId)); - cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); - - // Assert - cut.Markup.ShouldContain("Back to List"); - } + //cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); - [Fact] - public void ContractsView_ContractNotFound_BackButton_NavigatesToContractsList() - { - // Arrange - var contractId = Guid.NewGuid(); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(null!)); - - // Act - var cut = RenderComponent(parameters => parameters - .Add(p => p.ContractId, contractId)); - cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); - - // Find and click the Back to List button - IRefreshableElementCollection buttons = cut.FindAll("button"); - IElement? backButton = buttons.FirstOrDefault(b => b.TextContent.Contains("Back to List")); - backButton.ShouldNotBeNull(); - backButton.Click(); - // Assert - _fakeNavigationManager.Uri.ShouldContain("/contracts"); + _fakeNavigationManager.Uri.ShouldContain("error"); } } diff --git a/EstateManagementUI.BlazorServer.Tests/UIServices/ContractUIServiceTests.cs b/EstateManagementUI.BlazorServer.Tests/UIServices/ContractUIServiceTests.cs new file mode 100644 index 00000000..025dcdca --- /dev/null +++ b/EstateManagementUI.BlazorServer.Tests/UIServices/ContractUIServiceTests.cs @@ -0,0 +1,349 @@ +using EstateManagementUI.BlazorServer.Models; +using EstateManagementUI.BlazorServer.UIServices; +using EstateManagementUI.BusinessLogic.Requests; +using MediatR; +using Moq; +using Shouldly; +using SimpleResults; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace EstateManagementUI.BlazorServer.Tests.UIServices +{ + public class ContractUIServiceTests + { + private readonly Mock _mockMediator; + private readonly ContractUIService _service; + + public ContractUIServiceTests() + { + _mockMediator = new Mock(); + _service = new ContractUIService(_mockMediator.Object); + } + + [Fact] + public async Task GetContracts_ReturnsMappedList_WhenMediatorSucceeds() + { + // Arrange + var estateId = Guid.NewGuid(); + var correlationId = CorrelationIdHelper.New(); + + var bizContracts = new List + { + new() + { + ContractId = Guid.NewGuid(), + Description = "Contract A", + OperatorId = Guid.NewGuid(), + OperatorName = "OpA", + Products = new List + { + new() + { + ContractProductId = Guid.NewGuid(), + ProductName = "Prod1", + DisplayText = "Prod 1", + ProductType = "NotSet", + Value = "10.00", + NumberOfFees = 0, + TransactionFees = new List() + } + } + } + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(bizContracts)); + + // Act + var result = await _service.GetContracts(correlationId, estateId); + + // Assert + result.IsSuccess.ShouldBeTrue(); + result.Data.ShouldNotBeNull(); + result.Data!.Count.ShouldBe(1); + var mapped = result.Data.First(); + mapped.ContractId.ShouldBe(bizContracts[0].ContractId); + mapped.Description.ShouldBe("Contract A"); + mapped.OperatorName.ShouldBe("OpA"); + mapped.Products.ShouldNotBeNull(); + mapped.Products!.Count.ShouldBe(1); + mapped.Products![0].ProductName.ShouldBe("Prod1"); + } + + [Fact] + public async Task GetContracts_ReturnsFailure_WhenMediatorFails() + { + // Arrange + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure("err")); + + // Act + var result = await _service.GetContracts(CorrelationIdHelper.New(), Guid.NewGuid()); + + // Assert + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task GetContract_ReturnsMappedModel_WhenMediatorSucceeds() + { + // Arrange + var estateId = Guid.NewGuid(); + var contractId = Guid.NewGuid(); + var bizContract = new BusinessLogic.Models.ContractModel + { + ContractId = contractId, + Description = "Contract Detail", + OperatorId = Guid.NewGuid(), + OperatorName = "OpDetail", + Products = new List() + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(bizContract)); + + // Act + var result = await _service.GetContract(CorrelationIdHelper.New(), estateId, contractId); + + // Assert + result.IsSuccess.ShouldBeTrue(); + var model = result.Data!; + model.ContractId.ShouldBe(contractId); + model.Description.ShouldBe("Contract Detail"); + model.OperatorName.ShouldBe("OpDetail"); + } + + [Fact] + public async Task GetContract_ReturnsFailure_WhenMediatorFails() + { + // Arrange + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure("nf")); + + // Act + var result = await _service.GetContract(CorrelationIdHelper.New(), Guid.NewGuid(), Guid.NewGuid()); + + // Assert + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task AddProductToContract_SendsCommand_WithValue_WhenNotVariable() + { + // Arrange + var estateId = Guid.NewGuid(); + var contractId = Guid.NewGuid(); + + var productModel = new ContractModels.AddProductModel + { + ProductName = "P1", + DisplayText = "P One", + IsVariableValue = false, + Value = 12.34m + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + // Act + var result = await _service.AddProductToContract(CorrelationIdHelper.New(), estateId, contractId, productModel); + + // Assert + result.IsSuccess.ShouldBeTrue(); + _mockMediator.Verify(m => m.Send(It.Is(c => + c.EstateId == estateId && + c.ContractId == contractId && + c.ProductName == productModel.ProductName && + c.DisplayText == productModel.DisplayText && + c.Value.HasValue && c.Value.Value == productModel.Value + ), It.IsAny()), Times.Once); + } + + [Fact] + public async Task AddProductToContract_SendsCommand_NullValue_WhenVariable() + { + // Arrange + var estateId = Guid.NewGuid(); + var contractId = Guid.NewGuid(); + + var productModel = new ContractModels.AddProductModel + { + ProductName = "P2", + DisplayText = "P Two", + IsVariableValue = true, + Value = 99.99m + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + // Act + var result = await _service.AddProductToContract(CorrelationIdHelper.New(), estateId, contractId, productModel); + + // Assert + result.IsSuccess.ShouldBeTrue(); + _mockMediator.Verify(m => m.Send(It.Is(c => + c.EstateId == estateId && + c.ContractId == contractId && + c.ProductName == productModel.ProductName && + c.DisplayText == productModel.DisplayText && + c.Value == null + ), It.IsAny()), Times.Once); + } + + [Fact] + public async Task AddProductToContract_ReturnsFailure_WhenMediatorFails() + { + // Arrange + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure); + + // Act + var result = await _service.AddProductToContract(CorrelationIdHelper.New(), Guid.NewGuid(), Guid.NewGuid(), new ContractModels.AddProductModel { ProductName = "x", DisplayText = "y", IsVariableValue = false, Value = 1m }); + + // Assert + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task AddTransactionFeeToProduct_SendsCorrectCommand() + { + // Arrange + var estateId = Guid.NewGuid(); + var contractId = Guid.NewGuid(); + var contractProductId = Guid.NewGuid(); + + var feeModel = new ContractModels.AddTransactionFeeModel + { + Description = "Fee A", + FeeValue = 2.50m, + CalculationType = "Fixed", + FeeType = "Charge" + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + // Act + var result = await _service.AddTransactionFeeToProduct(CorrelationIdHelper.New(), estateId, contractId, contractProductId, feeModel); + + // Assert + result.IsSuccess.ShouldBeTrue(); + _mockMediator.Verify(m => m.Send(It.Is(c => + c.EstateId == estateId && + c.ContractId == contractId && + c.ProductId == contractProductId && + c.Description == feeModel.Description && + c.Value == feeModel.FeeValue.Value && + c.CalculationType == feeModel.CalculationType && + c.FeeType == feeModel.FeeType + ), It.IsAny()), Times.Once); + } + + [Fact] + public async Task AddTransactionFeeToProduct_ReturnsFailure_WhenMediatorFails() + { + // Arrange + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure); + + // Act + var result = await _service.AddTransactionFeeToProduct(CorrelationIdHelper.New(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), new ContractModels.AddTransactionFeeModel { Description = "d", FeeValue = 1m, CalculationType = "c", FeeType = "f" }); + + // Assert + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task RemoveTransactionFeeFromProduct_SendsCorrectCommand() + { + // Arrange + var estateId = Guid.NewGuid(); + var contractId = Guid.NewGuid(); + var contractProductId = Guid.NewGuid(); + var transactionFeeId = Guid.NewGuid(); + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + // Act + var result = await _service.RemoveTransactionFeeFromProduct(CorrelationIdHelper.New(), estateId, contractId, contractProductId, transactionFeeId); + + // Assert + result.IsSuccess.ShouldBeTrue(); + } + + [Fact] + public async Task RemoveTransactionFeeFromProduct_ReturnsFailure_WhenMediatorFails() + { + // Arrange + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure); + + // Act + var result = await _service.RemoveTransactionFeeFromProduct(CorrelationIdHelper.New(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()); + + // Assert + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task CreateContract_SendsCreateCommand_WithParsedOperatorId() + { + // Arrange + var estateId = Guid.NewGuid(); + var operatorId = Guid.NewGuid(); + var createModel = new ContractModels.CreateContractFormModel + { + Description = "New Contract", + OperatorId = operatorId.ToString() + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + // Act + var result = await _service.CreateContract(CorrelationIdHelper.New(), estateId, createModel); + + // Assert + result.IsSuccess.ShouldBeTrue(); + _mockMediator.Verify(m => m.Send(It.Is(c => + c.EstateId == estateId && + c.Description == createModel.Description && + c.OperatorId == operatorId + ), It.IsAny()), Times.Once); + } + + [Fact] + public async Task CreateContract_ReturnsFailure_WhenMediatorFails() + { + // Arrange + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure); + + // Act + var result = await _service.CreateContract(CorrelationIdHelper.New(), Guid.NewGuid(), new ContractModels.CreateContractFormModel { Description = "x", OperatorId = Guid.NewGuid().ToString() }); + + // Assert + result.IsFailed.ShouldBeTrue(); + } + } +} \ No newline at end of file diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Contracts/Edit.razor b/EstateManagementUI.BlazorServer/Components/Pages/Contracts/Edit.razor index 65644d1b..f24da40f 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Contracts/Edit.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Contracts/Edit.razor @@ -4,8 +4,9 @@ @using System.ComponentModel.DataAnnotations @using EstateManagementUI.BlazorServer.Factories @using EstateManagementUI.BlazorServer.Permissions +@using EstateManagementUI.BlazorServer.UIServices @using EstateManagementUI.BusinessLogic.Requests -@inject IMediator Mediator +@inject IContractUIService ContractUiService @inject NavigationManager NavigationManager @inject IPermissionService PermissionService @@ -26,8 +27,8 @@

Edit Contract: @contractModel.Description

-
@@ -73,9 +74,6 @@
-