fix(selftest): stabilize Resource_FetchedData and PasswordBox UserEditFires#149
Merged
Merged
Conversation
…tFires Two flake clusters surfaced in a 100x `Reactor.AppTests.Host --self-test` sweep on top of #139 (3/100 run-fail rate before; expected 0/100 after). - `Resource_FetchedData` (CovBoost_ComponentUseResource): the 10ms Task.Delay fetcher resolves during the 200ms wall-clock wait inside Harness.Render(200), then schedules a re-render that may not flush before Render(200) returns. Pump once more after the wall-clock wait to drain the queued re-render. - `EchoSuppress_PasswordBox_UserEditFires`: PasswordBox.PasswordChanged can be raised via the dispatcher rather than synchronously in the setter (same shape as the TabView/RadioButtons flake fixed in #139). Pump twice between `pb.Password = "typed"` and the counter assertion so the queued event lands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR tightens two flaky self-tests in Reactor.AppTests.Host by adding extra render pumps where async/dispatcher-driven updates can land after the existing wait. It fits the self-test harness work from #139 by continuing to stabilize timing-sensitive fixture assertions without changing production code.
Changes:
- Added a second
Harness.Render()after mutatingPasswordBox.Passwordso dispatcher-raisedPasswordChangedevents are observed before assertion. - Added an extra
Harness.Render()afterHarness.Render(200)in theUseResourcefixture so the queued re-render from the async fetch completes before verification.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
tests/Reactor.AppTests.Host/SelfTest/Fixtures/EchoSuppressionFixtures.cs |
Stabilizes the PasswordBox echo-suppression fixture by waiting for dispatcher-delivered change events. |
tests/Reactor.AppTests.Host/SelfTest/Fixtures/CoverageBoostFixtures.cs |
Stabilizes the UseResource fixture by draining the async re-render scheduled after the fetch completes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
3 tasks
codemonkeychris
added a commit
that referenced
this pull request
May 5, 2026
Two flake clusters surfaced in a 100x `Reactor.AppTests.Host --self-test` sweep on top of #149 (3/100 run-fail rate before; 0/100 after across a 100x verification sweep). - `Mutation_Completed` (CovBoost_ComponentUseMutation): the useMutation RunAsync resolves during the 100ms wall-clock wait inside Harness.Render(100), then schedules a re-render that may not flush before Render(100) returns. Pump once more after the wall-clock wait to drain the queued re-render. Same shape as the Resource_FetchedData fix in #149. - `GotFocus_FiresOnA` (PointerMod_GotLostFocusFires): TextBox.Focus() can raise GotFocus via the dispatcher rather than synchronously (same shape as the TabView/RadioButtons/PasswordBox flakes fixed in #139/#149). Pump twice between Focus() and the counter assertion so the queued event lands. Apply to both focus transitions in the fixture. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 task
codemonkeychris
added a commit
that referenced
this pull request
May 5, 2026
Flake surfaced in CI (run 25404199901 on PR #154): not ok InfiniteBasic_TotalKnown () - assertion failed Same shape as #149 (Resource_FetchedData) and #152 (Mutation_Completed): the fetcher's Task.Delay(10) resolves during a Render()'s 16ms wall-clock breathing-room delay, then schedules an Apply continuation on the dispatcher (which sets TotalCount inside ApplyPageResult) just after WaitForIdleAsync returned. The sibling Page1Loaded check still passes because pageFetches is incremented inside FetchPageAsync before it returns, and Items.Count >= 25 is satisfied via _highestInflightEnd from the in-flight slot — neither requires the Apply continuation to have run. Pump a third time to drain the queued re-render before the assertion. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
codemonkeychris
added a commit
that referenced
this pull request
May 7, 2026
The fixed two-pump guard added in #152 (and the same shape applied in #139/#149 for TabView/RadioButtons/PasswordBox) still flaked at ~0.3% across a 1000x sweep — 2 hits in 651 runs, both on `GotFocus_FiresOnA`. The number of dispatcher ticks before programmatic Focus() raises GotFocus isn't bounded, so any fixed pump count is a guess. Replace the fixed pumps with a pump-until-counter-updates loop, capped at 10 iterations (~200ms) to fail fast if the event genuinely never fires. Applied to both focus transitions in the fixture. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two remaining flake clusters surfaced in a 100×
Reactor.AppTests.Host --self-testsweep on top of #139 (3/100 run-fail rate before; expected 0/100 after). Both are async-timing races where a single render pump isn't enough.Resource_FetchedData(CovBoost_ComponentUseResource) — 2/100, runs 49 & 54.Task.Delay(10)fetcher resolves during the 200 ms wall-clock wait insideHarness.Render(200), then schedules a re-render that may not flush beforeRender(200)returns. Pump once more after the wall-clock wait so the queued re-render drains.EchoSuppress_PasswordBox_UserEditFires— 1/100, run 24.PasswordBox.PasswordChangedcan be raised via the dispatcher rather than synchronously in the setter (same shape as the TabView/RadioButtons flake fixed in fix(selftest): stabilize HostControlMountFunc + Tab/RadioButtons selection flakes #139). Pump twice betweenpb.Password = "typed"and the counter assertion.Diff is +8 lines across two fixture files — no production code changed.
Test plan
dotnet build tests/Reactor.AppTests.Host— clean (0 warnings, 0 errors)🤖 Generated with Claude Code