From 0fba694383ca5dad0854fdf09b3f94df7a3238ea Mon Sep 17 00:00:00 2001 From: Jon Crall Date: Tue, 30 Dec 2025 16:08:00 -0500 Subject: [PATCH] Refine select-all helper and add coverage --- .../ErsatzTV.Core.Tests.csproj | 1 + .../Pages/MediaCardSelectionHelperTests.cs | 38 +++++++++++++++++++ ErsatzTV/Pages/MediaCardSelectionHelper.cs | 20 ++++++++++ ErsatzTV/Pages/MultiSelectBase.cs | 10 ++--- 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 ErsatzTV.Core.Tests/Pages/MediaCardSelectionHelperTests.cs create mode 100644 ErsatzTV/Pages/MediaCardSelectionHelper.cs diff --git a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj index b480672de..8838b8727 100644 --- a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj +++ b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj @@ -30,6 +30,7 @@ + diff --git a/ErsatzTV.Core.Tests/Pages/MediaCardSelectionHelperTests.cs b/ErsatzTV.Core.Tests/Pages/MediaCardSelectionHelperTests.cs new file mode 100644 index 000000000..c39e911e0 --- /dev/null +++ b/ErsatzTV.Core.Tests/Pages/MediaCardSelectionHelperTests.cs @@ -0,0 +1,38 @@ +using ErsatzTV.Application.MediaCards; +using ErsatzTV.Pages; +using NUnit.Framework; +using Shouldly; +using System.Collections.Generic; + +namespace ErsatzTV.Core.Tests.Pages; + +[TestFixture] +public class MediaCardSelectionHelperTests +{ + [Test] + public void Should_replace_existing_selection_and_return_last_card() + { + var existingCard = new MediaCardViewModel(1, "Existing", "Sub", "Existing", "", Core.Domain.MediaItemState.Normal, false); + var selected = new HashSet { existingCard }; + + var first = new MediaCardViewModel(2, "First", "Sub", "First", "", Core.Domain.MediaItemState.Normal, false); + var second = new MediaCardViewModel(3, "Second", "Sub", "Second", "", Core.Domain.MediaItemState.Normal, false); + + MediaCardViewModel last = MediaCardSelectionHelper.SelectAllPageItems(selected, new[] { first, second }); + + selected.ShouldBe(new[] { first, second }, ignoreOrder: true); + last.ShouldBe(second); + } + + [Test] + public void Should_clear_selection_when_no_cards() + { + var existingCard = new MediaCardViewModel(1, "Existing", "Sub", "Existing", "", Core.Domain.MediaItemState.Normal, false); + var selected = new HashSet { existingCard }; + + MediaCardViewModel last = MediaCardSelectionHelper.SelectAllPageItems(selected, []); + + selected.ShouldBeEmpty(); + last.ShouldBeNull(); + } +} diff --git a/ErsatzTV/Pages/MediaCardSelectionHelper.cs b/ErsatzTV/Pages/MediaCardSelectionHelper.cs new file mode 100644 index 000000000..d94b11db0 --- /dev/null +++ b/ErsatzTV/Pages/MediaCardSelectionHelper.cs @@ -0,0 +1,20 @@ +using ErsatzTV.Application.MediaCards; +using System.Collections.Generic; +using System.Linq; + +namespace ErsatzTV.Pages; + +public static class MediaCardSelectionHelper +{ + public static MediaCardViewModel SelectAllPageItems( + ISet selectedItems, + IEnumerable cards) + { + List cardList = (cards ?? Enumerable.Empty()).ToList(); + + selectedItems.Clear(); + selectedItems.UnionWith(cardList); + + return cardList.LastOrDefault(); + } +} diff --git a/ErsatzTV/Pages/MultiSelectBase.cs b/ErsatzTV/Pages/MultiSelectBase.cs index e5eb72673..42fdb54f5 100644 --- a/ErsatzTV/Pages/MultiSelectBase.cs +++ b/ErsatzTV/Pages/MultiSelectBase.cs @@ -8,6 +8,8 @@ using MediatR; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using MudBlazor; +using System.Linq; +using static LanguageExt.Prelude; namespace ErsatzTV.Pages; @@ -40,12 +42,8 @@ public class MultiSelectBase : FragmentNavigationBase protected void SelectAllPageItems(IEnumerable cards) { - SelectedItems.Clear(); - foreach (MediaCardViewModel card in cards) - { - _recentlySelected = card; - SelectedItems.Add(card); - } + MediaCardViewModel lastSelected = MediaCardSelectionHelper.SelectAllPageItems(SelectedItems, cards); + _recentlySelected = Optional(lastSelected); StateHasChanged(); }