diff --git a/src/AzureIoTHub.Portal.Infrastructure/Repositories/DeviceTagRepository.cs b/src/AzureIoTHub.Portal.Infrastructure/Repositories/DeviceTagRepository.cs new file mode 100644 index 000000000..535bf59e0 --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Repositories/DeviceTagRepository.cs @@ -0,0 +1,15 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Infrastructure.Repositories +{ + using AzureIoTHub.Portal.Domain.Repositories; + using Domain.Entities; + + public class DeviceTagRepository : GenericRepository, IDeviceTagRepository + { + public DeviceTagRepository(PortalDbContext context) : base(context) + { + } + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/Repositories/GenericRepository.cs b/src/AzureIoTHub.Portal.Infrastructure/Repositories/GenericRepository.cs index 07af67243..d0961bc7a 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Repositories/GenericRepository.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Repositories/GenericRepository.cs @@ -24,7 +24,7 @@ public IEnumerable GetAll() .ToList(); } - public async Task GetByIdAsync(object id) + public async Task GetByIdAsync(object id) { var t = await this.context.Set().FindAsync(id); return t; diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPageTests.cs index 8d0bb6b07..877c36aeb 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPageTests.cs @@ -56,7 +56,7 @@ public void DeviceConfigurationDetailPageShouldRenderCorrectly() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); // Act var cut = RenderComponent(); @@ -84,7 +84,7 @@ public void DeviceConfigurationDetailShouldCreateConfiguration() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); _ = this.mockDeviceConfigurationsClientService.Setup(service => service.CreateDeviceConfiguration(It.Is(config => configuration.Equals(config)))) @@ -120,7 +120,7 @@ public void DeviceConfigurationDetailShouldProcessProblemDetailsExceptionWhenIss _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); _ = this.mockDeviceConfigurationsClientService.Setup(service => service.CreateDeviceConfiguration(It.Is(config => configuration.Equals(config)))) @@ -181,7 +181,7 @@ public void WhenClickToDeleteTagShouldRemoveTheSelectedTag() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new () { Name = "tag0" }, new () { Name = "tag1" } @@ -228,7 +228,7 @@ public void WhenClickToAddTagShouldAddTheSelectedTag() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new () { Name = "tag0" }, new () { Name = "tag1" } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPageTests.cs index 218a31cd7..70864a894 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPageTests.cs @@ -86,7 +86,7 @@ public void DeviceConfigurationDetailPageShouldRenderCorrectly() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); // Act var cut = RenderComponent(ComponentParameter.CreateParameter("ConfigId", configurationId)); @@ -153,7 +153,7 @@ public void ClickOnDeleteDeviceConfigurationShouldShowDeleteDialog() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); var mockDialogReference = MockRepository.Create(); _ = mockDialogReference.Setup(c => c.Result).ReturnsAsync(DialogResult.Cancel()); @@ -217,7 +217,7 @@ public void DeviceConfigurationDetailPageShouldRenderCardCorrectly() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); // Act var cut = RenderComponent(ComponentParameter.CreateParameter("ConfigId", configurationId)); @@ -280,7 +280,7 @@ public void DeviceConfigurationDetailPageShouldRenderTags() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new () { Name = "tag0" }, new () { Name = "tag1" } @@ -337,7 +337,7 @@ public void WhenClickToDeleteTagShouldRemoveTheSelectedTag() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new () { Name = "tag0" }, new () { Name = "tag1" } @@ -398,7 +398,7 @@ public void WhenClickToAddTagShouldAddTheSelectedTag() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new () { Name = "tag0" }, new () { Name = "tag1" } @@ -490,7 +490,7 @@ public void DeviceConfigurationDetailPageShouldRenderProperties() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); // Act var cut = RenderComponent(ComponentParameter.CreateParameter("ConfigId", configurationId)); @@ -574,7 +574,7 @@ public void WhenClickToDeletePropertyShouldRemoveTheSelectedProperty() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); var cut = RenderComponent(ComponentParameter.CreateParameter("ConfigId", configurationId)); @@ -656,7 +656,7 @@ public void WhenClickToAddPropertyShouldAddTheSelectedProperty() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); var cut = RenderComponent(ComponentParameter.CreateParameter("ConfigId", configurationId)); @@ -743,7 +743,7 @@ public void WhenClickToSaveShouldSendPutToTheEndpoint() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new () { Name = "tag0" }, new () { Name = "tag1" } @@ -836,7 +836,7 @@ public void DeviceConfigurationDetailPageShouldProcessProblemDetailsExceptionWhe _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new () { Name = "tag0" }, new () { Name = "tag1" } @@ -900,7 +900,7 @@ public void ReturnButtonMustNavigateToPreviousPage() _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); var cut = RenderComponent(ComponentParameter.CreateParameter("ConfigId", configurationId)); cut.WaitForAssertion(() => cut.Find("#returnButton")); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/CreateDevicePageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/CreateDevicePageTests.cs index 91f652791..a620fd807 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/CreateDevicePageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/CreateDevicePageTests.cs @@ -87,7 +87,7 @@ public async Task ClickOnSaveShouldPostDeviceDetailsAsync() }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new() { @@ -139,7 +139,7 @@ public async Task DeviceShouldNotBeCreatedWhenModelIsNotValid() }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new() { @@ -238,7 +238,7 @@ public async Task SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnCreat }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new() { @@ -293,7 +293,7 @@ public async Task ChangeModelShouldProcessProblemDetailsExceptionWhenIssueOccurs }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new() { @@ -347,7 +347,7 @@ public async Task ClickOnSaveAndAddNewShouldCreateDeviceAndResetCreateDevicePage }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new() { @@ -423,7 +423,7 @@ public async Task ClickOnSaveAndDuplicateShouldCreateDeviceAndDuplicateDeviceDet }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new() { diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceDetailPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceDetailPageTests.cs index af69c54d1..8a349acd6 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceDetailPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceDetailPageTests.cs @@ -86,7 +86,7 @@ public void ShouldLoadDeviceDetails() .ReturnsAsync(new DeviceModel()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); // Act var cut = RenderComponent(ComponentParameter.CreateParameter("DeviceID", deviceId)); @@ -114,7 +114,7 @@ public void ShouldLoadLoRaDeviceDetails() .ReturnsAsync(new List()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); // Act var cut = RenderComponent( @@ -145,7 +145,7 @@ public void ReturnButtonMustNavigateToPreviousPage() .ReturnsAsync(new DeviceModel()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); // Act @@ -170,7 +170,7 @@ public void ClickOnSaveShouldPutDeviceDetails() Name = Guid.NewGuid().ToString() }; - var mockTag = new DeviceTag + var mockTag = new DeviceTagDto { Label = Guid.NewGuid().ToString(), Name = Guid.NewGuid().ToString(), @@ -200,7 +200,7 @@ public void ClickOnSaveShouldPutDeviceDetails() .ReturnsAsync(mockDeviceModel); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockTag }); @@ -238,7 +238,7 @@ public void SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnUpdatingDev Name = Guid.NewGuid().ToString() }; - var mockTag = new DeviceTag + var mockTag = new DeviceTagDto { Label = Guid.NewGuid().ToString(), Name = Guid.NewGuid().ToString(), @@ -268,7 +268,7 @@ public void SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnUpdatingDev .ReturnsAsync(mockDeviceModel); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockTag }); @@ -299,7 +299,7 @@ public void ClickOnSaveShouldDisplaySnackbarIfValidationError() Name = Guid.NewGuid().ToString() }; - var mockTag = new DeviceTag + var mockTag = new DeviceTagDto { Label = Guid.NewGuid().ToString(), Name = Guid.NewGuid().ToString(), @@ -326,7 +326,7 @@ public void ClickOnSaveShouldDisplaySnackbarIfValidationError() .ReturnsAsync(mockDeviceModel); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockTag }); @@ -359,7 +359,7 @@ public void ClickOnConnectShouldDisplayDeviceCredentials() Name = Guid.NewGuid().ToString() }; - var mockTag = new DeviceTag + var mockTag = new DeviceTagDto { Label = Guid.NewGuid().ToString(), Name = Guid.NewGuid().ToString(), @@ -386,7 +386,7 @@ public void ClickOnConnectShouldDisplayDeviceCredentials() .ReturnsAsync(mockDeviceModel); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockTag }); @@ -420,7 +420,7 @@ public void ClickOnDeleteShouldDisplayConfirmationDialogAndReturnIfAborted() Name = Guid.NewGuid().ToString() }; - var mockTag = new DeviceTag + var mockTag = new DeviceTagDto { Label = Guid.NewGuid().ToString(), Name = Guid.NewGuid().ToString(), @@ -447,7 +447,7 @@ public void ClickOnDeleteShouldDisplayConfirmationDialogAndReturnIfAborted() .ReturnsAsync(mockDeviceModel); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockTag }); @@ -482,7 +482,7 @@ public void ClickOnDeleteShouldDisplayConfirmationDialogAndRedirectIfConfirmed() Name = Guid.NewGuid().ToString() }; - var mockTag = new DeviceTag + var mockTag = new DeviceTagDto { Label = Guid.NewGuid().ToString(), Name = Guid.NewGuid().ToString(), @@ -509,7 +509,7 @@ public void ClickOnDeleteShouldDisplayConfirmationDialogAndRedirectIfConfirmed() .ReturnsAsync(mockDeviceModel); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockTag }); @@ -545,7 +545,7 @@ public void ClickOnDuplicateShouldDuplicateDeviceDetailAndRedirectToCreateDevice Name = Guid.NewGuid().ToString() }; - var mockTag = new DeviceTag + var mockTag = new DeviceTagDto { Label = Guid.NewGuid().ToString(), Name = Guid.NewGuid().ToString(), @@ -572,7 +572,7 @@ public void ClickOnDuplicateShouldDuplicateDeviceDetailAndRedirectToCreateDevice .ReturnsAsync(mockDeviceModel); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockTag }); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DevicesListPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DevicesListPageTests.cs index c03c4e050..c99fe58f0 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DevicesListPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DevicesListPageTests.cs @@ -50,7 +50,7 @@ public void DeviceListPageRendersCorrectly() using var deviceResponseMock = new HttpResponseMessage(); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); _ = this.mockDeviceClientService.Setup(service => service.GetDevices($"{this.apiBaseUrl}?pageSize=10&searchText=&searchStatus=&searchState=")) @@ -85,7 +85,7 @@ public async Task WhenResetFilterButtonClickShouldClearFilters() _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); // Act @@ -122,7 +122,7 @@ public void WhenAddNewDeviceClickShouldNavigateToNewDevicePage() _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); var mockNavigationManager = Services.GetRequiredService(); @@ -151,7 +151,7 @@ public void ClickOnRefreshShouldReloadDevices() _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); var cut = RenderComponent(); @@ -178,7 +178,7 @@ public void WhenLoraFeatureDisableClickToItemShouldRedirectToDeviceDetailsPage() _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = false }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); var cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.Should().NotContain("Loading...")); @@ -206,7 +206,7 @@ public void WhenLoraFeatureEnableClickToItemShouldRedirectToLoRaDeviceDetailsPag _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); var cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.Should().NotContain("Loading...")); @@ -255,7 +255,7 @@ public void LoadItemsShouldProcessProblemDetailsExceptionWhenIssueOccursOnGettin _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); // Act var cut = RenderComponent(); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/CreateEdgeDevicePageTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/CreateEdgeDevicePageTest.cs index cf989b716..fe83aeb36 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/CreateEdgeDevicePageTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/CreateEdgeDevicePageTest.cs @@ -62,9 +62,9 @@ public async Task SaveShouldCreateEdgeDeviceAndRedirectToEdgeDeviceList() .ReturnsAsync(new List() { edgeModel }); _ = this.mockDeviceTagSettingsClientService.Setup(x => x.GetDeviceTags()) - .ReturnsAsync(new List() + .ReturnsAsync(new List() { - new DeviceTag(){ Name = "tag01", Required = true} + new DeviceTagDto(){ Name = "tag01", Required = true} }); _ = this.mockEdgeDeviceClientService @@ -103,9 +103,9 @@ public async Task CreateEdgeDevicePageSaveShouldProcessProblemDetailsExceptionWh .ReturnsAsync(new List() { edgeModel }); _ = this.mockDeviceTagSettingsClientService.Setup(x => x.GetDeviceTags()) - .ReturnsAsync(new List() + .ReturnsAsync(new List() { - new DeviceTag(){ Name = "tag01", Required = true} + new DeviceTagDto(){ Name = "tag01", Required = true} }); _ = this.mockEdgeDeviceClientService diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs index 056049c3d..0571cada9 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs @@ -138,15 +138,15 @@ public void EdgeDeviceDetailPageShouldProcessProblemDetailsExceptionWhenIssueOcc _ = this.mockDeviceTagSettingsClientService .Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List() + .ReturnsAsync(new List() { - new DeviceTag() + new DeviceTagDto() { Name = "test01", Label = "test01", Required = true }, - new DeviceTag() + new DeviceTagDto() { Name = "test02", Label = "test02", @@ -208,7 +208,7 @@ public void ClickOnRebootShouldRebootModule() .Setup(service => service.GetIoTEdgeModel(It.Is(x => x.Equals(mockIoTEdgeDevice.ModelId, StringComparison.Ordinal)))) .ReturnsAsync(new IoTEdgeModel()); - _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); + _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); _ = this.mockEdgeDeviceClientService.Setup(service => service.ExecuteModuleMethod(this.mockdeviceId, It.Is(module => mockIoTEdgeModule.ModuleName.Equals(module, StringComparison.Ordinal)), "RestartModule")) .ReturnsAsync(new C2Dresult() @@ -253,7 +253,7 @@ public void ClickOnRebootShouldDisplaySnackbarIfError() .Setup(service => service.GetIoTEdgeModel(It.Is(x => x.Equals(mockIoTEdgeDevice.ModelId, StringComparison.Ordinal)))) .ReturnsAsync(new IoTEdgeModel()); - _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); + _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); _ = this.mockEdgeDeviceClientService.Setup(service => service.ExecuteModuleMethod(this.mockdeviceId, It.Is(module => mockIoTEdgeModule.ModuleName.Equals(module, StringComparison.Ordinal)), "RestartModule")) .ReturnsAsync(new C2Dresult() @@ -299,7 +299,7 @@ public void EdgeDeviceDetailPageShouldProcessProblemDetailsExceptionWhenIssueOcc .Setup(service => service.GetIoTEdgeModel(It.Is(x => x.Equals(mockIoTEdgeDevice.ModelId, StringComparison.Ordinal)))) .ReturnsAsync(new IoTEdgeModel()); - _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); + _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); _ = this.mockEdgeDeviceClientService.Setup(service => service.ExecuteModuleMethod(this.mockdeviceId, It.Is(module => mockIoTEdgeModule.ModuleName.Equals(module, StringComparison.Ordinal)), "RestartModule")) .ThrowsAsync(new ProblemDetailsException(new ProblemDetailsWithExceptionDetails())); @@ -336,7 +336,7 @@ public void ClickOnLogsShouldDisplayLogs() .Setup(service => service.GetIoTEdgeModel(It.Is(x => x.Equals(mockIoTEdgeDevice.ModelId, StringComparison.Ordinal)))) .ReturnsAsync(new IoTEdgeModel()); - _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); + _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List()); var mockDialogReference = new DialogReference(Guid.NewGuid(), this.mockDialogService.Object); @@ -544,15 +544,15 @@ private IoTEdgeDevice SetupOnInitialisation() _ = this.mockDeviceTagSettingsClientService .Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List() + .ReturnsAsync(new List() { - new DeviceTag() + new DeviceTagDto() { Name = "test01", Label = "test01", Required = true }, - new DeviceTag() + new DeviceTagDto() { Name = "test02", Label = "test02", diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Settings/DeviceTagsPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Settings/DeviceTagsPageTests.cs index ad118690f..9d311a552 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Settings/DeviceTagsPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Settings/DeviceTagsPageTests.cs @@ -43,7 +43,7 @@ public void DeviceListPageRendersCorrectly() { // Arrange _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new() { @@ -87,7 +87,7 @@ public void OnclickOnReloadShouldReloadTags() MockHttpClient.Clear(); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(Fixture.Build().CreateMany(3).ToList()); + .ReturnsAsync(Fixture.Build().CreateMany(3).ToList()); // Act cut.WaitForElement("#reload-tags").Click(); @@ -130,7 +130,7 @@ public void ClickOnSaveShouldCreateUpdateTag() { //Arrange _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new() { @@ -138,7 +138,7 @@ public void ClickOnSaveShouldCreateUpdateTag() Searchable = false } }); - _ = this.mockDeviceTagSettingsClientService.Setup(service => service.CreateOrUpdateDeviceTag(It.IsAny())) + _ = this.mockDeviceTagSettingsClientService.Setup(service => service.CreateOrUpdateDeviceTag(It.IsAny())) .Returns(Task.CompletedTask); _ = this.mockSnackbarService.Setup(c => c.Add(It.IsAny(), Severity.Success, null)).Returns((Snackbar)null); @@ -160,7 +160,7 @@ public void ClickOnDeleteShouldDeleteTag() const string deviceTagName = "tagName"; _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new() { @@ -183,7 +183,7 @@ public void ClickOnDeleteShouldDeleteTag() [Test] public void ClickOnSaveShouldDisplayErrorSnackbarIfDuplicated() { - var mockTag = new DeviceTag + var mockTag = new DeviceTagDto { Label = "Label", Name = "Name", @@ -192,7 +192,7 @@ public void ClickOnSaveShouldDisplayErrorSnackbarIfDuplicated() }; _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockTag, mockTag @@ -216,7 +216,7 @@ public void ClickOnSaveShouldDisplayErrorSnackbarIfDuplicated() [Test] public void ClickOnSaveShouldDisplayErrorSnackbarIfValidationIssue() { - var mockTag = new DeviceTag + var mockTag = new DeviceTagDto { Label = "Label", Name = "InvalidName!", @@ -225,7 +225,7 @@ public void ClickOnSaveShouldDisplayErrorSnackbarIfValidationIssue() }; _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockTag, mockTag @@ -251,12 +251,12 @@ public void ClickOnSaveShouldProcessProblemDetailsExceptionIfIssueOccursWhenUpda { // Arrange _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new () { Label = "Label", Name = "Name", Required = false, Searchable = false } }); - _ = this.mockDeviceTagSettingsClientService.Setup(service => service.CreateOrUpdateDeviceTag(It.IsAny())) + _ = this.mockDeviceTagSettingsClientService.Setup(service => service.CreateOrUpdateDeviceTag(It.IsAny())) .ThrowsAsync(new ProblemDetailsException(new ProblemDetailsWithExceptionDetails())); // Act @@ -274,7 +274,7 @@ public void ClickOnAddNewTagShouldAddNewTag() { //Arrange _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) - .ReturnsAsync(Array.Empty()); + .ReturnsAsync(Array.Empty()); var cut = RenderComponent(); cut.WaitForAssertion(() => cut.Markup.Should().NotContain("Loading...")); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceLayoutServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceLayoutServiceTests.cs index 2ed0cb4bb..ffa873fa8 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceLayoutServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceLayoutServiceTests.cs @@ -117,7 +117,7 @@ public void ResetSharedDeviceShouldReturnNewDevice() public void ResetSharedDeviceShouldReturnNewDeviceWithExpectedTags() { // Arrange - var expectedTags = Fixture.CreateMany(2).ToList(); + var expectedTags = Fixture.CreateMany(2).ToList(); var expectedDevice = new DeviceDetails(); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceTagSettingsClientServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceTagSettingsClientServiceTests.cs index f63b1fda2..cf7591f18 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceTagSettingsClientServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceTagSettingsClientServiceTests.cs @@ -34,7 +34,7 @@ public override void Setup() public async Task GetDeviceTagsShouldReturnDeviceTags() { // Arrange - var expectedDeviceTags = Fixture.Build().CreateMany(3).ToList(); + var expectedDeviceTags = Fixture.Build().CreateMany(3).ToList(); _ = MockHttpClient.When(HttpMethod.Get, "/api/settings/device-tags") .RespondJson(expectedDeviceTags); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Repositories/DeviceTagRepositoryTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Repositories/DeviceTagRepositoryTests.cs new file mode 100644 index 000000000..5d7a9d081 --- /dev/null +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Repositories/DeviceTagRepositoryTests.cs @@ -0,0 +1,43 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Tests.Unit.Infrastructure.Repositories +{ + using System.Linq; + using System.Threading.Tasks; + using AutoFixture; + using AzureIoTHub.Portal.Domain.Entities; + using AzureIoTHub.Portal.Infrastructure.Repositories; + using FluentAssertions; + using UnitTests.Bases; + using NUnit.Framework; + + public class DeviceTagRepositoryTests : BackendUnitTest + { + private DeviceTagRepository deviceTagRepository; + + public override void Setup() + { + base.Setup(); + + this.deviceTagRepository = new DeviceTagRepository(DbContext); + } + + [Test] + public async Task GetAllShouldReturnExpectedDeviceTags() + { + // Arrange + var expectedDeviceTags = Fixture.CreateMany(5).ToList(); + + await DbContext.AddRangeAsync(expectedDeviceTags); + + _ = await DbContext.SaveChangesAsync(); + + // Act + var result = this.deviceTagRepository.GetAll().ToList(); + + // Assert + _ = result.Should().BeEquivalentTo(expectedDeviceTags); + } + } +} diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/DeviceTagSettingsControllerTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/DeviceTagSettingsControllerTest.cs index 3551b587d..8fb27ca53 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/DeviceTagSettingsControllerTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/DeviceTagSettingsControllerTest.cs @@ -47,7 +47,7 @@ public async Task PostShouldCreateNewEntity() // Arrange var deviceTagSettingsController = CreateDeviceTagSettingsController(); - var tag = new DeviceTag + var tag = new DeviceTagDto { Name = "testName", Label = "testLabel", @@ -55,11 +55,11 @@ public async Task PostShouldCreateNewEntity() Searchable = true }; - _ = this.mockDeviceTagService.Setup(c => c.UpdateTags(It.IsAny>())) + _ = this.mockDeviceTagService.Setup(c => c.UpdateTags(It.IsAny>())) .Returns(Task.CompletedTask); // Act - var result = await deviceTagSettingsController.Post(new List(new[] { tag })); + var result = await deviceTagSettingsController.Post(new List(new[] { tag })); // Assert Assert.IsNotNull(result); @@ -74,7 +74,7 @@ public void GetShouldReturnAList() // Arrange var deviceTagSettingsController = CreateDeviceTagSettingsController(); - _ = this.mockDeviceTagService.Setup(x => x.GetAllTags()).Returns(new DeviceTag[10].ToList()); + _ = this.mockDeviceTagService.Setup(x => x.GetAllTags()).Returns(new DeviceTagDto[10].ToList()); // Act var response = deviceTagSettingsController.Get(); @@ -87,7 +87,7 @@ public void GetShouldReturnAList() Assert.AreEqual(200, okResponse?.StatusCode); Assert.IsNotNull(okResponse?.Value); - var result = okResponse?.Value as IEnumerable; + var result = okResponse?.Value as IEnumerable; Assert.AreEqual(10, result?.Count()); this.mockDeviceTagService.VerifyAll(); @@ -98,14 +98,14 @@ public void GetShouldReturnAList() public async Task CreateOrUpdateDeviceTagShouldCreateOrUpdateDeviceTag() { // Arrange - var deviceTag = new DeviceTag + var deviceTag = new DeviceTagDto { Name = Guid.NewGuid().ToString(), }; var deviceTagSettingsController = CreateDeviceTagSettingsController(); - _ = this.mockDeviceTagService.Setup(x => x.CreateOrUpdateDeviceTag(It.Is(x => x.Name.Equals(deviceTag.Name, StringComparison.Ordinal)))) + _ = this.mockDeviceTagService.Setup(x => x.CreateOrUpdateDeviceTag(It.Is(x => x.Name.Equals(deviceTag.Name, StringComparison.Ordinal)))) .Returns(Task.CompletedTask); // Act @@ -121,7 +121,7 @@ public async Task CreateOrUpdateDeviceTagShouldCreateOrUpdateDeviceTag() public async Task DeleteDeviceTagByNameShouldDeleteDeviceTag() { // Arrange - var deviceTag = new DeviceTag + var deviceTag = new DeviceTagDto { Name = Guid.NewGuid().ToString(), }; diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceTagMapperTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceTagMapperTests.cs index f080bf7aa..fe47abed8 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceTagMapperTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceTagMapperTests.cs @@ -57,7 +57,7 @@ public void UpdateTableEntityStateUnderTestExpectedBehavior() var deviceTagMapper = CreateDeviceTagMapper(); var entity = new TableEntity(); - var element = new DeviceTag + var element = new DeviceTagDto { Name = "ExpectedName", Label = "ExpectedLabel", diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceTagServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceTagServiceTests.cs index 352e7fd2b..0d272e9e4 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceTagServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceTagServiceTests.cs @@ -6,110 +6,49 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services using System; using System.Collections.Generic; using System.Linq; - using System.Threading; using System.Threading.Tasks; - using Azure; - using Azure.Data.Tables; + using AutoFixture; using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Exceptions; - using AzureIoTHub.Portal.Server.Mappers; using AzureIoTHub.Portal.Server.Services; using FluentAssertions; + using Microsoft.EntityFrameworkCore; + using Microsoft.Extensions.DependencyInjection; using Models.v10; using Moq; using NUnit.Framework; + using Portal.Domain.Entities; + using Portal.Domain.Repositories; + using UnitTests.Bases; [TestFixture] - public class DeviceTagServiceTests + public class DeviceTagServiceTests : BackendUnitTest { - private MockRepository mockRepository; - private Mock mockDeviceTagMapper; - private Mock mockTableClientFactory; - private Mock mockDeviceTagTableClient; + private Mock mockDeviceTagRepository; + private Mock mockUnitOfWork; - [SetUp] - public void SetUp() - { - this.mockRepository = new MockRepository(MockBehavior.Strict); - this.mockDeviceTagMapper = this.mockRepository.Create(); - this.mockTableClientFactory = this.mockRepository.Create(); - this.mockDeviceTagTableClient = this.mockRepository.Create(); - } - - public DeviceTagService CreateDeviceTagService() - { - return new DeviceTagService( - this.mockDeviceTagMapper.Object, - this.mockTableClientFactory.Object); - } + private IDeviceTagService deviceTagService; - [Test] - public async Task UpdateShouldCreateNewEntity() + public override void Setup() { - var deviceTagService = CreateDeviceTagService(); - - var tag = new DeviceTag - { - Name = "testName", - Label = "testLabel", - Required = true, - Searchable = true - }; - - var mockResponse = this.mockRepository.Create(); - - _ = this.mockDeviceTagMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == tag.Name && x.PartitionKey == DeviceTagService.DefaultPartitionKey), - It.Is(x => x == tag))); - - _ = this.mockDeviceTagTableClient.Setup(c => c.AddEntityAsync( - It.Is(x => x.PartitionKey == DeviceTagService.DefaultPartitionKey && x.RowKey == tag.Name), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockDeviceTagTableClient.Setup(c => c.Query( - It.Is(_ => true), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(Pageable.FromPages(new[] { - Page.FromValues(new[] - { - new TableEntity(DeviceTagService.DefaultPartitionKey,tag.Name) - }, null, mockResponse.Object) - })); - - _ = this.mockDeviceTagTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(_ => true), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + base.Setup(); - // Act - await deviceTagService.UpdateTags(new List(new[] { tag })); - - // Assert - this.mockTableClientFactory.Verify(c => c.GetDeviceTagSettings()); + this.mockDeviceTagRepository = MockRepository.Create(); + this.mockUnitOfWork = MockRepository.Create(); - this.mockDeviceTagMapper.VerifyAll(); + _ = ServiceCollection.AddSingleton(this.mockDeviceTagRepository.Object); + _ = ServiceCollection.AddSingleton(this.mockUnitOfWork.Object); + _ = ServiceCollection.AddSingleton(); - this.mockDeviceTagTableClient.Verify(c => c.AddEntityAsync( - It.Is(x => x.RowKey == tag.Name && x.PartitionKey == DeviceTagService.DefaultPartitionKey), - It.IsAny()), Times.Once()); + Services = ServiceCollection.BuildServiceProvider(); - this.mockRepository.VerifyAll(); + this.deviceTagService = Services.GetRequiredService(); } [Test] - public async Task UpdateTagsShouldThrowInternalServerErrorExceptionWhenGettingExistingTags() + public async Task UpdateShouldCreateNewEntity() { - var deviceTagService = CreateDeviceTagService(); - - var tag = new DeviceTag + var tag = new DeviceTagDto { Name = "testName", Label = "testLabel", @@ -117,75 +56,52 @@ public async Task UpdateTagsShouldThrowInternalServerErrorExceptionWhenGettingEx Searchable = true }; - _ = this.mockDeviceTagTableClient.Setup(c => c.Query( - It.Is(_ => true), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException("test")); + _ = this.mockDeviceTagRepository.Setup(repository => repository.GetAll()) + .Returns(Array.Empty()); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + _ = this.mockDeviceTagRepository.Setup(repository => repository.InsertAsync(It.IsAny())) + .Returns(Task.CompletedTask); + + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); // Act - var act = () => deviceTagService.UpdateTags(new List(new[] { tag })); + await this.deviceTagService.UpdateTags(new List(new[] { tag })); // Assert - _ = await act.Should().ThrowAsync(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] - public async Task UpdateTagsShouldThrowInternalServerErrorExceptionWhenDeletingExistingTags() + public async Task UpdateTagsShouldDeleteExistingTagsAndCreatedNewTags() { - var deviceTagService = CreateDeviceTagService(); + var existingTags = Fixture.CreateMany(1).ToList(); - var tag = new DeviceTag - { - Name = "testName", - Label = "testLabel", - Required = true, - Searchable = true - }; + var newTags = Fixture.CreateMany(1).ToList(); + + _ = this.mockDeviceTagRepository.Setup(repository => repository.GetAll()) + .Returns(existingTags); + + this.mockDeviceTagRepository.Setup(repository => repository.Delete(It.IsAny())) + .Verifiable(); - var mockResponse = this.mockRepository.Create(); - - _ = this.mockDeviceTagTableClient.Setup(c => c.Query( - It.Is(_ => true), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(Pageable.FromPages(new[] { - Page.FromValues(new[] - { - new TableEntity(DeviceTagService.DefaultPartitionKey,tag.Name) - }, null, mockResponse.Object) - })); - - _ = this.mockDeviceTagTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(_ => true), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .ThrowsAsync(new RequestFailedException("test")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + _ = this.mockDeviceTagRepository.Setup(repository => repository.InsertAsync(It.IsAny())) + .Returns(Task.CompletedTask); + + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); // Act - var act = () => deviceTagService.UpdateTags(new List(new[] { tag })); + await this.deviceTagService.UpdateTags(newTags); // Assert - _ = await act.Should().ThrowAsync(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] - public async Task UpdateTagsShouldThrowInternalServerErrorExceptionWhenAddingNewTags() + public async Task UpdateTagsShouldThrowInternalServerErrorExceptionWhenDDbUpdateExceptionIsThrown() { - var deviceTagService = CreateDeviceTagService(); - - var tag = new DeviceTag + var tag = new DeviceTagDto { Name = "testName", Label = "testLabel", @@ -193,364 +109,206 @@ public async Task UpdateTagsShouldThrowInternalServerErrorExceptionWhenAddingNew Searchable = true }; - var mockResponse = this.mockRepository.Create(); - - _ = this.mockDeviceTagMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == tag.Name && x.PartitionKey == DeviceTagService.DefaultPartitionKey), - It.Is(x => x == tag))); - - _ = this.mockDeviceTagTableClient.Setup(c => c.AddEntityAsync( - It.Is(x => x.PartitionKey == DeviceTagService.DefaultPartitionKey && x.RowKey == tag.Name), - It.IsAny())) - .ThrowsAsync(new RequestFailedException("test")); - - _ = this.mockDeviceTagTableClient.Setup(c => c.Query( - It.Is(_ => true), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(Pageable.FromPages(new[] { - Page.FromValues(new[] - { - new TableEntity(DeviceTagService.DefaultPartitionKey,tag.Name) - }, null, mockResponse.Object) - })); - - _ = this.mockDeviceTagTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(_ => true), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + _ = this.mockDeviceTagRepository.Setup(repository => repository.GetAll()) + .Returns(Array.Empty()); + + _ = this.mockDeviceTagRepository.Setup(repository => repository.InsertAsync(It.IsAny())) + .Returns(Task.CompletedTask); + + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .ThrowsAsync(new DbUpdateException()); // Act - var act = () => deviceTagService.UpdateTags(new List(new[] { tag })); + var act = () => this.deviceTagService.UpdateTags(new List(new[] { tag })); // Assert _ = await act.Should().ThrowAsync(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public void GetAllTagsShouldReturnAList() { // Arrange - var deviceTagService = CreateDeviceTagService(); - var returnedIndex = 10; - - var mockTableResponse = this.mockRepository.Create>(); - var mockEnumerator = this.mockRepository.Create>(); - _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); - _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => returnedIndex-- > 0); - - _ = mockEnumerator.Setup(x => x.Current) - .Returns(new TableEntity(DeviceTagService.DefaultPartitionKey, "test")); - - _ = mockTableResponse.Setup(x => x.GetEnumerator()).Returns(mockEnumerator.Object); - - _ = this.mockDeviceTagTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) - .Returns(mockTableResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + var tags = Fixture.CreateMany(1).ToList(); + var expectedTags = tags.Select(tag => Mapper.Map(tag)).ToList(); - _ = this.mockDeviceTagMapper.Setup(c => c.GetDeviceTag(It.IsAny())) - .Returns((TableEntity _) => new DeviceTag - { - Name = Guid.NewGuid().ToString(), - Label = "test", - Required = true, - Searchable = true - }); + _ = this.mockDeviceTagRepository.Setup(repository => repository.GetAll()) + .Returns(tags); // Act - var result = deviceTagService.GetAllTags(); + var result = this.deviceTagService.GetAllTags(); // Assert - Assert.IsNotNull(result); - Assert.AreEqual(10, result.Count()); - Assert.IsAssignableFrom(result.First()); + _ = result.Should().BeEquivalentTo(expectedTags); - this.mockRepository.VerifyAll(); - } - - [Test] - public void GetAllTagsShouldThrowInternalServerErrorExceptionWhenIssueOccurs() - { - // Arrange - var deviceTagService = CreateDeviceTagService(); - - _ = this.mockDeviceTagTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), - It.IsAny>(), It.IsAny())) - .Throws(new RequestFailedException("test")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); - - // Act - var act = () => deviceTagService.GetAllTags(); - - // Assert - _ = act.Should().Throw(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public void GetAllTagsNamesShouldReturnAList() { // Arrange - var deviceTagService = CreateDeviceTagService(); - var returnedIndex = 10; - - var mockTableResponse = this.mockRepository.Create>(); - var mockEnumerator = this.mockRepository.Create>(); - _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); - _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => returnedIndex-- > 0); - - _ = mockEnumerator.Setup(x => x.Current) - .Returns(new TableEntity(DeviceTagService.DefaultPartitionKey, "test")); - - _ = mockTableResponse.Setup(x => x.GetEnumerator()).Returns(mockEnumerator.Object); - - _ = this.mockDeviceTagTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) - .Returns(mockTableResponse.Object); + var tags = Fixture.CreateMany(1).ToList(); + var expectedTagNames = tags.Select(tag => tag.Name).ToList(); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); - - _ = this.mockDeviceTagMapper.Setup(c => c.GetDeviceTag(It.IsAny())) - .Returns((TableEntity _) => new DeviceTag - { - Name = Guid.NewGuid().ToString(), - Label = "test", - Required = true, - Searchable = true - }); + _ = this.mockDeviceTagRepository.Setup(repository => repository.GetAll()) + .Returns(tags); // Act - var result = deviceTagService.GetAllTagsNames(); + var result = this.deviceTagService.GetAllTagsNames(); // Assert - Assert.IsNotNull(result); - Assert.AreEqual(10, result.Count()); - Assert.IsAssignableFrom(result.First()); - - this.mockRepository.VerifyAll(); - } - - [Test] - public void GetAllTagsNamesShouldThrowInternalServerErrorExceptionWhenAnIssueOccurs() - { - // Arrange - var deviceTagService = CreateDeviceTagService(); - - _ = this.mockDeviceTagTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) - .Throws(new RequestFailedException("test")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); - - // Act - var act = () => deviceTagService.GetAllTagsNames(); + _ = result.Should().BeEquivalentTo(expectedTagNames); - // Assert - _ = act.Should().Throw(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public void GetAllSearchableTagsNamesShouldReturnAList() { // Arrange - var deviceTagService = CreateDeviceTagService(); - var boolList = new List() { true, false, true }; - var returnedIndex = boolList.Count; - - var mockTableResponse = this.mockRepository.Create>(); - var mockEnumerator = this.mockRepository.Create>(); - _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); - _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => returnedIndex-- > 0); - - _ = mockEnumerator.Setup(x => x.Current) - .Returns(() => - { - return new TableEntity(DeviceTagService.DefaultPartitionKey, "test") - { - [nameof(DeviceTag.Searchable)] = boolList[returnedIndex], - }; - }); - - _ = mockTableResponse.Setup(x => x.GetEnumerator()).Returns(mockEnumerator.Object); - - _ = this.mockDeviceTagTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) - .Returns(mockTableResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); - - _ = this.mockDeviceTagMapper.Setup(c => c.GetDeviceTag(It.IsAny())) - .Returns((TableEntity entity) => new DeviceTag - { - Name = Guid.NewGuid().ToString(), - Label = "test", - Required = true, - Searchable = bool.Parse(entity[nameof(DeviceTag.Searchable)].ToString()) - }); + var tags = Fixture.CreateMany(1).Select(tag => + { + tag.Searchable = true; + return tag; + }).ToList(); + var expectedTagNames = tags.Select(tag => tag.Name).ToList(); + + _ = this.mockDeviceTagRepository.Setup(repository => repository.GetAll()) + .Returns(tags); // Act - var result = deviceTagService.GetAllSearchableTagsNames(); + var result = this.deviceTagService.GetAllSearchableTagsNames(); // Assert - Assert.IsNotNull(result); - Assert.AreEqual(2, result.Count()); - Assert.IsAssignableFrom(result.First()); + _ = result.Should().BeEquivalentTo(expectedTagNames); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] - public void GetAllSearchableTagsNamesShouldThrowInternalServerErrorExceptionWhenAnIssueOccurs() + public async Task CreateOrUpdateDeviceTagShouldInsertDeviceTag() { // Arrange - var deviceTagService = CreateDeviceTagService(); + var deviceTag = new DeviceTagDto + { + Name = Guid.NewGuid().ToString() + }; + + _ = this.mockDeviceTagRepository.Setup(repository => repository.GetByIdAsync(It.IsAny())) + .ReturnsAsync((DeviceTag)null); - _ = this.mockDeviceTagTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) - .Throws(new RequestFailedException("test")); + _ = this.mockDeviceTagRepository.Setup(repository => repository.InsertAsync(It.IsAny())) + .Returns(Task.CompletedTask); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); // Act - var act = () => deviceTagService.GetAllSearchableTagsNames(); + var act = () => this.deviceTagService.CreateOrUpdateDeviceTag(deviceTag); // Assert - _ = act.Should().Throw(); - this.mockRepository.VerifyAll(); + _ = await act.Should().NotThrowAsync(); + MockRepository.VerifyAll(); } [Test] - public async Task CreateOrUpdateDeviceTagShouldUpsertDeviceTag() + public async Task CreateOrUpdateDeviceTagShouldUpdateExistingDeviceTag() { // Arrange - var deviceTag = new DeviceTag + var deviceTag = new DeviceTagDto { Name = Guid.NewGuid().ToString() }; - var deviceTagService = CreateDeviceTagService(); - - var mockResponse = this.mockRepository.Create(); + _ = this.mockDeviceTagRepository.Setup(repository => repository.GetByIdAsync(It.IsAny())) + .ReturnsAsync(Mapper.Map(deviceTag)); - _ = this.mockDeviceTagMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == deviceTag.Name && x.PartitionKey == DeviceTagService.DefaultPartitionKey), - It.Is(x => x == deviceTag))); + this.mockDeviceTagRepository.Setup(repository => repository.Update(It.IsAny())) + .Verifiable(); - _ = this.mockDeviceTagTableClient.Setup(c => c.UpsertEntityAsync(It.Is(x => - x.PartitionKey == DeviceTagService.DefaultPartitionKey && x.RowKey == deviceTag.Name), It.IsAny(), It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); // Act - var act = () => deviceTagService.CreateOrUpdateDeviceTag(deviceTag); + var act = () => this.deviceTagService.CreateOrUpdateDeviceTag(deviceTag); // Assert _ = await act.Should().NotThrowAsync(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public async Task CreateOrUpdateDeviceTagShouldThrowInternalServerErrorExceptionWhenAnIssueOccurs() { // Arrange - var deviceTag = new DeviceTag + var deviceTag = new DeviceTagDto { Name = Guid.NewGuid().ToString() }; - var deviceTagService = CreateDeviceTagService(); - - _ = this.mockDeviceTagMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == deviceTag.Name && x.PartitionKey == DeviceTagService.DefaultPartitionKey), - It.Is(x => x == deviceTag))); + _ = this.mockDeviceTagRepository.Setup(repository => repository.GetByIdAsync(It.IsAny())) + .ReturnsAsync(Mapper.Map(deviceTag)); - _ = this.mockDeviceTagTableClient.Setup(c => c.UpsertEntityAsync(It.Is(x => - x.PartitionKey == DeviceTagService.DefaultPartitionKey && x.RowKey == deviceTag.Name), It.IsAny(), It.IsAny())) - .ThrowsAsync(new RequestFailedException("test")); + this.mockDeviceTagRepository.Setup(repository => repository.Update(It.IsAny())) + .Verifiable(); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .ThrowsAsync(new DbUpdateException()); // Act - var act = () => deviceTagService.CreateOrUpdateDeviceTag(deviceTag); + var act = () => this.deviceTagService.CreateOrUpdateDeviceTag(deviceTag); // Assert _ = await act.Should().ThrowAsync(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public async Task DeleteDeviceTagByNameShouldDeleteDeviceTag() { // Arrange - var deviceTag = new DeviceTag + var deviceTag = new DeviceTagDto { Name = Guid.NewGuid().ToString() }; - var deviceTagService = CreateDeviceTagService(); - - var mockResponse = this.mockRepository.Create(); + this.mockDeviceTagRepository.Setup(repository => repository.Delete(It.IsAny())) + .Verifiable(); - _ = this.mockDeviceTagTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(x => x.Equals(DeviceTagService.DefaultPartitionKey, StringComparison.Ordinal)), - It.Is(x => x.Equals(deviceTag.Name, StringComparison.Ordinal)), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); // Act - var act = () => deviceTagService.DeleteDeviceTagByName(deviceTag.Name); + var act = () => this.deviceTagService.DeleteDeviceTagByName(deviceTag.Name); // Assert _ = await act.Should().NotThrowAsync(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public async Task DeleteDeviceTagByNameShouldThrowInternalServerErrorExceptionWhenAnIssueOccurs() { // Arrange - var deviceTag = new DeviceTag + var deviceTag = new DeviceTagDto { Name = Guid.NewGuid().ToString() }; - var deviceTagService = CreateDeviceTagService(); - - _ = this.mockDeviceTagTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(x => x.Equals(DeviceTagService.DefaultPartitionKey, StringComparison.Ordinal)), - It.Is(x => x.Equals(deviceTag.Name, StringComparison.Ordinal)), - It.IsAny(), - It.IsAny())) - .ThrowsAsync(new RequestFailedException("test")); + this.mockDeviceTagRepository.Setup(repository => repository.Delete(It.IsAny())) + .Verifiable(); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTagSettings()) - .Returns(this.mockDeviceTagTableClient.Object); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .ThrowsAsync(new DbUpdateException()); // Act - var act = () => deviceTagService.DeleteDeviceTagByName(deviceTag.Name); + var act = () => this.deviceTagService.DeleteDeviceTagByName(deviceTag.Name); // Assert _ = await act.Should().ThrowAsync(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/UnitTests/Bases/BackendUnitTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/UnitTests/Bases/BackendUnitTest.cs index 7d421f4fa..b34bc4137 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/UnitTests/Bases/BackendUnitTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/UnitTests/Bases/BackendUnitTest.cs @@ -4,11 +4,16 @@ namespace AzureIoTHub.Portal.Tests.Unit.UnitTests.Bases { using System; + using AutoMapper; + using Microsoft.EntityFrameworkCore; + using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; + using Portal.Infrastructure; + using Portal.Server.Mappers; using RichardSzalay.MockHttp; public abstract class BackendUnitTest : IDisposable @@ -23,6 +28,10 @@ public abstract class BackendUnitTest : IDisposable protected virtual AutoFixture.Fixture Fixture { get; } = new(); + protected virtual IMapper Mapper { get; set; } + + protected virtual PortalDbContext DbContext { get; set; } + [SetUp] public virtual void Setup() { @@ -37,6 +46,23 @@ public virtual void Setup() var httpClient = MockHttpClient.ToHttpClient(); httpClient.BaseAddress = new Uri("http://fake.local"); _ = ServiceCollection.AddSingleton(httpClient); + + // Add Mapper Configuration + var mappingConfig = new MapperConfiguration(mc => + { + mc.AddProfile(new DeviceTagProfile()); + }); + Mapper = mappingConfig.CreateMapper(); + _ = ServiceCollection.AddSingleton(Mapper); + + // Add InMemory Database + var contextOptions = new DbContextOptionsBuilder() + .UseInMemoryDatabase("TestContext") + .ConfigureWarnings(b => b.Ignore(InMemoryEventId.TransactionIgnoredWarning)) + .Options; + DbContext = new PortalDbContext(contextOptions); + _ = DbContext.Database.EnsureDeleted(); + _ = DbContext.Database.EnsureCreated(); } [TearDown] diff --git a/src/AzureIoTHub.Portal/Client/Models/DeviceTagModel.cs b/src/AzureIoTHub.Portal/Client/Models/DeviceTagModel.cs index b18f7ba2e..671c6e633 100644 --- a/src/AzureIoTHub.Portal/Client/Models/DeviceTagModel.cs +++ b/src/AzureIoTHub.Portal/Client/Models/DeviceTagModel.cs @@ -5,14 +5,14 @@ namespace AzureIoTHub.Portal.Client.Models { using Portal.Models.v10; - public class DeviceTagModel : DeviceTag + public class DeviceTagModel : DeviceTagDto { public DeviceTagModel() { IsNewTag = true; } - public DeviceTagModel(DeviceTag deviceTag) + public DeviceTagModel(DeviceTagDto deviceTag) { Name = deviceTag.Name; Label = deviceTag.Label; diff --git a/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPage.razor b/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPage.razor index 355ab5c6a..4cec0974c 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPage.razor @@ -227,7 +227,7 @@ public DeviceConfig Configuration { get; set; } = new(); - IEnumerable AvailableTags { get; set; } = Array.Empty(); + IEnumerable AvailableTags { get; set; } = Array.Empty(); IEnumerable AvailableProperties = Array.Empty(); IEnumerable AvailableModels = Array.Empty(); diff --git a/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPage.razor b/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPage.razor index 757f6e4d6..9f4247a8a 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPage.razor @@ -221,7 +221,7 @@ [CascadingParameter] public Error Error {get; set;} - IEnumerable AvailableTags { get; set; } = Array.Empty(); + IEnumerable AvailableTags { get; set; } = Array.Empty(); IEnumerable AvailableProperties = Array.Empty(); public string SelectedTag { get; set; } diff --git a/src/AzureIoTHub.Portal/Client/Pages/Devices/CreateDevicePage.razor b/src/AzureIoTHub.Portal/Client/Pages/Devices/CreateDevicePage.razor index 29bb7ca97..6c1353c59 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/Devices/CreateDevicePage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/Devices/CreateDevicePage.razor @@ -151,7 +151,7 @@ Tags - @foreach (DeviceTag tag in TagList) + @foreach (DeviceTagDto tag in TagList) { await ChangeModel(value)); } } - private IEnumerable TagList { get; set; } = new List(); + private IEnumerable TagList { get; set; } = new List(); private List Properties = new List(); private bool displayValidationErrorMessages = false; @@ -402,7 +402,7 @@ { bool tagValidationError = false; - foreach (DeviceTag tag in TagList) + foreach (DeviceTagDto tag in TagList) { if (tag.Required && string.IsNullOrEmpty(Device.Tags[tag.Name])) { diff --git a/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceDetailPage.razor b/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceDetailPage.razor index 4cb4a77e4..3f98a3b40 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceDetailPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceDetailPage.razor @@ -113,7 +113,7 @@ Tags - @foreach (DeviceTag tag in TagList) + @foreach (DeviceTagDto tag in TagList) { @if (!Device.Tags.ContainsKey(tag.Name)) @@ -244,7 +244,7 @@ private IEnumerable Commands { get; set; } - private IEnumerable TagList { get; set; } = Array.Empty(); + private IEnumerable TagList { get; set; } = Array.Empty(); private IEnumerable Properties = Array.Empty(); @@ -352,7 +352,7 @@ { bool tagValidationError = false; - foreach (DeviceTag tag in TagList) + foreach (DeviceTagDto tag in TagList) { if (tag.Required && string.IsNullOrEmpty(Device.Tags[tag.Name])) { diff --git a/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceListPage.razor b/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceListPage.razor index e5c1953c8..3dc790c3c 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceListPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceListPage.razor @@ -18,7 +18,7 @@ - @foreach (DeviceTag tag in TagList) + @foreach (DeviceTagDto tag in TagList) { if (tag.Searchable) { @@ -175,7 +175,7 @@ private readonly Dictionary pages = new(); - private IEnumerable TagList { get; set; } = new List(); + private IEnumerable TagList { get; set; } = new List(); private int[] pageSizeOptions = new int[] { 2, 5, 10 }; diff --git a/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/CreateEdgeDevicePage.razor b/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/CreateEdgeDevicePage.razor index 4a4ddbbe5..943078c4c 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/CreateEdgeDevicePage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/CreateEdgeDevicePage.razor @@ -116,7 +116,7 @@ Tags - @foreach (DeviceTag tag in TagList) + @foreach (DeviceTagDto tag in TagList) { TagList { get; set; } = new List(); + private IEnumerable TagList { get; set; } = new List(); private bool displayValidationErrorMessages = false; @@ -224,7 +224,7 @@ { bool tagValidationError = false; - foreach (DeviceTag tag in TagList) + foreach (DeviceTagDto tag in TagList) { if (tag.Required && string.IsNullOrEmpty(EdgeDevice.Tags[tag.Name])) { diff --git a/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor b/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor index 33d99cc87..543ea9dcb 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor @@ -164,7 +164,7 @@ Tags - @foreach (DeviceTag tag in TagList) + @foreach (DeviceTagDto tag in TagList) { @if (!edgeDevice.Tags.ContainsKey(tag.Name)) @@ -203,7 +203,7 @@ private IoTEdgeDevice edgeDevice; private IoTEdgeModel edgeModel = new IoTEdgeModel(); - private IEnumerable TagList { get; set; } = Array.Empty(); + private IEnumerable TagList { get; set; } = Array.Empty(); private bool isLoaded = false; private bool isProcessing; @@ -369,7 +369,7 @@ { bool tagValidationError = false; - foreach (DeviceTag tag in TagList) + foreach (DeviceTagDto tag in TagList) { if (tag.Required && string.IsNullOrEmpty(edgeDevice.Tags[tag.Name])) { diff --git a/src/AzureIoTHub.Portal/Client/Services/DeviceLayoutService.cs b/src/AzureIoTHub.Portal/Client/Services/DeviceLayoutService.cs index f98e5f082..506ce94d6 100644 --- a/src/AzureIoTHub.Portal/Client/Services/DeviceLayoutService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/DeviceLayoutService.cs @@ -31,12 +31,12 @@ public IDeviceModel GetSharedDeviceModel() return this.sharedDeviceModel; } - public TDevice ResetSharedDevice(List tags = null) + public TDevice ResetSharedDevice(List tags = null) where TDevice : class, IDeviceDetails, new() { this.sharedDevice = new TDevice(); - foreach (var tag in tags ?? new List()) + foreach (var tag in tags ?? new List()) { _ = this.sharedDevice.Tags.TryAdd(tag.Name, string.Empty); } diff --git a/src/AzureIoTHub.Portal/Client/Services/DeviceTagSettingsClientService.cs b/src/AzureIoTHub.Portal/Client/Services/DeviceTagSettingsClientService.cs index 406156712..572895320 100644 --- a/src/AzureIoTHub.Portal/Client/Services/DeviceTagSettingsClientService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/DeviceTagSettingsClientService.cs @@ -20,7 +20,7 @@ public DeviceTagSettingsClientService(HttpClient http) this.http = http; } - public Task CreateOrUpdateDeviceTag(DeviceTag deviceTag) + public Task CreateOrUpdateDeviceTag(DeviceTagDto deviceTag) { var deviceTagAsJson = JsonConvert.SerializeObject(deviceTag); using var content = new StringContent(deviceTagAsJson, Encoding.UTF8, "application/json"); @@ -32,9 +32,9 @@ public Task DeleteDeviceTagByName(string deviceTagName) return this.http.DeleteAsync($"api/settings/device-tags/{deviceTagName}"); } - public async Task> GetDeviceTags() + public async Task> GetDeviceTags() { - return await this.http.GetFromJsonAsync>("api/settings/device-tags"); + return await this.http.GetFromJsonAsync>("api/settings/device-tags"); } } diff --git a/src/AzureIoTHub.Portal/Client/Services/IDeviceLayoutService.cs b/src/AzureIoTHub.Portal/Client/Services/IDeviceLayoutService.cs index 6b17713cc..f14f47d3a 100644 --- a/src/AzureIoTHub.Portal/Client/Services/IDeviceLayoutService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/IDeviceLayoutService.cs @@ -16,7 +16,7 @@ public interface IDeviceLayoutService IDeviceDetails GetSharedDevice(); IDeviceModel GetSharedDeviceModel(); - TDevice ResetSharedDevice(List tags = null) + TDevice ResetSharedDevice(List tags = null) where TDevice : class, IDeviceDetails, new(); TDeviceModel ResetSharedDeviceModel() where TDeviceModel : class, IDeviceModel, new(); diff --git a/src/AzureIoTHub.Portal/Client/Services/IDeviceTagSettingsClientService.cs b/src/AzureIoTHub.Portal/Client/Services/IDeviceTagSettingsClientService.cs index b7f0195f4..4a876cd19 100644 --- a/src/AzureIoTHub.Portal/Client/Services/IDeviceTagSettingsClientService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/IDeviceTagSettingsClientService.cs @@ -9,9 +9,9 @@ namespace AzureIoTHub.Portal.Client.Services public interface IDeviceTagSettingsClientService { - Task> GetDeviceTags(); + Task> GetDeviceTags(); - Task CreateOrUpdateDeviceTag(DeviceTag deviceTag); + Task CreateOrUpdateDeviceTag(DeviceTagDto deviceTag); Task DeleteDeviceTagByName(string deviceTagName); } diff --git a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceTagSettingsController.cs b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceTagSettingsController.cs index a2030236d..ba3ebb6a0 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceTagSettingsController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceTagSettingsController.cs @@ -49,7 +49,7 @@ public DeviceTagSettingsController( /// List of tags. /// The action result. [HttpPost(Name = "POST Update the Device tags settings")] - public async Task Post(IEnumerable tags) + public async Task Post(IEnumerable tags) { ArgumentNullException.ThrowIfNull(tags, nameof(tags)); @@ -62,7 +62,7 @@ public async Task Post(IEnumerable tags) /// /// The list of tags [HttpGet(Name = "GET Device tags settings")] - public ActionResult> Get() + public ActionResult> Get() { return Ok(this.deviceTagService.GetAllTags()); } @@ -73,7 +73,7 @@ public ActionResult> Get() /// Device Tag /// The action result [HttpPatch(Name = "Create or update a device tag")] - public async Task CreateOrUpdateDeviceTag([FromBody] DeviceTag deviceTag) + public async Task CreateOrUpdateDeviceTag([FromBody] DeviceTagDto deviceTag) { await this.deviceTagService.CreateOrUpdateDeviceTag(deviceTag); return Ok(); diff --git a/src/AzureIoTHub.Portal/Server/Mappers/DeviceTagMapper.cs b/src/AzureIoTHub.Portal/Server/Mappers/DeviceTagMapper.cs index dbae918dd..0ac0f4974 100644 --- a/src/AzureIoTHub.Portal/Server/Mappers/DeviceTagMapper.cs +++ b/src/AzureIoTHub.Portal/Server/Mappers/DeviceTagMapper.cs @@ -14,16 +14,16 @@ public class DeviceTagMapper : IDeviceTagMapper /// /// The entity. /// A device tag setting - public DeviceTag GetDeviceTag(TableEntity entity) + public DeviceTagDto GetDeviceTag(TableEntity entity) { ArgumentNullException.ThrowIfNull(entity, nameof(entity)); - return new DeviceTag + return new DeviceTagDto { Name = entity.RowKey, - Label = entity[nameof(DeviceTag.Label)].ToString(), - Required = bool.Parse(entity[nameof(DeviceTag.Required)].ToString() ?? "false"), - Searchable = bool.Parse(entity[nameof(DeviceTag.Searchable)].ToString() ?? "false") + Label = entity[nameof(DeviceTagDto.Label)].ToString(), + Required = bool.Parse(entity[nameof(DeviceTagDto.Required)].ToString() ?? "false"), + Searchable = bool.Parse(entity[nameof(DeviceTagDto.Searchable)].ToString() ?? "false") }; } @@ -32,14 +32,14 @@ public DeviceTag GetDeviceTag(TableEntity entity) /// /// The entity. /// The device tag object. - public void UpdateTableEntity(TableEntity tagEntity, DeviceTag element) + public void UpdateTableEntity(TableEntity tagEntity, DeviceTagDto element) { ArgumentNullException.ThrowIfNull(tagEntity, nameof(tagEntity)); ArgumentNullException.ThrowIfNull(element, nameof(element)); - tagEntity[nameof(DeviceTag.Label)] = element.Label; - tagEntity[nameof(DeviceTag.Required)] = element.Required; - tagEntity[nameof(DeviceTag.Searchable)] = element.Searchable; + tagEntity[nameof(DeviceTagDto.Label)] = element.Label; + tagEntity[nameof(DeviceTagDto.Required)] = element.Required; + tagEntity[nameof(DeviceTagDto.Searchable)] = element.Searchable; } } } diff --git a/src/AzureIoTHub.Portal/Server/Mappers/DeviceTagProfile.cs b/src/AzureIoTHub.Portal/Server/Mappers/DeviceTagProfile.cs new file mode 100644 index 000000000..244f77814 --- /dev/null +++ b/src/AzureIoTHub.Portal/Server/Mappers/DeviceTagProfile.cs @@ -0,0 +1,19 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Server.Mappers +{ + using AutoMapper; + using AzureIoTHub.Portal.Domain.Entities; + using AzureIoTHub.Portal.Models.v10; + + public class DeviceTagProfile : Profile + { + public DeviceTagProfile() + { + _ = CreateMap() + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.Name)) + .ReverseMap(); + } + } +} diff --git a/src/AzureIoTHub.Portal/Server/Mappers/IDeviceTagMapper.cs b/src/AzureIoTHub.Portal/Server/Mappers/IDeviceTagMapper.cs index ddda248c2..5f30bbf42 100644 --- a/src/AzureIoTHub.Portal/Server/Mappers/IDeviceTagMapper.cs +++ b/src/AzureIoTHub.Portal/Server/Mappers/IDeviceTagMapper.cs @@ -8,7 +8,7 @@ namespace AzureIoTHub.Portal.Server.Mappers public interface IDeviceTagMapper { - public DeviceTag GetDeviceTag(TableEntity entity); - public void UpdateTableEntity(TableEntity tagEntity, DeviceTag element); + public DeviceTagDto GetDeviceTag(TableEntity entity); + public void UpdateTableEntity(TableEntity tagEntity, DeviceTagDto element); } } diff --git a/src/AzureIoTHub.Portal/Server/Services/DeviceTagService.cs b/src/AzureIoTHub.Portal/Server/Services/DeviceTagService.cs index ff14324c8..6f312165f 100644 --- a/src/AzureIoTHub.Portal/Server/Services/DeviceTagService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/DeviceTagService.cs @@ -7,146 +7,103 @@ namespace AzureIoTHub.Portal.Server.Services using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; - using Azure; - using Azure.Data.Tables; - using AzureIoTHub.Portal.Domain; - using AzureIoTHub.Portal.Domain.Exceptions; - using AzureIoTHub.Portal.Models.v10; - using AzureIoTHub.Portal.Server.Mappers; + using AutoMapper; + using Domain; + using Domain.Exceptions; + using Models.v10; + using Domain.Entities; + using Domain.Repositories; + using Microsoft.EntityFrameworkCore; public class DeviceTagService : IDeviceTagService { - /// - /// The table client factory. - /// - private readonly ITableClientFactory tableClientFactory; - - /// - /// The device tag mapper. - /// - private readonly IDeviceTagMapper deviceTagMapper; - - /// - /// The default partition key in AzureDataTable - /// - public const string DefaultPartitionKey = "0"; - - public DeviceTagService(IDeviceTagMapper deviceTagMapper, ITableClientFactory tableClientFactory) + private readonly IMapper mapper; + private readonly IUnitOfWork unitOfWork; + private readonly IDeviceTagRepository deviceTagRepository; + + public DeviceTagService(IMapper mapper, + IUnitOfWork unitOfWork, + IDeviceTagRepository deviceTagRepository) { - this.deviceTagMapper = deviceTagMapper; - this.tableClientFactory = tableClientFactory; + this.mapper = mapper; + this.unitOfWork = unitOfWork; + this.deviceTagRepository = deviceTagRepository; } - public IEnumerable GetAllTags() + public IEnumerable GetAllTags() { - try - { - return this.tableClientFactory - .GetDeviceTagSettings() - .Query() - .Select(this.deviceTagMapper.GetDeviceTag) - .ToList(); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException("Unable to get devices tags", e); - } + return this.deviceTagRepository + .GetAll() + .Select(tag => this.mapper.Map(tag)) + .ToList(); } public IEnumerable GetAllTagsNames() { - try - { - var tagNameList = this.tableClientFactory - .GetDeviceTagSettings() - .Query() - .Select(c => this.deviceTagMapper.GetDeviceTag(c).Name); - - return tagNameList.ToList(); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException($"Unable to query device tags names: {e.Message}", e); - } + return this.deviceTagRepository + .GetAll() + .Select(tag => tag.Name) + .ToList(); } public IEnumerable GetAllSearchableTagsNames() { - try - { - var tagNameList = this.tableClientFactory - .GetDeviceTagSettings() - .Query() - .Where(c => this.deviceTagMapper.GetDeviceTag(c).Searchable) - .Select(c => this.deviceTagMapper.GetDeviceTag(c).Name); - - return tagNameList.ToList(); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException($"Unable to query searchable device tags names: {e.Message}", e); - } + return this.deviceTagRepository + .GetAll() + .Where(tag => tag.Searchable) + .Select(tag => tag.Name) + .ToList(); } - public async Task UpdateTags(IEnumerable tags) + public async Task UpdateTags(IEnumerable tags) { - ArgumentNullException.ThrowIfNull(tags, nameof(tags)); - - Pageable query; - try { - query = this.tableClientFactory - .GetDeviceTagSettings() - .Query(); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException("Unable to get existing devices tags", e); - } + ArgumentNullException.ThrowIfNull(tags); - foreach (var item in query) - { - try + var existingTags = this.deviceTagRepository.GetAll().ToList(); + + existingTags.ForEach(tag => { - _ = await this.tableClientFactory - .GetDeviceTagSettings() - .DeleteEntityAsync(item.PartitionKey, item.RowKey); - } - catch (RequestFailedException e) + this.deviceTagRepository.Delete(tag.Id); + }); + + foreach (var tag in tags) { - throw new InternalServerErrorException($"Unable to delete the device tag {item.RowKey}", e); + await this.deviceTagRepository.InsertAsync(this.mapper.Map(tag)); } - } - foreach (var tag in tags) + await this.unitOfWork.SaveAsync(); + } + catch (DbUpdateException e) { - var entity = new TableEntity() - { - PartitionKey = DefaultPartitionKey, - RowKey = tag.Name - }; - await SaveEntity(entity, tag); + throw new InternalServerErrorException("Unable to save devices tags", e); } } - public async Task CreateOrUpdateDeviceTag(DeviceTag deviceTag) + public async Task CreateOrUpdateDeviceTag(DeviceTagDto deviceTag) { - var entity = new TableEntity + try { - PartitionKey = DefaultPartitionKey, - RowKey = deviceTag.Name - }; + var deviceTagEntity = await this.deviceTagRepository.GetByIdAsync(deviceTag.Name); - this.deviceTagMapper.UpdateTableEntity(entity, deviceTag); + if (deviceTagEntity == null) + { + deviceTagEntity = this.mapper.Map(deviceTag); + await this.deviceTagRepository.InsertAsync(deviceTagEntity); + } + else + { + deviceTagEntity.Label = deviceTag.Label; + deviceTagEntity.Searchable = deviceTag.Searchable; + deviceTagEntity.Required = deviceTag.Required; - try - { - _ = await this.tableClientFactory - .GetDeviceTagSettings() - .UpsertEntityAsync(entity); + this.deviceTagRepository.Update(deviceTagEntity); + } + + await this.unitOfWork.SaveAsync(); } - catch (RequestFailedException e) + catch (DbUpdateException e) { throw new InternalServerErrorException($"Unable to create or update the device tag {deviceTag.Name}", e); } @@ -154,37 +111,15 @@ public async Task CreateOrUpdateDeviceTag(DeviceTag deviceTag) public async Task DeleteDeviceTagByName(string deviceTagName) { - try { - _ = await this.tableClientFactory - .GetDeviceTagSettings() - .DeleteEntityAsync(DefaultPartitionKey, deviceTagName); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException($"Unable to delete the device tag {deviceTagName}", e); - } - } - - /// - /// Saves the entity. - /// - /// The entity - /// The device tag - private async Task SaveEntity(TableEntity entity, DeviceTag tag) - { - this.deviceTagMapper.UpdateTableEntity(entity, tag); + this.deviceTagRepository.Delete(deviceTagName); - try - { - _ = await this.tableClientFactory - .GetDeviceTagSettings() - .AddEntityAsync(entity); + await this.unitOfWork.SaveAsync(); } - catch (RequestFailedException e) + catch (DbUpdateException e) { - throw new InternalServerErrorException($"Unable to save the device tag {tag.Name}", e); + throw new InternalServerErrorException($"Unable to delete the device tag {deviceTagName}", e); } } } diff --git a/src/AzureIoTHub.Portal/Server/Services/IDeviceTagService.cs b/src/AzureIoTHub.Portal/Server/Services/IDeviceTagService.cs index 612d9cf00..e54517814 100644 --- a/src/AzureIoTHub.Portal/Server/Services/IDeviceTagService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/IDeviceTagService.cs @@ -9,15 +9,15 @@ namespace AzureIoTHub.Portal.Server.Services public interface IDeviceTagService { - IEnumerable GetAllTags(); + IEnumerable GetAllTags(); IEnumerable GetAllTagsNames(); IEnumerable GetAllSearchableTagsNames(); - Task UpdateTags(IEnumerable tags); + Task UpdateTags(IEnumerable tags); - Task CreateOrUpdateDeviceTag(DeviceTag deviceTag); + Task CreateOrUpdateDeviceTag(DeviceTagDto deviceTag); Task DeleteDeviceTagByName(string deviceTagName); } diff --git a/src/AzureIoTHub.Portal/Server/Startup.cs b/src/AzureIoTHub.Portal/Server/Startup.cs index f8f4b1f8a..a9d843c2a 100644 --- a/src/AzureIoTHub.Portal/Server/Startup.cs +++ b/src/AzureIoTHub.Portal/Server/Startup.cs @@ -147,6 +147,7 @@ public void ConfigureServices(IServiceCollection services) _ = services.AddTransient(); _ = services.AddScoped(); + _ = services.AddScoped(); _ = services.AddMudServices(); @@ -268,6 +269,7 @@ Specify the authorization token got from your IDP as a header. _ = mc.CreateMap(typeof(AsyncPageable<>), typeof(List<>)); mc.AddProfile(new DevicePropertyProfile()); + mc.AddProfile(new DeviceTagProfile()); }); var mapper = mapperConfig.CreateMapper(); diff --git a/src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceTag.cs b/src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceTagDto.cs similarity index 98% rename from src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceTag.cs rename to src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceTagDto.cs index e1016ec5f..b79cce255 100644 --- a/src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceTag.cs +++ b/src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceTagDto.cs @@ -10,7 +10,7 @@ namespace AzureIoTHub.Portal.Models.v10 /// /// Device tag. /// - public class DeviceTag + public class DeviceTagDto { /// /// The registered name in the device twin. diff --git a/src/AzureIoTHubPortal.Domain/IRepository.cs b/src/AzureIoTHubPortal.Domain/IRepository.cs index 6ebdd1032..fcdc1952e 100644 --- a/src/AzureIoTHubPortal.Domain/IRepository.cs +++ b/src/AzureIoTHubPortal.Domain/IRepository.cs @@ -10,7 +10,7 @@ public interface IRepository where T : class { IEnumerable GetAll(); - Task GetByIdAsync(object id); + Task GetByIdAsync(object id); Task InsertAsync(T obj); diff --git a/src/AzureIoTHubPortal.Domain/Repositories/IDeviceTagRepository.cs b/src/AzureIoTHubPortal.Domain/Repositories/IDeviceTagRepository.cs new file mode 100644 index 000000000..bcc7bca2b --- /dev/null +++ b/src/AzureIoTHubPortal.Domain/Repositories/IDeviceTagRepository.cs @@ -0,0 +1,11 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Domain.Repositories +{ + using Entities; + + public interface IDeviceTagRepository : IRepository + { + } +}