turnip-extra_steps 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/Guardfile +77 -0
- data/LICENSE +21 -0
- data/README.md +39 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/config.ru +16 -0
- data/lib/turnip/extra_steps.rb +8 -0
- data/lib/turnip/extra_steps/all_steps.rb +8 -0
- data/lib/turnip/extra_steps/development_steps.rb +32 -0
- data/lib/turnip/extra_steps/email_steps.rb +148 -0
- data/lib/turnip/extra_steps/file_attachment_steps.rb +43 -0
- data/lib/turnip/extra_steps/support.rb +2 -0
- data/lib/turnip/extra_steps/support/custom_matchers.rb +30 -0
- data/lib/turnip/extra_steps/support/mail_finder.rb +59 -0
- data/lib/turnip/extra_steps/support/path_selector_fallbacks.rb +38 -0
- data/lib/turnip/extra_steps/support/step_fallback.rb +13 -0
- data/lib/turnip/extra_steps/support/tolerance_for_selenium_sync_issues.rb +42 -0
- data/lib/turnip/extra_steps/support/version.rb +3 -0
- data/lib/turnip/extra_steps/support/web_steps_helpers.rb +114 -0
- data/lib/turnip/extra_steps/table_steps.rb +187 -0
- data/lib/turnip/extra_steps/timecop_steps.rb +79 -0
- data/lib/turnip/extra_steps/version.rb +5 -0
- data/lib/turnip/extra_steps/web_steps.rb +760 -0
- data/turnip-extra_steps.gemspec +42 -0
- metadata +354 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
|
4
|
+
# Steps to travel through time using [Timecop](https://github.com/jtrupiano/timecop).
|
5
|
+
#
|
6
|
+
# See [this article](https://makandracards.com/makandra/1222-useful-cucumber-steps-to-travel-through-time-with-timecop) for details.
|
7
|
+
# FILE_COMMENT_END
|
8
|
+
|
9
|
+
|
10
|
+
if defined?(Timecop)
|
11
|
+
|
12
|
+
module TimecopHarness
|
13
|
+
|
14
|
+
# When you have to make your rails app time zone aware you have to go 100%
|
15
|
+
# otherwise you are better off ignoring time zones at all.
|
16
|
+
# https://makandracards.com/makandra/8723-guide-to-localizing-a-rails-application
|
17
|
+
|
18
|
+
def use_timezones?
|
19
|
+
active_record_loaded = defined?(ActiveRecord::Base)
|
20
|
+
(!active_record_loaded || ActiveRecord::Base.default_timezone != :local) && Time.zone
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse_time(str)
|
24
|
+
if use_timezones?
|
25
|
+
Time.zone.parse(str)
|
26
|
+
else
|
27
|
+
Time.parse(str)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def current_time
|
32
|
+
if use_timezones?
|
33
|
+
Time.current
|
34
|
+
else
|
35
|
+
Time.now
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
World(TimecopHarness)
|
42
|
+
|
43
|
+
# Example:
|
44
|
+
#
|
45
|
+
# Given the date is 2012-02-10
|
46
|
+
# Given the time is 2012-02-10 13:40
|
47
|
+
When /^the (?:date|time) is "?(\d{4}-\d{2}-\d{2}(?: \d{1,2}:\d{2})?)"?$/ do |time|
|
48
|
+
Timecop.travel(parse_time(time))
|
49
|
+
end
|
50
|
+
|
51
|
+
# Example:
|
52
|
+
#
|
53
|
+
# Given the time is 13:40
|
54
|
+
When /^the time is "?(\d{1,2}:\d{2})"?$/ do |time_without_date|
|
55
|
+
Timecop.travel(parse_time(time_without_date)) # date will be today
|
56
|
+
end
|
57
|
+
|
58
|
+
# Example:
|
59
|
+
#
|
60
|
+
# When it is 10 minutes later
|
61
|
+
# When it is a few hours earlier
|
62
|
+
When /^it is (\d+|a|some|a few) (seconds?|minutes?|hours?|days?|weeks?|months?|years?) (later|earlier)$/ do |amount, unit, direction|
|
63
|
+
amount = case amount
|
64
|
+
when 'a'
|
65
|
+
1
|
66
|
+
when 'some', 'a few'
|
67
|
+
10
|
68
|
+
else
|
69
|
+
amount.to_i
|
70
|
+
end
|
71
|
+
amount = -amount if direction == 'earlier'
|
72
|
+
Timecop.travel(current_time + amount.send(unit))
|
73
|
+
end
|
74
|
+
|
75
|
+
After do
|
76
|
+
Timecop.return
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,760 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
# Most of cucumber-rails' original web steps plus a few of our own.
|
4
|
+
#
|
5
|
+
# Note that cucumber-rails deprecated all its steps quite a while ago with the following
|
6
|
+
# deprecation notice. Decide for yourself whether you want to use them:
|
7
|
+
#
|
8
|
+
# > This file was generated by Cucumber-Rails and is only here to get you a head start
|
9
|
+
# > These step definitions are thin wrappers around the Capybara/Webrat API that lets you
|
10
|
+
# > visit pages, interact with widgets and make assertions about page content.
|
11
|
+
#
|
12
|
+
# > If you use these step definitions as basis for your features you will quickly end up
|
13
|
+
# > with features that are:
|
14
|
+
#
|
15
|
+
# > * Hard to maintain
|
16
|
+
# > * Verbose to read
|
17
|
+
#
|
18
|
+
# > A much better approach is to write your own higher level step definitions, following
|
19
|
+
# > the advice in the following blog posts:
|
20
|
+
#
|
21
|
+
# > * http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
|
22
|
+
# > * http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/
|
23
|
+
# > * http://elabs.se/blog/15-you-re-cuking-it-wrong
|
24
|
+
#
|
25
|
+
# FILE_COMMENT_END
|
26
|
+
|
27
|
+
require 'turnip/extra_steps/support/tolerance_for_selenium_sync_issues'
|
28
|
+
require 'turnip/extra_steps/support/path_selector_fallbacks'
|
29
|
+
require 'turnip/extra_steps/support/step_fallback'
|
30
|
+
require 'turnip/extra_steps/support/custom_matchers'
|
31
|
+
require 'turnip/extra_steps/support/web_steps_helpers'
|
32
|
+
require 'uri'
|
33
|
+
require 'cgi'
|
34
|
+
|
35
|
+
|
36
|
+
# You can append `within [selector]` to any other web step
|
37
|
+
#
|
38
|
+
# Example:
|
39
|
+
#
|
40
|
+
# Then I should see "some text" within ".page_body"
|
41
|
+
#When /^(.*) within (.*[^:])$/ do |nested_step, parent|
|
42
|
+
step "Then I should see :text within :parent" do |text, parent|
|
43
|
+
with_scope(parent) { step(nested_step) }
|
44
|
+
end
|
45
|
+
|
46
|
+
# nodoc
|
47
|
+
#When /^(.*) within (.*[^:]):$/ do |nested_step, parent, table_or_string|
|
48
|
+
#with_scope(parent) { step("#{nested_step}:", table_or_string) }
|
49
|
+
#end
|
50
|
+
|
51
|
+
#Given /^(?:|I )am on (.+)$/ do |page_name|
|
52
|
+
step "I am on :page_name" do |page_name|
|
53
|
+
visit _path_to(page_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
#When /^(?:|I )go to (.+)$/ do |page_name|
|
57
|
+
step "I go to :page_name" do |page_name|
|
58
|
+
visit _path_to(page_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
#Then /^(?:|I )should be on (.+)$/ do |page_name|
|
62
|
+
step "I should be on :page_name" do |page_name|
|
63
|
+
patiently do
|
64
|
+
fragment = URI.parse(current_url).fragment
|
65
|
+
fragment.sub!(/[#?].*/, '') if fragment # most js frameworks will usually use ? and # for params, we dont care about those
|
66
|
+
current_path = URI.parse(current_url).path
|
67
|
+
current_path << "##{fragment}" if fragment.present?
|
68
|
+
expected_path = _path_to(page_name)
|
69
|
+
|
70
|
+
# Consider two pages equal if they only differ by a trailing slash.
|
71
|
+
current_path = expected_path if current_path.chomp("/") == expected_path.chomp("/")
|
72
|
+
current_path = expected_path if current_path.gsub("/#", "#") == expected_path.gsub("/#", "#")
|
73
|
+
|
74
|
+
expect(current_path).to eq(expected_path)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#When /^(?:|I )press "([^"]*)"$/ do |button|
|
79
|
+
step "I press on :button" do |button|
|
80
|
+
patiently do
|
81
|
+
click_button(button)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#When /^(?:|I )follow "([^"]*)"$/ do |link|
|
86
|
+
step "I follow :link" do |link|
|
87
|
+
patiently do
|
88
|
+
click_link(link)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Fill in text field
|
93
|
+
#When /^(?:|I )fill in "([^"]*)" (?:with|for) "([^"]*)"$/ do |field, value|
|
94
|
+
step "I fill in :field with :value" do |field, value|
|
95
|
+
patiently do
|
96
|
+
fill_in(field, :with => value)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Fill in text field with multi-line block
|
101
|
+
# You can use a doc string to supply multi-line text
|
102
|
+
#
|
103
|
+
# Example:
|
104
|
+
#
|
105
|
+
# When I fill in "some field" with:
|
106
|
+
# """
|
107
|
+
# Apple
|
108
|
+
# Banana
|
109
|
+
# Pear
|
110
|
+
# """
|
111
|
+
#When /^(?:|I )fill in "([^"]*)" (?:with|for):$/ do |field, value|
|
112
|
+
step "I fill in :field with:" do |field, value|
|
113
|
+
patiently do
|
114
|
+
fill_in(field, :with => value)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Fill in text field
|
119
|
+
#When /^(?:|I )fill in "([^"]*)" (?:with|for) '(.*)'$/ do |field, value|
|
120
|
+
#step "I fill in :field with :value" do |field, value|
|
121
|
+
#patiently do
|
122
|
+
#fill_in(field, :with => value)
|
123
|
+
#end
|
124
|
+
#end
|
125
|
+
|
126
|
+
# Select from select box
|
127
|
+
#When /^(?:|I )select "([^"]*)" from "([^"]*)"$/ do |value, field|
|
128
|
+
step "I select :value from :field" do |value, field|
|
129
|
+
patiently do
|
130
|
+
select(value, :from => field)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Check a checkbox
|
135
|
+
#When /^(?:|I )check "([^"]*)"$/ do |field|
|
136
|
+
step "I check :field" do |field|
|
137
|
+
patiently do
|
138
|
+
check(field)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Uncheck a checkbox
|
143
|
+
#When /^(?:|I )uncheck "([^"]*)"$/ do |field|
|
144
|
+
step "I uncheck :field" do |field|
|
145
|
+
patiently do
|
146
|
+
uncheck(field)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Select a radio button
|
151
|
+
#When /^(?:|I )choose "([^"]*)"$/ do |field|
|
152
|
+
step "I choose :field" do |field|
|
153
|
+
patiently do
|
154
|
+
choose(field)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Attach a file to a file upload form field
|
159
|
+
#When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"$/ do |path, field|
|
160
|
+
step "I attach the file :path to :field" do |path, field|
|
161
|
+
patiently do
|
162
|
+
attach_file(field, File.expand_path(path))
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Checks that some text appears on the page
|
167
|
+
#
|
168
|
+
# Note that this does not detect if the text might be hidden via CSS
|
169
|
+
#Then /^(?:|I )should see "([^"]*)"$/ do |text|
|
170
|
+
step "I should see :text" do |text|
|
171
|
+
patiently do
|
172
|
+
page.should have_content(text)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Checks that a regexp appears on the page
|
177
|
+
#
|
178
|
+
# Note that this does not detect if the text might be hidden via CSS
|
179
|
+
#Then /^(?:|I )should see \/([^\/]*)\/$/ do |regexp|
|
180
|
+
step "I should see :regexp regexp" do |regexp|
|
181
|
+
regexp = Regexp.new(regexp)
|
182
|
+
patiently do
|
183
|
+
page.should have_xpath('//*', :text => regexp)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
#Then /^(?:|I )should not see "([^"]*)"$/ do |text|
|
188
|
+
step "I should not see :text" do |text|
|
189
|
+
patiently do
|
190
|
+
page.should have_no_content(text)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
#Then /^(?:|I )should not see \/([^\/]*)\/$/ do |regexp|
|
195
|
+
step "I should not see :regexp regexp" do |regexp|
|
196
|
+
patiently do
|
197
|
+
regexp = Regexp.new(regexp)
|
198
|
+
page.should have_no_xpath('//*', :text => regexp)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
# Checks that an input field contains some value (allowing * as wildcard character)
|
204
|
+
#Then /^the "([^"]*)" field should (not )?contain "([^"]*)"$/ do |label, negate, expected_string|
|
205
|
+
step "the :label field :whether_to contain :expected_string" do |label, positive, expected_string|
|
206
|
+
patiently do
|
207
|
+
field = find_field(label)
|
208
|
+
field_value = case field.tag_name
|
209
|
+
when 'select'
|
210
|
+
options = field.all('option')
|
211
|
+
selected_option = options.detect(&:selected?) || options.first
|
212
|
+
if selected_option && selected_option.text.present?
|
213
|
+
selected_option.text.strip
|
214
|
+
else
|
215
|
+
''
|
216
|
+
end
|
217
|
+
else
|
218
|
+
field.value
|
219
|
+
end
|
220
|
+
if positive
|
221
|
+
expect(field_value).to contain_with_wildcards(expected_string)
|
222
|
+
else
|
223
|
+
expect(field_value).not_to contain_with_wildcards(expected_string)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Checks that a multiline textarea contains some value (allowing * as wildcard character)
|
229
|
+
#Then(/^the "(.*?)" field should (not )?contain:$/) do |label, negate, expected_string|
|
230
|
+
step "the :label field :whether_to contain:" do |label, positive, expected_string|
|
231
|
+
patiently do
|
232
|
+
field = find_field(label)
|
233
|
+
if positive
|
234
|
+
expect(field.value.chomp).to contain_with_wildcards(expected_string)
|
235
|
+
else
|
236
|
+
expect(field.value.chomp).not_to contain_with_wildcards(expected_string)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Checks that a list of label/value pairs are visible as control inputs.
|
242
|
+
#
|
243
|
+
# Example:
|
244
|
+
#
|
245
|
+
# Then I should see a form with the following values:
|
246
|
+
# | E-mail | foo@bar.com |
|
247
|
+
# | Role | Administrator |
|
248
|
+
#
|
249
|
+
#Then /^I should see a form with the following values:$/ do |table|
|
250
|
+
step "I should see a form with the following values:" do |table|
|
251
|
+
expectations = table.raw
|
252
|
+
expectations.each do |label, expected_value|
|
253
|
+
step %(the "#{label}" field should contain "#{expected_value}")
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
# Checks that an input field was wrapped with a validation error
|
258
|
+
#Then /^the "([^"]*)" field should have the error "([^"]*)"$/ do |field, error_message|
|
259
|
+
step "the :field should have the error :error_message" do |field, error_message|
|
260
|
+
patiently do
|
261
|
+
element = find_field(field)
|
262
|
+
classes = element.find(:xpath, '..')[:class].split(' ')
|
263
|
+
|
264
|
+
form_for_input = element.find(:xpath, 'ancestor::form[1]')
|
265
|
+
using_formtastic = form_for_input[:class].include?('formtastic')
|
266
|
+
error_class = using_formtastic ? 'error' : 'field_with_errors'
|
267
|
+
|
268
|
+
classes.should include(error_class)
|
269
|
+
|
270
|
+
if using_formtastic
|
271
|
+
error_paragraph = element.find(:xpath, '../*[@class="inline-errors"][1]')
|
272
|
+
error_paragraph.should have_content(error_message)
|
273
|
+
else
|
274
|
+
page.should have_content("#{field.titlecase} #{error_message}")
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
#Then /^the "([^\"]*)" field should( not)? have an error$/ do |label, negate|
|
280
|
+
step "the :label field :whether_to have an error" do |label, positive|
|
281
|
+
patiently do
|
282
|
+
expectation = positive ? :should : :should_not
|
283
|
+
field = find_field(label)
|
284
|
+
field[:id].should be_present # prevent bad CSS selector if field lacks id
|
285
|
+
page.send(expectation, have_css(".field_with_errors ##{field[:id]}"))
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
#Then /^the "([^"]*)" field should have no error$/ do |field|
|
290
|
+
step "the :field should have no error" do |field|
|
291
|
+
patiently do
|
292
|
+
element = find_field(field)
|
293
|
+
classes = element.find(:xpath, '..')[:class].split(' ')
|
294
|
+
classes.should_not include('field_with_errors')
|
295
|
+
classes.should_not include('error')
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
# nodoc
|
300
|
+
#Then /^the "([^"]*)" checkbox should( not)? be checked$/ do |label, negate|
|
301
|
+
step "the :label checkbox :whether_to be checked" do |label, positive|
|
302
|
+
patiently do
|
303
|
+
field = find_field(label)
|
304
|
+
if positive
|
305
|
+
expect(field).to be_checked
|
306
|
+
else
|
307
|
+
expect(field).not_to be_checked
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
#Then /^the radio button "([^"]*)" should( not)? be (?:checked|selected)$/ do |field, negate|
|
313
|
+
step "the radio button :field :whether_to be checked/selected" do |positive, action|
|
314
|
+
patiently do
|
315
|
+
expectation = positive ? :has_checked_field? : :has_no_checked_field?
|
316
|
+
page.send(expectation, field).should == true
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
# Example:
|
321
|
+
#
|
322
|
+
# I should have the following query string:
|
323
|
+
# | locale | de |
|
324
|
+
# | currency_code | EUR |
|
325
|
+
#
|
326
|
+
# Succeeds when the URL contains the given `locale` and `currency_code` params
|
327
|
+
#Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
|
328
|
+
step "I should have the following query string:" do |expected_pairs|
|
329
|
+
patiently do
|
330
|
+
query = URI.parse(current_url).query
|
331
|
+
actual_params = query ? CGI.parse(query) : {}
|
332
|
+
expected_params = {}
|
333
|
+
expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
|
334
|
+
|
335
|
+
actual_params.should == expected_params
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
# Open the current Capybara page using the `launchy` gem
|
340
|
+
#Then /^show me the page$/ do
|
341
|
+
step "show me the page" do
|
342
|
+
save_and_open_page
|
343
|
+
end
|
344
|
+
|
345
|
+
|
346
|
+
# Checks for the existance of an input field (given its id or label)
|
347
|
+
#Then /^I should( not)? see a field "([^"]*)"$/ do |negate, name|
|
348
|
+
step "I should :whether_to see a field :name" do |positive, name|
|
349
|
+
expectation = positive ? :should : :should_not
|
350
|
+
patiently do
|
351
|
+
begin
|
352
|
+
field = find_field(name)
|
353
|
+
rescue Capybara::ElementNotFound
|
354
|
+
# In Capybara 0.4+ #find_field raises an error instead of returning nil
|
355
|
+
end
|
356
|
+
field.send(expectation, be_present)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
# Use this step to test for a number or money amount instead of a simple `Then I should see`
|
361
|
+
#
|
362
|
+
# Checks for an unexpected minus sign, correct decimal places etc.
|
363
|
+
#
|
364
|
+
# See [here](https://makandracards.com/makandra/1225-test-that-a-number-or-money-amount-is-shown-with-cucumber) for details
|
365
|
+
#Then /^I should( not)? see the (?:number|amount) ([\-\d,\.]+)(?: (.*?))?$/ do |negate, amount, unit|
|
366
|
+
step "I should :whether_to see the number/amount :amount :unit" do |positive, amount, unit|
|
367
|
+
no_minus = amount.starts_with?('-') ? '' : '[^\\-]'
|
368
|
+
nbsp = " "
|
369
|
+
regexp = Regexp.new(no_minus + "\\b" + Regexp.quote(amount) + (unit ? "( |#{nbsp}| )(#{unit}|#{Regexp.quote(HTMLEntities.new.encode(unit, :named))})" :"\\b"))
|
370
|
+
expectation = positive ? :should : :should_not
|
371
|
+
patiently do
|
372
|
+
page.body.send(expectation, match(regexp))
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
# Checks `Content-Type` HTTP header
|
377
|
+
#Then /^I should get a response with content-type "([^\"]*)"$/ do |expected_content_type|
|
378
|
+
step "I should get a response with context-type :expected_content_type" do |expected_content_type|
|
379
|
+
page.response_headers['Content-Type'].should =~ /\A#{Regexp.quote(expected_content_type)}($|;)/
|
380
|
+
end
|
381
|
+
|
382
|
+
# Checks `Content-Disposition` HTTP header
|
383
|
+
#
|
384
|
+
# Attention: Doesn't work with Selenium, see https://github.com/jnicklas/capybara#gotchas
|
385
|
+
#Then /^I should get a download with filename "([^\"]*)"$/ do |filename|
|
386
|
+
step "I should get a download with filename :filename" do |filename|
|
387
|
+
page.response_headers['Content-Disposition'].should =~ /filename="#{filename}"$/
|
388
|
+
end
|
389
|
+
|
390
|
+
# Checks that a certain option is selected for a text field
|
391
|
+
#Then /^"([^"]*)" should be selected for "([^"]*)"$/ do |value, field|
|
392
|
+
step ":value should be selected for :field" do |value, field|
|
393
|
+
step %(the "#{field}" field should contain "#{value}")
|
394
|
+
end
|
395
|
+
|
396
|
+
#Then /^nothing should be selected for "([^"]*)"?$/ do |field|
|
397
|
+
step "nothing should be selected for :field" do |field|
|
398
|
+
patiently do
|
399
|
+
select = find_field(field)
|
400
|
+
begin
|
401
|
+
select.find(:xpath, ".//option[@selected = 'selected']").should be_blank
|
402
|
+
rescue Capybara::ElementNotFound
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
# Checks for the presence of an option in a select
|
408
|
+
#Then /^"([^"]*)" should( not)? be an option for "([^"]*)"$/ do |value, negate, field|
|
409
|
+
step ":value :whether_to be an option for :field" do |value, positive, field|
|
410
|
+
patiently do
|
411
|
+
xpath = ".//option[text() = '#{value}']"
|
412
|
+
if positive
|
413
|
+
field_labeled(field).find(:xpath, xpath).should be_present
|
414
|
+
else
|
415
|
+
begin
|
416
|
+
field_labeled(field).find(:xpath, xpath).should_not be_present
|
417
|
+
rescue Capybara::ElementNotFound
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
# Like `Then I should see`, but with single instead of double quotes. In case
|
424
|
+
# the expected string contains quotes as well.
|
425
|
+
#Then /^(?:|I )should see '([^']*)'$/ do |text|
|
426
|
+
step "I should see :text" do |text|
|
427
|
+
patiently do
|
428
|
+
page.should have_content(text)
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
# Check that the raw HTML contains a string
|
433
|
+
#Then /^I should see "([^\"]*)" in the HTML$/ do |text|
|
434
|
+
step "I should see :text in the HTML" do |text|
|
435
|
+
patiently do
|
436
|
+
page.body.should include(text)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
#Then /^I should not see "([^\"]*)" in the HTML$/ do |text|
|
441
|
+
step "I should not see :text in the HTML" do |text|
|
442
|
+
patiently do
|
443
|
+
page.body.should_not include(text)
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
# Checks that status code is 400..599
|
448
|
+
#Then /^I should see an error$/ do
|
449
|
+
step "I should see an error" do
|
450
|
+
(400 .. 599).should include(page.status_code)
|
451
|
+
end
|
452
|
+
|
453
|
+
#nodoc
|
454
|
+
#Then /^the window should be titled "([^"]*)"$/ do |title|
|
455
|
+
step "the window should be title :title" do |title|
|
456
|
+
patiently do
|
457
|
+
page.should have_css('title', :text => title)
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
#When /^I reload the page$/ do
|
462
|
+
step "I reload the page" do
|
463
|
+
case Capybara::current_driver
|
464
|
+
when :selenium
|
465
|
+
page.execute_script(<<-JAVASCRIPT)
|
466
|
+
window.location.reload(true);
|
467
|
+
JAVASCRIPT
|
468
|
+
else
|
469
|
+
visit current_path
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
# Checks that an element is actually present and visible, also considering styles.
|
474
|
+
# Within a selenium test, the browser is asked whether the element is really visible
|
475
|
+
# In a non-selenium test, we only check for `.hidden`, `.invisible` or `style: display:none`
|
476
|
+
#
|
477
|
+
# The step 'Then (the tag )?"..." should **not** be visible' is ambiguous. Please use 'Then (the tag )?"..." should be hidden' or 'Then I should not see "..."' instead.
|
478
|
+
#
|
479
|
+
# More details [here](https://makandracards.com/makandra/1049-capybara-check-that-a-page-element-is-hidden-via-css)
|
480
|
+
#Then /^(the tag )?"([^\"]+)" should( not)? be visible$/ do |tag, selector_or_text, hidden|
|
481
|
+
step "the tag :selector_or_text :whether_to be visible" do |selector_or_text, positive|
|
482
|
+
unless positive
|
483
|
+
warn "The step 'Then ... should not be visible' is ambiguous. Please use 'Then ... should be hidden' or 'Then I should not see ...' instead."
|
484
|
+
end
|
485
|
+
|
486
|
+
options = {}
|
487
|
+
options.store(:selector, selector_or_text)
|
488
|
+
|
489
|
+
positive ? assert_visible(options) : assert_hidden(options)
|
490
|
+
end
|
491
|
+
|
492
|
+
step ":selector_or_text :whether_to be visible" do |selector_or_text, positive|
|
493
|
+
unless positive
|
494
|
+
warn "The step 'Then ... should not be visible' is ambiguous. Please use 'Then ... should be hidden' or 'Then I should not see ...' instead."
|
495
|
+
end
|
496
|
+
|
497
|
+
options = {}
|
498
|
+
options.store(:text, selector_or_text)
|
499
|
+
|
500
|
+
positive ? assert_visible(options) : assert_hidden(options)
|
501
|
+
end
|
502
|
+
|
503
|
+
|
504
|
+
|
505
|
+
# Checks that an element is actually present and hidden, also considering styles.
|
506
|
+
# Within a selenium test, the browser is asked whether the element is really hidden.
|
507
|
+
# In a non-selenium test, we only check for `.hidden`, `.invisible` or `style: display:none`
|
508
|
+
#Then /^(the tag )?"([^\"]+)" should be hidden$/ do |tag, selector_or_text|
|
509
|
+
step "the tag :selector_or_text should be hidden" do |selector_or_text|
|
510
|
+
options = {}
|
511
|
+
options.store(:selector, selector_or_text)
|
512
|
+
|
513
|
+
assert_hidden(options)
|
514
|
+
end
|
515
|
+
|
516
|
+
#Then /^(the tag )?"([^\"]+)" should be hidden$/ do |tag, selector_or_text|
|
517
|
+
step ":selector_or_text should be hidden" do |selector_or_text|
|
518
|
+
options = {}
|
519
|
+
options.store(:text, selector_or_text)
|
520
|
+
|
521
|
+
assert_hidden(options)
|
522
|
+
end
|
523
|
+
|
524
|
+
|
525
|
+
|
526
|
+
# Click on some text that might not be a link
|
527
|
+
#When /^I click on "([^\"]+)"$/ do |text|
|
528
|
+
step "I click on :text" do |text|
|
529
|
+
patiently do
|
530
|
+
contains_text = %{contains(., \"#{text}\")}
|
531
|
+
# find the innermost selector that matches
|
532
|
+
element = page.find(:xpath, ".//*[#{contains_text} and not (./*[#{contains_text}])]")
|
533
|
+
element.click
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
# Use this step to check external links.
|
538
|
+
#
|
539
|
+
# Example:
|
540
|
+
#
|
541
|
+
# Then "Sponsor" should link to "http://makandra.com"
|
542
|
+
#
|
543
|
+
#Then /^"([^"]*)" should link to "([^"]*)"$/ do |link_label, target|
|
544
|
+
step ":link_label should link to :target" do |link_label, target|
|
545
|
+
patiently do
|
546
|
+
link = find_link(link_label)
|
547
|
+
link[:href].should =~ /#{Regexp.escape target}(\?[^\/]*)?$/ # ignore trailing timestamps
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
# Example:
|
552
|
+
#
|
553
|
+
# Then I should see an element ".page .container"
|
554
|
+
#
|
555
|
+
#Then /^I should (not )?see an element "([^"]*)"$/ do |negate, selector|
|
556
|
+
step "I :whether_to see an element :selector" do |positive, selector|
|
557
|
+
expectation = positive ? :should : :should_not
|
558
|
+
patiently do
|
559
|
+
page.send(expectation, have_css(selector))
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
# Checks that the result has content type `text/plain`
|
564
|
+
#Then /^I should get a text response$/ do
|
565
|
+
step "I should get a text response" do
|
566
|
+
step 'I should get a response with content-type "text/plain"'
|
567
|
+
end
|
568
|
+
|
569
|
+
# Click a link within an element matching the given selector. Will try to be clever
|
570
|
+
# and disregard elements that don't contain a matching link.
|
571
|
+
#
|
572
|
+
# Example:
|
573
|
+
#
|
574
|
+
# When I follow "Read more" inside any ".text_snippet"
|
575
|
+
#
|
576
|
+
#When /^I follow "([^"]*)" inside any "([^"]*)"$/ do |label, selector|
|
577
|
+
step "I follow :label inside my :selector" do
|
578
|
+
node = find("#{selector} a", :text => label)
|
579
|
+
node.click
|
580
|
+
end
|
581
|
+
|
582
|
+
#Then /^I should( not)? see "([^"]*)" inside any "([^"]*)"$/ do |negate, text, selector|
|
583
|
+
step "I :whether_to see :text inside my :selector" do |positive, text, selector|
|
584
|
+
expectation = positive ? :should : :should_not
|
585
|
+
page.send(expectation, have_css(selector, :text => text))
|
586
|
+
end
|
587
|
+
|
588
|
+
#When /^I fill in "([^"]*)" with "([^"]*)" inside any "([^"]*)"$/ do |field, value, selector|
|
589
|
+
step "I fill in :field with :value inside any :selector" do |field, value, selector|
|
590
|
+
containers = all(:css, selector)
|
591
|
+
input = nil
|
592
|
+
containers.detect do |container|
|
593
|
+
input = container.first(:xpath, XPath::HTML.fillable_field(field))
|
594
|
+
end
|
595
|
+
if input
|
596
|
+
input.set(value)
|
597
|
+
else
|
598
|
+
raise "Could not find an input field \"#{field}\" inside any \"#{selector}\""
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
#When /^I confirm the browser dialog$/ do
|
603
|
+
step "I confirm the browser dialog" do
|
604
|
+
page.driver.browser.switch_to.alert.accept
|
605
|
+
end
|
606
|
+
|
607
|
+
#When /^I cancel the browser dialog$/ do
|
608
|
+
step "I cancel the browser dialog" do
|
609
|
+
page.driver.browser.switch_to.alert.dismiss
|
610
|
+
end
|
611
|
+
|
612
|
+
#When /^I enter "([^"]*)" into the browser dialog$/ do |text|
|
613
|
+
step "I enter :text into the browser dialog" do
|
614
|
+
alert = page.driver.browser.switch_to.alert
|
615
|
+
alert.send_keys(text)
|
616
|
+
alert.accept
|
617
|
+
end
|
618
|
+
|
619
|
+
#When /^I switch to the new tab$/ do
|
620
|
+
step "I switch to the new tab" do
|
621
|
+
Capybara::current_driver == :selenium or raise("This step works only with selenium")
|
622
|
+
page.driver.browser.switch_to.window(page.driver.browser.window_handles.last)
|
623
|
+
end
|
624
|
+
|
625
|
+
# Checks that these strings are rendered in the given order in a single line or in multiple lines
|
626
|
+
#
|
627
|
+
# Example:
|
628
|
+
#
|
629
|
+
# Then I should see in this order:
|
630
|
+
# | Alpha Group |
|
631
|
+
# | Augsburg |
|
632
|
+
# | Berlin |
|
633
|
+
# | Beta Group |
|
634
|
+
#
|
635
|
+
#Then /^I should see in this order:?$/ do |text|
|
636
|
+
step "I should see in this order:" do |text|
|
637
|
+
if text.is_a?(String)
|
638
|
+
lines = text.split(/\n/)
|
639
|
+
else
|
640
|
+
lines = text.raw.flatten
|
641
|
+
end
|
642
|
+
lines = lines.collect { |line| line.gsub(/\s+/, ' ')}.collect(&:strip).reject(&:blank?)
|
643
|
+
pattern = lines.collect(&Regexp.method(:quote)).join('.*?')
|
644
|
+
pattern = Regexp.compile(pattern)
|
645
|
+
patiently do
|
646
|
+
page.text.gsub(/\s+/, ' ').should =~ pattern
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
650
|
+
# Tests that an input or button with the given label is disabled.
|
651
|
+
#Then /^the "([^\"]*)" (field|button) should( not)? be disabled$/ do |label, kind, negate|
|
652
|
+
step "the :label :kind :wether_to be disabled" do |label, kind, positive|
|
653
|
+
if kind == 'field'
|
654
|
+
element = find_field(label)
|
655
|
+
else
|
656
|
+
element = find_button(label)
|
657
|
+
end
|
658
|
+
expectation = positive ? :should : :should_not
|
659
|
+
["false", "", nil].send(expectation, include(element[:disabled]))
|
660
|
+
end
|
661
|
+
|
662
|
+
# Tests that a field with the given label is visible.
|
663
|
+
#Then /^the "([^\"]*)" field should( not)? be visible$/ do |label, hidden|
|
664
|
+
step "the :label field :whether_to be visible" do |label, positive|
|
665
|
+
field = find_field(label)
|
666
|
+
|
667
|
+
case Capybara::current_driver
|
668
|
+
when :selenium, :webkit
|
669
|
+
patiently do
|
670
|
+
visibility_detecting_javascript = %[
|
671
|
+
(function(){
|
672
|
+
var field = $('##{field['id']}');
|
673
|
+
return(field.is(':visible'));
|
674
|
+
})();
|
675
|
+
].gsub(/\n/, ' ')
|
676
|
+
page.evaluate_script(visibility_detecting_javascript).should == !hidden
|
677
|
+
end
|
678
|
+
else
|
679
|
+
expectation = positive ? :should : :should_not
|
680
|
+
field.send(expectation, be_visible)
|
681
|
+
end
|
682
|
+
end
|
683
|
+
|
684
|
+
# Waits for the page to finish loading and AJAX requests to finish.
|
685
|
+
#
|
686
|
+
# More details [here](https://makandracards.com/makandra/12139-waiting-for-page-loads-and-ajax-requests-to-finish-with-capybara).
|
687
|
+
#When /^I wait for the page to load$/ do
|
688
|
+
step "I wait for the page to load" do
|
689
|
+
if [:selenium, :webkit, :poltergeist].include?(Capybara.current_driver)
|
690
|
+
patiently do
|
691
|
+
# when no jQuery is loaded, we assume there are no pending AJAX requests
|
692
|
+
page.evaluate_script("typeof jQuery === 'undefined' || $.active == 0").should == true
|
693
|
+
end
|
694
|
+
end
|
695
|
+
page.has_content? ''
|
696
|
+
end
|
697
|
+
|
698
|
+
# Performs HTTP basic authentication with the given credentials and visits the given path.
|
699
|
+
#
|
700
|
+
# More details [here](https://makandracards.com/makandra/971-perform-http-basic-authentication-in-cucumber).
|
701
|
+
#When /^I perform basic authentication as "([^\"]*)\/([^\"]*)" and go to (.*)$/ do |user, password, page_name|
|
702
|
+
step "I perform basic authentication as :user/:password and go to :page_name" do |user, password, page_name|
|
703
|
+
path = _path_to(page_name)
|
704
|
+
if Capybara::current_driver == :selenium
|
705
|
+
visit("http://#{user}:#{password}@#{page.driver.rack_server.host}:#{page.driver.rack_server.port}#{path}")
|
706
|
+
else
|
707
|
+
authorizers = [
|
708
|
+
(page.driver.browser if page.driver.respond_to?(:browser)),
|
709
|
+
(self),
|
710
|
+
(page.driver)
|
711
|
+
].compact
|
712
|
+
authorizer = authorizers.detect { |authorizer| authorizer.respond_to?(:basic_authorize) }
|
713
|
+
authorizer.basic_authorize(user, password)
|
714
|
+
visit path
|
715
|
+
end
|
716
|
+
end
|
717
|
+
|
718
|
+
# Goes to the previously viewed page.
|
719
|
+
#When /^I go back$/ do
|
720
|
+
step "I go back" do
|
721
|
+
case Capybara::current_driver
|
722
|
+
when :selenium, :webkit
|
723
|
+
page.evaluate_script('window.history.back()')
|
724
|
+
else
|
725
|
+
if page.driver.respond_to?(:browser)
|
726
|
+
visit page.driver.browser.last_request.env['HTTP_REFERER']
|
727
|
+
else
|
728
|
+
visit page.driver.last_request.env['HTTP_REFERER']
|
729
|
+
end
|
730
|
+
end
|
731
|
+
end
|
732
|
+
|
733
|
+
# Tests whether a select field is sorted. Uses Array#natural_sort, if defined;
|
734
|
+
# Array#sort else.
|
735
|
+
#Then /^the "(.*?)" select should( not)? be sorted$/ do |label, negate|
|
736
|
+
step "the :label select :whether_to be sorted" do |label, positive|
|
737
|
+
select = find_field(label)
|
738
|
+
options = select.all('option').reject { |o| o.value.blank? }
|
739
|
+
option_texts = options.collect(&:text)
|
740
|
+
|
741
|
+
if positive
|
742
|
+
expect(option_texts).to be_sorted
|
743
|
+
else
|
744
|
+
expect(option_texts).not_to be_sorted
|
745
|
+
end
|
746
|
+
end
|
747
|
+
|
748
|
+
placeholder :whether_to do
|
749
|
+
match /should not/ do
|
750
|
+
false
|
751
|
+
end
|
752
|
+
|
753
|
+
match /should/ do
|
754
|
+
true
|
755
|
+
end
|
756
|
+
end
|
757
|
+
# step 'I :whether_to see :text' do |positive, text|
|
758
|
+
# expectation = positive ? :to : :not_to
|
759
|
+
# expect(page.body).send expectation, eq(text)
|
760
|
+
# end
|