---
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>
