diff --git a/src/AzureIoTHub.Portal.Infrastructure/Repositories/DeviceModelCommandRepository.cs b/src/AzureIoTHub.Portal.Infrastructure/Repositories/DeviceModelCommandRepository.cs new file mode 100644 index 000000000..a27761603 --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Repositories/DeviceModelCommandRepository.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 DeviceModelCommandRepository : GenericRepository, IDeviceModelCommandRepository + { + public DeviceModelCommandRepository(PortalDbContext context) : base(context) + { + } + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/Repositories/DeviceModelRepository.cs b/src/AzureIoTHub.Portal.Infrastructure/Repositories/DeviceModelRepository.cs new file mode 100644 index 000000000..aaa3896f4 --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Repositories/DeviceModelRepository.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 DeviceModelRepository : GenericRepository, IDeviceModelRepository + { + public DeviceModelRepository(PortalDbContext context) : base(context) + { + } + } +} 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 877c36aeb..3fcdb2228 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPageTests.cs @@ -52,7 +52,7 @@ public void DeviceConfigurationDetailPageShouldRenderCorrectly() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) @@ -80,7 +80,7 @@ public void DeviceConfigurationDetailShouldCreateConfiguration() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) @@ -116,7 +116,7 @@ public void DeviceConfigurationDetailShouldProcessProblemDetailsExceptionWhenIss _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) @@ -158,7 +158,7 @@ public void DeviceConfigurationDetailPageShouldProcessProblemDetailsExceptionWhe // Arrange _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) @@ -177,7 +177,7 @@ public void WhenClickToDeleteTagShouldRemoveTheSelectedTag() // Arrange _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) @@ -213,7 +213,7 @@ public void WhenClickToAddTagShouldAddTheSelectedTag() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List + .ReturnsAsync(new List { new () { 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 70864a894..28e562023 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPageTests.cs @@ -73,7 +73,7 @@ public void DeviceConfigurationDetailPageShouldRenderCorrectly() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -140,7 +140,7 @@ public void ClickOnDeleteDeviceConfigurationShouldShowDeleteDialog() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -176,7 +176,7 @@ public void DeviceConfigurationDetailPageShouldRenderCardCorrectly() var configurationId = Guid.NewGuid().ToString(); var modelId = Guid.NewGuid().ToString(); - var model = new DeviceModel + var model = new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -267,7 +267,7 @@ public void DeviceConfigurationDetailPageShouldRenderTags() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -324,7 +324,7 @@ public void WhenClickToDeleteTagShouldRemoveTheSelectedTag() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -385,7 +385,7 @@ public void WhenClickToAddTagShouldAddTheSelectedTag() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -451,7 +451,7 @@ public void DeviceConfigurationDetailPageShouldRenderProperties() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -535,7 +535,7 @@ public void WhenClickToDeletePropertyShouldRemoveTheSelectedProperty() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -617,7 +617,7 @@ public void WhenClickToAddPropertyShouldAddTheSelectedProperty() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -704,7 +704,7 @@ public void WhenClickToSaveShouldSendPutToTheEndpoint() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -797,7 +797,7 @@ public void DeviceConfigurationDetailPageShouldProcessProblemDetailsExceptionWhe _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() @@ -887,7 +887,7 @@ public void ReturnButtonMustNavigateToPreviousPage() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(It.Is(s => modelId.Equals(s, StringComparison.Ordinal)))) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = modelId, Name = Guid.NewGuid().ToString() 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 a620fd807..5be3f94e8 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/CreateDevicePageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/CreateDevicePageTests.cs @@ -62,7 +62,7 @@ public override void Setup() [Test] public async Task ClickOnSaveShouldPostDeviceDetailsAsync() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -81,7 +81,7 @@ public async Task ClickOnSaveShouldPostDeviceDetailsAsync() .Returns(Task.CompletedTask); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockDeviceModel }); @@ -124,7 +124,7 @@ public async Task ClickOnSaveShouldPostDeviceDetailsAsync() [Test] public async Task DeviceShouldNotBeCreatedWhenModelIsNotValid() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -133,7 +133,7 @@ public async Task DeviceShouldNotBeCreatedWhenModelIsNotValid() }; _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockDeviceModel }); @@ -171,7 +171,7 @@ public async Task DeviceShouldNotBeCreatedWhenModelIsNotValid() [Test] public void OnInitializedAsyncShouldProcessProblemDetailsExceptionWhenIssueOccursOnGettingDeviceTags() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -180,7 +180,7 @@ public void OnInitializedAsyncShouldProcessProblemDetailsExceptionWhenIssueOccur }; _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockDeviceModel }); @@ -213,7 +213,7 @@ public void OnInitializedAsyncShouldProcessProblemDetailsExceptionWhenIssueOccur [Test] public async Task SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnCreatingDevice() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -232,7 +232,7 @@ public async Task SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnCreat .ThrowsAsync(new ProblemDetailsException(new ProblemDetailsWithExceptionDetails())); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockDeviceModel }); @@ -271,7 +271,7 @@ public async Task SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnCreat [Test] public async Task ChangeModelShouldProcessProblemDetailsExceptionWhenIssueOccursOnGettingModelProperties() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -287,7 +287,7 @@ public async Task ChangeModelShouldProcessProblemDetailsExceptionWhenIssueOccurs }; _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockDeviceModel }); @@ -322,7 +322,7 @@ public async Task ChangeModelShouldProcessProblemDetailsExceptionWhenIssueOccurs [Test] public async Task ClickOnSaveAndAddNewShouldCreateDeviceAndResetCreateDevicePage() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -341,7 +341,7 @@ public async Task ClickOnSaveAndAddNewShouldCreateDeviceAndResetCreateDevicePage .Returns(Task.CompletedTask); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockDeviceModel }); @@ -398,7 +398,7 @@ public async Task ClickOnSaveAndAddNewShouldCreateDeviceAndResetCreateDevicePage [Test] public async Task ClickOnSaveAndDuplicateShouldCreateDeviceAndDuplicateDeviceDetailsInCreateDevicePage() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -417,7 +417,7 @@ public async Task ClickOnSaveAndDuplicateShouldCreateDeviceAndDuplicateDeviceDet .Returns(Task.CompletedTask); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new List + .ReturnsAsync(new List { mockDeviceModel }); 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 8a349acd6..f9be89c19 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceDetailPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceDetailPageTests.cs @@ -83,7 +83,7 @@ public void ShouldLoadDeviceDetails() .ReturnsAsync(new List()); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(modelId)) - .ReturnsAsync(new DeviceModel()); + .ReturnsAsync(new DeviceModelDto()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) .ReturnsAsync(new List()); @@ -108,10 +108,10 @@ public void ShouldLoadLoRaDeviceDetails() .ReturnsAsync(new LoRaDeviceDetails() { ModelId = modelId }); _ = this.mockLoRaWanDeviceModelsClientService.Setup(service => service.GetDeviceModel(modelId)) - .ReturnsAsync(new LoRaDeviceModel()); + .ReturnsAsync(new LoRaDeviceModelDto()); _ = this.mockLoRaWanDeviceModelsClientService.Setup(service => service.GetDeviceModelCommands(modelId)) - .ReturnsAsync(new List()); + .ReturnsAsync(new List()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) .ReturnsAsync(new List()); @@ -142,7 +142,7 @@ public void ReturnButtonMustNavigateToPreviousPage() .ReturnsAsync(new List()); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(modelId)) - .ReturnsAsync(new DeviceModel()); + .ReturnsAsync(new DeviceModelDto()); _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()) .ReturnsAsync(new List()); @@ -162,7 +162,7 @@ public void ReturnButtonMustNavigateToPreviousPage() [Test] public void ClickOnSaveShouldPutDeviceDetails() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -217,7 +217,7 @@ public void ClickOnSaveShouldPutDeviceDetails() // Act var cut = RenderComponent(ComponentParameter.CreateParameter("DeviceID", mockDeviceDetails.DeviceID)); - cut.WaitForAssertion(() => cut.Find($"#{nameof(DeviceModel.Name)}").InnerHtml.Should().NotBeEmpty()); + cut.WaitForAssertion(() => cut.Find($"#{nameof(DeviceModelDto.Name)}").InnerHtml.Should().NotBeEmpty()); var saveButton = cut.WaitForElement("#saveButton"); saveButton.Click(); @@ -230,7 +230,7 @@ public void ClickOnSaveShouldPutDeviceDetails() [Test] public void SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnUpdatingDevice() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -291,7 +291,7 @@ public void SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnUpdatingDev [Test] public void ClickOnSaveShouldDisplaySnackbarIfValidationError() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -351,7 +351,7 @@ public void ClickOnSaveShouldDisplaySnackbarIfValidationError() [Test] public void ClickOnConnectShouldDisplayDeviceCredentials() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -412,7 +412,7 @@ public void ClickOnConnectShouldDisplayDeviceCredentials() [Test] public void ClickOnDeleteShouldDisplayConfirmationDialogAndReturnIfAborted() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -474,7 +474,7 @@ public void ClickOnDeleteShouldDisplayConfirmationDialogAndReturnIfAborted() [Test] public void ClickOnDeleteShouldDisplayConfirmationDialogAndRedirectIfConfirmed() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -537,7 +537,7 @@ public void ClickOnDeleteShouldDisplayConfirmationDialogAndRedirectIfConfirmed() [Test] public void ClickOnDuplicateShouldDuplicateDeviceDetailAndRedirectToCreateDevicePage() { - var mockDeviceModel = new DeviceModel + var mockDeviceModel = new DeviceModelDto { ModelId = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), @@ -583,7 +583,7 @@ public void ClickOnDuplicateShouldDuplicateDeviceDetailAndRedirectToCreateDevice var popoverProvider = RenderComponent(); var cut = RenderComponent(ComponentParameter.CreateParameter("DeviceID", mockDeviceDetails.DeviceID)); - cut.WaitForAssertion(() => cut.Find($"#{nameof(DeviceModel.Name)}").InnerHtml.Should().NotBeEmpty()); + cut.WaitForAssertion(() => cut.Find($"#{nameof(DeviceModelDto.Name)}").InnerHtml.Should().NotBeEmpty()); var saveButton = cut.WaitForElement("#saveButton"); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceToDuplicateSelectorTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceToDuplicateSelectorTests.cs index 803bede5b..8fa0ca53f 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceToDuplicateSelectorTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/DeviceToDuplicateSelectorTests.cs @@ -95,7 +95,7 @@ public void SelectDeviceShouldDuplicateDeviceAndItsModel() // Arrange var query = Fixture.Create(); - var expectedDeviceModel = new DeviceModel + var expectedDeviceModel = new DeviceModelDto { ModelId = Fixture.Create() }; @@ -150,7 +150,7 @@ public void SelectDeviceShouldProcessProblemDetailsExceptionWhenGettingDeviceDet // Arrange var query = Fixture.Create(); - var expectedDeviceModel = new DeviceModel + var expectedDeviceModel = new DeviceModelDto { ModelId = Fixture.Create() }; @@ -202,7 +202,7 @@ public void SelectLoraDeviceShouldDuplicateLoraDeviceAndItsLoraModel() // Arrange var query = Fixture.Create(); - var expectedDeviceModel = new LoRaDeviceModel + var expectedDeviceModel = new LoRaDeviceModelDto { ModelId = Fixture.Create() }; diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/LoRaWan/CreateLoraDeviceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/LoRaWan/CreateLoraDeviceTests.cs index 9691ab850..1398d1999 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/LoRaWan/CreateLoraDeviceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/LoRaWan/CreateLoraDeviceTests.cs @@ -28,7 +28,7 @@ public override void Setup() [Test] public void WhenUseOTAAShouldDisplayOTAATextboxes() { - var mockLoRaModel = new LoRaDeviceModel + var mockLoRaModel = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), UseOTAA = true @@ -48,7 +48,7 @@ public void WhenUseOTAAShouldDisplayOTAATextboxes() var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(CreateLoraDevice.LoRaDevice), deviceDetails), - ComponentParameter.CreateParameter(nameof(CreateLoraDevice.loraModel), mockLoRaModel), + ComponentParameter.CreateParameter(nameof(CreateLoraDevice.LoraModelDto), mockLoRaModel), ComponentParameter.CreateParameter(nameof(CreateLoraDevice.LoraValidator), validator)); @@ -60,7 +60,7 @@ public void WhenUseOTAAShouldDisplayOTAATextboxes() [Test] public void WhenNotUseOTAAShouldDisplayABPTextboxes() { - var mockLoRaModel = new LoRaDeviceModel + var mockLoRaModel = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), UseOTAA = false @@ -79,7 +79,7 @@ public void WhenNotUseOTAAShouldDisplayABPTextboxes() // Act var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(CreateLoraDevice.LoRaDevice), deviceDetails), - ComponentParameter.CreateParameter(nameof(CreateLoraDevice.loraModel), mockLoRaModel), + ComponentParameter.CreateParameter(nameof(CreateLoraDevice.LoraModelDto), mockLoRaModel), ComponentParameter.CreateParameter(nameof(CreateLoraDevice.LoraValidator), validator)); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/LoRaWan/EditLoraDeviceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/LoRaWan/EditLoraDeviceTests.cs index 1dec07096..ed6bfadaf 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/LoRaWan/EditLoraDeviceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/Devices/LoRaWan/EditLoraDeviceTests.cs @@ -42,7 +42,7 @@ public override void Setup() [Test] public void WhenUseOTAAShouldDisplayOTAATextboxes() { - var mockLoRaModel = new LoRaDeviceModel + var mockLoRaModel = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), UseOTAA = true @@ -61,7 +61,7 @@ public void WhenUseOTAAShouldDisplayOTAATextboxes() // Act var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDevice), deviceDetails), - ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModel), mockLoRaModel), + ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModelDto), mockLoRaModel), ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoraValidator), validator)); @@ -73,7 +73,7 @@ public void WhenUseOTAAShouldDisplayOTAATextboxes() [Test] public void WhenNotUseOTAAShouldDisplayABPTextboxes() { - var mockLoRaModel = new LoRaDeviceModel + var mockLoRaModel = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), UseOTAA = false @@ -92,7 +92,7 @@ public void WhenNotUseOTAAShouldDisplayABPTextboxes() // Act var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDevice), deviceDetails), - ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModel), mockLoRaModel), + ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModelDto), mockLoRaModel), ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoraValidator), validator)); // Assert @@ -106,7 +106,7 @@ public void EditLoRaDevicePageShouldBeRenderedProperly() { // Arrange - var mockLoRaModel = new LoRaDeviceModel + var mockLoRaModel = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), UseOTAA = false @@ -125,7 +125,7 @@ public void EditLoRaDevicePageShouldBeRenderedProperly() // Act var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDevice), deviceDetails), - ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModel), mockLoRaModel), + ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModelDto), mockLoRaModel), ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoraValidator), validator)); // Assert @@ -136,13 +136,13 @@ public void EditLoRaDevicePageShouldBeRenderedProperly() public void WhenDeviceNeverConnectedCommandsShouldBeDisabled() { // Arrange - var model = new LoRaDeviceModel + var model = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), }; - var commands = new List + var commands = new List { - new DeviceModelCommand + new DeviceModelCommandDto { Name = Guid.NewGuid().ToString() } @@ -156,7 +156,7 @@ public void WhenDeviceNeverConnectedCommandsShouldBeDisabled() // Act var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDevice), device), - ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModel), model), + ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModelDto), model), ComponentParameter.CreateParameter(nameof(EditLoraDevice.Commands), commands)); // Assert @@ -169,13 +169,13 @@ public void WhenDeviceNeverConnectedCommandsShouldBeDisabled() public void WhenDeviceAlteadyConnectedCommandsShouldBeEnabled() { // Arrange - var model = new LoRaDeviceModel + var model = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), }; - var commands = new List + var commands = new List { - new DeviceModelCommand + new DeviceModelCommandDto { Name = Guid.NewGuid().ToString() } @@ -190,7 +190,7 @@ public void WhenDeviceAlteadyConnectedCommandsShouldBeEnabled() // Act var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDevice), device), - ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModel), model), + ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModelDto), model), ComponentParameter.CreateParameter(nameof(EditLoraDevice.Commands), commands)); // Assert @@ -202,13 +202,13 @@ public void WhenDeviceAlteadyConnectedCommandsShouldBeEnabled() public void WhenClickToSendCommandShouldExecuteCommandToService() { // Arrange - var model = new LoRaDeviceModel + var model = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), }; - var commands = new List + var commands = new List { - new DeviceModelCommand + new DeviceModelCommandDto { Name = Guid.NewGuid().ToString() } @@ -229,7 +229,7 @@ public void WhenClickToSendCommandShouldExecuteCommandToService() // Act var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDevice), device), - ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModel), model), + ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModelDto), model), ComponentParameter.CreateParameter(nameof(EditLoraDevice.Commands), commands)); // Assert @@ -244,7 +244,7 @@ public void WhenClickToSendCommandShouldExecuteCommandToService() public void EditLoRaDeviceDetailPageShouldBeRenderedProperly() { // Arrange - var mockLoRaModel = new LoRaDeviceModel + var mockLoRaModel = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), UseOTAA = false @@ -265,7 +265,7 @@ public void EditLoRaDeviceDetailPageShouldBeRenderedProperly() // Act var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDevice), deviceDetails), - ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModel), mockLoRaModel), + ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModelDto), mockLoRaModel), ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoraValidator), validator)); @@ -278,7 +278,7 @@ public void EditLoRaDeviceDetailPageShouldBeRenderedProperly() public void EditLoRaDeviceDetailPageWithReportedProperties() { // Arrange - var mockLoRaModel = new LoRaDeviceModel + var mockLoRaModel = new LoRaDeviceModelDto { ModelId = Guid.NewGuid().ToString(), UseOTAA = false @@ -299,7 +299,7 @@ public void EditLoRaDeviceDetailPageWithReportedProperties() // Act var cut = RenderComponent( ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDevice), deviceDetails), - ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModel), mockLoRaModel), + ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoRaDeviceModelDto), mockLoRaModel), ComponentParameter.CreateParameter(nameof(EditLoraDevice.LoraValidator), validator)); // Assert diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/CreateDeviceModelPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/CreateDeviceModelPageTests.cs index 863a46876..e6eca3cbe 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/CreateDeviceModelPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/CreateDeviceModelPageTests.cs @@ -59,7 +59,7 @@ public void ClickOnSaveShouldPostNonLoRaDeviceModelData() _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = false }); _ = this.mockDeviceModelsClientService.Setup(service => - service.CreateDeviceModel(It.Is(model => + service.CreateDeviceModel(It.Is(model => modelName.Equals(model.Name, StringComparison.Ordinal) && description.Equals(model.Description, StringComparison.Ordinal) && !model.SupportLoRaFeatures))) .Returns(Task.CompletedTask); @@ -73,8 +73,8 @@ public void ClickOnSaveShouldPostNonLoRaDeviceModelData() var cut = RenderComponent(); var saveButton = cut.WaitForElement("#SaveButton"); - cut.WaitForElement($"#{nameof(DeviceModel.Name)}").Change(modelName); - cut.WaitForElement($"#{nameof(DeviceModel.Description)}").Change(description); + cut.WaitForElement($"#{nameof(DeviceModelDto.Name)}").Change(modelName); + cut.WaitForElement($"#{nameof(DeviceModelDto.Description)}").Change(description); saveButton.Click(); @@ -93,7 +93,7 @@ public void ClickOnSaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnCrea _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = false }); _ = this.mockDeviceModelsClientService.Setup(service => - service.CreateDeviceModel(It.Is(model => + service.CreateDeviceModel(It.Is(model => modelName.Equals(model.Name, StringComparison.Ordinal) && description.Equals(model.Description, StringComparison.Ordinal) && !model.SupportLoRaFeatures))) .ThrowsAsync(new ProblemDetailsException(new ProblemDetailsWithExceptionDetails())); @@ -101,8 +101,8 @@ public void ClickOnSaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnCrea var cut = RenderComponent(); var saveButton = cut.WaitForElement("#SaveButton"); - cut.WaitForElement($"#{nameof(DeviceModel.Name)}").Change(modelName); - cut.WaitForElement($"#{nameof(DeviceModel.Description)}").Change(description); + cut.WaitForElement($"#{nameof(DeviceModelDto.Name)}").Change(modelName); + cut.WaitForElement($"#{nameof(DeviceModelDto.Description)}").Change(description); saveButton.Click(); @@ -121,7 +121,7 @@ public void ClickOnAddPropertyShouldAddNewProperty() _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = false }); _ = this.mockDeviceModelsClientService.Setup(service => - service.CreateDeviceModel(It.IsAny())) + service.CreateDeviceModel(It.IsAny())) .Returns(Task.CompletedTask); _ = this.mockDeviceModelsClientService.Setup(service => @@ -135,8 +135,8 @@ public void ClickOnAddPropertyShouldAddNewProperty() var saveButton = cut.WaitForElement("#SaveButton"); var addPropertyButton = cut.WaitForElement("#addPropertyButton"); - cut.WaitForElement($"#{nameof(DeviceModel.Name)}").Change(Guid.NewGuid().ToString()); - cut.WaitForElement($"#{nameof(DeviceModel.Description)}").Change(Guid.NewGuid().ToString()); + cut.WaitForElement($"#{nameof(DeviceModelDto.Name)}").Change(Guid.NewGuid().ToString()); + cut.WaitForElement($"#{nameof(DeviceModelDto.Description)}").Change(Guid.NewGuid().ToString()); addPropertyButton.Click(); @@ -164,7 +164,7 @@ public void ClickOnRemovePropertyShouldRemoveTheProperty() _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = false }); _ = this.mockDeviceModelsClientService.Setup(service => - service.CreateDeviceModel(It.IsAny())) + service.CreateDeviceModel(It.IsAny())) .Returns(Task.CompletedTask); _ = this.mockDeviceModelsClientService.Setup(service => @@ -177,8 +177,8 @@ public void ClickOnRemovePropertyShouldRemoveTheProperty() var cut = RenderComponent(); var saveButton = cut.WaitForElement("#SaveButton"); - cut.WaitForElement($"#{nameof(DeviceModel.Name)}").Change(Guid.NewGuid().ToString()); - cut.WaitForElement($"#{nameof(DeviceModel.Description)}").Change(Guid.NewGuid().ToString()); + cut.WaitForElement($"#{nameof(DeviceModelDto.Name)}").Change(Guid.NewGuid().ToString()); + cut.WaitForElement($"#{nameof(DeviceModelDto.Description)}").Change(Guid.NewGuid().ToString()); var addPropertyButton = cut.WaitForElement("#addPropertyButton"); addPropertyButton.Click(); @@ -261,12 +261,12 @@ public void ClickOnSaveShouldPostLoRaDeviceModelData() _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); _ = this.mockLoRaWanDeviceModelsClientService.Setup(service => - service.CreateDeviceModel(It.Is(model => + service.CreateDeviceModel(It.Is(model => modelName.Equals(model.Name, StringComparison.Ordinal) && description.Equals(model.Description, StringComparison.Ordinal) && model.SupportLoRaFeatures))) .Returns(Task.CompletedTask); _ = this.mockLoRaWanDeviceModelsClientService.Setup(service => - service.SetDeviceModelCommands(It.IsAny(), new List())) + service.SetDeviceModelCommands(It.IsAny(), new List())) .Returns(Task.CompletedTask); _ = this.mockSnackbarService.Setup(c => c.Add(It.IsAny(), Severity.Success, It.IsAny>())).Returns((Snackbar)null); @@ -278,8 +278,8 @@ public void ClickOnSaveShouldPostLoRaDeviceModelData() cut.WaitForElement("#SupportLoRaFeatures").Change(true); cut.WaitForState(() => cut.FindAll(".mud-tabs .mud-tab").Count == 2); - cut.WaitForElement($"#{nameof(DeviceModel.Name)}").Change(modelName); - cut.WaitForElement($"#{nameof(DeviceModel.Description)}").Change(description); + cut.WaitForElement($"#{nameof(DeviceModelDto.Name)}").Change(modelName); + cut.WaitForElement($"#{nameof(DeviceModelDto.Description)}").Change(description); saveButton.Click(); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/DeviceModelDetailsPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/DeviceModelDetailsPageTests.cs index f9ee867fc..4c6bad375 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/DeviceModelDetailsPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/DeviceModelDetailsPageTests.cs @@ -68,7 +68,7 @@ public void ClickOnSaveShouldPostDeviceModelData() var expectedModel = SetupMockDeviceModel(properties: expectedProperties); _ = this.mockDeviceModelsClientService.Setup(service => - service.UpdateDeviceModel(It.Is(model => + service.UpdateDeviceModel(It.Is(model => expectedModel.ModelId.Equals(model.ModelId, StringComparison.Ordinal) && expectedModel.Name.Equals(model.Name, StringComparison.Ordinal) && expectedModel.Description.Equals(model.Description, StringComparison.Ordinal) && !model.SupportLoRaFeatures && !model.IsBuiltin))) .Returns(Task.CompletedTask); @@ -106,7 +106,7 @@ public void ClickOnSaveShouldProcessProblemDetailsExceptionIfIssueOccursWhenUpda var expectedModel = SetupMockDeviceModel(properties: expectedProperties); _ = this.mockDeviceModelsClientService.Setup(service => - service.UpdateDeviceModel(It.Is(model => + service.UpdateDeviceModel(It.Is(model => expectedModel.ModelId.Equals(model.ModelId, StringComparison.Ordinal) && expectedModel.Name.Equals(model.Name, StringComparison.Ordinal) && expectedModel.Description.Equals(model.Description, StringComparison.Ordinal) && !model.SupportLoRaFeatures && !model.IsBuiltin))) .ThrowsAsync(new ProblemDetailsException(new ProblemDetailsWithExceptionDetails())); @@ -143,7 +143,7 @@ public void ClickOnSaveShouldDisplaySnackbarIfValidationError() var cut = RenderComponent (ComponentParameter.CreateParameter(nameof(DeviceModelDetailPage.ModelID), this.mockModelId)); - cut.WaitForElement($"#{nameof(DeviceModel.Name)}").Change(""); + cut.WaitForElement($"#{nameof(DeviceModelDto.Name)}").Change(""); var saveButton = cut.WaitForElement("#saveButton"); saveButton.Click(); @@ -161,7 +161,7 @@ public void ClickOnAddPropertyShouldAddNewProperty() _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(this.mockModelId)) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = this.mockModelId, Name = Guid.NewGuid().ToString() @@ -176,7 +176,7 @@ public void ClickOnAddPropertyShouldAddNewProperty() .ReturnsAsync(string.Empty); _ = this.mockDeviceModelsClientService.Setup(service => - service.UpdateDeviceModel(It.IsAny())) + service.UpdateDeviceModel(It.IsAny())) .Returns(Task.CompletedTask); _ = this.mockDeviceModelsClientService.Setup(service => @@ -214,7 +214,7 @@ public void ClickOnRemovePropertyShouldRemoveTheProperty() // Arrange _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModel(this.mockModelId)) - .ReturnsAsync(new DeviceModel + .ReturnsAsync(new DeviceModelDto { ModelId = this.mockModelId, Name = Guid.NewGuid().ToString() @@ -232,7 +232,7 @@ public void ClickOnRemovePropertyShouldRemoveTheProperty() .ReturnsAsync(string.Empty); _ = this.mockDeviceModelsClientService.Setup(service => - service.UpdateDeviceModel(It.IsAny())) + service.UpdateDeviceModel(It.IsAny())) .Returns(Task.CompletedTask); _ = this.mockDeviceModelsClientService.Setup(service => @@ -350,9 +350,9 @@ public void OnInitializedShouldProcessProblemDetailsExceptionWhenIssueOccursOnGe cut.WaitForAssertion(() => MockRepository.VerifyAll()); } - private DeviceModel SetupMockDeviceModel(DeviceProperty[] properties = null) + private DeviceModelDto SetupMockDeviceModel(DeviceProperty[] properties = null) { - var deviceModel = new DeviceModel + var deviceModel = new DeviceModelDto { ModelId = this.mockModelId, Name = this.mockModelId, @@ -377,9 +377,9 @@ private DeviceModel SetupMockDeviceModel(DeviceProperty[] properties = null) return deviceModel; } - private LoRaDeviceModel SetupMockLoRaWANDeviceModel(DeviceModelCommand[] commands = null) + private LoRaDeviceModelDto SetupMockLoRaWANDeviceModel(DeviceModelCommandDto[] commands = null) { - var deviceModel = new LoRaDeviceModel + var deviceModel = new LoRaDeviceModelDto { ModelId = this.mockModelId, Name = this.mockModelId, @@ -394,7 +394,7 @@ private LoRaDeviceModel SetupMockLoRaWANDeviceModel(DeviceModelCommand[] command _ = this.mockLoRaWanDeviceModelsClientService.Setup(service => service.GetDeviceModelCommands(this.mockModelId)) - .ReturnsAsync(commands ?? Array.Empty()); + .ReturnsAsync(commands ?? Array.Empty()); _ = this.mockLoRaWanDeviceModelsClientService.Setup(service => service.GetAvatarUrl(this.mockModelId)) @@ -403,9 +403,9 @@ private LoRaDeviceModel SetupMockLoRaWANDeviceModel(DeviceModelCommand[] command return deviceModel; } - private LoRaDeviceModel SetupMockLoRaWANDeviceModelThrowingException() + private LoRaDeviceModelDto SetupMockLoRaWANDeviceModelThrowingException() { - var deviceModel = new LoRaDeviceModel + var deviceModel = new LoRaDeviceModelDto { ModelId = this.mockModelId, Name = this.mockModelId, diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/DeviceModelListPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/DeviceModelListPageTests.cs index e58bc5d00..797b13cd8 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/DeviceModelListPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/DeviceModelListPageTests.cs @@ -44,7 +44,7 @@ public void WhenLoraFeatureDisableClickToItemShouldRedirectToDeviceDetailsPage() var modelId = Fixture.Create(); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new[] { new DeviceModel { ModelId = modelId, SupportLoRaFeatures = false } }); + .ReturnsAsync(new[] { new DeviceModelDto { ModelId = modelId, SupportLoRaFeatures = false } }); _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); @@ -66,7 +66,7 @@ public void WhenLoraFeatureEnableClickToItemShouldRedirectToLoRaDeviceDetailsPag var modelId = Guid.NewGuid().ToString(); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new[] { new DeviceModel { ModelId = modelId, SupportLoRaFeatures = true } }); + .ReturnsAsync(new[] { new DeviceModelDto { ModelId = modelId, SupportLoRaFeatures = true } }); _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); @@ -87,8 +87,8 @@ public void DeviceModelListPageRendersCorrectly() // Arrange _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) .ReturnsAsync(new[] { - new DeviceModel { ModelId = Guid.NewGuid().ToString() }, - new DeviceModel{ ModelId = Guid.NewGuid().ToString() } + new DeviceModelDto { ModelId = Guid.NewGuid().ToString() }, + new DeviceModelDto{ ModelId = Guid.NewGuid().ToString() } }); _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); @@ -114,7 +114,7 @@ public void WhenAddNewDeviceModelClickShouldNavigateToNewDeviceModelPage() var deviceId = Guid.NewGuid().ToString(); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new[] { new DeviceModel { ModelId = deviceId, SupportLoRaFeatures = true } }); + .ReturnsAsync(new[] { new DeviceModelDto { ModelId = deviceId, SupportLoRaFeatures = true } }); _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); @@ -151,7 +151,7 @@ public async Task WhenRefreshClickShouldReloadFromApi() var deviceId = Guid.NewGuid().ToString(); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new[] { new DeviceModel { ModelId = deviceId, SupportLoRaFeatures = true } }); + .ReturnsAsync(new[] { new DeviceModelDto { ModelId = deviceId, SupportLoRaFeatures = true } }); _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); @@ -177,7 +177,7 @@ public void ClickOnDeleteShouldDisplayConfirmationDialogAndReturnIfAborted() var deviceId = Guid.NewGuid().ToString(); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new[] { new DeviceModel { ModelId = deviceId, SupportLoRaFeatures = true } }); + .ReturnsAsync(new[] { new DeviceModelDto { ModelId = deviceId, SupportLoRaFeatures = true } }); _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); @@ -202,7 +202,7 @@ public void ClickOnDeleteShouldDisplayConfirmationDialogAndReloadDeviceModelIfCo var deviceId = Guid.NewGuid().ToString(); _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels()) - .ReturnsAsync(new[] { new DeviceModel { ModelId = deviceId, SupportLoRaFeatures = true } }); + .ReturnsAsync(new[] { new DeviceModelDto { ModelId = deviceId, SupportLoRaFeatures = true } }); _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true }); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/LoRaWAN/CreateLoRaDeviceModelPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/LoRaWAN/CreateLoRaDeviceModelPageTests.cs index c89ceb19e..8262ad47f 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/LoRaWAN/CreateLoRaDeviceModelPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/LoRaWAN/CreateLoRaDeviceModelPageTests.cs @@ -23,8 +23,8 @@ public override void Setup() public void CreateLoRaDeviceModelPageShouldBeRenderedProperly() { // Arrange - var model = new LoRaDeviceModel(); - var commands = new List(); + var model = new LoRaDeviceModelDto(); + var commands = new List(); var cut = RenderComponent( ComponentParameter.CreateParameter("LoRaDeviceModel", model), @@ -38,8 +38,8 @@ public void CreateLoRaDeviceModelPageShouldBeRenderedProperly() public void ClickOnAddShouldAddRow() { // Arrange - var model = new LoRaDeviceModel(); - var commands = new List(); + var model = new LoRaDeviceModelDto(); + var commands = new List(); var cut = RenderComponent( ComponentParameter.CreateParameter("LoRaDeviceModel", model), @@ -56,8 +56,8 @@ public void ClickOnAddShouldAddRow() public void ClickOnRemoveShouldDeleteRow() { // Arrange - var model = new LoRaDeviceModel(); - var commands = new List(); + var model = new LoRaDeviceModelDto(); + var commands = new List(); var cut = RenderComponent( ComponentParameter.CreateParameter("LoRaDeviceModel", model), diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/LoRaWAN/EditLoraDeviceModelPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/LoRaWAN/EditLoraDeviceModelPageTests.cs index 595539298..7a2d123b0 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/LoRaWAN/EditLoraDeviceModelPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/DevicesModels/LoRaWAN/EditLoraDeviceModelPageTests.cs @@ -22,8 +22,8 @@ public override void Setup() public void CreateLoRaDeviceModelPageShouldBeRenderedProperly() { // Arrange - var model = new LoRaDeviceModel(); - var commands = new List(); + var model = new LoRaDeviceModelDto(); + var commands = new List(); var cut = RenderComponent( ComponentParameter.CreateParameter("LoRaDeviceModel", model), @@ -37,8 +37,8 @@ public void CreateLoRaDeviceModelPageShouldBeRenderedProperly() public void ClickOnAddShouldAddRow() { // Arrange - var model = new LoRaDeviceModel(); - var commands = new List(); + var model = new LoRaDeviceModelDto(); + var commands = new List(); var cut = RenderComponent( ComponentParameter.CreateParameter("LoRaDeviceModel", model), @@ -55,8 +55,8 @@ public void ClickOnAddShouldAddRow() public void ClickOnRemoveShouldDeleteRow() { // Arrange - var model = new LoRaDeviceModel(); - var commands = new List(); + var model = new LoRaDeviceModelDto(); + var commands = new List(); var cut = RenderComponent( ComponentParameter.CreateParameter("LoRaDeviceModel", model), diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceLayoutServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceLayoutServiceTests.cs index ffa873fa8..8863908e2 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceLayoutServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceLayoutServiceTests.cs @@ -91,7 +91,7 @@ public void DuplicateSharedDeviceShouldReturnDuplicatedLoraWanDevice() public void DuplicateSharedDeviceModelShouldReturnDuplicatedDeviceModel() { // Arrange - var deviceModel = Fixture.Create(); + var deviceModel = Fixture.Create(); // Act var result = this.deviceLayoutService.DuplicateSharedDeviceModel(deviceModel); @@ -137,10 +137,10 @@ public void ResetSharedDeviceShouldReturnNewDeviceWithExpectedTags() public void ResetSharedDeviceModelShouldReturnNewDeviceModel() { // Arrange - var expectedDeviceModel = new DeviceModel(); + var expectedDeviceModel = new DeviceModelDto(); // Act - var result = this.deviceLayoutService.ResetSharedDeviceModel(); + var result = this.deviceLayoutService.ResetSharedDeviceModel(); // Assert _ = result.Should().BeEquivalentTo(expectedDeviceModel); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceModelsClientServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceModelsClientServiceTests.cs index 49e9fd5f7..492eec089 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceModelsClientServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/DeviceModelsClientServiceTests.cs @@ -36,7 +36,7 @@ public override void Setup() public async Task GetDeviceModelsShouldReturnDeviceModels() { // Arrange - var expectedDeviceModels = Fixture.Build().CreateMany(3).ToList(); + var expectedDeviceModels = Fixture.Build().CreateMany(3).ToList(); _ = MockHttpClient.When(HttpMethod.Get, "/api/models") .RespondJson(expectedDeviceModels); @@ -54,7 +54,7 @@ public async Task GetDeviceModelsShouldReturnDeviceModels() public async Task GetDeviceModelShouldReturnDeviceModel() { // Arrange - var expectedDeviceModel = Fixture.Create(); + var expectedDeviceModel = Fixture.Create(); _ = MockHttpClient.When(HttpMethod.Get, $"/api/models/{expectedDeviceModel.ModelId}") .RespondJson(expectedDeviceModel); @@ -72,13 +72,13 @@ public async Task GetDeviceModelShouldReturnDeviceModel() public async Task CreateDeviceModelShouldCreateDeviceModel() { // Arrange - var expectedDeviceModel = Fixture.Create(); + var expectedDeviceModel = Fixture.Create(); _ = MockHttpClient.When(HttpMethod.Post, "/api/models") .With(m => { - _ = m.Content.Should().BeAssignableTo>(); - var body = m.Content as ObjectContent; + _ = m.Content.Should().BeAssignableTo>(); + var body = m.Content as ObjectContent; _ = body.Value.Should().BeEquivalentTo(expectedDeviceModel); return true; }) @@ -96,13 +96,13 @@ public async Task CreateDeviceModelShouldCreateDeviceModel() public async Task UpdateDeviceModelShouldUpdateDeviceModel() { // Arrange - var expectedDeviceModel = Fixture.Create(); + var expectedDeviceModel = Fixture.Create(); _ = MockHttpClient.When(HttpMethod.Put, $"/api/models/{expectedDeviceModel.ModelId}") .With(m => { - _ = m.Content.Should().BeAssignableTo>(); - var body = m.Content as ObjectContent; + _ = m.Content.Should().BeAssignableTo>(); + var body = m.Content as ObjectContent; _ = body.Value.Should().BeEquivalentTo(expectedDeviceModel); return true; }) @@ -120,7 +120,7 @@ public async Task UpdateDeviceModelShouldUpdateDeviceModel() public async Task DeleteDeviceModelShouldDeleteDeviceModel() { // Arrange - var expectedDeviceModel = Fixture.Create(); + var expectedDeviceModel = Fixture.Create(); _ = MockHttpClient.When(HttpMethod.Delete, $"/api/models/{expectedDeviceModel.ModelId}") .Respond(HttpStatusCode.NoContent); @@ -137,7 +137,7 @@ public async Task DeleteDeviceModelShouldDeleteDeviceModel() public async Task GetDeviceModelModelPropertiesShouldReturnDeviceModelModelProperties() { // Arrange - var deviceModel = Fixture.Create(); + var deviceModel = Fixture.Create(); var expectedDeviceModelProperties = Fixture.Build().CreateMany(3).ToList(); _ = MockHttpClient.When(HttpMethod.Get, $"/api/models/{deviceModel.ModelId}/properties") @@ -156,7 +156,7 @@ public async Task GetDeviceModelModelPropertiesShouldReturnDeviceModelModelPrope public async Task SetDeviceModelModelPropertiesShouldSetDeviceModelModelProperties() { // Arrange - var deviceModel = Fixture.Create(); + var deviceModel = Fixture.Create(); var expectedDeviceModelProperties = Fixture.Build().CreateMany(3).ToList(); _ = MockHttpClient.When(HttpMethod.Get, $"/api/models/{deviceModel.ModelId}/properties") @@ -181,7 +181,7 @@ public async Task SetDeviceModelModelPropertiesShouldSetDeviceModelModelProperti public async Task GetAvatarUrlShouldReturnAvatarUrl() { // Arrange - var deviceModel = Fixture.Create(); + var deviceModel = Fixture.Create(); _ = MockHttpClient.When(HttpMethod.Get, $"/api/models/{deviceModel.ModelId}/avatar") .RespondJson(deviceModel.ImageUrl.ToString()); @@ -199,7 +199,7 @@ public async Task GetAvatarUrlShouldReturnAvatarUrl() public async Task ChangeAvatarPropertiesShouldChangeAvatar() { // Arrange - var deviceModel = Fixture.Create(); + var deviceModel = Fixture.Create(); using var content = new MultipartFormDataContent(); _ = MockHttpClient.When(HttpMethod.Post, $"/api/models/{deviceModel.ModelId}/avatar") diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/EdgeModelClientServiceTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/EdgeModelClientServiceTest.cs index f0af4a950..80c42e484 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/EdgeModelClientServiceTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/EdgeModelClientServiceTest.cs @@ -130,7 +130,7 @@ public async Task UpdateIoTEdgeModelShouldUpdateEdgeModel() public async Task DeleteIoTEdgeModelShouldDeleteEdgeModel() { // Arrange - var expectedEdgeModel = Fixture.Create(); + var expectedEdgeModel = Fixture.Create(); _ = MockHttpClient.When(HttpMethod.Delete, $"api/edge/models/{expectedEdgeModel.ModelId}") .Respond(HttpStatusCode.NoContent); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/LoRaWanDeviceModelsClientServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/LoRaWanDeviceModelsClientServiceTests.cs index 90a095c24..f2ffe69c8 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/LoRaWanDeviceModelsClientServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Services/LoRaWanDeviceModelsClientServiceTests.cs @@ -39,7 +39,7 @@ public async Task GetDeviceModelShouldReturnDeviceModel() // Arrange var deviceModelId = Fixture.Create(); - var expectedDeviceModel = new LoRaDeviceModel + var expectedDeviceModel = new LoRaDeviceModelDto { ModelId = deviceModelId }; @@ -60,7 +60,7 @@ public async Task GetDeviceModelShouldReturnDeviceModel() public async Task CreateDeviceModelShouldCreateDeviceModel() { // Arrange - var expectedDeviceModel = new LoRaDeviceModel + var expectedDeviceModel = new LoRaDeviceModelDto { ModelId = Fixture.Create() }; @@ -68,8 +68,8 @@ public async Task CreateDeviceModelShouldCreateDeviceModel() _ = MockHttpClient.When(HttpMethod.Post, "/api/lorawan/models") .With(m => { - _ = m.Content.Should().BeAssignableTo>(); - var body = m.Content as ObjectContent; + _ = m.Content.Should().BeAssignableTo>(); + var body = m.Content as ObjectContent; _ = body.Value.Should().BeEquivalentTo(expectedDeviceModel); return true; }) @@ -87,7 +87,7 @@ public async Task CreateDeviceModelShouldCreateDeviceModel() public async Task UpdateDeviceModelShouldUpdateDeviceModel() { // Arrange - var expectedDeviceModel = new LoRaDeviceModel + var expectedDeviceModel = new LoRaDeviceModelDto { ModelId = Fixture.Create() }; @@ -95,8 +95,8 @@ public async Task UpdateDeviceModelShouldUpdateDeviceModel() _ = MockHttpClient.When(HttpMethod.Put, $"/api/lorawan/models/{expectedDeviceModel.ModelId}") .With(m => { - _ = m.Content.Should().BeAssignableTo>(); - var body = m.Content as ObjectContent; + _ = m.Content.Should().BeAssignableTo>(); + var body = m.Content as ObjectContent; _ = body.Value.Should().BeEquivalentTo(expectedDeviceModel); return true; }) @@ -114,18 +114,18 @@ public async Task UpdateDeviceModelShouldUpdateDeviceModel() public async Task SetDeviceModelCommandsShouldSetDeviceModelCommands() { // Arrange - var deviceModelId = new LoRaDeviceModel + var deviceModelId = new LoRaDeviceModelDto { ModelId = Fixture.Create() }; - var expectedCommands = Fixture.Build().CreateMany(3).ToList(); + var expectedCommands = Fixture.Build().CreateMany(3).ToList(); _ = MockHttpClient.When(HttpMethod.Get, $"/api/lorawan/models/{deviceModelId.ModelId}/properties") .With(m => { - _ = m.Content.Should().BeAssignableTo>>(); - var body = m.Content as ObjectContent>; + _ = m.Content.Should().BeAssignableTo>>(); + var body = m.Content as ObjectContent>; _ = body.Value.Should().BeEquivalentTo(expectedCommands); return true; }) @@ -145,7 +145,7 @@ public async Task GetDeviceModelCommandsShouldReturnCommands() // Arrange var deviceModelId = Fixture.Create(); - var expectedCommands = Fixture.CreateMany().ToList(); + var expectedCommands = Fixture.CreateMany().ToList(); _ = MockHttpClient.When(HttpMethod.Get, $"/api/lorawan/models/{deviceModelId}/commands") .RespondJson(expectedCommands); @@ -163,7 +163,7 @@ public async Task GetDeviceModelCommandsShouldReturnCommands() public async Task GetAvatarUrlShouldReturnAvatarUrl() { // Arrange - var deviceModel = new LoRaDeviceModel + var deviceModel = new LoRaDeviceModelDto { ModelId = Fixture.Create(), ImageUrl = Fixture.Create() @@ -185,7 +185,7 @@ public async Task GetAvatarUrlShouldReturnAvatarUrl() public async Task ChangeAvatarPropertiesShouldChangeAvatar() { // Arrange - var deviceModel = new LoRaDeviceModel + var deviceModel = new LoRaDeviceModelDto { ModelId = Fixture.Create() }; diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/DeviceModelValidatorTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/DeviceModelValidatorTests.cs index 0c5a7287e..b4c4c79f7 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/DeviceModelValidatorTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/DeviceModelValidatorTests.cs @@ -16,7 +16,7 @@ public void ValidateValidModel() // Arrange var standardModelValidator = new DeviceModelValidator(); - var deviceModel = new DeviceModel() + var deviceModel = new DeviceModelDto() { Name = Guid.NewGuid().ToString(), }; @@ -34,7 +34,7 @@ public void ValidateMissingNameShouldReturnError() { // Arrange var standardModelValidator = new DeviceModelValidator(); - var deviceModel = new DeviceModel(); + var deviceModel = new DeviceModelDto(); // Act var standardModelValidation = standardModelValidator.Validate(deviceModel); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/LoRaDeviceModelCommandValidatorTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/LoRaDeviceModelCommandValidatorTests.cs index 74094cca0..12906c498 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/LoRaDeviceModelCommandValidatorTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/LoRaDeviceModelCommandValidatorTests.cs @@ -17,7 +17,7 @@ public void ValidateValidCommand() // Arrange var cmdValidator = new LoRaDeviceModelCommandValidator(); - var commmand = new DeviceModelCommand() + var commmand = new DeviceModelCommandDto() { Name = Guid.NewGuid().ToString(), Frame = "ABCDEF1234567890", @@ -39,7 +39,7 @@ public void ValidateMissingNameShouldReturnError() { // Arrange var cmdValidator = new LoRaDeviceModelCommandValidator(); - var commmand = new DeviceModelCommand() + var commmand = new DeviceModelCommandDto() { Frame = "ABCDEF1234567890", Port = 1 @@ -59,7 +59,7 @@ public void ValidateMissingFrameShouldReturnError() { // Arrange var cmdValidator = new LoRaDeviceModelCommandValidator(); - var commmand = new DeviceModelCommand() + var commmand = new DeviceModelCommandDto() { Name = Guid.NewGuid().ToString(), Port = 1 @@ -80,7 +80,7 @@ public void ValidateWrongLengthFrameShouldReturnError() var frameValue = new string('A', 256); // Arrange var cmdValidator = new LoRaDeviceModelCommandValidator(); - var commmand = new DeviceModelCommand() + var commmand = new DeviceModelCommandDto() { Name = Guid.NewGuid().ToString(), Frame = frameValue, @@ -102,7 +102,7 @@ public void ValidateInvalidFrameShouldReturnError() var frameValue = "AZERTY"; // Arrange var cmdValidator = new LoRaDeviceModelCommandValidator(); - var commmand = new DeviceModelCommand() + var commmand = new DeviceModelCommandDto() { Name = Guid.NewGuid().ToString(), Frame = frameValue, @@ -123,7 +123,7 @@ public void ValidateInvalidPortShouldReturnError() { // Arrange var cmdValidator = new LoRaDeviceModelCommandValidator(); - var commmand = new DeviceModelCommand() + var commmand = new DeviceModelCommandDto() { Name = Guid.NewGuid().ToString(), Frame = "ABCDEF1234567890", diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/LoRaDeviceModelValidatorTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/LoRaDeviceModelValidatorTests.cs index b4bebd6c2..f6a0a5dc1 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/LoRaDeviceModelValidatorTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Validators/LoRaDeviceModelValidatorTests.cs @@ -15,7 +15,7 @@ public void ValidateValidOTAAModel() // Arrange var loraModelValidator = new LoRaDeviceModelValidator(); - var loraModel = new LoRaDeviceModel() + var loraModel = new LoRaDeviceModelDto() { UseOTAA = true, //AppEUI = Guid.NewGuid().ToString(), diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Repositories/DeviceModelCommandRepositoryTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Repositories/DeviceModelCommandRepositoryTests.cs new file mode 100644 index 000000000..40d9300af --- /dev/null +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Repositories/DeviceModelCommandRepositoryTests.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 DeviceModelCommandRepositoryTests : BackendUnitTest + { + private DeviceModelCommandRepository deviceModelCommandRepository; + + public override void Setup() + { + base.Setup(); + + this.deviceModelCommandRepository = new DeviceModelCommandRepository(DbContext); + } + + [Test] + public async Task GetAllShouldReturnExpectedDeviceModelCommands() + { + // Arrange + var expectedDeviceModelCommands = Fixture.CreateMany(5).ToList(); + + await DbContext.AddRangeAsync(expectedDeviceModelCommands); + + _ = await DbContext.SaveChangesAsync(); + + // Act + var result = this.deviceModelCommandRepository.GetAll().ToList(); + + // Assert + _ = result.Should().BeEquivalentTo(expectedDeviceModelCommands); + } + } +} diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Repositories/DeviceModelRepositoryTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Repositories/DeviceModelRepositoryTests.cs new file mode 100644 index 000000000..9397d1eb9 --- /dev/null +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Repositories/DeviceModelRepositoryTests.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 DeviceModelRepositoryTests : BackendUnitTest + { + private DeviceModelRepository deviceModelRepository; + + public override void Setup() + { + base.Setup(); + + this.deviceModelRepository = new DeviceModelRepository(DbContext); + } + + [Test] + public async Task GetAllShouldReturnExpectedDeviceModelCommands() + { + // Arrange + var expectedDeviceModels = Fixture.CreateMany(5).ToList(); + + await DbContext.AddRangeAsync(expectedDeviceModels); + + _ = await DbContext.SaveChangesAsync(); + + // Act + var result = this.deviceModelRepository.GetAll().ToList(); + + // Assert + _ = result.Should().BeEquivalentTo(expectedDeviceModels); + } + } +} diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/DeviceModelsControllerTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/DeviceModelsControllerTests.cs index b25bc8bc5..5784bc5f3 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/DeviceModelsControllerTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/DeviceModelsControllerTests.cs @@ -3,952 +3,172 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Controllers.v1._0 { - using System; - using System.Collections.Generic; - using System.IO; using System.Linq; - using System.Linq.Expressions; - using System.Threading; using System.Threading.Tasks; - using Azure; - using Azure.Data.Tables; - using AzureIoTHub.Portal.Domain; - using AzureIoTHub.Portal.Domain.Exceptions; + using AutoFixture; using AzureIoTHub.Portal.Server.Controllers.V10; - using AzureIoTHub.Portal.Server.Controllers.V10.LoRaWAN; - using AzureIoTHub.Portal.Server.Managers; - using AzureIoTHub.Portal.Server.Mappers; using AzureIoTHub.Portal.Server.Services; using FluentAssertions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; - using Microsoft.Azure.Devices.Provisioning.Service; - using Microsoft.Azure.Devices.Shared; - using Microsoft.Extensions.Logging; + using Microsoft.Extensions.DependencyInjection; using Models.v10; using Moq; using NUnit.Framework; + using UnitTests.Bases; [TestFixture] - public class DeviceModelsControllerTests + public class DeviceModelsControllerTests : BackendUnitTest { - private MockRepository mockRepository; - - private Mock> mockLogger; - private Mock mockDeviceModelImageManager; - private Mock mockDeviceModelCommandMapper; - private Mock> mockDeviceModelMapper; - private Mock mockDeviceService; - private Mock mockTableClientFactory; - private Mock mockDeviceProvisioningServiceManager; - private Mock mockDeviceTemplatesTableClient; - private Mock mockCommandsTableClient; - private Mock mockConfigService; - - [SetUp] - public void SetUp() - { - this.mockRepository = new MockRepository(MockBehavior.Strict); - - this.mockLogger = this.mockRepository.Create>(); - this.mockDeviceModelImageManager = this.mockRepository.Create(); - this.mockDeviceModelCommandMapper = this.mockRepository.Create(); - this.mockDeviceProvisioningServiceManager = this.mockRepository.Create(); - this.mockDeviceModelMapper = this.mockRepository.Create>(); - this.mockDeviceService = this.mockRepository.Create(); - this.mockTableClientFactory = this.mockRepository.Create(); - this.mockDeviceTemplatesTableClient = this.mockRepository.Create(); - this.mockCommandsTableClient = this.mockRepository.Create(); - this.mockConfigService = this.mockRepository.Create(); - } + private Mock> mockDeviceModelService; - private DeviceModelsController CreateDeviceModelsController() - { - return new DeviceModelsController( - this.mockLogger.Object, - this.mockDeviceModelImageManager.Object, - this.mockDeviceModelMapper.Object, - this.mockDeviceService.Object, - this.mockTableClientFactory.Object, - this.mockDeviceProvisioningServiceManager.Object, - this.mockConfigService.Object); - } + private DeviceModelsController deviceModelsController; - [Test] - public void GetListShouldReturnAList() + public override void Setup() { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - 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(Guid.NewGuid().ToString(), Guid.NewGuid().ToString())); + base.Setup(); - _ = mockTableResponse.Setup(x => x.GetEnumerator()) - .Returns(mockEnumerator.Object); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) - .Returns(mockTableResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceModelMapper.Setup(c => c.CreateDeviceModelListItem(It.IsAny())) - .Returns((TableEntity _) => new DeviceModel()); - - // Act - var response = deviceModelsController.GetItems(); - - // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - var okResponse = response.Result as OkObjectResult; + this.mockDeviceModelService = MockRepository.Create>(); - Assert.AreEqual(200, okResponse.StatusCode); + _ = ServiceCollection.AddSingleton(this.mockDeviceModelService.Object); - Assert.IsNotNull(okResponse.Value); - var result = okResponse.Value as IEnumerable; - Assert.AreEqual(10, result?.Count()); + Services = ServiceCollection.BuildServiceProvider(); - this.mockRepository.VerifyAll(); + this.deviceModelsController = new DeviceModelsController(Services.GetRequiredService>()); } [Test] - public void WhenQueryFailedGetListShouldThrowAnExceptionInternalServerErrorException() + public async Task GetListShouldReturnAList() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); + var expectedDeviceModels = Fixture.CreateMany(3).ToList(); - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) - .Throws(new RequestFailedException("request failed.")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); + _ = this.mockDeviceModelService.Setup(service => service.GetDeviceModels()) + .ReturnsAsync(expectedDeviceModels); // Act - var act = () => deviceModelsController.GetItems(); + var response = await this.deviceModelsController.GetItems(); // Assert - _ = act.Should().Throw(); - - this.mockRepository.VerifyAll(); + _ = ((OkObjectResult)response.Result)?.Value.Should().BeEquivalentTo(expectedDeviceModels); + MockRepository.VerifyAll(); } [Test] public async Task GetItemShouldReturnAValue() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var mockResponse = this.mockRepository.Create>(); - _ = mockResponse.Setup(c => c.Value).Returns(new TableEntity(Guid.NewGuid().ToString(), Guid.NewGuid().ToString())); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == "test"), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceModelMapper.Setup(c => c.CreateDeviceModel(It.IsAny())) - .Returns((TableEntity _) => new DeviceModel()); - - // Act - var result = await deviceModelsController.GetItem("test"); - - // Assert - Assert.IsNotNull(result); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenModelNotExistsGetItemShouldReturn404() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); + var expectedDeviceModel = Fixture.Create(); - SetupNotFoundEntity(); + _ = this.mockDeviceModelService.Setup(service => service.GetDeviceModel(expectedDeviceModel.ModelId)) + .ReturnsAsync(expectedDeviceModel); // Act - var response = await deviceModelsController.GetItem(Guid.NewGuid().ToString()); + var response = await this.deviceModelsController.GetItem(expectedDeviceModel.ModelId); // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - - this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); - this.mockDeviceModelImageManager.VerifyAll(); - } - - [Test] - public async Task WhenGetEntityFailedOnGetItemShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupErrorEntity(); - - // Act - var act = () => deviceModelsController.GetItem(Guid.NewGuid().ToString()); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + _ = response.Value.Should().BeEquivalentTo(expectedDeviceModel); + MockRepository.VerifyAll(); } [Test] public async Task GetAvatarShouldReturnTheComputedModelAvatarUri() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var entity = SetupMockEntity(); - - var expectedUrl = new Uri($"http://fake.local/{entity.RowKey}"); + var deviceModel = Fixture.Create(); + var expectedAvatar = Fixture.Create(); - _ = this.mockDeviceModelImageManager.Setup(c => c.ComputeImageUri(It.Is(x => x == entity.RowKey))) - .Returns(expectedUrl); + _ = this.mockDeviceModelService.Setup(service => service.GetDeviceModelAvatar(deviceModel.ModelId)) + .ReturnsAsync(expectedAvatar); // Act - var response = await deviceModelsController.GetAvatar(entity.RowKey); + var response = await this.deviceModelsController.GetAvatar(deviceModel.ModelId); // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - var okResponse = response.Result as OkObjectResult; - - Assert.AreEqual(200, okResponse.StatusCode); - - Assert.IsNotNull(okResponse.Value); - Assert.AreEqual(expectedUrl, okResponse.Value.ToString()); - - this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); - this.mockDeviceModelImageManager.VerifyAll(); - } - - [Test] - public async Task WhenModelNotExistsGetAvatarShouldReturn404() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupNotFoundEntity(); - - // Act - var response = await deviceModelsController.GetAvatar(Guid.NewGuid().ToString()); - - // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenGetEntityThrowAnErrorGetAvatarShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupErrorEntity(); - - // Act - var act = async () => await deviceModelsController.GetAvatar(Guid.NewGuid().ToString()); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + _ = ((OkObjectResult)response.Result)?.Value.Should().BeEquivalentTo(expectedAvatar); + MockRepository.VerifyAll(); } [Test] public async Task ChangeAvatarShouldChangeModelImageStream() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var entity = SetupMockEntity(); - - var mockFile = this.mockRepository.Create(); - var expectedUrl = $"http://fake.local/{entity.RowKey}"; + var deviceModel = Fixture.Create(); + var expectedAvatar = Fixture.Create(); - using var imageStream = new MemoryStream(); - - _ = mockFile.Setup(c => c.OpenReadStream()) - .Returns(imageStream); - - _ = this.mockDeviceModelImageManager.Setup(c => c.ChangeDeviceModelImageAsync( - It.Is(x => x == entity.RowKey), - It.Is(x => x == imageStream))) - .ReturnsAsync(expectedUrl); + _ = this.mockDeviceModelService.Setup(service => service.UpdateDeviceModelAvatar(deviceModel.ModelId, It.IsAny())) + .ReturnsAsync(expectedAvatar); // Act - var response = await deviceModelsController.ChangeAvatar(entity.RowKey, mockFile.Object); + var response = await this.deviceModelsController.ChangeAvatar(deviceModel.ModelId, MockRepository.Create().Object); // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - var okResponse = response.Result as OkObjectResult; - - Assert.AreEqual(200, okResponse.StatusCode); - - Assert.IsNotNull(okResponse.Value); - Assert.AreEqual(expectedUrl, okResponse.Value.ToString()); - - this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); - this.mockDeviceModelImageManager.VerifyAll(); - } - - [Test] - public async Task WhenModelNotExistsChangeAvatarShouldReturn404() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupNotFoundEntity(); - - var mockFile = this.mockRepository.Create(); - - // Act - var response = await deviceModelsController.ChangeAvatar(Guid.NewGuid().ToString(), mockFile.Object); - - // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenGetEntityThrowAnErrorChangeAvatarShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - IFormFile formFile = null; - - SetupErrorEntity(); - - // Act - var act = async () => await deviceModelsController.ChangeAvatar(Guid.NewGuid().ToString(), formFile); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + _ = ((OkObjectResult)response.Result)?.Value.Should().BeEquivalentTo(expectedAvatar); + MockRepository.VerifyAll(); } [Test] public async Task DeleteAvatarShouldRemoveModelImage() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var entity = SetupMockEntity(); + var deviceModel = Fixture.Create(); - _ = this.mockDeviceModelImageManager.Setup(c => c.DeleteDeviceModelImageAsync( - It.Is(x => x == entity.RowKey))) + _ = this.mockDeviceModelService.Setup(service => service.DeleteDeviceModelAvatar(deviceModel.ModelId)) .Returns(Task.CompletedTask); // Act - var result = await deviceModelsController.DeleteAvatar(entity.RowKey); - - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - - this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); - this.mockDeviceModelImageManager.VerifyAll(); - } - - [Test] - public async Task WhenModelNotExistsDeleteAvatarShouldReturn404() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupNotFoundEntity(); - - _ = this.mockRepository.Create(); - - // Act - var result = await deviceModelsController.DeleteAvatar(Guid.NewGuid().ToString()); - - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenGetEntityThrowAnErrorDeleteAvatarShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupErrorEntity(); - - // Act - var act = async () => await deviceModelsController.DeleteAvatar(Guid.NewGuid().ToString()); + _ = await this.deviceModelsController.DeleteAvatar(deviceModel.ModelId); // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public async Task PostShouldCreateANewEntity() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - SetupNotFoundEntity(); - - var requestModel = new DeviceModel - { - Name = Guid.NewGuid().ToString(), - ModelId = Guid.NewGuid().ToString() - }; - var mockEnrollmentGroup = this.mockRepository.Create(string.Empty, new SymmetricKeyAttestation(string.Empty, string.Empty)); - - var mockResponse = this.mockRepository.Create(); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.UpsertEntityAsync( - It.Is(x => x.RowKey == requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockDeviceModelMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny())) - .Returns(new Dictionary()); - - _ = this.mockDeviceProvisioningServiceManager.Setup(c => c.CreateEnrollmentGroupFromModelAsync( - It.IsAny(), - It.Is(x => x == requestModel.Name), - It.IsAny())) - .ReturnsAsync(mockEnrollmentGroup.Object); - - _ = this.mockConfigService.Setup(c => c.RollOutDeviceModelConfiguration( - It.Is(x => x == requestModel.ModelId), - It.IsAny>())) - .Returns(Task.CompletedTask); - - // Act - var result = await deviceModelsController.Post(requestModel); - - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - var okObjectResult = result as OkResult; - - Assert.IsNotNull(okObjectResult); - Assert.AreEqual(200, okObjectResult.StatusCode); - - this.mockRepository.VerifyAll(); - } + var deviceModel = Fixture.Create(); - [Test] - public async Task WhenEmptyModelIdPostShouldCreateANewEntity() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var requestModel = new DeviceModel - { - ModelId = String.Empty, - Name = Guid.NewGuid().ToString(), - }; - - var mockResponse = this.mockRepository.Create(); - var mockEnrollmentGroup = this.mockRepository.Create(string.Empty, new SymmetricKeyAttestation(string.Empty, string.Empty)); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.UpsertEntityAsync( - It.Is(x => x.RowKey != requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockDeviceModelMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey != requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny())) - .Returns(new Dictionary()); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceProvisioningServiceManager.Setup(c => c.CreateEnrollmentGroupFromModelAsync( - It.IsAny(), - It.Is(x => x == requestModel.Name), - It.IsAny())) - .ReturnsAsync(mockEnrollmentGroup.Object); - - _ = this.mockConfigService.Setup(c => c.RollOutDeviceModelConfiguration( - It.Is(x => x == requestModel.ModelId), - It.IsAny>())) + _ = this.mockDeviceModelService.Setup(service => service.CreateDeviceModel(deviceModel)) .Returns(Task.CompletedTask); // Act - var result = await deviceModelsController.Post(requestModel); - - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - var okObjectResult = result as OkResult; - - Assert.IsNotNull(okObjectResult); - Assert.AreEqual(200, okObjectResult.StatusCode); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenDeviceModelIdExistsPostShouldReturnBadRequest() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var entity = SetupMockEntity(); - - var deviceModel = new DeviceModel - { - ModelId = entity.RowKey - }; - - // Act - var result = await deviceModelsController.Post(deviceModel); - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - } - - [Test] - public async Task WhenGetEntityThrowAnErrorPostShouldThrowInternalServerErrorExceptiont() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupErrorEntity(); - - var deviceModel = new DeviceModel - { - ModelId = Guid.NewGuid().ToString() - }; - - // Act - var act = async () => await deviceModelsController.Post(deviceModel); + _ = await this.deviceModelsController.Post(deviceModel); // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public async Task PutShouldUpdateTheDeviceModel() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var deviceModel = SetupMockEntity(); - var mockResponse = this.mockRepository.Create(); - - var requestModel = new DeviceModel - { - Name = Guid.NewGuid().ToString(), - ModelId = deviceModel.RowKey - }; - - var mockEnrollmentGroup = this.mockRepository.Create(string.Empty, new SymmetricKeyAttestation(string.Empty, string.Empty)); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.UpsertEntityAsync( - It.Is(x => x.RowKey == deviceModel.RowKey && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockDeviceModelMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == deviceModel.RowKey && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(x => x == requestModel))) - .Returns(new Dictionary()); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceProvisioningServiceManager.Setup(c => c.CreateEnrollmentGroupFromModelAsync( - It.IsAny(), - It.Is(x => x == requestModel.Name), - It.IsAny())) - .ReturnsAsync(mockEnrollmentGroup.Object); - - _ = this.mockConfigService.Setup(c => c.RollOutDeviceModelConfiguration( - It.Is(x => x == requestModel.ModelId), - It.IsAny>())) - .Returns(Task.CompletedTask); - - // Act - var result = await deviceModelsController.Put(requestModel); - - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - var okObjectResult = result as OkResult; - - Assert.IsNotNull(okObjectResult); - Assert.AreEqual(200, okObjectResult.StatusCode); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenDeviceModelIdNotExistsPutShouldReturnBadRequest() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - SetupNotFoundEntity(); - - var deviceModel = new DeviceModel - { - ModelId = Guid.NewGuid().ToString() - }; - - // Act - var result = await deviceModelsController.Put(deviceModel); - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - } + var deviceModel = Fixture.Create(); - [Test] - public async Task WhenGetEntityThrowAnErrorPutShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupErrorEntity(); - - var deviceModel = new DeviceModel - { - ModelId = Guid.NewGuid().ToString() - }; - - // Act - var act = async () => await deviceModelsController.Put(deviceModel); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task DeleteShouldRemoveTheEntityCommandsAndAvatar() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var id = Guid.NewGuid().ToString(); - var commandId = Guid.NewGuid().ToString(); - var returned = false; - - var mockModelResponse = this.mockRepository.Create>(); - - var mockResponse = this.mockRepository.Create(); - var mockTableResponse = this.mockRepository.Create>(); - var mockEnumerator = this.mockRepository.Create>(); - _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); - _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => - { - if (returned) - return false; - - returned = true; - return true; - }); - - _ = mockEnumerator.Setup(x => x.Current) - .Returns(new TableEntity(id, commandId)); - - _ = mockTableResponse.Setup(x => x.GetEnumerator()) - .Returns(mockEnumerator.Object); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == id), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockModelResponse.Object); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == id), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockDeviceService.Setup(c => c.GetAllDevice( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(new PaginationResult - { - Items = new List() - }); - - _ = this.mockDeviceModelImageManager.Setup(c => c.DeleteDeviceModelImageAsync(It.Is(x => x == id))) + _ = this.mockDeviceModelService.Setup(service => service.UpdateDeviceModel(deviceModel)) .Returns(Task.CompletedTask); - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.IsAny>>(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(mockTableResponse.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(p => p == id), - It.Is(k => k == commandId), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - // Act - _ = await deviceModelsController.Delete(id); + _ = await this.deviceModelsController.Put(deviceModel); // Assert - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] - public void WhenGetEntityThrowAnErrorDeleteShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - _ = this.mockDeviceService.Setup(c => c.GetAllDevice( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(new PaginationResult - { - Items = new List() - }); - - SetupErrorEntity(); - - // Act - var act = async () => await deviceModelsController.Delete(Guid.NewGuid().ToString()); - - // Assert - _ = act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenQueryThrowAnErrorDeleteShouldThrowInternalServerErrorException() + public async Task DeleteShouldRemoveTheEntityCommandsAndAvatar() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var id = Guid.NewGuid().ToString(); - - var mockModelResponse = this.mockRepository.Create>(); - - _ = this.mockDeviceService.Setup(c => c.GetAllDevice( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(new PaginationResult - { - Items = new List() - }); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == id), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockModelResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.IsAny>>(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException("")); - - // Act - var act = async () => await deviceModelsController.Delete(id); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); - } + var deviceModel = Fixture.Create(); - [Test] - public async Task WhenDeleteCommandAsyncThrowAnErrorDeleteShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var id = Guid.NewGuid().ToString(); - var commandId = Guid.NewGuid().ToString(); - var returned = false; - - var mockModelResponse = this.mockRepository.Create>(); - - var mockTableResponse = this.mockRepository.Create>(); - var mockEnumerator = this.mockRepository.Create>(); - _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); - _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => - { - if (returned) - return false; - - returned = true; - return true; - }); - - _ = mockEnumerator.Setup(x => x.Current) - .Returns(new TableEntity(id, commandId)); - - _ = mockTableResponse.Setup(x => x.GetEnumerator()) - .Returns(mockEnumerator.Object); - - _ = this.mockDeviceService.Setup(c => c.GetAllDevice( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(new PaginationResult - { - Items = new List() - }); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == id), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockModelResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.IsAny>>(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(mockTableResponse.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(p => p == id), - It.Is(k => k == commandId), - It.IsAny(), - It.IsAny())) - .ThrowsAsync(new RequestFailedException("")); + _ = this.mockDeviceModelService.Setup(service => service.DeleteDeviceModel(deviceModel.ModelId)) + .Returns(Task.CompletedTask); // Act - var act = async () => await deviceModelsController.Delete(id); + _ = await this.deviceModelsController.Delete(deviceModel.ModelId); // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); - } - - private TableEntity SetupMockEntity() - { - var mockResponse = this.mockRepository.Create>(); - var modelId = Guid.NewGuid().ToString(); - var entity = new TableEntity(LoRaWANDeviceModelsController.DefaultPartitionKey, modelId); - - mockResponse.Setup(c => c.Value) - .Returns(entity) - .Verifiable(); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == modelId), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - return entity; - } - - private void SetupNotFoundEntity() - { - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException(StatusCodes.Status404NotFound, "Not Found")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - } - - private void SetupErrorEntity() - { - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException("")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); + MockRepository.VerifyAll(); } } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/LoRaWAN/LoRaWANCommandsControllerTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/LoRaWAN/LoRaWANCommandsControllerTests.cs index f6a87d5a3..0ea3d0853 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/LoRaWAN/LoRaWANCommandsControllerTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/LoRaWAN/LoRaWANCommandsControllerTests.cs @@ -32,7 +32,7 @@ public void SetUp() public async Task PostShouldCreateCommand() { // Arrange - var command = new DeviceModelCommand + var command = new DeviceModelCommandDto { Name = Guid.NewGuid().ToString() }; @@ -55,7 +55,7 @@ public async Task PostShouldCreateCommand() public async Task PostNullModelIdShouldThrowArgumentNullException() { //Arrange - var command = new DeviceModelCommand + var command = new DeviceModelCommandDto { Name = Guid.NewGuid().ToString() }; @@ -88,7 +88,7 @@ public async Task PostNullCommandsShouldThrowArgumentNullException() public async Task GetShouldReturnDeviceModelCommands() { // Arrange - var command = new DeviceModelCommand + var command = new DeviceModelCommandDto { Name = Guid.NewGuid().ToString() }; @@ -109,9 +109,9 @@ public async Task GetShouldReturnDeviceModelCommands() var okResult = (OkObjectResult)response.Result; Assert.IsNotNull(okResult); - Assert.IsAssignableFrom(okResult.Value); + Assert.IsAssignableFrom(okResult.Value); - var result = (DeviceModelCommand[])okResult.Value; + var result = (DeviceModelCommandDto[])okResult.Value; Assert.IsNotNull(result); Assert.AreEqual(1, result.Length); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsControllerTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsControllerTest.cs index 5ded11adb..3c05784ed 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsControllerTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsControllerTest.cs @@ -3,953 +3,189 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Controllers.v1._0.LoRaWAN { - using System; - using System.Collections.Generic; - using System.IO; using System.Linq; - using System.Linq.Expressions; - using System.Threading; using System.Threading.Tasks; - using Azure; - using Azure.Data.Tables; - using AzureIoTHub.Portal.Domain; - using AzureIoTHub.Portal.Domain.Exceptions; - using AzureIoTHub.Portal.Models.v10.LoRaWAN; - using AzureIoTHub.Portal.Server.Controllers.V10; - using AzureIoTHub.Portal.Server.Controllers.V10.LoRaWAN; - using AzureIoTHub.Portal.Server.Managers; - using AzureIoTHub.Portal.Server.Mappers; + using AutoFixture; using AzureIoTHub.Portal.Server.Services; using FluentAssertions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; - using Microsoft.Azure.Devices.Provisioning.Service; - using Microsoft.Azure.Devices.Shared; - using Microsoft.Extensions.Logging; + using Microsoft.Extensions.DependencyInjection; using Models.v10; + using Models.v10.LoRaWAN; using Moq; using NUnit.Framework; + using Portal.Server.Controllers.V10.LoRaWAN; + using UnitTests.Bases; [TestFixture] - public class LoRaWANDeviceModelsControllerTest + public class LoRaWANDeviceModelsControllerTest : BackendUnitTest { - private MockRepository mockRepository; - - private Mock>> mockLogger; - private Mock mockDeviceModelImageManager; - private Mock mockDeviceModelCommandMapper; - private Mock> mockDeviceModelMapper; - private Mock mockDeviceService; - private Mock mockTableClientFactory; - private Mock mockDeviceProvisioningServiceManager; - private Mock mockDeviceTemplatesTableClient; - private Mock mockCommandsTableClient; - private Mock mockConfigService; - - [SetUp] - public void SetUp() - { - this.mockRepository = new MockRepository(MockBehavior.Strict); - - this.mockLogger = this.mockRepository.Create>>(); - this.mockDeviceModelImageManager = this.mockRepository.Create(); - this.mockDeviceModelCommandMapper = this.mockRepository.Create(); - this.mockDeviceProvisioningServiceManager = this.mockRepository.Create(); - this.mockDeviceModelMapper = this.mockRepository.Create>(); - this.mockDeviceService = this.mockRepository.Create(); - this.mockTableClientFactory = this.mockRepository.Create(); - this.mockDeviceTemplatesTableClient = this.mockRepository.Create(); - this.mockCommandsTableClient = this.mockRepository.Create(); - this.mockConfigService = this.mockRepository.Create(); - } + private Mock> mockDeviceModelService; - private LoRaWANDeviceModelsController CreateDeviceModelsController() - { - return new LoRaWANDeviceModelsController( - this.mockLogger.Object, - this.mockDeviceModelImageManager.Object, - this.mockDeviceModelMapper.Object, - this.mockDeviceService.Object, - this.mockTableClientFactory.Object, - this.mockDeviceProvisioningServiceManager.Object, - this.mockConfigService.Object); - } + private LoRaWANDeviceModelsController deviceModelsController; - [Test] - public void GetListShouldReturnAList() + public override void Setup() { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - 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(Guid.NewGuid().ToString(), Guid.NewGuid().ToString())); - - _ = mockTableResponse.Setup(x => x.GetEnumerator()) - .Returns(mockEnumerator.Object); + base.Setup(); - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) - .Returns(mockTableResponse.Object); + this.mockDeviceModelService = MockRepository.Create>(); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); + _ = ServiceCollection.AddSingleton(this.mockDeviceModelService.Object); - _ = this.mockDeviceModelMapper.Setup(c => c.CreateDeviceModelListItem(It.IsAny())) - .Returns((TableEntity _) => new DeviceModel()); + Services = ServiceCollection.BuildServiceProvider(); - // Act - var response = deviceModelsController.GetItems(); - - // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - var okResponse = response.Result as OkObjectResult; - - Assert.AreEqual(200, okResponse.StatusCode); - - Assert.IsNotNull(okResponse.Value); - var result = okResponse.Value as IEnumerable; - Assert.AreEqual(10, result?.Count()); - - this.mockRepository.VerifyAll(); + this.deviceModelsController = new LoRaWANDeviceModelsController(Services.GetRequiredService>()); } [Test] - public void WhenQueryFailedGetListShouldThrowAnExceptionInternalServerErrorException() + public async Task GetListShouldReturnAList() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) - .Throws(new RequestFailedException("request failed.")); + var expectedDeviceModels = Fixture.CreateMany(3).Select(dto => + { + dto.SupportLoRaFeatures = true; + return dto; + }) .ToList(); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); + _ = this.mockDeviceModelService.Setup(service => service.GetDeviceModels()) + .ReturnsAsync(expectedDeviceModels); // Act - var act = () => deviceModelsController.GetItems(); + var response = await this.deviceModelsController.GetItems(); // Assert - _ = act.Should().Throw(); - - this.mockRepository.VerifyAll(); + _ = ((OkObjectResult)response.Result)?.Value.Should().BeEquivalentTo(expectedDeviceModels); + MockRepository.VerifyAll(); } [Test] public async Task GetItemShouldReturnAValue() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var mockResponse = this.mockRepository.Create>(); - _ = mockResponse.Setup(c => c.Value).Returns(new TableEntity(Guid.NewGuid().ToString(), Guid.NewGuid().ToString())); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == "test"), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceModelMapper.Setup(c => c.CreateDeviceModel(It.IsAny())) - .Returns((TableEntity _) => new LoRaDeviceModel()); - - // Act - var result = await deviceModelsController.GetItem("test"); - - // Assert - Assert.IsNotNull(result); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenModelNotExistsGetItemShouldReturn404() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupNotFoundEntity(); - - // Act - var response = await deviceModelsController.GetItem(Guid.NewGuid().ToString()); - - // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - - this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); - this.mockDeviceModelImageManager.VerifyAll(); - } - - [Test] - public async Task WhenGetEntityFailedOnGetItemShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); + var expectedDeviceModel = new LoRaDeviceModelDto + { + ModelId = Fixture.Create() + }; - SetupErrorEntity(); + _ = this.mockDeviceModelService.Setup(service => service.GetDeviceModel(expectedDeviceModel.ModelId)) + .ReturnsAsync(expectedDeviceModel); // Act - var act = () => deviceModelsController.GetItem(Guid.NewGuid().ToString()); + var response = await this.deviceModelsController.GetItem(expectedDeviceModel.ModelId); // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + _ = response.Value.Should().BeEquivalentTo(expectedDeviceModel); + MockRepository.VerifyAll(); } [Test] public async Task GetAvatarShouldReturnTheComputedModelAvatarUri() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var entity = SetupMockEntity(); - - var expectedUrl = new Uri($"http://fake.local/{entity.RowKey}"); - - _ = this.mockDeviceModelImageManager.Setup(c => c.ComputeImageUri(It.Is(x => x == entity.RowKey))) - .Returns(expectedUrl); - - // Act - var response = await deviceModelsController.GetAvatar(entity.RowKey); - - // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - var okResponse = response.Result as OkObjectResult; - - Assert.AreEqual(200, okResponse.StatusCode); - - Assert.IsNotNull(okResponse.Value); - Assert.AreEqual(expectedUrl, okResponse.Value.ToString()); - - this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); - this.mockDeviceModelImageManager.VerifyAll(); - } - - [Test] - public async Task WhenModelNotExistsGetAvatarShouldReturn404() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupNotFoundEntity(); - - // Act - var response = await deviceModelsController.GetAvatar(Guid.NewGuid().ToString()); - - // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenGetEntityThrowAnErrorGetAvatarShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); + var deviceModel = Fixture.Create(); + var expectedAvatar = Fixture.Create(); - SetupErrorEntity(); + _ = this.mockDeviceModelService.Setup(service => service.GetDeviceModelAvatar(deviceModel.ModelId)) + .ReturnsAsync(expectedAvatar); // Act - var act = async () => await deviceModelsController.GetAvatar(Guid.NewGuid().ToString()); + var response = await this.deviceModelsController.GetAvatar(deviceModel.ModelId); // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + _ = ((OkObjectResult)response.Result)?.Value.Should().BeEquivalentTo(expectedAvatar); + MockRepository.VerifyAll(); } [Test] public async Task ChangeAvatarShouldChangeModelImageStream() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var entity = SetupMockEntity(); - - var mockFile = this.mockRepository.Create(); - var expectedUrl = $"http://fake.local/{entity.RowKey}"; - - using var imageStream = new MemoryStream(); - - _ = mockFile.Setup(c => c.OpenReadStream()) - .Returns(imageStream); - - _ = this.mockDeviceModelImageManager.Setup(c => c.ChangeDeviceModelImageAsync( - It.Is(x => x == entity.RowKey), - It.Is(x => x == imageStream))) - .ReturnsAsync(expectedUrl); - - // Act - var response = await deviceModelsController.ChangeAvatar(entity.RowKey, mockFile.Object); - - // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - var okResponse = response.Result as OkObjectResult; - - Assert.AreEqual(200, okResponse.StatusCode); - - Assert.IsNotNull(okResponse.Value); - Assert.AreEqual(expectedUrl, okResponse.Value.ToString()); - - this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); - this.mockDeviceModelImageManager.VerifyAll(); - } - - [Test] - public async Task WhenModelNotExistsChangeAvatarShouldReturn404() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupNotFoundEntity(); + var deviceModel = Fixture.Create(); + var expectedAvatar = Fixture.Create(); - var mockFile = this.mockRepository.Create(); + _ = this.mockDeviceModelService.Setup(service => service.UpdateDeviceModelAvatar(deviceModel.ModelId, It.IsAny())) + .ReturnsAsync(expectedAvatar); // Act - var response = await deviceModelsController.ChangeAvatar(Guid.NewGuid().ToString(), mockFile.Object); + var response = await this.deviceModelsController.ChangeAvatar(deviceModel.ModelId, MockRepository.Create().Object); // Assert - Assert.IsNotNull(response); - Assert.IsAssignableFrom(response.Result); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenGetEntityThrowAnErrorChangeAvatarShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - IFormFile formFile = null; - - SetupErrorEntity(); - - // Act - var act = async () => await deviceModelsController.ChangeAvatar(Guid.NewGuid().ToString(), formFile); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + _ = ((OkObjectResult)response.Result)?.Value.Should().BeEquivalentTo(expectedAvatar); + MockRepository.VerifyAll(); } [Test] public async Task DeleteAvatarShouldRemoveModelImage() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var entity = SetupMockEntity(); + var deviceModel = Fixture.Create(); - _ = this.mockDeviceModelImageManager.Setup(c => c.DeleteDeviceModelImageAsync( - It.Is(x => x == entity.RowKey))) + _ = this.mockDeviceModelService.Setup(service => service.DeleteDeviceModelAvatar(deviceModel.ModelId)) .Returns(Task.CompletedTask); // Act - var result = await deviceModelsController.DeleteAvatar(entity.RowKey); + _ = await this.deviceModelsController.DeleteAvatar(deviceModel.ModelId); // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - - this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once); - this.mockDeviceModelImageManager.VerifyAll(); - } - - [Test] - public async Task WhenModelNotExistsDeleteAvatarShouldReturn404() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupNotFoundEntity(); - - _ = this.mockRepository.Create(); - - // Act - var result = await deviceModelsController.DeleteAvatar(Guid.NewGuid().ToString()); - - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenGetEntityThrowAnErrorDeleteAvatarShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupErrorEntity(); - - // Act - var act = async () => await deviceModelsController.DeleteAvatar(Guid.NewGuid().ToString()); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public async Task PostShouldCreateANewEntity() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - SetupNotFoundEntity(); - - var requestModel = new LoRaDeviceModel - { - Name = Guid.NewGuid().ToString(), - ModelId = Guid.NewGuid().ToString() - }; - var mockEnrollmentGroup = this.mockRepository.Create(string.Empty, new SymmetricKeyAttestation(string.Empty, string.Empty)); - - var mockResponse = this.mockRepository.Create(); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.UpsertEntityAsync( - It.Is(x => x.RowKey == requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockDeviceModelMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny())) - .Returns(new Dictionary()); - - _ = this.mockDeviceProvisioningServiceManager.Setup(c => c.CreateEnrollmentGroupFromModelAsync( - It.IsAny(), - It.Is(x => x == requestModel.Name), - It.IsAny())) - .ReturnsAsync(mockEnrollmentGroup.Object); - - _ = this.mockConfigService.Setup(c => c.RollOutDeviceModelConfiguration( - It.Is(x => x == requestModel.ModelId), - It.IsAny>())) - .Returns(Task.CompletedTask); - - // Act - var result = await deviceModelsController.Post(requestModel); - - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - var okObjectResult = result as OkResult; - - Assert.IsNotNull(okObjectResult); - Assert.AreEqual(200, okObjectResult.StatusCode); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenEmptyModelIdPostShouldCreateANewEntity() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var requestModel = new LoRaDeviceModel + var deviceModel = new LoRaDeviceModelDto { - ModelId = String.Empty, - Name = Guid.NewGuid().ToString(), + ModelId = Fixture.Create() }; - var mockResponse = this.mockRepository.Create(); - var mockEnrollmentGroup = this.mockRepository.Create(string.Empty, new SymmetricKeyAttestation(string.Empty, string.Empty)); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.UpsertEntityAsync( - It.Is(x => x.RowKey != requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockDeviceModelMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey != requestModel.ModelId && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny())) - .Returns(new Dictionary()); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceProvisioningServiceManager.Setup(c => c.CreateEnrollmentGroupFromModelAsync( - It.IsAny(), - It.Is(x => x == requestModel.Name), - It.IsAny())) - .ReturnsAsync(mockEnrollmentGroup.Object); - - _ = this.mockConfigService.Setup(c => c.RollOutDeviceModelConfiguration( - It.Is(x => x == requestModel.ModelId), - It.IsAny>())) + _ = this.mockDeviceModelService.Setup(service => service.CreateDeviceModel(deviceModel)) .Returns(Task.CompletedTask); // Act - var result = await deviceModelsController.Post(requestModel); - - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - var okObjectResult = result as OkResult; - - Assert.IsNotNull(okObjectResult); - Assert.AreEqual(200, okObjectResult.StatusCode); - - this.mockRepository.VerifyAll(); - } + _ = await this.deviceModelsController.Post(deviceModel); - [Test] - public async Task WhenDeviceModelIdExistsPostShouldReturnBadRequest() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var entity = SetupMockEntity(); - - var deviceModel = new LoRaDeviceModel - { - ModelId = entity.RowKey - }; - - // Act - var result = await deviceModelsController.Post(deviceModel); // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - } - - [Test] - public async Task WhenGetEntityThrowAnErrorPostShouldThrowInternalServerErrorExceptiont() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupErrorEntity(); - - var deviceModel = new LoRaDeviceModel - { - ModelId = Guid.NewGuid().ToString() - }; - - // Act - var act = async () => await deviceModelsController.Post(deviceModel); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public async Task PutShouldUpdateTheDeviceModel() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var deviceModel = SetupMockEntity(); - var mockResponse = this.mockRepository.Create(); - - var requestModel = new LoRaDeviceModel + var deviceModel = new LoRaDeviceModelDto { - Name = Guid.NewGuid().ToString(), - ModelId = deviceModel.RowKey + ModelId = Fixture.Create() }; - var mockEnrollmentGroup = this.mockRepository.Create(string.Empty, new SymmetricKeyAttestation(string.Empty, string.Empty)); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.UpsertEntityAsync( - It.Is(x => x.RowKey == deviceModel.RowKey && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockDeviceModelMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == deviceModel.RowKey && x.PartitionKey == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(x => x == requestModel))) - .Returns(new Dictionary()); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceProvisioningServiceManager.Setup(c => c.CreateEnrollmentGroupFromModelAsync( - It.IsAny(), - It.Is(x => x == requestModel.Name), - It.IsAny())) - .ReturnsAsync(mockEnrollmentGroup.Object); - - _ = this.mockConfigService.Setup(c => c.RollOutDeviceModelConfiguration( - It.Is(x => x == requestModel.ModelId), - It.IsAny>())) + _ = this.mockDeviceModelService.Setup(service => service.UpdateDeviceModel(deviceModel)) .Returns(Task.CompletedTask); // Act - var result = await deviceModelsController.Put(requestModel); + _ = await this.deviceModelsController.Put(deviceModel); // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - var okObjectResult = result as OkResult; - - Assert.IsNotNull(okObjectResult); - Assert.AreEqual(200, okObjectResult.StatusCode); - - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] - public async Task WhenDeviceModelIdNotExistsPutShouldReturnBadRequest() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - SetupNotFoundEntity(); - - var deviceModel = new LoRaDeviceModel - { - ModelId = Guid.NewGuid().ToString() - }; - - // Act - var result = await deviceModelsController.Put(deviceModel); - // Assert - Assert.IsNotNull(result); - Assert.IsAssignableFrom(result); - } - - [Test] - public async Task WhenGetEntityThrowAnErrorPutShouldThrowInternalServerErrorException() + public async Task DeleteShouldRemoveTheEntityCommandsAndAvatar() { // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - SetupErrorEntity(); - - var deviceModel = new LoRaDeviceModel + var deviceModel = new LoRaDeviceModelDto { - ModelId = Guid.NewGuid().ToString() + ModelId = Fixture.Create() }; - // Act - var act = async () => await deviceModelsController.Put(deviceModel); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task DeleteShouldRemoveTheEntityCommandsAndAvatar() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - var id = Guid.NewGuid().ToString(); - var commandId = Guid.NewGuid().ToString(); - var returned = false; - - var mockModelResponse = this.mockRepository.Create>(); - - var mockResponse = this.mockRepository.Create(); - var mockTableResponse = this.mockRepository.Create>(); - var mockEnumerator = this.mockRepository.Create>(); - _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); - _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => - { - if (returned) - return false; - - returned = true; - return true; - }); - - _ = mockEnumerator.Setup(x => x.Current) - .Returns(new TableEntity(id, commandId)); - - _ = mockTableResponse.Setup(x => x.GetEnumerator()) - .Returns(mockEnumerator.Object); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == id), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockModelResponse.Object); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == id), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockDeviceService.Setup(c => c.GetAllDevice( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(new PaginationResult - { - Items = new List() - }); - - _ = this.mockDeviceModelImageManager.Setup(c => c.DeleteDeviceModelImageAsync(It.Is(x => x == id))) + _ = this.mockDeviceModelService.Setup(service => service.DeleteDeviceModel(deviceModel.ModelId)) .Returns(Task.CompletedTask); - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.IsAny>>(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(mockTableResponse.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(p => p == id), - It.Is(k => k == commandId), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - - // Act - _ = await deviceModelsController.Delete(id); - - // Assert - this.mockRepository.VerifyAll(); - } - - [Test] - public void WhenGetEntityThrowAnErrorDeleteShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - _ = this.mockDeviceService.Setup(c => c.GetAllDevice( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(new PaginationResult - { - Items = new List() - }); - - SetupErrorEntity(); - // Act - var act = async () => await deviceModelsController.Delete(Guid.NewGuid().ToString()); + _ = await this.deviceModelsController.Delete(deviceModel.ModelId); // Assert - _ = act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenQueryThrowAnErrorDeleteShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var id = Guid.NewGuid().ToString(); - - var mockModelResponse = this.mockRepository.Create>(); - - _ = this.mockDeviceService.Setup(c => c.GetAllDevice( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(new PaginationResult - { - Items = new List() - }); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == id), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockModelResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.IsAny>>(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException("")); - - // Act - var act = async () => await deviceModelsController.Delete(id); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task WhenDeleteCommandAsyncThrowAnErrorDeleteShouldThrowInternalServerErrorException() - { - // Arrange - var deviceModelsController = CreateDeviceModelsController(); - - var id = Guid.NewGuid().ToString(); - var commandId = Guid.NewGuid().ToString(); - var returned = false; - - var mockModelResponse = this.mockRepository.Create>(); - - var mockTableResponse = this.mockRepository.Create>(); - var mockEnumerator = this.mockRepository.Create>(); - _ = mockEnumerator.Setup(x => x.Dispose()).Callback(() => { }); - _ = mockEnumerator.Setup(x => x.MoveNext()).Returns(() => - { - if (returned) - return false; - - returned = true; - return true; - }); - - _ = mockEnumerator.Setup(x => x.Current) - .Returns(new TableEntity(id, commandId)); - - _ = mockTableResponse.Setup(x => x.GetEnumerator()) - .Returns(mockEnumerator.Object); - - _ = this.mockDeviceService.Setup(c => c.GetAllDevice( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(new PaginationResult - { - Items = new List() - }); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == id), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockModelResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.IsAny>>(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(mockTableResponse.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(p => p == id), - It.Is(k => k == commandId), - It.IsAny(), - It.IsAny())) - .ThrowsAsync(new RequestFailedException("")); - - // Act - var act = async () => await deviceModelsController.Delete(id); - - // Assert - _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); - } - - private TableEntity SetupMockEntity() - { - var mockResponse = this.mockRepository.Create>(); - var modelId = Guid.NewGuid().ToString(); - var entity = new TableEntity(LoRaWANDeviceModelsController.DefaultPartitionKey, modelId); - - mockResponse.Setup(c => c.Value) - .Returns(entity) - .Verifiable(); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == modelId), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - return entity; - } - - private void SetupNotFoundEntity() - { - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException(StatusCodes.Status404NotFound, "Not Found")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - } - - private void SetupErrorEntity() - { - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException("")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); + MockRepository.VerifyAll(); } } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Managers/DeviceModelCommandsManagerTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Managers/DeviceModelCommandsManagerTests.cs index 0cf4940de..7480d9f67 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Managers/DeviceModelCommandsManagerTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Managers/DeviceModelCommandsManagerTests.cs @@ -92,8 +92,8 @@ public void RetrieveDeviceModelCommandsStateUnderTestExpectedBehavior() var resultReturned = false; var entityMock = new TableEntity(deviceModel, "bbbb"); - _ = entityMock.TryAdd(nameof(DeviceModelCommand.Frame), "ADETRDTHDFG"); - _ = entityMock.TryAdd(nameof(DeviceModelCommand.Port), 125); + _ = entityMock.TryAdd(nameof(DeviceModelCommandDto.Frame), "ADETRDTHDFG"); + _ = entityMock.TryAdd(nameof(DeviceModelCommandDto.Port), 125); var mockTable = this.mockRepository.Create(); var mockTableResponse = this.mockRepository.Create>(); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Managers/LoraDeviceMethodManagerTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Managers/LoraDeviceMethodManagerTests.cs index 5560779b8..e07fe2d03 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Managers/LoraDeviceMethodManagerTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Managers/LoraDeviceMethodManagerTests.cs @@ -62,7 +62,7 @@ public async Task ExecuteLoRaDeviceMessageMustBeSuccessfullWhenParametersAreProv { // Arrange var deviceId = Fixture.Create(); - var command = new DeviceModelCommand + var command = new DeviceModelCommandDto { Frame = Fixture.Create(), Confirmed = Fixture.Create(), diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceModelCommandMapperTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceModelCommandMapperTests.cs index 60fd9745d..a8a80f0c6 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceModelCommandMapperTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceModelCommandMapperTests.cs @@ -55,7 +55,7 @@ public void UpdateTableEntityStateUnderTestExpectedBehavior() var deviceModelCommandMapper = CreateDeviceModelCommandMapper(); var entity = new TableEntity(); - var element = new DeviceModelCommand + var element = new DeviceModelCommandDto { Name = "000-000-001", Frame = "ExpectedFrame", diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceModelMapperTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceModelMapperTests.cs index ac88bf1cd..6bc695ae5 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceModelMapperTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/DeviceModelMapperTests.cs @@ -8,6 +8,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Mappers using Models.v10; using AzureIoTHub.Portal.Server.Managers; using AzureIoTHub.Portal.Server.Mappers; + using FluentAssertions; using Moq; using NUnit.Framework; @@ -17,7 +18,6 @@ public class DeviceModelMapperTests private MockRepository mockRepository; private Mock mockDeviceModelImageManager; - private Mock mockDeviceModelCommandsManager; [SetUp] public void SetUp() @@ -25,8 +25,6 @@ public void SetUp() this.mockRepository = new MockRepository(MockBehavior.Strict); this.mockDeviceModelImageManager = this.mockRepository.Create(); - - this.mockDeviceModelCommandsManager = this.mockRepository.Create(); } private DeviceModelMapper CreateDeviceModelMapper() @@ -93,25 +91,21 @@ public void CreateDeviceModelListItemStateUnderTestExpectedBehavior() } [Test] - public void UpdateTableEntityStateUnderTestExpectedBehavior() + public void BuildDeviceModelDesiredPropertiesShouldReturnEmptyDesiredPropertiesForDeviceModel() { // Arrange var deviceModelMapper = CreateDeviceModelMapper(); - var entity = new TableEntity(); - var model = new DeviceModel + var model = new DeviceModelDto { Name = "DeviceModelName", Description = "Description" }; // Act - _ = deviceModelMapper.UpdateTableEntity( - entity, - model); + var result = deviceModelMapper.BuildDeviceModelDesiredProperties(model); // Assert - Assert.AreEqual("DeviceModelName", entity["Name"]); - Assert.AreEqual("Description", entity["Description"]); + _ = result.Should().BeEmpty(); this.mockRepository.VerifyAll(); } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/LoRaDeviceModelMapperTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/LoRaDeviceModelMapperTests.cs index 9395d7cb8..f993fad54 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/LoRaDeviceModelMapperTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Mappers/LoRaDeviceModelMapperTests.cs @@ -8,6 +8,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Mappers using Models.v10.LoRaWAN; using AzureIoTHub.Portal.Server.Managers; using AzureIoTHub.Portal.Server.Mappers; + using FluentAssertions; using Moq; using NUnit.Framework; @@ -16,7 +17,6 @@ public class LoRaDeviceModelMapperTests { private MockRepository mockRepository; - private Mock mockDeviceModelCommandsManager; private Mock mockDeviceModelImageManager; [SetUp] @@ -24,14 +24,12 @@ public void SetUp() { this.mockRepository = new MockRepository(MockBehavior.Strict); - this.mockDeviceModelCommandsManager = this.mockRepository.Create(); this.mockDeviceModelImageManager = this.mockRepository.Create(); } private LoRaDeviceModelMapper CreateLoRaDeviceModelMapper() { return new LoRaDeviceModelMapper( - this.mockDeviceModelCommandsManager.Object, this.mockDeviceModelImageManager.Object); } @@ -49,10 +47,10 @@ public void CreateDeviceModelListItemStateUnderTestExpectedBehavior(bool isBuilt _ = this.mockDeviceModelImageManager.Setup(c => c.ComputeImageUri(It.Is(x => x == entity.RowKey))) .Returns(expectedModelImageUri); - entity[nameof(LoRaDeviceModel.IsBuiltin)] = isBuiltin; - entity[nameof(LoRaDeviceModel.SupportLoRaFeatures)] = supportLora; - entity[nameof(LoRaDeviceModel.Name)] = "FAKE DEVICE"; - entity[nameof(LoRaDeviceModel.Description)] = "FAKE DESCRIPTION"; + entity[nameof(LoRaDeviceModelDto.IsBuiltin)] = isBuiltin; + entity[nameof(LoRaDeviceModelDto.SupportLoRaFeatures)] = supportLora; + entity[nameof(LoRaDeviceModelDto.Name)] = "FAKE DEVICE"; + entity[nameof(LoRaDeviceModelDto.Description)] = "FAKE DESCRIPTION"; // Act var result = loRaDeviceModelMapper.CreateDeviceModelListItem(entity); @@ -60,10 +58,10 @@ public void CreateDeviceModelListItemStateUnderTestExpectedBehavior(bool isBuilt // Assert Assert.IsNotNull(result); Assert.AreEqual(entity.RowKey, result.ModelId); - Assert.AreEqual(entity[nameof(LoRaDeviceModel.Name)], result.Name); - Assert.AreEqual(entity[nameof(LoRaDeviceModel.Description)], result.Description); - Assert.AreEqual(entity[nameof(LoRaDeviceModel.SupportLoRaFeatures)], supportLora); - Assert.AreEqual(entity[nameof(LoRaDeviceModel.IsBuiltin)], isBuiltin); + Assert.AreEqual(entity[nameof(LoRaDeviceModelDto.Name)], result.Name); + Assert.AreEqual(entity[nameof(LoRaDeviceModelDto.Description)], result.Description); + Assert.AreEqual(entity[nameof(LoRaDeviceModelDto.SupportLoRaFeatures)], supportLora); + Assert.AreEqual(entity[nameof(LoRaDeviceModelDto.IsBuiltin)], isBuiltin); this.mockRepository.VerifyAll(); } @@ -82,11 +80,11 @@ public void CreateDeviceModelStateUnderTestExpectedBehavior(bool isBuiltin, bool _ = this.mockDeviceModelImageManager.Setup(c => c.ComputeImageUri(It.Is(x => x == entity.RowKey))) .Returns(expectedModelImageUri); - entity[nameof(LoRaDeviceModel.IsBuiltin)] = isBuiltin; - entity[nameof(LoRaDeviceModel.SupportLoRaFeatures)] = supportLora; - entity[nameof(LoRaDeviceModel.Name)] = "FAKE DEVICE"; - entity[nameof(LoRaDeviceModel.Description)] = "FAKE DESCRIPTION"; - entity[nameof(LoRaDeviceModel.SensorDecoder)] = "FAKE SENSORDECODERURL"; + entity[nameof(LoRaDeviceModelDto.IsBuiltin)] = isBuiltin; + entity[nameof(LoRaDeviceModelDto.SupportLoRaFeatures)] = supportLora; + entity[nameof(LoRaDeviceModelDto.Name)] = "FAKE DEVICE"; + entity[nameof(LoRaDeviceModelDto.Description)] = "FAKE DESCRIPTION"; + entity[nameof(LoRaDeviceModelDto.SensorDecoder)] = "FAKE SENSORDECODERURL"; // Act var result = loRaDeviceModelMapper.CreateDeviceModel( @@ -95,11 +93,11 @@ public void CreateDeviceModelStateUnderTestExpectedBehavior(bool isBuiltin, bool // Assert Assert.IsNotNull(result); Assert.AreEqual(entity.RowKey, result.ModelId); - Assert.AreEqual(entity[nameof(LoRaDeviceModel.Name)], result.Name); - Assert.AreEqual(entity[nameof(LoRaDeviceModel.Description)], result.Description); - Assert.AreEqual(entity[nameof(LoRaDeviceModel.SensorDecoder)], result.SensorDecoder); - Assert.AreEqual(entity[nameof(LoRaDeviceModel.SupportLoRaFeatures)], supportLora); - Assert.AreEqual(entity[nameof(LoRaDeviceModel.IsBuiltin)], isBuiltin); + Assert.AreEqual(entity[nameof(LoRaDeviceModelDto.Name)], result.Name); + Assert.AreEqual(entity[nameof(LoRaDeviceModelDto.Description)], result.Description); + Assert.AreEqual(entity[nameof(LoRaDeviceModelDto.SensorDecoder)], result.SensorDecoder); + Assert.AreEqual(entity[nameof(LoRaDeviceModelDto.SupportLoRaFeatures)], supportLora); + Assert.AreEqual(entity[nameof(LoRaDeviceModelDto.IsBuiltin)], isBuiltin); this.mockRepository.VerifyAll(); } @@ -111,10 +109,9 @@ public void UpdateTableEntityStateUnderTestExpectedBehavior(bool isBuiltin) { // Arrange var loRaDeviceModelMapper = CreateLoRaDeviceModelMapper(); - var entity = new TableEntity(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); - var model = new LoRaDeviceModel + var model = new LoRaDeviceModelDto { - ModelId = entity.RowKey, + ModelId = Guid.NewGuid().ToString(), Name = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), ImageUrl = new Uri("http://fake.local"), @@ -123,17 +120,11 @@ public void UpdateTableEntityStateUnderTestExpectedBehavior(bool isBuiltin) }; // Act - _ = loRaDeviceModelMapper.UpdateTableEntity( - entity, - model); + var result = loRaDeviceModelMapper.BuildDeviceModelDesiredProperties(model); // Assert - Assert.AreEqual(model.ModelId, entity.RowKey); - Assert.AreEqual(model.Name, entity[nameof(LoRaDeviceModel.Name)]); - Assert.AreEqual(model.Description, entity[nameof(LoRaDeviceModel.Description)]); - Assert.AreEqual(true, entity[nameof(LoRaDeviceModel.SupportLoRaFeatures)]); - Assert.AreEqual(isBuiltin, entity[nameof(LoRaDeviceModel.IsBuiltin)]); - Assert.AreEqual(model.SensorDecoder, entity[nameof(LoRaDeviceModel.SensorDecoder)]); + _ = result.Keys.Count.Should().Be(13); + this.mockRepository.VerifyAll(); } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs new file mode 100644 index 000000000..b766d9839 --- /dev/null +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs @@ -0,0 +1,473 @@ +// 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.Server.Services +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Threading.Tasks; + using AutoFixture; + using AzureIoTHub.Portal.Domain; + using AzureIoTHub.Portal.Server.Services; + using FluentAssertions; + using Microsoft.AspNetCore.Http; + using Microsoft.Azure.Devices.Provisioning.Service; + using Microsoft.Azure.Devices.Shared; + using Microsoft.EntityFrameworkCore; + using Microsoft.Extensions.DependencyInjection; + using Models.v10; + using Moq; + using NUnit.Framework; + using Portal.Domain.Entities; + using Portal.Domain.Exceptions; + using Portal.Domain.Repositories; + using Portal.Server.Managers; + using UnitTests.Bases; + + [TestFixture] + public class DeviceModelServiceTests : BackendUnitTest + { + private Mock mockUnitOfWork; + private Mock mockDeviceModelRepository; + private Mock mockDeviceModelCommandRepository; + private Mock mockDeviceProvisioningServiceManager; + private Mock mockConfigService; + private Mock mockDeviceModelImageManager; + private Mock mockDeviceService; + private Mock> mockDeviceModelMapper; + + private IDeviceModelService deviceModelService; + + public override void Setup() + { + base.Setup(); + + this.mockUnitOfWork = MockRepository.Create(); + this.mockDeviceModelRepository = MockRepository.Create(); + + this.mockDeviceModelCommandRepository = MockRepository.Create(); + this.mockDeviceProvisioningServiceManager = MockRepository.Create(); + this.mockConfigService = MockRepository.Create(); + this.mockDeviceModelImageManager = MockRepository.Create(); + this.mockDeviceService = MockRepository.Create(); + this.mockDeviceModelMapper = MockRepository.Create>(); + + _ = ServiceCollection.AddSingleton(this.mockUnitOfWork.Object); + _ = ServiceCollection.AddSingleton(this.mockDeviceModelRepository.Object); + _ = ServiceCollection.AddSingleton(this.mockDeviceModelCommandRepository.Object); + _ = ServiceCollection.AddSingleton(this.mockDeviceProvisioningServiceManager.Object); + _ = ServiceCollection.AddSingleton(this.mockConfigService.Object); + _ = ServiceCollection.AddSingleton(this.mockDeviceModelImageManager.Object); + _ = ServiceCollection.AddSingleton(this.mockDeviceService.Object); + _ = ServiceCollection.AddSingleton(this.mockDeviceModelMapper.Object); + _ = ServiceCollection.AddSingleton, DeviceModelService>(); + + Services = ServiceCollection.BuildServiceProvider(); + + this.deviceModelService = Services.GetRequiredService>(); + } + + [Test] + public async Task GetDeviceModelsShouldReturnExpectedDeviceModels() + { + // Arrange + var expectedDeviceModels = Fixture.CreateMany(3).ToList(); + var expectedDeviceModelsDto = expectedDeviceModels.Select(model => Mapper.Map(model)).ToList(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetAll()) + .Returns(expectedDeviceModels); + + // Act + var result = await this.deviceModelService.GetDeviceModels(); + + // Assert + _ = result.Should().BeEquivalentTo(expectedDeviceModelsDto); + MockRepository.VerifyAll(); + } + + [Test] + public async Task GetDeviceModelShouldReturnExpectedDeviceModel() + { + // Arrange + var expectedDeviceModel = Fixture.Create(); + var expectedDeviceModelDto = Mapper.Map(expectedDeviceModel); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(expectedDeviceModel.Id)) + .ReturnsAsync(expectedDeviceModel); + + // Act + var result = await this.deviceModelService.GetDeviceModel(expectedDeviceModel.Id); + + // Assert + _ = result.Should().BeEquivalentTo(expectedDeviceModelDto); + MockRepository.VerifyAll(); + } + + [Test] + public async Task GetDeviceModelShouldThrowResourceNotFoundExceptionWhenDeviceModelNotExist() + { + // Arrange + var deviceModelId = Fixture.Create(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModelId)) + .ReturnsAsync((DeviceModel)null); + + // Act + var act = () => this.deviceModelService.GetDeviceModel(deviceModelId); + + // Assert + _ = await act.Should().ThrowAsync(); + MockRepository.VerifyAll(); + } + + [Test] + public async Task CreateDeviceModelShouldCreateDeviceModel() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.InsertAsync(It.IsAny())) + .Returns(Task.CompletedTask); + + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); + + _ = this.mockDeviceModelMapper + .Setup(mapper => mapper.BuildDeviceModelDesiredProperties(It.IsAny())) + .Returns(new Dictionary()); + + _ = this.mockDeviceProvisioningServiceManager.Setup(manager => + manager.CreateEnrollmentGroupFromModelAsync(deviceModelDto.ModelId, deviceModelDto.Name, + It.IsAny())) + .ReturnsAsync((EnrollmentGroup)null); + + _ = this.mockConfigService.Setup(service => + service.RollOutDeviceModelConfiguration(deviceModelDto.ModelId, + It.IsAny>())) + .Returns(Task.CompletedTask); + + // Act + await this.deviceModelService.CreateDeviceModel(deviceModelDto); + + // Assert + MockRepository.VerifyAll(); + } + + [Test] + public async Task CreateDeviceModelShouldThrowInternalServerErrorExceptionWhenDDbUpdateExceptionIsThrown() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.InsertAsync(It.IsAny())) + .Returns(Task.CompletedTask); + + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .ThrowsAsync(new DbUpdateException()); + + // Act + var act = () => this.deviceModelService.CreateDeviceModel(deviceModelDto); + + // Assert + _ = await act.Should().ThrowAsync(); + MockRepository.VerifyAll(); + } + + [Test] + public async Task UpdateDeviceModelShouldUpdateDeviceModel() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModelDto.ModelId)) + .ReturnsAsync(new DeviceModel()); + + this.mockDeviceModelRepository.Setup(repository => repository.Update(It.IsAny())) + .Verifiable(); + + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); + + _ = this.mockDeviceModelMapper + .Setup(mapper => mapper.BuildDeviceModelDesiredProperties(It.IsAny())) + .Returns(new Dictionary()); + + _ = this.mockDeviceProvisioningServiceManager.Setup(manager => + manager.CreateEnrollmentGroupFromModelAsync(deviceModelDto.ModelId, deviceModelDto.Name, + It.IsAny())) + .ReturnsAsync((EnrollmentGroup)null); + + _ = this.mockConfigService.Setup(service => + service.RollOutDeviceModelConfiguration(deviceModelDto.ModelId, + It.IsAny>())) + .Returns(Task.CompletedTask); + + // Act + await this.deviceModelService.UpdateDeviceModel(deviceModelDto); + + // Assert + MockRepository.VerifyAll(); + } + + [Test] + public async Task UpdateDeviceModelShouldThrowInternalServerErrorExceptionWhenDDbUpdateExceptionIsThrown() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModelDto.ModelId)) + .ReturnsAsync(new DeviceModel()); + + this.mockDeviceModelRepository.Setup(repository => repository.Update(It.IsAny())) + .Verifiable(); + + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .ThrowsAsync(new DbUpdateException()); + + // Act + var act = () => this.deviceModelService.UpdateDeviceModel(deviceModelDto); + + // Assert + _ = await act.Should().ThrowAsync(); + MockRepository.VerifyAll(); + } + + [Test] + public async Task UpdateDeviceModelShouldThrowResourceNotFoundExceptionWhenDeviceModelDOntExist() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModelDto.ModelId)) + .ReturnsAsync((DeviceModel)null); + + // Act + var act = () => this.deviceModelService.UpdateDeviceModel(deviceModelDto); + + // Assert + _ = await act.Should().ThrowAsync(); + MockRepository.VerifyAll(); + } + + [Test] + public async Task DeleteDeviceModelShouldDeleteDeviceModel() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + var commands = Fixture.CreateMany(5).Select(command => + { + command.DeviceModelId = deviceModelDto.ModelId; + return command; + }) .ToList(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModelDto.ModelId)) + .ReturnsAsync(new DeviceModel()); + + _ = this.mockDeviceService.Setup(service => service.GetAllDevice( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(new PaginationResult + { + Items = Array.Empty() + }); + + _ = this.mockDeviceModelCommandRepository.Setup(repository => repository.GetAll()) + .Returns(commands); + + this.mockDeviceModelCommandRepository.Setup(repository => repository.Delete(It.IsAny())) + .Verifiable(); + + _ = this.mockDeviceModelImageManager + .Setup(manager => manager.DeleteDeviceModelImageAsync(deviceModelDto.ModelId)) + .Returns(Task.CompletedTask); + + this.mockDeviceModelRepository.Setup(repository => repository.Delete(deviceModelDto.ModelId)) + .Verifiable(); + + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); + + // Act + await this.deviceModelService.DeleteDeviceModel(deviceModelDto.ModelId); + + // Assert + MockRepository.VerifyAll(); + } + + [Test] + public async Task DeleteDeviceModelShouldThrowInternalServerErrorExceptionWhenDDbUpdateExceptionIsThrown() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + var commands = Fixture.CreateMany(5).Select(command => + { + command.DeviceModelId = deviceModelDto.ModelId; + return command; + }) .ToList(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModelDto.ModelId)) + .ReturnsAsync(new DeviceModel()); + + _ = this.mockDeviceService.Setup(service => service.GetAllDevice( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(new PaginationResult + { + Items = Array.Empty() + }); + + _ = this.mockDeviceModelCommandRepository.Setup(repository => repository.GetAll()) + .Returns(commands); + + this.mockDeviceModelCommandRepository.Setup(repository => repository.Delete(It.IsAny())) + .Verifiable(); + + _ = this.mockDeviceModelImageManager + .Setup(manager => manager.DeleteDeviceModelImageAsync(deviceModelDto.ModelId)) + .Returns(Task.CompletedTask); + + this.mockDeviceModelRepository.Setup(repository => repository.Delete(deviceModelDto.ModelId)) + .Verifiable(); + + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .ThrowsAsync(new DbUpdateException()); + + // Act + var act = () => this.deviceModelService.DeleteDeviceModel(deviceModelDto.ModelId); + + // Assert + _ = await act.Should().ThrowAsync(); + MockRepository.VerifyAll(); + } + + [Test] + public async Task DeleteDeviceModelShouldThrowInternalServerErrorExceptionWhenDeviceModelIsUsedByDevice() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModelDto.ModelId)) + .ReturnsAsync(new DeviceModel()); + + _ = this.mockDeviceService.Setup(service => service.GetAllDevice( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(new PaginationResult + { + Items = new List + { + new() + { + Tags = new TwinCollection + { + ["modelId"] = deviceModelDto.ModelId + } + } + } + }); + + // Act + var act = () => this.deviceModelService.DeleteDeviceModel(deviceModelDto.ModelId); + + // Assert + _ = await act.Should().ThrowAsync(); + MockRepository.VerifyAll(); + } + + [Test] + public async Task DeleteDeviceModelShouldNotDeleteNonExistingDevice() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModelDto.ModelId)) + .ReturnsAsync((DeviceModel)null); + + // Act + await this.deviceModelService.DeleteDeviceModel(deviceModelDto.ModelId); + + // Assert + MockRepository.VerifyAll(); + } + + [Test] + public async Task GetDeviceModelAvatarShouldReturnDeviceModelAvatar() + { + // Arrange + var deviceModelDto = Fixture.Create(); + var expectedAvatarUrl = Fixture.Create(); + _ = this.mockDeviceModelImageManager.Setup(manager => manager.ComputeImageUri(deviceModelDto.ModelId)) + .Returns(expectedAvatarUrl); + + // Act + var result = await this.deviceModelService.GetDeviceModelAvatar(deviceModelDto.ModelId); + + // Assert + _ = result.Should().Be(expectedAvatarUrl.ToString()); + MockRepository.VerifyAll(); + } + + [Test] + public async Task UpdateDeviceModelAvatarShouldUpdateDeviceModelAvatar() + { + // Arrange + var deviceModelDto = Fixture.Create(); + var expectedAvatarUrl = Fixture.Create(); + + var mockFormFile = MockRepository.Create(); + + _ = this.mockDeviceModelImageManager.Setup(manager => + manager.ChangeDeviceModelImageAsync(deviceModelDto.ModelId, It.IsAny())) + .ReturnsAsync(expectedAvatarUrl); + + _ = mockFormFile.Setup(file => file.OpenReadStream()) + .Returns(Stream.Null); + + // Act + var result = await this.deviceModelService.UpdateDeviceModelAvatar(deviceModelDto.ModelId, mockFormFile.Object); + + // Assert + _ = result.Should().Be(expectedAvatarUrl); + MockRepository.VerifyAll(); + } + + [Test] + public async Task DeleteDeviceModelAvatarShouldDeleteDeviceModelAvatar() + { + // Arrange + var deviceModelDto = Fixture.Create(); + + _ = this.mockDeviceModelImageManager + .Setup(manager => manager.DeleteDeviceModelImageAsync(deviceModelDto.ModelId)) + .Returns(Task.CompletedTask); + + // Act + await this.deviceModelService.DeleteDeviceModelAvatar(deviceModelDto.ModelId); + + // Assert + MockRepository.VerifyAll(); + } + } +} diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs index 450ea5f74..a373241f0 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs @@ -1616,7 +1616,7 @@ public async Task GetEnrollmentCredentialsShouldReturnEnrollmentCredentials() var mockTableClient = this.mockRepository.Create(); var mockDeviceModelEntity = new TableEntity { - [nameof(DeviceModel.Name)] = "ccc" + [nameof(DeviceModelDto.Name)] = "ccc" }; var mockResponse = this.mockRepository.Create>(); @@ -1700,7 +1700,7 @@ public async Task WhenUnableToGetModelGetEnrollmentCredentialsShouldThrowInterna var mockTableClient = this.mockRepository.Create(); var mockDeviceModelEntity = new TableEntity { - [nameof(DeviceModel.Name)] = "ccc" + [nameof(DeviceModelDto.Name)] = "ccc" }; var mockResponse = this.mockRepository.Create>(); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANCommandServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANCommandServiceTests.cs index b08630fe1..8d35dbb97 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANCommandServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANCommandServiceTests.cs @@ -4,426 +4,137 @@ namespace AzureIoTHub.Portal.Tests.Unit.Domain.Services { using System; - using System.Collections.Generic; - using System.Threading; + using System.Linq; 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.Controllers.V10.LoRaWAN; - using AzureIoTHub.Portal.Server.Mappers; using AzureIoTHub.Portal.Server.Services; using FluentAssertions; - using Microsoft.AspNetCore.Http; - using Microsoft.Extensions.Logging; + using Microsoft.EntityFrameworkCore; + using Microsoft.Extensions.DependencyInjection; using Models.v10.LoRaWAN; using Moq; using NUnit.Framework; + using Portal.Domain.Entities; + using Portal.Domain.Repositories; + using UnitTests.Bases; [TestFixture] - public class LoRaWANCommandServiceTests + public class LoRaWANCommandServiceTests : BackendUnitTest { - private MockRepository mockRepository; + private Mock mockDeviceModelRepository; + private Mock mockDeviceModelCommandRepository; + private Mock mockUnitOfWork; - private Mock mockDeviceModelCommandMapper; - private Mock mockTableClientFactory; - private Mock mockDeviceTemplatesTableClient; - private Mock mockCommandsTableClient; - private Mock> mockLogger; + private ILoRaWANCommandService loRaWanCommandService; - [SetUp] - public void SetUp() + public override void Setup() { - this.mockRepository = new MockRepository(MockBehavior.Strict); + base.Setup(); - this.mockLogger = this.mockRepository.Create>(); - this.mockDeviceModelCommandMapper = this.mockRepository.Create(); - this.mockTableClientFactory = this.mockRepository.Create(); - this.mockDeviceTemplatesTableClient = this.mockRepository.Create(); - this.mockCommandsTableClient = this.mockRepository.Create(); - } - - [Test] - public async Task PostShouldCreateCommand() - { - // Arrange - var deviceModelCommandsService = CreateDeviceModelCommandsService(); - var entity = SetupMockDeviceModel(); - - var command = new DeviceModelCommand - { - Name = Guid.NewGuid().ToString() - }; - - var mockResponse = this.mockRepository.Create(); - - _ = this.mockDeviceModelCommandMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == command.Name && x.PartitionKey == entity.RowKey), - It.Is(x => x == command))); - - _ = this.mockCommandsTableClient.Setup(c => c.AddEntityAsync( - It.Is(x => x.RowKey == command.Name && x.PartitionKey == entity.RowKey), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.Is(x => x == $"PartitionKey eq '{entity.RowKey}'"), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(Pageable.FromPages(new[] - { - Page.FromValues(new[] - { - new TableEntity(entity.RowKey, Guid.NewGuid().ToString()) - }, null, mockResponse.Object) - })); - - _ = this.mockCommandsTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(x => x == entity.RowKey), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - - // Act - await deviceModelCommandsService.PostDeviceModelCommands(entity.RowKey, new[] { command }); - - // Assert - this.mockTableClientFactory.Verify(c => c.GetDeviceTemplates(), Times.Once()); - this.mockDeviceTemplatesTableClient.Verify(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == entity.RowKey), - It.IsAny>(), - It.IsAny()), Times.Once); - - this.mockTableClientFactory.Verify(c => c.GetDeviceCommands()); - this.mockDeviceModelCommandMapper.VerifyAll(); - this.mockCommandsTableClient.Verify(c => c.AddEntityAsync( - It.Is(x => x.RowKey == command.Name && x.PartitionKey == entity.RowKey), - It.IsAny()), Times.Once()); - } - - [Test] - public async Task PostShouldThrowInternalServerErrorExceptionWhenFailQueryingExistingCommands() - { - // Arrange - var deviceModelCommandsService = CreateDeviceModelCommandsService(); - - var mockResponse = this.mockRepository.Create>(); - var modelId = Guid.NewGuid().ToString(); - var entity = new TableEntity(LoRaWANDeviceModelsController.DefaultPartitionKey, modelId); + this.mockDeviceModelRepository = MockRepository.Create(); + this.mockDeviceModelCommandRepository = MockRepository.Create(); + this.mockUnitOfWork = MockRepository.Create(); - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == modelId), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); + _ = ServiceCollection.AddSingleton(this.mockDeviceModelRepository.Object); + _ = ServiceCollection.AddSingleton(this.mockDeviceModelCommandRepository.Object); + _ = ServiceCollection.AddSingleton(this.mockUnitOfWork.Object); + _ = ServiceCollection.AddSingleton(); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); + Services = ServiceCollection.BuildServiceProvider(); - var command = new DeviceModelCommand - { - Name = Guid.NewGuid().ToString() - }; - - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.Is(x => x == $"PartitionKey eq '{entity.RowKey}'"), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException("test")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - - // Act - var act = () => deviceModelCommandsService.PostDeviceModelCommands(entity.RowKey, new[] { command }); - - // Assert - _ = await act.Should().ThrowAsync(); - this.mockRepository.VerifyAll(); + this.loRaWanCommandService = Services.GetRequiredService(); } [Test] - public async Task PostShouldThrowInternalServerErrorExceptionWhenFailDeletingExistingCommands() + public async Task PostShouldCreateCommandShouldDeleteExistingModelCommandsAndCreateNewModelCommands() { // Arrange - var deviceModelCommandsService = CreateDeviceModelCommandsService(); - - var mockResponseTableEntity = this.mockRepository.Create>(); - var mockResponse = this.mockRepository.Create(); - var modelId = Guid.NewGuid().ToString(); - var entity = new TableEntity(LoRaWANDeviceModelsController.DefaultPartitionKey, modelId); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == modelId), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockResponseTableEntity.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - var command = new DeviceModelCommand - { - Name = Guid.NewGuid().ToString() - }; - - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.Is(x => x == $"PartitionKey eq '{entity.RowKey}'"), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(Pageable.FromPages(new[] + var deviceModel = Fixture.Create(); + var existingCommands = Fixture.CreateMany(2) + .Select(command => { - Page.FromValues(new[] - { - new TableEntity(entity.RowKey, Guid.NewGuid().ToString()) - }, null, mockResponse.Object) - })); - - _ = this.mockCommandsTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(x => x == entity.RowKey), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .ThrowsAsync(new RequestFailedException("test")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - - // Act - var act = () => deviceModelCommandsService.PostDeviceModelCommands(entity.RowKey, new[] { command }); - - // Assert - _ = await act.Should().ThrowAsync(); - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task PostShouldThrowInternalServerErrorExceptionWhenFailAddingNewCommands() - { - // Arrange - var deviceModelCommandsService = CreateDeviceModelCommandsService(); - - var mockResponseTableEntity = this.mockRepository.Create>(); - var mockResponse = this.mockRepository.Create(); - var modelId = Guid.NewGuid().ToString(); - var entity = new TableEntity(LoRaWANDeviceModelsController.DefaultPartitionKey, modelId); + command.DeviceModelId = deviceModel.Id; + return command; + }) + .ToList(); - var command = new DeviceModelCommand - { - Name = Guid.NewGuid().ToString() - }; + var newCommands = Fixture.CreateMany(5); - _ = this.mockDeviceModelCommandMapper.Setup(c => c.UpdateTableEntity( - It.Is(x => x.RowKey == command.Name && x.PartitionKey == entity.RowKey), - It.Is(x => x == command))); + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModel.Id)) + .ReturnsAsync(deviceModel); - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == modelId), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockResponseTableEntity.Object); + _ = this.mockDeviceModelCommandRepository.Setup(repository => repository.GetAll()) + .Returns(existingCommands); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); + this.mockDeviceModelCommandRepository + .Setup(repository => repository.Delete(It.IsAny())) + .Verifiable(); - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.Is(x => x == $"PartitionKey eq '{entity.RowKey}'"), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(Pageable.FromPages(new[] - { - Page.FromValues(new[] - { - new TableEntity(entity.RowKey, Guid.NewGuid().ToString()) - }, null, mockResponse.Object) - })); + _ = this.mockDeviceModelCommandRepository + .Setup(repository => repository.InsertAsync(It.IsAny())) + .Returns(Task.CompletedTask); - _ = this.mockCommandsTableClient.Setup(c => c.DeleteEntityAsync( - It.Is(x => x == entity.RowKey), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockCommandsTableClient.Setup(c => c.AddEntityAsync( - It.Is(x => x.RowKey == command.Name && x.PartitionKey == entity.RowKey), - It.IsAny())) - .ThrowsAsync(new RequestFailedException("test")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); // Act - var act = () => deviceModelCommandsService.PostDeviceModelCommands(entity.RowKey, new[] { command }); + await this.loRaWanCommandService.PostDeviceModelCommands(deviceModel.Id, newCommands.ToArray()); // Assert - _ = await act.Should().ThrowAsync(); - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] - public async Task PostShouldThrowInternalServerErrorExceptionWhenModelDoesNotExist() + public async Task PostShouldCreateCommandShouldThrowInternalServerErrorExceptionWhenDDbUpdateExceptionIsThrown() { // Arrange - var deviceModelCommandsService = CreateDeviceModelCommandsService(); + var deviceModel = Fixture.Create(); + var commands = Fixture.CreateMany(5); - SetupNotFoundDeviceModel(); + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModel.Id)) + .ReturnsAsync(deviceModel); - // Act - var act = () => deviceModelCommandsService.PostDeviceModelCommands(Guid.NewGuid().ToString(), new[] { new DeviceModelCommand() }); + _ = this.mockDeviceModelCommandRepository.Setup(repository => repository.GetAll()) + .Returns(Array.Empty()); - // Assert - _ = await act.Should().ThrowAsync(); + _ = this.mockDeviceModelCommandRepository + .Setup(repository => repository.InsertAsync(It.IsAny())) + .Returns(Task.CompletedTask); - this.mockRepository.VerifyAll(); - } - - [Test] - public async Task GetShouldThrowInternalServerErrorExceptionWhenModelDoesNotExist() - { - // Arrange - var deviceModelCommandsService = CreateDeviceModelCommandsService(); - - SetupNotFoundDeviceModel(); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .ThrowsAsync(new DbUpdateException()); // Act - var act = () => deviceModelCommandsService.GetDeviceModelCommandsFromModel(Guid.NewGuid().ToString()); + var act = () => this.loRaWanCommandService.PostDeviceModelCommands(deviceModel.Id, commands.ToArray()); // Assert _ = await act.Should().ThrowAsync(); - - this.mockRepository.VerifyAll(); + MockRepository.VerifyAll(); } [Test] public async Task GetShouldReturnDeviceModelCommands() { // Arrange - var deviceModel = SetupMockDeviceModel(); - var deviceModelId = deviceModel.RowKey; - var deviceModelCommandsService = CreateDeviceModelCommandsService(); - var mockResponse = this.mockRepository.Create(); - - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.Is(x => x == $"PartitionKey eq '{deviceModelId}'"), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Returns(Pageable.FromPages(new[] - { - Page.FromValues(new[] - { - new TableEntity(deviceModelId, Guid.NewGuid().ToString()) - }, null, mockResponse.Object) - })); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); - - _ = this.mockDeviceModelCommandMapper.Setup(c => c.GetDeviceModelCommand( - It.Is(x => x.PartitionKey == deviceModelId))) - .Returns(new DeviceModelCommand()); - - // Act - var result = await deviceModelCommandsService.GetDeviceModelCommandsFromModel(deviceModelId); - - // Assert - Assert.IsAssignableFrom(result); - Assert.IsNotNull(result); - Assert.AreEqual(1, result.Length); - } - - [Test] - public async Task GetShouldThrowRequestFailedExceptionWhenIssueOccursWhenQueryingCommands() - { - // Arrange - var mockResponse = this.mockRepository.Create>(); - var deviceModelId = Guid.NewGuid().ToString(); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == deviceModelId), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - var deviceModelCommandsService = CreateDeviceModelCommandsService(); - - _ = this.mockCommandsTableClient.Setup(c => c.Query( - It.Is(x => x == $"PartitionKey eq '{deviceModelId}'"), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException("test")); + var deviceModel = Fixture.Create(); + var commands = Fixture.CreateMany(5).Select(command => + { + command.DeviceModelId = deviceModel.Id; + return command; + }) .ToList(); + var expectedCommands = commands.Select(command => Mapper.Map(command)).ToArray(); - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - .Returns(this.mockCommandsTableClient.Object); + _ = this.mockDeviceModelCommandRepository.Setup(repository => repository.GetAll()) + .Returns(commands); // Act - var act = () => deviceModelCommandsService.GetDeviceModelCommandsFromModel(deviceModelId); + var result = await this.loRaWanCommandService.GetDeviceModelCommandsFromModel(deviceModel.Id); // Assert - _ = await act.Should().ThrowAsync(); - this.mockRepository.VerifyAll(); - } - - private TableEntity SetupMockDeviceModel() - { - var mockResponse = this.mockRepository.Create>(); - var modelId = Guid.NewGuid().ToString(); - var entity = new TableEntity(LoRaWANDeviceModelsController.DefaultPartitionKey, modelId); - - _ = mockResponse.Setup(c => c.Value) - .Returns(entity); - - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.Is(k => k == modelId), - It.IsAny>(), - It.IsAny())) - .ReturnsAsync(mockResponse.Object); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - - return entity; - } - - private void SetupNotFoundDeviceModel() - { - _ = this.mockDeviceTemplatesTableClient.Setup(c => c.GetEntityAsync( - It.Is(p => p == LoRaWANDeviceModelsController.DefaultPartitionKey), - It.IsAny(), - It.IsAny>(), - It.IsAny())) - .Throws(new RequestFailedException(StatusCodes.Status404NotFound, "Not Found")); - - _ = this.mockTableClientFactory.Setup(c => c.GetDeviceTemplates()) - .Returns(this.mockDeviceTemplatesTableClient.Object); - } - - private LoRaWANCommandService CreateDeviceModelCommandsService() - { - return new LoRaWANCommandService( - this.mockLogger.Object, - this.mockDeviceModelCommandMapper.Object, - this.mockTableClientFactory.Object); + _ = result.Should().BeEquivalentTo(expectedCommands); + MockRepository.VerifyAll(); } } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANDeviceServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANDeviceServiceTests.cs index 65b4fe321..a447e6eec 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANDeviceServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANDeviceServiceTests.cs @@ -77,7 +77,7 @@ public async Task ExecuteCommandStateUnderTestExpectedBehavior() var mockResponse = this.mockRepository.Create(); _ = this.mockDeviceModelCommandMapper .Setup(c => c.GetDeviceModelCommand(It.Is(x => x.RowKey == commandId && x.PartitionKey == modelId))) - .Returns(new DeviceModelCommand + .Returns(new DeviceModelCommandDto { Name = commandId, Frame = Guid.NewGuid().ToString(), @@ -104,7 +104,7 @@ public async Task ExecuteCommandStateUnderTestExpectedBehavior() _ = this.mockLoraDeviceMethodManager.Setup(c => c.ExecuteLoRaDeviceMessage( It.Is(x => x == deviceId), - It.Is(x => x.Name == commandId))) + It.Is(x => x.Name == commandId))) .ReturnsAsync(success); _ = this.mockLogger.Setup(c => c.Log( @@ -233,7 +233,7 @@ public void ExecuteCommandFailedShouldThrowInternalServerErrorException() var mockResponse = this.mockRepository.Create(); _ = this.mockDeviceModelCommandMapper .Setup(c => c.GetDeviceModelCommand(It.Is(x => x.RowKey == commandId && x.PartitionKey == modelId))) - .Returns(new DeviceModelCommand + .Returns(new DeviceModelCommandDto { Name = commandId, Frame = Guid.NewGuid().ToString(), @@ -260,7 +260,7 @@ public void ExecuteCommandFailedShouldThrowInternalServerErrorException() _ = this.mockLoraDeviceMethodManager.Setup(c => c.ExecuteLoRaDeviceMessage( It.Is(x => x == deviceId), - It.Is(x => x.Name == commandId))) + It.Is(x => x.Name == commandId))) .ReturnsAsync(internalServerError); _ = this.mockLogger.Setup(c => c.Log( diff --git a/src/AzureIoTHub.Portal.Tests.Unit/UnitTests/Bases/BackendUnitTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/UnitTests/Bases/BackendUnitTest.cs index b34bc4137..0948fa51c 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/UnitTests/Bases/BackendUnitTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/UnitTests/Bases/BackendUnitTest.cs @@ -51,6 +51,8 @@ public virtual void Setup() var mappingConfig = new MapperConfiguration(mc => { mc.AddProfile(new DeviceTagProfile()); + mc.AddProfile(new DeviceModelProfile()); + mc.AddProfile(new DeviceModelCommandProfile()); }); Mapper = mappingConfig.CreateMapper(); _ = ServiceCollection.AddSingleton(Mapper); diff --git a/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPage.razor b/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPage.razor index 4cec0974c..6eebbd63f 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/CreateDeviceConfigurationsPage.razor @@ -28,7 +28,7 @@ Select a device model to configure. - AvailableTags { get; set; } = Array.Empty(); IEnumerable AvailableProperties = Array.Empty(); - IEnumerable AvailableModels = Array.Empty(); + IEnumerable AvailableModels = Array.Empty(); public string SelectedTag { get; set; } public string SelectedProperty { get; set; } @@ -280,7 +280,7 @@ } } - public async Task SelectModel(DeviceModel model) + public async Task SelectModel(DeviceModelDto model) { if (model == null) { @@ -303,7 +303,7 @@ /// /// Text entered in the field /// Item of the device model list that matches the user's value - private async Task> Search(string value) + private async Task> Search(string value) { // In real life use an asynchronous function for fetching data from an api. await Task.Delay(0); diff --git a/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPage.razor b/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPage.razor index 9f4247a8a..a5cd356cd 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/DeviceConfigurations/DeviceConfigurationDetailPage.razor @@ -231,7 +231,7 @@ public string ConfigId { get; set; } public DeviceConfig Configuration { get; set; } = new(); - public DeviceModel DeviceModel { get; set; } = new(); + public DeviceModelDto DeviceModel { get; set; } = new(); private ConfigurationMetrics Metrics { get; set; } = new(); private void Return() => navigationManager.NavigateTo("/device-configurations"); diff --git a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/CreateDeviceModelPage.razor b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/CreateDeviceModelPage.razor index ceacf4c19..ab9510c67 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/CreateDeviceModelPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/CreateDeviceModelPage.razor @@ -150,7 +150,7 @@ @if (IsLoRa) { - } @@ -168,7 +168,7 @@ private DeviceModelValidator standardValidator = new DeviceModelValidator(); private LoRaDeviceModelValidator loraValidator = new LoRaDeviceModelValidator(); private DevicePropertyValidator propertiesValidator = new DevicePropertyValidator(); - private List Commands { get; set; } + private List Commands { get; set; } private List Properties { get; set; } = new List(); private LoRaDeviceModelCommandValidator CommandValidator = new LoRaDeviceModelCommandValidator(); @@ -179,7 +179,7 @@ { get { - return this.Model is LoRaDeviceModel; + return this.Model is LoRaDeviceModelDto; } set { @@ -195,13 +195,13 @@ private void SetLoRaDeviceModel() { - Model = new LoRaDeviceModel(Model); - Commands = new List(); + Model = new LoRaDeviceModelDto(Model); + Commands = new List(); } private void SetStandardDeviceModel() { - Model = new DeviceModel + Model = new DeviceModelDto { ModelId = Model.ModelId, Name = Model.Name, @@ -210,7 +210,7 @@ }; } - internal IDeviceModel Model { get; set; } = new DeviceModel + internal IDeviceModel Model { get; set; } = new DeviceModelDto { ModelId = Guid.NewGuid().ToString() }; @@ -221,7 +221,7 @@ private bool CheckLoRaValidation() { - if (IsLoRa && this.Model is LoRaDeviceModel loRaDeviceModel) + if (IsLoRa && this.Model is LoRaDeviceModelDto loRaDeviceModel) { return !this.loraValidator.Validate(loRaDeviceModel).IsValid; } @@ -231,7 +231,7 @@ private bool CheckGeneralValidation() { - if (!IsLoRa && this.Model is DeviceModel deviceModel) + if (!IsLoRa && this.Model is DeviceModelDto deviceModel) { return !this.standardValidator.Validate(deviceModel).IsValid; } @@ -296,8 +296,8 @@ } } - if (!IsLoRa ? !standardValidator.Validate(Model as DeviceModel).IsValid : - (!this.loraValidator.Validate(this.Model as LoRaDeviceModel).IsValid + if (!IsLoRa ? !standardValidator.Validate(Model as DeviceModelDto).IsValid : + (!this.loraValidator.Validate(this.Model as LoRaDeviceModelDto).IsValid || duplicated || cmdValidationError)) { @@ -312,13 +312,13 @@ { if (IsLoRa) { - await LoRaWanDeviceModelsClientService.CreateDeviceModel(Model as LoRaDeviceModel); + await LoRaWanDeviceModelsClientService.CreateDeviceModel(Model as LoRaDeviceModelDto); await LoRaWanDeviceModelsClientService.SetDeviceModelCommands(Model.ModelId, Commands); } else { - await DeviceModelsClientService.CreateDeviceModel(Model as DeviceModel); + await DeviceModelsClientService.CreateDeviceModel(Model as DeviceModelDto); await DeviceModelsClientService.SetDeviceModelModelProperties(Model.ModelId, Properties); } diff --git a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/DeviceModelDetailPage.razor b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/DeviceModelDetailPage.razor index bc8ded96d..d90de79bf 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/DeviceModelDetailPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/DeviceModelDetailPage.razor @@ -139,7 +139,7 @@ @if (IsLoRa) { - } @@ -165,7 +165,7 @@ private LoRaDeviceModelValidator loraValidator = new LoRaDeviceModelValidator(); private DevicePropertyValidator propertiesValidator = new DevicePropertyValidator(); - private List Commands { get; set; } = new List(); + private List Commands { get; set; } = new List(); private List Properties { get; set; } = new List(); private LoRaDeviceModelCommandValidator CommandValidator = new LoRaDeviceModelCommandValidator(); @@ -176,7 +176,7 @@ { get { - return this.Model is LoRaDeviceModel; + return this.Model is LoRaDeviceModelDto; } set { @@ -190,9 +190,9 @@ } } - private void SetLoRaDeviceModel() => Model = new LoRaDeviceModel(Model); + private void SetLoRaDeviceModel() => Model = new LoRaDeviceModelDto(Model); - private void SetStandardDeviceModel() => Model = new DeviceModel + private void SetStandardDeviceModel() => Model = new DeviceModelDto { ModelId = Model.ModelId, Name = Model.Name, @@ -200,7 +200,7 @@ Description = Model.Description }; - private IDeviceModel Model { get; set; } = new DeviceModel + private IDeviceModel Model { get; set; } = new DeviceModelDto { ModelId = Guid.NewGuid().ToString() }; @@ -211,7 +211,7 @@ private bool CheckLoRaValidation() { - if (IsLoRa && this.Model is LoRaDeviceModel loRaDeviceModel) + if (IsLoRa && this.Model is LoRaDeviceModelDto loRaDeviceModel) { return !this.loraValidator.Validate(loRaDeviceModel).IsValid; } @@ -221,7 +221,7 @@ private bool CheckGeneralValidation() { - if (!IsLoRa && this.Model is DeviceModel deviceModel) + if (!IsLoRa && this.Model is DeviceModelDto deviceModel) { return !this.standardValidator.Validate(deviceModel).IsValid; } @@ -312,8 +312,8 @@ } } - if (!IsLoRa ? !standardValidator.Validate(Model as DeviceModel).IsValid : - (!this.loraValidator.Validate(this.Model as LoRaDeviceModel).IsValid + if (!IsLoRa ? !standardValidator.Validate(Model as DeviceModelDto).IsValid : + (!this.loraValidator.Validate(this.Model as LoRaDeviceModelDto).IsValid || duplicated || cmdValidationError)) { @@ -332,13 +332,13 @@ { if (IsLoRa) { - await LoRaWanDeviceModelsClientService.UpdateDeviceModel(Model as LoRaDeviceModel); + await LoRaWanDeviceModelsClientService.UpdateDeviceModel(Model as LoRaDeviceModelDto); await LoRaWanDeviceModelsClientService.SetDeviceModelCommands(Model.ModelId, Commands); } else { - await DeviceModelsClientService.UpdateDeviceModel(Model as DeviceModel); + await DeviceModelsClientService.UpdateDeviceModel(Model as DeviceModelDto); await DeviceModelsClientService.SetDeviceModelModelProperties(Model.ModelId, Properties); } diff --git a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/DeviceModelListPage.razor b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/DeviceModelListPage.razor index e8b6e4ff6..0400606a2 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/DeviceModelListPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/DeviceModelListPage.razor @@ -9,7 +9,7 @@ - + @@ -74,7 +74,7 @@ public Error Error { get; set; } private int[] pageSizeOptions = new int[] { 2, 5, 10 }; - private List result = new(); + private List result = new(); private bool IsLoading = true; protected override async Task OnInitializedAsync() @@ -105,7 +105,7 @@ } } - private async Task DeleteDeviceModel(DeviceModel deviceModel) + private async Task DeleteDeviceModel(DeviceModelDto deviceModel) { var parameters = new DialogParameters(); parameters.Add("deviceModelID", deviceModel.ModelId); @@ -121,7 +121,7 @@ await LoadDeviceModels(); } - private void GoToDetails(DeviceModel item) + private void GoToDetails(DeviceModelDto item) { navigationManager.NavigateTo($"/device-models/{item.ModelId}{((item.SupportLoRaFeatures && Portal.IsLoRaSupported) ? "?isLora=true" : "")}"); } diff --git a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/LoRaWAN/CreateLoraDeviceModel.razor b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/LoRaWAN/CreateLoraDeviceModel.razor index 410022e4e..43d7f0d81 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/LoRaWAN/CreateLoraDeviceModel.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/LoRaWAN/CreateLoraDeviceModel.razor @@ -147,10 +147,10 @@ - + - + @@ -176,14 +176,14 @@ @code { [Parameter] - public LoRaDeviceModel LoRaDeviceModel { get; set; } + public LoRaDeviceModelDto LoRaDeviceModel { get; set; } [Parameter] - public IList Commands { get; set; } + public IList Commands { get; set; } private bool loraProperty { get; set; } - private DeviceModelCommand DeviceModelCommand { get; set; } = new DeviceModelCommand(); + private DeviceModelCommandDto DeviceModelCommandDto { get; set; } = new DeviceModelCommandDto(); private void AddCommand() { @@ -191,11 +191,11 @@ if (Commands.Count == 0 || (last.Name is not null && last.Frame is not null)) { - Commands.Add(new DeviceModelCommand()); + Commands.Add(new DeviceModelCommandDto()); } } - private void DeleteCommand(DeviceModelCommand item) + private void DeleteCommand(DeviceModelCommandDto item) { Commands.Remove(item); } diff --git a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/LoRaWAN/EditLoraDeviceModel.razor b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/LoRaWAN/EditLoraDeviceModel.razor index c64130ccd..e623a101e 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/LoRaWAN/EditLoraDeviceModel.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/DeviceModels/LoRaWAN/EditLoraDeviceModel.razor @@ -179,12 +179,12 @@ @code { [Parameter] - public LoRaDeviceModel LoRaDeviceModel { get; set; } + public LoRaDeviceModelDto LoRaDeviceModel { get; set; } [Parameter] - public IList Commands { get; set; } + public IList Commands { get; set; } - private DeviceModelCommand DeviceModelCommand { get; set; } = new DeviceModelCommand(); + private DeviceModelCommandDto DeviceModelCommandDto { get; set; } = new DeviceModelCommandDto(); protected override Task OnInitializedAsync() { @@ -197,11 +197,11 @@ if (Commands.Count == 0 || (last.Name is not null && last.Frame is not null)) { - Commands.Add(new DeviceModelCommand()); + Commands.Add(new DeviceModelCommandDto()); } } - private void DeleteCommand(DeviceModelCommand item) + private void DeleteCommand(DeviceModelCommandDto item) { Commands.Remove(item); } diff --git a/src/AzureIoTHub.Portal/Client/Pages/Devices/CreateDevicePage.razor b/src/AzureIoTHub.Portal/Client/Pages/Devices/CreateDevicePage.razor index 6c1353c59..938efb297 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/Devices/CreateDevicePage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/Devices/CreateDevicePage.razor @@ -235,7 +235,7 @@ @if (IsLoRa) { - + } @@ -253,7 +253,7 @@ private DeviceDetailsValidator standardValidator = new DeviceDetailsValidator(); private LoRaDeviceDetailsValidator loraValidator = new LoRaDeviceDetailsValidator(); - private LoRaDeviceModel loRaDeviceModel { get; set; } + private LoRaDeviceModelDto LoRaDeviceModelDto { get; set; } private bool IsLoRa { @@ -323,7 +323,7 @@ public void Dispose() { DeviceLayoutService.ResetSharedDevice(); - DeviceLayoutService.ResetSharedDeviceModel(); + DeviceLayoutService.ResetSharedDeviceModel(); DeviceLayoutService.RefreshDeviceOccurred -= DeviceServiceOnRefreshDeviceOccurred; } @@ -382,7 +382,7 @@ break; case DeviceSaveAction.SaveAndAddNew: Device = DeviceLayoutService.ResetSharedDevice(TagList.ToList()); - DeviceModel = DeviceLayoutService.ResetSharedDeviceModel(); + DeviceModel = DeviceLayoutService.ResetSharedDeviceModel(); break; case DeviceSaveAction.SaveAndDuplicate: Device = DeviceLayoutService.DuplicateSharedDevice(Device as DeviceDetails); @@ -506,7 +506,7 @@ UseOTAA = loRaDeviceModelResult.UseOTAA }; - loRaDeviceModel = loRaDeviceModelResult; + LoRaDeviceModelDto = loRaDeviceModelResult; } else { diff --git a/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceDetailPage.razor b/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceDetailPage.razor index 3f98a3b40..9cdabc163 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceDetailPage.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceDetailPage.razor @@ -202,7 +202,7 @@ @if (IsLoRa && Device != null && Commands != null) { - + } @@ -231,7 +231,7 @@ private IDeviceDetails Device { get; set; } = new DeviceDetails(); - private IDeviceModel DeviceModel { get; set; } = new DeviceModel(); + private IDeviceModel DeviceModel { get; set; } = new DeviceModelDto(); private bool isLoaded = false; @@ -242,7 +242,7 @@ private void Return() => NavManager.NavigateTo("devices"); - private IEnumerable Commands { get; set; } + private IEnumerable Commands { get; set; } private IEnumerable TagList { get; set; } = Array.Empty(); diff --git a/src/AzureIoTHub.Portal/Client/Pages/Devices/LoRaWAN/CreateLoraDevice.razor b/src/AzureIoTHub.Portal/Client/Pages/Devices/LoRaWAN/CreateLoraDevice.razor index 23f4ff0c3..3acb7b778 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/Devices/LoRaWAN/CreateLoraDevice.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/Devices/LoRaWAN/CreateLoraDevice.razor @@ -9,7 +9,7 @@ LoraWAN - @if (loraModel.UseOTAA) + @if (LoraModelDto.UseOTAA) { - @if (LoRaDeviceModel.UseOTAA) + @if (LoRaDeviceModelDto.UseOTAA) { @@ -166,14 +166,14 @@ public LoRaDeviceDetailsValidator LoraValidator { get; set; } [Parameter] - public LoRaDeviceModel LoRaDeviceModel { get; set; } + public LoRaDeviceModelDto LoRaDeviceModelDto { get; set; } [Parameter] - public IEnumerable Commands { get; set; } + public IEnumerable Commands { get; set; } private bool isProcessing; - private async Task ExecuteMethod(DeviceModelCommand method) + private async Task ExecuteMethod(DeviceModelCommandDto method) { try { diff --git a/src/AzureIoTHub.Portal/Client/Services/DeviceModelsClientService.cs b/src/AzureIoTHub.Portal/Client/Services/DeviceModelsClientService.cs index 6731f837b..10ef6db79 100644 --- a/src/AzureIoTHub.Portal/Client/Services/DeviceModelsClientService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/DeviceModelsClientService.cs @@ -18,22 +18,22 @@ public DeviceModelsClientService(HttpClient http) this.http = http; } - public async Task> GetDeviceModels() + public async Task> GetDeviceModels() { - return await this.http.GetFromJsonAsync>("api/models"); + return await this.http.GetFromJsonAsync>("api/models"); } - public Task GetDeviceModel(string deviceModelId) + public Task GetDeviceModel(string deviceModelId) { - return this.http.GetFromJsonAsync($"api/models/{deviceModelId}"); + return this.http.GetFromJsonAsync($"api/models/{deviceModelId}"); } - public Task CreateDeviceModel(DeviceModel deviceModel) + public Task CreateDeviceModel(DeviceModelDto deviceModel) { return this.http.PostAsJsonAsync("api/models", deviceModel); } - public Task UpdateDeviceModel(DeviceModel deviceModel) + public Task UpdateDeviceModel(DeviceModelDto deviceModel) { return this.http.PutAsJsonAsync($"api/models/{deviceModel.ModelId}", deviceModel); } diff --git a/src/AzureIoTHub.Portal/Client/Services/IDeviceModelsClientService.cs b/src/AzureIoTHub.Portal/Client/Services/IDeviceModelsClientService.cs index aadd5abe8..939242b3f 100644 --- a/src/AzureIoTHub.Portal/Client/Services/IDeviceModelsClientService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/IDeviceModelsClientService.cs @@ -10,13 +10,13 @@ namespace AzureIoTHub.Portal.Client.Services public interface IDeviceModelsClientService { - Task> GetDeviceModels(); + Task> GetDeviceModels(); - Task GetDeviceModel(string deviceModelId); + Task GetDeviceModel(string deviceModelId); - Task CreateDeviceModel(DeviceModel deviceModel); + Task CreateDeviceModel(DeviceModelDto deviceModel); - Task UpdateDeviceModel(DeviceModel deviceModel); + Task UpdateDeviceModel(DeviceModelDto deviceModel); Task DeleteDeviceModel(string deviceModelId); diff --git a/src/AzureIoTHub.Portal/Client/Services/ILoRaWanDeviceModelsClientService.cs b/src/AzureIoTHub.Portal/Client/Services/ILoRaWanDeviceModelsClientService.cs index e2733a6cd..1451eaa43 100644 --- a/src/AzureIoTHub.Portal/Client/Services/ILoRaWanDeviceModelsClientService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/ILoRaWanDeviceModelsClientService.cs @@ -10,15 +10,15 @@ namespace AzureIoTHub.Portal.Client.Services public interface ILoRaWanDeviceModelsClientService { - Task GetDeviceModel(string deviceModelId); + Task GetDeviceModel(string deviceModelId); - Task CreateDeviceModel(LoRaDeviceModel deviceModel); + Task CreateDeviceModel(LoRaDeviceModelDto deviceModelDto); - Task UpdateDeviceModel(LoRaDeviceModel deviceModel); + Task UpdateDeviceModel(LoRaDeviceModelDto deviceModelDto); - Task SetDeviceModelCommands(string deviceModelId, IList commands); + Task SetDeviceModelCommands(string deviceModelId, IList commands); - Task> GetDeviceModelCommands(string deviceModelId); + Task> GetDeviceModelCommands(string deviceModelId); Task GetAvatarUrl(string deviceModelId); diff --git a/src/AzureIoTHub.Portal/Client/Services/LoRaWanDeviceModelsClientService.cs b/src/AzureIoTHub.Portal/Client/Services/LoRaWanDeviceModelsClientService.cs index 235efebc1..3306ae0e7 100644 --- a/src/AzureIoTHub.Portal/Client/Services/LoRaWanDeviceModelsClientService.cs +++ b/src/AzureIoTHub.Portal/Client/Services/LoRaWanDeviceModelsClientService.cs @@ -18,29 +18,29 @@ public LoRaWanDeviceModelsClientService(HttpClient http) this.http = http; } - public Task GetDeviceModel(string deviceModelId) + public Task GetDeviceModel(string deviceModelId) { - return this.http.GetFromJsonAsync($"api/lorawan/models/{deviceModelId}"); + return this.http.GetFromJsonAsync($"api/lorawan/models/{deviceModelId}"); } - public Task CreateDeviceModel(LoRaDeviceModel deviceModel) + public Task CreateDeviceModel(LoRaDeviceModelDto deviceModelDto) { - return this.http.PostAsJsonAsync("api/lorawan/models", deviceModel); + return this.http.PostAsJsonAsync("api/lorawan/models", deviceModelDto); } - public Task UpdateDeviceModel(LoRaDeviceModel deviceModel) + public Task UpdateDeviceModel(LoRaDeviceModelDto deviceModelDto) { - return this.http.PutAsJsonAsync($"api/lorawan/models/{deviceModel.ModelId}", deviceModel); + return this.http.PutAsJsonAsync($"api/lorawan/models/{deviceModelDto.ModelId}", deviceModelDto); } - public Task SetDeviceModelCommands(string deviceModelId, IList commands) + public Task SetDeviceModelCommands(string deviceModelId, IList commands) { return this.http.PostAsJsonAsync($"api/lorawan/models/{deviceModelId}/commands", commands); } - public async Task> GetDeviceModelCommands(string deviceModelId) + public async Task> GetDeviceModelCommands(string deviceModelId) { - return await this.http.GetFromJsonAsync>($"api/lorawan/models/{deviceModelId}/commands"); + return await this.http.GetFromJsonAsync>($"api/lorawan/models/{deviceModelId}/commands"); } public Task GetAvatarUrl(string deviceModelId) diff --git a/src/AzureIoTHub.Portal/Client/Validators/DeviceModelValidator.cs b/src/AzureIoTHub.Portal/Client/Validators/DeviceModelValidator.cs index b22f17fdc..f038ed4b4 100644 --- a/src/AzureIoTHub.Portal/Client/Validators/DeviceModelValidator.cs +++ b/src/AzureIoTHub.Portal/Client/Validators/DeviceModelValidator.cs @@ -6,7 +6,7 @@ namespace AzureIoTHub.Portal.Client.Validators using AzureIoTHub.Portal.Models.v10; using FluentValidation; - public class DeviceModelValidator : AbstractValidator + public class DeviceModelValidator : AbstractValidator { public DeviceModelValidator() { diff --git a/src/AzureIoTHub.Portal/Client/Validators/LoRaDeviceModelCommandValidator.cs b/src/AzureIoTHub.Portal/Client/Validators/LoRaDeviceModelCommandValidator.cs index 9cd49895d..62ee24506 100644 --- a/src/AzureIoTHub.Portal/Client/Validators/LoRaDeviceModelCommandValidator.cs +++ b/src/AzureIoTHub.Portal/Client/Validators/LoRaDeviceModelCommandValidator.cs @@ -10,7 +10,7 @@ namespace AzureIoTHub.Portal.Client.Validators using AzureIoTHub.Portal.Models.v10.LoRaWAN; using FluentValidation; - public class LoRaDeviceModelCommandValidator : AbstractValidator + public class LoRaDeviceModelCommandValidator : AbstractValidator { public LoRaDeviceModelCommandValidator() { diff --git a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceModelControllerBase.cs b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceModelControllerBase.cs index 7543fecff..4f0680229 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceModelControllerBase.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceModelControllerBase.cs @@ -3,22 +3,12 @@ namespace AzureIoTHub.Portal.Server.Controllers.V10 { - using System; 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.Server.Helpers; - using AzureIoTHub.Portal.Server.Managers; - using AzureIoTHub.Portal.Server.Services; + using Services; using AzureIoTHub.Portal.Shared.Models; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; - using Microsoft.Azure.Devices.Shared; - using Microsoft.Extensions.Logging; public abstract class DeviceModelsControllerBase : ControllerBase where TListItemModel : class, IDeviceModel @@ -31,100 +21,24 @@ public abstract class DeviceModelsControllerBase : Contr public const string DefaultPartitionKey = "0"; #pragma warning restore RCS1158 // Static member in generic type should use a type parameter. - /// - /// The logger. - /// - private readonly ILogger log; - - /// - /// The table client factory. - /// - private readonly ITableClientFactory tableClientFactory; - - /// - /// The device model mapper. - /// - private readonly IDeviceModelMapper deviceModelMapper; - - /// - /// The device model image manager. - /// - private readonly IDeviceModelImageManager deviceModelImageManager; - - /// - /// The devices service. - /// - private readonly IDeviceService devicesService; - - /// - /// The device provisioning service manager. - /// - private readonly IDeviceProvisioningServiceManager deviceProvisioningServiceManager; - - /// - /// The configuration service. - /// - private readonly IConfigService configService; - - /// - /// The device template filter. - /// - private readonly string filter; + private readonly IDeviceModelService deviceModelService; /// /// Initializes a new instance of the class. /// - /// The logger. - /// The device model image manager. - /// The device model mapper. - /// The devices service. - /// The table client factory. - /// The device provisioning service manager. - /// The configuration service. - /// The device template filter query string. - protected DeviceModelsControllerBase( - ILogger log, - IDeviceModelImageManager deviceModelImageManager, - IDeviceModelMapper deviceModelMapper, - IDeviceService devicesService, - ITableClientFactory tableClientFactory, - IDeviceProvisioningServiceManager deviceProvisioningServiceManager, - IConfigService configService, - string filter) + /// + protected DeviceModelsControllerBase(IDeviceModelService deviceModelService) { - this.log = log; - this.deviceModelMapper = deviceModelMapper; - this.tableClientFactory = tableClientFactory; - this.deviceModelImageManager = deviceModelImageManager; - this.devicesService = devicesService; - this.filter = filter; - this.deviceProvisioningServiceManager = deviceProvisioningServiceManager; - this.configService = configService; + this.deviceModelService = deviceModelService; } /// /// Gets the device models. /// /// The list of device models. - public virtual ActionResult> GetItems() + public virtual async Task>> GetItems() { - Pageable entities; - try - { - // PartitionKey 0 contains all device models - entities = this.tableClientFactory - .GetDeviceTemplates() - .Query(this.filter); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException("Unable to get device models.", e); - } - - // Converts the query result into a list of device models - var deviceModelList = entities.Select(this.deviceModelMapper.CreateDeviceModelListItem); - - return Ok(deviceModelList.ToArray()); + return Ok(await this.deviceModelService.GetDeviceModels()); } /// @@ -134,25 +48,7 @@ public virtual ActionResult> GetItems() /// The corresponding model. public virtual async Task> GetItem(string id) { - try - { - var query = await this.tableClientFactory - .GetDeviceTemplates() - .GetEntityAsync(DefaultPartitionKey, id); - - return Ok(this.deviceModelMapper.CreateDeviceModel(query.Value)); - } - catch (RequestFailedException e) - { - if (e.Status == StatusCodes.Status404NotFound) - { - return NotFound(); - } - - this.log.Log(LogLevel.Error, e.Message, e); - - throw new InternalServerErrorException($"Unable to get the device model with the id: {id}", e); - } + return await this.deviceModelService.GetDeviceModel(id); } /// @@ -162,25 +58,7 @@ public virtual async Task> GetItem(string id) /// The avatar. public virtual async Task> GetAvatar(string id) { - try - { - _ = await this.tableClientFactory - .GetDeviceTemplates() - .GetEntityAsync(DefaultPartitionKey, id); - - return this.Ok(this.deviceModelImageManager.ComputeImageUri(id).ToString()); - } - catch (RequestFailedException e) - { - if (e.Status == StatusCodes.Status404NotFound) - { - return NotFound(); - } - - this.log.Log(LogLevel.Error, e.Message, e); - - throw new InternalServerErrorException("Unable to get the device model avatar.", e); - } + return Ok(await this.deviceModelService.GetDeviceModelAvatar(id)); } /// @@ -191,25 +69,7 @@ public virtual async Task> GetAvatar(string id) /// The avatar. public virtual async Task> ChangeAvatar(string id, IFormFile file) { - try - { - _ = await this.tableClientFactory - .GetDeviceTemplates() - .GetEntityAsync(DefaultPartitionKey, id); - - return Ok(await this.deviceModelImageManager.ChangeDeviceModelImageAsync(id, file?.OpenReadStream())); - } - catch (RequestFailedException e) - { - if (e.Status == StatusCodes.Status404NotFound) - { - return NotFound(); - } - - this.log.Log(LogLevel.Error, e.Message, e); - - throw new InternalServerErrorException($"Unable to change the device model avatar with id:{id}.", e); - } + return Ok(await this.deviceModelService.UpdateDeviceModelAvatar(id, file)); } /// @@ -218,27 +78,9 @@ public virtual async Task> ChangeAvatar(string id, IFormFil /// The model identifier. public virtual async Task DeleteAvatar(string id) { - try - { - _ = await this.tableClientFactory - .GetDeviceTemplates() - .GetEntityAsync(DefaultPartitionKey, id); - - await this.deviceModelImageManager.DeleteDeviceModelImageAsync(id); - - return NoContent(); - } - catch (RequestFailedException e) - { - if (e.Status == StatusCodes.Status404NotFound) - { - return NotFound(); - } + await this.deviceModelService.DeleteDeviceModelAvatar(id); - this.log.Log(LogLevel.Error, e.Message, e); - - throw new InternalServerErrorException($"Unable to delete avatar of the device model with the id: {id}", e); - } + return NoContent(); } /// @@ -248,34 +90,7 @@ public virtual async Task DeleteAvatar(string id) /// The action result. public virtual async Task Post(TModel deviceModel) { - if (!string.IsNullOrEmpty(deviceModel?.ModelId)) - { - try - { - _ = await this.tableClientFactory - .GetDeviceTemplates() - .GetEntityAsync(DefaultPartitionKey, deviceModel.ModelId); - - return BadRequest("Cannot create a device model with an existing id."); - } - catch (RequestFailedException e) - { - if (e.Status != StatusCodes.Status404NotFound) - { - this.log.Log(LogLevel.Error, e.Message, e); - - throw new InternalServerErrorException($"Unable create the device model with id: {deviceModel?.ModelId}.", e); - } - } - } - - var entity = new TableEntity() - { - PartitionKey = DefaultPartitionKey, - RowKey = string.IsNullOrEmpty(deviceModel.ModelId) ? Guid.NewGuid().ToString() : deviceModel.ModelId - }; - - await SaveEntity(entity, deviceModel); + await this.deviceModelService.CreateDeviceModel(deviceModel); return Ok(); } @@ -287,32 +102,7 @@ public virtual async Task Post(TModel deviceModel) /// The action result. public virtual async Task Put(TModel deviceModel) { - if (string.IsNullOrEmpty(deviceModel?.ModelId)) - { - return BadRequest("Should provide the model id."); - } - - TableEntity entity; - - try - { - entity = await this.tableClientFactory - .GetDeviceTemplates() - .GetEntityAsync(DefaultPartitionKey, deviceModel.ModelId); - } - catch (RequestFailedException e) - { - if (e.Status == StatusCodes.Status404NotFound) - { - return NotFound(); - } - - this.log.Log(LogLevel.Error, e.Message, e); - - throw new InternalServerErrorException($"Unable to update device model with id: {deviceModel?.ModelId}", e); - } - - await SaveEntity(entity, deviceModel); + await this.deviceModelService.UpdateDeviceModel(deviceModel); return Ok(); } @@ -324,103 +114,9 @@ public virtual async Task Put(TModel deviceModel) /// The action result. public virtual async Task Delete(string id) { - // we get all devices - var deviceList = await this.devicesService.GetAllDevice(); - - try - { - _ = await this.tableClientFactory - .GetDeviceTemplates() - .GetEntityAsync(DefaultPartitionKey, id); - } - catch (RequestFailedException e) - { - if (e.Status == StatusCodes.Status404NotFound) - { - return NotFound(); - } - - this.log.Log(LogLevel.Error, e.Message, e); - - throw new InternalServerErrorException("Unable to get the device model entity.", e); - } - - if (deviceList.Items.Any(x => DeviceHelper.RetrieveTagValue(x, "modelId") == id)) - { - return BadRequest("This model is already in use by a device and cannot be deleted."); - } - - TableEntity[] queryCommand; - - try - { - queryCommand = this.tableClientFactory - .GetDeviceCommands() - .Query(t => t.PartitionKey == id) - .ToArray(); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException($"Unable to get commands for the device models with id: {id}", e); - } - - - foreach (var item in queryCommand) - { - try - { - _ = await this.tableClientFactory - .GetDeviceCommands() - .DeleteEntityAsync(id, item.RowKey); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException("Unable to delete the device model command entity.", e); - } - } - - // Image deletion - await this.deviceModelImageManager.DeleteDeviceModelImageAsync(id); - - try - { - _ = await this.tableClientFactory - .GetDeviceTemplates() - .DeleteEntityAsync(DefaultPartitionKey, id); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException("Unable to delete the device model entity.", e); - } + await this.deviceModelService.DeleteDeviceModel(id); return NoContent(); } - - /// - /// Saves the entity. - /// - /// The entity. - /// The device model object. - private async Task SaveEntity(TableEntity entity, TModel deviceModelObject) - { - var desiredProperties = this.deviceModelMapper.UpdateTableEntity(entity, deviceModelObject); - - try - { - _ = await this.tableClientFactory - .GetDeviceTemplates() - .UpsertEntityAsync(entity); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException("Unable to upsert the device model entity.", e); - } - - var deviceModelTwin = new TwinCollection(); - - _ = await this.deviceProvisioningServiceManager.CreateEnrollmentGroupFromModelAsync(deviceModelObject.ModelId, deviceModelObject.Name, deviceModelTwin); - - await this.configService.RollOutDeviceModelConfiguration(deviceModelObject.ModelId, desiredProperties); - } } } diff --git a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceModelsController.cs b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceModelsController.cs index a7a700002..b4f016b53 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceModelsController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/DeviceModelsController.cs @@ -5,40 +5,25 @@ namespace AzureIoTHub.Portal.Server.Controllers.V10 { using System.Collections.Generic; using System.Threading.Tasks; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Models.v10; - using AzureIoTHub.Portal.Server.Managers; - using AzureIoTHub.Portal.Server.Services; + using Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; - using Microsoft.Extensions.Logging; [Authorize] [ApiController] [ApiVersion("1.0")] [Route("api/models")] [ApiExplorerSettings(GroupName = "Device Models")] - public class DeviceModelsController : DeviceModelsControllerBase + public class DeviceModelsController : DeviceModelsControllerBase { /// /// Initializes a new instance of the class. /// - /// The logger. - /// The device model image manager. - /// The device model mapper. - /// The devices service. - /// The table client factory. - /// The device provisioning service manager. - /// The configuration service. - public DeviceModelsController(ILogger> log, - IDeviceModelImageManager deviceModelImageManager, - IDeviceModelMapper deviceModelMapper, - IDeviceService devicesService, - ITableClientFactory tableClientFactory, - IDeviceProvisioningServiceManager deviceProvisioningServiceManager, - IConfigService configService) - : base(log, deviceModelImageManager, deviceModelMapper, devicesService, tableClientFactory, deviceProvisioningServiceManager, configService, "") + /// Device Model Service + public DeviceModelsController(IDeviceModelService deviceModelService) + : base(deviceModelService) { } @@ -48,7 +33,7 @@ public DeviceModelsController(ILoggerAn array representing the device models. [HttpGet(Name = "GET Device model list")] [ProducesResponseType(StatusCodes.Status200OK)] - public override ActionResult> GetItems() + public override Task>> GetItems() { return base.GetItems(); } @@ -61,7 +46,7 @@ public override ActionResult> GetItems() [HttpGet("{id}", Name = "GET Device model")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public override Task> GetItem(string id) + public override Task> GetItem(string id) { return base.GetItem(id); } @@ -112,7 +97,7 @@ public override Task DeleteAvatar(string id) [HttpPost(Name = "POST Create a new device model")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - public override Task Post(DeviceModel deviceModel) + public override Task Post(DeviceModelDto deviceModel) { return base.Post(deviceModel); } @@ -126,7 +111,7 @@ public override Task Post(DeviceModel deviceModel) [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public override Task Put(DeviceModel deviceModel) + public override Task Put(DeviceModelDto deviceModel) { return base.Put(deviceModel); } diff --git a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/LoRaWAN/LoRaWANCommandsController.cs b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/LoRaWAN/LoRaWANCommandsController.cs index c3b08a0ac..acdb73560 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/LoRaWAN/LoRaWANCommandsController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/LoRaWAN/LoRaWANCommandsController.cs @@ -42,7 +42,7 @@ public LoRaWANCommandsController(ILoRaWANCommandService loRaWANCommandService) /// The action result. [HttpPost(Name = "POST Set device model commands")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task Post(string id, DeviceModelCommand[] commands) + public async Task Post(string id, DeviceModelCommandDto[] commands) { ArgumentNullException.ThrowIfNull(id, nameof(id)); ArgumentNullException.ThrowIfNull(commands, nameof(commands)); @@ -59,7 +59,7 @@ public async Task Post(string id, DeviceModelCommand[] commands) /// The action result. [HttpGet(Name = "GET Device model commands")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> Get(string id) + public async Task> Get(string id) { ArgumentNullException.ThrowIfNull(id, nameof(id)); diff --git a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsController.cs b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsController.cs index f3ca5398f..cd7352613 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/v1.0/LoRaWAN/LoRaWANDeviceModelsController.cs @@ -4,17 +4,15 @@ namespace AzureIoTHub.Portal.Server.Controllers.V10.LoRaWAN { using System.Collections.Generic; + using System.Linq; using System.Threading.Tasks; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Models.v10; using AzureIoTHub.Portal.Models.v10.LoRaWAN; - using AzureIoTHub.Portal.Server.Filters; - using AzureIoTHub.Portal.Server.Managers; - using AzureIoTHub.Portal.Server.Services; + using Filters; + using Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; - using Microsoft.Extensions.Logging; [Authorize] [ApiController] @@ -22,29 +20,18 @@ namespace AzureIoTHub.Portal.Server.Controllers.V10.LoRaWAN [Route("api/lorawan/models")] [ApiExplorerSettings(GroupName = "LoRa WAN")] [LoRaFeatureActiveFilter] - public class LoRaWANDeviceModelsController : DeviceModelsControllerBase + public class LoRaWANDeviceModelsController : DeviceModelsControllerBase { + private readonly IDeviceModelService deviceModelService; + /// /// Initializes a new instance of the class. /// - /// The logger. - /// The device model image manager. - /// The device model mapper. - /// The devices service. - /// The table client factory. - /// The device provisioning service manager. - /// The configuration service. - public LoRaWANDeviceModelsController( - ILogger> log, - IDeviceModelImageManager deviceModelImageManager, - IDeviceModelMapper deviceModelMapper, - IDeviceService devicesService, - ITableClientFactory tableClientFactory, - IDeviceProvisioningServiceManager deviceProvisioningServiceManager, - IConfigService configService) - : base(log, deviceModelImageManager, deviceModelMapper, devicesService, tableClientFactory, deviceProvisioningServiceManager, configService, - $"{nameof(DeviceModel.SupportLoRaFeatures)} eq true") + /// Device Model Service + public LoRaWANDeviceModelsController(IDeviceModelService deviceModelService) + : base(deviceModelService) { + this.deviceModelService = deviceModelService; } /// @@ -53,9 +40,10 @@ public LoRaWANDeviceModelsController( /// An array representing the device models. [HttpGet(Name = "GET LoRaWAN device model list")] [ProducesResponseType(StatusCodes.Status200OK)] - public override ActionResult> GetItems() + public override async Task>> GetItems() { - return base.GetItems(); + var devices = await this.deviceModelService.GetDeviceModels(); + return Ok(devices.Where(device => device.SupportLoRaFeatures)); } /// @@ -66,7 +54,7 @@ public override ActionResult> GetItems() [HttpGet("{id}", Name = "GET LoRaWAN device model")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public override Task> GetItem(string id) + public override Task> GetItem(string id) { return base.GetItem(id); } @@ -112,28 +100,28 @@ public override Task DeleteAvatar(string id) /// /// Creates the specified device model. /// - /// The device model. + /// The device model. /// The action result. [HttpPost(Name = "POST Create a new LoRaWAN device model")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - public override Task Post(LoRaDeviceModel deviceModel) + public override Task Post(LoRaDeviceModelDto deviceModelDto) { - return base.Post(deviceModel); + return base.Post(deviceModelDto); } /// /// Updates the specified device model. /// - /// The device model. + /// The device model. /// The action result. [HttpPut("{id}", Name = "PUT Update the LoRaWAN device model")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public override Task Put(LoRaDeviceModel deviceModel) + public override Task Put(LoRaDeviceModelDto deviceModelDto) { - return base.Put(deviceModel); + return base.Put(deviceModelDto); } /// diff --git a/src/AzureIoTHub.Portal/Server/Managers/DeviceModelCommandsManager.cs b/src/AzureIoTHub.Portal/Server/Managers/DeviceModelCommandsManager.cs index 4c2c65e72..124e9c4f3 100644 --- a/src/AzureIoTHub.Portal/Server/Managers/DeviceModelCommandsManager.cs +++ b/src/AzureIoTHub.Portal/Server/Managers/DeviceModelCommandsManager.cs @@ -53,9 +53,9 @@ public ReadOnlyCollection RetrieveCommands(string deviceModel) return commands.AsReadOnly(); } - public ReadOnlyCollection RetrieveDeviceModelCommands(string deviceModel) + public ReadOnlyCollection RetrieveDeviceModelCommands(string deviceModel) { - var commands = new List(); + var commands = new List(); if (deviceModel == null) { diff --git a/src/AzureIoTHub.Portal/Server/Managers/IDeviceModelCommandsManager.cs b/src/AzureIoTHub.Portal/Server/Managers/IDeviceModelCommandsManager.cs index 2e504db60..c436977da 100644 --- a/src/AzureIoTHub.Portal/Server/Managers/IDeviceModelCommandsManager.cs +++ b/src/AzureIoTHub.Portal/Server/Managers/IDeviceModelCommandsManager.cs @@ -10,6 +10,6 @@ public interface IDeviceModelCommandsManager { ReadOnlyCollection RetrieveCommands(string deviceModel); - ReadOnlyCollection RetrieveDeviceModelCommands(string deviceModel); + ReadOnlyCollection RetrieveDeviceModelCommands(string deviceModel); } } diff --git a/src/AzureIoTHub.Portal/Server/Managers/ILoraDeviceMethodManager.cs b/src/AzureIoTHub.Portal/Server/Managers/ILoraDeviceMethodManager.cs index 0768bbd40..e696242fa 100644 --- a/src/AzureIoTHub.Portal/Server/Managers/ILoraDeviceMethodManager.cs +++ b/src/AzureIoTHub.Portal/Server/Managers/ILoraDeviceMethodManager.cs @@ -10,7 +10,7 @@ namespace AzureIoTHub.Portal.Server.Managers public interface ILoraDeviceMethodManager { - Task ExecuteLoRaDeviceMessage(string deviceId, DeviceModelCommand command); + Task ExecuteLoRaDeviceMessage(string deviceId, DeviceModelCommandDto commandDto); Task CheckAzureFunctionReturn(CancellationToken cancellationToken); } } diff --git a/src/AzureIoTHub.Portal/Server/Managers/LoraDeviceMethodManager.cs b/src/AzureIoTHub.Portal/Server/Managers/LoraDeviceMethodManager.cs index 3593756a2..8610c8ace 100644 --- a/src/AzureIoTHub.Portal/Server/Managers/LoraDeviceMethodManager.cs +++ b/src/AzureIoTHub.Portal/Server/Managers/LoraDeviceMethodManager.cs @@ -21,16 +21,16 @@ public LoraDeviceMethodManager(HttpClient httpClient) this.httpClient = httpClient; } - public async Task ExecuteLoRaDeviceMessage(string deviceId, DeviceModelCommand command) + public async Task ExecuteLoRaDeviceMessage(string deviceId, DeviceModelCommandDto commandDto) { ArgumentNullException.ThrowIfNull(deviceId, nameof(deviceId)); - ArgumentNullException.ThrowIfNull(command, nameof(command)); + ArgumentNullException.ThrowIfNull(commandDto, nameof(commandDto)); var body = new LoRaCloudToDeviceMessage { - RawPayload = Convert.ToBase64String(Encoding.UTF8.GetBytes(command.Frame)), - Fport = command.Port, - Confirmed = command.Confirmed + RawPayload = Convert.ToBase64String(Encoding.UTF8.GetBytes(commandDto.Frame)), + Fport = commandDto.Port, + Confirmed = commandDto.Confirmed }; using var commandContent = JsonContent.Create(body); diff --git a/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelCommandMapper.cs b/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelCommandMapper.cs index b60f711a0..56743f17f 100644 --- a/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelCommandMapper.cs +++ b/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelCommandMapper.cs @@ -15,17 +15,17 @@ public class DeviceModelCommandMapper : IDeviceModelCommandMapper /// /// The entity. /// The device model comamnd. - public DeviceModelCommand GetDeviceModelCommand(TableEntity entity) + public DeviceModelCommandDto GetDeviceModelCommand(TableEntity entity) { ArgumentNullException.ThrowIfNull(entity, nameof(entity)); - return new DeviceModelCommand + return new DeviceModelCommandDto { Name = entity.RowKey, - Frame = entity[nameof(DeviceModelCommand.Frame)].ToString(), - Port = int.Parse(entity[nameof(DeviceModelCommand.Port)].ToString(), CultureInfo.InvariantCulture), - IsBuiltin = bool.Parse(entity[nameof(DeviceModelCommand.IsBuiltin)]?.ToString() ?? "false"), - Confirmed = bool.Parse(entity[nameof(DeviceModelCommand.Confirmed)]?.ToString() ?? "false"), + Frame = entity[nameof(DeviceModelCommandDto.Frame)].ToString(), + Port = int.Parse(entity[nameof(DeviceModelCommandDto.Port)].ToString(), CultureInfo.InvariantCulture), + IsBuiltin = bool.Parse(entity[nameof(DeviceModelCommandDto.IsBuiltin)]?.ToString() ?? "false"), + Confirmed = bool.Parse(entity[nameof(DeviceModelCommandDto.Confirmed)]?.ToString() ?? "false"), }; } @@ -34,15 +34,15 @@ public DeviceModelCommand GetDeviceModelCommand(TableEntity entity) /// /// The command entity. /// The element. - public void UpdateTableEntity(TableEntity commandEntity, DeviceModelCommand element) + public void UpdateTableEntity(TableEntity commandEntity, DeviceModelCommandDto element) { ArgumentNullException.ThrowIfNull(commandEntity, nameof(commandEntity)); ArgumentNullException.ThrowIfNull(element, nameof(element)); - commandEntity[nameof(DeviceModelCommand.Frame)] = element.Frame; - commandEntity[nameof(DeviceModelCommand.Port)] = element.Port; - commandEntity[nameof(DeviceModelCommand.IsBuiltin)] = element.IsBuiltin; - commandEntity[nameof(DeviceModelCommand.Confirmed)] = element.Confirmed; + commandEntity[nameof(DeviceModelCommandDto.Frame)] = element.Frame; + commandEntity[nameof(DeviceModelCommandDto.Port)] = element.Port; + commandEntity[nameof(DeviceModelCommandDto.IsBuiltin)] = element.IsBuiltin; + commandEntity[nameof(DeviceModelCommandDto.Confirmed)] = element.Confirmed; } } } diff --git a/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelCommandProfile.cs b/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelCommandProfile.cs new file mode 100644 index 000000000..208e9d678 --- /dev/null +++ b/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelCommandProfile.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 Models.v10.LoRaWAN; + + public class DeviceModelCommandProfile : Profile + { + public DeviceModelCommandProfile() + { + _ = CreateMap() + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.Name)) + .ReverseMap(); + } + } +} diff --git a/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelMapper.cs b/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelMapper.cs index e774ac8fd..8c47b485c 100644 --- a/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelMapper.cs +++ b/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelMapper.cs @@ -9,7 +9,7 @@ namespace AzureIoTHub.Portal.Server.Mappers using System; using System.Collections.Generic; - public class DeviceModelMapper : IDeviceModelMapper + public class DeviceModelMapper : IDeviceModelMapper { private readonly IDeviceModelImageManager deviceModelImageManager; @@ -18,45 +18,37 @@ public DeviceModelMapper(IDeviceModelImageManager deviceModelImageManager) this.deviceModelImageManager = deviceModelImageManager; } - public DeviceModel CreateDeviceModelListItem(TableEntity entity) + public DeviceModelDto CreateDeviceModelListItem(TableEntity entity) { ArgumentNullException.ThrowIfNull(entity, nameof(entity)); - return new DeviceModel + return new DeviceModelDto { ModelId = entity.RowKey, - IsBuiltin = bool.Parse(entity[nameof(DeviceModel.IsBuiltin)]?.ToString() ?? "false"), - SupportLoRaFeatures = bool.Parse(entity[nameof(DeviceModel.SupportLoRaFeatures)]?.ToString() ?? "false"), + IsBuiltin = bool.Parse(entity[nameof(DeviceModelDto.IsBuiltin)]?.ToString() ?? "false"), + SupportLoRaFeatures = bool.Parse(entity[nameof(DeviceModelDto.SupportLoRaFeatures)]?.ToString() ?? "false"), ImageUrl = this.deviceModelImageManager.ComputeImageUri(entity.RowKey), - Name = entity[nameof(DeviceModel.Name)]?.ToString(), - Description = entity[nameof(DeviceModel.Description)]?.ToString(), + Name = entity[nameof(DeviceModelDto.Name)]?.ToString(), + Description = entity[nameof(DeviceModelDto.Description)]?.ToString(), }; } - public DeviceModel CreateDeviceModel(TableEntity entity) + public DeviceModelDto CreateDeviceModel(TableEntity entity) { ArgumentNullException.ThrowIfNull(entity, nameof(entity)); - return new DeviceModel + return new DeviceModelDto { ModelId = entity.RowKey, - IsBuiltin = bool.Parse(entity[nameof(DeviceModel.IsBuiltin)]?.ToString() ?? "false"), + IsBuiltin = bool.Parse(entity[nameof(DeviceModelDto.IsBuiltin)]?.ToString() ?? "false"), ImageUrl = this.deviceModelImageManager.ComputeImageUri(entity.RowKey), - Name = entity[nameof(DeviceModel.Name)]?.ToString(), - Description = entity[nameof(DeviceModel.Description)]?.ToString() + Name = entity[nameof(DeviceModelDto.Name)]?.ToString(), + Description = entity[nameof(DeviceModelDto.Description)]?.ToString() }; } - public Dictionary UpdateTableEntity(TableEntity entity, DeviceModel model) + public Dictionary BuildDeviceModelDesiredProperties(DeviceModelDto model) { - ArgumentNullException.ThrowIfNull(entity, nameof(entity)); - ArgumentNullException.ThrowIfNull(model, nameof(model)); - - entity[nameof(DeviceModel.Name)] = model.Name; - entity[nameof(DeviceModel.Description)] = model.Description; - entity[nameof(DeviceModel.IsBuiltin)] = model.IsBuiltin; - entity[nameof(DeviceModel.SupportLoRaFeatures)] = false; - return new Dictionary(); } } diff --git a/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelProfile.cs b/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelProfile.cs new file mode 100644 index 000000000..d3dbb3e17 --- /dev/null +++ b/src/AzureIoTHub.Portal/Server/Mappers/DeviceModelProfile.cs @@ -0,0 +1,24 @@ +// 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 Models.v10; + using Models.v10.LoRaWAN; + + public class DeviceModelProfile : Profile + { + public DeviceModelProfile() + { + _ = CreateMap() + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.ModelId)) + .ReverseMap(); + + _ = CreateMap() + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.ModelId)) + .ReverseMap(); + } + } +} diff --git a/src/AzureIoTHub.Portal/Server/Mappers/IDeviceModelCommandMapper.cs b/src/AzureIoTHub.Portal/Server/Mappers/IDeviceModelCommandMapper.cs index d7dd129e3..7910b0995 100644 --- a/src/AzureIoTHub.Portal/Server/Mappers/IDeviceModelCommandMapper.cs +++ b/src/AzureIoTHub.Portal/Server/Mappers/IDeviceModelCommandMapper.cs @@ -8,8 +8,8 @@ namespace AzureIoTHub.Portal.Server.Mappers public interface IDeviceModelCommandMapper { - public DeviceModelCommand GetDeviceModelCommand(TableEntity entity); + public DeviceModelCommandDto GetDeviceModelCommand(TableEntity entity); - public void UpdateTableEntity(TableEntity commandEntity, DeviceModelCommand element); + public void UpdateTableEntity(TableEntity commandEntity, DeviceModelCommandDto element); } } diff --git a/src/AzureIoTHub.Portal/Server/Mappers/IDeviceModelMapper.cs b/src/AzureIoTHub.Portal/Server/Mappers/IDeviceModelMapper.cs index a540eb9a5..94e199dce 100644 --- a/src/AzureIoTHub.Portal/Server/Mappers/IDeviceModelMapper.cs +++ b/src/AzureIoTHub.Portal/Server/Mappers/IDeviceModelMapper.cs @@ -15,6 +15,6 @@ public interface IDeviceModelMapper public TModel CreateDeviceModel(TableEntity entity); - public Dictionary UpdateTableEntity(TableEntity entity, TModel model); + public Dictionary BuildDeviceModelDesiredProperties(TModel model); } } diff --git a/src/AzureIoTHub.Portal/Server/Mappers/LoRaDeviceModelMapper.cs b/src/AzureIoTHub.Portal/Server/Mappers/LoRaDeviceModelMapper.cs index cb248c35a..664611916 100644 --- a/src/AzureIoTHub.Portal/Server/Mappers/LoRaDeviceModelMapper.cs +++ b/src/AzureIoTHub.Portal/Server/Mappers/LoRaDeviceModelMapper.cs @@ -6,97 +6,85 @@ namespace AzureIoTHub.Portal.Server.Mappers using System; using System.Collections.Generic; using Azure.Data.Tables; - using AzureIoTHub.Portal.Server.Managers; - using AzureIoTHub.Portal.Models.v10; - using AzureIoTHub.Portal.Models.v10.LoRaWAN; + using Managers; + using Models.v10; + using Models.v10.LoRaWAN; - public class LoRaDeviceModelMapper : IDeviceModelMapper + public class LoRaDeviceModelMapper : IDeviceModelMapper { - private readonly IDeviceModelCommandsManager deviceModelCommandsManager; private readonly IDeviceModelImageManager deviceModelImageManager; - public LoRaDeviceModelMapper(IDeviceModelCommandsManager deviceModelCommandsManager, IDeviceModelImageManager deviceModelImageManager) + public LoRaDeviceModelMapper(IDeviceModelImageManager deviceModelImageManager) { - this.deviceModelCommandsManager = deviceModelCommandsManager; this.deviceModelImageManager = deviceModelImageManager; } - public DeviceModel CreateDeviceModelListItem(TableEntity entity) + public DeviceModelDto CreateDeviceModelListItem(TableEntity entity) { ArgumentNullException.ThrowIfNull(entity, nameof(entity)); - return new DeviceModel + return new DeviceModelDto { ModelId = entity.RowKey, - IsBuiltin = bool.Parse(entity[nameof(LoRaDeviceModel.IsBuiltin)]?.ToString() ?? "false"), - SupportLoRaFeatures = bool.Parse(entity[nameof(LoRaDeviceModel.SupportLoRaFeatures)]?.ToString() ?? "false"), + IsBuiltin = bool.Parse(entity[nameof(LoRaDeviceModelDto.IsBuiltin)]?.ToString() ?? "false"), + SupportLoRaFeatures = bool.Parse(entity[nameof(LoRaDeviceModelDto.SupportLoRaFeatures)]?.ToString() ?? "false"), ImageUrl = this.deviceModelImageManager.ComputeImageUri(entity.RowKey), - Name = entity[nameof(LoRaDeviceModel.Name)]?.ToString(), - Description = entity[nameof(LoRaDeviceModel.Description)]?.ToString(), + Name = entity[nameof(LoRaDeviceModelDto.Name)]?.ToString(), + Description = entity[nameof(LoRaDeviceModelDto.Description)]?.ToString(), }; } - public LoRaDeviceModel CreateDeviceModel(TableEntity entity) + public LoRaDeviceModelDto CreateDeviceModel(TableEntity entity) { ArgumentNullException.ThrowIfNull(entity, nameof(entity)); - return new LoRaDeviceModel + return new LoRaDeviceModelDto { ModelId = entity.RowKey, - IsBuiltin = bool.Parse(entity[nameof(LoRaDeviceModel.IsBuiltin)]?.ToString() ?? "false"), + IsBuiltin = bool.Parse(entity[nameof(LoRaDeviceModelDto.IsBuiltin)]?.ToString() ?? "false"), ImageUrl = this.deviceModelImageManager.ComputeImageUri(entity.RowKey), - Name = entity[nameof(LoRaDeviceModel.Name)]?.ToString(), - Description = entity[nameof(LoRaDeviceModel.Description)]?.ToString(), - SensorDecoder = entity[nameof(LoRaDeviceModel.SensorDecoder)]?.ToString(), - UseOTAA = bool.Parse(entity[nameof(LoRaDeviceModel.UseOTAA)]?.ToString() ?? "true"), - PreferredWindow = int.TryParse(entity[nameof(LoRaDeviceModel.PreferredWindow)]?.ToString(), out var intResult) ? intResult : 1, - Supports32BitFCnt = bool.TryParse(entity[nameof(LoRaDeviceModel.Supports32BitFCnt)]?.ToString(), out var boolResult) ? boolResult : null, - ABPRelaxMode = bool.TryParse(entity[nameof(LoRaDeviceModel.ABPRelaxMode)]?.ToString(), out boolResult) ? boolResult : null, - KeepAliveTimeout = int.TryParse(entity[nameof(LoRaDeviceModel.KeepAliveTimeout)]?.ToString(), out intResult) ? intResult : null, - Deduplication = Enum.TryParse(entity[nameof(LoRaDeviceModel.Deduplication)]?.ToString(), out var deduplication) ? deduplication : DeduplicationMode.None, - Downlink = bool.TryParse(entity[nameof(LoRaDeviceModel.Downlink)]?.ToString(), out boolResult) ? boolResult : null, - FCntDownStart = int.TryParse(entity[nameof(LoRaDeviceModel.FCntDownStart)]?.ToString(), out intResult) ? intResult : null, - FCntResetCounter = int.TryParse(entity[nameof(LoRaDeviceModel.FCntResetCounter)]?.ToString(), out intResult) ? intResult : null, - FCntUpStart = int.TryParse(entity[nameof(LoRaDeviceModel.FCntUpStart)]?.ToString(), out intResult) ? intResult : null, - RX1DROffset = int.TryParse(entity[nameof(LoRaDeviceModel.RX1DROffset)]?.ToString(), out intResult) ? intResult : null, - RX2DataRate = int.TryParse(entity[nameof(LoRaDeviceModel.RX2DataRate)]?.ToString(), out intResult) ? intResult : null, - RXDelay = int.TryParse(entity[nameof(LoRaDeviceModel.RXDelay)]?.ToString(), out intResult) ? intResult : null + Name = entity[nameof(LoRaDeviceModelDto.Name)]?.ToString(), + Description = entity[nameof(LoRaDeviceModelDto.Description)]?.ToString(), + SensorDecoder = entity[nameof(LoRaDeviceModelDto.SensorDecoder)]?.ToString(), + UseOTAA = bool.Parse(entity[nameof(LoRaDeviceModelDto.UseOTAA)]?.ToString() ?? "true"), + PreferredWindow = int.TryParse(entity[nameof(LoRaDeviceModelDto.PreferredWindow)]?.ToString(), out var intResult) ? intResult : 1, + Supports32BitFCnt = bool.TryParse(entity[nameof(LoRaDeviceModelDto.Supports32BitFCnt)]?.ToString(), out var boolResult) ? boolResult : null, + ABPRelaxMode = bool.TryParse(entity[nameof(LoRaDeviceModelDto.ABPRelaxMode)]?.ToString(), out boolResult) ? boolResult : null, + KeepAliveTimeout = int.TryParse(entity[nameof(LoRaDeviceModelDto.KeepAliveTimeout)]?.ToString(), out intResult) ? intResult : null, + Deduplication = Enum.TryParse(entity[nameof(LoRaDeviceModelDto.Deduplication)]?.ToString(), out var deduplication) ? deduplication : DeduplicationMode.None, + Downlink = bool.TryParse(entity[nameof(LoRaDeviceModelDto.Downlink)]?.ToString(), out boolResult) ? boolResult : null, + FCntDownStart = int.TryParse(entity[nameof(LoRaDeviceModelDto.FCntDownStart)]?.ToString(), out intResult) ? intResult : null, + FCntResetCounter = int.TryParse(entity[nameof(LoRaDeviceModelDto.FCntResetCounter)]?.ToString(), out intResult) ? intResult : null, + FCntUpStart = int.TryParse(entity[nameof(LoRaDeviceModelDto.FCntUpStart)]?.ToString(), out intResult) ? intResult : null, + RX1DROffset = int.TryParse(entity[nameof(LoRaDeviceModelDto.RX1DROffset)]?.ToString(), out intResult) ? intResult : null, + RX2DataRate = int.TryParse(entity[nameof(LoRaDeviceModelDto.RX2DataRate)]?.ToString(), out intResult) ? intResult : null, + RXDelay = int.TryParse(entity[nameof(LoRaDeviceModelDto.RXDelay)]?.ToString(), out intResult) ? intResult : null }; } - public Dictionary UpdateTableEntity(TableEntity entity, LoRaDeviceModel model) + public Dictionary BuildDeviceModelDesiredProperties(LoRaDeviceModelDto modelDto) { - ArgumentNullException.ThrowIfNull(entity, nameof(entity)); - ArgumentNullException.ThrowIfNull(model, nameof(model)); - - entity[nameof(LoRaDeviceModel.Name)] = model.Name; - entity[nameof(LoRaDeviceModel.Description)] = model.Description; - entity[nameof(LoRaDeviceModel.IsBuiltin)] = model.IsBuiltin; - entity[nameof(LoRaDeviceModel.SupportLoRaFeatures)] = model.SupportLoRaFeatures; - entity[nameof(LoRaDeviceModel.UseOTAA)] = model.UseOTAA; - var desiredProperties = new Dictionary(); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.SensorDecoder), model.SensorDecoder, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.Supports32BitFCnt), model.Supports32BitFCnt, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.ABPRelaxMode), model.ABPRelaxMode, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.KeepAliveTimeout), model.KeepAliveTimeout, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.PreferredWindow), model.PreferredWindow, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.Downlink), model.Downlink, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.Deduplication), model.Deduplication.ToString(), desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.FCntDownStart), model.FCntDownStart, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.FCntResetCounter), model.FCntResetCounter, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.FCntUpStart), model.FCntUpStart, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.RX1DROffset), model.RX1DROffset, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.RX2DataRate), model.RX2DataRate, desiredProperties); - AddOptionnalProperties(entity, nameof(LoRaDeviceModel.RXDelay), model.RXDelay, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.SensorDecoder), modelDto.SensorDecoder, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.Supports32BitFCnt), modelDto.Supports32BitFCnt, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.ABPRelaxMode), modelDto.ABPRelaxMode, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.KeepAliveTimeout), modelDto.KeepAliveTimeout, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.PreferredWindow), modelDto.PreferredWindow, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.Downlink), modelDto.Downlink, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.Deduplication), modelDto.Deduplication.ToString(), desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.FCntDownStart), modelDto.FCntDownStart, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.FCntResetCounter), modelDto.FCntResetCounter, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.FCntUpStart), modelDto.FCntUpStart, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.RX1DROffset), modelDto.RX1DROffset, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.RX2DataRate), modelDto.RX2DataRate, desiredProperties); + AddOptionalProperties(nameof(LoRaDeviceModelDto.RXDelay), modelDto.RXDelay, desiredProperties); return desiredProperties; } - private static void AddOptionnalProperties(TableEntity entity, string propertyName, object propertyValue, Dictionary desiredProperties) + private static void AddOptionalProperties(string propertyName, object propertyValue, Dictionary desiredProperties) { - entity[propertyName] = propertyValue; desiredProperties.Add($"properties.desired.{propertyName}", propertyValue); } } diff --git a/src/AzureIoTHub.Portal/Server/Services/DeviceModelService.cs b/src/AzureIoTHub.Portal/Server/Services/DeviceModelService.cs new file mode 100644 index 000000000..29d299efc --- /dev/null +++ b/src/AzureIoTHub.Portal/Server/Services/DeviceModelService.cs @@ -0,0 +1,184 @@ +// 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.Services +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using AutoMapper; + using Domain.Exceptions; + using AzureIoTHub.Portal.Shared.Models; + using Domain.Entities; + using Domain.Repositories; + using Domain; + using Managers; + using Microsoft.AspNetCore.Http; + using Microsoft.Azure.Devices.Shared; + using Helpers; + using Microsoft.EntityFrameworkCore; + + public class DeviceModelService : IDeviceModelService + where TListItem : class, IDeviceModel + where TModel : class, IDeviceModel + { + private readonly IMapper mapper; + private readonly IUnitOfWork unitOfWork; + private readonly IDeviceModelRepository deviceModelRepository; + private readonly IDeviceModelCommandRepository deviceModelCommandRepository; + + private readonly IDeviceProvisioningServiceManager deviceProvisioningServiceManager; + private readonly IConfigService configService; + private readonly IDeviceModelImageManager deviceModelImageManager; + private readonly IDeviceModelMapper deviceModelMapper; + private readonly IDeviceService deviceService; + + public DeviceModelService(IMapper mapper, + IUnitOfWork unitOfWork, + IDeviceModelRepository deviceModelRepository, + IDeviceModelCommandRepository deviceModelCommandRepository, + IDeviceProvisioningServiceManager deviceProvisioningServiceManager, + IConfigService configService, + IDeviceModelImageManager deviceModelImageManager, + IDeviceModelMapper deviceModelMapper, + IDeviceService deviceService) + { + this.mapper = mapper; + this.unitOfWork = unitOfWork; + this.deviceModelRepository = deviceModelRepository; + this.deviceModelCommandRepository = deviceModelCommandRepository; + this.deviceProvisioningServiceManager = deviceProvisioningServiceManager; + this.configService = configService; + this.deviceModelImageManager = deviceModelImageManager; + this.deviceModelMapper = deviceModelMapper; + this.deviceService = deviceService; + } + + public async Task> GetDeviceModels() + { + return await Task.Run(() => this.deviceModelRepository.GetAll() + .Select(model => this.mapper.Map(model)) + .ToList()); + } + + public async Task GetDeviceModel(string deviceModelId) + { + var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(deviceModelId); + + if (deviceModelEntity == null) + { + throw new ResourceNotFoundException($"The device model {deviceModelId} doesn't exist"); + } + + return this.mapper.Map(deviceModelEntity); + } + + public async Task CreateDeviceModel(TModel deviceModel) + { + try + { + var deviceModelEntity = this.mapper.Map(deviceModel); + + await this.deviceModelRepository.InsertAsync(deviceModelEntity); + await this.unitOfWork.SaveAsync(); + + await CreateDeviceModelConfiguration(deviceModel); + } + catch (DbUpdateException e) + { + throw new InternalServerErrorException($"Unable to create the device model {deviceModel.Name}", e); + } + } + + public async Task UpdateDeviceModel(TModel deviceModel) + { + try + { + var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(deviceModel.ModelId); + + if (deviceModelEntity == null) + { + throw new ResourceNotFoundException($"The device model {deviceModel.ModelId} doesn't exist"); + } + + _ = this.mapper.Map(deviceModel, deviceModelEntity); + + this.deviceModelRepository.Update(deviceModelEntity); + await this.unitOfWork.SaveAsync(); + + await CreateDeviceModelConfiguration(deviceModel); + } + catch (DbUpdateException e) + { + throw new InternalServerErrorException($"Unable to update the device model {deviceModel.Name}", e); + } + } + + public async Task DeleteDeviceModel(string deviceModelId) + { + try + { + var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(deviceModelId); + + if (deviceModelEntity == null) + { + return; + } + + var devices = await this.deviceService.GetAllDevice(); + + if (devices.Items.Any(x => DeviceHelper.RetrieveTagValue(x, "modelId") == deviceModelId)) + { + throw new ResourceAlreadyExistsException( + $"The device model {deviceModelId} is already in use by a device and cannot be deleted"); + } + + var deviceModelCommands = this.deviceModelCommandRepository.GetAll().Where(command => + command.DeviceModelId.Equals(deviceModelId, StringComparison.Ordinal)).ToList(); + + foreach (var deviceModelCommand in deviceModelCommands) + { + this.deviceModelCommandRepository.Delete(deviceModelCommand.Id); + } + + // Image deletion + await this.deviceModelImageManager.DeleteDeviceModelImageAsync(deviceModelId); + + this.deviceModelRepository.Delete(deviceModelId); + + await this.unitOfWork.SaveAsync(); + } + catch (DbUpdateException e) + { + throw new InternalServerErrorException($"Unable to delete the device model {deviceModelId}", e); + } + } + + public Task GetDeviceModelAvatar(string deviceModelId) + { + return Task.Run(() => this.deviceModelImageManager.ComputeImageUri(deviceModelId).ToString()); + } + + public Task UpdateDeviceModelAvatar(string deviceModelId, IFormFile file) + { + return Task.Run(() => this.deviceModelImageManager.ChangeDeviceModelImageAsync(deviceModelId, file?.OpenReadStream())); + } + + public Task DeleteDeviceModelAvatar(string deviceModelId) + { + return this.deviceModelImageManager.DeleteDeviceModelImageAsync(deviceModelId); + } + + private async Task CreateDeviceModelConfiguration(TModel deviceModel) + { + var desiredProperties = this.deviceModelMapper.BuildDeviceModelDesiredProperties(deviceModel); + + var deviceModelTwin = new TwinCollection(); + + _ = await this.deviceProvisioningServiceManager.CreateEnrollmentGroupFromModelAsync(deviceModel.ModelId, deviceModel.Name, deviceModelTwin); + + await this.configService.RollOutDeviceModelConfiguration(deviceModel.ModelId, desiredProperties); + } + } +} diff --git a/src/AzureIoTHub.Portal/Server/Services/DeviceService.cs b/src/AzureIoTHub.Portal/Server/Services/DeviceService.cs index ced59737e..cfb95f1b1 100644 --- a/src/AzureIoTHub.Portal/Server/Services/DeviceService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/DeviceService.cs @@ -605,7 +605,7 @@ public async Task GetEnrollmentCredentials(string deviceI var modelEntity = response.Value; - return await this.deviceProvisioningServiceManager.GetEnrollmentCredentialsAsync(deviceId, modelEntity[nameof(DeviceModel.Name)].ToString()); + return await this.deviceProvisioningServiceManager.GetEnrollmentCredentialsAsync(deviceId, modelEntity[nameof(DeviceModelDto.Name)].ToString()); } catch (RequestFailedException e) { diff --git a/src/AzureIoTHub.Portal/Server/Services/IDeviceModelService.cs b/src/AzureIoTHub.Portal/Server/Services/IDeviceModelService.cs new file mode 100644 index 000000000..9cfc7ceef --- /dev/null +++ b/src/AzureIoTHub.Portal/Server/Services/IDeviceModelService.cs @@ -0,0 +1,31 @@ +// 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.Services +{ + using System.Collections.Generic; + using System.Threading.Tasks; + using AzureIoTHub.Portal.Shared.Models; + using Microsoft.AspNetCore.Http; + + public interface IDeviceModelService + where TListItem : class, IDeviceModel + where TModel : class, IDeviceModel + { + Task> GetDeviceModels(); + + Task GetDeviceModel(string deviceModelId); + + Task CreateDeviceModel(TModel deviceModel); + + Task UpdateDeviceModel(TModel deviceModel); + + Task DeleteDeviceModel(string deviceModelId); + + Task GetDeviceModelAvatar(string deviceModelId); + + Task UpdateDeviceModelAvatar(string deviceModelId, IFormFile file); + + Task DeleteDeviceModelAvatar(string deviceModelId); + } +} diff --git a/src/AzureIoTHub.Portal/Server/Services/ILoRaWANCommandService.cs b/src/AzureIoTHub.Portal/Server/Services/ILoRaWANCommandService.cs index b25d3dec2..c3a3ad4bd 100644 --- a/src/AzureIoTHub.Portal/Server/Services/ILoRaWANCommandService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/ILoRaWANCommandService.cs @@ -8,7 +8,7 @@ namespace AzureIoTHub.Portal.Server.Services public interface ILoRaWANCommandService { - Task GetDeviceModelCommandsFromModel(string id); - Task PostDeviceModelCommands(string id, DeviceModelCommand[] commands); + Task GetDeviceModelCommandsFromModel(string id); + Task PostDeviceModelCommands(string id, DeviceModelCommandDto[] commands); } } diff --git a/src/AzureIoTHub.Portal/Server/Services/LoRaWANCommandService.cs b/src/AzureIoTHub.Portal/Server/Services/LoRaWANCommandService.cs index 160ae896b..c0f308906 100644 --- a/src/AzureIoTHub.Portal/Server/Services/LoRaWANCommandService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/LoRaWANCommandService.cs @@ -3,140 +3,75 @@ namespace AzureIoTHub.Portal.Server.Services { - using System.Collections.Generic; + using System; + 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.LoRaWAN; - using AzureIoTHub.Portal.Server.Controllers.V10.LoRaWAN; - using AzureIoTHub.Portal.Server.Mappers; - using Microsoft.AspNetCore.Http; - using Microsoft.Extensions.Logging; + using AutoMapper; + using Domain; + using Domain.Exceptions; + using Models.v10.LoRaWAN; + using Domain.Entities; + using Domain.Repositories; + using Microsoft.EntityFrameworkCore; public class LoRaWANCommandService : ILoRaWANCommandService { - /// - /// The table client factory. - /// - private readonly ITableClientFactory tableClientFactory; - - /// - /// The device model command mapper. - /// H - private readonly IDeviceModelCommandMapper deviceModelCommandMapper; - - /// - /// The logger. - /// - private readonly ILogger log; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The device model command mapper. - /// The table client factory. - public LoRaWANCommandService( - ILogger log, - IDeviceModelCommandMapper deviceModelCommandMapper, - ITableClientFactory tableClientFactory) + private readonly IMapper mapper; + private readonly IUnitOfWork unitOfWork; + private readonly IDeviceModelCommandRepository deviceModelCommandRepository; + private readonly IDeviceModelRepository deviceModelRepository; + + public LoRaWANCommandService(IMapper mapper, + IUnitOfWork unitOfWork, + IDeviceModelCommandRepository deviceModelCommandRepository, + IDeviceModelRepository deviceModelRepository) { - this.log = log; - this.tableClientFactory = tableClientFactory; - this.deviceModelCommandMapper = deviceModelCommandMapper; + this.mapper = mapper; + this.unitOfWork = unitOfWork; + this.deviceModelCommandRepository = deviceModelCommandRepository; + this.deviceModelRepository = deviceModelRepository; } - public async Task PostDeviceModelCommands(string id, DeviceModelCommand[] commands) + public async Task PostDeviceModelCommands(string id, DeviceModelCommandDto[] commands) { - var query = await GetCommandsQueryFromModelId(id); - - foreach (var item in query) - { - try - { - _ = await this.tableClientFactory - .GetDeviceCommands() - .DeleteEntityAsync(item.PartitionKey, item.RowKey); - } - catch (RequestFailedException e) - { - throw new InternalServerErrorException($"Unable to delete the command {item.RowKey} of the model with id {id}", e); - } - } - - foreach (var command in commands) + try { - var entity = new TableEntity() - { - PartitionKey = id, - RowKey = command.Name - }; + var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(id); - this.deviceModelCommandMapper.UpdateTableEntity(entity, command); - - try + if (deviceModelEntity == null) { - _ = await this.tableClientFactory - .GetDeviceCommands() - .AddEntityAsync(entity); + throw new ResourceNotFoundException($"The device model {id} doesn't exist"); } - catch (RequestFailedException e) - { - throw new InternalServerErrorException($"Unable to create the command {command.Name} of the model with id {id}", e); - } - } - } - public async Task GetDeviceModelCommandsFromModel(string id) - { - var query = await GetCommandsQueryFromModelId(id); - var commands = new List(); + var existingDeviceModelCommands = await GetDeviceModelCommandsFromModel(id); - foreach (var item in query) - { - var command = this.deviceModelCommandMapper.GetDeviceModelCommand(item); - commands.Add(command); - } - - return commands.ToArray(); - } - - private async Task> GetCommandsQueryFromModelId(string id) - { - try - { - _ = await this.tableClientFactory - .GetDeviceTemplates() - .GetEntityAsync(LoRaWANDeviceModelsController.DefaultPartitionKey, id); - } - catch (RequestFailedException e) - { - if (e.Status == StatusCodes.Status404NotFound) + foreach (var deviceModelCommand in existingDeviceModelCommands) { - throw new InternalServerErrorException($"Unable to find a model with id {id}.", e); + this.deviceModelCommandRepository.Delete(deviceModelCommand.Name); } - this.log.LogError(e.Message, e); - - throw; - } + foreach (var deviceModelCommand in commands) + { + var deviceModelCommandEntity = this.mapper.Map(deviceModelCommand); + deviceModelCommandEntity.DeviceModelId = id; - Pageable query; + await this.deviceModelCommandRepository.InsertAsync(deviceModelCommandEntity); + } - try - { - query = this.tableClientFactory - .GetDeviceCommands() - .Query(filter: $"PartitionKey eq '{id}'"); + await this.unitOfWork.SaveAsync(); } - catch (RequestFailedException e) + catch (DbUpdateException e) { - throw new InternalServerErrorException($"Unable to get existing commands of the model with id {id}", e); + throw new InternalServerErrorException($"Unable to create the commands for the model with id {id}", e); } + } - return query; + public Task GetDeviceModelCommandsFromModel(string id) + { + return Task.Run(() => this.deviceModelCommandRepository.GetAll() + .Where(command => command.DeviceModelId.Equals(id, StringComparison.Ordinal)) + .Select(command => this.mapper.Map(command)) + .ToArray()); } } } diff --git a/src/AzureIoTHub.Portal/Server/Startup.cs b/src/AzureIoTHub.Portal/Server/Startup.cs index a9d843c2a..f36d0eede 100644 --- a/src/AzureIoTHub.Portal/Server/Startup.cs +++ b/src/AzureIoTHub.Portal/Server/Startup.cs @@ -128,8 +128,8 @@ public void ConfigureServices(IServiceCollection services) _ = services.AddTransient, DeviceTwinMapper>(); _ = services.AddTransient, LoRaDeviceTwinMapper>(); - _ = services.AddTransient, DeviceModelMapper>(); - _ = services.AddTransient, LoRaDeviceModelMapper>(); + _ = services.AddTransient, DeviceModelMapper>(); + _ = services.AddTransient, LoRaDeviceModelMapper>(); _ = services.AddTransient(); _ = services.AddTransient(); _ = services.AddTransient(); @@ -145,9 +145,12 @@ public void ConfigureServices(IServiceCollection services) _ = services.AddTransient(); _ = services.AddTransient(); _ = services.AddTransient(); + _ = services.AddTransient(typeof(IDeviceModelService<,>), typeof(DeviceModelService<,>)); _ = services.AddScoped(); _ = services.AddScoped(); + _ = services.AddScoped(); + _ = services.AddScoped(); _ = services.AddMudServices(); @@ -270,6 +273,8 @@ Specify the authorization token got from your IDP as a header. mc.AddProfile(new DevicePropertyProfile()); mc.AddProfile(new DeviceTagProfile()); + mc.AddProfile(new DeviceModelProfile()); + mc.AddProfile(new DeviceModelCommandProfile()); }); var mapper = mapperConfig.CreateMapper(); diff --git a/src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceModel.cs b/src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceModelDto.cs similarity index 93% rename from src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceModel.cs rename to src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceModelDto.cs index ae5724591..3a262ef4e 100644 --- a/src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceModel.cs +++ b/src/AzureIoTHub.Portal/Shared/Models/v1.0/DeviceModelDto.cs @@ -10,7 +10,7 @@ namespace AzureIoTHub.Portal.Models.v10 /// /// Device model. /// - public class DeviceModel : IDeviceModel + public class DeviceModelDto : IDeviceModel { /// /// The device model identifier. @@ -44,9 +44,9 @@ public class DeviceModel : IDeviceModel public bool SupportLoRaFeatures { get; set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public DeviceModel() + public DeviceModelDto() { } } diff --git a/src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/DeviceModelCommand.cs b/src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/DeviceModelCommandDto.cs similarity index 97% rename from src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/DeviceModelCommand.cs rename to src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/DeviceModelCommandDto.cs index aa1bb0c0e..ae18bee39 100644 --- a/src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/DeviceModelCommand.cs +++ b/src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/DeviceModelCommandDto.cs @@ -8,7 +8,7 @@ namespace AzureIoTHub.Portal.Models.v10.LoRaWAN /// /// Device model command. /// - public class DeviceModelCommand + public class DeviceModelCommandDto { /// /// The command name. diff --git a/src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/LoRaDeviceModel.cs b/src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/LoRaDeviceModelDto.cs similarity index 93% rename from src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/LoRaDeviceModel.cs rename to src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/LoRaDeviceModelDto.cs index 90defaa0a..d9dfef6fd 100644 --- a/src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/LoRaDeviceModel.cs +++ b/src/AzureIoTHub.Portal/Shared/Models/v1.0/LoRaWAN/LoRaDeviceModelDto.cs @@ -12,7 +12,7 @@ namespace AzureIoTHub.Portal.Models.v10.LoRaWAN /// /// LoRa Device model. /// - public class LoRaDeviceModel : LoRaDeviceBase, IDeviceModel + public class LoRaDeviceModelDto : LoRaDeviceBase, IDeviceModel { /// /// The device model identifier. @@ -62,10 +62,10 @@ public class LoRaDeviceModel : LoRaDeviceBase, IDeviceModel public bool? Downlink { get; set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The device model taht the LoRa Device model should herit. - public LoRaDeviceModel(IDeviceModel from) + public LoRaDeviceModelDto(IDeviceModel from) { ArgumentNullException.ThrowIfNull(from, nameof(from)); @@ -78,9 +78,9 @@ public LoRaDeviceModel(IDeviceModel from) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public LoRaDeviceModel() + public LoRaDeviceModelDto() { ClassType = ClassType.A; Downlink = true; diff --git a/src/AzureIoTHubPortal.Domain/Entities/DeviceModel.cs b/src/AzureIoTHubPortal.Domain/Entities/DeviceModel.cs index 71b1cd6de..add66fa1a 100644 --- a/src/AzureIoTHubPortal.Domain/Entities/DeviceModel.cs +++ b/src/AzureIoTHubPortal.Domain/Entities/DeviceModel.cs @@ -3,7 +3,7 @@ namespace AzureIoTHub.Portal.Domain.Entities { - using AzureIoTHub.Portal.Models.v10.LoRaWAN; + using Models.v10.LoRaWAN; using Base; public class DeviceModel : EntityBase diff --git a/src/AzureIoTHubPortal.Domain/Repositories/IDeviceModelCommandRepository.cs b/src/AzureIoTHubPortal.Domain/Repositories/IDeviceModelCommandRepository.cs new file mode 100644 index 000000000..4683571df --- /dev/null +++ b/src/AzureIoTHubPortal.Domain/Repositories/IDeviceModelCommandRepository.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 IDeviceModelCommandRepository : IRepository + { + } +} diff --git a/src/AzureIoTHubPortal.Domain/Repositories/IDeviceModelRepository.cs b/src/AzureIoTHubPortal.Domain/Repositories/IDeviceModelRepository.cs new file mode 100644 index 000000000..e85d46444 --- /dev/null +++ b/src/AzureIoTHubPortal.Domain/Repositories/IDeviceModelRepository.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 IDeviceModelRepository : IRepository + { + } +}