Skip to content

Commit

Permalink
[Fix] mount: .parents() now filters out sibling path trees.
Browse files Browse the repository at this point in the history
Merge pull request #713 from just-boris/master
  • Loading branch information
ljharb authored Dec 2, 2016
2 parents 01f415c + 16e2a2e commit fae0293
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 61 deletions.
120 changes: 63 additions & 57 deletions src/MountedTraversal.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,77 @@ export function childrenOfInst(node) {
return childrenOfInstInternal(internalInstanceOrComponent(node));
}

// This function should be called with an "internal instance". Nevertheless, if it is
// called with a "public instance" instead, the function will call itself with the
// internal instance and return the proper result.
function findAllInRenderedTreeInternal(inst, test) {
if (!inst) {
return [];
}

if (!inst.getPublicInstance) {
const internal = internalInstance(inst);
return findAllInRenderedTreeInternal(internal, test);
}
const publicInst = inst.getPublicInstance() || inst._instance;
let ret = test(publicInst) ? [publicInst] : [];
const currentElement = inst._currentElement;
if (isDOMComponent(publicInst)) {
const renderedChildren = renderedChildrenOfInst(inst);
values(renderedChildren || {}).filter((node) => {
if (REACT013 && !node.getPublicInstance) {
return false;
}
return true;
}).forEach((node) => {
ret = ret.concat(findAllInRenderedTreeInternal(node, test));
});
} else if (
!REACT013 &&
isElement(currentElement) &&
typeof currentElement.type === 'function'
) {
ret = ret.concat(
findAllInRenderedTreeInternal(
inst._renderedComponent,
test,
),
);
} else if (
REACT013 &&
isCompositeComponent(publicInst)
) {
ret = ret.concat(
findAllInRenderedTreeInternal(
inst._renderedComponent,
test,
),
);
}
return ret;
}

// This function could be called with a number of different things technically, so we need to
// pass the *right* thing to our internal helper.
export function treeFilter(node, test) {
return findAllInRenderedTreeInternal(internalInstanceOrComponent(node), test);
}

function pathFilter(path, fn) {
return path.filter(tree => treeFilter(tree, fn).length !== 0);
}

export function pathToNode(node, root) {
const queue = [root];
const path = [];

const hasNode = testNode => node === testNode;

while (queue.length) {
const current = queue.pop();
const children = childrenOfInst(current);

if (current === node) return path;
if (current === node) return pathFilter(path, hasNode);

path.push(current);

Expand Down Expand Up @@ -232,59 +294,3 @@ export function buildInstPredicate(selector) {
throw new TypeError('Enzyme::Selector expects a string, object, or Component Constructor');
}
}

// This function should be called with an "internal instance". Nevertheless, if it is
// called with a "public instance" instead, the function will call itself with the
// internal instance and return the proper result.
function findAllInRenderedTreeInternal(inst, test) {
if (!inst) {
return [];
}

if (!inst.getPublicInstance) {
const internal = internalInstance(inst);
return findAllInRenderedTreeInternal(internal, test);
}
const publicInst = inst.getPublicInstance() || inst._instance;
let ret = test(publicInst) ? [publicInst] : [];
const currentElement = inst._currentElement;
if (isDOMComponent(publicInst)) {
const renderedChildren = renderedChildrenOfInst(inst);
values(renderedChildren || {}).filter((node) => {
if (REACT013 && !node.getPublicInstance) {
return false;
}
return true;
}).forEach((node) => {
ret = ret.concat(findAllInRenderedTreeInternal(node, test));
});
} else if (
!REACT013 &&
isElement(currentElement) &&
typeof currentElement.type === 'function'
) {
ret = ret.concat(
findAllInRenderedTreeInternal(
inst._renderedComponent,
test,
),
);
} else if (
REACT013 &&
isCompositeComponent(publicInst)
) {
ret = ret.concat(
findAllInRenderedTreeInternal(
inst._renderedComponent,
test,
),
);
}
return ret;
}

// This function could be called with a number of different things technically, so we need to
// pass the *right* thing to our internal helper.
export function treeFilter(node, test) {
return findAllInRenderedTreeInternal(internalInstanceOrComponent(node), test);
}
2 changes: 1 addition & 1 deletion src/ReactWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ class ReactWrapper {
*/
parents(selector) {
const allParents = this.wrap(
this.single('parents', n => parentsOfInst(n, this.root.getNode())),
this.single('parents', n => parentsOfInst(n, this.root.getNode())),
);
return selector ? allParents.filter(selector) : allParents;
}
Expand Down
5 changes: 4 additions & 1 deletion test/ReactWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1950,14 +1950,17 @@ describeWithDOM('mount', () => {
});

describe('.parents([selector])', () => {
it('should return an array of current nodes ancestors', () => {
it('should return an array of current node’s ancestors', () => {
const wrapper = mount(
<div className="bax">
<div className="foo">
<div className="bar">
<div className="baz" />
</div>
</div>
<div className="qux">
<div className="qoo" />
</div>
</div>,
);

Expand Down
6 changes: 4 additions & 2 deletions test/ShallowWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1785,14 +1785,17 @@ describe('shallow', () => {
});

describe('.parents([selector])', () => {
it('should return an array of current nodes ancestors', () => {
it('should return an array of current node’s ancestors', () => {
const wrapper = shallow(
<div className="bax">
<div className="foo">
<div className="bar">
<div className="baz" />
</div>
</div>
<div className="qux">
<div className="qoo" />
</div>
</div>,
);

Expand All @@ -1802,7 +1805,6 @@ describe('shallow', () => {
expect(parents.at(0).hasClass('bar')).to.equal(true);
expect(parents.at(1).hasClass('foo')).to.equal(true);
expect(parents.at(2).hasClass('bax')).to.equal(true);

});

it('should work for non-leaf nodes as well', () => {
Expand Down

0 comments on commit fae0293

Please sign in to comment.