@samitouri / QOS-React-2 / commits / a9dc73cfd4

Handle info, group, and groupCollapsed in Strict Mode logging (#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

Tim Neutkens committed Sep 6, 2022 at 19:03 UTC a9dc73cfd4db480b4cadf8624351004fe96f5a12
3 files changed +83 -2
packages/react-devtools-shared/src/__tests__/console-test.js
+65
@@ -16,6 +16,8 @@ let fakeConsole;
16 let legacyRender;
17 let mockError;
18 let mockInfo;
19 +let mockGroup;
20 +let mockGroupCollapsed;
21 let mockLog;
22 let mockWarn;
23 let patchConsole;
@@ -25,6 +27,7 @@ let rendererID;
27 describe('console', () => {
28 beforeEach(() => {
29 const Console = require('react-devtools-shared/src/backend/console');
30 +
31 patchConsole = Console.patch;
32 unpatchConsole = Console.unpatch;
33
@@ -33,6 +36,8 @@ describe('console', () => {
36 // because Jest itself has hooks into it as does our test env setup.
37 mockError = jest.fn();
38 mockInfo = jest.fn();
39 + mockGroup = jest.fn();
40 + mockGroupCollapsed = jest.fn();
41 mockLog = jest.fn();
42 mockWarn = jest.fn();
43 fakeConsole = {
@@ -40,6 +45,8 @@ describe('console', () => {
45 info: mockInfo,
46 log: mockLog,
47 warn: mockWarn,
48 + group: mockGroup,
49 + groupCollapsed: mockGroupCollapsed,
50 };
51
52 Console.dangerous_setTargetConsoleForTesting(fakeConsole);
@@ -69,6 +76,8 @@ describe('console', () => {
76 expect(fakeConsole.info).toBe(mockInfo);
77 expect(fakeConsole.log).toBe(mockLog);
78 expect(fakeConsole.warn).not.toBe(mockWarn);
79 + expect(fakeConsole.group).toBe(mockGroup);
80 + expect(fakeConsole.groupCollapsed).toBe(mockGroupCollapsed);
81 });
82
83 // @reactVersion >=18.0
@@ -491,6 +500,9 @@ describe('console', () => {
500 fakeConsole.log('log');
501 fakeConsole.warn('warn');
502 fakeConsole.error('error');
503 + fakeConsole.info('info');
504 + fakeConsole.group('group');
505 + fakeConsole.groupCollapsed('groupCollapsed');
506 return <div />;
507 }
508
@@ -528,6 +540,36 @@ describe('console', () => {
540 `color: ${process.env.DARK_MODE_DIMMED_ERROR_COLOR}`,
541 'error',
542 ]);
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 + ]);
573 });
574
575 it('should not double log if hideConsoleLogsInStrictMode is enabled in Strict mode', () => {
@@ -538,9 +580,16 @@ describe('console', () => {
580 const root = ReactDOMClient.createRoot(container);
581
582 function App() {
583 + console.log(
584 + 'CALL',
585 + global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__,
586 + );
587 fakeConsole.log('log');
588 fakeConsole.warn('warn');
589 fakeConsole.error('error');
590 + fakeConsole.info('info');
591 + fakeConsole.group('group');
592 + fakeConsole.groupCollapsed('groupCollapsed');
593 return <div />;
594 }
595
@@ -563,6 +612,18 @@ describe('console', () => {
612 expect(mockError).toHaveBeenCalledTimes(1);
613 expect(mockError.mock.calls[0]).toHaveLength(1);
614 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');
627 });
628
629 it('should double log in Strict mode initial render for extension', () => {
@@ -734,6 +795,8 @@ describe('console error', () => {
795 // because Jest itself has hooks into it as does our test env setup.
796 mockError = jest.fn();
797 mockInfo = jest.fn();
798 + mockGroup = jest.fn();
799 + mockGroupCollapsed = jest.fn();
800 mockLog = jest.fn();
801 mockWarn = jest.fn();
802 fakeConsole = {
@@ -741,6 +804,8 @@ describe('console error', () => {
804 info: mockInfo,
805 log: mockLog,
806 warn: mockWarn,
807 + group: mockGroup,
808 + groupCollapsed: mockGroupCollapsed,
809 };
810
811 Console.dangerous_setTargetConsoleForTesting(fakeConsole);
packages/react-devtools-shared/src/backend/console.js
+9 -1
@@ -301,7 +301,15 @@ let unpatchForStrictModeFn: null | (() => void) = null;
301 // NOTE: KEEP IN SYNC with src/hook.js:patchConsoleForInitialRenderInStrictMode
302 export function patchForStrictMode() {
303 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 + ];
313
314 if (unpatchForStrictModeFn !== null) {
315 // Don't patch twice.
packages/react-devtools-shared/src/hook.js
+9 -1
@@ -228,7 +228,15 @@ export function installHook(target: any): DevToolsHook | null {
228 hideConsoleLogsInStrictMode: boolean,
229 browserTheme: BrowserTheme,
230 }) {
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 + ];
240
241 if (unpatchFn !== null) {
242 // Don't patch twice.