From c35ee76987a36b848851a6bc3e7cfb87d7ecc37f Mon Sep 17 00:00:00 2001 From: Dev Date: Thu, 9 Apr 2026 13:07:46 +0200 Subject: [PATCH] test(17-02): add failing tests for group pill expansion and backward compatibility - BuildHtml_NoGroupMembers_IdenticalToDefault - BuildHtml_WithGroupMembers_RendersExpandablePill - BuildHtml_WithGroupMembers_RendersHiddenMemberSubRow - BuildHtml_WithEmptyMemberList_RendersMembersUnavailable - BuildHtml_ContainsToggleGroupJs - BuildHtml_Simplified_WithGroupMembers_RendersExpandablePill --- .../Services/Export/HtmlExportServiceTests.cs | 89 ++++++++++++++++++- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/SharepointToolbox.Tests/Services/Export/HtmlExportServiceTests.cs b/SharepointToolbox.Tests/Services/Export/HtmlExportServiceTests.cs index ac8de01..2889bf6 100644 --- a/SharepointToolbox.Tests/Services/Export/HtmlExportServiceTests.cs +++ b/SharepointToolbox.Tests/Services/Export/HtmlExportServiceTests.cs @@ -5,15 +5,14 @@ namespace SharepointToolbox.Tests.Services.Export; /// /// Tests for PERM-06: HTML export output. -/// These tests reference HtmlExportService which will be implemented in Plan 03. -/// Until Plan 03 runs they will fail to compile — that is expected. /// public class HtmlExportServiceTests { private static PermissionEntry MakeEntry( string users, string userLogins, - string url = "https://contoso.sharepoint.com/sites/A") => - new("Web", "Site A", url, true, users, userLogins, "Read", "Direct Permissions", "User"); + string url = "https://contoso.sharepoint.com/sites/A", + string principalType = "User") => + new("Web", "Site A", url, true, users, userLogins, "Read", "Direct Permissions", principalType); private static ReportBranding MakeBranding(bool msp = true, bool client = false) { @@ -22,6 +21,13 @@ public class HtmlExportServiceTests return new ReportBranding(mspLogo, clientLogo); } + private static IReadOnlyDictionary> MakeGroupMembers( + string groupName, params ResolvedMember[] members) => + new Dictionary>(StringComparer.OrdinalIgnoreCase) + { + [groupName] = members.ToList() + }; + [Fact] public void BuildHtml_WithKnownEntries_ContainsUserNames() { @@ -87,4 +93,79 @@ public class HtmlExportServiceTests Assert.Contains("data:image/png;base64,bXNw", html); Assert.Contains("data:image/jpeg;base64,Y2xpZW50", html); } + + // ── Group expansion tests (Phase 17) ────────────────────────────────────── + + [Fact] + public void BuildHtml_NoGroupMembers_IdenticalToDefault() + { + var entry = MakeEntry("Site Members", "i:0#.f|membership|group@contoso.com", principalType: "SharePointGroup"); + var svc = new HtmlExportService(); + var htmlDefault = svc.BuildHtml(new[] { entry }); + var htmlNullNull = svc.BuildHtml(new[] { entry }, null, null); + + Assert.Equal(htmlDefault, htmlNullNull); + } + + [Fact] + public void BuildHtml_WithGroupMembers_RendersExpandablePill() + { + var entry = MakeEntry("Site Members", "i:0#.f|membership|group@contoso.com", principalType: "SharePointGroup"); + var groupMembers = MakeGroupMembers("Site Members", new ResolvedMember("Alice", "alice@co.com")); + var svc = new HtmlExportService(); + var html = svc.BuildHtml(new[] { entry }, null, groupMembers); + + Assert.Contains("onclick=\"toggleGroup('grpmem0')\"", html); + Assert.Contains("class=\"user-pill group-expandable\"", html); + } + + [Fact] + public void BuildHtml_WithGroupMembers_RendersHiddenMemberSubRow() + { + var entry = MakeEntry("Site Members", "i:0#.f|membership|group@contoso.com", principalType: "SharePointGroup"); + var groupMembers = MakeGroupMembers("Site Members", new ResolvedMember("Alice", "alice@co.com")); + var svc = new HtmlExportService(); + var html = svc.BuildHtml(new[] { entry }, null, groupMembers); + + Assert.Contains("data-group=\"grpmem0\"", html); + Assert.Contains("display:none", html); + Assert.Contains("Alice", html); + Assert.Contains("alice@co.com", html); + } + + [Fact] + public void BuildHtml_WithEmptyMemberList_RendersMembersUnavailable() + { + var entry = MakeEntry("Site Members", "i:0#.f|membership|group@contoso.com", principalType: "SharePointGroup"); + var groupMembers = MakeGroupMembers("Site Members"); // empty list + var svc = new HtmlExportService(); + var html = svc.BuildHtml(new[] { entry }, null, groupMembers); + + Assert.Contains("members unavailable", html); + } + + [Fact] + public void BuildHtml_ContainsToggleGroupJs() + { + var entry = MakeEntry("Site Members", "i:0#.f|membership|group@contoso.com", principalType: "SharePointGroup"); + var groupMembers = MakeGroupMembers("Site Members", new ResolvedMember("Alice", "alice@co.com")); + var svc = new HtmlExportService(); + var html = svc.BuildHtml(new[] { entry }, null, groupMembers); + + Assert.Contains("function toggleGroup", html); + } + + [Fact] + public void BuildHtml_Simplified_WithGroupMembers_RendersExpandablePill() + { + var innerEntry = new PermissionEntry("Web", "Site A", "https://contoso.sharepoint.com/sites/A", + true, "Site Members", "i:0#.f|membership|group@contoso.com", "Read", "Direct Permissions", "SharePointGroup"); + var simplifiedEntry = new SimplifiedPermissionEntry(innerEntry); + var groupMembers = MakeGroupMembers("Site Members", new ResolvedMember("Bob", "bob@co.com")); + var svc = new HtmlExportService(); + var html = svc.BuildHtml(new[] { simplifiedEntry }, null, groupMembers); + + Assert.Contains("onclick=\"toggleGroup('grpmem0')\"", html); + Assert.Contains("class=\"user-pill group-expandable\"", html); + } }