Skip to content

Commit

Permalink
Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lunaruan committed Aug 6, 2021
1 parent c1f236d commit 78904f7
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 22 deletions.
91 changes: 89 additions & 2 deletions packages/react-devtools-shared/src/__tests__/console-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

describe('console', () => {
let React;
let ReactDOM;
let act;
let fakeConsole;
let legacyRender;
Expand Down Expand Up @@ -48,6 +49,7 @@ describe('console', () => {
appendComponentStack: true,
breakOnWarn: false,
showInlineWarningsAndErrors: false,
hideDoubleLogsInStrictLegacy: false,
});

const inject = global.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject;
Expand All @@ -58,6 +60,7 @@ describe('console', () => {
};

React = require('react');
ReactDOM = require('react-dom');

const utils = require('./utils');
act = utils.act;
Expand All @@ -73,10 +76,10 @@ describe('console', () => {
);
}

it('should not patch console methods that do not receive component stacks', () => {
it('should not patch console methods that are not explicitly overriden', () => {
expect(fakeConsole.error).not.toBe(mockError);
expect(fakeConsole.info).toBe(mockInfo);
expect(fakeConsole.log).toBe(mockLog);
expect(fakeConsole.log).not.toBe(mockLog);
expect(fakeConsole.warn).not.toBe(mockWarn);
});

Expand Down Expand Up @@ -465,4 +468,88 @@ describe('console', () => {
expect(mockWarn).toHaveBeenCalledTimes(1);
expect(mockWarn.mock.calls[0][0]).toBe('Symbol:');
});

it('should double log if hideDoubleLogsInStrictMode is disabled in Strict mode', () => {
const container = document.createElement('div');
const root = ReactDOM.createRoot(container);

function App() {
fakeConsole.log('log');
fakeConsole.warn('warn');
fakeConsole.error('error');
return <div />;
}

patchConsole({
appendComponentStack: false,
breakOnWarn: false,
showInlineWarningsAndErrors: false,
hideDoubleLogsInStrictMode: false,
});

act(() =>
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
),
);

expect(mockLog).toHaveBeenCalledTimes(2);
expect(mockLog.mock.calls[0]).toHaveLength(1);
expect(mockLog.mock.calls[0][0]).toBe('log');
expect(mockLog.mock.calls[1]).toHaveLength(2);
expect(mockLog.mock.calls[1][0]).toBe('%clog');

expect(mockWarn).toHaveBeenCalledTimes(2);
expect(mockWarn.mock.calls[0]).toHaveLength(1);
expect(mockWarn.mock.calls[0][0]).toBe('warn');
expect(mockWarn.mock.calls[1]).toHaveLength(2);
expect(mockWarn.mock.calls[1][0]).toBe('%cwarn');

expect(mockError).toHaveBeenCalledTimes(2);
expect(mockError.mock.calls[0]).toHaveLength(1);
expect(mockError.mock.calls[0][0]).toBe('error');
expect(mockError.mock.calls[1]).toHaveLength(2);
expect(mockError.mock.calls[1][0]).toBe('%cerror');
});

fit('should not double log if hideDoubleLogsInStrictMode is enabled iin Strict mode', () => {
const container = document.createElement('div');
const root = ReactDOM.createRoot(container);

function App() {
fakeConsole.log('log');
fakeConsole.warn('warn');
fakeConsole.error('error');
return <div />;
}

patchConsole({
appendComponentStack: false,
breakOnWarn: false,
showInlineWarningsAndErrors: false,
hideDoubleLogsInStrictMode: true,
});

act(() =>
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
),
);

expect(mockLog).toHaveBeenCalledTimes(1);
expect(mockLog.mock.calls[0]).toHaveLength(1);
expect(mockLog.mock.calls[0][0]).toBe('log');

expect(mockWarn).toHaveBeenCalledTimes(1);
expect(mockWarn.mock.calls[0]).toHaveLength(1);
expect(mockWarn.mock.calls[0][0]).toBe('warn');

expect(mockError).toHaveBeenCalledTimes(1);
expect(mockError.mock.calls[0]).toHaveLength(1);
expect(mockError.mock.calls[0][0]).toBe('error');
});
});
8 changes: 8 additions & 0 deletions packages/react-reconciler/src/ReactFiberReconciler.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ export {
observeVisibleRects,
} from './ReactTestSelectors';

import * as Scheduler from './Scheduler';
import {setSuppressWarning} from 'shared/consoleWithStackDev';

type OpaqueRoot = FiberRoot;

// 0 is PROD, 1 is DEV.
Expand Down Expand Up @@ -714,6 +717,11 @@ export function getIsStrictModeForDevtools() {
}

export function setIsStrictModeForDevtools(newIsStrictMode: boolean) {
// We're in a test. Disable yielding during the double render
if (typeof Scheduler.unstable_yieldValue === 'function') {
Scheduler._setDisableYieldValue(newIsStrictMode);
setSuppressWarning(newIsStrictMode);
}
isStrictMode = newIsStrictMode;
}

Expand Down
8 changes: 8 additions & 0 deletions packages/react-reconciler/src/ReactFiberReconciler.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ export {
observeVisibleRects,
} from './ReactTestSelectors';

import * as Scheduler from './Scheduler';
import {setSuppressWarning} from 'shared/consoleWithStackDev';

type OpaqueRoot = FiberRoot;

// 0 is PROD, 1 is DEV.
Expand Down Expand Up @@ -714,6 +717,11 @@ export function getIsStrictModeForDevtools() {
}

export function setIsStrictModeForDevtools(newIsStrictMode: boolean) {
// We're in a test. Disable yielding during the double render
if (typeof Scheduler.unstable_yieldValue === 'function') {
Scheduler._setDisableYieldValue(newIsStrictMode);
setSuppressWarning(newIsStrictMode);
}
isStrictMode = newIsStrictMode;
}

Expand Down
3 changes: 3 additions & 0 deletions packages/react-reconciler/src/Scheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ export const NormalPriority = Scheduler.unstable_NormalPriority;
export const LowPriority = Scheduler.unstable_LowPriority;
export const IdlePriority = Scheduler.unstable_IdlePriority;
export type SchedulerCallback = (isSync: boolean) => SchedulerCallback | null;

export const unstable_yieldValue = Scheduler.unstable_yieldValue;
export const _setDisableYieldValue = Scheduler._setDisableYieldValue;
26 changes: 13 additions & 13 deletions packages/react/src/__tests__/ReactStrictMode-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -893,8 +893,8 @@ describe('context legacy', () => {
ReactDOM.render(<Root />, container);
});

describe('disableLogs', () => {
it('disables logs once for class double render', () => {
describe('no disable logs', () => {
it('does not disable logs for class double render', () => {
spyOnDevAndProd(console, 'log');

let count = 0;
Expand All @@ -915,14 +915,14 @@ describe('context legacy', () => {
);

expect(count).toBe(__DEV__ ? 2 : 1);
expect(console.log).toBeCalledTimes(1);
expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);
// Note: we should display the first log because otherwise
// there is a risk of suppressing warnings when they happen,
// and on the next render they'd get deduplicated and ignored.
expect(console.log).toBeCalledWith('foo 1');
});

it('disables logs once for class double ctor', () => {
it('does not disable logs for class double ctor', () => {
spyOnDevAndProd(console, 'log');

let count = 0;
Expand All @@ -946,14 +946,14 @@ describe('context legacy', () => {
);

expect(count).toBe(__DEV__ ? 2 : 1);
expect(console.log).toBeCalledTimes(1);
expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);
// Note: we should display the first log because otherwise
// there is a risk of suppressing warnings when they happen,
// and on the next render they'd get deduplicated and ignored.
expect(console.log).toBeCalledWith('foo 1');
});

it('disables logs once for class double getDerivedStateFromProps', () => {
it('does not disable logs for class double getDerivedStateFromProps', () => {
spyOnDevAndProd(console, 'log');

let count = 0;
Expand All @@ -978,14 +978,14 @@ describe('context legacy', () => {
);

expect(count).toBe(__DEV__ ? 2 : 1);
expect(console.log).toBeCalledTimes(1);
expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);
// Note: we should display the first log because otherwise
// there is a risk of suppressing warnings when they happen,
// and on the next render they'd get deduplicated and ignored.
expect(console.log).toBeCalledWith('foo 1');
});

it('disables logs once for class double shouldComponentUpdate', () => {
it('does not disable logs for class double shouldComponentUpdate', () => {
spyOnDevAndProd(console, 'log');

let count = 0;
Expand Down Expand Up @@ -1017,14 +1017,14 @@ describe('context legacy', () => {
);

expect(count).toBe(__DEV__ ? 2 : 1);
expect(console.log).toBeCalledTimes(1);
expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);
// Note: we should display the first log because otherwise
// there is a risk of suppressing warnings when they happen,
// and on the next render they'd get deduplicated and ignored.
expect(console.log).toBeCalledWith('foo 1');
});

it('disables logs once for class state updaters', () => {
it('does not disable logs for class state updaters', () => {
spyOnDevAndProd(console, 'log');

let inst;
Expand All @@ -1051,14 +1051,14 @@ describe('context legacy', () => {
});

expect(count).toBe(__DEV__ ? 2 : 1);
expect(console.log).toBeCalledTimes(1);
expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);
// Note: we should display the first log because otherwise
// there is a risk of suppressing warnings when they happen,
// and on the next render they'd get deduplicated and ignored.
expect(console.log).toBeCalledWith('foo 1');
});

it('disables logs once for function double render', () => {
it('does not disable logs for function double render', () => {
spyOnDevAndProd(console, 'log');

let count = 0;
Expand All @@ -1077,7 +1077,7 @@ describe('context legacy', () => {
);

expect(count).toBe(__DEV__ ? 2 : 1);
expect(console.log).toBeCalledTimes(1);
expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);
// Note: we should display the first log because otherwise
// there is a risk of suppressing warnings when they happen,
// and on the next render they'd get deduplicated and ignored.
Expand Down
11 changes: 9 additions & 2 deletions packages/scheduler/src/forks/SchedulerMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ let isFlushing: boolean = false;
let needsPaint: boolean = false;
let shouldYieldForPaint: boolean = false;

var _disableYieldValue = false;

function setDisableYieldValue(newValue) {
_disableYieldValue = newValue;
}

function advanceTimers(currentTime) {
// Check for tasks that are no longer delayed and add them to the queue.
let timer = peek(timerQueue);
Expand Down Expand Up @@ -570,7 +576,7 @@ function unstable_flushAll(): void {

function unstable_yieldValue(value: mixed): void {
// eslint-disable-next-line react-internal/no-production-logging
if (console.log.name === 'disabledLog') {
if (console.log.name === 'disabledLog' || _disableYieldValue) {
// If console.log has been patched, we assume we're in render
// replaying and we ignore any values yielding in the second pass.
return;
Expand All @@ -584,7 +590,7 @@ function unstable_yieldValue(value: mixed): void {

function unstable_advanceTime(ms: number) {
// eslint-disable-next-line react-internal/no-production-logging
if (console.log.name === 'disabledLog') {
if (console.log.name === 'disabledLog' || _disableYieldValue) {
// If console.log has been patched, we assume we're in render
// replaying and we ignore any time advancing in the second pass.
return;
Expand Down Expand Up @@ -629,6 +635,7 @@ export {
unstable_yieldValue,
unstable_advanceTime,
reset,
setDisableYieldValue as _setDisableYieldValue,
};

export const unstable_Profiling = enableProfiling
Expand Down
15 changes: 13 additions & 2 deletions packages/shared/consoleWithStackDev.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@

import ReactSharedInternals from 'shared/ReactSharedInternals';

let suppressWarning = false;
export function setSuppressWarning(newSuppressWarning) {
if (__DEV__) {
suppressWarning = newSuppressWarning;
}
}

// In DEV, calls to console.warn and console.error get replaced
// by calls to these methods by a Babel plugin.
//
Expand All @@ -15,13 +22,17 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';

export function warn(format, ...args) {
if (__DEV__) {
printWarning('warn', format, args);
if (!suppressWarning) {
printWarning('warn', format, args);
}
}
}

export function error(format, ...args) {
if (__DEV__) {
printWarning('error', format, args);
if (!suppressWarning) {
printWarning('error', format, args);
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion packages/shared/forks/Scheduler.umd.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ const {
unstable_forceFrameRate,

// this doesn't actually exist on the scheduler, but it *does*
// on scheduler/unstable_mock, which we'll need inside act().
// on scheduler/unstable_mock, which we'll need inside act()
// and for internal testing
unstable_flushAllWithoutAsserting,
unstable_yieldValue,
_setDisableYieldValue,
} = ReactInternals.Scheduler;

export {
Expand All @@ -54,4 +57,6 @@ export {
unstable_IdlePriority,
unstable_forceFrameRate,
unstable_flushAllWithoutAsserting,
unstable_yieldValue,
_setDisableYieldValue,
};
Loading

0 comments on commit 78904f7

Please sign in to comment.