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.
This commit is contained in:
Yorick Peterse 2014-07-30 00:16:44 +02:00
parent 9a97d936e3
commit 52a4375278
2 changed files with 44 additions and 28 deletions

View File

@ -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

View File

@ -3,45 +3,65 @@ require 'spec_helper'
describe Oga::XPath::Evaluator do
context 'following axis' do
before do
document = parse('<a><b></b><c></c><c></c></a>')
# Strip whitespace so it's easier to retrieve/compare elements.
@document = parse(<<-EOF.strip.gsub(/\s+/m, ''))
<root>
<foo>
<bar></bar>
<baz>
<baz></baz>
</baz>
</foo>
<baz></baz>
</root>
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 <c> node' do
@set[0].should == @first_c
end
example 'return the second <c> node' do
@set[1].should == @second_c
example 'return the second <baz> 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 <baz> node' do
@set[0].should == @first_baz
end
example 'return the second <baz> node' do
@set[1].should == @second_baz
end
example 'return the third <baz> node' do
@set[2].should == @third_baz
end
end
end
end