fnando-rspec-hpricot-matchers 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +117 -0
- data/Rakefile +34 -0
- data/VERSION +1 -0
- data/lib/rspec-hpricot-matchers.rb +16 -0
- data/lib/rspec-hpricot-matchers/base.rb +109 -0
- data/lib/rspec-hpricot-matchers/have_node.rb +16 -0
- data/lib/rspec-hpricot-matchers/have_tag.rb +16 -0
- data/lib/rspec-hpricot-matchers/matchers.rb +11 -0
- data/rspec-hpricot-matchers.gemspec +51 -0
- data/spec/rspec-hpricot-matchers/have_tag_spec.rb +251 -0
- data/spec/spec_helper.rb +10 -0
- metadata +72 -0
data/README.markdown
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
Rspec Hpricot Matchers
|
2
|
+
======================
|
3
|
+
|
4
|
+
This is a <http://github.com/pd/rspec_hpricot_matchers> "switch back to hpricot" port.
|
5
|
+
|
6
|
+
Install
|
7
|
+
-------
|
8
|
+
|
9
|
+
On Ruby projects:
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
require "spec"
|
13
|
+
require "rspec-hpricot-matchers"
|
14
|
+
|
15
|
+
Spec::Runner.configure do |config|
|
16
|
+
config.include(HpricotSpec::Matchers)
|
17
|
+
end
|
18
|
+
|
19
|
+
On Rails projects:
|
20
|
+
|
21
|
+
# using as plugin
|
22
|
+
script/plugin install git://github.com/fnando/rspec-hpricot-matchers.git
|
23
|
+
|
24
|
+
# using as gem
|
25
|
+
# on config/environments/test.rb
|
26
|
+
config.gem "fnando-rspec-hpricot-matchers",
|
27
|
+
:lib => "rspec-hpricot-matchers",
|
28
|
+
:source => "http://gems.github.com"
|
29
|
+
|
30
|
+
# then on spec/spec_helper.rb
|
31
|
+
Spec::Runner.configure do |config|
|
32
|
+
config.include HpricotSpec::Matchers
|
33
|
+
end
|
34
|
+
|
35
|
+
FAQ
|
36
|
+
---
|
37
|
+
|
38
|
+
### Why switching back to Hpricot?
|
39
|
+
|
40
|
+
I personally don't use Nokogiri, so it makes no sense to install it just for testing.
|
41
|
+
|
42
|
+
### What kind of selectors can I use?
|
43
|
+
|
44
|
+
Check it out the [Hpricot wiki](http://wiki.github.com/why/hpricot/supported-css-selectors) for supported selectors.
|
45
|
+
|
46
|
+
|
47
|
+
Usage:
|
48
|
+
------
|
49
|
+
|
50
|
+
HTML content:
|
51
|
+
|
52
|
+
html = <<-HTML
|
53
|
+
<ul>
|
54
|
+
<li>Item 1</li>
|
55
|
+
<li>
|
56
|
+
<a href="http://simplesideias.com.br" rel="external">
|
57
|
+
Simples Ideias
|
58
|
+
</a>
|
59
|
+
</li>
|
60
|
+
</ul>
|
61
|
+
HTML
|
62
|
+
|
63
|
+
html.should have_tag("li", :count => 2)
|
64
|
+
html.should have_tag("ul > li", :minimum => :1)
|
65
|
+
html.should have_tag("ul > li", :maximum => :2)
|
66
|
+
html.should have_tag("a[@rel='external']", /Simples Ideias/)
|
67
|
+
|
68
|
+
XML content:
|
69
|
+
|
70
|
+
xml = <<-XML
|
71
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
72
|
+
<content>
|
73
|
+
<item type="html">
|
74
|
+
<a href="http://simplesideias.com.br">
|
75
|
+
Simples Ideias
|
76
|
+
</a>
|
77
|
+
</item>
|
78
|
+
<item type="text"><![CDATA[Some text]]></item>
|
79
|
+
</content>
|
80
|
+
XML
|
81
|
+
|
82
|
+
xml.should have_node("item", :count => 2)
|
83
|
+
xml.should have_node("content > item", /Some text/, :count => 1)
|
84
|
+
|
85
|
+
Running Rpec Hpricot Matchers tests
|
86
|
+
-----------------------------------
|
87
|
+
|
88
|
+
rake spec
|
89
|
+
|
90
|
+
MAINTAINER
|
91
|
+
----------
|
92
|
+
|
93
|
+
* Nando Vieira (<http://simplesideias.com.br>)
|
94
|
+
|
95
|
+
LICENSE:
|
96
|
+
--------
|
97
|
+
|
98
|
+
(The MIT License)
|
99
|
+
|
100
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
101
|
+
a copy of this software and associated documentation files (the
|
102
|
+
'Software'), to deal in the Software without restriction, including
|
103
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
104
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
105
|
+
permit persons to whom the Software is furnished to do so, subject to
|
106
|
+
the following conditions:
|
107
|
+
|
108
|
+
The above copyright notice and this permission notice shall be
|
109
|
+
included in all copies or substantial portions of the Software.
|
110
|
+
|
111
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
112
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
113
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
114
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
115
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
116
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
117
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "jeweler"
|
3
|
+
require "spec/rake/spectask"
|
4
|
+
|
5
|
+
RELEASE_VERSION = "0.0.2"
|
6
|
+
|
7
|
+
JEWEL = Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "rspec-hpricot-matchers"
|
9
|
+
gem.version = RELEASE_VERSION
|
10
|
+
gem.summary = "Replace have_tag to enable advanced selectors using Hpricot"
|
11
|
+
gem.description = <<-TXT
|
12
|
+
A http://github.com/pd/rspec_hpricot_matchers 'switch back to hpricot' port
|
13
|
+
TXT
|
14
|
+
|
15
|
+
gem.authors = ["Nando Vieira"]
|
16
|
+
gem.email = "fnando.vieira@gmail.com"
|
17
|
+
gem.homepage = "http://github.com/fnando/rspec-hpricot-matchers"
|
18
|
+
|
19
|
+
gem.has_rdoc = false
|
20
|
+
gem.files = %w(Rakefile rspec-hpricot-matchers.gemspec VERSION README.markdown) + Dir["{lib,templates}/**/*"]
|
21
|
+
|
22
|
+
gem.add_dependency "hpricot"
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Generate gemspec, build and install the gem"
|
26
|
+
task :package do
|
27
|
+
File.open("VERSION", "w+") {|f| f << RELEASE_VERSION }
|
28
|
+
|
29
|
+
Rake::Task["gemspec"].invoke
|
30
|
+
Rake::Task["build"].invoke
|
31
|
+
Rake::Task["install"].invoke
|
32
|
+
end
|
33
|
+
|
34
|
+
Spec::Rake::SpecTask.new {|t| t.spec_opts = ["-c", "-f s"] }
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.2
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "spec"
|
3
|
+
require "hpricot"
|
4
|
+
|
5
|
+
module Hpricot
|
6
|
+
class Elem
|
7
|
+
alias body inner_html
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
12
|
+
|
13
|
+
require "rspec-hpricot-matchers/base"
|
14
|
+
require "rspec-hpricot-matchers/have_tag"
|
15
|
+
require "rspec-hpricot-matchers/have_node"
|
16
|
+
require "rspec-hpricot-matchers/matchers"
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module HpricotSpec
|
2
|
+
class Base
|
3
|
+
attr_reader :options
|
4
|
+
attr_reader :selector
|
5
|
+
attr_reader :actual
|
6
|
+
attr_reader :actual_count
|
7
|
+
attr_reader :doc
|
8
|
+
|
9
|
+
def initialize(selector, inner_text_or_options, options={}, &block)
|
10
|
+
@selector = selector
|
11
|
+
|
12
|
+
if Hash === inner_text_or_options
|
13
|
+
@options = inner_text_or_options
|
14
|
+
else
|
15
|
+
@options = options
|
16
|
+
options[:text] = inner_text_or_options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def matches?(_actual, &block)
|
21
|
+
@actual = _actual
|
22
|
+
@doc = doc_for(actual)
|
23
|
+
|
24
|
+
matches = doc.search(selector)
|
25
|
+
|
26
|
+
if matches.empty?
|
27
|
+
return options[:count] == 0
|
28
|
+
end
|
29
|
+
|
30
|
+
if options[:text]
|
31
|
+
matches = filter_on_inner_text(matches)
|
32
|
+
end
|
33
|
+
|
34
|
+
if block
|
35
|
+
matches = filter_on_nested_expectations(matches, block)
|
36
|
+
end
|
37
|
+
|
38
|
+
@actual_count = matches.size
|
39
|
+
|
40
|
+
return false if not acceptable_count?(actual_count)
|
41
|
+
|
42
|
+
!matches.empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
def failure_message
|
46
|
+
explanation = actual_count ? "but found #{actual_count}" : "but did not"
|
47
|
+
"expected\n#{doc.to_s}\nto have #{failure_count_phrase} #{failure_selector_phrase}, #{explanation}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def negative_failure_message
|
51
|
+
explanation = actual_count ? "but found #{actual_count}" : "but did"
|
52
|
+
"expected\n#{doc.to_s}\nnot to have #{failure_count_phrase} #{failure_selector_phrase}, #{explanation}"
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def filter_on_inner_text(elements)
|
57
|
+
elements.select do |el|
|
58
|
+
next(el.inner_text =~ options[:text]) if options[:text].is_a?(Regexp)
|
59
|
+
el.inner_text == options[:text]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def filter_on_nested_expectations(elements, block)
|
64
|
+
elements.select do |el|
|
65
|
+
begin
|
66
|
+
block.call(el)
|
67
|
+
rescue Spec::Expectations::ExpectationNotMetError
|
68
|
+
false
|
69
|
+
else
|
70
|
+
true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def acceptable_count?(count)
|
76
|
+
if options[:count]
|
77
|
+
return false unless options[:count] === count
|
78
|
+
end
|
79
|
+
|
80
|
+
if options[:minimum]
|
81
|
+
return false unless count >= options[:minimum]
|
82
|
+
end
|
83
|
+
|
84
|
+
if options[:maximum]
|
85
|
+
return false unless count <= options[:maximum]
|
86
|
+
end
|
87
|
+
|
88
|
+
true
|
89
|
+
end
|
90
|
+
|
91
|
+
def failure_count_phrase
|
92
|
+
if options[:count]
|
93
|
+
"#{options[:count]} elements matching"
|
94
|
+
elsif options[:minimum] || options[:maximum]
|
95
|
+
count_explanations = []
|
96
|
+
count_explanations << "at least #{options[:minimum]}" if options[:minimum]
|
97
|
+
count_explanations << "at most #{options[:maximum]}" if options[:maximum]
|
98
|
+
"#{count_explanations.join(' and ')} elements matching"
|
99
|
+
else
|
100
|
+
"an element matching"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def failure_selector_phrase
|
105
|
+
phrase = selector.inspect
|
106
|
+
phrase << (options[:text] ? " with inner text #{options[:text].inspect}" : "")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HpricotSpec
|
2
|
+
class HaveNode < Base
|
3
|
+
private
|
4
|
+
def doc_for(input)
|
5
|
+
if String === input
|
6
|
+
Hpricot.XML(input)
|
7
|
+
elsif input.respond_to?(:body)
|
8
|
+
Hpricot.XML(input.body.to_s)
|
9
|
+
elsif Hpricot::Elem === input
|
10
|
+
input
|
11
|
+
else
|
12
|
+
Hpricot.XML(input.to_s)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HpricotSpec
|
2
|
+
class HaveTag < Base
|
3
|
+
private
|
4
|
+
def doc_for(input)
|
5
|
+
if String === input
|
6
|
+
Hpricot(input)
|
7
|
+
elsif input.respond_to?(:body)
|
8
|
+
Hpricot(input.body.to_s)
|
9
|
+
elsif Hpricot::Elem === input
|
10
|
+
input
|
11
|
+
else
|
12
|
+
Hpricot(input.to_s)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module HpricotSpec
|
2
|
+
module Matchers
|
3
|
+
def have_tag(selector, inner_text_or_options=nil, options={}, &block)
|
4
|
+
HaveTag.new(selector, inner_text_or_options, options, &block)
|
5
|
+
end
|
6
|
+
|
7
|
+
def have_node(selector, inner_text_or_options=nil, options={}, &block)
|
8
|
+
HaveNode.new(selector, inner_text_or_options, options, &block)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{rspec-hpricot-matchers}
|
8
|
+
s.version = "0.0.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Nando Vieira"]
|
12
|
+
s.date = %q{2009-08-11}
|
13
|
+
s.description = %q{A http://github.com/pd/rspec_hpricot_matchers 'switch back to hpricot' port}
|
14
|
+
s.email = %q{fnando.vieira@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.markdown"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"README.markdown",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"lib/rspec-hpricot-matchers.rb",
|
23
|
+
"lib/rspec-hpricot-matchers/base.rb",
|
24
|
+
"lib/rspec-hpricot-matchers/have_node.rb",
|
25
|
+
"lib/rspec-hpricot-matchers/have_tag.rb",
|
26
|
+
"lib/rspec-hpricot-matchers/matchers.rb",
|
27
|
+
"rspec-hpricot-matchers.gemspec"
|
28
|
+
]
|
29
|
+
s.homepage = %q{http://github.com/fnando/rspec-hpricot-matchers}
|
30
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
31
|
+
s.require_paths = ["lib"]
|
32
|
+
s.rubygems_version = %q{1.3.1}
|
33
|
+
s.summary = %q{Replace have_tag to enable advanced selectors using Hpricot}
|
34
|
+
s.test_files = [
|
35
|
+
"spec/rspec-hpricot-matchers/have_tag_spec.rb",
|
36
|
+
"spec/spec_helper.rb"
|
37
|
+
]
|
38
|
+
|
39
|
+
if s.respond_to? :specification_version then
|
40
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
41
|
+
s.specification_version = 2
|
42
|
+
|
43
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
44
|
+
s.add_runtime_dependency(%q<hpricot>, [">= 0"])
|
45
|
+
else
|
46
|
+
s.add_dependency(%q<hpricot>, [">= 0"])
|
47
|
+
end
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<hpricot>, [">= 0"])
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,251 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
|
3
|
+
describe "have_tag" do
|
4
|
+
attr_reader :html
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@html = "<ul><li>An egregiously long string</li></ul>"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should match against strings" do
|
11
|
+
html.should have_tag("li")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should match against Hpricot::Elem" do
|
15
|
+
doc = Hpricot(html)
|
16
|
+
doc.search("li").should have_tag("li")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should match against Hpricot::Document" do
|
20
|
+
doc = Hpricot(html)
|
21
|
+
doc.should have_tag("li")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should match against the response of body method" do
|
25
|
+
OpenStruct.new(:body => html).should have_tag("li")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should match against the response of to_s method" do
|
29
|
+
[html].should have_tag("li")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not match when the target does not have the selected element" do
|
33
|
+
html.should_not have_tag("dd")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should match against the inner text of the selected element" do
|
37
|
+
html.should have_tag("li", "An egregiously long string")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should match negatively against the inner text" do
|
41
|
+
html.should_not have_tag("li", "Some other string entirely")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should match against a Regexp describing the inner text" do
|
45
|
+
html.should have_tag("li", /GREG/i)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should match negatively against a Regexp describing the inner text" do
|
49
|
+
html.should_not have_tag("li", /GREG/)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should include the body in the failure message" do
|
53
|
+
lambda {
|
54
|
+
html.should have_tag("abbr")
|
55
|
+
}.should raise_error(SpecFailed, /#{Regexp.escape(html)}/)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should include the selector in the failure message" do
|
59
|
+
lambda {
|
60
|
+
html.should have_tag("abbr")
|
61
|
+
}.should raise_error(SpecFailed, /"abbr"/)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should include the expected inner text if provided" do
|
65
|
+
lambda {
|
66
|
+
html.should have_tag("li", /something else/)
|
67
|
+
}.should raise_error(SpecFailed, %r{/something else/})
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "inner expectations" do
|
71
|
+
it "should fail when the outer selector fails" do
|
72
|
+
lambda {
|
73
|
+
html.should have_tag("dl") do |dl|
|
74
|
+
dl.should have_tag("li")
|
75
|
+
end
|
76
|
+
}.should raise_error(SpecFailed)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should match the inner expectations against the elements matched by the outer selector" do
|
80
|
+
html.should have_tag("ul") do |ul|
|
81
|
+
ul.should have_tag("li")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should support negated inner expectations" do
|
86
|
+
html.should have_tag("ul") do |ul|
|
87
|
+
ul.should_not have_tag("dd")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should treat multiple nested have_tag() expectations as a logical AND" do
|
92
|
+
html.should have_tag("ul") do |ul|
|
93
|
+
ul.should have_tag("li")
|
94
|
+
ul.should_not have_tag("dd")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should only match against a single element at a time when nesting expectations (see RSpec LH#316)" do
|
99
|
+
html = <<-EOHTML
|
100
|
+
<ul>
|
101
|
+
<li>
|
102
|
+
<a href="1">1</a>
|
103
|
+
</li>
|
104
|
+
<li>
|
105
|
+
<a href="2">2</a>
|
106
|
+
<span>Hello</span>
|
107
|
+
</li>
|
108
|
+
</ul>
|
109
|
+
EOHTML
|
110
|
+
|
111
|
+
html.should have_tag("li", :count => 1) do |li|
|
112
|
+
li.should have_tag("a")
|
113
|
+
li.should have_tag("span")
|
114
|
+
end
|
115
|
+
|
116
|
+
html.should have_tag("li", :count => 1) do |li|
|
117
|
+
li.should have_tag("a")
|
118
|
+
li.should_not have_tag("span")
|
119
|
+
end
|
120
|
+
|
121
|
+
html.should have_tag("li", :count => 2) do |li|
|
122
|
+
li.should have_tag("a")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should yield elements which respond to #body" do
|
127
|
+
html = <<-EOHTML
|
128
|
+
<ul>
|
129
|
+
<li>
|
130
|
+
<a href="1">1</a>
|
131
|
+
</li>
|
132
|
+
<li>
|
133
|
+
<a href="2">2</a>
|
134
|
+
<span>Hello</span>
|
135
|
+
</li>
|
136
|
+
</ul>
|
137
|
+
EOHTML
|
138
|
+
|
139
|
+
html.should have_tag("ul") do |ul|
|
140
|
+
ul.should respond_to(:body)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should supports arbitrary expectations within the block" do
|
145
|
+
html = %q{<span class="sha1">cbc0bd52f99fe19304bccad383694e92b8ee2c71</span>}
|
146
|
+
html.should have_tag("span.sha1") do |span|
|
147
|
+
span.inner_text.length.should == 40
|
148
|
+
end
|
149
|
+
|
150
|
+
html.should_not have_tag("span.sha1") do |span|
|
151
|
+
span.inner_text.length.should == 41
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "with counts" do
|
157
|
+
before(:each) do
|
158
|
+
@html = <<-EOHTML
|
159
|
+
<ul>
|
160
|
+
<li>Foo</li>
|
161
|
+
<li>Bar</li>
|
162
|
+
<li>Foo again</li>
|
163
|
+
<li><a href="/baz">With inner elements</a></li>
|
164
|
+
</ul>
|
165
|
+
EOHTML
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should treat an integer :count as expecting exactly n matched elements" do
|
169
|
+
html.should have_tag("li", :count => 4)
|
170
|
+
html.should_not have_tag("li", :count => 3)
|
171
|
+
html.should_not have_tag("li", :count => 5)
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should treat a range :count as expecting between x and y matched elements" do
|
175
|
+
html.should have_tag("li", :count => 1..5)
|
176
|
+
html.should_not have_tag("li", :count => 2..3)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should treat a :count of zero as if a negative match were expected" do
|
180
|
+
html.should have_tag("dd", :count => 0)
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should treat :minimum as expecting at least n matched elements" do
|
184
|
+
(0..4).each { |n| html.should have_tag("li", :minimum => n) }
|
185
|
+
html.should_not have_tag("li", :minimum => 5)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should treat :maximum as expecting at most n matched elements" do
|
189
|
+
html.should_not have_tag("li", :maximum => 3)
|
190
|
+
html.should have_tag("li", :maximum => 4)
|
191
|
+
html.should have_tag("li", :maximum => 5)
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should support matching of content while specifying a count" do
|
195
|
+
html.should have_tag("li", /foo/i, :count => 2)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should work when the have_tag is nested" do
|
199
|
+
html.should have_tag("ul") do |ul|
|
200
|
+
ul.should have_tag("li", :minimum => 2)
|
201
|
+
ul.should have_tag("li", /foo/i, :count => 2)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should include the actual number of elements matched in the failure message" do
|
206
|
+
lambda {
|
207
|
+
html.should have_tag("li", :count => 3)
|
208
|
+
}.should raise_error(SpecFailed, /found 4/)
|
209
|
+
|
210
|
+
lambda {
|
211
|
+
html.should have_tag("li", :count => 5)
|
212
|
+
}.should raise_error(SpecFailed, /found 4/)
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should include the actual number of elements matched in the negative failure message" do
|
216
|
+
lambda {
|
217
|
+
html.should_not have_tag("li", :count => 4)
|
218
|
+
}.should raise_error(SpecFailed, /found 4/)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should include the expected number of elements in the failure message" do
|
222
|
+
lambda {
|
223
|
+
html.should have_tag("li", :count => 2)
|
224
|
+
}.should raise_error(SpecFailed, /to have 2 elements matching/)
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should include the expected number of elements in the negative failure message" do
|
228
|
+
lambda {
|
229
|
+
html.should_not have_tag("li", :count => 4)
|
230
|
+
}.should raise_error(SpecFailed, /to have 4 elements matching/)
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should describe the :minimum case using 'at least ...'" do
|
234
|
+
lambda {
|
235
|
+
html.should have_tag("li", :minimum => 80)
|
236
|
+
}.should raise_error(SpecFailed, /to have at least 80 elements matching/)
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should describe the :maximum case using 'at most ...'" do
|
240
|
+
lambda {
|
241
|
+
html.should have_tag("li", :maximum => 2)
|
242
|
+
}.should raise_error(SpecFailed, /to have at most 2 elements matching/)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should describe the :minimum and :maximum case using 'at least ... and at most ...'" do
|
246
|
+
lambda {
|
247
|
+
html.should have_tag("li", :minimum => 8, :maximum => 30)
|
248
|
+
}.should raise_error(SpecFailed, /to have at least 8 and at most 30 elements matching/)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../lib/rspec-hpricot-matchers"
|
2
|
+
require "ostruct"
|
3
|
+
|
4
|
+
Spec::Runner.configure do |config|
|
5
|
+
config.include(HpricotSpec::Matchers)
|
6
|
+
end
|
7
|
+
|
8
|
+
unless defined?(SpecFailed)
|
9
|
+
SpecFailed = Spec::Expectations::ExpectationNotMetError
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fnando-rspec-hpricot-matchers
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nando Vieira
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-11 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hpricot
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: A http://github.com/pd/rspec_hpricot_matchers 'switch back to hpricot' port
|
26
|
+
email: fnando.vieira@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.markdown
|
33
|
+
files:
|
34
|
+
- README.markdown
|
35
|
+
- Rakefile
|
36
|
+
- VERSION
|
37
|
+
- lib/rspec-hpricot-matchers.rb
|
38
|
+
- lib/rspec-hpricot-matchers/base.rb
|
39
|
+
- lib/rspec-hpricot-matchers/have_node.rb
|
40
|
+
- lib/rspec-hpricot-matchers/have_tag.rb
|
41
|
+
- lib/rspec-hpricot-matchers/matchers.rb
|
42
|
+
- rspec-hpricot-matchers.gemspec
|
43
|
+
has_rdoc: false
|
44
|
+
homepage: http://github.com/fnando/rspec-hpricot-matchers
|
45
|
+
licenses:
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --charset=UTF-8
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.5
|
67
|
+
signing_key:
|
68
|
+
specification_version: 2
|
69
|
+
summary: Replace have_tag to enable advanced selectors using Hpricot
|
70
|
+
test_files:
|
71
|
+
- spec/rspec-hpricot-matchers/have_tag_spec.rb
|
72
|
+
- spec/spec_helper.rb
|