Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SchedulerMock.unstable_yieldValue -> SchedulerMock.log #26312

Merged
merged 2 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions packages/internal-test-utils/ReactInternalTestUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {equals} from '@jest/expect-utils';
import enqueueTask from './enqueueTask';

function assertYieldsWereCleared(Scheduler) {
const actualYields = Scheduler.unstable_clearYields();
const actualYields = Scheduler.unstable_clearLog();
if (actualYields.length !== 0) {
const error = Error(
'The event log is not empty. Call assertLog(...) first.',
Expand Down Expand Up @@ -45,14 +45,14 @@ export async function waitFor(expectedLog) {
SchedulerMock.unstable_flushNumberOfYields(
expectedLog.length - actualLog.length,
);
actualLog.push(...SchedulerMock.unstable_clearYields());
actualLog.push(...SchedulerMock.unstable_clearLog());
if (expectedLog.length > actualLog.length) {
// Continue flushing until we've logged the expected number of items.
} else {
// Once we've reached the expected sequence, wait one more microtask to
// flush any remaining synchronous work.
await waitForMicrotasks();
actualLog.push(...SchedulerMock.unstable_clearYields());
actualLog.push(...SchedulerMock.unstable_clearLog());
break;
}
} else {
Expand Down Expand Up @@ -91,7 +91,7 @@ export async function waitForAll(expectedLog) {
SchedulerMock.unstable_flushAllWithoutAsserting();
} while (true);

const actualLog = SchedulerMock.unstable_clearYields();
const actualLog = SchedulerMock.unstable_clearLog();
if (equals(actualLog, expectedLog)) {
return;
}
Expand Down Expand Up @@ -166,7 +166,7 @@ export async function waitForPaint(expectedLog) {
await waitForMicrotasks();
}

const actualLog = SchedulerMock.unstable_clearYields();
const actualLog = SchedulerMock.unstable_clearLog();
if (equals(actualLog, expectedLog)) {
return;
}
Expand All @@ -180,7 +180,7 @@ ${diff(expectedLog, actualLog)}
}

export function assertLog(expectedLog) {
const actualLog = SchedulerMock.unstable_clearYields();
const actualLog = SchedulerMock.unstable_clearLog();
if (equals(actualLog, expectedLog)) {
return;
}
Expand Down
160 changes: 160 additions & 0 deletions packages/internal-test-utils/__tests__/ReactInternalTestUtils-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails react-core
* @jest-environment node
*/

'use strict';

const React = require('react');
const {startTransition, useDeferredValue} = React;
const ReactNoop = require('react-noop-renderer');
const {
waitFor,
waitForAll,
waitForPaint,
waitForThrow,
assertLog,
} = require('internal-test-utils');
const act = require('jest-react').act;
const Scheduler = require('scheduler/unstable_mock');

describe('ReactInternalTestUtils', () => {
test('waitFor', async () => {
const Yield = ({id}) => {
Scheduler.log(id);
return id;
};

const root = ReactNoop.createRoot();
startTransition(() => {
root.render(
<div>
<Yield id="foo" />
<Yield id="bar" />
<Yield id="baz" />
</div>
);
});

await waitFor(['foo', 'bar']);
expect(root).toMatchRenderedOutput(null);
await waitFor(['baz']);
expect(root).toMatchRenderedOutput(null);
await waitForAll([]);
expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);
});

test('waitForAll', async () => {
const Yield = ({id}) => {
Scheduler.log(id);
return id;
};

const root = ReactNoop.createRoot();
startTransition(() => {
root.render(
<div>
<Yield id="foo" />
<Yield id="bar" />
<Yield id="baz" />
</div>
);
});

await waitForAll(['foo', 'bar', 'baz']);
expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);
});

test('waitForThrow', async () => {
const Yield = ({id}) => {
Scheduler.log(id);
return id;
};

function BadRender() {
throw new Error('Oh no!');
}

function App() {
return (
<div>
<Yield id="A" />
<Yield id="B" />
<BadRender />
<Yield id="C" />
<Yield id="D" />
</div>
);
}

const root = ReactNoop.createRoot();
root.render(<App />);

await waitForThrow('Oh no!');
assertLog([
'A',
'B',
'C',
'D',
// React will try one more time before giving up.
'A',
'B',
'C',
'D',
]);
});

test('waitForPaint', async () => {
function App({prop}) {
const deferred = useDeferredValue(prop);
const text = `Urgent: ${prop}, Deferred: ${deferred}`;
Scheduler.log(text);
return text;
}

const root = ReactNoop.createRoot();
root.render(<App prop="A" />);

await waitForAll(['Urgent: A, Deferred: A']);
expect(root).toMatchRenderedOutput('Urgent: A, Deferred: A');

// This update will result in two separate paints: an urgent one, and a
// deferred one.
root.render(<App prop="B" />);
// Urgent paint
await waitForPaint(['Urgent: B, Deferred: A']);
expect(root).toMatchRenderedOutput('Urgent: B, Deferred: A');

// Deferred paint
await waitForPaint(['Urgent: B, Deferred: B']);
expect(root).toMatchRenderedOutput('Urgent: B, Deferred: B');
});

test('assertLog', async () => {
const Yield = ({id}) => {
Scheduler.log(id);
return id;
};

function App() {
return (
<div>
<Yield id="A" />
<Yield id="B" />
<Yield id="C" />
</div>
);
}

const root = ReactNoop.createRoot();
await act(async () => {
root.render(<App />);
});
assertLog(['A', 'B', 'C']);
});
});
2 changes: 1 addition & 1 deletion packages/jest-react/src/JestReact.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function captureAssertion(fn) {

function assertYieldsWereCleared(root) {
const Scheduler = root._Scheduler;
const actualYields = Scheduler.unstable_clearYields();
const actualYields = Scheduler.unstable_clearLog();
if (actualYields.length !== 0) {
const error = Error(
'Log of yielded values is not empty. ' +
Expand Down
24 changes: 10 additions & 14 deletions packages/react-cache/src/__tests__/ReactCacheOld-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,12 @@ describe('ReactCache', () => {
listeners = [{resolve, reject}];
setTimeout(() => {
if (textResourceShouldFail) {
Scheduler.unstable_yieldValue(
`Promise rejected [${text}]`,
);
Scheduler.log(`Promise rejected [${text}]`);
status = 'rejected';
value = new Error('Failed to load: ' + text);
listeners.forEach(listener => listener.reject(value));
} else {
Scheduler.unstable_yieldValue(
`Promise resolved [${text}]`,
);
Scheduler.log(`Promise resolved [${text}]`);
status = 'resolved';
value = text;
listeners.forEach(listener => listener.resolve(value));
Expand Down Expand Up @@ -93,21 +89,21 @@ describe('ReactCache', () => {
});

function Text(props) {
Scheduler.unstable_yieldValue(props.text);
Scheduler.log(props.text);
return props.text;
}

function AsyncText(props) {
const text = props.text;
try {
TextResource.read([props.text, props.ms]);
Scheduler.unstable_yieldValue(text);
Scheduler.log(text);
return text;
} catch (promise) {
if (typeof promise.then === 'function') {
Scheduler.unstable_yieldValue(`Suspend! [${text}]`);
Scheduler.log(`Suspend! [${text}]`);
} else {
Scheduler.unstable_yieldValue(`Error! [${text}]`);
Scheduler.log(`Error! [${text}]`);
}
throw promise;
}
Expand Down Expand Up @@ -171,7 +167,7 @@ describe('ReactCache', () => {
});

function App() {
Scheduler.unstable_yieldValue('App');
Scheduler.log('App');
return BadTextResource.read(['Hi', 100]);
}

Expand Down Expand Up @@ -322,13 +318,13 @@ describe('ReactCache', () => {
const text = props.text;
try {
const actualText = BadTextResource.read([props.text, props.ms]);
Scheduler.unstable_yieldValue(actualText);
Scheduler.log(actualText);
return actualText;
} catch (promise) {
if (typeof promise.then === 'function') {
Scheduler.unstable_yieldValue(`Suspend! [${text}]`);
Scheduler.log(`Suspend! [${text}]`);
} else {
Scheduler.unstable_yieldValue(`Error! [${text}]`);
Scheduler.log(`Error! [${text}]`);
}
throw promise;
}
Expand Down
8 changes: 4 additions & 4 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ describe('ReactFlight', () => {
}

function ClientDoubler({el}) {
Scheduler.unstable_yieldValue('ClientDoubler');
Scheduler.log('ClientDoubler');
return (
<>
{el}
Expand Down Expand Up @@ -990,10 +990,10 @@ describe('ReactFlight', () => {

function Bar() {
if (!promise.unsuspend) {
Scheduler.unstable_yieldValue('suspended');
Scheduler.log('suspended');
throw promise;
}
Scheduler.unstable_yieldValue('rendered');
Scheduler.log('rendered');
const context = React.useContext(ServerContext);
return context;
}
Expand Down Expand Up @@ -1027,7 +1027,7 @@ describe('ReactFlight', () => {
);

function ClientBar() {
Scheduler.unstable_yieldValue('ClientBar');
Scheduler.log('ClientBar');
const context = React.useContext(ServerContext);
return <span>{context}</span>;
}
Expand Down
Loading