diff --git a/src/MountedTraversal.js b/src/MountedTraversal.js index e458f60e9..88a88fd82 100644 --- a/src/MountedTraversal.js +++ b/src/MountedTraversal.js @@ -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); @@ -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); -} diff --git a/src/ReactWrapper.jsx b/src/ReactWrapper.jsx index 75bb8abe0..f73f5dbbb 100644 --- a/src/ReactWrapper.jsx +++ b/src/ReactWrapper.jsx @@ -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; } diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index dd67a9503..4c7a8b64a 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -1950,7 +1950,7 @@ 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(
@@ -1958,6 +1958,9 @@ describeWithDOM('mount', () => {
+
+
+
, ); diff --git a/test/ShallowWrapper-spec.jsx b/test/ShallowWrapper-spec.jsx index abdb8f486..750c93cda 100644 --- a/test/ShallowWrapper-spec.jsx +++ b/test/ShallowWrapper-spec.jsx @@ -1785,7 +1785,7 @@ 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(
@@ -1793,6 +1793,9 @@ describe('shallow', () => {
+
+
+
, ); @@ -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', () => {