From 52a4375278f911a9cfdcaf88ce1757ba841c7e14 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 30 Jul 2014 00:16:44 +0200 Subject: [PATCH] Prepare setup for *actual* following support. The previous commit was nonsense as I didn't understand XPath's "following" axis properly. This commit introduces proper tests and a note for future me so that I can implement it properly. --- lib/oga/xpath/evaluator.rb | 18 +++---- .../xpath/evaluator/axes/following_spec.rb | 54 +++++++++++++------ 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/lib/oga/xpath/evaluator.rb b/lib/oga/xpath/evaluator.rb index 9f161f8..e97c3fa 100644 --- a/lib/oga/xpath/evaluator.rb +++ b/lib/oga/xpath/evaluator.rb @@ -254,17 +254,13 @@ module Oga context.each do |context_node| current = context_node - while current.respond_to?(:next) - next_node = current.next - - if can_match_node?(next_node) and node_matches?(next_node, node) - nodes << next_node - end - - # When this returns nil the loop automaticall breaks since `nil` - # doesn't respond to `next`. - current = next_node - end + # TODO: implement me properly this time. + # + # Step 1: gather *all* the nodes that come after the current node, + # regardless of their nesting. + # + # Step 2: compare all those nodes with the given test, only return + # those that match. end return nodes diff --git a/spec/oga/xpath/evaluator/axes/following_spec.rb b/spec/oga/xpath/evaluator/axes/following_spec.rb index a701b10..7684326 100644 --- a/spec/oga/xpath/evaluator/axes/following_spec.rb +++ b/spec/oga/xpath/evaluator/axes/following_spec.rb @@ -3,45 +3,65 @@ require 'spec_helper' describe Oga::XPath::Evaluator do context 'following axis' do before do - document = parse('') + # Strip whitespace so it's easier to retrieve/compare elements. + @document = parse(<<-EOF.strip.gsub(/\s+/m, '')) + + + + + + + + + + EOF - @first_c = document.children[0].children[1] - @second_c = document.children[0].children[2] - @evaluator = described_class.new(document) + @first_baz = @document.children[0].children[1] + @second_baz = @first_baz.children[0] + @third_baz = @document.children[0].children[0].children[1] + @evaluator = described_class.new(@document) end # This should return an empty set since the document doesn't have any # following nodes. context 'using a document as the root' do before do - @set = @evaluator.evaluate('following::a') + @set = @evaluator.evaluate('following::foo') end it_behaves_like :empty_node_set end - context 'matching following elements using a name' do + context 'matching nodes in the current context' do before do - @set = @evaluator.evaluate('a/b/following::c') + @set = @evaluator.evaluate('root/foo/following::baz') end - it_behaves_like :node_set, :length => 2 + it_behaves_like :node_set, :length => 1 - example 'return the first node' do - @set[0].should == @first_c - end - - example 'return the second node' do - @set[1].should == @second_c + example 'return the second node' do + @set[0].should == @first_baz end end - context 'matching following elements using a wildcard' do + context 'matching nodes in other contexts' do before do - @set = @evaluator.evaluate('a/b/following::*') + @set = @evaluator.evaluate('root/foo/bar/following::baz') end - it_behaves_like :node_set, :length => 2 + it_behaves_like :node_set, :length => 3 + + example 'return the first node' do + @set[0].should == @first_baz + end + + example 'return the second node' do + @set[1].should == @second_baz + end + + example 'return the third node' do + @set[2].should == @third_baz + end end end end