Skip to content

Commit b9dfb88

Browse files
committed
suspense tests 3
1 parent 45e7e0e commit b9dfb88

File tree

1 file changed

+26
-107
lines changed

1 file changed

+26
-107
lines changed

src/__tests__/suspense-fake-timers.test.tsx

Lines changed: 26 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -142,117 +142,36 @@ testGateReact19('handles suspense with error boundary in fake timers', async ()
142142
expect(screen.queryByText('Loading...')).not.toBeOnTheScreen();
143143
});
144144

145-
function AnimationSuspending() {
146-
const [progress, setProgress] = React.useState(0);
145+
function MultiComponentSuspense() {
146+
let resolveFirst: (value: unknown) => void;
147+
let resolveSecond: (value: unknown) => void;
147148

148-
React.useEffect(() => {
149-
const animate = () => {
150-
setProgress(p => {
151-
if (p >= 100) return 100;
152-
setTimeout(animate, 16); // 60fps
153-
return p + 1;
154-
});
155-
};
156-
animate();
157-
}, []);
158-
159-
if (progress < 100) {
160-
const promise = new Promise(() => {}); // Suspend until animation complete
161-
React.use(promise);
162-
}
163-
164-
return <View testID="animation-complete" />;
165-
}
166-
167-
testGateReact19('handles animation-like suspense with fake timers', async () => {
168-
await renderAsync(
169-
<React.Suspense fallback={<Text>Animating...</Text>}>
170-
<AnimationSuspending />
171-
</React.Suspense>,
172-
);
173-
174-
expect(screen.getByText('Animating...')).toBeOnTheScreen();
175-
expect(screen.queryByTestId('animation-complete')).not.toBeOnTheScreen();
176-
177-
// Should complete after animation finishes
178-
expect(await screen.findByTestId('animation-complete')).toBeOnTheScreen();
179-
expect(screen.queryByText('Animating...')).not.toBeOnTheScreen();
180-
});
181-
182-
function RetryingSuspending({ maxRetries = 3 }: { maxRetries?: number }) {
183-
const [retries, setRetries] = React.useState(0);
184-
185-
const promise = React.useMemo(() => {
186-
if (retries < maxRetries) {
187-
// Simulate a failing request that retries
188-
setTimeout(() => setRetries(r => r + 1), 100);
189-
return new Promise(() => {}); // Never resolves, will retry
190-
}
191-
// Success case
192-
return Promise.resolve('success');
193-
}, [retries, maxRetries]);
149+
const firstPromise = new Promise((resolve) => {
150+
resolveFirst = resolve;
151+
});
152+
const secondPromise = new Promise((resolve) => {
153+
resolveSecond = resolve;
154+
});
194155

195-
const data = React.use(promise);
196-
return <View testID={`retry-content-${data}`} />;
197-
}
198-
199-
testGateReact19('handles retry logic with fake timers', async () => {
200-
await renderAsync(
201-
<React.Suspense fallback={<Text>Retrying...</Text>}>
202-
<RetryingSuspending maxRetries={2} />
203-
</React.Suspense>,
204-
);
205-
206-
expect(screen.getByText('Retrying...')).toBeOnTheScreen();
207-
expect(screen.queryByTestId('retry-content-success')).not.toBeOnTheScreen();
208-
209-
// Should eventually succeed after retries
210-
expect(await screen.findByTestId('retry-content-success')).toBeOnTheScreen();
211-
expect(screen.queryByText('Retrying...')).not.toBeOnTheScreen();
212-
});
213-
214-
function CascadingSuspending({ level }: { level: number }) {
215-
const delay = level * 50;
216-
const promise = React.useMemo(() =>
217-
new Promise((resolve) => {
218-
setTimeout(() => resolve(level), delay);
219-
}), [delay, level]
156+
return (
157+
<View>
158+
<React.Suspense fallback={<Text>First Loading...</Text>}>
159+
<Suspending promise={firstPromise} />
160+
</React.Suspense>
161+
<React.Suspense fallback={<Text>Second Loading...</Text>}>
162+
<View testID="second-boundary">
163+
<Suspending promise={secondPromise} />
164+
</View>
165+
</React.Suspense>
166+
</View>
220167
);
221-
222-
const data = React.use(promise);
223-
224-
if (level > 1) {
225-
return (
226-
<View>
227-
<View testID={`cascade-${data}`} />
228-
<React.Suspense fallback={<Text>Cascade Loading {level - 1}...</Text>}>
229-
<CascadingSuspending level={level - 1} />
230-
</React.Suspense>
231-
</View>
232-
);
233-
}
234-
235-
return <View testID={`cascade-${data}`} />;
236168
}
237169

238-
testGateReact19('handles cascading suspense with fake timers', async () => {
239-
await renderAsync(
240-
<React.Suspense fallback={<Text>Cascade Loading 3...</Text>}>
241-
<CascadingSuspending level={3} />
242-
</React.Suspense>,
243-
);
244-
245-
expect(screen.getByText('Cascade Loading 3...')).toBeOnTheScreen();
246-
247-
// Should resolve level by level
248-
expect(await screen.findByTestId('cascade-3')).toBeOnTheScreen();
249-
expect(screen.getByText('Cascade Loading 2...')).toBeOnTheScreen();
170+
testGateReact19('handles multiple independent suspense boundaries', async () => {
171+
await renderAsync(<MultiComponentSuspense />);
250172

251-
expect(await screen.findByTestId('cascade-2')).toBeOnTheScreen();
252-
expect(screen.getByText('Cascade Loading 1...')).toBeOnTheScreen();
253-
254-
expect(await screen.findByTestId('cascade-1')).toBeOnTheScreen();
255-
expect(screen.queryByText('Cascade Loading 1...')).not.toBeOnTheScreen();
256-
expect(screen.queryByText('Cascade Loading 2...')).not.toBeOnTheScreen();
257-
expect(screen.queryByText('Cascade Loading 3...')).not.toBeOnTheScreen();
173+
expect(screen.getByText('First Loading...')).toBeOnTheScreen();
174+
expect(screen.getByText('Second Loading...')).toBeOnTheScreen();
175+
expect(screen.queryByTestId('content')).not.toBeOnTheScreen();
176+
expect(screen.queryByTestId('second-boundary')).not.toBeOnTheScreen();
258177
});

0 commit comments

Comments
 (0)