--- 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" --- 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. @C:/Users/dev/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/dev/.claude/get-shit-done/templates/summary.md @.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 Task 1: Make helper methods internal static and create retry + pagination tests SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs, SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs, SharepointToolbox.Tests/Helpers/ExecuteQueryRetryHelperTests.cs, SharepointToolbox.Tests/Helpers/SharePointPaginationHelperTests.cs 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 `"2000"` - `[Fact]` BuildPagedViewXml_EmptyString_ReturnsViewWithRowLimit: same for `""` - `[Fact]` BuildPagedViewXml_ExistingRowLimit_Replaces: input `"100"` with rowLimit 2000 returns `"2000"` - `[Fact]` BuildPagedViewXml_NoRowLimit_Appends: input `""` with rowLimit 2000 returns the same XML with `2000` inserted before `` - `[Fact]` BuildPagedViewXml_WhitespaceOnly_ReturnsViewWithRowLimit: input `" "` returns minimal view Note: Create the `Helpers/` subdirectory under the test project if it doesn't exist. dotnet test SharepointToolbox.Tests/SharepointToolbox.Tests.csproj --filter "ExecuteQueryRetryHelper|SharePointPagination" -v quiet 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. Task 2: Create exhaustive FR locale completeness test SharepointToolbox.Tests/Localization/LocaleCompletenessTests.cs 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. dotnet test SharepointToolbox.Tests/SharepointToolbox.Tests.csproj --filter "LocaleCompleteness" -v quiet 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. 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). - 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 After completion, create `.planning/phases/05-distribution-and-hardening/05-01-SUMMARY.md`