test(15-02): add PermissionConsolidatorTests with 9 test cases (RPT-04-a through RPT-04-i)

- RPT-04-a: empty input returns empty list
- RPT-04-b: single entry -> 1 row with 1 location
- RPT-04-c: 3 entries same key -> 1 row with 3 locations
- RPT-04-d: different PermissionLevel -> separate rows
- RPT-04-e: case-insensitive key merges ALICE@ and alice@
- RPT-04-f: MakeKey produces pipe-delimited lowercase format
- RPT-04-g: 11-row input with 3 merge groups -> 7 consolidated rows
- RPT-04-h: LocationCount equals Locations.Count
- RPT-04-i: IsHighPrivilege/IsExternalUser preserved from first entry
This commit is contained in:
Dev
2026-04-09 11:45:22 +02:00
parent 9bfdfb77dd
commit 7b9f3e17aa

View File

@@ -0,0 +1,256 @@
using SharepointToolbox.Core.Helpers;
using SharepointToolbox.Core.Models;
namespace SharepointToolbox.Tests.Helpers;
/// <summary>
/// Unit tests for PermissionConsolidator static helper.
/// RPT-04: Validates consolidation logic for empty input, single entry, merging,
/// case-insensitivity, MakeKey format, the 10-row/7-row scenario, LocationCount,
/// and preservation of IsHighPrivilege / IsExternalUser flags.
/// </summary>
public class PermissionConsolidatorTests
{
// ---------------------------------------------------------------------------
// Helper factory — reduces boilerplate across all test methods
// ---------------------------------------------------------------------------
private static UserAccessEntry MakeEntry(
string userLogin = "alice@contoso.com",
string siteUrl = "https://contoso.sharepoint.com/sites/hr",
string siteTitle = "HR Site",
string objectType = "List",
string objectTitle = "Documents",
string objectUrl = "https://contoso.sharepoint.com/sites/hr/Documents",
string permissionLevel = "Contribute",
AccessType accessType = AccessType.Direct,
string grantedThrough = "Direct Permissions",
string userDisplayName = "Alice Smith",
bool isHighPrivilege = false,
bool isExternalUser = false)
{
return new UserAccessEntry(
userDisplayName, userLogin, siteUrl, siteTitle,
objectType, objectTitle, objectUrl,
permissionLevel, accessType, grantedThrough,
isHighPrivilege, isExternalUser);
}
// ---------------------------------------------------------------------------
// RPT-04-a: Empty input returns empty list
// ---------------------------------------------------------------------------
[Fact]
public void Consolidate_EmptyInput_ReturnsEmptyList()
{
var result = PermissionConsolidator.Consolidate(Array.Empty<UserAccessEntry>());
Assert.Empty(result);
}
// ---------------------------------------------------------------------------
// RPT-04-b: Single entry produces 1 consolidated row with 1 location
// ---------------------------------------------------------------------------
[Fact]
public void Consolidate_SingleEntry_ReturnsOneRowWithOneLocation()
{
var entry = MakeEntry();
var result = PermissionConsolidator.Consolidate(new[] { entry });
var row = Assert.Single(result);
Assert.Single(row.Locations);
Assert.Equal("alice@contoso.com", row.UserLogin);
}
// ---------------------------------------------------------------------------
// RPT-04-c: 3 entries with same key (different sites) merge to 1 row with 3 locations
// ---------------------------------------------------------------------------
[Fact]
public void Consolidate_ThreeEntriesSameKey_ReturnsOneRowWithThreeLocations()
{
var entries = new[]
{
MakeEntry(siteUrl: "https://contoso.sharepoint.com/sites/hr", siteTitle: "HR Site"),
MakeEntry(siteUrl: "https://contoso.sharepoint.com/sites/fin", siteTitle: "Finance Site"),
MakeEntry(siteUrl: "https://contoso.sharepoint.com/sites/mkt", siteTitle: "Marketing Site"),
};
var result = PermissionConsolidator.Consolidate(entries);
Assert.Single(result);
Assert.Equal(3, result[0].Locations.Count);
}
// ---------------------------------------------------------------------------
// RPT-04-d: Entries with different keys remain as separate rows
// ---------------------------------------------------------------------------
[Fact]
public void Consolidate_DifferentKeys_RemainSeparateRows()
{
var entries = new[]
{
MakeEntry(permissionLevel: "Contribute"),
MakeEntry(permissionLevel: "Full Control"),
};
var result = PermissionConsolidator.Consolidate(entries);
Assert.Equal(2, result.Count);
}
// ---------------------------------------------------------------------------
// RPT-04-e: Case-insensitive key — "ALICE@CONTOSO.COM" and "alice@contoso.com" merge
// ---------------------------------------------------------------------------
[Fact]
public void Consolidate_CaseInsensitiveKey_MergesCorrectly()
{
var entries = new[]
{
MakeEntry(userLogin: "ALICE@CONTOSO.COM", siteUrl: "https://contoso.sharepoint.com/sites/hr"),
MakeEntry(userLogin: "alice@contoso.com", siteUrl: "https://contoso.sharepoint.com/sites/fin"),
};
var result = PermissionConsolidator.Consolidate(entries);
Assert.Single(result);
Assert.Equal(2, result[0].Locations.Count);
}
// ---------------------------------------------------------------------------
// RPT-04-f: MakeKey produces pipe-delimited lowercase format
// ---------------------------------------------------------------------------
[Fact]
public void MakeKey_ProducesPipeDelimitedLowercaseFormat()
{
var entry = MakeEntry(
userLogin: "Alice@Contoso.com",
permissionLevel: "Full Control",
accessType: AccessType.Direct,
grantedThrough: "Direct Permissions");
var key = PermissionConsolidator.MakeKey(entry);
// AccessType.ToString() preserves casing ("Direct"); all string fields are lowercased
Assert.Equal("alice@contoso.com|full control|Direct|direct permissions", key);
}
// ---------------------------------------------------------------------------
// RPT-04-g: 10-row input with 3 duplicate pairs produces 7 consolidated rows
// ---------------------------------------------------------------------------
[Fact]
public void Consolidate_TenRowsWithThreeDuplicatePairs_ReturnsSevenRows()
{
var entries = new[]
{
// alice / Contribute / Direct — 3 entries -> merges to 1
MakeEntry(userLogin: "alice@contoso.com", permissionLevel: "Contribute",
accessType: AccessType.Direct, grantedThrough: "Direct Permissions",
siteUrl: "https://contoso.sharepoint.com/sites/hr", siteTitle: "HR"),
MakeEntry(userLogin: "alice@contoso.com", permissionLevel: "Contribute",
accessType: AccessType.Direct, grantedThrough: "Direct Permissions",
siteUrl: "https://contoso.sharepoint.com/sites/fin", siteTitle: "Finance"),
MakeEntry(userLogin: "alice@contoso.com", permissionLevel: "Contribute",
accessType: AccessType.Direct, grantedThrough: "Direct Permissions",
siteUrl: "https://contoso.sharepoint.com/sites/mkt", siteTitle: "Marketing"),
// bob / Full Control / Group — 2 entries -> merges to 1
MakeEntry(userLogin: "bob@contoso.com", userDisplayName: "Bob Jones",
permissionLevel: "Full Control", accessType: AccessType.Group,
grantedThrough: "SharePoint Group: Owners",
siteUrl: "https://contoso.sharepoint.com/sites/hr", siteTitle: "HR"),
MakeEntry(userLogin: "bob@contoso.com", userDisplayName: "Bob Jones",
permissionLevel: "Full Control", accessType: AccessType.Group,
grantedThrough: "SharePoint Group: Owners",
siteUrl: "https://contoso.sharepoint.com/sites/fin", siteTitle: "Finance"),
// carol / Read / Inherited — 2 entries -> merges to 1
MakeEntry(userLogin: "carol@contoso.com", userDisplayName: "Carol White",
permissionLevel: "Read", accessType: AccessType.Inherited,
grantedThrough: "Inherited Permissions",
siteUrl: "https://contoso.sharepoint.com/sites/hr", siteTitle: "HR"),
MakeEntry(userLogin: "carol@contoso.com", userDisplayName: "Carol White",
permissionLevel: "Read", accessType: AccessType.Inherited,
grantedThrough: "Inherited Permissions",
siteUrl: "https://contoso.sharepoint.com/sites/fin", siteTitle: "Finance"),
// alice / Full Control / Direct — different key from alice's Contribute -> unique row
MakeEntry(userLogin: "alice@contoso.com", permissionLevel: "Full Control",
accessType: AccessType.Direct, grantedThrough: "Direct Permissions",
siteUrl: "https://contoso.sharepoint.com/sites/hr", siteTitle: "HR"),
// dave — unique
MakeEntry(userLogin: "dave@contoso.com", userDisplayName: "Dave Brown",
permissionLevel: "Contribute", accessType: AccessType.Direct,
grantedThrough: "Direct Permissions",
siteUrl: "https://contoso.sharepoint.com/sites/hr", siteTitle: "HR"),
// eve — unique
MakeEntry(userLogin: "eve@contoso.com", userDisplayName: "Eve Green",
permissionLevel: "Read", accessType: AccessType.Direct,
grantedThrough: "Direct Permissions",
siteUrl: "https://contoso.sharepoint.com/sites/hr", siteTitle: "HR"),
// frank — unique (4th unique row)
MakeEntry(userLogin: "frank@contoso.com", userDisplayName: "Frank Black",
permissionLevel: "Contribute", accessType: AccessType.Group,
grantedThrough: "SharePoint Group: Members",
siteUrl: "https://contoso.sharepoint.com/sites/hr", siteTitle: "HR"),
};
var result = PermissionConsolidator.Consolidate(entries);
// 3 merged groups (alice-Contribute 3->1, bob 2->1, carol 2->1) + 4 unique rows
// (alice-FullControl, dave, eve, frank) = 7 total
Assert.Equal(7, result.Count);
}
// ---------------------------------------------------------------------------
// RPT-04-h: LocationCount property equals Locations.Count for a merged entry
// ---------------------------------------------------------------------------
[Fact]
public void Consolidate_MergedEntry_LocationCountMatchesLocationsCount()
{
var entries = new[]
{
MakeEntry(siteUrl: "https://contoso.sharepoint.com/sites/hr", siteTitle: "HR"),
MakeEntry(siteUrl: "https://contoso.sharepoint.com/sites/fin", siteTitle: "Finance"),
MakeEntry(siteUrl: "https://contoso.sharepoint.com/sites/mkt", siteTitle: "Marketing"),
};
var result = PermissionConsolidator.Consolidate(entries);
Assert.Single(result);
Assert.Equal(result[0].Locations.Count, result[0].LocationCount);
Assert.Equal(3, result[0].LocationCount);
}
// ---------------------------------------------------------------------------
// RPT-04-i: IsHighPrivilege and IsExternalUser from first entry are preserved
// ---------------------------------------------------------------------------
[Fact]
public void Consolidate_PreservesIsHighPrivilegeAndIsExternalUser()
{
var entries = new[]
{
MakeEntry(isHighPrivilege: true, isExternalUser: true,
siteUrl: "https://contoso.sharepoint.com/sites/hr"),
MakeEntry(isHighPrivilege: false, isExternalUser: false,
siteUrl: "https://contoso.sharepoint.com/sites/fin"),
};
var result = PermissionConsolidator.Consolidate(entries);
Assert.Single(result);
Assert.True(result[0].IsHighPrivilege);
Assert.True(result[0].IsExternalUser);
}
}