html_matchers 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|