diff --git a/src/collections/Node.js b/src/collections/Node.js index a9e8e890..b1ee3d0b 100644 --- a/src/collections/Node.js +++ b/src/collections/Node.js @@ -77,8 +77,10 @@ var traversalMethods = { var parent = path.parent; while ( parent && - !type.check(parent.value) && - !(filter && matchNode(parent.value, filter)) + !( + type.check(parent.value) && + (!filter || matchNode(parent.value, filter)) + ) ) { parent = parent.parent; } diff --git a/src/collections/__tests__/Node-test.js b/src/collections/__tests__/Node-test.js index d0b018e2..71d87037 100644 --- a/src/collections/__tests__/Node-test.js +++ b/src/collections/__tests__/Node-test.js @@ -130,23 +130,14 @@ describe('Collection API', function() { }); describe('closest', function() { - it('finds closest node (up the tree) of the given type', function() { - var functionDeclaration = ast.body[1]; - var decl = Collection.fromNodes([ast]) - .find(types.Identifier) - .closest(types.FunctionDeclaration); - - expect(decl.size()).toBe(1); - expect(decl.nodes()[0]).toBe(functionDeclaration); - }); - - it('allows to filter nodes by pattern', function() { - var decl = b.functionDeclaration( + var decl; + beforeEach(()=> { + decl = b.functionDeclaration( b.identifier('foo'), [], b.blockStatement([ b.functionDeclaration( - b.identifier('foo'), + b.identifier('bar'), [], b.blockStatement([ b.returnStatement( @@ -156,6 +147,19 @@ describe('Collection API', function() { ), ]) ); + }); + + it('finds closest node (up the tree) of the given type', function() { + var functionDeclaration = ast.body[1]; + decl = Collection.fromNodes([ast]) + .find(types.Identifier) + .closest(types.FunctionDeclaration); + + expect(decl.size()).toBe(1); + expect(decl.nodes()[0]).toBe(functionDeclaration); + }); + + it('allows to filter nodes by pattern', function() { var literals = Collection.fromNodes([decl]) .find(types.Literal); expect(literals.get(0).node.value).toBe(3); @@ -165,6 +169,28 @@ describe('Collection API', function() { ); expect(closest.get(0).node.id.name).toBe('foo'); }); + + it('allows to filter nodes with a filter function', function() { + var literals = Collection.fromNodes([decl]) + .find(types.Literal); + expect(literals.get(0).node.value).toBe(3); + var closest = literals.closest( + types.FunctionDeclaration, + (node) => node.id && node.id.name === 'foo' + ); + expect(closest.get(0).node.id.name).toBe('foo'); + }); + + it('fails when filter evaluates as false', function() { + var literals = Collection.fromNodes([decl]) + .find(types.Literal); + expect(literals.get(0).node.value).toBe(3); + var closest = literals.closest( + types.FunctionDeclaration, + (node) => node.id && node.id.name === 'blue' + ); + expect(closest.nodes().length).toBe(0); + }); }); describe('getVariableDeclarators', function() {