docs(06): create phase plan for global site selection (5 plans, 3 waves)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
206
.planning/phases/06-global-site-selection/06-05-PLAN.md
Normal file
206
.planning/phases/06-global-site-selection/06-05-PLAN.md
Normal file
@@ -0,0 +1,206 @@
|
||||
---
|
||||
phase: 06-global-site-selection
|
||||
plan: 05
|
||||
type: execute
|
||||
wave: 3
|
||||
depends_on: [06-01, 06-02, 06-04]
|
||||
files_modified:
|
||||
- SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs
|
||||
autonomous: true
|
||||
requirements:
|
||||
- SITE-01
|
||||
- SITE-02
|
||||
must_haves:
|
||||
truths:
|
||||
- "Unit tests verify GlobalSitesChangedMessage broadcasts when MainWindowViewModel global sites change"
|
||||
- "Unit tests verify FeatureViewModelBase receives global sites and updates GlobalSites property"
|
||||
- "Unit tests verify single-site tab VMs pre-fill SiteUrl from first global site"
|
||||
- "Unit tests verify PermissionsViewModel pre-populates SelectedSites from global sites"
|
||||
- "Unit tests verify local override prevents global sites from overwriting tab state"
|
||||
- "Unit tests verify tenant switch clears global site selection"
|
||||
- "All tests pass with dotnet test"
|
||||
artifacts:
|
||||
- path: "SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs"
|
||||
provides: "Comprehensive unit tests for global site selection flow"
|
||||
contains: "GlobalSiteSelectionTests"
|
||||
key_links:
|
||||
- from: "SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs"
|
||||
to: "SharepointToolbox/ViewModels/MainWindowViewModel.cs"
|
||||
via: "Tests broadcast and clear behavior"
|
||||
pattern: "GlobalSelectedSites"
|
||||
- from: "SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs"
|
||||
to: "SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs"
|
||||
via: "Tests single-site consumption and local override"
|
||||
pattern: "OnGlobalSitesChanged"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Create unit tests covering the full global site selection flow: message broadcast, base class reception, tab VM consumption, local override behavior, and tenant switch clearing.
|
||||
|
||||
Purpose: Verify the contracts established in plans 06-01 through 06-04 work correctly end-to-end without requiring a live SharePoint tenant.
|
||||
Output: GlobalSiteSelectionTests.cs with passing tests covering all critical paths.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/06-global-site-selection/06-CONTEXT.md
|
||||
@.planning/phases/06-global-site-selection/06-01-SUMMARY.md
|
||||
@.planning/phases/06-global-site-selection/06-02-SUMMARY.md
|
||||
@.planning/phases/06-global-site-selection/06-04-SUMMARY.md
|
||||
|
||||
<interfaces>
|
||||
<!-- From plan 06-01: Base class contract -->
|
||||
```csharp
|
||||
// FeatureViewModelBase
|
||||
protected IReadOnlyList<SiteInfo> GlobalSites { get; private set; }
|
||||
protected virtual void OnGlobalSitesChanged(IReadOnlyList<SiteInfo> sites) { }
|
||||
// Registers for GlobalSitesChangedMessage in OnActivated()
|
||||
```
|
||||
|
||||
<!-- From plan 06-02: MainWindowViewModel -->
|
||||
```csharp
|
||||
public ObservableCollection<SiteInfo> GlobalSelectedSites { get; }
|
||||
public RelayCommand OpenGlobalSitePickerCommand { get; }
|
||||
public string GlobalSitesSelectedLabel { get; }
|
||||
// CollectionChanged on GlobalSelectedSites sends GlobalSitesChangedMessage
|
||||
// OnSelectedProfileChanged clears GlobalSelectedSites
|
||||
// ClearSessionAsync clears GlobalSelectedSites
|
||||
```
|
||||
|
||||
<!-- From plan 06-04: Tab VM overrides -->
|
||||
```csharp
|
||||
// StorageViewModel (and Search, Duplicates, FolderStructure)
|
||||
protected override void OnGlobalSitesChanged(IReadOnlyList<SiteInfo> sites)
|
||||
{
|
||||
if (_hasLocalSiteOverride) return;
|
||||
SiteUrl = sites.Count > 0 ? sites[0].Url : string.Empty;
|
||||
}
|
||||
|
||||
// PermissionsViewModel
|
||||
protected override void OnGlobalSitesChanged(IReadOnlyList<SiteInfo> sites)
|
||||
{
|
||||
if (_hasLocalSiteOverride) return;
|
||||
SelectedSites.Clear();
|
||||
foreach (var site in sites) SelectedSites.Add(site);
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Existing test patterns (from v1.0) -->
|
||||
```csharp
|
||||
// Tests use Moq for service interfaces, internal constructors for VMs
|
||||
// InternalsVisibleTo is already configured
|
||||
// WeakReferenceMessenger.Default for message sending in tests
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Create GlobalSiteSelectionTests with comprehensive test coverage</name>
|
||||
<files>SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs</files>
|
||||
<behavior>
|
||||
- Test 1: GlobalSitesChangedMessage carries site list — send message, verify receiver gets the sites
|
||||
- Test 2: FeatureViewModelBase updates GlobalSites on message receive — send message to a derived VM, check GlobalSites property
|
||||
- Test 3: StorageViewModel pre-fills SiteUrl from first global site — send global sites message, verify SiteUrl equals first site URL
|
||||
- Test 4: StorageViewModel local override prevents global update — set SiteUrl manually, then send global sites, verify SiteUrl unchanged
|
||||
- Test 5: StorageViewModel clearing SiteUrl reverts to global — set local override, clear SiteUrl, verify it reverts to global site
|
||||
- Test 6: PermissionsViewModel pre-populates SelectedSites from global sites — send global sites, verify SelectedSites matches
|
||||
- Test 7: PermissionsViewModel local picker override prevents global update — mark local override, send global sites, verify SelectedSites unchanged
|
||||
- Test 8: Tenant switch clears global sites on StorageViewModel — send global sites, then send TenantSwitchedMessage, verify SiteUrl cleared and override reset
|
||||
- Test 9: TransferViewModel pre-fills SourceSiteUrl from first global site
|
||||
- Test 10: MainWindowViewModel GlobalSitesSelectedLabel updates with count — add sites to GlobalSelectedSites, verify label text
|
||||
</behavior>
|
||||
<action>
|
||||
Create `SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs` with the tests described above.
|
||||
|
||||
Use the existing test patterns from the project:
|
||||
- Moq for `IStorageService`, `ISessionManager`, `IPermissionsService`, `ISiteListService`, `ILogger<FeatureViewModelBase>`
|
||||
- Internal test constructors for ViewModels (already available via InternalsVisibleTo)
|
||||
- `WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(...))` to simulate the toolbar broadcasting
|
||||
|
||||
Key implementation notes:
|
||||
|
||||
1. For tests that need to verify GlobalSites property on FeatureViewModelBase: Create a minimal concrete subclass in the test file:
|
||||
```csharp
|
||||
private class TestFeatureViewModel : FeatureViewModelBase
|
||||
{
|
||||
public TestFeatureViewModel(ILogger<FeatureViewModelBase> logger) : base(logger) { }
|
||||
protected override Task RunOperationAsync(CancellationToken ct, IProgress<OperationProgress> progress)
|
||||
=> Task.CompletedTask;
|
||||
// Expose protected property for test assertions
|
||||
public IReadOnlyList<SiteInfo> TestGlobalSites => GlobalSites;
|
||||
}
|
||||
```
|
||||
|
||||
2. For StorageViewModel tests: use the internal test constructor `StorageViewModel(IStorageService, ISessionManager, ILogger<FeatureViewModelBase>)`.
|
||||
|
||||
3. For PermissionsViewModel tests: use the internal test constructor `PermissionsViewModel(IPermissionsService, ISiteListService, ISessionManager, ILogger<FeatureViewModelBase>)`.
|
||||
|
||||
4. For TransferViewModel tests: use the production constructor with mocked dependencies. Check if TransferViewModel has an internal test constructor — if not, mock all constructor parameters.
|
||||
|
||||
5. For MainWindowViewModel label test: use the production constructor with mocked ProfileService, SessionManager, ILogger. Add SiteInfo items to GlobalSelectedSites and assert the label property.
|
||||
|
||||
6. Reset WeakReferenceMessenger.Default between tests to avoid cross-test contamination:
|
||||
```csharp
|
||||
public GlobalSiteSelectionTests()
|
||||
{
|
||||
WeakReferenceMessenger.Default.Reset();
|
||||
}
|
||||
```
|
||||
|
||||
7. Each test should be a `[Fact]` with a descriptive name following the pattern: `MethodOrScenario_Condition_ExpectedResult`.
|
||||
|
||||
Example test structure:
|
||||
```csharp
|
||||
[Fact]
|
||||
public void OnGlobalSitesChanged_WithSites_PreFillsSiteUrlOnStorageTab()
|
||||
{
|
||||
var logger = Mock.Of<ILogger<FeatureViewModelBase>>();
|
||||
var vm = new StorageViewModel(
|
||||
Mock.Of<IStorageService>(),
|
||||
Mock.Of<ISessionManager>(),
|
||||
logger);
|
||||
|
||||
var sites = new List<SiteInfo>
|
||||
{
|
||||
new("https://contoso.sharepoint.com/sites/hr", "HR"),
|
||||
new("https://contoso.sharepoint.com/sites/finance", "Finance")
|
||||
};
|
||||
WeakReferenceMessenger.Default.Send(new GlobalSitesChangedMessage(sites.AsReadOnly()));
|
||||
|
||||
Assert.Equal("https://contoso.sharepoint.com/sites/hr", vm.SiteUrl);
|
||||
}
|
||||
```
|
||||
|
||||
Write all 10 tests. Ensure every test has clear Arrange/Act/Assert sections.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet test SharepointToolbox.Tests/SharepointToolbox.Tests.csproj --filter "FullyQualifiedName~GlobalSiteSelection" --verbosity normal 2>&1 | tail -20</automated>
|
||||
</verify>
|
||||
<done>All 10 tests in GlobalSiteSelectionTests pass. Tests cover message broadcast, base class reception, single-site pre-fill, multi-site pre-populate, local override, override reset, tenant switch clear, and label update.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- `dotnet test SharepointToolbox.Tests --filter "GlobalSiteSelection"` shows 10 passed, 0 failed
|
||||
- `dotnet test SharepointToolbox.Tests` shows no regressions in existing tests
|
||||
- Test file exists at SharepointToolbox.Tests/ViewModels/GlobalSiteSelectionTests.cs
|
||||
- Tests cover both SITE-01 (global consumption) and SITE-02 (local override) requirements
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
All 10 unit tests pass, validating the full global site selection contract: message creation, base class plumbing, tab VM consumption (multi-site and single-site), local override behavior, and tenant switch clearing. No regressions in existing test suite.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/06-global-site-selection/06-05-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user