chore: archive v1.1 Enhanced Reports milestone
Some checks failed
Release SharePoint Toolbox v2 / release (push) Failing after 14s
Some checks failed
Release SharePoint Toolbox v2 / release (push) Failing after 14s
v1.1 shipped with 4 phases (25 plans), 10/10 requirements complete: - Global site selection (toolbar picker, all tabs consume) - User access audit (Graph people-picker, direct/group/inherited) - Simplified permissions (plain-language labels, risk levels, detail toggle) - Storage visualization (LiveCharts2 pie/donut + bar charts) Post-phase polish: centralized site selection (removed per-tab pickers), claims prefix stripping, StorageMetrics backfill, chart tooltip fix, summary stats in app + HTML exports. 205 tests passing, 10,484 LOC. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -85,7 +85,8 @@ public class UserAccessAuditViewModelTests
|
||||
var (vm, auditMock, _) = CreateViewModel();
|
||||
|
||||
vm.SelectedUsers.Add(MakeUser());
|
||||
vm.SelectedSites.Add(new SiteInfo("https://contoso.sharepoint.com", "Contoso"));
|
||||
WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(
|
||||
new List<SiteInfo> { new("https://contoso.sharepoint.com", "Contoso") }.AsReadOnly()));
|
||||
|
||||
await vm.TestRunOperationAsync(CancellationToken.None, new Progress<OperationProgress>());
|
||||
|
||||
@@ -115,7 +116,8 @@ public class UserAccessAuditViewModelTests
|
||||
var (vm, _, _) = CreateViewModel(entries);
|
||||
|
||||
vm.SelectedUsers.Add(MakeUser());
|
||||
vm.SelectedSites.Add(new SiteInfo("https://contoso.sharepoint.com", "Contoso"));
|
||||
WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(
|
||||
new List<SiteInfo> { new("https://contoso.sharepoint.com", "Contoso") }.AsReadOnly()));
|
||||
|
||||
await vm.TestRunOperationAsync(CancellationToken.None, new Progress<OperationProgress>());
|
||||
|
||||
@@ -137,7 +139,8 @@ public class UserAccessAuditViewModelTests
|
||||
var (vm, _, _) = CreateViewModel(entries);
|
||||
|
||||
vm.SelectedUsers.Add(MakeUser());
|
||||
vm.SelectedSites.Add(new SiteInfo("https://contoso.sharepoint.com", "Contoso"));
|
||||
WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(
|
||||
new List<SiteInfo> { new("https://contoso.sharepoint.com", "Contoso") }.AsReadOnly()));
|
||||
|
||||
await vm.TestRunOperationAsync(CancellationToken.None, new Progress<OperationProgress>());
|
||||
|
||||
@@ -156,7 +159,8 @@ public class UserAccessAuditViewModelTests
|
||||
|
||||
// Populate state
|
||||
vm.SelectedUsers.Add(MakeUser());
|
||||
vm.SelectedSites.Add(new SiteInfo("https://contoso.sharepoint.com", "Contoso"));
|
||||
WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(
|
||||
new List<SiteInfo> { new("https://contoso.sharepoint.com", "Contoso") }.AsReadOnly()));
|
||||
await vm.TestRunOperationAsync(CancellationToken.None, new Progress<OperationProgress>());
|
||||
Assert.NotEmpty(vm.Results);
|
||||
Assert.NotEmpty(vm.SelectedUsers);
|
||||
@@ -173,54 +177,31 @@ public class UserAccessAuditViewModelTests
|
||||
// Assert: state cleared
|
||||
Assert.Empty(vm.Results);
|
||||
Assert.Empty(vm.SelectedUsers);
|
||||
Assert.Empty(vm.SelectedSites);
|
||||
Assert.Empty(vm.FilterText);
|
||||
}
|
||||
|
||||
// ── Test 5: GlobalSitesChanged updates SelectedSites ─────────────────────
|
||||
// ── Test 5: RunOperation uses GlobalSites directly ─────────────────────
|
||||
|
||||
[Fact]
|
||||
public void OnGlobalSitesChanged_updates_selected_sites()
|
||||
public async Task RunOperation_fails_gracefully_without_global_sites()
|
||||
{
|
||||
var (vm, _, _) = CreateViewModel();
|
||||
var sites = new List<SiteInfo>
|
||||
{
|
||||
new("https://contoso.sharepoint.com/sites/hr", "HR"),
|
||||
new("https://contoso.sharepoint.com/sites/finance", "Finance")
|
||||
}.AsReadOnly();
|
||||
var (vm, auditMock, _) = CreateViewModel();
|
||||
vm.SelectedUsers.Add(MakeUser());
|
||||
// Do NOT send GlobalSitesChangedMessage — no sites selected
|
||||
|
||||
WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(sites));
|
||||
await vm.TestRunOperationAsync(CancellationToken.None, new Progress<OperationProgress>());
|
||||
|
||||
Assert.Equal(2, vm.SelectedSites.Count);
|
||||
Assert.Equal("https://contoso.sharepoint.com/sites/hr", vm.SelectedSites[0].Url);
|
||||
}
|
||||
|
||||
// ── Test 6: GlobalSitesChanged skipped when override active ──────────────
|
||||
|
||||
[Fact]
|
||||
public void OnGlobalSitesChanged_skipped_when_override()
|
||||
{
|
||||
var (vm, _, _) = CreateViewModel();
|
||||
|
||||
// Add a local site and set the override flag via reflection
|
||||
var localSite = new SiteInfo("https://contoso.sharepoint.com/sites/local", "Local");
|
||||
vm.SelectedSites.Add(localSite);
|
||||
|
||||
var field = typeof(UserAccessAuditViewModel)
|
||||
.GetField("_hasLocalSiteOverride",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
field!.SetValue(vm, true);
|
||||
|
||||
// Act: send global sites message
|
||||
var sites = new List<SiteInfo>
|
||||
{
|
||||
new("https://contoso.sharepoint.com/sites/global1", "Global1")
|
||||
}.AsReadOnly();
|
||||
WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(sites));
|
||||
|
||||
// Assert: SelectedSites unchanged (override prevented update)
|
||||
Assert.Single(vm.SelectedSites);
|
||||
Assert.Equal("https://contoso.sharepoint.com/sites/local", vm.SelectedSites[0].Url);
|
||||
// Should not call audit service — early return with status message
|
||||
auditMock.Verify(
|
||||
s => s.AuditUsersAsync(
|
||||
It.IsAny<ISessionManager>(),
|
||||
It.IsAny<TenantProfile>(),
|
||||
It.IsAny<IReadOnlyList<string>>(),
|
||||
It.IsAny<IReadOnlyList<SiteInfo>>(),
|
||||
It.IsAny<ScanOptions>(),
|
||||
It.IsAny<IProgress<OperationProgress>>(),
|
||||
It.IsAny<CancellationToken>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
// ── Test 7: CanExport false when no results ───────────────────────────────
|
||||
@@ -245,7 +226,8 @@ public class UserAccessAuditViewModelTests
|
||||
var (vm, _, _) = CreateViewModel(entries);
|
||||
|
||||
vm.SelectedUsers.Add(MakeUser());
|
||||
vm.SelectedSites.Add(new SiteInfo("https://contoso.sharepoint.com", "Contoso"));
|
||||
WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(
|
||||
new List<SiteInfo> { new("https://contoso.sharepoint.com", "Contoso") }.AsReadOnly()));
|
||||
|
||||
await vm.TestRunOperationAsync(CancellationToken.None, new Progress<OperationProgress>());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user