diff --git a/packages/react-test-renderer/src/ReactTestRenderer.js b/packages/react-test-renderer/src/ReactTestRenderer.js index 1bf7d4d4adbcf..40358e3fa2cab 100644 --- a/packages/react-test-renderer/src/ReactTestRenderer.js +++ b/packages/react-test-renderer/src/ReactTestRenderer.js @@ -22,6 +22,8 @@ import { HostPortal, HostText, HostRoot, + ContextConsumer, + ContextProvider, } from 'shared/ReactTypeOfWork'; import invariant from 'fbjs/lib/invariant'; @@ -367,6 +369,9 @@ function toTree(node: ?Fiber) { return node.stateNode.text; case Fragment: return childrenToTree(node.child); + case ContextConsumer: + case ContextProvider: + return toTree(node.child); default: invariant( false, @@ -393,6 +398,8 @@ const validWrapperTypes = new Set([ FunctionalComponent, ClassComponent, HostComponent, + ContextProvider, + ContextConsumer, ]); class ReactTestInstance { @@ -432,7 +439,7 @@ class ReactTestInstance { } get props(): Object { - return this._currentFiber().memoizedProps; + return this._currentFiber().memoizedProps || {}; } get parent(): ?ReactTestInstance { @@ -463,6 +470,8 @@ class ReactTestInstance { children.push('' + node.memoizedProps); break; case Fragment: + case ContextConsumer: + case ContextProvider: descend = true; break; default: @@ -545,7 +554,6 @@ function findAll( ): Array { const deep = options ? options.deep : true; const results = []; - if (predicate(root)) { results.push(root); if (!deep) { @@ -606,7 +614,6 @@ const ReactTestRendererFiber = { ); invariant(root != null, 'something went wrong'); TestRenderer.updateContainer(element, root, null, null); - const entry = { root: undefined, // makes flow happy // we define a 'getter' for 'root' below using 'Object.defineProperty' diff --git a/packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.js b/packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.js index f1df422e9321c..e1ea1c7f083fb 100644 --- a/packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.js +++ b/packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.js @@ -745,6 +745,30 @@ describe('ReactTestRenderer', () => { ); }); + it('toTree() handles ContextConsumer and ContextProvider components', () => { + const {Consumer, Provider} = React.createContext('foo'); + + const renderer = ReactTestRenderer.create( + + {value =>
{value}
}
+
, + ); + + const tree = renderer.toTree(); + + cleanNodeOrArray(tree); + + expect(prettyFormat(tree)).toEqual( + prettyFormat({ + type: 'div', + nodeType: 'host', + instance: null, + props: {}, + rendered: ['bar'], + }), + ); + }); + it('root instance and createNodeMock ref return the same value', () => { const createNodeMock = ref => ({node: ref}); let refInst = null; @@ -879,4 +903,30 @@ describe('ReactTestRenderer', () => { 'world', ]); }); + + it('can update Providers and Consumers', () => { + const {Consumer, Provider} = React.createContext('foo'); + + const renderer = ReactTestRenderer.create( + + {value =>
{value}
}
+
, + ); + + expect(renderer.toJSON()).toEqual({ + type: 'div', + children: ['bar'], + props: {}, + }); + renderer.update( + + {value =>
{value}
}
+
, + ); + expect(renderer.toJSON()).toEqual({ + type: 'div', + children: ['corge'], + props: {}, + }); + }); }); diff --git a/packages/react-test-renderer/src/__tests__/ReactTestRendererTraversal-test.js b/packages/react-test-renderer/src/__tests__/ReactTestRendererTraversal-test.js index 587a094f8ab70..d5bf31ad17c5d 100644 --- a/packages/react-test-renderer/src/__tests__/ReactTestRendererTraversal-test.js +++ b/packages/react-test-renderer/src/__tests__/ReactTestRendererTraversal-test.js @@ -17,9 +17,14 @@ const RCTView = 'RCTView'; const View = props => ; describe('ReactTestRendererTraversal', () => { + let Consumer, Provider; + beforeEach(() => { jest.resetModules(); ReactTestRenderer = require('react-test-renderer'); + const context = React.createContext('corge'); + Consumer = context.Consumer; + Provider = context.Provider; }); class Example extends React.Component { @@ -37,6 +42,9 @@ describe('ReactTestRendererTraversal', () => { + + {value => } + ); @@ -54,7 +62,7 @@ describe('ReactTestRendererTraversal', () => { // assert .props, .type and .parent attributes const foo = render.root.find(hasFooProp); - expect(foo.props.children).toHaveLength(7); + expect(foo.props.children).toHaveLength(8); expect(foo.type).toBe(View); expect(render.root.parent).toBe(null); expect(foo.children[0].parent).toBe(foo); @@ -69,6 +77,8 @@ describe('ReactTestRendererTraversal', () => { const hasNullProp = node => node.props.hasOwnProperty('null'); const hasVoidProp = node => node.props.hasOwnProperty('void'); const hasItselfProp = node => node.props.hasOwnProperty('itself'); + const hasProviderType = node => node.type === Provider; + const hasConsumerType = node => node.type === Consumer; expect(() => render.root.find(hasFooProp)).not.toThrow(); // 1 match expect(() => render.root.find(hasBarProp)).toThrow(); // >1 matches @@ -76,6 +86,8 @@ describe('ReactTestRendererTraversal', () => { expect(() => render.root.find(hasBingProp)).not.toThrow(); // 1 match expect(() => render.root.find(hasNullProp)).not.toThrow(); // 1 match expect(() => render.root.find(hasVoidProp)).toThrow(); // 0 matches + expect(() => render.root.find(hasProviderType)).toThrow(); // 0 matches + expect(() => render.root.find(hasConsumerType)).toThrow(); // 0 matches // same assertion as .find(), but confirm length expect(render.root.findAll(hasFooProp, {deep: false})).toHaveLength(1); @@ -119,10 +131,12 @@ describe('ReactTestRendererTraversal', () => { // note: there are clearly multiple in general, but there // is only one being rendered at root node level expect(() => render.root.findByType(ExampleNull)).toThrow(); // 2 matches + expect(() => render.root.findByType(Provider)).toThrow(); // 0 matches + expect(() => render.root.findByType(Consumer)).toThrow(); // 0 matches expect(render.root.findAllByType(ExampleFn)).toHaveLength(1); expect(render.root.findAllByType(View, {deep: false})).toHaveLength(1); - expect(render.root.findAllByType(View)).toHaveLength(7); + expect(render.root.findAllByType(View)).toHaveLength(8); expect(render.root.findAllByType(ExampleNull)).toHaveLength(2); const nulls = render.root.findAllByType(ExampleNull);