All checks were successful
Release zip package / release (push) Successful in 10s
Archive 5 phases (36 plans) to milestones/v1.0-phases/. Archive roadmap, requirements, and audit to milestones/. Evolve PROJECT.md with shipped state and validated requirements. Collapse ROADMAP.md to one-line milestone summary. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
162 lines
9.0 KiB
Markdown
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>
|