From 9add2592b377023fb0e9a67f74bca562fe43a2bd Mon Sep 17 00:00:00 2001 From: Dev Date: Tue, 7 Apr 2026 10:14:48 +0200 Subject: [PATCH] =?UTF-8?q?docs(06-05):=20complete=20GlobalSiteSelectionTe?= =?UTF-8?q?sts=20plan=20=E2=80=94=20phase=206=20done?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SUMMARY.md created with test coverage details and decision rationale - STATE.md updated: progress 100%, decisions recorded, session logged - ROADMAP.md phase 6 marked Complete (5/5 plans with summaries) --- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 15 ++- .../06-global-site-selection/06-05-SUMMARY.md | 120 ++++++++++++++++++ 3 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 .planning/phases/06-global-site-selection/06-05-SUMMARY.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 026108f..dceaf7e 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -20,7 +20,7 @@ **v1.1 Enhanced Reports** -- [ ] **Phase 6: Global Site Selection** — Toolbar-level multi-site picker that all feature tabs consume as their default target +- [x] **Phase 6: Global Site Selection** — Toolbar-level multi-site picker that all feature tabs consume as their default target (completed 2026-04-07) - [ ] **Phase 7: User Access Audit** — New feature tab: export every SharePoint/Teams access a specific user holds across selected sites - [ ] **Phase 8: Simplified Permissions** — Plain-language labels, summary counts, color coding, and detail-level toggle on the permissions report - [ ] **Phase 9: Storage Visualization** — Charting dependency + pie/donut and bar chart views of storage by file type in the Storage Metrics tab @@ -36,7 +36,7 @@ 2. Selecting sites in the toolbar causes all feature tabs to default to those sites when an operation is run 3. A user can override the global selection on any individual tab without clearing the global state 4. The global site selection persists across tab switches within the same session -**Plans:** 4/5 plans executed +**Plans:** 5/5 plans complete Plans: - [ ] 06-01-PLAN.md — GlobalSitesChangedMessage + FeatureViewModelBase extension - [ ] 06-02-PLAN.md — MainWindowViewModel global selection state + command @@ -86,7 +86,7 @@ Plans: | 3. Storage and File Operations | v1.0 | 8/8 | Complete | 2026-04-02 | | 4. Bulk Operations and Provisioning | v1.0 | 10/10 | Complete | 2026-04-03 | | 5. Distribution and Hardening | v1.0 | 3/3 | Complete | 2026-04-03 | -| 6. Global Site Selection | 4/5 | In Progress| | - | +| 6. Global Site Selection | 5/5 | Complete | 2026-04-07 | - | | 7. User Access Audit | v1.1 | 0/? | Not started | - | | 8. Simplified Permissions | v1.1 | 0/? | Not started | - | | 9. Storage Visualization | v1.1 | 0/? | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index 0c799dc..14aa975 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: completed -stopped_at: Completed 06-04-PLAN.md — all 6 tab VMs wired to OnGlobalSitesChanged with local override protection -last_updated: "2026-04-07T08:10:03.678Z" +stopped_at: Completed 06-05-PLAN.md — 10 GlobalSiteSelectionTests covering full global site selection contract +last_updated: "2026-04-07T08:14:30.489Z" last_activity: 2026-04-07 — Roadmap created (Phases 6-9), 10/10 requirements mapped progress: total_phases: 4 - completed_phases: 0 + completed_phases: 1 total_plans: 5 - completed_plans: 4 + completed_plans: 5 --- # Project State @@ -46,6 +46,7 @@ Phase 6 [ ] → Phase 7 [ ] → Phase 8 [ ] → Phase 9 [ ] | Phase 06-global-site-selection P01 | 2 | 2 tasks | 3 files | | Phase 06-global-site-selection P03 | 2 | 3 tasks | 5 files | | Phase 06-global-site-selection P04 | 2 | 3 tasks | 6 files | +| Phase 06-global-site-selection P05 | 2 | 1 tasks | 1 files | ## Accumulated Context @@ -66,6 +67,8 @@ Decisions are logged in PROJECT.md Key Decisions table. - [Phase 06-global-site-selection]: PermissionsViewModel uses _hasLocalSiteOverride guard for SelectedSites; site picker sets flag, tenant switch resets it - [Phase 06-global-site-selection]: Single-site VMs use partial void OnSiteUrlChanged to detect local typing; clearing field reverts to global - [Phase 06-global-site-selection]: BulkMembersViewModel confirmed excluded: no SiteUrl field, CSV-driven per-row site URLs +- [Phase 06-global-site-selection]: Test 8 asserts override-reset via next global sites message (not SiteUrl='' — OnSiteUrlChanged re-applies global immediately when cleared) +- [Phase 06-global-site-selection]: Used reflection to set _hasLocalSiteOverride in PermissionsViewModel test — avoids needing a real SitePickerDialog ### Pending Todos @@ -77,6 +80,6 @@ None. ## Session Continuity -Last session: 2026-04-07T08:10:03.675Z -Stopped at: Completed 06-04-PLAN.md — all 6 tab VMs wired to OnGlobalSitesChanged with local override protection +Last session: 2026-04-07T08:14:30.486Z +Stopped at: Completed 06-05-PLAN.md — 10 GlobalSiteSelectionTests covering full global site selection contract Resume file: None diff --git a/.planning/phases/06-global-site-selection/06-05-SUMMARY.md b/.planning/phases/06-global-site-selection/06-05-SUMMARY.md new file mode 100644 index 0000000..115f02d --- /dev/null +++ b/.planning/phases/06-global-site-selection/06-05-SUMMARY.md @@ -0,0 +1,120 @@ +--- +phase: 06-global-site-selection +plan: 05 +subsystem: testing +tags: [xunit, moq, wpf, mvvm, weak-reference-messenger, global-sites] + +# Dependency graph +requires: + - phase: 06-global-site-selection/06-01 + provides: GlobalSitesChangedMessage, FeatureViewModelBase.GlobalSites, OnGlobalSitesChanged virtual hook + - phase: 06-global-site-selection/06-02 + provides: MainWindowViewModel.GlobalSelectedSites, GlobalSitesSelectedLabel + - phase: 06-global-site-selection/06-04 + provides: Tab VM OnGlobalSitesChanged overrides with local override protection +provides: + - GlobalSiteSelectionTests (10 unit tests covering full global site selection contract) + - Test coverage for message broadcast, base class reception, single/multi-site pre-fill + - Test coverage for local override, override reset, tenant switch clearing, label update +affects: [] + +# Tech tracking +tech-stack: + added: [] + patterns: + - "TestFeatureViewModel inner class pattern — expose protected property for assertion via public accessor" + - "WeakReferenceMessenger.Default.Reset() in test constructor — prevents cross-test message contamination" + - "Reflection to set private bool flag (_hasLocalSiteOverride) for testing guard conditions without requiring a dialog to open" + +key-files: + created: + - SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs + modified: [] + +key-decisions: + - "Test 8 (tenant switch) verifies override reset by sending new global sites after TenantSwitchedMessage — cleaner than asserting SiteUrl='' since OnSiteUrlChanged immediately re-applies global when SiteUrl is cleared and GlobalSites is non-empty" + - "Used reflection to set _hasLocalSiteOverride in PermissionsViewModel override test — avoids needing a real SitePickerDialog; acceptable for unit test scenario coverage" + - "MainWindowViewModel instantiated with real ProfileRepository (temp file path) and MsalClientFactory() — avoids needing to refactor VM for testability while still keeping test hermetic" + +patterns-established: + - "Messenger reset pattern: WeakReferenceMessenger.Default.Reset() in constructor prevents leakage between WeakReferenceMessenger-heavy tests" + +requirements-completed: + - SITE-01 + - SITE-02 + +# Metrics +duration: 3min +completed: 2026-04-07 +--- + +# Phase 06 Plan 05: GlobalSiteSelectionTests Summary + +**10 unit tests validating the full global site selection contract — message broadcast, base class GlobalSites property, single-site pre-fill, multi-site pre-populate, local override protection, override reset on clear, tenant switch clearing, and toolbar label count** + +## Performance + +- **Duration:** ~3 min +- **Started:** 2026-04-07T08:11:40Z +- **Completed:** 2026-04-07T08:14:30Z +- **Tasks:** 1 +- **Files modified:** 1 created + +## Accomplishments +- All 10 tests pass covering both SITE-01 (global consumption) and SITE-02 (local override) requirements +- Total test suite grows from 134 to 144 passing tests (22 skipped unchanged) +- Tests exercise the full flow: MainWindowViewModel broadcasts, FeatureViewModelBase receives, tab VMs react, local override blocks global, tenant switch resets state +- No regressions in any pre-existing test + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Create GlobalSiteSelectionTests with comprehensive test coverage** - `80ef092` (test) + +## Files Created/Modified +- `SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs` — 10 xUnit Fact tests covering all critical paths in the global site selection flow + +## Decisions Made +- Test 8 revised to verify override-reset behavior indirectly: after `TenantSwitchedMessage`, sending new global sites verifies override was cleared (the simpler `Assert.Equal("", SiteUrl)` was wrong — `OnSiteUrlChanged` immediately re-applies GlobalSites when SiteUrl is cleared and GlobalSites is non-empty, which is correct designed behavior) +- Used `System.Reflection` to set `_hasLocalSiteOverride` on `PermissionsViewModel` for Test 7 — allows testing the guard without requiring a live dialog factory +- `MainWindowViewModel` instantiated via concrete `ProfileRepository(tempFile)` and `new MsalClientFactory()` — no refactoring needed, test remains hermetic + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Corrected Test 8 assertion to match actual StorageViewModel behavior** +- **Found during:** Task 1 (first test run) +- **Issue:** Initial Test 8 asserted `vm.SiteUrl == string.Empty` after tenant switch, but `OnSiteUrlChanged` immediately re-applies `GlobalSites[0].Url` when SiteUrl is cleared and GlobalSites is non-empty — this is correct, designed behavior (clearing = revert to global) +- **Fix:** Rewrote test to assert the real contract: after tenant switch, override flag is reset, so the next global sites message is applied to SiteUrl +- **Files modified:** SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs +- **Verification:** All 10 tests pass +- **Committed in:** 80ef092 (Task 1 commit) + +--- + +**Total deviations:** 1 auto-fixed (1 bug — incorrect test assertion) +**Impact on plan:** Fix was necessary for test correctness; the assertion was wrong about the expected behavior, not the VM code. + +## Issues Encountered +- First test run had 9/10 passing; Test 8 failed because the assertion tested an intermediate state that the VM immediately transitions through (SiteUrl clears then immediately re-fills from GlobalSites). Fixed by testing the stable end state instead. + +## User Setup Required +None — no external service configuration required. + +## Self-Check: PASSED + +File exists: SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs +Commit 80ef092 exists in git log. +All 10 tests pass: `dotnet test --filter "GlobalSiteSelection"` → 10 Passed, 0 Failed. +No regressions: full suite → 144 Passed, 22 Skipped. + +## Next Phase Readiness +- Phase 6 is complete — all 5 plans executed, all requirements SITE-01 and SITE-02 covered +- The global site selection feature is fully implemented and tested end-to-end +- No blockers for Phase 7 + +--- +*Phase: 06-global-site-selection* +*Completed: 2026-04-07*