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)
This commit is contained in:
Dev
2026-04-07 13:00:18 +02:00
parent 35b2c2a109
commit 855e4df49b
3 changed files with 138 additions and 9 deletions

View File

@@ -0,0 +1,126 @@
---
phase: 07-user-access-audit
plan: 08
subsystem: testing
tags: [unit-tests, xunit, moq, user-access-audit, csv-export, html-export, viewmodel]
requires:
- phase: 07-02
provides: [UserAccessAuditService]
- phase: 07-03
provides: [GraphUserSearchService, IGraphUserSearchService]
- phase: 07-04
provides: [UserAccessAuditViewModel]
- phase: 07-06
provides: [UserAccessCsvExportService, UserAccessHtmlExportService]
provides:
- Unit tests for UserAccessAuditService (12 tests)
- Unit tests for UserAccessCsvExportService (5 tests)
- Unit tests for UserAccessHtmlExportService (7 tests)
- Unit tests for UserAccessAuditViewModel (8 tests)
affects: []
tech-stack:
added: []
patterns: [Moq mock setup with ReturnsAsync, reflection for private field access in override guard tests, WeakReferenceMessenger.Reset in test constructor]
key-files:
created:
- SharepointToolbox.Tests/Services/UserAccessAuditServiceTests.cs
- SharepointToolbox.Tests/Services/Export/UserAccessCsvExportServiceTests.cs
- SharepointToolbox.Tests/Services/Export/UserAccessHtmlExportServiceTests.cs
- SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelTests.cs
modified: []
key-decisions:
- "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"
patterns-established:
- "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"
requirements-completed: [UACC-01, UACC-02]
duration: 2min
completed: 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:
- FOUND: 5df9503
- FOUND: 35b2c2a
---
*Phase: 07-user-access-audit*
*Completed: 2026-04-07*