Skip to content

Commit a9dc73c

Browse files
authored
Handle info, group, and groupCollapsed in Strict Mode logging (facebook#25172)
* Handle info, group, and groupCollapsed in Strict Mode logging While working on the new Next.js router which heavily relies on useReducer I noticed that `group` and `groupCollapsed` which both take labels were showing as-is in the console for the second render/dispatch in Strict Mode logs. While looking at the code I found that `info` was also not instrumented. I've added additional handling for: - `info` - `group` - `groupCollapsed` * Remove console.log * Fix tests
1 parent 81b79c7 commit a9dc73c

File tree

3 files changed

+83
-2
lines changed

3 files changed

+83
-2
lines changed

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

+65
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ let fakeConsole;
1616
let legacyRender;
1717
let mockError;
1818
let mockInfo;
19+
let mockGroup;
20+
let mockGroupCollapsed;
1921
let mockLog;
2022
let mockWarn;
2123
let patchConsole;
@@ -25,6 +27,7 @@ let rendererID;
2527
describe('console', () => {
2628
beforeEach(() => {
2729
const Console = require('react-devtools-shared/src/backend/console');
30+
2831
patchConsole = Console.patch;
2932
unpatchConsole = Console.unpatch;
3033

@@ -33,13 +36,17 @@ describe('console', () => {
3336
// because Jest itself has hooks into it as does our test env setup.
3437
mockError = jest.fn();
3538
mockInfo = jest.fn();
39+
mockGroup = jest.fn();
40+
mockGroupCollapsed = jest.fn();
3641
mockLog = jest.fn();
3742
mockWarn = jest.fn();
3843
fakeConsole = {
3944
error: mockError,
4045
info: mockInfo,
4146
log: mockLog,
4247
warn: mockWarn,
48+
group: mockGroup,
49+
groupCollapsed: mockGroupCollapsed,
4350
};
4451

4552
Console.dangerous_setTargetConsoleForTesting(fakeConsole);
@@ -69,6 +76,8 @@ describe('console', () => {
6976
expect(fakeConsole.info).toBe(mockInfo);
7077
expect(fakeConsole.log).toBe(mockLog);
7178
expect(fakeConsole.warn).not.toBe(mockWarn);
79+
expect(fakeConsole.group).toBe(mockGroup);
80+
expect(fakeConsole.groupCollapsed).toBe(mockGroupCollapsed);
7281
});
7382

7483
// @reactVersion >=18.0
@@ -491,6 +500,9 @@ describe('console', () => {
491500
fakeConsole.log('log');
492501
fakeConsole.warn('warn');
493502
fakeConsole.error('error');
503+
fakeConsole.info('info');
504+
fakeConsole.group('group');
505+
fakeConsole.groupCollapsed('groupCollapsed');
494506
return <div />;
495507
}
496508

@@ -528,6 +540,36 @@ describe('console', () => {
528540
`color: ${process.env.DARK_MODE_DIMMED_ERROR_COLOR}`,
529541
'error',
530542
]);
543+
544+
expect(mockInfo).toHaveBeenCalledTimes(2);
545+
expect(mockInfo.mock.calls[0]).toHaveLength(1);
546+
expect(mockInfo.mock.calls[0][0]).toBe('info');
547+
expect(mockInfo.mock.calls[1]).toHaveLength(3);
548+
expect(mockInfo.mock.calls[1]).toEqual([
549+
'%c%s',
550+
`color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
551+
'info',
552+
]);
553+
554+
expect(mockGroup).toHaveBeenCalledTimes(2);
555+
expect(mockGroup.mock.calls[0]).toHaveLength(1);
556+
expect(mockGroup.mock.calls[0][0]).toBe('group');
557+
expect(mockGroup.mock.calls[1]).toHaveLength(3);
558+
expect(mockGroup.mock.calls[1]).toEqual([
559+
'%c%s',
560+
`color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
561+
'group',
562+
]);
563+
564+
expect(mockGroupCollapsed).toHaveBeenCalledTimes(2);
565+
expect(mockGroupCollapsed.mock.calls[0]).toHaveLength(1);
566+
expect(mockGroupCollapsed.mock.calls[0][0]).toBe('groupCollapsed');
567+
expect(mockGroupCollapsed.mock.calls[1]).toHaveLength(3);
568+
expect(mockGroupCollapsed.mock.calls[1]).toEqual([
569+
'%c%s',
570+
`color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
571+
'groupCollapsed',
572+
]);
531573
});
532574

533575
it('should not double log if hideConsoleLogsInStrictMode is enabled in Strict mode', () => {
@@ -538,9 +580,16 @@ describe('console', () => {
538580
const root = ReactDOMClient.createRoot(container);
539581

540582
function App() {
583+
console.log(
584+
'CALL',
585+
global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__,
586+
);
541587
fakeConsole.log('log');
542588
fakeConsole.warn('warn');
543589
fakeConsole.error('error');
590+
fakeConsole.info('info');
591+
fakeConsole.group('group');
592+
fakeConsole.groupCollapsed('groupCollapsed');
544593
return <div />;
545594
}
546595

@@ -563,6 +612,18 @@ describe('console', () => {
563612
expect(mockError).toHaveBeenCalledTimes(1);
564613
expect(mockError.mock.calls[0]).toHaveLength(1);
565614
expect(mockError.mock.calls[0][0]).toBe('error');
615+
616+
expect(mockInfo).toHaveBeenCalledTimes(1);
617+
expect(mockInfo.mock.calls[0]).toHaveLength(1);
618+
expect(mockInfo.mock.calls[0][0]).toBe('info');
619+
620+
expect(mockGroup).toHaveBeenCalledTimes(1);
621+
expect(mockGroup.mock.calls[0]).toHaveLength(1);
622+
expect(mockGroup.mock.calls[0][0]).toBe('group');
623+
624+
expect(mockGroupCollapsed).toHaveBeenCalledTimes(1);
625+
expect(mockGroupCollapsed.mock.calls[0]).toHaveLength(1);
626+
expect(mockGroupCollapsed.mock.calls[0][0]).toBe('groupCollapsed');
566627
});
567628

568629
it('should double log in Strict mode initial render for extension', () => {
@@ -734,13 +795,17 @@ describe('console error', () => {
734795
// because Jest itself has hooks into it as does our test env setup.
735796
mockError = jest.fn();
736797
mockInfo = jest.fn();
798+
mockGroup = jest.fn();
799+
mockGroupCollapsed = jest.fn();
737800
mockLog = jest.fn();
738801
mockWarn = jest.fn();
739802
fakeConsole = {
740803
error: mockError,
741804
info: mockInfo,
742805
log: mockLog,
743806
warn: mockWarn,
807+
group: mockGroup,
808+
groupCollapsed: mockGroupCollapsed,
744809
};
745810

746811
Console.dangerous_setTargetConsoleForTesting(fakeConsole);

packages/react-devtools-shared/src/backend/console.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,15 @@ let unpatchForStrictModeFn: null | (() => void) = null;
301301
// NOTE: KEEP IN SYNC with src/hook.js:patchConsoleForInitialRenderInStrictMode
302302
export function patchForStrictMode() {
303303
if (consoleManagedByDevToolsDuringStrictMode) {
304-
const overrideConsoleMethods = ['error', 'trace', 'warn', 'log'];
304+
const overrideConsoleMethods = [
305+
'error',
306+
'group',
307+
'groupCollapsed',
308+
'info',
309+
'log',
310+
'trace',
311+
'warn',
312+
];
305313

306314
if (unpatchForStrictModeFn !== null) {
307315
// Don't patch twice.

packages/react-devtools-shared/src/hook.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,15 @@ export function installHook(target: any): DevToolsHook | null {
228228
hideConsoleLogsInStrictMode: boolean,
229229
browserTheme: BrowserTheme,
230230
}) {
231-
const overrideConsoleMethods = ['error', 'trace', 'warn', 'log'];
231+
const overrideConsoleMethods = [
232+
'error',
233+
'group',
234+
'groupCollapsed',
235+
'info',
236+
'log',
237+
'trace',
238+
'warn',
239+
];
232240

233241
if (unpatchFn !== null) {
234242
// Don't patch twice.

0 commit comments

Comments
 (0)