Skip to content

Commit

Permalink
Fix/1562 increase code coverage on device list page (#1690)
Browse files Browse the repository at this point in the history
* Increase code coverage on DeviceListPage

* Add test DeleteDevice_Clicked_DeleteDeviceDialogIsShown

* Update test DeviceListPageRendersCorrectly

* Add unit test ImportDevices_FileAdded_DevicesExported

* Test addLoadItem_ascSelect

* Add test

* Correction test

* Add unit test on sort devices by id asc and desc

Co-authored-by: crib <[email protected]>
Co-authored-by: Hocine Hacherouf <[email protected]>
  • Loading branch information
3 people authored Jan 12, 2023
1 parent 75465a3 commit 9a99e76
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 88 deletions.
70 changes: 17 additions & 53 deletions src/AzureIoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@
<MudButton id="exportTemplateButton" Variant="Variant.Text" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Download" OnClick="ExportTemplateFile">Download template file</MudButton>
</MudItem>
<MudItem>
<MudFileUpload T="IBrowserFile" FilesChanged="ImportDeviceList">
<MudFileUpload id="importDevicesButton" T="IBrowserFile" FilesChanged="ImportDeviceList">
<ButtonTemplate>
<MudButton id="importDevicesButton" Variant="Variant.Text"
<MudButton Variant="Variant.Text"
HtmlTag="label"
Color="Color.Primary"
StartIcon="@Icons.Outlined.Upload"
Expand All @@ -166,7 +166,7 @@
</ToolBarContent>
<HeaderContent>
<MudTh></MudTh>
<MudTh><MudTableSortLabel SortLabel="Id" T="DeviceListItem">Device</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel id="sortDeviceId" SortLabel="Id" T="DeviceListItem">Device</MudTableSortLabel></MudTh>
<MudTh Style="text-align: center"><MudTableSortLabel SortLabel="IsEnabled" T="DeviceListItem">Allowed</MudTableSortLabel></MudTh>
<MudTh Style="text-align: center"><MudTableSortLabel SortLabel="IsConnected" T="DeviceListItem">Connection state</MudTableSortLabel></MudTh>
<MudTh Style="text-align: center"><MudTableSortLabel SortLabel="StatusUpdatedTime" T="DeviceListItem">Last status update</MudTableSortLabel></MudTh>
Expand Down Expand Up @@ -241,7 +241,7 @@
</MudTd>
<MudTd DataLabel="Delete" Style="text-align: center">
<MudTooltip Text="Delete device">
<MudIconButton Color="Color.Default" Icon="@Icons.Material.Filled.Delete" Size="Size.Medium" OnClick="@(e => DeleteDevice(context))"></MudIconButton>
<MudIconButton id="@($"delete-device-{@context.DeviceID}")" Color="Color.Default" Icon="@Icons.Material.Filled.Delete" Size="Size.Medium" OnClick="@(e => DeleteDevice(context))"></MudIconButton>
</MudTooltip>
</MudTd>
</RowTemplate>
Expand Down Expand Up @@ -271,17 +271,9 @@

private bool IsLoading { get; set; } = true;

private List<DeviceModelDto> ModelList = new List<DeviceModelDto>();
private DeviceModelDto _model;
private List<DeviceModelDto> ModelList = new List<DeviceModelDto>();

public DeviceModelDto Model
{
get => _model;
set
{
Task.Run(async () => await ChangeModel(value));
}
}
private DeviceModelDto Model {get; set;}

private IEnumerable<DeviceTagDto> TagList { get; set; } = new List<DeviceTagDto>();

Expand Down Expand Up @@ -413,29 +405,7 @@
private void GoToDetails(DeviceListItem item)
{
navigationManager.NavigateTo($"devices/{item.DeviceID}{((item.SupportLoRaFeatures && Portal.IsLoRaSupported) ? "?isLora=true" : "")}");
}

internal async Task ChangeModel(DeviceModelDto Model)
{
try
{
this._model = Model;

if (Model == null || string.IsNullOrWhiteSpace(Model.ModelId))
{
return;
}

}
catch (ProblemDetailsException exception)
{
Error?.ProcessProblemDetails(exception);
}
finally
{
await InvokeAsync(StateHasChanged);
}
}
}

