diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6363beb7c651..ee5c4133cb94 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -127,6 +127,8 @@
([#5720](https://github.com/facebook/jest/pull/5720))
* `[pretty-format]` Handle React fragments better
([#5816](https://github.com/facebook/jest/pull/5816))
+* `[pretty-format]` Handle formatting of `React.forwardRef` and `Context`
+ components ([#6093](https://github.com/facebook/jest/pull/6093))
* `[jest-cli]` Switch collectCoverageFrom back to a string
([#5914](https://github.com/facebook/jest/pull/5914))
* `[jest-regex-util]` Fix handling regex symbols in tests path on Windows
diff --git a/packages/pretty-format/src/__tests__/react.test.js b/packages/pretty-format/src/__tests__/react.test.js
index f136884305d9..f25d7b30187d 100644
--- a/packages/pretty-format/src/__tests__/react.test.js
+++ b/packages/pretty-format/src/__tests__/react.test.js
@@ -717,3 +717,38 @@ test('ReactTestComponent plugin highlights syntax with color from theme option',
}),
).toMatchSnapshot();
});
+
+test('supports forwardRef with a child', () => {
+ function Cat(props) {
+ return React.createElement('div', props, props.children);
+ }
+
+ expect(
+ // $FlowFixMe - https://github.com/facebook/flow/issues/6103
+ formatElement(React.createElement(React.forwardRef(Cat), null, 'mouse')),
+ ).toEqual('\n mouse\n');
+});
+
+test('supports context Provider with a child', () => {
+ const {Provider} = React.createContext('test');
+
+ expect(
+ formatElement(
+ React.createElement(Provider, {value: 'test-value'}, 'child'),
+ ),
+ ).toEqual(
+ '\n child\n',
+ );
+});
+
+test('supports context Consumer with a child', () => {
+ const {Consumer} = React.createContext('test');
+
+ expect(
+ formatElement(
+ React.createElement(Consumer, null, () =>
+ React.createElement('div', null, 'child'),
+ ),
+ ),
+ ).toEqual('\n [Function anonymous]\n');
+});
diff --git a/packages/pretty-format/src/plugins/react_element.js b/packages/pretty-format/src/plugins/react_element.js
index 1fd2be25b83d..78b73be8ae2e 100644
--- a/packages/pretty-format/src/plugins/react_element.js
+++ b/packages/pretty-format/src/plugins/react_element.js
@@ -19,6 +19,8 @@ import {
const elementSymbol = Symbol.for('react.element');
const fragmentSymbol = Symbol.for('react.fragment');
const forwardRefSymbol = Symbol.for('react.forward_ref');
+const providerSymbol = Symbol.for('react.provider');
+const contextSymbol = Symbol.for('react.context');
// Given element.props.children, or subtree during recursive traversal,
// return flattened array of children.
@@ -34,22 +36,32 @@ const getChildren = (arg, children = []) => {
};
const getType = element => {
- if (typeof element.type === 'string') {
- return element.type;
+ const type = element.type;
+ if (typeof type === 'string') {
+ return type;
}
- if (typeof element.type === 'function') {
- return element.type.displayName || element.type.name || 'Unknown';
+ if (typeof type === 'function') {
+ return type.displayName || type.name || 'Unknown';
}
- if (element.type === fragmentSymbol) {
+ if (type === fragmentSymbol) {
return 'React.Fragment';
}
- if (element.type === forwardRefSymbol) {
- const functionName =
- element.type.render.displayName || element.type.render.name || '';
+ if (typeof type === 'object' && type !== null) {
+ if (type.$$typeof === providerSymbol) {
+ return 'Context.Provider';
+ }
- return functionName !== ''
- ? 'ForwardRef(' + functionName + ')'
- : 'ForwardRef';
+ if (type.$$typeof === contextSymbol) {
+ return 'Context.Consumer';
+ }
+
+ if (type.$$typeof === forwardRefSymbol) {
+ const functionName = type.render.displayName || type.render.name || '';
+
+ return functionName !== ''
+ ? 'ForwardRef(' + functionName + ')'
+ : 'ForwardRef';
+ }
}
return 'UNDEFINED';
};