Skip to content

Commit

Permalink
Skip special nodes when reading TestInstance.parent (#12813)
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed May 15, 2018
1 parent e96dc14 commit 7dc1a17
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 30 deletions.
42 changes: 14 additions & 28 deletions packages/react-test-renderer/src/ReactTestRenderer.js
Expand Up @@ -245,10 +245,14 @@ class ReactTestInstance {
}

get parent(): ?ReactTestInstance {
const parent = this._fiber.return;
return parent === null || parent.tag === HostRoot
? null
: wrapFiber(parent);
let parent = this._fiber.return;
while (parent !== null) {
if (validWrapperTypes.has(parent.tag)) {
return wrapFiber(parent);
}
parent = parent.return;
}
return null;
}

get children(): Array<ReactTestInstance | string> {
Expand All @@ -262,30 +266,12 @@ class ReactTestInstance {
node = node.child;
outer: while (true) {
let descend = false;
switch (node.tag) {
case FunctionalComponent:
case ClassComponent:
case HostComponent:
case ForwardRef:
children.push(wrapFiber(node));
break;
case HostText:
children.push('' + node.memoizedProps);
break;
case Fragment:
case ContextProvider:
case ContextConsumer:
case Mode:
case Profiler:
descend = true;
break;
default:
invariant(
false,
'Unsupported component type %s in test renderer. ' +
'This is probably a bug in React.',
node.tag,
);
if (validWrapperTypes.has(node.tag)) {
children.push(wrapFiber(node));
} else if (node.tag === HostText) {
children.push('' + node.memoizedProps);
} else {
descend = true;
}
if (descend && node.child !== null) {
node.child.return = node;
Expand Down
Expand Up @@ -12,6 +12,7 @@

const React = require('react');
let ReactTestRenderer;
let Context;

const RCTView = 'RCTView';
const View = props => <RCTView {...props} />;
Expand All @@ -20,6 +21,7 @@ describe('ReactTestRendererTraversal', () => {
beforeEach(() => {
jest.resetModules();
ReactTestRenderer = require('react-test-renderer');
Context = React.createContext(null);
});

class Example extends React.Component {
Expand All @@ -40,6 +42,17 @@ describe('ReactTestRendererTraversal', () => {
<React.unstable_Profiler id="test" onRender={() => {}}>
<ExampleForwardRef qux="qux" />
</React.unstable_Profiler>
<React.Fragment>
<React.Fragment>
<Context.Provider value={null}>
<Context.Consumer>
{() => <View nested={true} />}
</Context.Consumer>
</Context.Provider>
</React.Fragment>
<View nested={true} />
<View nested={true} />
</React.Fragment>
</View>
</View>
);
Expand All @@ -61,7 +74,7 @@ describe('ReactTestRendererTraversal', () => {

// assert .props, .type and .parent attributes
const foo = render.root.find(hasFooProp);
expect(foo.props.children).toHaveLength(8);
expect(foo.props.children).toHaveLength(9);
expect(foo.type).toBe(View);
expect(render.root.parent).toBe(null);
expect(foo.children[0].parent).toBe(foo);
Expand All @@ -76,13 +89,15 @@ describe('ReactTestRendererTraversal', () => {
const hasNullProp = node => node.props.hasOwnProperty('null');
const hasVoidProp = node => node.props.hasOwnProperty('void');
const hasItselfProp = node => node.props.hasOwnProperty('itself');
const hasNestedProp = node => node.props.hasOwnProperty('nested');

expect(() => render.root.find(hasFooProp)).not.toThrow(); // 1 match
expect(() => render.root.find(hasBarProp)).toThrow(); // >1 matches
expect(() => render.root.find(hasBazProp)).toThrow(); // >1 matches
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(hasNestedProp)).toThrow(); // >1 matches

// same assertion as .find(), but confirm length
expect(render.root.findAll(hasFooProp, {deep: false})).toHaveLength(1);
Expand All @@ -91,6 +106,7 @@ describe('ReactTestRendererTraversal', () => {
expect(render.root.findAll(hasBingProp, {deep: false})).toHaveLength(1);
expect(render.root.findAll(hasNullProp, {deep: false})).toHaveLength(1);
expect(render.root.findAll(hasVoidProp, {deep: false})).toHaveLength(0);
expect(render.root.findAll(hasNestedProp, {deep: false})).toHaveLength(3);

// note: with {deep: true}, .findAll() will continue to
// search children, even after finding a match
Expand All @@ -100,6 +116,7 @@ describe('ReactTestRendererTraversal', () => {
expect(render.root.findAll(hasBingProp)).toHaveLength(1); // no spread
expect(render.root.findAll(hasNullProp)).toHaveLength(1); // no spread
expect(render.root.findAll(hasVoidProp)).toHaveLength(0);
expect(render.root.findAll(hasNestedProp, {deep: false})).toHaveLength(3);

const bing = render.root.find(hasBingProp);
expect(bing.find(hasBarProp)).toBe(bing);
Expand Down Expand Up @@ -130,7 +147,7 @@ describe('ReactTestRendererTraversal', () => {

expect(render.root.findAllByType(ExampleFn)).toHaveLength(1);
expect(render.root.findAllByType(View, {deep: false})).toHaveLength(1);
expect(render.root.findAllByType(View)).toHaveLength(8);
expect(render.root.findAllByType(View)).toHaveLength(11);
expect(render.root.findAllByType(ExampleNull)).toHaveLength(2);
expect(render.root.findAllByType(ExampleForwardRef)).toHaveLength(1);

Expand Down Expand Up @@ -164,4 +181,22 @@ describe('ReactTestRendererTraversal', () => {
expect(render.root.findAllByProps({baz})).toHaveLength(4);
expect(render.root.findAllByProps({qux})).toHaveLength(3);
});

it('skips special nodes', () => {
const render = ReactTestRenderer.create(<Example />);
expect(render.root.findAllByType(React.Fragment)).toHaveLength(0);
expect(render.root.findAllByType(Context.Consumer)).toHaveLength(0);
expect(render.root.findAllByType(Context.Provider)).toHaveLength(0);

const expectedParent = render.root.findByProps({foo: 'foo'}, {deep: false})
.children[0];
const nestedViews = render.root.findAllByProps(
{nested: true},
{deep: false},
);
expect(nestedViews.length).toBe(3);
expect(nestedViews[0].parent).toBe(expectedParent);
expect(nestedViews[1].parent).toBe(expectedParent);
expect(nestedViews[2].parent).toBe(expectedParent);
});
});

0 comments on commit 7dc1a17

Please sign in to comment.