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,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,5 @@
1
+ module Turnip
2
+ module ExtraSteps
3
+ VERSION = "0.1.0"
4
+ end
5
+ 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}|&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