turnip-extra_steps 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ module Turnip::ExtraSteps::Support
2
+ end
@@ -0,0 +1,30 @@
1
+ module Turnip::ExtraSteps::Support::CustomMatchers
2
+ rspec = defined?(RSpec) ? RSpec : Spec
3
+
4
+ rspec::Matchers.define :contain_with_wildcards do |expected_string|
5
+ match do |field_value|
6
+ @field_value = field_value.to_s
7
+ @expected_string = expected_string
8
+ regex_parts = expected_string.to_s.split('*', -1).collect { |part| Regexp.escape(part) }
9
+
10
+ @field_value =~ /\A#{regex_parts.join(".*")}\z/m
11
+ end
12
+
13
+ failure_message do
14
+ "The field's content #{@field_value.inspect} did not match #{@expected_string.inspect}"
15
+ end
16
+
17
+ failure_message_when_negated do
18
+ "The field's content #{@field_value.inspect} matches #{@expected_string.inspect}"
19
+ end
20
+ end
21
+
22
+ rspec::Matchers.define :be_sorted do
23
+ match do |array|
24
+ sort_method = defined?(array.natural_sort) ? :natural_sort : :sort
25
+
26
+ array == array.send(sort_method)
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,59 @@
1
+ # coding: UTF-8
2
+
3
+ class MailFinder
4
+ class << self
5
+
6
+ attr_accessor :user_identity
7
+
8
+ def find(conditions)
9
+ filename_method = Rails::VERSION::MAJOR < 3 ? 'original_filename' : 'filename'
10
+ ActionMailer::Base.deliveries.detect do |mail|
11
+ mail_body = email_text_body(mail)
12
+ [ conditions[:to].nil? || mail.to.include?(resolve_email conditions[:to]),
13
+ conditions[:cc].nil? || mail.cc.andand.include?(resolve_email conditions[:cc]),
14
+ conditions[:bcc].nil? || mail.bcc.andand.include?(resolve_email conditions[:bcc]),
15
+ conditions[:from].nil? || mail.from.include?(resolve_email conditions[:from]),
16
+ conditions[:reply_to].nil? || mail.reply_to.include?(resolve_email conditions[:reply_to]),
17
+ conditions[:subject].nil? || mail.subject.include?(conditions[:subject]),
18
+ conditions[:body].nil? || mail_body.include?(conditions[:body]),
19
+ conditions[:attachments].nil? || conditions[:attachments].split(/\s*,\s*/).sort == Array(mail.attachments).collect(&:"#{filename_method}").sort
20
+ ].all?
21
+ end.tap do |mail|
22
+ log(mail)
23
+ end
24
+ end
25
+
26
+ def resolve_email(identity)
27
+ if identity =~ /^.+\@.+$/
28
+ identity
29
+ else
30
+ User.send("find_by_#{user_identity || 'email'}!", identity).email
31
+ end
32
+ end
33
+
34
+ def log(mail)
35
+ if mail.present?
36
+ if defined?(Rails)
37
+ File.open(Rails.root.join("log/test_mails.log"), "a") do |file|
38
+ file << "From: #{mail.from}\n"
39
+ file << "To: #{mail.to.join(', ')}\n" if mail.to
40
+ file << "Subject: #{mail.subject}\n\n"
41
+ file << email_text_body(mail)
42
+ file << "\n-------------------------\n\n"
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def email_text_body(mail)
49
+ if mail.parts.any?
50
+ mail.parts.select { |part| part.content_type.include?('text/') }.collect(&:decoded).join("\n")
51
+ elsif mail.body.respond_to? :raw_source
52
+ mail.body.raw_source
53
+ else
54
+ mail.body
55
+ end
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,38 @@
1
+ # coding: UTF-8
2
+
3
+ module Turnip::ExtraSteps::Support::PathSelectorFallbacks
4
+ def _selector_for(locator)
5
+ if respond_to?(:selector_for)
6
+ selector_for(locator)
7
+ elsif locator =~ /^"(.+)"$/
8
+ $1
9
+ else
10
+ raise "Can't find mapping from \"#{locator}\" to a selector.\n" +
11
+ "Add and require a selectors.rb file (compare /examples/selectors.rb)"
12
+ end
13
+ end
14
+
15
+ def _path_to(page_name)
16
+ if respond_to?(:path_to)
17
+ path_to(page_name)
18
+ else
19
+ begin
20
+ page_name =~ /^the (.*) page$/
21
+ path_components = $1.split(/\s+/)
22
+ self.send(path_components.push('path').join('_').to_sym)
23
+ rescue NoMethodError, ArgumentError
24
+ raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
25
+ "Add and require a paths.rb file (compare /examples/paths.rb)"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ RSpec.configure { |c| c.include Turnip::ExtraSteps::Support::PathSelectorFallbacks}
31
+
32
+ module Turnip::ExtraSteps::Support::WithinHelpers
33
+ def with_scope(locator)
34
+ locator ? within(*_selector_for(locator)) { yield } : yield
35
+ end
36
+ end
37
+ RSpec.configure { |c| c.include Turnip::ExtraSteps::Support::WithinHelpers}
38
+
@@ -0,0 +1,13 @@
1
+ # coding: UTF-8
2
+
3
+ module Turnip::ExtraSteps::Support::StepFallback
4
+ def step(*args)
5
+ if defined?(super)
6
+ super
7
+ else
8
+ When(*args)
9
+ end
10
+ end
11
+ end
12
+
13
+ RSpec.configure { |c| c.include Turnip::ExtraSteps::Support::StepFallback}
@@ -0,0 +1,42 @@
1
+ # coding: UTF-8
2
+
3
+ module Turnip::ExtraSteps::Support::ToleranceForSeleniumSyncIssues
4
+ RETRY_ERRORS = %w[
5
+ Capybara::ElementNotFound
6
+ Spec::Expectations::ExpectationNotMetError
7
+ RSpec::Expectations::ExpectationNotMetError
8
+ Minitest::Assertion
9
+ Capybara::Poltergeist::ClickFailed
10
+ Capybara::ExpectationNotMet
11
+ Selenium::WebDriver::Error::StaleElementReferenceError
12
+ Selenium::WebDriver::Error::NoAlertPresentError
13
+ Selenium::WebDriver::Error::ElementNotVisibleError
14
+ Selenium::WebDriver::Error::NoSuchFrameError
15
+ Selenium::WebDriver::Error::NoAlertPresentError
16
+ ]
17
+
18
+ # This is similiar but not entirely the same as Capybara::Node::Base#wait_until or Capybara::Session#wait_until
19
+ def patiently(seconds=Capybara.default_wait_time, &block)
20
+ old_wait_time = Capybara.default_wait_time
21
+ # dont make nested wait_untils use up all the alloted time
22
+ Capybara.default_wait_time = 0 # for we are a jealous gem
23
+ if page.driver.wait?
24
+ start_time = Time.now
25
+ begin
26
+ block.call
27
+ rescue Exception => e
28
+ raise e unless RETRY_ERRORS.include?(e.class.name)
29
+ raise e if (Time.now - start_time) >= seconds
30
+ sleep(0.05)
31
+ raise Capybara::FrozenInTime, "time appears to be frozen, Capybara does not work with libraries which freeze time, consider using time travelling instead" if Time.now == start_time
32
+ retry
33
+ end
34
+ else
35
+ block.call
36
+ end
37
+ ensure
38
+ Capybara.default_wait_time = old_wait_time
39
+ end
40
+ end
41
+
42
+ RSpec.configure { |c| c.include Turnip::ExtraSteps::Support::ToleranceForSeleniumSyncIssues}
@@ -0,0 +1,3 @@
1
+ module Spreewald
2
+ VERSION = '1.2.6'
3
+ end
@@ -0,0 +1,114 @@
1
+ module Turnip::ExtraSteps::Support::WebStepsHelpers
2
+
3
+ def assert_visible(options)
4
+ visibility_test(options.merge(:expectation => :visible))
5
+ end
6
+
7
+ def assert_hidden(options)
8
+ visibility_test(options.merge(:expectation => :hidden))
9
+ end
10
+
11
+ private
12
+
13
+ def visibility_test(options)
14
+ case Capybara::current_driver
15
+ when :selenium, :webkit, :poltergeist
16
+ detect_visibility_with_js(options)
17
+ else
18
+ detect_visibility_with_capybara(options)
19
+ end
20
+ end
21
+
22
+ def detect_visibility_with_js(options)
23
+ patiently do
24
+
25
+ selector_javascript = if options.has_key?(:selector)
26
+ options[:selector].to_json
27
+ else
28
+ "':contains(' + " + options[:text].to_json + " + ')'"
29
+ end
30
+
31
+ visibility_detecting_javascript = %[
32
+ (function() {
33
+ var selector = #{selector_javascript};
34
+ var jqueryLoaded = (typeof jQuery != 'undefined');
35
+
36
+ function findCandidates() {
37
+ if (jqueryLoaded) {
38
+ return $(selector);
39
+ } else {
40
+ return $$(selector);
41
+ }
42
+ }
43
+
44
+ function isExactCandidate(candidate) {
45
+ if (jqueryLoaded) {
46
+ return $(candidate).find(selector).length == 0;
47
+ } else {
48
+ return candidate.select(selector).length == 0;
49
+ }
50
+ }
51
+
52
+ function elementVisible(element) {
53
+ if (jqueryLoaded) {
54
+ return $(element).is(':visible');
55
+ } else {
56
+ return element.offsetWidth > 0 && element.offsetHeight > 0;
57
+ }
58
+ }
59
+
60
+ var candidates = findCandidates();
61
+
62
+ if (candidates.length == 0) {
63
+ throw("Selector not found in page: " + selector);
64
+ }
65
+
66
+ for (var i = 0; i < candidates.length; i++) {
67
+ var candidate = candidates[i];
68
+ if (isExactCandidate(candidate) && elementVisible(candidate)) {
69
+ return true;
70
+ }
71
+ }
72
+ return false;
73
+
74
+ })();
75
+ ]
76
+
77
+ visibility_detecting_javascript.gsub!(/\n/, ' ')
78
+ if options[:expectation] == :visible
79
+ expect(page.evaluate_script(visibility_detecting_javascript)).to be_truthy
80
+ else
81
+ expect(page.evaluate_script(visibility_detecting_javascript)).to be_falsy
82
+ end
83
+ end
84
+ end
85
+
86
+ def detect_visibility_with_capybara(options)
87
+ begin
88
+ old_ignore_hidden_elements = Capybara.ignore_hidden_elements
89
+ Capybara.ignore_hidden_elements = false
90
+ if options.has_key?(:selector)
91
+ expect(page).to have_css(options[:selector])
92
+ have_hidden_tag = have_css(".hidden #{options[:selector]}, .invisible #{selector_or_text}, [style~=\"display: none\"] #{options[:selector]}")
93
+ if options[:expectation] == :hidden
94
+ expect(page).to have_hidden_tag
95
+ else
96
+ expect(page).not_to have_hidden_tag
97
+ end
98
+ else
99
+ expect(page).to have_css('*', :text => options[:text])
100
+ have_hidden_text = have_css('.hidden, .invisible, [style~="display: none"]', :text => options[:text])
101
+ if options[:expectation] == :hidden
102
+ expect(page).to have_hidden_text
103
+ else
104
+ expect(page).not_to have_hidden_text
105
+ end
106
+ end
107
+ ensure
108
+ Capybara.ignore_hidden_elements = old_ignore_hidden_elements
109
+ end
110
+ end
111
+
112
+ end
113
+
114
+ RSpec.configure { |c| c.include Turnip::ExtraSteps::Support::WebStepsHelpers}
@@ -0,0 +1,187 @@
1
+ # coding: UTF-8
2
+
3
+ require 'turnip/extra_steps/support/tolerance_for_selenium_sync_issues'
4
+
5
+ module Turnip::ExtraSteps::Support::TableStepsHelper
6
+ module ArrayMethods
7
+
8
+ def find_row(expected_row)
9
+ find_index do |row|
10
+ expected_row.all? do |expected_column|
11
+ first_column = row.find_index do |column|
12
+ content = normalize_content(column.content)
13
+ expected_content = normalize_content(expected_column)
14
+ matching_parts = expected_content.split(/\s*\*\s*/, -1).collect { |part| Regexp.escape(part) }
15
+ matching_expression = /\A#{matching_parts.join(".*")}\z/
16
+ content =~ matching_expression
17
+ end
18
+ if first_column.nil?
19
+ false
20
+ else
21
+ row = row[(first_column + 1)..-1]
22
+ true
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def normalize_content(content)
29
+ nbsp = " "
30
+ content.gsub(/[\r\n\t]+/, ' ').gsub(nbsp, ' ').gsub(/ {2,}/, ' ').strip
31
+ end
32
+
33
+ end
34
+
35
+ rspec = defined?(RSpec) ? RSpec : Spec
36
+
37
+ rspec::Matchers.define :contain_table do |*args|
38
+ match do |tables|
39
+ @last_unmatched_row = nil
40
+ @extra_rows = nil
41
+ @best_rows_matched = -1
42
+ options = args.extract_options!
43
+ expected_table = args.first
44
+ tables.any? do |table|
45
+ skipped_rows = []
46
+ rows_matched = 0
47
+ match = expected_table.all? do |expected_row|
48
+ if @best_rows_matched < rows_matched
49
+ @last_unmatched_row = expected_row
50
+ @best_rows_matched = rows_matched
51
+ end
52
+ table.extend ArrayMethods
53
+ first_row = table.find_row(expected_row)
54
+ if first_row.nil?
55
+ false
56
+ else
57
+ rows_matched += 1
58
+ if options[:unordered]
59
+ table.delete_at(first_row)
60
+ else
61
+ skipped_rows += table[0...first_row]
62
+ table = table[(first_row + 1)..-1]
63
+ end
64
+ true
65
+ end
66
+ end
67
+ remaining_rows = skipped_rows + table
68
+ if match and options[:exactly] and not remaining_rows.empty?
69
+ @extra_rows = remaining_rows
70
+ match = false
71
+ end
72
+ match
73
+ end
74
+ end
75
+
76
+ failure_message do
77
+ if @extra_rows
78
+ "Found the following extra row: #{@extra_rows.first.collect(&:content).collect(&:squish).inspect}"
79
+ elsif @last_unmatched_row
80
+ "Could not find the following row: #{@last_unmatched_row.inspect}"
81
+ else
82
+ "Could not find a table"
83
+ end
84
+ end
85
+
86
+ failure_message_when_negated do
87
+ "Found the complete table: #{args.first.inspect}."
88
+ end
89
+ end
90
+
91
+ def parse_table(table)
92
+ if table.is_a?(String)
93
+ table.sub!(/^\n/, '')
94
+ # multiline string. split it assuming a format like cucumber tables have.
95
+ table.split(/\n/).collect do |line|
96
+ line.sub!(/^\|/, '')
97
+ line.sub!(/\|$/, '')
98
+ line.gsub!(/^\ +/, '')
99
+ line.gsub!(/\ +$/, '')
100
+ line.split(/\s*\|\s*/)
101
+ end
102
+ else
103
+ # vanilla cucumber table.
104
+ table.raw
105
+ end
106
+ end
107
+ end
108
+ RSpec.configure { |c| c.include Turnip::ExtraSteps::Support::TableStepsHelper}
109
+
110
+
111
+ # Check the content of tables in your HTML.
112
+ #
113
+ # See [this article](https://makandracards.com/makandra/763-cucumber-step-to-match-table-rows-with-capybara) for details.
114
+ #Then /^I should( not)? see a table with (exactly )?the following rows( in any order)?:?$/ do |negate, exactly, unordered, expected_table|
115
+ step "I :whether_to see a table with the following rows:" do |positive, expected_table|
116
+ patiently do
117
+ document = Nokogiri::HTML(page.body)
118
+ tables = document.xpath('//table').collect { |table| table.xpath('.//tr').collect { |row| row.xpath('.//th|td') } }
119
+ parsed_table = parse_table(expected_table)
120
+
121
+ options = { exactly: false , unordered: false }
122
+
123
+ if positive
124
+ expect(tables).to contain_table(parsed_table, options)
125
+ #tables.should contain_table(parsed_table, options)
126
+ else
127
+ expect(tables).not_to contain_table(parsed_table, options)
128
+ #tables.should_not contain_table(parsed_table, options)
129
+ end
130
+ end
131
+ end
132
+
133
+ step "I :whether_to see a table with exactly the following rows:" do |positive, expected_table|
134
+ patiently do
135
+ document = Nokogiri::HTML(page.body)
136
+ tables = document.xpath('//table').collect { |table| table.xpath('.//tr').collect { |row| row.xpath('.//th|td') } }
137
+ parsed_table = parse_table(expected_table)
138
+
139
+ options = { exactly: true, unordered: false }
140
+
141
+ if positive
142
+ expect(tables).to contain_table(parsed_table, options)
143
+ #tables.should contain_table(parsed_table, options)
144
+ else
145
+ expect(tables).not_to contain_table(parsed_table, options)
146
+ #tables.should_not contain_table(parsed_table, options)
147
+ end
148
+ end
149
+ end
150
+
151
+ step "I :whether_to see a table with the following rows in any order:" do |positive, expected_table|
152
+ patiently do
153
+ document = Nokogiri::HTML(page.body)
154
+ tables = document.xpath('//table').collect { |table| table.xpath('.//tr').collect { |row| row.xpath('.//th|td') } }
155
+ parsed_table = parse_table(expected_table)
156
+
157
+ options = { exactly: false, unordered: true }
158
+
159
+ if positive
160
+ expect(tables).to contain_table(parsed_table, options)
161
+ #tables.should contain_table(parsed_table, options)
162
+ else
163
+ expect(tables).not_to contain_table(parsed_table, options)
164
+ #tables.should_not contain_table(parsed_table, options)
165
+ end
166
+ end
167
+ end
168
+
169
+ step "I :whether_to see a table with exactly the following rows in any order:" do |positive, expected_table|
170
+ patiently do
171
+ document = Nokogiri::HTML(page.body)
172
+ tables = document.xpath('//table').collect { |table| table.xpath('.//tr').collect { |row| row.xpath('.//th|td') } }
173
+ parsed_table = parse_table(expected_table)
174
+
175
+ options = { exactly: true, unordered: true }
176
+
177
+ if positive
178
+ expect(tables).to contain_table(parsed_table, options)
179
+ #tables.should contain_table(parsed_table, options)
180
+ else
181
+ expect(tables).not_to contain_table(parsed_table, options)
182
+ #tables.should_not contain_table(parsed_table, options)
183
+ end
184
+ end
185
+ end
186
+
187
+