Migrate testRunner from jasmine2 to jest-circus (#26144)

## Summary

In jest v27, jest-circus as default test runner
(https://github.com/facebook/jest/pull/10686)

## How did you test this change?

ci green
This commit is contained in:
Ming Ye 2023-02-11 02:39:14 +08:00 committed by GitHub
parent b8ae89f382
commit 71cace4d32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 264 additions and 263 deletions

View File

@ -434,7 +434,6 @@ module.exports = {
es6: true,
node: true,
jest: true,
jasmine: true,
},
globals: {

View File

@ -69,12 +69,10 @@
"gzip-size": "^5.1.1",
"hermes-eslint": "^0.9.0",
"hermes-parser": "^0.9.0",
"jasmine-check": "^1.0.0-rc.0",
"jest": "^29.4.1",
"jest-cli": "^29.4.1",
"jest-diff": "^29.4.1",
"jest-environment-jsdom": "^29.4.1",
"jest-jasmine2": "^29.4.1",
"jest-snapshot-serializer-raw": "^1.1.0",
"minimatch": "^3.0.4",
"minimist": "^1.2.3",

View File

@ -91,6 +91,10 @@ describe('ReactFlight', () => {
};
});
afterEach(() => {
jest.restoreAllMocks();
});
function clientReference(value) {
return Object.defineProperties(
function () {
@ -240,7 +244,7 @@ describe('ReactFlight', () => {
ReactNoop.render(rootModel);
});
expect(ReactNoop).toMatchRenderedOutput('Loading...');
spyOnDevAndProd(console, 'error');
spyOnDevAndProd(console, 'error').mockImplementation(() => {});
await load();
expect(console.error).toHaveBeenCalledTimes(1);
});
@ -322,7 +326,7 @@ describe('ReactFlight', () => {
ReactNoop.render(rootModel);
});
expect(ReactNoop).toMatchRenderedOutput('Loading...');
spyOnDevAndProd(console, 'error');
spyOnDevAndProd(console, 'error').mockImplementation(() => {});
await load();
expect(console.error).toHaveBeenCalledTimes(1);
});

View File

@ -1172,28 +1172,5 @@ declare var expect: {
},
};
// TODO handle return type
// https://jasmine.github.io/2.4/introduction.html#section-Spies
declare function spyOn(value: mixed, method: string): Object;
/** Holds all functions related to manipulating test runner */
declare var jest: JestObjectType;
/**
* The global Jasmine object, this is generally not exposed as the public API,
* using features inside here could break in later versions of Jest.
*/
declare var jasmine: {
DEFAULT_TIMEOUT_INTERVAL: number,
any(value: mixed): JestAsymmetricEqualityType,
anything(): any,
arrayContaining(value: Array<mixed>): Array<mixed>,
clock(): JestClockType,
createSpy(name: string): JestSpyType,
createSpyObj(
baseName: string,
methodNames: Array<string>
): {[methodName: string]: JestSpyType},
objectContaining(value: Object): Object,
stringMatching(value: string): string,
};

View File

