diff --git a/SharepointToolbox.Tests/Helpers/PermissionLevelMappingTests.cs b/SharepointToolbox.Tests/Helpers/PermissionLevelMappingTests.cs new file mode 100644 index 0000000..ac6f035 --- /dev/null +++ b/SharepointToolbox.Tests/Helpers/PermissionLevelMappingTests.cs @@ -0,0 +1,87 @@ +using SharepointToolbox.Core.Helpers; +using SharepointToolbox.Core.Models; + +namespace SharepointToolbox.Tests.Helpers; + +/// +/// Unit tests for PermissionLevelMapping static helper. +/// SIMP-01: Validates mapping correctness for known roles, unknown fallback, +/// case insensitivity, semicolon splitting, risk ranking, and label generation. +/// +public class PermissionLevelMappingTests +{ + [Theory] + [InlineData("Full Control", RiskLevel.High)] + [InlineData("Site Collection Administrator", RiskLevel.High)] + [InlineData("Contribute", RiskLevel.Medium)] + [InlineData("Edit", RiskLevel.Medium)] + [InlineData("Design", RiskLevel.Medium)] + [InlineData("Approve", RiskLevel.Medium)] + [InlineData("Manage Hierarchy", RiskLevel.Medium)] + [InlineData("Read", RiskLevel.Low)] + [InlineData("Restricted Read", RiskLevel.Low)] + [InlineData("View Only", RiskLevel.ReadOnly)] + [InlineData("Restricted View", RiskLevel.ReadOnly)] + public void GetMapping_KnownRoles_ReturnsCorrectRiskLevel(string roleName, RiskLevel expected) + { + var result = PermissionLevelMapping.GetMapping(roleName); + Assert.Equal(expected, result.RiskLevel); + Assert.NotEmpty(result.Label); + } + + [Fact] + public void GetMapping_UnknownRole_ReturnsMediumRiskWithRawName() + { + var result = PermissionLevelMapping.GetMapping("Custom Permission Level"); + Assert.Equal(RiskLevel.Medium, result.RiskLevel); + Assert.Equal("Custom Permission Level", result.Label); + } + + [Fact] + public void GetMapping_CaseInsensitive() + { + var lower = PermissionLevelMapping.GetMapping("full control"); + var upper = PermissionLevelMapping.GetMapping("FULL CONTROL"); + Assert.Equal(RiskLevel.High, lower.RiskLevel); + Assert.Equal(RiskLevel.High, upper.RiskLevel); + } + + [Fact] + public void GetMappings_SemicolonDelimited_SplitsAndMaps() + { + var results = PermissionLevelMapping.GetMappings("Full Control; Read"); + Assert.Equal(2, results.Count); + Assert.Equal(RiskLevel.High, results[0].RiskLevel); + Assert.Equal(RiskLevel.Low, results[1].RiskLevel); + } + + [Fact] + public void GetMappings_EmptyString_ReturnsEmpty() + { + var results = PermissionLevelMapping.GetMappings(""); + Assert.Empty(results); + } + + [Fact] + public void GetHighestRisk_MultipleLevels_ReturnsHighest() + { + // Full Control (High) + Read (Low) => High + var risk = PermissionLevelMapping.GetHighestRisk("Full Control; Read"); + Assert.Equal(RiskLevel.High, risk); + } + + [Fact] + public void GetHighestRisk_SingleReadOnly_ReturnsReadOnly() + { + var risk = PermissionLevelMapping.GetHighestRisk("View Only"); + Assert.Equal(RiskLevel.ReadOnly, risk); + } + + [Fact] + public void GetSimplifiedLabels_JoinsLabels() + { + var labels = PermissionLevelMapping.GetSimplifiedLabels("Contribute; Read"); + Assert.Contains("Can edit files and list items", labels); + Assert.Contains("Can view files and pages", labels); + } +} diff --git a/SharepointToolbox.Tests/Models/PermissionSummaryBuilderTests.cs b/SharepointToolbox.Tests/Models/PermissionSummaryBuilderTests.cs new file mode 100644 index 0000000..6c4724b --- /dev/null +++ b/SharepointToolbox.Tests/Models/PermissionSummaryBuilderTests.cs @@ -0,0 +1,82 @@ +using SharepointToolbox.Core.Models; + +namespace SharepointToolbox.Tests.Models; + +/// +/// Unit tests for PermissionSummaryBuilder and SimplifiedPermissionEntry. +/// SIMP-02: Validates summary aggregation, risk-level grouping, distinct user counting, +/// and SimplifiedPermissionEntry wrapping behavior. +/// +public class PermissionSummaryBuilderTests +{ + private static PermissionEntry MakeEntry(string permLevels, string users = "User1", string logins = "user1@test.com") => + new PermissionEntry( + ObjectType: "Site", + Title: "Test", + Url: "https://test.sharepoint.com", + HasUniquePermissions: true, + Users: users, + UserLogins: logins, + PermissionLevels: permLevels, + GrantedThrough: "Direct Permissions", + PrincipalType: "User"); + + [Fact] + public void Build_ReturnsAllFourRiskLevels() + { + var entries = SimplifiedPermissionEntry.WrapAll(new[] + { + MakeEntry("Full Control"), + MakeEntry("Contribute"), + MakeEntry("Read"), + MakeEntry("View Only") + }); + + var summaries = PermissionSummaryBuilder.Build(entries); + + Assert.Equal(4, summaries.Count); + Assert.Contains(summaries, s => s.RiskLevel == RiskLevel.High && s.Count == 1); + Assert.Contains(summaries, s => s.RiskLevel == RiskLevel.Medium && s.Count == 1); + Assert.Contains(summaries, s => s.RiskLevel == RiskLevel.Low && s.Count == 1); + Assert.Contains(summaries, s => s.RiskLevel == RiskLevel.ReadOnly && s.Count == 1); + } + + [Fact] + public void Build_EmptyCollection_ReturnsZeroCounts() + { + var summaries = PermissionSummaryBuilder.Build(Array.Empty()); + + Assert.Equal(4, summaries.Count); + Assert.All(summaries, s => Assert.Equal(0, s.Count)); + } + + [Fact] + public void Build_CountsDistinctUsers() + { + var entries = SimplifiedPermissionEntry.WrapAll(new[] + { + MakeEntry("Full Control", "Alice", "alice@test.com"), + MakeEntry("Full Control", "Bob", "bob@test.com"), + MakeEntry("Full Control", "Alice", "alice@test.com"), // duplicate user + }); + + var summaries = PermissionSummaryBuilder.Build(entries); + var high = summaries.Single(s => s.RiskLevel == RiskLevel.High); + + Assert.Equal(3, high.Count); // 3 entries + Assert.Equal(2, high.DistinctUsers); // 2 distinct users + } + + [Fact] + public void SimplifiedPermissionEntry_WrapAll_PreservesInner() + { + var original = MakeEntry("Contribute"); + var wrapped = SimplifiedPermissionEntry.WrapAll(new[] { original }); + + Assert.Single(wrapped); + Assert.Same(original, wrapped[0].Inner); + Assert.Equal("Contribute", wrapped[0].PermissionLevels); + Assert.Equal(RiskLevel.Medium, wrapped[0].RiskLevel); + Assert.Contains("Can edit", wrapped[0].SimplifiedLabels); + } +}