/// <summary>
/// Allows to autocomplete the Device Model field in the form.
Expand Down Expand Up @@ -488,24 +458,18 @@
private async Task ImportDeviceList(IBrowserFile file)
{
menuIsOpen = false;
try
{
var fileContent = new StreamContent(file.OpenReadStream());
fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);

var content = new MultipartFormDataContent();
content.Add(content: fileContent,
name: "\"file\"",
fileName: file.Name);
var fileContent = new StreamContent(file.OpenReadStream());
fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);

var parameters = new DialogParameters { { "Content", content } };
var options = new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true, CloseButton = true };
await DialogService.Show<ImportReportDialog>("Import summary", parameters, options).Result;
}
catch (ProblemDetailsException exception)
{
Error?.ProcessProblemDetails(exception);
}
var content = new MultipartFormDataContent();
content.Add(content: fileContent,
name: "\"file\"",
fileName: file.Name);

var parameters = new DialogParameters { { "Content", content } };
var options = new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true, CloseButton = true };
await DialogService.Show<ImportReportDialog>("Import summary", parameters, options).Result;
}

public bool menuIsOpen;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@ namespace AzureIoTHub.Portal.Tests.Unit.Client.Pages.Devices
using Bunit;
using Bunit.TestDoubles;
using FluentAssertions;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.DependencyInjection;
using Models.v10;
using Moq;
using MudBlazor;
using NUnit.Framework;
using System.Linq;
using AzureIoTHub.Portal.Shared.Models.v10;
using UnitTests.Bases;
using AutoFixture;
using Microsoft.AspNetCore.Components.Forms;

[TestFixture]
public class DevicesListPageTests : BlazorUnitTest
Expand Down Expand Up @@ -72,18 +70,19 @@ public void DeviceListPageRendersCorrectly()
service.GetDevices($"{this.apiBaseUrl}?pageNumber=0&pageSize=10&searchText=&searchStatus=&searchState=&orderBy=&modelId="))
.ReturnsAsync(new PaginationResult<DeviceListItem>
{
Items = Array.Empty<DeviceListItem>()
Items = new[] { new DeviceListItem { DeviceID = Guid.NewGuid().ToString(), IsEnabled = true, IsConnected = true } }
});

_ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true });

// Act
var cut = RenderComponent<DeviceListPage>();
cut.WaitForAssertion(() => cut.Markup.Should().NotContain("Loading..."));

// Assert
cut.WaitForAssertion(() => cut.Find(".mud-expansion-panels .mud-expand-panel .mud-expand-panel-header .mud-expand-panel-text").TextContent.Should().Be("Search panel"));
cut.WaitForAssertion(() => cut.Find(".mud-expansion-panels .mud-expand-panel").ClassList.Should().NotContain("Search panel should be collapsed"));

cut.WaitForAssertion(() => cut.FindAll("table tbody tr").Count.Should().Be(1));
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}

Expand Down Expand Up @@ -322,10 +321,9 @@ public void LoadItemsShouldProcessProblemDetailsExceptionWhenIssueOccursOnGettin
}

[Test]
public async Task FliterBySelectModelShould()
public async Task TypingSomeCharactersInTheAutocompleteShouldFilterTheDeviceModels()
{
// Arrange
//var expectedUrl = "api/devices?pageNumber=0&pageSize=10&searchText=&searchStatus=&orderBy=&modelId=";
_ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags())
.ReturnsAsync(new List<DeviceTagDto>());

Expand Down Expand Up @@ -420,6 +418,45 @@ public void ShowDeviceTelemetry_Clicked_LoRaDeviceTelemetryDialogIsShown()
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}

[Test]
public void DeleteDevice_Clicked_DeleteDeviceDialogIsShown()
{
// Arrange
var deviceId = Guid.NewGuid().ToString();

_ = this.mockDeviceClientService.Setup(service =>
service.GetDevices($"{this.apiBaseUrl}?pageNumber=0&pageSize=10&searchText=&searchStatus=&searchState=&orderBy=&modelId="))
.ReturnsAsync(new PaginationResult<DeviceListItem>
{
Items = new[] { new DeviceListItem { DeviceID = deviceId, SupportLoRaFeatures = true, HasLoRaTelemetry = true } }
});

_ = this.mockDeviceClientService.Setup(service => service.GetAvailableLabels())
.ReturnsAsync(Array.Empty<LabelDto>());

_ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true });

_ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags())
.ReturnsAsync(new List<DeviceTagDto>());

_ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels())
.ReturnsAsync(new List<DeviceModelDto>());

var mockDialogReference = MockRepository.Create<IDialogReference>();
_ = mockDialogReference.Setup(c => c.Result).ReturnsAsync(DialogResult.Ok("Ok"));
_ = this.mockDialogService.Setup(c => c.Show<DeleteDevicePage>(It.IsAny<string>(), It.IsAny<DialogParameters>()))
.Returns(mockDialogReference.Object);

var cut = RenderComponent<DeviceListPage>();
cut.WaitForAssertion(() => cut.Markup.Should().NotContain("Loading..."));

// Act
cut.WaitForElement($"#delete-device-{deviceId}").Click();

// Assert
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}

[Test]
public async Task ExportDevicesClickedShouldDownloadTheFile()
{
Expand Down Expand Up @@ -545,47 +582,139 @@ public void SearchDeviceModels_InputExisingDeviceModelName_DeviceModelReturned()
var items = popoverProvider.FindComponents<MudListItem>().ToArray();
_ = items.Length.Should().Be(1);
_ = items.First().Markup.Should().Contain(expectedDeviceModel.Name);
items.First().Find("div.mud-list-item").Click();

cut.WaitForAssertion(() => MockRepository.VerifyAll());
}

//[Test]
//public async Task ImportDevicesClickedShouldImportTheFile()
//{
// // Arrange
// var deviceId = Guid.NewGuid().ToString();
[Test]
public async Task ImportDevices_FileAdded_DevicesExported()
{
// Arrange
var deviceId = Guid.NewGuid().ToString();
List<InputFileContent> Files = new()
{
InputFileContent.CreateFromText(Guid.NewGuid().ToString(), "upload.csv", contentType: "text/csv")
};

_ = this.mockDeviceClientService.Setup(service =>
service.GetDevices($"{this.apiBaseUrl}?pageNumber=0&pageSize=10&searchText=&searchStatus=&searchState=&orderBy=&modelId="))
.ReturnsAsync(new PaginationResult<DeviceListItem>
{
Items = new[] { new DeviceListItem { DeviceID = deviceId, SupportLoRaFeatures = true } }
});

_ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true });

// _ = this.mockDeviceClientService.Setup(service =>
// service.GetDevices($"{this.apiBaseUrl}?pageNumber=0&pageSize=10&searchText=&searchStatus=&searchState=&orderBy=&modelId="))
// .ReturnsAsync(new PaginationResult<DeviceListItem>
// {
// Items = new[] { new DeviceListItem { DeviceID = deviceId, SupportLoRaFeatures = true } }
// });
_ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags())
.ReturnsAsync(new List<DeviceTagDto>());

// _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true });
_ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels())
.ReturnsAsync(new List<DeviceModelDto>());

// _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags())
// .ReturnsAsync(new List<DeviceTagDto>());
_ = this.mockDeviceClientService.Setup(service => service.GetAvailableLabels())
.ReturnsAsync(Array.Empty<LabelDto>());

// _ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels())
// .ReturnsAsync(new List<DeviceModelDto>());
var mockDialogReference = MockRepository.Create<IDialogReference>();
_ = mockDialogReference.Setup(c => c.Result).ReturnsAsync(DialogResult.Ok("Ok"));
_ = this.mockDialogService.Setup(c => c.Show<ImportReportDialog>(It.IsAny<string>(), It.IsAny<DialogParameters>(), It.IsAny<DialogOptions>()))
.Returns(mockDialogReference.Object);

// _ = this.mockDeviceClientService.Setup(c => c.ImportDeviceList(It.IsAny<MultipartFormDataContent>()))
// .ReturnsAsync(Array.Empty<ImportResultLine>());
var popoverProvider = RenderComponent<MudPopoverProvider>();
var cut = RenderComponent<DeviceListPage>();

