Skip to content

Commit 85b70b0

Browse files
test(signals): de-flake #2843 pin with a test-resolved deferred fetch
The pin sampled the revalidating window with wall-clock timers (5ms sample vs 20ms fetch); under a loaded full-suite run the sample fired late, after the refetch settled, and the isPending assertion read false. The fetch now resolves only when the test says so, keeping the window open until sampled. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 4b5272f commit 85b70b0

1 file changed

Lines changed: 12 additions & 6 deletions

File tree

packages/solid-signals/tests/scheduler-livelock.test.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,20 @@ it("disposing a subtree with a stale height-adjust entry does not corrupt the di
141141
* @see https://github.com/solidjs/solid/issues/2843
142142
*/
143143
it("isPending(() => latest(x)) in a user effect does not loop on refetch (#2843)", async () => {
144-
const delay = (ms: number) => new Promise(r => setTimeout(r, ms));
144+
// Deferred fetch (not wall-clock timers): the revalidating window must stay
145+
// open until the test closes it, or a loaded event loop lets the refetch
146+
// settle before the assertion samples and the pin flakes.
147+
const settle = () => new Promise(r => setTimeout(r, 0));
145148
const [version, setVersion] = createSignal(0);
146149
const states: boolean[] = [];
150+
let resolveFetch!: () => void;
147151
let dispose!: () => void;
148152

149153
createRoot(d => {
150154
dispose = d;
151155
const data = createMemo(async () => {
152156
const v = version();
153-
await delay(20);
157+
await new Promise<void>(r => (resolveFetch = r));
154158
return `payload v${v}`;
155159
});
156160
// `data` deliberately not read by any render effect
@@ -163,18 +167,20 @@ it("isPending(() => latest(x)) in a user effect does not loop on refetch (#2843)
163167
});
164168

165169
flush();
166-
await delay(40);
170+
resolveFetch();
171+
await settle();
167172
flush();
168173
expect(states.at(-1)).toBe(false); // settled -> idle
169174

170175
// the post-settle write that triggered the unbounded spin
171176
setVersion(v => v + 1);
172177
flush(); // threw "Potential Infinite Loop Detected." when broken
173-
await delay(5);
178+
await settle();
174179
flush();
175-
expect(states.at(-1)).toBe(true); // revalidating
180+
expect(states.at(-1)).toBe(true); // revalidating (fetch still deferred)
176181

177-
await delay(40);
182+
resolveFetch();
183+
await settle();
178184
flush();
179185
expect(states.at(-1)).toBe(false); // back to idle
180186

0 commit comments

Comments
 (0)