Fix the flaky TransientNotice timer test blocking both Dependabot PRs - #113
Merged
Merged
Conversation
Show_TwiceQuickly_LaterMessageSurvivesTheEarlierTimer has been failing CI on both open Dependabot PRs. It is flaky, not a regression: PR #110's same commit passed at 21:39 and failed at 21:44 on 2026-08-17. The test slept 100ms then 180ms against a 200ms dismiss deadline that restarted at the 100ms mark, so it asserted ~280ms into a window closing at ~300ms. Twenty milliseconds of headroom across two Task.Delay calls, on a shared runner, against ~15.6ms timer granularity. TransientNotice now takes an optional TimeProvider, defaulting to TimeProvider.System so all six call sites are untouched, and the auto-dismiss awaits Task.Delay against it. The tests drive a FakeTimeProvider and land their assertions exactly on the deadlines that matter instead of sampling somewhere between them. The dismiss clears state before invoking the re-render callback, so the tests use that callback as their completion signal rather than sleeping. Where a test asserts that a cancelled timer never fires, it first waits a real grace window - safe here because fake time only moves when a test moves it, so a correctly cancelled timer never fires however long we wait. Confirmed by mutation: dropping the Cancel() from Show() fails Show_TwiceQuickly_LaterMessageSurvivesTheEarlierTimer, and dropping it from Clear() fails Clear_RemovesMessageImmediatelyAndStopsTimer. 710 tests green in Release.
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.
What
TransientNoticeTests.Show_TwiceQuickly_LaterMessageSurvivesTheEarlierTimerhas been failing CI on both open Dependabot PRs (#110, #111), blocking the whole Dependabot lane. #111 has auto-merge on and is stuck behind it.It is flaky, not a regression — and the run history proves that rather than merely suggesting it. On PR #110's same commit, CI passed at
2026-08-17T21:39:26Zand failed at21:43:59Z.Why it flakes
The test drove a 200ms auto-dismiss with real
Task.Delaycalls:Two
Task.Delaycalls that between them had to not overshoot by more than 20ms, on a shared runner, against ~15.6ms Windows timer granularity. It was always going to fail eventually.The fix
TransientNoticenow takes an optionalTimeProvider, defaulting toTimeProvider.Systemso all six call sites are untouched, and the auto-dismiss awaitsTask.Delayagainst it. The tests drive aFakeTimeProviderand land their assertions exactly on the deadlines that matter instead of sampling somewhere between them.The dismiss clears state before invoking the re-render callback, so the tests use that callback as their completion signal rather than sleeping. Where a test asserts that a cancelled timer never fires, it first waits a real grace window — safe here precisely because fake time only moves when a test moves it, so a correctly cancelled timer never fires however long we wait.
Clear_RemovesMessageImmediatelyAndStopsTimergets stronger in passing: it used to prove the timer had not fired within 50ms of a 60s deadline, and now advances five minutes past it.Verification
Cancel()fromShow()failsShow_TwiceQuickly_LaterMessageSurvivesTheEarlierTimer; dropping it fromClear()failsClear_RemovesMessageImmediatelyAndStopsTimer.Adds
Microsoft.Extensions.TimeProvider.Testing(first-party, test project only) via CPM.