elabs_matchers 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/Gemfile.lock +37 -26
- data/README.md +57 -47
- data/development.txt +26 -0
- data/doc/ElabsMatchers/Helpers/Fixtures.html +33 -23
- data/doc/ElabsMatchers/Helpers/NormalizeKeys.html +222 -0
- data/doc/ElabsMatchers/Helpers/ReloadRecord.html +302 -0
- data/doc/ElabsMatchers/Helpers/SelectYearAndMonth.html +251 -0
- data/doc/ElabsMatchers/Helpers.html +29 -22
- data/doc/ElabsMatchers/Matchers/Allow/AllowMatcher.html +707 -0
- data/doc/ElabsMatchers/Matchers/Allow.html +229 -0
- data/doc/ElabsMatchers/Matchers/ContainHash/ContainHashMatcher.html +506 -0
- data/doc/ElabsMatchers/Matchers/ContainHash.html +222 -0
- data/doc/ElabsMatchers/Matchers/HaveAttribute/HaveAttributeMatcher.html +656 -0
- data/doc/ElabsMatchers/Matchers/HaveAttribute.html +239 -0
- data/doc/ElabsMatchers/Matchers/HaveFields/HaveFieldsMatcher.html +572 -0
- data/doc/ElabsMatchers/Matchers/HaveFields.html +220 -0
- data/doc/ElabsMatchers/Matchers/HaveFlash/HaveFlashMatcher.html +654 -0
- data/doc/ElabsMatchers/Matchers/HaveFlash.html +306 -0
- data/doc/ElabsMatchers/Matchers/HaveFormErrorsOn/HaveFormErrorsOnMatcher.html +678 -0
- data/doc/ElabsMatchers/Matchers/HaveFormErrorsOn.html +236 -0
- data/doc/ElabsMatchers/Matchers/HaveHeader/HaveHeaderMatcher.html +568 -0
- data/doc/ElabsMatchers/Matchers/HaveHeader.html +219 -0
- data/doc/ElabsMatchers/Matchers/HaveImage/HaveImageMatcher.html +592 -0
- data/doc/ElabsMatchers/Matchers/HaveImage.html +219 -0
- data/doc/ElabsMatchers/Matchers/HaveTableRow/HaveTableRowMatcher.html +654 -0
- data/doc/ElabsMatchers/Matchers/HaveTableRow.html +236 -0
- data/doc/ElabsMatchers/Matchers/OnlyInclude/OnlyIncludeMatcher.html +494 -0
- data/doc/ElabsMatchers/Matchers/OnlyInclude.html +221 -0
- data/doc/ElabsMatchers/Matchers/Persist/PersistMatcher.html +586 -0
- data/doc/ElabsMatchers/Matchers/Persist.html +235 -0
- data/doc/ElabsMatchers/Matchers.html +29 -22
- data/doc/ElabsMatchers.html +1144 -21
- data/doc/_index.html +161 -79
- data/doc/class_list.html +12 -6
- data/doc/css/full_list.css +4 -2
- data/doc/css/style.css +50 -44
- data/doc/file.README.html +71 -73
- data/doc/file_list.html +12 -6
- data/doc/frames.html +20 -5
- data/doc/index.html +71 -73
- data/doc/js/app.js +52 -43
- data/doc/js/full_list.js +9 -9
- data/doc/js/jquery.js +4 -16
- data/doc/method_list.html +603 -77
- data/doc/top-level-namespace.html +24 -103
- data/elabs_matchers.gemspec +4 -3
- data/history.txt +15 -0
- data/lib/elabs_matchers/extensions/module.rb +24 -0
- data/lib/elabs_matchers/helpers/fixtures.rb +2 -2
- data/lib/elabs_matchers/helpers/{common.rb → normalize_keys.rb} +3 -4
- data/lib/elabs_matchers/helpers/{orm.rb → reload_record.rb} +9 -6
- data/lib/elabs_matchers/helpers/{capybara.rb → select_year_and_month.rb} +5 -3
- data/lib/elabs_matchers/matchers/allow.rb +130 -0
- data/lib/elabs_matchers/matchers/contain_hash.rb +58 -0
- data/lib/elabs_matchers/matchers/have_attribute.rb +62 -0
- data/lib/elabs_matchers/matchers/have_fields.rb +45 -0
- data/lib/elabs_matchers/matchers/have_flash.rb +65 -0
- data/lib/elabs_matchers/matchers/have_form_errors_on.rb +79 -0
- data/lib/elabs_matchers/matchers/have_header.rb +53 -0
- data/lib/elabs_matchers/matchers/have_image.rb +69 -0
- data/lib/elabs_matchers/matchers/have_table_row.rb +113 -0
- data/lib/elabs_matchers/matchers/only_include.rb +41 -0
- data/lib/elabs_matchers/matchers/persist.rb +42 -0
- data/lib/elabs_matchers/version.rb +1 -1
- data/lib/elabs_matchers.rb +90 -10
- data/spec/elabs_matchers/helpers/fixtures_spec.rb +1 -1
- data/spec/elabs_matchers/helpers/{common_spec.rb → normalize_keys_spec.rb} +2 -2
- data/spec/elabs_matchers/helpers/{orm_spec.rb → reload_record_spec.rb} +3 -2
- data/spec/elabs_matchers/helpers/select_year_and_month_spec.rb +32 -0
- data/spec/elabs_matchers/matchers/{rspec/allow_spec.rb → allow_spec.rb} +5 -4
- data/spec/elabs_matchers/matchers/contain_hash_spec.rb +86 -0
- data/spec/elabs_matchers/matchers/have_attribute_spec.rb +65 -0
- data/spec/elabs_matchers/matchers/have_fields_spec.rb +46 -0
- data/spec/elabs_matchers/matchers/have_flash_spec.rb +97 -0
- data/spec/elabs_matchers/matchers/have_form_errors_on_spec.rb +93 -0
- data/spec/elabs_matchers/matchers/have_header_spec.rb +54 -0
- data/spec/elabs_matchers/matchers/have_image_spec.rb +49 -0
- data/spec/elabs_matchers/matchers/have_table_row_spec.rb +119 -0
- data/spec/elabs_matchers/matchers/only_include_spec.rb +32 -0
- data/spec/elabs_matchers/matchers/persist_spec.rb +21 -0
- data/{lib/elabs_matchers/orm → spec/fixtures}/post.rb +0 -0
- data/spec/spec_helper.rb +19 -8
- data/todo.txt +6 -0
- metadata +104 -48
- data/lib/elabs_matchers/cucumber/common.rb +0 -57
- data/lib/elabs_matchers/helpers/session.rb +0 -81
- data/lib/elabs_matchers/matchers/capybara/common.rb +0 -245
- data/lib/elabs_matchers/matchers/rspec/allow.rb +0 -112
- data/lib/elabs_matchers/matchers/rspec/common.rb +0 -59
- data/lib/elabs_matchers/matchers/rspec/orm.rb +0 -29
- data/spec/elabs_matchers/cucumber/common_spec.rb +0 -49
- data/spec/elabs_matchers/helpers/capybara_spec.rb +0 -32
- data/spec/elabs_matchers/helpers/session_spec.rb +0 -35
- data/spec/elabs_matchers/matchers/capybara/common_spec.rb +0 -202
- data/spec/elabs_matchers/matchers/rspec/common_spec.rb +0 -74
- data/spec/elabs_matchers/matchers/rspec/orm_spec.rb +0 -16
@@ -0,0 +1,58 @@
|
|
1
|
+
module ElabsMatchers
|
2
|
+
module Matchers
|
3
|
+
module ContainHash
|
4
|
+
rspec
|
5
|
+
|
6
|
+
class ContainHashMatcher < Struct.new(:expected, :actual)
|
7
|
+
def matches?(actual)
|
8
|
+
@actual = actual
|
9
|
+
contains?(expected, actual)
|
10
|
+
end
|
11
|
+
|
12
|
+
def failure_message_for_should
|
13
|
+
"Expected #{expected.inspect} to exist in #{actual.inspect} but it did not."
|
14
|
+
end
|
15
|
+
|
16
|
+
def failure_message_for_should_not
|
17
|
+
"Expected #{expected.inspect} to not exist in #{actual.inspect} but it did."
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def contains?(expected, actual)
|
23
|
+
return false unless actual.is_a?(expected.class)
|
24
|
+
|
25
|
+
if expected.is_a?(Array)
|
26
|
+
expected.all? do |expected_value|
|
27
|
+
actual.any? do |actual_value|
|
28
|
+
contains?(expected_value, actual_value)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
elsif expected.is_a?(Hash)
|
32
|
+
expected.all? do |key, value|
|
33
|
+
contains?(value, actual[key])
|
34
|
+
end
|
35
|
+
else
|
36
|
+
actual == expected
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
#
|
44
|
+
# Asserts if the hash contains the supplied hash.
|
45
|
+
# Works with nested hashes and array of hashes.
|
46
|
+
#
|
47
|
+
# @param [Hash] hash Key => value pairs seperated by comma
|
48
|
+
#
|
49
|
+
# Example:
|
50
|
+
# { "foo" => ["quox", { "bar" => "baz"}]}.should contain_hash({ "foo" => [{ "bar" => "baz" }]})
|
51
|
+
# { "foo" => "bar", "baz" => "quox" }.should_not contain_hash({ "baz" => "bar" })
|
52
|
+
|
53
|
+
def contain_hash(hash)
|
54
|
+
ContainHashMatcher.new(hash)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ElabsMatchers
|
2
|
+
module Matchers
|
3
|
+
module HaveAttribute
|
4
|
+
rspec :type => :request
|
5
|
+
|
6
|
+
class HaveAttributeMatcher < Struct.new(:label, :value)
|
7
|
+
attr_reader :page
|
8
|
+
|
9
|
+
def matches?(page)
|
10
|
+
@page = page
|
11
|
+
page.has_selector?(selector_type, selector)
|
12
|
+
end
|
13
|
+
|
14
|
+
def does_not_match?(page)
|
15
|
+
@page = page
|
16
|
+
page.has_no_selector?(selector_type, selector)
|
17
|
+
end
|
18
|
+
|
19
|
+
def failure_message_for_should
|
20
|
+
attributes = page.all(:css, "li.wrapper").map(&:text).to_sentence
|
21
|
+
"expected there to be an attribute #{label}: #{value}, but the only attributes were: #{attributes}."
|
22
|
+
end
|
23
|
+
|
24
|
+
def failure_message_for_should_not
|
25
|
+
"expected there to be no attribute #{label}: #{value}, but there was."
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def selector_type
|
31
|
+
ElabsMatchers.attribute_selector_type
|
32
|
+
end
|
33
|
+
|
34
|
+
def selector
|
35
|
+
if ElabsMatchers.attribute_selector
|
36
|
+
ElabsMatchers.attribute_selector[label, value]
|
37
|
+
else
|
38
|
+
XPath.generate do |x|
|
39
|
+
x.descendant(:p)[x.attr(:class).contains("wrapper")][x.child(:strong).contains(label)][x.contains(value)]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
#
|
47
|
+
# Asserts if the supplied show_for* attribute exists or not
|
48
|
+
#
|
49
|
+
# @param [String] label The name of the attribute.
|
50
|
+
# @param [String] value The value of the attribute.
|
51
|
+
#
|
52
|
+
# Example:
|
53
|
+
# page.should have_attribute("Status", "Pending")
|
54
|
+
#
|
55
|
+
# * https://github.com/plataformatec/show_for
|
56
|
+
|
57
|
+
def have_attribute(label, value)
|
58
|
+
HaveAttributeMatcher.new(label, value)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ElabsMatchers
|
2
|
+
module Matchers
|
3
|
+
module HaveFields
|
4
|
+
rspec :type => :request
|
5
|
+
|
6
|
+
class HaveFieldsMatcher < Struct.new(:fields)
|
7
|
+
attr_reader :page
|
8
|
+
|
9
|
+
def matches?(page)
|
10
|
+
@page = page
|
11
|
+
fields.all? { |label, value| page.has_field?(label, :with => value) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def does_not_match?(page)
|
15
|
+
@page = page
|
16
|
+
fields.all? { |label, value| page.has_no_field?(label, :with => value) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def failure_message_for_should
|
20
|
+
field_values = page.all("input, textarea").map { |input| input[:value] }
|
21
|
+
|
22
|
+
"expected page to have the fields #{fields.inspect}, but it didn't.
|
23
|
+
The fields on the page had the following values: #{field_values.to_sentence}."
|
24
|
+
end
|
25
|
+
|
26
|
+
def failure_message_for_should_not
|
27
|
+
"expected page not to have the fields #{fields.inspect}, but it did."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
#
|
33
|
+
# Asserts if the supplied fields exists or not
|
34
|
+
#
|
35
|
+
# @param [Hash] fields A hash containing pairs of field name => value
|
36
|
+
#
|
37
|
+
# Example:
|
38
|
+
# page.should have_fields("Author" => "Adam", "Year" => "2011")
|
39
|
+
|
40
|
+
def have_fields(fields)
|
41
|
+
HaveFieldsMatcher.new(fields)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ElabsMatchers
|
2
|
+
module Matchers
|
3
|
+
module HaveFlash
|
4
|
+
rspec :type => :request
|
5
|
+
|
6
|
+
class HaveFlashMatcher < Struct.new(:type, :message)
|
7
|
+
attr_reader :page
|
8
|
+
|
9
|
+
def matches?(page)
|
10
|
+
@page = page
|
11
|
+
page.has_selector?(selector_type, selector, :text => message)
|
12
|
+
end
|
13
|
+
|
14
|
+
def does_not_match?(page)
|
15
|
+
@page = page
|
16
|
+
page.has_no_selector?(selector_type, selector, :text => message)
|
17
|
+
end
|
18
|
+
|
19
|
+
def failure_message_for_should
|
20
|
+
"Expected flash #{type} to be '#{message}' but was '#{page.find(selector_type, selector).text}'."
|
21
|
+
end
|
22
|
+
|
23
|
+
def failure_message_for_should_not
|
24
|
+
"Expected flash #{type} to not be '#{message}' but it was."
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def selector_type
|
30
|
+
ElabsMatchers.send(:"flash_#{type}_selector_type")
|
31
|
+
end
|
32
|
+
|
33
|
+
def selector
|
34
|
+
ElabsMatchers.send(:"flash_#{type}_selector")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
#
|
40
|
+
# Asserts if the supplied flash notice exists or not
|
41
|
+
#
|
42
|
+
# @param [String] message The content of the flash notice
|
43
|
+
#
|
44
|
+
# Example:
|
45
|
+
# page.should have_flash_notice("Success")
|
46
|
+
|
47
|
+
def have_flash_notice(message)
|
48
|
+
HaveFlashMatcher.new(:notice, message)
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
#
|
53
|
+
# Asserts if the supplied flash alert exists or not
|
54
|
+
#
|
55
|
+
# @param [String] message The content of the flash alert
|
56
|
+
#
|
57
|
+
# Example:
|
58
|
+
# page.should have_flash_alert("Error")
|
59
|
+
|
60
|
+
def have_flash_alert(message)
|
61
|
+
HaveFlashMatcher.new(:alert, message)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module ElabsMatchers
|
2
|
+
module Matchers
|
3
|
+
module HaveFormErrorsOn
|
4
|
+
rspec :type => :request
|
5
|
+
|
6
|
+
class HaveFormErrorsOnMatcher < Struct.new(:field, :message)
|
7
|
+
attr_reader :page
|
8
|
+
|
9
|
+
def matches?(page)
|
10
|
+
@page = page
|
11
|
+
|
12
|
+
if page.has_field?(field)
|
13
|
+
page.find_field(field).has_selector?(selector_type, selector, :text => message)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def does_not_match?(page)
|
18
|
+
@page = page
|
19
|
+
page.has_no_field?(field) || page.find_field(field).has_no_selector?(selector_type, selector, :text => message)
|
20
|
+
end
|
21
|
+
|
22
|
+
def failure_message_for_should
|
23
|
+
if page.has_field?(field)
|
24
|
+
error = page.find_field(field).all(selector_type, selector).first
|
25
|
+
if not error
|
26
|
+
"Expected field '#{field}' to have an error, but it didn't."
|
27
|
+
elsif error.text != message
|
28
|
+
"Expected error message on #{field} to be '#{message}' but was '#{error.text}'."
|
29
|
+
end
|
30
|
+
else
|
31
|
+
"No such field #{field}."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def failure_message_for_should_not
|
36
|
+
"Expected error message on '#{field}' not to be '#{message}' but it was."
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def selector_type
|
42
|
+
:xpath
|
43
|
+
end
|
44
|
+
|
45
|
+
def selector
|
46
|
+
if ElabsMatchers.form_errors_on_selector
|
47
|
+
ElabsMatchers.form_errors_on_selector
|
48
|
+
else
|
49
|
+
outside_input_container_xpath = %Q{ancestor::*[contains(@class, 'field_with_errors') and contains(@class, 'error')]}
|
50
|
+
error_as_sibling_xpath = %Q{..//span[contains(@class,'error')]}
|
51
|
+
input_nested_in_label_xpath = %Q{..//..//label/following-sibling::*[1]/self::span[@class='error']}
|
52
|
+
twitter_bootstrap_xpath = %Q{ancestor::*[contains(concat(' ', @class, ' '), ' control-group ') and contains(concat(' ', @class, ' '), ' error ')]}
|
53
|
+
|
54
|
+
[
|
55
|
+
outside_input_container_xpath,
|
56
|
+
error_as_sibling_xpath,
|
57
|
+
input_nested_in_label_xpath,
|
58
|
+
twitter_bootstrap_xpath
|
59
|
+
].join(" | ")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
#
|
66
|
+
# Asserts if the supplied flash alert exists or not
|
67
|
+
#
|
68
|
+
# @param [String] field The label content associated with the field. Any selector which works with has_field? works here too.
|
69
|
+
# @param [String] message The error message expected.
|
70
|
+
#
|
71
|
+
# Example:
|
72
|
+
# page.should have_form_errors_on("Name", "Can't be blank")
|
73
|
+
|
74
|
+
def have_form_errors_on(field, message)
|
75
|
+
HaveFormErrorsOnMatcher.new(field, message)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ElabsMatchers
|
2
|
+
module Matchers
|
3
|
+
module HaveHeader
|
4
|
+
rspec :type => :request
|
5
|
+
|
6
|
+
class HaveHeaderMatcher < Struct.new(:text)
|
7
|
+
attr_reader :page
|
8
|
+
|
9
|
+
def matches?(page)
|
10
|
+
@page = page
|
11
|
+
page.has_selector?(selector_type, selector, :text => text)
|
12
|
+
end
|
13
|
+
|
14
|
+
def does_not_match?(page)
|
15
|
+
@page = page
|
16
|
+
page.has_no_selector?(selector_type, selector, :text => text)
|
17
|
+
end
|
18
|
+
|
19
|
+
def failure_message_for_should
|
20
|
+
headers = page.all(selector_type, selector).map { |h| "'#{h.text}'" }.to_sentence
|
21
|
+
"Expected header to be '#{text}' but it had the headers #{headers}."
|
22
|
+
end
|
23
|
+
|
24
|
+
def failure_message_for_should_not
|
25
|
+
"Expected header not to be '#{text}' but it was."
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def selector
|
31
|
+
ElabsMatchers.header_selector
|
32
|
+
end
|
33
|
+
|
34
|
+
def selector_type
|
35
|
+
ElabsMatchers.header_selector_type
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
#
|
41
|
+
# Asserts if the supplied header exists or not
|
42
|
+
#
|
43
|
+
# @param [String] text The content of the header
|
44
|
+
#
|
45
|
+
# Example:
|
46
|
+
# page.should have_header("Elabs")
|
47
|
+
|
48
|
+
def have_header(text)
|
49
|
+
HaveHeaderMatcher.new(text)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ElabsMatchers
|
2
|
+
module Matchers
|
3
|
+
module HaveImage
|
4
|
+
rspec :type => :request
|
5
|
+
|
6
|
+
class HaveImageMatcher < Struct.new(:value)
|
7
|
+
attr_reader :page
|
8
|
+
|
9
|
+
def matches?(page)
|
10
|
+
@page = page
|
11
|
+
page.has_selector?(selector_type, selector)
|
12
|
+
end
|
13
|
+
|
14
|
+
def does_not_match?(page)
|
15
|
+
@page = page
|
16
|
+
page.has_no_selector?(selector_type, selector)
|
17
|
+
end
|
18
|
+
|
19
|
+
def failure_message_for_should
|
20
|
+
images = page.all("img").map do |image|
|
21
|
+
hash = {}
|
22
|
+
hash[:alt] = image[:alt] if image[:alt].present?
|
23
|
+
hash[:src] = image[:src] if image[:src].present?
|
24
|
+
hash[:id] = image[:id] if image[:id].present?
|
25
|
+
hash[:class] = image[:class] if image[:class].present?
|
26
|
+
hash
|
27
|
+
end.to_sentence
|
28
|
+
|
29
|
+
if ElabsMatchers.image_selector.nil?
|
30
|
+
"expected image alt to be '#{value}' but only had the images: #{images}."
|
31
|
+
else
|
32
|
+
"expected to find image '#{value}' but only had the images: #{images}."
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def failure_message_for_should_not
|
37
|
+
"expected image not to be '#{value}' but it was."
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def selector_type
|
43
|
+
ElabsMatchers.image_selector_type
|
44
|
+
end
|
45
|
+
|
46
|
+
def selector
|
47
|
+
if ElabsMatchers.image_selector
|
48
|
+
ElabsMatchers.image_selector[value]
|
49
|
+
else
|
50
|
+
"img[alt=\"#{value}\"]"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
#
|
57
|
+
# Asserts if the supplied image exists or not
|
58
|
+
#
|
59
|
+
# @param [String] value The alt attribute content of the image
|
60
|
+
#
|
61
|
+
# Example:
|
62
|
+
# page.should have_image("Logo")
|
63
|
+
|
64
|
+
def have_image(value)
|
65
|
+
HaveImageMatcher.new(value)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module ElabsMatchers
|
2
|
+
module Matchers
|
3
|
+
module HaveTableRow
|
4
|
+
rspec :type => :request
|
5
|
+
|
6
|
+
class HaveTableRowMatcher < Struct.new(:table_name, :row)
|
7
|
+
attr_reader :page
|
8
|
+
|
9
|
+
def matches?(page)
|
10
|
+
@page = page
|
11
|
+
table and table.has_selector?(selector_type, selector)
|
12
|
+
end
|
13
|
+
|
14
|
+
def does_not_match?(page)
|
15
|
+
@page = page
|
16
|
+
!table or table.has_no_selector?(selector_type, selector)
|
17
|
+
end
|
18
|
+
|
19
|
+
def failure_message_for_should
|
20
|
+
"Expected #{row.inspect} to be included in the table #{table_name}, but it wasn't:\n\n#{ascii_table}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def failure_message_for_should_not
|
24
|
+
"Expected there to be no table #{table_name} with row #{row.inspect}, but there was.\n\n#{ascii_table}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def selector_type
|
30
|
+
:xpath
|
31
|
+
end
|
32
|
+
|
33
|
+
def selector
|
34
|
+
if ElabsMatchers.table_row_selector
|
35
|
+
ElabsMatchers.table_row_selector[row, table]
|
36
|
+
else
|
37
|
+
exps = row.map do |header, value|
|
38
|
+
col_index = table.all("th").index { |th| th.text.include?(header.to_s) }
|
39
|
+
col_index = if col_index then col_index + 1 else 0 end
|
40
|
+
|
41
|
+
XPath.generate do |x|
|
42
|
+
cell = x.child(:td, :th)[col_index.to_s.to_sym]
|
43
|
+
|
44
|
+
if value.blank?
|
45
|
+
cell["not(node())".to_sym].or(cell.descendant(:input)["string-length(normalize-space(@value))=0".to_sym])
|
46
|
+
else
|
47
|
+
cell[x.contains(value).or(x.descendant(:input)[x.attr(:value).contains(value)])]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
XPath.descendant["tr"][exps.reduce(:&)]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def table
|
57
|
+
table_xpath = XPath::HTML.table(table_name)
|
58
|
+
|
59
|
+
if page.has_xpath?(table_xpath)
|
60
|
+
page.find(:xpath, table_xpath)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def ascii_table
|
65
|
+
if table
|
66
|
+
column_lengths = []
|
67
|
+
table.all("tr").map do |tr|
|
68
|
+
tr.all("td,th").each_with_index do |td, i|
|
69
|
+
size = td_content(td).strip.size
|
70
|
+
if (column_lengths[i] || 0) < size
|
71
|
+
column_lengths[i] = size
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
table.all("tr").map do |tr|
|
77
|
+
middle = []
|
78
|
+
space = if tr.all("td,th").first.tag_name == "th" then "_" else " " end
|
79
|
+
wall = "|"
|
80
|
+
|
81
|
+
tr.all("td,th").each_with_index do |td, i|
|
82
|
+
middle << td_content(td).strip.ljust(column_lengths[i], space)
|
83
|
+
end
|
84
|
+
|
85
|
+
[wall, space, middle.join(space + wall + space), space, wall].join
|
86
|
+
end.join("\n")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def td_content(td)
|
91
|
+
text = td.text.presence
|
92
|
+
text ||= td.find("input, textarea")[:value] if td.has_css?("input")
|
93
|
+
text || ""
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
##
|
99
|
+
#
|
100
|
+
# Asserts if the supplied table row exists in the table
|
101
|
+
#
|
102
|
+
# @param [String] table_name The tables's caption text.
|
103
|
+
# @param [Hash] row A hash representing the column name and value in key-value form.
|
104
|
+
#
|
105
|
+
# Example:
|
106
|
+
# table.should have_table_row("Posts", "Title" => "First", :year => "2012")
|
107
|
+
|
108
|
+
def have_table_row(table_name, row)
|
109
|
+
HaveTableRowMatcher.new(table_name, row)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|