Files
Sharepoint-Toolbox/.planning/phases/05-distribution-and-hardening/05-01-PLAN.md
Dev 0122a47c9e docs(05): create phase plan for distribution and hardening
3 plans in 2 waves: helper tests + locale completeness (W1), FR diacritics + publish config (W1), verification + human checkpoint (W2).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 14:40:41 +02:00

162 lines
9.0 KiB
Markdown

---
phase: 05-distribution-and-hardening
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs
- SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs
- SharepointToolbox.Tests/Helpers/ExecuteQueryRetryHelperTests.cs
- SharepointToolbox.Tests/Helpers/SharePointPaginationHelperTests.cs
- SharepointToolbox.Tests/Localization/LocaleCompletenessTests.cs
autonomous: true
requirements:
- FOUND-11
must_haves:
truths:
- "ExecuteQueryRetryHelper.IsThrottleException correctly classifies 429, 503, and throttle messages"
- "SharePointPaginationHelper.BuildPagedViewXml injects or replaces RowLimit in CAML XML"
- "Every EN key in Strings.resx has a non-empty, non-bracketed FR translation in Strings.fr.resx"
artifacts:
- path: "SharepointToolbox.Tests/Helpers/ExecuteQueryRetryHelperTests.cs"
provides: "Throttle exception classification unit tests"
min_lines: 20
- path: "SharepointToolbox.Tests/Helpers/SharePointPaginationHelperTests.cs"
provides: "CAML XML RowLimit injection unit tests"
min_lines: 20
- path: "SharepointToolbox.Tests/Localization/LocaleCompletenessTests.cs"
provides: "Exhaustive FR locale parity test"
min_lines: 15
key_links:
- from: "SharepointToolbox.Tests/Helpers/ExecuteQueryRetryHelperTests.cs"
to: "SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs"
via: "InternalsVisibleTo + internal static IsThrottleException"
pattern: "ExecuteQueryRetryHelper\\.IsThrottleException"
- from: "SharepointToolbox.Tests/Helpers/SharePointPaginationHelperTests.cs"
to: "SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs"
via: "InternalsVisibleTo + internal static BuildPagedViewXml"
pattern: "SharePointPaginationHelper\\.BuildPagedViewXml"
---
<objective>
Create unit tests for the retry helper, pagination helper, and locale completeness — the three testable verification axes of Phase 5. Change private static methods to internal static so tests can access them (established InternalsVisibleTo pattern from Phase 2).
Purpose: These tests prove the reliability guarantees (throttle retry, 5k-item pagination) and locale completeness that FOUND-11's success criteria require. Without them, the only verification is manual smoke testing.
Output: Three new test files, two visibility changes in helpers.
</objective>
<execution_context>
@C:/Users/dev/.claude/get-shit-done/workflows/execute-plan.md
@C:/Users/dev/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/05-distribution-and-hardening/05-RESEARCH.md
@SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs
@SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs
@SharepointToolbox/Localization/Strings.resx
@SharepointToolbox/Localization/Strings.fr.resx
@SharepointToolbox/AssemblyInfo.cs
</context>
<tasks>
<task type="auto">
<name>Task 1: Make helper methods internal static and create retry + pagination tests</name>
<files>
SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs,
SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs,
SharepointToolbox.Tests/Helpers/ExecuteQueryRetryHelperTests.cs,
SharepointToolbox.Tests/Helpers/SharePointPaginationHelperTests.cs
</files>
<action>
1. In `ExecuteQueryRetryHelper.cs`, change `private static bool IsThrottleException(Exception ex)` to `internal static bool IsThrottleException(Exception ex)`. No other changes to the file.
2. In `SharePointPaginationHelper.cs`, change `private static string BuildPagedViewXml(string? existingXml, int rowLimit)` to `internal static string BuildPagedViewXml(string? existingXml, int rowLimit)`. No other changes.
3. Create `SharepointToolbox.Tests/Helpers/ExecuteQueryRetryHelperTests.cs`:
- Namespace: `SharepointToolbox.Tests.Helpers`
- Using: `SharepointToolbox.Core.Helpers`
- `[Theory]` with `[InlineData]` for throttle messages: "The request has been throttled -- 429", "Service unavailable 503", "SharePoint has throttled your request"
- Each creates `new Exception(message)` and asserts `ExecuteQueryRetryHelper.IsThrottleException(ex)` returns true
- `[Fact]` for non-throttle: `new Exception("File not found")` returns false
- `[Fact]` for nested throttle: `new Exception("outer", new Exception("429"))` — test whether inner exceptions are checked (current implementation only checks top-level Message — test should assert false to document this behavior)
4. Create `SharepointToolbox.Tests/Helpers/SharePointPaginationHelperTests.cs`:
- Namespace: `SharepointToolbox.Tests.Helpers`
- Using: `SharepointToolbox.Core.Helpers`
- `[Fact]` BuildPagedViewXml_NullInput_ReturnsViewWithRowLimit: `BuildPagedViewXml(null, 2000)` returns `"<View><RowLimit>2000</RowLimit></View>"`
- `[Fact]` BuildPagedViewXml_EmptyString_ReturnsViewWithRowLimit: same for `""`
- `[Fact]` BuildPagedViewXml_ExistingRowLimit_Replaces: input `"<View><RowLimit>100</RowLimit></View>"` with rowLimit 2000 returns `"<View><RowLimit>2000</RowLimit></View>"`
- `[Fact]` BuildPagedViewXml_NoRowLimit_Appends: input `"<View><Query><OrderBy><FieldRef Name='Title'/></OrderBy></Query></View>"` with rowLimit 2000 returns the same XML with `<RowLimit>2000</RowLimit>` inserted before `</View>`
- `[Fact]` BuildPagedViewXml_WhitespaceOnly_ReturnsViewWithRowLimit: input `" "` returns minimal view
Note: Create the `Helpers/` subdirectory under the test project if it doesn't exist.
</action>
<verify>
<automated>dotnet test SharepointToolbox.Tests/SharepointToolbox.Tests.csproj --filter "ExecuteQueryRetryHelper|SharePointPagination" -v quiet</automated>
</verify>
<done>All retry helper and pagination helper tests pass. IsThrottleException correctly classifies 429/503/throttle messages. BuildPagedViewXml correctly handles null, empty, existing RowLimit, and missing RowLimit inputs.</done>
</task>
<task type="auto">
<name>Task 2: Create exhaustive FR locale completeness test</name>
<files>SharepointToolbox.Tests/Localization/LocaleCompletenessTests.cs</files>
<action>
Create `SharepointToolbox.Tests/Localization/LocaleCompletenessTests.cs`:
- Namespace: `SharepointToolbox.Tests.Localization`
- Using: `System.Globalization`, `System.Resources`, `System.Collections`, `SharepointToolbox.Localization`
Test 1 — `[Fact] AllEnKeys_HaveNonEmptyFrTranslation`:
- Create `ResourceManager` for `"SharepointToolbox.Localization.Strings"` using `typeof(Strings).Assembly`
- Get the invariant resource set via `GetResourceSet(CultureInfo.InvariantCulture, true, true)`
- Create `CultureInfo("fr")` (not "fr-FR" — the satellite assembly uses neutral "fr" culture)
- Iterate all `DictionaryEntry` in the resource set
- For each key: call `GetString(key, frCulture)` and assert it is not null or whitespace
- Also assert it does not start with `"["` (bracketed fallback indicator)
- Collect all failures into a list and assert the list is empty (single assertion with all missing keys listed in the failure message for easy debugging)
Test 2 — `[Fact] FrStrings_ContainExpectedDiacritics`:
- Spot-check 5 known keys that MUST have diacritics after the fix in Plan 02:
- `"transfer.mode.move"` should contain `"é"` (Deplacer -> Deplacer is wrong, Déplacer is correct)
- `"bulksites.execute"` should contain `"é"` (Créer)
- `"templates.list"` should contain `"è"` (Modèles)
- `"bulk.result.success"` should contain `"é"` (Terminé, réussis, échoués)
- `"folderstruct.library"` should contain `"è"` (Bibliothèque)
- For each: get FR string via ResourceManager and assert it contains the expected accented character
Note: This test will FAIL until Plan 02 fixes the diacritics — that is correct TDD-style behavior. The test documents the expected state.
</action>
<verify>
<automated>dotnet test SharepointToolbox.Tests/SharepointToolbox.Tests.csproj --filter "LocaleCompleteness" -v quiet</automated>
</verify>
<done>LocaleCompletenessTests.cs exists and compiles. Test 1 (AllEnKeys_HaveNonEmptyFrTranslation) passes (all keys have values). Test 2 (FrStrings_ContainExpectedDiacritics) fails until Plan 02 fixes diacritics — expected behavior.</done>
</task>
</tasks>
<verification>
All new tests compile and the helper tests pass:
```bash
dotnet test SharepointToolbox.Tests/SharepointToolbox.Tests.csproj --filter "ExecuteQueryRetryHelper|SharePointPagination|LocaleCompleteness" -v quiet
```
Existing test suite remains green (no regressions from visibility changes).
</verification>
<success_criteria>
- ExecuteQueryRetryHelperTests: 4+ tests pass (3 throttle-true, 1 non-throttle-false)
- SharePointPaginationHelperTests: 4+ tests pass (null, empty, replace, append)
- LocaleCompletenessTests: Test 1 passes (key parity), Test 2 may fail (diacritics pending Plan 02)
- Full existing test suite still green
</success_criteria>
<output>
After completion, create `.planning/phases/05-distribution-and-hardening/05-01-SUMMARY.md`
</output>