Skip to content

Commit

Permalink
Added some additional interaction tests for interleaved suspense and …
Browse files Browse the repository at this point in the history
…high-pri renders
  • Loading branch information
Brian Vaughn committed Sep 18, 2018
1 parent be18adc commit 845fccd
Showing 1 changed file with 208 additions and 4 deletions.
212 changes: 208 additions & 4 deletions packages/react/src/__tests__/ReactProfiler-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2198,9 +2198,9 @@ describe('Profiler', () => {
return text;
} catch (promise) {
if (typeof promise.then === 'function') {
yieldForRenderer(`Suspend! [${text}]`);
yieldForRenderer(`Suspend [${text}]`);
} else {
yieldForRenderer(`Error! [${text}]`);
yieldForRenderer(`Error [${text}]`);
}
throw promise;
}
Expand Down Expand Up @@ -2242,7 +2242,7 @@ describe('Profiler', () => {
expect(getWorkForReactThreads(onWorkStopped)).toHaveLength(0);

expect(ReactNoop.flush()).toEqual([
'Suspend! [Async]',
'Suspend [Async]',
'Text [Loading...]',
'Text [Sync]',
]);
Expand Down Expand Up @@ -2422,7 +2422,7 @@ describe('Profiler', () => {
advanceTimeBy(1500);
await awaitableAdvanceTimers(1500);

expect(renderer).toFlushAll(['Suspend! [loaded]', 'Text [loading]']);
expect(renderer).toFlushAll(['Suspend [loaded]', 'Text [loading]']);
expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();

advanceTimeBy(2500);
Expand Down Expand Up @@ -2473,6 +2473,210 @@ describe('Profiler', () => {
onInteractionScheduledWorkCompleted,
).toHaveBeenLastNotifiedOfInteraction(interaction);
});

it('handles high-pri renderers between suspended and resolved (sync) trees', async () => {
let instance;
class ClassComponent extends React.Component {
render() {
instance = this;
yieldForRenderer(`ClassComponent [${this.props.value}]`);
return this.props.value;
}
}

const initialRenderInteraction = {
id: 0,
name: 'initial render',
timestamp: mockNow(),
};

const onRender = jest.fn();
let renderer;
SchedulerTracing.unstable_trace(
initialRenderInteraction.name,
initialRenderInteraction.timestamp,
() => {
renderer = ReactTestRenderer.create(
<React.unstable_Profiler id="app" onRender={onRender}>
<React.Placeholder
delayMs={2000}
fallback={<Text text="loading" />}>
<AsyncText text="loaded" ms={1000} />
</React.Placeholder>
<ClassComponent value="initial" />
</React.unstable_Profiler>,
);
},
);
expect(renderer.toJSON()).toEqual(['loading', 'initial']);

expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();
expect(onRender).toHaveBeenCalledTimes(2); // Sync null commit, placeholder commit
expect(onRender.mock.calls[0][6]).toMatchInteractions([
initialRenderInteraction,
]);
onRender.mockClear();

const highPriUpdateInteraction = {
id: 1,
name: 'hiPriUpdate',
timestamp: mockNow(),
};

const originalPromise = resourcePromise;

renderer.unstable_flushSync(() => {
SchedulerTracing.unstable_trace(
highPriUpdateInteraction.name,
highPriUpdateInteraction.timestamp,
() => {
renderer.update(
<React.unstable_Profiler id="app" onRender={onRender}>
<React.Placeholder
delayMs={2000}
fallback={<Text text="loading" />}>
<AsyncText text="loaded" ms={1000} />
</React.Placeholder>
<ClassComponent value="updated" />
</React.unstable_Profiler>,
);
},
);
});
expect(renderer.toJSON()).toEqual(['loading', 'updated']);

expect(onRender).toHaveBeenCalledTimes(2); // Sync null commit, placeholder commit
expect(onRender.mock.calls[0][6]).toMatchInteractions([
initialRenderInteraction,
highPriUpdateInteraction,
]);
onRender.mockClear();

expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();

advanceTimeBy(1000);
jest.advanceTimersByTime(1000);
await originalPromise;
expect(renderer.toJSON()).toEqual(['loaded', 'updated']);

expect(onRender).toHaveBeenCalledTimes(2);
expect(onRender.mock.calls[0][6]).toMatchInteractions([
initialRenderInteraction,
highPriUpdateInteraction,
]);

expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);
expect(
onInteractionScheduledWorkCompleted.mock.calls[0][0],
).toMatchInteraction(initialRenderInteraction);
expect(
onInteractionScheduledWorkCompleted.mock.calls[1][0],
).toMatchInteraction(highPriUpdateInteraction);
});

it('handles high-pri renderers between suspended and resolved (async) trees', async () => {
let instance;
class ClassComponent extends React.Component {
render() {
instance = this;
yieldForRenderer(`ClassComponent [${this.props.value}]`);
return this.props.value;
}
}

const initialRenderInteraction = {
id: 0,
name: 'initial render',
timestamp: mockNow(),
};

const onRender = jest.fn();
let renderer;
SchedulerTracing.unstable_trace(
initialRenderInteraction.name,
initialRenderInteraction.timestamp,
() => {
renderer = ReactTestRenderer.create(
<React.unstable_Profiler id="app" onRender={onRender}>
<React.Placeholder
delayMs={2000}
fallback={<Text text="loading" />}>
<AsyncText text="loaded" ms={1000} />
</React.Placeholder>
<ClassComponent value="initial" />
</React.unstable_Profiler>,
{unstable_isAsync: true},
);
},
);
expect(renderer).toFlushAll([
'Suspend [loaded]',
'Text [loading]',
'ClassComponent [initial]',
]);

expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();
expect(onRender).not.toHaveBeenCalled();

advanceTimeBy(500);
jest.advanceTimersByTime(500);

const highPriUpdateInteraction = {
id: 1,
name: 'hiPriUpdate',
timestamp: mockNow(),
};

const originalPromise = resourcePromise;

renderer.unstable_flushSync(() => {
SchedulerTracing.unstable_trace(
highPriUpdateInteraction.name,
highPriUpdateInteraction.timestamp,
() => {
renderer.update(
<React.unstable_Profiler id="app" onRender={onRender}>
<React.Placeholder
delayMs={2000}
fallback={<Text text="loading" />}>
<AsyncText text="loaded" ms={1000} />
</React.Placeholder>
<ClassComponent value="updated" />
</React.unstable_Profiler>,
);
},
);
});
expect(renderer.toJSON()).toEqual(['loading', 'updated']);

expect(onRender).toHaveBeenCalledTimes(1);
expect(onRender.mock.calls[0][6]).toMatchInteractions([
highPriUpdateInteraction,
]);
onRender.mockClear();

expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);
expect(
onInteractionScheduledWorkCompleted,
).toHaveBeenLastNotifiedOfInteraction(highPriUpdateInteraction);

advanceTimeBy(500);
jest.advanceTimersByTime(500);
await originalPromise;
expect(renderer).toFlushAll(['AsyncText [loaded]']);
expect(renderer.toJSON()).toEqual(['loaded', 'updated']);

expect(onRender).toHaveBeenCalledTimes(1);
expect(onRender.mock.calls[0][6]).toMatchInteractions([
initialRenderInteraction,
highPriUpdateInteraction,
]);

expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);
expect(
onInteractionScheduledWorkCompleted,
).toHaveBeenLastNotifiedOfInteraction(initialRenderInteraction);
});
});
});
});

0 comments on commit 845fccd

Please sign in to comment.