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:
@@ -61,6 +61,7 @@ describe('useDelayed', () => {
|
|||||||
const cleanup = $effect.root(() => {
|
const cleanup = $effect.root(() => {
|
||||||
delayed = useDelayed(() => source, 100);
|
delayed = useDelayed(() => source, 100);
|
||||||
});
|
});
|
||||||
|
flushSync(); // run the initial $effect so the setTimeout is scheduled
|
||||||
|
|
||||||
vi.advanceTimersByTime(200);
|
vi.advanceTimersByTime(200);
|
||||||
expect(delayed.value).toBe(true);
|
expect(delayed.value).toBe(true);
|
||||||
|
|||||||
@@ -11,15 +11,6 @@ export function useDelayed(
|
|||||||
let delayed = $state(false);
|
let delayed = $state(false);
|
||||||
let timeout: ReturnType<typeof setTimeout> | null = null;
|
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(() => {
|
$effect(() => {
|
||||||
const v = source();
|
const v = source();
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
|
|||||||
Reference in New Issue
Block a user