Repository: facebook/react
Pull request: Don't strip out component stack in assertConsole helpers

Use the same normalizeCodeLocInfo that we use everywhere else.

We should actually test the component stack itself. Not just that it exists. This was causing false passes.

However, the logic was also wrong before because it wouldn't always strip out the last line so wouldn't accurately normalize it. Leading to false failures as well.


Changed files:
filename: packages/internal-test-utils/__tests__/ReactInternalTestUtils-test.js
patch: @@ -1002,8 +1002,8 @@ describe('ReactInternalTestUtils console assertions', () => {
         - Hi
         - Wow
         - Bye
-        + Wow  <component stack>
-        + Bye  <component stack>"
+        + Wow      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
 
@@ -1025,8 +1025,8 @@ describe('ReactInternalTestUtils console assertions', () => {
         - Hi
         - Wow
         - Bye
-        + Hi  <component stack>
-        + Bye  <component stack>"
+        + Hi      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
 
@@ -1048,8 +1048,8 @@ describe('ReactInternalTestUtils console assertions', () => {
         - Hi
         - Wow
         - Bye
-        + Hi  <component stack>
-        + Wow  <component stack>"
+        + Hi      in div (at **)
+        + Wow      in div (at **)"
       `);
     });
 
@@ -1071,9 +1071,9 @@ describe('ReactInternalTestUtils console assertions', () => {
 
         - Wow
         - Bye
-        + Hi  <component stack>
-        + Wow  <component stack>
-        + Bye  <component stack>"
+        + Hi      in div (at **)
+        + Wow      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
 
@@ -1095,9 +1095,9 @@ describe('ReactInternalTestUtils console assertions', () => {
 
         - Hi
         - Bye
-        + Hi  <component stack>
-        + Wow  <component stack>
-        + Bye  <component stack>"
+        + Hi      in div (at **)
+        + Wow      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
 
@@ -1119,9 +1119,9 @@ describe('ReactInternalTestUtils console assertions', () => {
 
         - Hi
         - Wow
-        + Hi  <component stack>
-        + Wow  <component stack>
-        + Bye  <component stack>"
+        + Hi      in div (at **)
+        + Wow      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
 
@@ -1297,7 +1297,8 @@ describe('ReactInternalTestUtils console assertions', () => {
           "assertConsoleWarnDev(expected)
 
           Unexpected component stack for:
-            "Hello <component stack>"
+            "Hello
+              in div (at **)"
 
           If this warning should include a component stack, remove {withoutStack: true} from this warning.
           If all warnings should include the component stack, you may need to remove {withoutStack: true} from the assertConsoleWarnDev call."
@@ -1318,10 +1319,12 @@ describe('ReactInternalTestUtils console assertions', () => {
           "assertConsoleWarnDev(expected)
 
           Unexpected component stack for:
-            "Hello <component stack>"
+            "Hello
+              in div (at **)"
 
           Unexpected component stack for:
-            "Bye <component stack>"
+            "Bye
+              in div (at **)"
 
           If this warning should include a component stack, remove {withoutStack: true} from this warning.
           If all warnings should include the component stack, you may need to remove {withoutStack: true} from the assertConsoleWarnDev call."
@@ -1444,7 +1447,8 @@ describe('ReactInternalTestUtils console assertions', () => {
           "assertConsoleWarnDev(expected)
 
           Unexpected component stack for:
-            "Hello <component stack>"
+            "Hello
+              in div (at **)"
 
           If this warning should include a component stack, remove {withoutStack: true} from this warning.
           If all warnings should include the component stack, you may need to remove {withoutStack: true} from the assertConsoleWarnDev call."
@@ -1477,10 +1481,12 @@ describe('ReactInternalTestUtils console assertions', () => {
           "assertConsoleWarnDev(expected)
 
           Unexpected component stack for:
-            "Hello <component stack>"
+            "Hello
+              in div (at **)"
 
           Unexpected component stack for:
-            "Bye <component stack>"
+            "Bye
+              in div (at **)"
 
           If this warning should include a component stack, remove {withoutStack: true} from this warning.
           If all warnings should include the component stack, you may need to remove {withoutStack: true} from the assertConsoleWarnDev call."
@@ -1934,8 +1940,8 @@ describe('ReactInternalTestUtils console assertions', () => {
         - Hi
         - Wow
         - Bye
-        + Wow  <component stack>
-        + Bye  <component stack>"
+        + Wow      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
 
@@ -1957,8 +1963,8 @@ describe('ReactInternalTestUtils console assertions', () => {
         - Hi
         - Wow
         - Bye
-        + Hi  <component stack>
-        + Bye  <component stack>"
+        + Hi      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
 
@@ -1980,8 +1986,8 @@ describe('ReactInternalTestUtils console assertions', () => {
         - Hi
         - Wow
         - Bye
-        + Hi  <component stack>
-        + Wow  <component stack>"
+        + Hi      in div (at **)
+        + Wow      in div (at **)"
       `);
     });
 
@@ -2003,9 +2009,9 @@ describe('ReactInternalTestUtils console assertions', () => {
 
         - Wow
         - Bye
-        + Hi  <component stack>
-        + Wow  <component stack>
-        + Bye  <component stack>"
+        + Hi      in div (at **)
+        + Wow      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
 
@@ -2027,9 +2033,9 @@ describe('ReactInternalTestUtils console assertions', () => {
 
         - Hi
         - Bye
-        + Hi  <component stack>
-        + Wow  <component stack>
-        + Bye  <component stack>"
+        + Hi      in div (at **)
+        + Wow      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
 
@@ -2051,9 +2057,9 @@ describe('ReactInternalTestUtils console assertions', () => {
 
         - Hi
         - Wow
-        + Hi  <component stack>
-        + Wow  <component stack>
-        + Bye  <component stack>"
+        + Hi      in div (at **)
+        + Wow      in div (at **)
+        + Bye      in div (at **)"
       `);
     });
     // @gate __DEV__
@@ -2170,7 +2176,7 @@ describe('ReactInternalTestUtils console assertions', () => {
         + Received errors
 
         - This is a completely different message that happens to start with "T"
-        + Message that happens to contain a "T" <component stack>"
+        + Message that happens to contain a "T"     in div (at **)"
       `);
     });
 
@@ -2247,7 +2253,8 @@ describe('ReactInternalTestUtils console assertions', () => {
           "assertConsoleErrorDev(expected)
 
           Unexpected component stack for:
-            "Hello <component stack>"
+            "Hello
+              in div (at **)"
 
           If this error should include a component stack, remove {withoutStack: true} from this error.
           If all errors should include the component stack, you may need to remove {withoutStack: true} from the assertConsoleErrorDev call."
@@ -2268,10 +2275,12 @@ describe('ReactInternalTestUtils console assertions', () => {
           "assertConsoleErrorDev(expected)
 
           Unexpected component stack for:
-            "Hello <component stack>"
+            "Hello
+              in div (at **)"
 
           Unexpected component stack for:
-            "Bye <component stack>"
+            "Bye
+              in div (at **)"
 
           If this error should include a component stack, remove {withoutStack: true} from this error.
           If all errors should include the component stack, you may need to remove {withoutStack: true} from the assertConsoleErrorDev call."
@@ -2394,7 +2403,8 @@ describe('ReactInternalTestUtils console assertions', () => {
           "assertConsoleErrorDev(expected)
 
           Unexpected component stack for:
-            "Hello <component stack>"
+            "Hello
+              in div (at **)"
 
           If this error should include a component stack, remove {withoutStack: true} from this error.
           If all errors should include the component stack, you may need to remove {withoutStack: true} from the assertConsoleErrorDev call."
@@ -2427,10 +2437,12 @@ describe('ReactInternalTestUtils console assertions', () => {
           "assertConsoleErrorDev(expected)
 
           Unexpected component stack for:
-            "Hello <component stack>"
+            "Hello
+              in div (at **)"
 
           Unexpected component stack for:
-            "Bye <component stack>"
+            "Bye
+              in div (at **)"
 
           If this error should include a component stack, remove {withoutStack: true} from this error.
           If all errors should include the component stack, you may need to remove {withoutStack: true} from the assertConsoleErrorDev call."
@@ -2459,7 +2471,7 @@ describe('ReactInternalTestUtils console assertions', () => {
           + Received errors
 
           - Hello
-          + Bye <component stack>"
+          + Bye     in div (at **)"
         `);
       });
     });

filename: packages/internal-test-utils/consoleMock.js
patch: @@ -228,7 +228,7 @@ export function assertConsoleLogsCleared() {
   }
 }
 
-function replaceComponentStack(str) {
+function normalizeCodeLocInfo(str) {
   if (typeof str !== 'string') {
     return str;
   }
@@ -239,8 +239,13 @@ function replaceComponentStack(str) {
   //  at Component (/path/filename.js:123:45)
   // React format:
   //    in Component (at filename.js:123)
-  return str.replace(/\n +(?:at|in) ([\S]+)[^\n]*.*/, function (m, name) {
-    return chalk.dim(' <component stack>');
+  return str.replace(/\n +(?:at|in) ([\S]+)[^\n]*/g, function (m, name) {
+    if (name.endsWith('.render')) {
+      // Class components will have the `render` method as part of their stack trace.
+      // We strip that out in our normalization to make it look more like component stacks.
+      name = name.slice(0, name.length - 7);
+    }
+    return '\n    in ' + name + ' (at **)';
   });
 }
 
@@ -382,11 +387,11 @@ export function createLogAssertion(
             );
           }
 
-          expectedMessage = replaceComponentStack(currentExpectedMessage);
+          expectedMessage = normalizeCodeLocInfo(currentExpectedMessage);
           expectedWithoutStack = expectedMessageOrArray[1].withoutStack;
         } else if (typeof expectedMessageOrArray === 'string') {
           // Should be in the form assert(['log']) or assert(['log'], {withoutStack: true})
-          expectedMessage = replaceComponentStack(expectedMessageOrArray);
+          expectedMessage = normalizeCodeLocInfo(expectedMessageOrArray);
           if (consoleMethod === 'log') {
             expectedWithoutStack = true;
           } else {
@@ -410,7 +415,7 @@ export function createLogAssertion(
           );
         }
 
-        const normalizedMessage = replaceComponentStack(message);
+        const normalizedMessage = normalizeCodeLocInfo(message);
         receivedLogs.push(normalizedMessage);
 
         // Check the number of %s interpolations.