Skip to content

Commit cc8be41

Browse files
committed
Tests
1 parent c1f236d commit cc8be41

File tree

9 files changed

+162
-22
lines changed

9 files changed

+162
-22
lines changed

packages/react-devtools-shared/src/__tests__/console-test.js

+89-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
describe('console', () => {
1111
let React;
12+
let ReactDOM;
1213
let act;
1314
let fakeConsole;
1415
let legacyRender;
@@ -48,6 +49,7 @@ describe('console', () => {
4849
appendComponentStack: true,
4950
breakOnWarn: false,
5051
showInlineWarningsAndErrors: false,
52+
hideDoubleLogsInStrictLegacy: false,
5153
});
5254

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

6062
React = require('react');
63+
ReactDOM = require('react-dom');
6164

6265
const utils = require('./utils');
6366
act = utils.act;
@@ -73,10 +76,10 @@ describe('console', () => {
7376
);
7477
}
7578

76-
it('should not patch console methods that do not receive component stacks', () => {
79+
it('should not patch console methods that are not explicitly overriden', () => {
7780
expect(fakeConsole.error).not.toBe(mockError);
7881
expect(fakeConsole.info).toBe(mockInfo);
79-
expect(fakeConsole.log).toBe(mockLog);
82+
expect(fakeConsole.log).not.toBe(mockLog);
8083
expect(fakeConsole.warn).not.toBe(mockWarn);
8184
});
8285

@@ -465,4 +468,88 @@ describe('console', () => {
465468
expect(mockWarn).toHaveBeenCalledTimes(1);
466469
expect(mockWarn.mock.calls[0][0]).toBe('Symbol:');
467470
});
471+
472+
it('should double log if hideDoubleLogsInStrictMode is disabled in Strict mode', () => {
473+
const container = document.createElement('div');
474+
const root = ReactDOM.createRoot(container);
475+
476+
function App() {
477+
fakeConsole.log('log');
478+
fakeConsole.warn('warn');
479+
fakeConsole.error('error');
480+
return <div />;
481+
}
482+
483+
patchConsole({
484+
appendComponentStack: false,
485+
breakOnWarn: false,
486+
showInlineWarningsAndErrors: false,
487+
hideDoubleLogsInStrictMode: false,
488+
});
489+
490+
act(() =>
491+
root.render(
492+
<React.StrictMode>
493+
<App />
494+
</React.StrictMode>,
495+
),
496+
);
497+
498+
expect(mockLog).toHaveBeenCalledTimes(2);
499+
expect(mockLog.mock.calls[0]).toHaveLength(1);
500+
expect(mockLog.mock.calls[0][0]).toBe('log');
501+
expect(mockLog.mock.calls[1]).toHaveLength(2);
502+
expect(mockLog.mock.calls[1][0]).toBe('%clog');
503+
504+
expect(mockWarn).toHaveBeenCalledTimes(2);
505+
expect(mockWarn.mock.calls[0]).toHaveLength(1);
506+
expect(mockWarn.mock.calls[0][0]).toBe('warn');
507+
expect(mockWarn.mock.calls[1]).toHaveLength(2);
508+
expect(mockWarn.mock.calls[1][0]).toBe('%cwarn');
509+
510+
expect(mockError).toHaveBeenCalledTimes(2);
511+
expect(mockError.mock.calls[0]).toHaveLength(1);
512+
expect(mockError.mock.calls[0][0]).toBe('error');
513+
expect(mockError.mock.calls[1]).toHaveLength(2);
514+
expect(mockError.mock.calls[1][0]).toBe('%cerror');
515+
});
516+
517+
it('should not double log if hideDoubleLogsInStrictMode is enabled iin Strict mode', () => {
518+
const container = document.createElement('div');
519+
const root = ReactDOM.createRoot(container);
520+
521+
function App() {
522+
fakeConsole.log('log');
523+
fakeConsole.warn('warn');
524+
fakeConsole.error('error');
525+
return <div />;
526+
}
527+
528+
patchConsole({
529+
appendComponentStack: false,
530+
breakOnWarn: false,
531+
showInlineWarningsAndErrors: false,
532+
hideDoubleLogsInStrictMode: true,
533+
});
534+
535+
act(() =>
536+
root.render(
537+
<React.StrictMode>
538+
<App />
539+
</React.StrictMode>,
540+
),
541+
);
542+
543+
expect(mockLog).toHaveBeenCalledTimes(1);
544+
expect(mockLog.mock.calls[0]).toHaveLength(1);
545+
expect(mockLog.mock.calls[0][0]).toBe('log');
546+
547+
expect(mockWarn).toHaveBeenCalledTimes(1);
548+
expect(mockWarn.mock.calls[0]).toHaveLength(1);
549+
expect(mockWarn.mock.calls[0][0]).toBe('warn');
550+
551+
expect(mockError).toHaveBeenCalledTimes(1);
552+
expect(mockError.mock.calls[0]).toHaveLength(1);
553+
expect(mockError.mock.calls[0][0]).toBe('error');
554+
});
468555
});

packages/react-reconciler/src/ReactFiberReconciler.new.js

+8
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ export {
105105
observeVisibleRects,
106106
} from './ReactTestSelectors';
107107

108+
import * as Scheduler from './Scheduler';
109+
import {setSuppressWarning} from 'shared/consoleWithStackDev';
110+
108111
type OpaqueRoot = FiberRoot;
109112

110113
// 0 is PROD, 1 is DEV.
@@ -714,6 +717,11 @@ export function getIsStrictModeForDevtools() {
714717
}
715718

716719
export function setIsStrictModeForDevtools(newIsStrictMode: boolean) {
720+
// We're in a test. Disable yielding during the double render
721+
if (typeof Scheduler.unstable_yieldValue === 'function') {
722+
Scheduler._setDisableYieldValue(newIsStrictMode);
723+
setSuppressWarning(newIsStrictMode);
724+
}
717725
isStrictMode = newIsStrictMode;
718726
}
719727

packages/react-reconciler/src/ReactFiberReconciler.old.js

+8
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ export {
105105
observeVisibleRects,
106106
} from './ReactTestSelectors';
107107

108+
import * as Scheduler from './Scheduler';
109+
import {setSuppressWarning} from 'shared/consoleWithStackDev';
110+
108111
type OpaqueRoot = FiberRoot;
109112

110113
// 0 is PROD, 1 is DEV.
@@ -714,6 +717,11 @@ export function getIsStrictModeForDevtools() {
714717
}
715718

716719
export function setIsStrictModeForDevtools(newIsStrictMode: boolean) {
720+
// We're in a test. Disable yielding during the double render
721+
if (typeof Scheduler.unstable_yieldValue === 'function') {
722+
Scheduler._setDisableYieldValue(newIsStrictMode);
723+
setSuppressWarning(newIsStrictMode);
724+
}
717725
isStrictMode = newIsStrictMode;
718726
}
719727

packages/react-reconciler/src/Scheduler.js

+3
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ export const NormalPriority = Scheduler.unstable_NormalPriority;
2626
export const LowPriority = Scheduler.unstable_LowPriority;
2727
export const IdlePriority = Scheduler.unstable_IdlePriority;
2828
export type SchedulerCallback = (isSync: boolean) => SchedulerCallback | null;
29+
30+
export const unstable_yieldValue = Scheduler.unstable_yieldValue;
31+
export const _setDisableYieldValue = Scheduler._setDisableYieldValue;

packages/react/src/__tests__/ReactStrictMode-test.js

+13-13
Original file line numberDiff line numberDiff line change
@@ -893,8 +893,8 @@ describe('context legacy', () => {
893893
ReactDOM.render(<Root />, container);
894894
});
895895

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

900900
let count = 0;
@@ -915,14 +915,14 @@ describe('context legacy', () => {
915915
);
916916

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

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

928928
let count = 0;
@@ -946,14 +946,14 @@ describe('context legacy', () => {
946946
);
947947

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

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

959959
let count = 0;
@@ -978,14 +978,14 @@ describe('context legacy', () => {
978978
);
979979

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

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

991991
let count = 0;
@@ -1017,14 +1017,14 @@ describe('context legacy', () => {
10171017
);
10181018

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

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

10301030
let inst;
@@ -1051,14 +1051,14 @@ describe('context legacy', () => {
10511051
});
10521052

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

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

10641064
let count = 0;
@@ -1077,7 +1077,7 @@ describe('context legacy', () => {
10771077
);
10781078

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

packages/scheduler/src/forks/SchedulerMock.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ let isFlushing: boolean = false;
7979
let needsPaint: boolean = false;
8080
let shouldYieldForPaint: boolean = false;
8181

82+
var _disableYieldValue = false;
83+
84+
function setDisableYieldValue(newValue) {
85+
_disableYieldValue = newValue;
86+
}
87+
8288
function advanceTimers(currentTime) {
8389
// Check for tasks that are no longer delayed and add them to the queue.
8490
let timer = peek(timerQueue);
@@ -570,7 +576,7 @@ function unstable_flushAll(): void {
570576

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

585591
function unstable_advanceTime(ms: number) {
586592
// eslint-disable-next-line react-internal/no-production-logging
587-
if (console.log.name === 'disabledLog') {
593+
if (console.log.name === 'disabledLog' || _disableYieldValue) {
588594
// If console.log has been patched, we assume we're in render
589595
// replaying and we ignore any time advancing in the second pass.
590596
return;
@@ -629,6 +635,7 @@ export {
629635
unstable_yieldValue,
630636
unstable_advanceTime,
631637
reset,
638+
setDisableYieldValue as _setDisableYieldValue,
632639
};
633640

634641
export const unstable_Profiling = enableProfiling

packages/shared/consoleWithStackDev.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77

88
import ReactSharedInternals from 'shared/ReactSharedInternals';
99

10+
let suppressWarning = false;
11+
export function setSuppressWarning(newSuppressWarning) {
12+
if (__DEV__) {
13+
suppressWarning = newSuppressWarning;
14+
}
15+
}
16+
1017
// In DEV, calls to console.warn and console.error get replaced
1118
// by calls to these methods by a Babel plugin.
1219
//
@@ -15,13 +22,17 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';
1522

1623
export function warn(format, ...args) {
1724
if (__DEV__) {
18-
printWarning('warn', format, args);
25+
if (!suppressWarning) {
26+
printWarning('warn', format, args);
27+
}
1928
}
2029
}
2130

2231
export function error(format, ...args) {
2332
if (__DEV__) {
24-
printWarning('error', format, args);
33+
if (!suppressWarning) {
34+
printWarning('error', format, args);
35+
}
2536
}
2637
}
2738

packages/shared/forks/Scheduler.umd.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ const {
3131
unstable_forceFrameRate,
3232

3333
// this doesn't actually exist on the scheduler, but it *does*
34-
// on scheduler/unstable_mock, which we'll need inside act().
34+
// on scheduler/unstable_mock, which we'll need inside act()
35+
// and for internal testing
3536
unstable_flushAllWithoutAsserting,
37+
unstable_yieldValue,
38+
_setDisableYieldValue,
3639
} = ReactInternals.Scheduler;
3740

3841
export {
@@ -54,4 +57,6 @@ export {
5457
unstable_IdlePriority,
5558
unstable_forceFrameRate,
5659
unstable_flushAllWithoutAsserting,
60+
unstable_yieldValue,
61+
_setDisableYieldValue,
5762
};

0 commit comments

Comments
 (0)