Skip to content

Commit a98e242

Browse files
author
Brian Vaughn
committed
Added some additional interaction tests for interleaved suspense and high-pri renders
1 parent be18adc commit a98e242

File tree

1 file changed

+190
-4
lines changed

1 file changed

+190
-4
lines changed

packages/react/src/__tests__/ReactProfiler-test.internal.js

Lines changed: 190 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2198,9 +2198,9 @@ describe('Profiler', () => {
21982198
return text;
21992199
} catch (promise) {
22002200
if (typeof promise.then === 'function') {
2201-
yieldForRenderer(`Suspend! [${text}]`);
2201+
yieldForRenderer(`Suspend [${text}]`);
22022202
} else {
2203-
yieldForRenderer(`Error! [${text}]`);
2203+
yieldForRenderer(`Error [${text}]`);
22042204
}
22052205
throw promise;
22062206
}
@@ -2242,7 +2242,7 @@ describe('Profiler', () => {
22422242
expect(getWorkForReactThreads(onWorkStopped)).toHaveLength(0);
22432243

22442244
expect(ReactNoop.flush()).toEqual([
2245-
'Suspend! [Async]',
2245+
'Suspend [Async]',
22462246
'Text [Loading...]',
22472247
'Text [Sync]',
22482248
]);
@@ -2422,7 +2422,7 @@ describe('Profiler', () => {
24222422
advanceTimeBy(1500);
24232423
await awaitableAdvanceTimers(1500);
24242424

2425-
expect(renderer).toFlushAll(['Suspend! [loaded]', 'Text [loading]']);
2425+
expect(renderer).toFlushAll(['Suspend [loaded]', 'Text [loading]']);
24262426
expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();
24272427

24282428
advanceTimeBy(2500);
@@ -2473,6 +2473,192 @@ describe('Profiler', () => {
24732473
onInteractionScheduledWorkCompleted,
24742474
).toHaveBeenLastNotifiedOfInteraction(interaction);
24752475
});
2476+
2477+
it('handles high-pri renderers between suspended and resolved (sync) trees', async () => {
2478+
const initialRenderInteraction = {
2479+
id: 0,
2480+
name: 'initial render',
2481+
timestamp: mockNow(),
2482+
};
2483+
2484+
const onRender = jest.fn();
2485+
let renderer;
2486+
SchedulerTracing.unstable_trace(
2487+
initialRenderInteraction.name,
2488+
initialRenderInteraction.timestamp,
2489+
() => {
2490+
renderer = ReactTestRenderer.create(
2491+
<React.unstable_Profiler id="app" onRender={onRender}>
2492+
<React.Placeholder
2493+
delayMs={2000}
2494+
fallback={<Text text="loading" />}>
2495+
<AsyncText text="loaded" ms={1000} />
2496+
</React.Placeholder>
2497+
<Text text="initial" />
2498+
</React.unstable_Profiler>,
2499+
);
2500+
},
2501+
);
2502+
expect(renderer.toJSON()).toEqual(['loading', 'initial']);
2503+
2504+
expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();
2505+
expect(onRender).toHaveBeenCalledTimes(2); // Sync null commit, placeholder commit
2506+
expect(onRender.mock.calls[0][6]).toMatchInteractions([
2507+
initialRenderInteraction,
2508+
]);
2509+
onRender.mockClear();
2510+
2511+
const highPriUpdateInteraction = {
2512+
id: 1,
2513+
name: 'hiPriUpdate',
2514+
timestamp: mockNow(),
2515+
};
2516+
2517+
const originalPromise = resourcePromise;
2518+
2519+
renderer.unstable_flushSync(() => {
2520+
SchedulerTracing.unstable_trace(
2521+
highPriUpdateInteraction.name,
2522+
highPriUpdateInteraction.timestamp,
2523+
() => {
2524+
renderer.update(
2525+
<React.unstable_Profiler id="app" onRender={onRender}>
2526+
<React.Placeholder
2527+
delayMs={2000}
2528+
fallback={<Text text="loading" />}>
2529+
<AsyncText text="loaded" ms={1000} />
2530+
</React.Placeholder>
2531+
<Text text="updated" />
2532+
</React.unstable_Profiler>,
2533+
);
2534+
},
2535+
);
2536+
});
2537+
expect(renderer.toJSON()).toEqual(['loading', 'updated']);
2538+
2539+
expect(onRender).toHaveBeenCalledTimes(2); // Sync null commit, placeholder commit
2540+
expect(onRender.mock.calls[0][6]).toMatchInteractions([
2541+
initialRenderInteraction,
2542+
highPriUpdateInteraction,
2543+
]);
2544+
onRender.mockClear();
2545+
2546+
expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();
2547+
2548+
advanceTimeBy(1000);
2549+
jest.advanceTimersByTime(1000);
2550+
await originalPromise;
2551+
expect(renderer.toJSON()).toEqual(['loaded', 'updated']);
2552+
2553+
expect(onRender).toHaveBeenCalledTimes(2);
2554+
expect(onRender.mock.calls[0][6]).toMatchInteractions([
2555+
initialRenderInteraction,
2556+
highPriUpdateInteraction,
2557+
]);
2558+
2559+
expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);
2560+
expect(
2561+
onInteractionScheduledWorkCompleted.mock.calls[0][0],
2562+
).toMatchInteraction(initialRenderInteraction);
2563+
expect(
2564+
onInteractionScheduledWorkCompleted.mock.calls[1][0],
2565+
).toMatchInteraction(highPriUpdateInteraction);
2566+
});
2567+
2568+
it('handles high-pri renderers between suspended and resolved (async) trees', async () => {
2569+
const initialRenderInteraction = {
2570+
id: 0,
2571+
name: 'initial render',
2572+
timestamp: mockNow(),
2573+
};
2574+
2575+
const onRender = jest.fn();
2576+
let renderer;
2577+
SchedulerTracing.unstable_trace(
2578+
initialRenderInteraction.name,
2579+
initialRenderInteraction.timestamp,
2580+
() => {
2581+
renderer = ReactTestRenderer.create(
2582+
<React.unstable_Profiler id="app" onRender={onRender}>
2583+
<React.Placeholder
2584+
delayMs={2000}
2585+
fallback={<Text text="loading" />}>
2586+
<AsyncText text="loaded" ms={1000} />
2587+
</React.Placeholder>
2588+
<Text text="initial" />
2589+
</React.unstable_Profiler>,
2590+
{unstable_isAsync: true},
2591+
);
2592+
},
2593+
);
2594+
expect(renderer).toFlushAll([
2595+
'Suspend [loaded]',
2596+
'Text [loading]',
2597+
'Text [initial]',
2598+
]);
2599+
2600+
expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();
2601+
expect(onRender).not.toHaveBeenCalled();
2602+
2603+
advanceTimeBy(500);
2604+
jest.advanceTimersByTime(500);
2605+
2606+
const highPriUpdateInteraction = {
2607+
id: 1,
2608+
name: 'hiPriUpdate',
2609+
timestamp: mockNow(),
2610+
};
2611+
2612+
const originalPromise = resourcePromise;
2613+
2614+
renderer.unstable_flushSync(() => {
2615+
SchedulerTracing.unstable_trace(
2616+
highPriUpdateInteraction.name,
2617+
highPriUpdateInteraction.timestamp,
2618+
() => {
2619+
renderer.update(
2620+
<React.unstable_Profiler id="app" onRender={onRender}>
2621+
<React.Placeholder
2622+
delayMs={2000}
2623+
fallback={<Text text="loading" />}>
2624+
<AsyncText text="loaded" ms={1000} />
2625+
</React.Placeholder>
2626+
<Text text="updated" />
2627+
</React.unstable_Profiler>,
2628+
);
2629+
},
2630+
);
2631+
});
2632+
expect(renderer.toJSON()).toEqual(['loading', 'updated']);
2633+
2634+
expect(onRender).toHaveBeenCalledTimes(1);
2635+
expect(onRender.mock.calls[0][6]).toMatchInteractions([
2636+
highPriUpdateInteraction,
2637+
]);
2638+
onRender.mockClear();
2639+
2640+
expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);
2641+
expect(
2642+
onInteractionScheduledWorkCompleted,
2643+
).toHaveBeenLastNotifiedOfInteraction(highPriUpdateInteraction);
2644+
2645+
advanceTimeBy(500);
2646+
jest.advanceTimersByTime(500);
2647+
await originalPromise;
2648+
expect(renderer).toFlushAll(['AsyncText [loaded]']);
2649+
expect(renderer.toJSON()).toEqual(['loaded', 'updated']);
2650+
2651+
expect(onRender).toHaveBeenCalledTimes(1);
2652+
expect(onRender.mock.calls[0][6]).toMatchInteractions([
2653+
initialRenderInteraction,
2654+
highPriUpdateInteraction,
2655+
]);
2656+
2657+
expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);
2658+
expect(
2659+
onInteractionScheduledWorkCompleted,
2660+
).toHaveBeenLastNotifiedOfInteraction(initialRenderInteraction);
2661+
});
24762662
});
24772663
});
24782664
});

0 commit comments

Comments
 (0)