@ -47,6 +47,10 @@ describe('Timeline profiler', () => {
store = global.store;
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('User Timing API', () => {
let clearedMarks;
let featureDetectionMarkName = null;
@ -517,7 +521,7 @@ describe('Timeline profiler', () => {
clearPendingMarks();
let errorMessage;
spyOn(console, 'error').and.callFake(message => {
jest.spyOn(console, 'error').mockImplementation(message => {
errorMessage = message;
});
@ -571,7 +575,7 @@ describe('Timeline profiler', () => {
clearPendingMarks();
let errorMessage;
spyOn(console, 'error').and.callFake(message => {
jest.spyOn(console, 'error').mockImplementation(message => {
errorMessage = message;
});
@ -740,7 +744,7 @@ describe('Timeline profiler', () => {
});
it('should mark sync render that throws', async () => {
spyOn(console, 'error');
jest.spyOn(console, 'error').mockImplementation(() => {});
class ErrorBoundary extends React.Component {
state = {error: null};
@ -802,7 +806,7 @@ describe('Timeline profiler', () => {
});
it('should mark concurrent render that throws', async () => {
spyOn(console, 'error');
jest.spyOn(console, 'error').mockImplementation(() => {});
class ErrorBoundary extends React.Component {
state = {error: null};
@ -1697,7 +1701,7 @@ describe('Timeline profiler', () => {
renderRootHelper(<Example />);
let errorMessage;
spyOn(console, 'error').and.callFake(message => {
jest.spyOn(console, 'error').mockImplementation(message => {
errorMessage = message;
});
@ -1766,7 +1770,7 @@ describe('Timeline profiler', () => {
renderRootHelper(<Example />);
let errorMessage;
spyOn(console, 'error').and.callFake(message => {
jest.spyOn(console, 'error').mockImplementation(message => {
errorMessage = message;
});
@ -1993,7 +1997,7 @@ describe('Timeline profiler', () => {
});
it('should mark sync render that throws', async () => {
spyOn(console, 'error');
jest.spyOn(console, 'error').mockImplementation(() => {});
class ErrorBoundary extends React.Component {
state = {error: null};
@ -2088,7 +2092,7 @@ describe('Timeline profiler', () => {
});
it('should mark concurrent render that throws', async () => {
spyOn(console, 'error');
jest.spyOn(console, 'error').mockImplementation(() => {});
class ErrorBoundary extends React.Component {
state = {error: null};

View File

@ -38,7 +38,7 @@ describe('Bridge', () => {
expect(wall.send).toHaveBeenCalledWith('shutdown');
// Verify that the Bridge doesn't send messages after shutdown.
spyOn(console, 'warn');
jest.spyOn(console, 'warn').mockImplementation(() => {});
wall.send.mockClear();
bridge.send('should not send');
jest.runAllTimers();

View File

@ -2121,7 +2121,7 @@ describe('InspectedElement', () => {
});
it('should gracefully surface backend errors on the frontend rather than timing out', async () => {
spyOn(console, 'error');
jest.spyOn(console, 'error').mockImplementation(() => {});
let shouldThrow = false;
@ -2738,7 +2738,7 @@ describe('InspectedElement', () => {
it('inspecting nested renderers should not throw', async () => {
// Ignoring react art warnings
spyOn(console, 'error');
jest.spyOn(console, 'error').mockImplementation(() => {});
const ReactArt = require('react-art');
const ArtSVGMode = require('art/modes/svg');
const ARTCurrentMode = require('art/modes/current');

View File

@ -760,7 +760,7 @@ describe('InspectedElementContext', () => {
const rendererID = ((store.getRendererIDForElement(id): any): number);
const logSpy = jest.fn();
spyOn(console, 'log').and.callFake(logSpy);
jest.spyOn(console, 'log').mockImplementation(logSpy);
// Should store the whole value (not just the hydrated parts)
backendAPI.storeAsGlobal({

View File

@ -1135,7 +1135,7 @@ describe('Timeline profiler', () => {
);
const invalidUserTimingData = createUserTimingData(invalidMarks);
const error = spyOn(console, 'error');
const error = jest.spyOn(console, 'error').mockImplementation(() => {});
preprocessData([
...createBoilerplateEntries(),
...invalidUserTimingData,
@ -1153,7 +1153,7 @@ describe('Timeline profiler', () => {
);
const invalidUserTimingData = createUserTimingData(invalidMarks);
const error = spyOn(console, 'error');
const error = jest.spyOn(console, 'error').mockImplementation(() => {});
preprocessData([
...createBoilerplateEntries(),
...invalidUserTimingData,
@ -1748,7 +1748,7 @@ describe('Timeline profiler', () => {
describe('errors thrown while rendering', () => {
// @reactVersion >= 18.0
it('shoult parse Errors thrown during render', async () => {
spyOn(console, 'error');
jest.spyOn(console, 'error');
class ErrorBoundary extends React.Component {
state = {error: null};

View File

@ -73,7 +73,7 @@ describe('ProfilerStore', () => {
const fauxProfilingData = {
dataForRoots: new Map(),
};
spyOn(console, 'warn');
jest.spyOn(console, 'warn').mockImplementation(() => {});
store.profilerStore.profilingData = fauxProfilingData;
expect(store.profilerStore.profilingData).not.toBe(fauxProfilingData);
expect(console.warn).toHaveBeenCalledTimes(1);

View File

@ -32,8 +32,7 @@ if (compactConsole) {
global.console = new CustomConsole(process.stdout, process.stderr, formatter);
}
const env = jasmine.getEnv();
env.beforeEach(() => {
beforeEach(() => {
global.mockClipboardCopy = jest.fn();
// Test environment doesn't support document methods like execCommand()
@ -169,7 +168,7 @@ env.beforeEach(() => {
}
global.fetch = mockFetch;
});
env.afterEach(() => {
afterEach(() => {
delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
// It's important to reset modules between test runs;

View File

@ -65,7 +65,7 @@ describe('InvalidEventListeners', () => {
if (!__DEV__) {
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.calls.argsFor(0)[0]).toEqual(
expect(console.error.mock.calls[0][0]).toEqual(
expect.objectContaining({
detail: expect.objectContaining({
message:

View File

@ -24,6 +24,10 @@ describe('ReactDOMComponent', () => {
ReactTestUtils = require('react-dom/test-utils');
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('updateDOM', () => {
it('should handle className', () => {
const container = document.createElement('div');
@ -1239,7 +1243,7 @@ describe('ReactDOMComponent', () => {
if (__DEV__) {
expect(console.log).toHaveBeenCalledTimes(1);
expect(console.log.calls.argsFor(0)[0]).toContain('onError called');
expect(console.log.mock.calls[0][0]).toContain('onError called');
}
});
@ -1464,7 +1468,7 @@ describe('ReactDOMComponent', () => {
it('should support custom elements which extend native elements', () => {
const container = document.createElement('div');
spyOnDevAndProd(document, 'createElement').and.callThrough();
spyOnDevAndProd(document, 'createElement');
ReactDOM.render(<div is="custom-div" />, container);
expect(document.createElement).toHaveBeenCalledWith('div', {
is: 'custom-div',
@ -1496,8 +1500,8 @@ describe('ReactDOMComponent', () => {
if (__DEV__) {
expect(console.log).toHaveBeenCalledTimes(2);
expect(console.log.calls.argsFor(0)[0]).toContain('onError called');
expect(console.log.calls.argsFor(1)[0]).toContain('onLoad called');
expect(console.log.mock.calls[0][0]).toContain('onError called');
expect(console.log.mock.calls[1][0]).toContain('onLoad called');
}
});

View File

@ -49,6 +49,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
afterEach(() => {
document.body.removeChild(container);
window.removeEventListener('error', windowOnError);
jest.restoreAllMocks();
});
describe('ReactDOMClient.createRoot', () => {
@ -95,7 +96,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported because we're in a browser click event:
expect.objectContaining({
@ -125,7 +126,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported because we're in a browser click event:
expect.objectContaining({
@ -140,14 +141,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
root.render(<NoError />);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([]);
expect(console.error.mock.calls).toEqual([]);
}
});
@ -181,7 +182,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported due to the guarded callback:
expect.objectContaining({
@ -212,7 +213,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -224,14 +225,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
root.render(<NoError />);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([]);
expect(console.error.mock.calls).toEqual([]);
}
});
@ -267,7 +268,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by jsdom due to the guarded callback:
expect.objectContaining({
@ -298,7 +299,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -310,14 +311,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
root.render(<NoError />);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([]);
expect(console.error.mock.calls).toEqual([]);
}
});
@ -347,7 +348,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported due to the guarded callback:
expect.objectContaining({
@ -368,7 +369,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -380,14 +381,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
root.render(<NoError />);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([]);
expect(console.error.mock.calls).toEqual([]);
}
});
@ -419,7 +420,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by jsdom due to the guarded callback:
expect.objectContaining({
@ -440,7 +441,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -452,14 +453,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
root.render(<NoError />);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([]);
expect(console.error.mock.calls).toEqual([]);
}
});
@ -489,7 +490,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported due to the guarded callback:
expect.objectContaining({
@ -510,7 +511,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -522,14 +523,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
root.render(<NoError />);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([]);
expect(console.error.mock.calls).toEqual([]);
}
});
@ -561,7 +562,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by jsdom due to the guarded callback:
expect.objectContaining({
@ -582,7 +583,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -594,14 +595,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
root.render(<NoError />);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([]);
expect(console.error.mock.calls).toEqual([]);
}
});
});
@ -649,7 +650,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
[
// Reported because we're in a browser click event:
@ -680,7 +681,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported because we're in a browser click event:
expect.objectContaining({
@ -695,14 +696,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
ReactDOM.render(<NoError />, container);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
]);
}
@ -730,7 +731,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
[
// Reported due to the guarded callback:
@ -752,7 +753,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -764,14 +765,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
ReactDOM.render(<NoError />, container);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
]);
}
@ -802,7 +803,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
[
// Reported by jsdom due to the guarded callback:
@ -824,7 +825,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -836,14 +837,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
ReactDOM.render(<NoError />, container);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
]);
}
@ -874,7 +875,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
[
// Reported due to the guarded callback:
@ -896,7 +897,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -908,14 +909,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
ReactDOM.render(<NoError />, container);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
]);
}
@ -949,7 +950,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
[
// Reported by jsdom due to the guarded callback:
@ -971,7 +972,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -983,14 +984,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
ReactDOM.render(<NoError />, container);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
]);
}
@ -1021,7 +1022,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
[
// Reported due to the guarded callback:
@ -1043,7 +1044,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -1055,14 +1056,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
ReactDOM.render(<NoError />, container);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
]);
}
@ -1096,7 +1097,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
}),
],
]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
[
// Reported by jsdom due to the guarded callback:
@ -1118,7 +1119,7 @@ describe('ReactDOMConsoleErrorReporting', () => {
// The top-level error was caught with try/catch, and there's no guarded callback,
// so in production we don't see an error event.
expect(windowOnError.mock.calls).toEqual([]);
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[
// Reported by React with no extra message:
expect.objectContaining({
@ -1130,14 +1131,14 @@ describe('ReactDOMConsoleErrorReporting', () => {
// Check next render doesn't throw.
windowOnError.mockReset();
console.error.calls.reset();
console.error.mockReset();
act(() => {
ReactDOM.render(<NoError />, container);
});
expect(container.textContent).toBe('OK');
expect(windowOnError.mock.calls).toEqual([]);
if (__DEV__) {
expect(console.error.calls.all().map(c => c.args)).toEqual([
expect(console.error.mock.calls).toEqual([
[expect.stringContaining('ReactDOM.render is no longer supported')],
]);
}

View File

@ -24,6 +24,7 @@ describe('ReactDOMFiber', () => {
afterEach(() => {
document.body.removeChild(container);
container = null;
jest.restoreAllMocks();
});
it('should render strings as children', () => {
@ -1154,11 +1155,11 @@ describe('ReactDOMFiber', () => {
expect(ops).toEqual(['A']);
if (__DEV__) {
expect(console.error.calls.count()).toBe(2);
expect(console.error.calls.argsFor(0)[0]).toMatch(
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error.mock.calls[0][0]).toMatch(
'ReactDOM.render is no longer supported in React 18',
);
expect(console.error.calls.argsFor(1)[0]).toMatch(
expect(console.error.mock.calls[1][0]).toMatch(
'ReactDOM.render is no longer supported in React 18',
);
}
@ -1257,7 +1258,7 @@ describe('ReactDOMFiber', () => {
let actualDocument;
let textNode;
spyOnDevAndProd(iframeContainer, 'appendChild').and.callFake(node => {
spyOnDevAndProd(iframeContainer, 'appendChild').mockImplementation(node => {
actualDocument = node.ownerDocument;
textNode = node;
});

View File

@ -63,6 +63,10 @@ describe('ReactDOMFizzShellHydration', () => {
});
});
afterEach(() => {
jest.restoreAllMocks();
});
async function serverAct(callback) {
await callback();
// Await one turn around the event loop.
@ -286,7 +290,7 @@ describe('ReactDOMFizzShellHydration', () => {
});
test('TODO: A large component stack causes SSR to stack overflow', async () => {
spyOnDevAndProd(console, 'error');
spyOnDevAndProd(console, 'error').mockImplementation(() => {});
function NestedComponent({depth}: {depth: number}) {
if (depth <= 0) {
@ -302,7 +306,7 @@ describe('ReactDOMFizzShellHydration', () => {
);
});
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.calls.argsFor(0)[0].toString()).toBe(
expect(console.error.mock.calls[0][0].toString()).toBe(
'RangeError: Maximum call stack size exceeded',
);
});

View File

@ -48,6 +48,7 @@ describe('ReactDOMInput', () => {
afterEach(() => {
document.body.removeChild(container);
jest.restoreAllMocks();
});
it('should warn for controlled value of 0 with missing onChange', () => {
@ -1670,7 +1671,9 @@ describe('ReactDOMInput', () => {
it('sets type, step, min, max before value always', () => {
const log = [];
const originalCreateElement = document.createElement;
spyOnDevAndProd(document, 'createElement').and.callFake(function (type) {
spyOnDevAndProd(document, 'createElement').mockImplementation(function (
type,
) {
const el = originalCreateElement.apply(this, arguments);
let value = '';
@ -1684,7 +1687,7 @@ describe('ReactDOMInput', () => {
log.push('set property value');
},
});
spyOnDevAndProd(el, 'setAttribute').and.callFake(function (name) {
spyOnDevAndProd(el, 'setAttribute').mockImplementation(function (name) {
log.push('set attribute ' + name);
});
}
@ -1743,7 +1746,9 @@ describe('ReactDOMInput', () => {
const log = [];
const originalCreateElement = document.createElement;
spyOnDevAndProd(document, 'createElement').and.callFake(function (type) {
spyOnDevAndProd(document, 'createElement').mockImplementation(function (
type,
) {
const el = originalCreateElement.apply(this, arguments);
const getDefaultValue = Object.getOwnPropertyDescriptor(
HTMLInputElement.prototype,
@ -1780,7 +1785,10 @@ describe('ReactDOMInput', () => {
setValue.call(this, val);
},
});
spyOnDevAndProd(el, 'setAttribute').and.callFake(function (name, val) {
spyOnDevAndProd(el, 'setAttribute').mockImplementation(function (
name,
val,
) {
log.push(`node.setAttribute(${strify(name)}, ${strify(val)})`);
});
}

View File

@ -42,6 +42,10 @@ describe('ReactDOMTextarea', () => {
};
});
afterEach(() => {
jest.restoreAllMocks();
});
it('should allow setting `defaultValue`', () => {
const container = document.createElement('div');
const node = renderTextarea(<textarea defaultValue="giraffe" />, container);
@ -133,7 +137,9 @@ describe('ReactDOMTextarea', () => {
let counter = 0;
const originalCreateElement = document.createElement;
spyOnDevAndProd(document, 'createElement').and.callFake(function (type) {
spyOnDevAndProd(document, 'createElement').mockImplementation(function (
type,
) {
const el = originalCreateElement.apply(this, arguments);
let value = '';
if (type === 'textarea') {

View File

@ -796,10 +796,10 @@ describe('ReactErrorBoundaries', () => {
);
if (__DEV__) {
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'ReactDOM.render is no longer supported',
);
expect(console.error.calls.argsFor(1)[0]).toContain(
expect(console.error.mock.calls[1][0]).toContain(
'The above error occurred in the <BrokenRender> component:',
);
}

View File

@ -584,6 +584,10 @@ describe('ReactLegacyErrorBoundaries', () => {
};
});
afterEach(() => {
jest.restoreAllMocks();
});
it('does not swallow exceptions on mounting without boundaries', () => {
let container = document.createElement('div');
expect(() => {
@ -677,10 +681,10 @@ describe('ReactLegacyErrorBoundaries', () => {
);
if (__DEV__) {
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'ReactDOM.render is no longer supported',
);
expect(console.error.calls.argsFor(1)[0]).toContain(
expect(console.error.mock.calls[1][0]).toContain(
'The above error occurred in the <BrokenRender> component:',
);
}

View File

@ -9,6 +9,10 @@ describe('ReactDOMRoot', () => {
ReactDOM = require('react-dom');
});
afterEach(() => {
jest.restoreAllMocks();
});
test('deprecation warning for ReactDOM.render', () => {
spyOnDev(console, 'error');
@ -16,7 +20,7 @@ describe('ReactDOMRoot', () => {
expect(container.textContent).toEqual('Hi');
if (__DEV__) {
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'ReactDOM.render is no longer supported',
);
}
@ -30,7 +34,7 @@ describe('ReactDOMRoot', () => {
expect(container.textContent).toEqual('Hi');
if (__DEV__) {
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'ReactDOM.hydrate is no longer supported',
);
}

View File

@ -333,7 +333,7 @@ describe('ReactTestUtils', () => {
e.persist();
},
};
spyOnDevAndProd(obj, 'handler').and.callThrough();
spyOnDevAndProd(obj, 'handler');
const container = document.createElement('div');
const node = ReactDOM.render(
<input type="text" onChange={obj.handler} />,
@ -369,7 +369,7 @@ describe('ReactTestUtils', () => {
e.persist();
},
};
spyOnDevAndProd(obj, 'handler').and.callThrough();
spyOnDevAndProd(obj, 'handler');
const container = document.createElement('div');
const instance = ReactDOM.render(
<SomeComponent handleChange={obj.handler} />,

View File

@ -28,6 +28,10 @@ function sleep(period) {
}
describe('ReactTestUtils.act()', () => {
afterEach(() => {
jest.restoreAllMocks();
});
// first we run all the tests with concurrent mode
if (__EXPERIMENTAL__) {
let concurrentRoot = null;
@ -488,13 +492,13 @@ function runActTests(label, render, unmount, rerender) {
// @gate __DEV__
it('warns if you do not await an act call', async () => {
spyOnDevAndProd(console, 'error');
spyOnDevAndProd(console, 'error').mockImplementation(() => {});
act(async () => {});
// it's annoying that we have to wait a tick before this warning comes in
await sleep(0);
if (__DEV__) {
expect(console.error.calls.count()).toEqual(1);
expect(console.error.calls.argsFor(0)[0]).toMatch(
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.mock.calls[0][0]).toMatch(
'You called act(async () => ...) without await.',
);
}
@ -502,7 +506,7 @@ function runActTests(label, render, unmount, rerender) {
// @gate __DEV__
it('warns if you try to interleave multiple act calls', async () => {
spyOnDevAndProd(console, 'error');
spyOnDevAndProd(console, 'error').mockImplementation(() => {});
await Promise.all([
act(async () => {
@ -516,10 +520,10 @@ function runActTests(label, render, unmount, rerender) {
await sleep(150);
if (__DEV__) {
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error.calls.argsFor(0)[0]).toMatch(
expect(console.error.mock.calls[0][0]).toMatch(
'You seem to have overlapping act() calls',
);
expect(console.error.calls.argsFor(1)[0]).toMatch(
expect(console.error.mock.calls[1][0]).toMatch(
'You seem to have overlapping act() calls',
);
}

View File

@ -1706,7 +1706,7 @@ describe('ReactUpdates', () => {
it('prevents infinite update loop triggered by synchronous updates in useEffect', () => {
// Ignore flushSync warning
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
function NonTerminating() {
const [step, setStep] = React.useState(0);

View File

@ -67,19 +67,23 @@ module.exports = function (initModules) {
// performs fn asynchronously and expects count errors logged to console.error.
// will fail the test if the count of errors logged is not equal to count.
async function expectErrors(fn, count) {
if (console.error.calls && console.error.calls.reset) {
console.error.calls.reset();
if (console.error.mockClear) {
console.error.mockClear();
} else {
// TODO: Rewrite tests that use this helper to enumerate expected errors.
// This will enable the helper to use the .toErrorDev() matcher instead of spying.
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
}
const result = await fn();
if (console.error.calls && console.error.calls.count() !== 0) {
if (
console.error.mock &&
console.error.mock.calls &&
console.error.mock.calls.length !== 0
) {
const filteredWarnings = [];
for (let i = 0; i < console.error.calls.count(); i++) {
const args = console.error.calls.argsFor(i);
for (let i = 0; i < console.error.mock.calls.length; i++) {
const args = console.error.mock.calls[i];
const [format, ...rest] = args;
if (!shouldIgnoreConsoleError(format, rest)) {
filteredWarnings.push(args);

View File

@ -33,14 +33,14 @@ describe('DebugTracing', () => {
const groups = [];
spyOnDevAndProd(console, 'log').and.callFake(message => {
spyOnDevAndProd(console, 'log').mockImplementation(message => {
logs.push(`log: ${message.replace(/%c/g, '')}`);
});
spyOnDevAndProd(console, 'group').and.callFake(message => {
spyOnDevAndProd(console, 'group').mockImplementation(message => {
logs.push(`group: ${message.replace(/%c/g, '')}`);
groups.push(message);
});
spyOnDevAndProd(console, 'groupEnd').and.callFake(() => {
spyOnDevAndProd(console, 'groupEnd').mockImplementation(() => {
const message = groups.pop();
logs.push(`groupEnd: ${message.replace(/%c/g, '')}`);
});

View File

@ -1724,7 +1724,7 @@ describe('ReactHooks', () => {
// Regression test for #14674
it('does not swallow original error when updating another component in render phase', async () => {
const {useState} = React;
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
let _setState;
function A() {
@ -1754,7 +1754,7 @@ describe('ReactHooks', () => {
if (__DEV__) {
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'Warning: Cannot update a component (`%s`) while rendering ' +
'a different component (`%s`).',
);

View File

@ -29,6 +29,10 @@ describe('ReactIncrementalErrorHandling', () => {
act = require('jest-react').act;
});
afterEach(() => {
jest.restoreAllMocks();
});
function normalizeCodeLocInfo(str) {
return (
str &&
@ -1520,8 +1524,8 @@ describe('ReactIncrementalErrorHandling', () => {
});
it('error boundaries capture non-errors', () => {
spyOnProd(console, 'error');
spyOnDev(console, 'error');
spyOnProd(console, 'error').mockImplementation(() => {});
spyOnDev(console, 'error').mockImplementation(() => {});
class ErrorBoundary extends React.Component {
state = {error: null};
@ -1583,12 +1587,12 @@ describe('ReactIncrementalErrorHandling', () => {
if (__DEV__) {
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'The above error occurred in the <BadRender> component:',
);
} else {
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.calls.argsFor(0)[0]).toBe(notAnError);
expect(console.error.mock.calls[0][0]).toBe(notAnError);
}
});
@ -1950,7 +1954,7 @@ describe('ReactIncrementalErrorHandling', () => {
// point to prevent an infinite loop in the case where there is (by
// accident) a render phase triggered from userspace.
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
let numberOfThrows = 0;
@ -1990,10 +1994,10 @@ describe('ReactIncrementalErrorHandling', () => {
if (__DEV__) {
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'Cannot update a component (`%s`) while rendering a different component',
);
expect(console.error.calls.argsFor(1)[0]).toContain(
expect(console.error.mock.calls[1][0]).toContain(
'The above error occurred in the <App> component',
);
}

View File

@ -34,6 +34,10 @@ describe('isomorphic act()', () => {
global.IS_REACT_ACT_ENVIRONMENT = true;
});
afterEach(() => {
jest.restoreAllMocks();
});
// @gate __DEV__
test('bypasses queueMicrotask', async () => {
const root = ReactNoop.createRoot();
@ -208,7 +212,7 @@ describe('isomorphic act()', () => {
return use(promise);
}
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
const root = ReactNoop.createRoot();
act(() => {
startTransition(() => {
@ -229,8 +233,8 @@ describe('isomorphic act()', () => {
await null;
await null;
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.mock.calls[0][0]).toContain(
'Warning: A component suspended inside an `act` scope, but the `act` ' +
'call was not awaited. When testing React components that ' +
'depend on asynchronous data, you must await the result:\n\n' +
@ -260,7 +264,7 @@ describe('isomorphic act()', () => {
return 'Async';
}
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
const root = ReactNoop.createRoot();
act(() => {
startTransition(() => {
@ -282,7 +286,7 @@ describe('isomorphic act()', () => {
await null;
await null;
expect(console.error.calls.count()).toBe(0);
expect(console.error).toHaveBeenCalledTimes(0);
// Finish loading the data
await act(async () => {

View File

@ -161,7 +161,7 @@ describe('ReactLazy', () => {
});
it('does not support arbitrary promises, only module objects', async () => {
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
const LazyText = lazy(async () => Text);
@ -181,7 +181,7 @@ describe('ReactLazy', () => {
expect(Scheduler).toFlushAndThrow('Element type is invalid');
if (__DEV__) {
expect(console.error).toHaveBeenCalledTimes(3);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'Expected the result of a dynamic import() call',
);
}

View File

@ -26,6 +26,10 @@ describe('ReactNewContext', () => {
gen = require('random-seed');
});
afterEach(() => {
jest.restoreAllMocks();
});
function Text(props) {
Scheduler.unstable_yieldValue(props.text);
return <span prop={props.text} />;
@ -860,7 +864,7 @@ describe('ReactNewContext', () => {
});
it('warns if multiple renderers concurrently render the same context', () => {
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
const Context = React.createContext(0);
function Foo(props) {
@ -898,7 +902,7 @@ describe('ReactNewContext', () => {
expect(Scheduler).toFlushAndYield(['Foo', 'Foo']);
if (__DEV__) {
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'Detected multiple renderers concurrently rendering the same ' +
'context provider. This is currently unsupported',
);
@ -1047,12 +1051,12 @@ describe('ReactNewContext', () => {
describe('Context.Consumer', () => {
it('warns if child is not a function', () => {
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
const Context = React.createContext(0);
ReactNoop.render(<Context.Consumer />);
expect(Scheduler).toFlushAndThrow('is not a function');
if (__DEV__) {
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'A context consumer was rendered with multiple children, or a child ' +
"that isn't a function",
);

View File

@ -505,7 +505,7 @@ describe('ReactThenable', () => {
}
}
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
function App() {
return (
<Suspense fallback={<Text text="Loading..." />}>
@ -522,8 +522,8 @@ describe('ReactThenable', () => {
});
if (__DEV__) {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.mock.calls[0][0]).toContain(
'Warning: `use` was called from inside a try/catch block. This is not ' +
'allowed and can lead to unexpected behavior. To handle errors ' +
'triggered by `use`, wrap your component in a error boundary.',

View File

@ -1904,7 +1904,7 @@ describe('useMutableSource', () => {
// Get a new copy of ReactNoop.
loadModules();
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
// Use the mutablesource again but with a different renderer.
ReactNoop.render(
@ -1917,7 +1917,7 @@ describe('useMutableSource', () => {
);
expect(Scheduler).toFlushAndYieldThrough(['c:one']);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'Detected multiple renderers concurrently rendering the ' +
'same mutable source. This is currently unsupported.',
);
@ -1985,7 +1985,7 @@ describe('useMutableSource', () => {
// Get a new copy of ReactNoop.
loadModules();
spyOnDev(console, 'error');
spyOnDev(console, 'error').mockImplementation(() => {});
// Mutate before the new render reads from the source.
source.value = 'two';
@ -2001,7 +2001,7 @@ describe('useMutableSource', () => {
);
expect(Scheduler).toFlushAndYieldThrough(['c:two']);
expect(console.error.calls.argsFor(0)[0]).toContain(
expect(console.error.mock.calls[0][0]).toContain(
'Detected multiple renderers concurrently rendering the ' +
'same mutable source. This is currently unsupported.',
);

View File

@ -29,21 +29,28 @@ function runJest(testFile) {
const cwd = process.cwd();
const extension = process.platform === 'win32' ? '.cmd' : '';
const command = process.env.npm_lifecycle_event;
const defaultReporter = '--reporters=default';
const equivalenceReporter =
'--reporters=<rootDir>/scripts/jest/spec-equivalence-reporter/equivalenceReporter.js';
if (!command.startsWith('test')) {
throw new Error(
'Expected this test to run as a result of one of test commands.',
);
}
const result = spawnSync('yarn' + extension, [command, testFile], {
cwd,
env: Object.assign({}, process.env, {
REACT_CLASS_EQUIVALENCE_TEST: 'true',
// Remove these so that the test file is not filtered out by the mechanism
// we use to parallelize tests in CI
CIRCLE_NODE_TOTAL: '',
CIRCLE_NODE_INDEX: '',
}),
});
const result = spawnSync(
'yarn' + extension,
[command, testFile, defaultReporter, equivalenceReporter],
{
cwd,
env: Object.assign({}, process.env, {
REACT_CLASS_EQUIVALENCE_TEST: 'true',
// Remove these so that the test file is not filtered out by the mechanism
// we use to parallelize tests in CI
CIRCLE_NODE_TOTAL: '',
CIRCLE_NODE_INDEX: '',
}),
},
);
if (result.error) {
throw result.error;

View File

@ -982,6 +982,10 @@ describe('context legacy', () => {
PropTypes = require('prop-types');
});
afterEach(() => {
jest.restoreAllMocks();
});
it('should warn if the legacy context API have been used in strict mode', () => {
class LegacyContextProvider extends React.Component {
getChildContext() {

View File

@ -481,14 +481,14 @@ Task 1 [Normal] │ █████████
it('automatically stops profiling and warns if event log gets too big', async () => {
Scheduler.unstable_Profiling.startLoggingProfilingEvents();
spyOnDevAndProd(console, 'error');
spyOnDevAndProd(console, 'error').mockImplementation(() => {});
// Increase infinite loop guard limit
const originalMaxIterations = global.__MAX_ITERATIONS__;
global.__MAX_ITERATIONS__ = 120000;
let taskId = 1;
while (console.error.calls.count() === 0) {
while (console.error.mock.calls.length === 0) {
taskId++;
const task = scheduleCallback(NormalPriority, () => {});
cancelCallback(task);
@ -496,7 +496,7 @@ Task 1 [Normal] │ █████████
}
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
expect(console.error.mock.calls[0][0]).toBe(
"Scheduler Profiling: Event log exceeded maximum size. Don't forget " +
'to call `stopLoggingProfilingEvents()`.',
);

View File

@ -97,12 +97,14 @@ describe('Component stack trace displaying', () => {
});
if (__DEV__) {
let i = 0;
expect(console.error.calls.count()).toBe(Object.keys(fileNames).length);
expect(console.error).toHaveBeenCalledTimes(
Object.keys(fileNames).length,
);
for (const fileName in fileNames) {
if (!fileNames.hasOwnProperty(fileName)) {
continue;
}
const args = console.error.calls.argsFor(i);
const args = console.error.mock.calls[i];
const stack = args[args.length - 1];
const expected = fileNames[fileName];
expect(stack).toContain(`at ${expected}:`);

View File

@ -30,5 +30,5 @@ module.exports = {
testEnvironment: 'jsdom',
testRunner: 'jasmine2',
testRunner: 'jest-circus/runner',
};

View File

@ -10,16 +10,11 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
// require that instead.
require('./spec-equivalence-reporter/setupTests.js');
} else {
const env = jasmine.getEnv();
const errorMap = require('../error-codes/codes.json');
// TODO: Stop using spyOn in all the test since that seem deprecated.
// This is a legacy upgrade path strategy from:
// https://github.com/facebook/jest/blob/v20.0.4/packages/jest-matchers/src/spyMatchers.js#L160
const isSpy = spy => spy.calls && typeof spy.calls.count === 'function';
const spyOn = global.spyOn;
const noop = function () {};
// By default, jest.spyOn also calls the spied method.
const spyOn = jest.spyOn;
const noop = jest.fn;
// Spying on console methods in production builds can mask errors.
// This is why we added an explicit spyOnDev() helper.
@ -55,10 +50,10 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
// global variable. The global lets us detect an infinite loop even if
// the actual error object ends up being caught and ignored. An infinite
// loop must always fail the test!
env.beforeEach(() => {
beforeEach(() => {
global.infiniteLoopError = null;
});
env.afterEach(() => {
afterEach(() => {
const error = global.infiniteLoopError;
global.infiniteLoopError = null;
if (error) {
@ -97,7 +92,10 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
expectedMatcher,
unexpectedConsoleCallStacks
) => {
if (console[methodName] !== mockMethod && !isSpy(console[methodName])) {
if (
console[methodName] !== mockMethod &&
!jest.isMockFunction(console[methodName])
) {
throw new Error(
`Test did not tear down console.${methodName} mock properly.`
);
@ -157,8 +155,8 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
unexpectedWarnCallStacks.length = 0;
};
env.beforeEach(resetAllUnexpectedConsoleCalls);
env.afterEach(flushAllUnexpectedConsoleCalls);
beforeEach(resetAllUnexpectedConsoleCalls);
afterEach(flushAllUnexpectedConsoleCalls);
if (process.env.NODE_ENV === 'production') {
// In production, we strip error messages and turn them into codes.
@ -309,6 +307,4 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
const flags = getTestFlags();
return fn(flags);
};
require('jasmine-check').install();
}

View File

@ -0,0 +1,20 @@
/*!
* 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.
*/
'use strict';
class EquivalenceReporter {
onTestCaseResult(test, testCaseResult) {
console.log(
`EQUIVALENCE: ${testCaseResult.title}, ` +
`status: ${testCaseResult.status}, ` +
`numExpectations: ${testCaseResult.numPassingAsserts}`
);
}
}
module.exports = EquivalenceReporter;

View File

@ -7,16 +7,7 @@
'use strict';
const expect = global.expect;
let numExpectations = 0;
global.expect = function () {
numExpectations += 1;
return expect.apply(this, arguments);
};
const spyOn = global.spyOn;
const spyOn = jest.spyOn;
// Spying on console methods in production builds can mask errors.
// This is why we added an explicit spyOnDev() helper.
@ -50,15 +41,3 @@ expect.extend({
...require('../matchers/toThrow'),
...require('../matchers/toWarnDev'),
});
beforeEach(() => (numExpectations = 0));
jasmine.currentEnv_.addReporter({
specDone: spec => {
console.log(
`EQUIVALENCE: ${spec.description}, ` +
`status: ${spec.status}, ` +
`numExpectations: ${numExpectations}`
);
},
});

View File

@ -1,4 +1,3 @@
declare var jasmine: any;
declare var __DEV__: boolean;
declare var __TEST__: boolean;
declare var __EXTENSION__: boolean;
@ -71,9 +70,5 @@ interface MockFunction {
mockReturnValueOnce(value: any): MockFunction
}
// Allow importing jasmine-check
declare module 'jasmine-check' {
export function install(global?: any): void;
}
declare var check: any;
declare var gen: any;

View File

@ -10277,13 +10277,6 @@ isurl@^1.0.0-alpha5:
has-to-string-tag-x "^1.2.0"
is-object "^1.0.1"
jasmine-check@^1.0.0-rc.0:
version "1.0.0-rc.0"
resolved "https://registry.yarnpkg.com/jasmine-check/-/jasmine-check-1.0.0-rc.0.tgz#117728c150078ecf211986c5f164275b71e937a4"
integrity sha512-V11aKvbAAEN34vVMRQVqylq3j8kw1Hmkf8JOVLYPcVpQX1jZ5pQPTYwbSnjMEjuRp5XQnI0qOqd2yosJoH7Vzw==
dependencies:
testcheck "^1.0.0-rc"
jed@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
@ -10469,29 +10462,6 @@ jest-haste-map@^29.4.1:
optionalDependencies:
fsevents "^2.3.2"
jest-jasmine2@^29.4.1:
version "29.4.1"
resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-29.4.1.tgz#67fbf2a729889ea390a8aa70ba3582e9d6c32603"
integrity sha512-fuwfsso6Kc7eGjNCWfWQgW4lcJwdkbfnVx6KQSw2a6a2VBOcxUSn/q8lAwblvJc6hYB7XhGfSVLDw2mvjYDZ0A==
dependencies:
"@jest/environment" "^29.4.1"
"@jest/expect" "^29.4.1"
"@jest/source-map" "^29.2.0"
"@jest/test-result" "^29.4.1"
"@jest/types" "^29.4.1"
"@types/node" "*"
chalk "^4.0.0"
co "^4.6.0"
is-generator-fn "^2.0.0"
jest-each "^29.4.1"
jest-matcher-utils "^29.4.1"
jest-message-util "^29.4.1"
jest-runtime "^29.4.1"
jest-snapshot "^29.4.1"
jest-util "^29.4.1"
p-limit "^3.1.0"
pretty-format "^29.4.1"
jest-leak-detector@^29.4.1:
version "29.4.1"
resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.4.1.tgz#632186c546e084da2b490b7496fee1a1c9929637"
@ -16039,11 +16009,6 @@ test-exclude@^6.0.0:
glob "^7.1.4"
minimatch "^3.0.4"
testcheck@^1.0.0-rc:
version "1.0.0-rc.2"
resolved "https://registry.yarnpkg.com/testcheck/-/testcheck-1.0.0-rc.2.tgz#11356a25b84575efe0b0857451e85b5fa74ee4e4"
integrity sha512-lY0PM4ypOuf3WenJkx/C8+LeLPucHnnRAOtHRQkm8K6pG170tYw0xmxyVjrejJ2bpHWHn5EUkoC+qhnhFAUcvg==
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"