using SharepointToolbox.Core.Helpers; namespace SharepointToolbox.Tests.Services; /// /// Tests for PERM-03: external user detection, permission-level filtering, /// and SharePoint system-group classification (Limited Access / SharingLinks). /// Pure static logic — runs immediately without stubs. /// public class PermissionEntryClassificationTests { // ── IsExternalUser ───────────────────────────────────────────────────────── [Fact] public void IsExternalUser_WithExtHashInLoginName_ReturnsTrue() { Assert.True(PermissionEntryHelper.IsExternalUser("ext_user_domain.com#EXT#@contoso.onmicrosoft.com")); } [Fact] public void IsExternalUser_WithNormalLoginName_ReturnsFalse() { Assert.False(PermissionEntryHelper.IsExternalUser("i:0#.f|membership|alice@contoso.com")); } // ── FilterPermissionLevels ───────────────────────────────────────────────── [Fact] public void PermissionEntry_FiltersOutLimitedAccess_WhenOnlyPermissionIsLimitedAccess() { var result = PermissionEntryHelper.FilterPermissionLevels(new[] { "Limited Access" }); Assert.Empty(result); } [Fact] public void FilterPermissionLevels_RetainsOtherLevels_WhenMixedWithLimitedAccess() { var result = PermissionEntryHelper.FilterPermissionLevels(new[] { "Limited Access", "Contribute" }); Assert.Equal(new[] { "Contribute" }, result); } // ── IsBareLimitedAccessSystemGroup ───────────────────────────────────────── [Fact] public void IsBareLimitedAccessSystemGroup_WithExactMatch_ReturnsTrue() { Assert.True(PermissionEntryHelper.IsBareLimitedAccessSystemGroup("Limited Access System Group")); } [Fact] public void IsBareLimitedAccessSystemGroup_WithForWebVariant_ReturnsFalse() { // The "For Web {guid}" variant is enriched, not filtered. Assert.False(PermissionEntryHelper.IsBareLimitedAccessSystemGroup( "Limited Access System Group For Web e55a4f7a-b132-4baa-bd96-c63d8dc1fc80")); } [Fact] public void IsBareLimitedAccessSystemGroup_WithNormalGroup_ReturnsFalse() { Assert.False(PermissionEntryHelper.IsBareLimitedAccessSystemGroup("Owners")); } // ── Classify ─────────────────────────────────────────────────────────────── [Fact] public void Classify_WithNormalGroupTitle_ReturnsNone() { var c = PermissionEntryHelper.Classify("Site Owners"); Assert.Equal(SystemGroupKind.None, c.Kind); } [Fact] public void Classify_WithBareLimitedAccess_ReturnsLimitedAccessBare() { var c = PermissionEntryHelper.Classify("Limited Access System Group"); Assert.Equal(SystemGroupKind.LimitedAccessBare, c.Kind); } [Fact] public void Classify_WithLimitedAccessForWeb_ExtractsWebId() { var c = PermissionEntryHelper.Classify( "Limited Access System Group For Web e55a4f7a-b132-4baa-bd96-c63d8dc1fc80"); Assert.Equal(SystemGroupKind.LimitedAccessWeb, c.Kind); Assert.Equal(Guid.Parse("e55a4f7a-b132-4baa-bd96-c63d8dc1fc80"), c.WebId); Assert.Null(c.ListId); Assert.Null(c.ItemUniqueId); } [Fact] public void Classify_WithLimitedAccessForList_ExtractsListId() { var c = PermissionEntryHelper.Classify( "Limited Access System Group For List b20e3b22-2b09-4c99-9ba4-37b42f3a12dc"); Assert.Equal(SystemGroupKind.LimitedAccessList, c.Kind); Assert.Equal(Guid.Parse("b20e3b22-2b09-4c99-9ba4-37b42f3a12dc"), c.ListId); Assert.Null(c.WebId); Assert.Null(c.ItemUniqueId); } [Fact] public void Classify_WithSharingLink_ExtractsItemAndShareId() { var c = PermissionEntryHelper.Classify( "SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.OrganizationEdit.64c27910-66ea-421d-b0f0-8f0f72dcfaf6"); Assert.Equal(SystemGroupKind.SharingLink, c.Kind); Assert.Equal(Guid.Parse("e686221e-d1cb-43c5-8c68-04aa7f90f329"), c.ItemUniqueId); Assert.Equal(Guid.Parse("64c27910-66ea-421d-b0f0-8f0f72dcfaf6"), c.ShareId); Assert.Equal("OrganizationEdit", c.LinkType); } [Theory] [InlineData("SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.AnonymousView.64c27910-66ea-421d-b0f0-8f0f72dcfaf6", "AnonymousView")] [InlineData("SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.Flexible.64c27910-66ea-421d-b0f0-8f0f72dcfaf6", "Flexible")] [InlineData("SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.OrganizationView.64c27910-66ea-421d-b0f0-8f0f72dcfaf6", "OrganizationView")] public void Classify_WithVariousSharingLinkTypes_PreservesLinkType(string title, string expected) { var c = PermissionEntryHelper.Classify(title); Assert.Equal(SystemGroupKind.SharingLink, c.Kind); Assert.Equal(expected, c.LinkType); } [Fact] public void Classify_WithMalformedSharingLink_ReturnsNone() { // Missing share GUID at the end var c = PermissionEntryHelper.Classify("SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.Edit"); Assert.Equal(SystemGroupKind.None, c.Kind); } [Fact] public void Classify_WithEmptyString_ReturnsNone() { var c = PermissionEntryHelper.Classify(""); Assert.Equal(SystemGroupKind.None, c.Kind); } }