// var popoverProvider = RenderComponent<MudPopoverProvider>();
// var cut = RenderComponent<DeviceListPage>();
cut.WaitForAssertion(() => cut.Markup.Should().NotContain("loading..."));

// cut.WaitForAssertion(() => cut.Markup.Should().NotContain("Loading..."));
cut.Find("#manageDevicesButtonToggle").Click();
var multiple = popoverProvider.FindComponent<MudFileUpload<IBrowserFile>>();
var multipleInput = multiple.FindComponent<InputFile>();

// popoverProvider.FindComponent<MudFileUpload<IBrowserFile>>()
// .Instance.
// Act
multipleInput.UploadFiles(Files.ToArray());

// // Act
// popoverProvider.WaitForElement("#importDevicesButton").Click();
// Assert
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}

// // Assert
// cut.WaitForAssertion(() => MockRepository.VerifyAll());
//}
[Test]
public void Sort_ClickOnSortIdAsc_DevicesSorted()
{
// Arrange
_ = this.mockDeviceClientService.Setup(service =>
service.GetDevices($"{this.apiBaseUrl}?pageNumber=0&pageSize=10&searchText=&searchStatus=&searchState=&orderBy=&modelId="))
.ReturnsAsync(new PaginationResult<DeviceListItem>
{
Items = Array.Empty<DeviceListItem>()
});
_ = this.mockDeviceClientService.Setup(service =>
service.GetDevices($"{this.apiBaseUrl}?pageNumber=0&pageSize=10&searchText=&searchStatus=&searchState=&orderBy=Id asc&modelId="))
.ReturnsAsync(new PaginationResult<DeviceListItem>
{
Items = Array.Empty<DeviceListItem>()
});

_ = this.mockDeviceClientService.Setup(service => service.GetAvailableLabels())
.ReturnsAsync(Array.Empty<LabelDto>());

_ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true });

_ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags())
.ReturnsAsync(new List<DeviceTagDto>());

_ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels())
.ReturnsAsync(new List<DeviceModelDto>());

var cut = RenderComponent<DeviceListPage>();

// Act
cut.WaitForElement("#sortDeviceId").Click();

// Assert
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}

[Test]
public void Sort_ClickOnSortIdDesc_DevicesSorted()
{
// Arrange
_ = this.mockDeviceClientService.Setup(service =>
service.GetDevices($"{this.apiBaseUrl}?pageNumber=0&pageSize=10&searchText=&searchStatus=&searchState=&orderBy=&modelId="))
.ReturnsAsync(new PaginationResult<DeviceListItem>
{
Items = Array.Empty<DeviceListItem>()
});
_ = this.mockDeviceClientService.Setup(service =>
service.GetDevices($"{this.apiBaseUrl}?pageNumber=0&pageSize=10&searchText=&searchStatus=&searchState=&orderBy=Id asc&modelId="))
.ReturnsAsync(new PaginationResult<DeviceListItem>
{
Items = Array.Empty<DeviceListItem>()
});
_ = this.mockDeviceClientService.Setup(service =>
service.GetDevices($"{this.apiBaseUrl}?pageNumber=0&pageSize=10&searchText=&searchStatus=&searchState=&orderBy=Id desc&modelId="))
.ReturnsAsync(new PaginationResult<DeviceListItem>
{
Items = Array.Empty<DeviceListItem>()
});

_ = this.mockDeviceClientService.Setup(service => service.GetAvailableLabels())
.ReturnsAsync(Array.Empty<LabelDto>());

_ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = true });

_ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags())
.ReturnsAsync(new List<DeviceTagDto>());

_ = this.mockDeviceModelsClientService.Setup(service => service.GetDeviceModels())
.ReturnsAsync(new List<DeviceModelDto>());

var cut = RenderComponent<DeviceListPage>();

// Act
cut.WaitForElement("#sortDeviceId").Click();
cut.WaitForElement("#sortDeviceId").Click();

// Assert
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}
}
}

0 comments on commit 9a99e76

Please sign in to comment.