- 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
257 lines
12 KiB
C#
257 lines
12 KiB
C#
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);
|
|
}
|
|
}
|