Files
Sharepoint-Toolbox/.planning/phases/07-user-access-audit/07-08-SUMMARY.md
Dev 855e4df49b docs(07-08): complete unit tests plan summary
- 07-08-SUMMARY.md: 32 tests across 4 files, all passing
- STATE.md: advance plan, record metrics and decisions
- ROADMAP.md: phase 7 complete (8/8 plans)
2026-04-07 13:00:18 +02:00

6.6 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
07-user-access-audit 08 testing
unit-tests
xunit
moq
user-access-audit
csv-export
html-export
viewmodel
phase provides
07-02
UserAccessAuditService
phase provides
07-03
GraphUserSearchService
IGraphUserSearchService
phase provides
07-04
UserAccessAuditViewModel
phase provides
07-06
UserAccessCsvExportService
UserAccessHtmlExportService
Unit tests for UserAccessAuditService (12 tests)
Unit tests for UserAccessCsvExportService (5 tests)
Unit tests for UserAccessHtmlExportService (7 tests)
Unit tests for UserAccessAuditViewModel (8 tests)
added patterns
Moq mock setup with ReturnsAsync
reflection for private field access in override guard tests
WeakReferenceMessenger.Reset in test constructor
created modified
SharepointToolbox.Tests/Services/UserAccessAuditServiceTests.cs
SharepointToolbox.Tests/Services/Export/UserAccessCsvExportServiceTests.cs
SharepointToolbox.Tests/Services/Export/UserAccessHtmlExportServiceTests.cs
SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelTests.cs
Used internal TestRunOperationAsync to exercise ViewModel business logic directly, consistent with PermissionsViewModelTests pattern
Application.Current is null in tests — RunOperationAsync else branch executes synchronously, no Dispatcher mocking required
WeakReferenceMessenger.Default.Reset() in test constructor prevents cross-test contamination from GlobalSitesChangedMessage and TenantSwitchedMessage registrations
Reflection used to set _hasLocalSiteOverride for override guard tests, consistent with existing GlobalSiteSelectionTests pattern
UserAccess test helpers: MakeEntry() factory for UserAccessEntry, CreateViewModel() factory returns (vm, mockAudit) tuple
Service test pattern: CreateService() returns (svc, permMock, sessionMock) and sets up ScanSiteAsync/GetOrCreateContextAsync on all mocks
UACC-01
UACC-02
2min 2026-04-07

Phase 7 Plan 08: Unit Tests Summary

32 unit tests covering UserAccessAuditService (user filtering, claim matching, access classification), CSV/HTML export services (format correctness, encoding), and UserAccessAuditViewModel (audit invocation, result population, summary properties, tenant reset, site selection) — all passing with no regressions.

Performance

  • Duration: ~2 min
  • Started: 2026-04-07T11:16:30Z
  • Completed: 2026-04-07T11:18:50Z
  • Tasks: 2
  • Files modified: 4

Accomplishments

  • UserAccessAuditServiceTests (12 tests): full coverage of user login filtering, claim format bidirectional matching, Direct/Group/Inherited classification, Full Control + Site Collection Administrator high-privilege detection, external user #EXT# flagging, semicolon-delimited user and permission level splitting, multi-site scan loop verification
  • UserAccessCsvExportServiceTests (5 tests): summary section content, data header presence, RFC 4180 double-quote escaping, 7-column count enforcement, WriteSingleFileAsync multi-user combined output
  • UserAccessHtmlExportServiceTests (7 tests): DOCTYPE prefix, stat-card presence, dual-view section identifiers (view-user/view-site), access-direct/group/inherited CSS badge classes, filterTable/toggleView JS functions, HTML entity encoding for XSS-risk content
  • UserAccessAuditViewModelTests (8 tests): AuditUsersAsync mock invocation, Results population count, TotalAccessCount/SitesCount/HighPrivilegeCount computed properties, OnTenantSwitched full reset, GlobalSitesChangedMessage updates SelectedSites, override guard prevents global update, CanExport false/true states

Task Commits

  1. Task 1: Write UserAccessAuditService unit tests - 5df9503 (test)
  2. Task 2: Write export service and ViewModel tests - 35b2c2a (test)

Files Created/Modified

  • SharepointToolbox.Tests/Services/UserAccessAuditServiceTests.cs — 12 tests for audit service business logic
  • SharepointToolbox.Tests/Services/Export/UserAccessCsvExportServiceTests.cs — 5 tests for CSV export formatting
  • SharepointToolbox.Tests/Services/Export/UserAccessHtmlExportServiceTests.cs — 7 tests for HTML export content
  • SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelTests.cs — 8 tests for ViewModel orchestration

Decisions Made

  1. TestRunOperationAsync for ViewModel tests — Used the internal TestRunOperationAsync method to exercise RunOperationAsync business logic directly. This avoids requiring a full WPF application pump (no Application.Current in tests). Since Application.Current?.Dispatcher returns null in the test runner, the else branch executes synchronously — Results and summary properties are set immediately.

  2. WeakReferenceMessenger.Reset in constructor — Test class constructor calls WeakReferenceMessenger.Default.Reset() to clear all registered receivers between tests. This prevents cross-test contamination where a GlobalSitesChangedMessage from one test bleeds into another.

  3. Reflection for override guard test — The _hasLocalSiteOverride field is private with no public setter. Using reflection to set it directly is the standard pattern established by GlobalSiteSelectionTests for PermissionsViewModel — consistent approach maintained.

  4. No special WPF threading setup — The CollectionViewSource and ICollectionView used in the ViewModel constructor work in a WPF-enabled test environment (the test project targets net10.0-windows with UseWPF=true). No mock dispatcher or [STAThread] annotation needed.

Deviations from Plan

None — plan executed exactly as written.

Issues Encountered

None.

User Setup Required

None - no external service configuration required.

Next Phase Readiness

  • All Phase 7 unit tests complete. 32 new tests, 176 total passing, 22 skipped (pre-existing).
  • Phase 7 is fully implemented: models (07-01), audit service (07-02), Graph search (07-03), ViewModel (07-04), view (07-05), exports (07-06), integration wiring (07-07), unit tests (07-08).
  • Ready to proceed to Phase 8 or Phase 9.

Self-Check: PASSED

Files confirmed present:

  • FOUND: SharepointToolbox.Tests/Services/UserAccessAuditServiceTests.cs
  • FOUND: SharepointToolbox.Tests/Services/Export/UserAccessCsvExportServiceTests.cs
  • FOUND: SharepointToolbox.Tests/Services/Export/UserAccessHtmlExportServiceTests.cs
  • FOUND: SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelTests.cs

Commits confirmed:


Phase: 07-user-access-audit Completed: 2026-04-07