html_matchers 0.0.1
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/.gitignore +1 -0
- data/MIT-LICENSE +20 -0
- data/README +25 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/init.rb +2 -0
- data/install.rb +1 -0
- data/lib/.gitignore +1 -0
- data/lib/html_matchers.rb +60 -0
- data/lib/matchers/.gitignore +1 -0
- data/lib/matchers/button_matcher.rb +33 -0
- data/lib/matchers/check_box_group_matcher.rb +42 -0
- data/lib/matchers/drop_down_matcher.rb +43 -0
- data/lib/matchers/image_matcher.rb +32 -0
- data/lib/matchers/options_matcher.rb +29 -0
- data/lib/matchers/radio_group_matcher.rb +32 -0
- data/lib/matchers/span_text_matcher.rb +31 -0
- data/lib/matchers/table_body_matcher.rb +39 -0
- data/lib/matchers/table_header_matcher.rb +43 -0
- data/lib/matchers/table_matcher.rb +57 -0
- data/lib/matchers/td_link_matcher.rb +30 -0
- data/spec/button_matcher_spec.rb +59 -0
- data/spec/check_box_group_matcher_spec.rb +58 -0
- data/spec/drop_down_matcher_spec.rb +48 -0
- data/spec/image_matcher_spec.rb +34 -0
- data/spec/radio_group_matcher_spec.rb +39 -0
- data/spec/span_text_matcher_spec.rb +39 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/table_body_matcher_spec.rb +77 -0
- data/spec/table_header_matcher_spec.rb +111 -0
- data/spec/table_matcher_spec.rb +117 -0
- data/tasks/.gitignore +1 -0
- data/tasks/html_matchers_tasks.rake +4 -0
- data/uninstall.rb +1 -0
- metadata +105 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.svn
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 [name of plugin creator]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
HtmlMatchers
|
2
|
+
============
|
3
|
+
|
4
|
+
This Rails plugin provides a layer of abstraction on top of Rspec for testing
|
5
|
+
HTML contents.
|
6
|
+
|
7
|
+
It depends on Rspec and Hpricot: rspec, and rspec-rails because enhancing them
|
8
|
+
is the whole point of this plugin, and Hpricot because I find it so much more
|
9
|
+
capable, and faster than the assert_select that is built into Rails.
|
10
|
+
|
11
|
+
Using from Cucumber
|
12
|
+
===================
|
13
|
+
|
14
|
+
Add require 'cucumber/rails/rspec' to features/support/env.rb.
|
15
|
+
|
16
|
+
This is important, so that rspec matchers are in play.
|
17
|
+
|
18
|
+
|
19
|
+
Example
|
20
|
+
=======
|
21
|
+
|
22
|
+
Example goes here.
|
23
|
+
|
24
|
+
|
25
|
+
Copyright (c) 2008 [name of plugin creator], released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
# require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
desc 'Default: run spec tests.'
|
7
|
+
task :default => :spec
|
8
|
+
|
9
|
+
desc "Run all specs"
|
10
|
+
Spec::Rake::SpecTask.new do |t|
|
11
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
12
|
+
t.spec_opts = ['--options', 'spec/spec.opts']
|
13
|
+
# unless ENV['NO_RCOV']
|
14
|
+
# t.rcov = true
|
15
|
+
# t.rcov_dir = 'coverage'
|
16
|
+
# t.rcov_opts = ['--exclude', 'lib/spec.rb,lib/spec/runner.rb,spec\/spec,bin\/spec,examples,\/var\/lib\/gems,\/Library\/Ruby,\.autotest']
|
17
|
+
# end
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Generate documentation for the html_matchers plugin.'
|
21
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
22
|
+
rdoc.rdoc_dir = 'rdoc'
|
23
|
+
rdoc.title = 'HtmlMatchers'
|
24
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
25
|
+
rdoc.rdoc_files.include('README')
|
26
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'jeweler'
|
31
|
+
Jeweler::Tasks.new do |gemspec|
|
32
|
+
gemspec.name = "html_matchers"
|
33
|
+
gemspec.summary = "HTML entity matchers for RSpec"
|
34
|
+
gemspec.description = "HTML entity matchers for RSpec"
|
35
|
+
gemspec.email = "stephen@bendyworks.com"
|
36
|
+
gemspec.homepage = "http://github.com/bendyworks/html_matchers"
|
37
|
+
gemspec.authors = ["bendycode, helabed, listrophy"]
|
38
|
+
end
|
39
|
+
Jeweler::GemcutterTasks.new
|
40
|
+
rescue LoadError
|
41
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
42
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/init.rb
ADDED
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
data/lib/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.svn
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'hpricot'
|
2
|
+
|
3
|
+
# %w(check_box_group drop_down radio_group span_text table_body table_header td_link).each do |element|
|
4
|
+
# require File.join(File.dirname(__FILE__), 'matchers', "#{element}_matcher")
|
5
|
+
# end
|
6
|
+
|
7
|
+
Dir.glob(File.dirname(__FILE__) + '/matchers/*.rb').each do |rb|
|
8
|
+
require rb
|
9
|
+
end
|
10
|
+
|
11
|
+
module Spec # :nodoc:
|
12
|
+
module Rails
|
13
|
+
module Matchers
|
14
|
+
|
15
|
+
def have_button expected
|
16
|
+
ButtonMatcher.new expected
|
17
|
+
end
|
18
|
+
|
19
|
+
def have_check_box_group target_name, expected
|
20
|
+
CheckBoxGroupMatcher.new target_name, expected
|
21
|
+
end
|
22
|
+
|
23
|
+
def have_dropdown target_id, expected_options
|
24
|
+
DropDownMatcher.new target_id, expected_options
|
25
|
+
end
|
26
|
+
|
27
|
+
def have_image expected_path
|
28
|
+
ImageMatcher.new expected_path
|
29
|
+
end
|
30
|
+
|
31
|
+
def have_options expected_options
|
32
|
+
OptionsMatcher.new expected_options
|
33
|
+
end
|
34
|
+
|
35
|
+
def have_radio_group target_name, expected_radio_choices
|
36
|
+
RadioGroupMatcher.new target_name, expected_radio_choices
|
37
|
+
end
|
38
|
+
|
39
|
+
def have_span_text target_id, expected_text
|
40
|
+
SpanTextMatcher.new target_id, expected_text
|
41
|
+
end
|
42
|
+
|
43
|
+
def have_table table_id_or_expected, expected = nil
|
44
|
+
TableMatcher.new table_id_or_expected, expected
|
45
|
+
end
|
46
|
+
|
47
|
+
def have_table_header table_id_or_expected, expected = nil
|
48
|
+
TableHeaderMatcher.new table_id_or_expected, expected
|
49
|
+
end
|
50
|
+
|
51
|
+
def have_table_body table_id_or_expected, expected = nil
|
52
|
+
TableBodyMatcher.new table_id_or_expected, expected
|
53
|
+
end
|
54
|
+
|
55
|
+
def have_td_link target_id, expected_link, expected_text
|
56
|
+
TdLinkMatcher.new target_id, expected_link, expected_text
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
.svn
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Spec # :nodoc:
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
class ButtonMatcher
|
5
|
+
def initialize expected_value
|
6
|
+
# @target_id = target_id
|
7
|
+
@expected = expected_value
|
8
|
+
end
|
9
|
+
|
10
|
+
def matches? response
|
11
|
+
@actual = extract_html_content response.body
|
12
|
+
@actual == @expected
|
13
|
+
end
|
14
|
+
|
15
|
+
def failure_message
|
16
|
+
"\nWrong button value.\nexpected: #{@expected.inspect}\n found: #{@actual.inspect}\n\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
def negative_failure_message
|
20
|
+
"\nShould not have matched button: #{@target_id}, with text: '#{@expected}'\n\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
def extract_html_content html
|
24
|
+
doc = Hpricot.XML(html)
|
25
|
+
# elements = doc.search("//input[@value='#{@expected}' & @type='button|submit']")
|
26
|
+
# elements = doc.search("input[@value~='#{@expected}'][@type]")
|
27
|
+
elements = doc.search("//input[@value='#{@expected}']").select{|e| ['submit', 'button'].include?(e['type'])}
|
28
|
+
elements.map{|n| n['value']}.first
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Spec # :nodoc:
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
class CheckBoxGroupMatcher
|
5
|
+
|
6
|
+
def initialize target_name, expected
|
7
|
+
@expected = expected
|
8
|
+
@target_name = target_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches? response
|
12
|
+
@actual = extract_html_content response.body
|
13
|
+
@actual == @expected
|
14
|
+
end
|
15
|
+
|
16
|
+
def failure_message
|
17
|
+
"\nWrong check box group contents.\nexpected: #{@expected.inspect}\n found: #{@actual.inspect}\n\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
def negative_failure_message
|
21
|
+
"\nShould not have matched check box group: name: #{@target_name}, with: #{@expected.inspect}\n\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
def extract_html_content html
|
25
|
+
doc = Hpricot.XML(html)
|
26
|
+
# elements = doc.search('div input[type="checkbox"]')
|
27
|
+
elements = doc.search('div/input')
|
28
|
+
elements = elements.select{|n| n.elem? && n.get_attribute('type') == 'checkbox' && n.get_attribute('name') == @target_name}
|
29
|
+
elements.map{|n| value = n.get_attribute('value'); [value, find_label(n)]}
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def find_label node
|
35
|
+
label_node = node.next_sibling
|
36
|
+
label_node.inner_text
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Spec # :nodoc:
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
class DropDownMatcher
|
5
|
+
|
6
|
+
def initialize target_id, expected
|
7
|
+
@target_id = target_id
|
8
|
+
@expected = expected
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches? response
|
12
|
+
@actual = extract_html_content response.body
|
13
|
+
@actual == @expected
|
14
|
+
end
|
15
|
+
|
16
|
+
def failure_message
|
17
|
+
if @found_select
|
18
|
+
"\nWrong '#{@target_id}' drop down contents.\nexpected: #{@expected.inspect}\n found: #{@actual.inspect}\n\n"
|
19
|
+
else
|
20
|
+
"\nCould not find a select element with id: '#{@target_id}'\n\n"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def negative_failure_message
|
25
|
+
"\nShould not have matched dropdown with id: #{@target_id}\n\tand contents: #{@expected.inspect}\n\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def extract_html_content html
|
29
|
+
doc = Hpricot.XML(html)
|
30
|
+
select = doc.search("select##{@target_id}")
|
31
|
+
@found_select = ! select.empty?
|
32
|
+
|
33
|
+
if @found_select
|
34
|
+
select.search("/option").map{|n| n.inner_text.strip}
|
35
|
+
else
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Spec # :nodoc:
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
class ImageMatcher
|
5
|
+
def initialize expected_path
|
6
|
+
@expected = expected_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches? response
|
10
|
+
@actual = extract_html_content response.body
|
11
|
+
@actual =~ /#{@expected}/
|
12
|
+
end
|
13
|
+
|
14
|
+
def failure_message
|
15
|
+
"\nWrong image path.\nexpected: #{@expected.inspect}\n found: #{@actual.inspect}\n\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
def negative_failure_message
|
19
|
+
"\nShould not have matched image with path: '#{@expected}'\n\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
def extract_html_content html
|
23
|
+
doc = Hpricot.XML(html)
|
24
|
+
elements = doc.search("img[@src*=\"#{@expected}\"]")
|
25
|
+
# elements.each {|e| puts e.inspect}
|
26
|
+
# elements.first.to_html
|
27
|
+
elements.map{|n| n.to_html}.first
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Spec # :nodoc:
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
class OptionsMatcher
|
5
|
+
def initialize expected
|
6
|
+
@expected = expected
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches? response
|
10
|
+
@actual = extract_html_content response.body
|
11
|
+
@actual == @expected
|
12
|
+
end
|
13
|
+
|
14
|
+
def failure_message
|
15
|
+
"\nWrong option contents.\nexpected: #{@expected.inspect}\n found: #{@actual.inspect}\n\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
def negative_failure_message
|
19
|
+
"\nShould not have matched contents: #{@expected.inspect}\n\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
def extract_html_content html
|
23
|
+
doc = Hpricot.XML(html)
|
24
|
+
doc.search("/option").map{|n| n.inner_text.strip}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Spec # :nodoc:
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
class RadioGroupMatcher
|
5
|
+
def initialize target_name, expected
|
6
|
+
@expected = expected
|
7
|
+
@target_name = target_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def matches? response
|
11
|
+
@actual = extract_html_content response.body
|
12
|
+
@actual == @expected
|
13
|
+
end
|
14
|
+
|
15
|
+
def failure_message
|
16
|
+
"\nWrong radio group contents.\nexpected: #{@expected.inspect}\n found: #{@actual.inspect}\n\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
def negative_failure_message
|
20
|
+
"\nShould not have matched radio group: name: #{@target_name}, with: #{@expected.inspect}\n\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
def extract_html_content html
|
24
|
+
doc = Hpricot.XML(html)
|
25
|
+
elements = doc.search('input')
|
26
|
+
elements = elements.select{|n| n.elem? && n.get_attribute('name') == @target_name}
|
27
|
+
elements.map{|n| n.get_attribute('value')}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Spec # :nodoc:
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
class SpanTextMatcher
|
5
|
+
def initialize target_id, expected_text
|
6
|
+
@target_id = target_id
|
7
|
+
@expected = expected_text
|
8
|
+
end
|
9
|
+
|
10
|
+
def matches? response
|
11
|
+
@actual = extract_html_content response.body
|
12
|
+
@actual == @expected
|
13
|
+
end
|
14
|
+
|
15
|
+
def failure_message
|
16
|
+
"\nWrong span text contents.\nexpected: #{@expected.inspect}\n found: #{@actual.inspect}\n\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
def negative_failure_message
|
20
|
+
"\nShould not have matched span: #{@target_id}, with text: '#{@expected}'\n\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
def extract_html_content html
|
24
|
+
doc = Hpricot.XML(html)
|
25
|
+
elements = doc.search("p span##{@target_id}")
|
26
|
+
elements.map{|n| n.inner_text.strip}.first
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Spec # :nodoc:
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
class TableBodyMatcher
|
5
|
+
|
6
|
+
def initialize table_id_or_expected, expected
|
7
|
+
case table_id_or_expected
|
8
|
+
when String
|
9
|
+
@table_id = table_id_or_expected
|
10
|
+
@expected = expected
|
11
|
+
when Array
|
12
|
+
@expected = table_id_or_expected
|
13
|
+
end
|
14
|
+
raise 'Invalid "expected" argument' if @expected.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches? response
|
18
|
+
@actual = extract_html_content response.body
|
19
|
+
@actual == @expected
|
20
|
+
end
|
21
|
+
|
22
|
+
def failure_message
|
23
|
+
"\nWrong table body contents.\nexpected: #{@expected.inspect}\n found: #{@actual.inspect}\n\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
def negative_failure_message
|
27
|
+
"\nTable body should not have matched: #{@expected.inspect}\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
def extract_html_content html
|
31
|
+
doc = Hpricot.XML(html)
|
32
|
+
elements = doc.search("table#{"##{@table_id}" if @table_id} tr").reject{|e| e.search('td').empty? }
|
33
|
+
elements.map{|n| n.search('/td').map{|n| n.inner_text.strip.gsub(/[ \t]*\n[\n \t]*/, "\n")}}
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|