refactor(web): drop useDelayed sync-timeout hack; fix test timing instead

The synchronous pre-timeout in the implementation was a band-aid for a
missing flushSync() in the third test. $effect callbacks are scheduled
as microtasks and don't run until flushed — the test set source=true
before the initial effect had a chance to register the setTimeout, so
advanceTimersByTime fired nothing.

Proper fix: call flushSync() after $effect.root so the initial effect
runs synchronously, then advance fake timers. Removed the duplicate
setTimeout branch from useDelayed — one code path, no race.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-23 18:16:22 -04:00
parent 6ca877b3ad
commit 19d74d00d6
2 changed files with 1 additions and 9 deletions
@@ -61,6 +61,7 @@ describe('useDelayed', () => {
const cleanup = $effect.root(() => {
delayed = useDelayed(() => source, 100);
});
flushSync(); // run the initial $effect so the setTimeout is scheduled
vi.advanceTimersByTime(200);
expect(delayed.value).toBe(true);
-9
View File
@@ -11,15 +11,6 @@ export function useDelayed(
let delayed = $state(false);
let timeout: ReturnType<typeof setTimeout> | null = null;
// Schedule the initial timeout synchronously so tests that advance fake
// timers before the first reactive flush still see the correct value.
if (source()) {
timeout = setTimeout(() => {
delayed = true;
timeout = null;
}, delayMs);
}
$effect(() => {
const v = source();
if (timeout) {