spreewald 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -28,58 +28,426 @@ Alternatively, you can require everything by doing
28
28
 
29
29
  require 'spreewald/all_steps'
30
30
 
31
+ ## Waiting for page load
32
+
33
+ Spreewald's web steps are all aware, that you might run them with a Selenium/Capybara webdriver, and wait for the browser to finish loading the page, if necessary.
34
+
35
+ This is done, by rerunning any assertions until they suceed, or a timeout is reached.
36
+
37
+ You can achieve this in your own steps by wrapping them inside a `patiently do` block, like
38
+
39
+ Then /^I should see "([^\"]*)" in the HTML$/ do |text|
40
+ patiently do
41
+ page.body.should include(text)
42
+ end
43
+ end
44
+
45
+ More info [here](https://makandracards.com/makandra/12139-waiting-for-page-load-with-spreewald).
46
+
31
47
  ## Steps
32
48
 
33
- For a complete list of steps you have to take a look at the step definitions themselves. This is just a rough overview.
49
+ ### development_steps.rb
50
+
51
+
52
+
53
+ * **Then it should work**
54
+
55
+ Marks scenario as pending
56
+
57
+
58
+ * **Then debugger**
59
+
60
+ Starts debugger
61
+
62
+
63
+ * **@slow**
64
+
65
+ Waits 2 seconds after each step
66
+
67
+
68
+ * **@single**
69
+
70
+ Waits for keypress after each step
71
+
72
+
73
+
74
+ ### email_steps.rb
75
+
76
+
34
77
 
35
- ### [development_steps](/makandra/spreewald/blob/master/lib/spreewald/development_steps.rb)
78
+ * **When I clear my emails**
36
79
 
37
- Some development steps. Supports
80
+
38
81
 
39
- * `Then debugger`
40
- * `Then it should work` (marks step as pending)
41
- * `@slow-motion` (waits 2 seconds after each step)
42
- * `@single-step` (waits for keyboard input after each step)
43
82
 
83
+ * **Then (an|no) e?mail should have been sent with:**
44
84
 
45
- ### [email_steps](/makandra/spreewald/blob/master/lib/spreewald/email_steps.rb)
85
+ Example:
86
+
87
+ Then an email should have been sent with:
88
+ """
89
+ From: max.mustermann@example.com
90
+ To: john.doe@example.com
91
+ Subject: Unter anderem der Betreff kann auch "Anführungszeichen" enthalten
92
+ Body: ...
93
+ Attachments: ...
94
+ """
95
+
96
+ You can skip lines, of course.
46
97
 
47
- Check for the existance of an email with
48
98
 
49
- Then an email should have been sent with:
50
- """
51
- From: max.mustermann@example.com
52
- To: john.doe@example.com
53
- Subject: Unter anderem der Betreff kann auch "Anführungszeichen" enthalten
54
- Body: ...
55
- Attachments: ...
56
- """
99
+ * **When I follow the (first|second|third)? link in the e?mail**
57
100
 
58
- You can obviously skip lines.
101
+ Only works after you have retrieved the mail using "Then an email should have been sent with:"
59
102
 
60
- After you have used that step, you can also check for content with
61
103
 
62
- And that mail should have the following lines in the body:
63
- """
64
- Jede dieser Text-Zeilen
65
- muss irgendwo im Body vorhanden sein
66
- """
104
+ * **Then no e?mail should have been sent**
67
105
 
68
- ### [table_steps](/makandra/spreewald/blob/master/lib/spreewald/table_steps.rb)
106
+
107
+
108
+
109
+ * **Then I should see "..." in the e?mail**
110
+
111
+ Checks that the last sent email includes some text
112
+
113
+
114
+ * **Then show me the e?mails**
115
+
116
+ Print all sent emails to STDOUT.
117
+
118
+
119
+ * **Then that e?mail should have the following lines in the body:**
120
+
121
+ Only works after you've retrieved the email using "Then an email should have been sent with:"
122
+
123
+ Example:
124
+
125
+ And that mail should have the following lines in the body:
126
+ """
127
+ All of these lines
128
+ need to be present
129
+ """
130
+
131
+
132
+ * **Then that e?mail should have the following body:**
133
+
134
+ Only works after you've retrieved the email using "Then an email should have been sent with:"
135
+ Checks that the text should be included in the retrieved email
136
+
137
+
138
+
139
+ ### table_steps.rb
69
140
 
70
141
  Check the content of tables in your HTML.
71
142
 
72
143
  See [this article](https://makandracards.com/makandra/763-cucumber-step-to-match-table-rows-with-capybara) for details.
73
144
 
145
+ * **Then I should( not)? see a table with the following rows( in any order)?**
146
+
147
+
148
+
149
+
74
150
 
75
- ### [timecop_steps](/makandra/spreewald/blob/master/lib/spreewald/timecop_steps.rb)
151
+ ### timecop_steps.rb
76
152
 
77
153
  Steps to travel through time using [Timecop](https://github.com/jtrupiano/timecop).
78
154
 
79
155
  See [this article](https://makandracards.com/makandra/1222-useful-cucumber-steps-to-travel-through-time-with-timecop) for details.
80
156
 
81
- ### [web_steps](/makandra/spreewald/blob/master/lib/spreewald/web_steps.rb)
157
+ * **When the (date|time) is "(\d{4}-\d{2}-\d{2}( \d{1,2}:\d{2})?)"**
158
+
159
+ Example:
160
+
161
+ Given the date is "2012-02-10"
162
+ Given the time is "2012-02-10 13:40"
163
+
164
+
165
+ * **When the time is "(\d{1,2}:\d{2})"**
166
+
167
+ Example:
168
+
169
+ Given the time is "13:40"
170
+
171
+
172
+ * **When it is (\d+|a|some|a few) (seconds?|minutes?|hours?|days?|weeks?|months?|years?) (later|earlier)**
173
+
174
+ Example:
175
+
176
+ When it is 10 minutes later
177
+ When it is a few hours earlier
178
+
179
+
180
+
181
+ ### web_steps.rb
182
+
183
+ Most of cucumber-rails' original web steps plus a few of our own.
184
+
185
+ Note that cucumber-rails deprecated all its steps quite a while ago with the following
186
+ deprecation notice. Decide for yourself whether you want to use them:
187
+
188
+ > This file was generated by Cucumber-Rails and is only here to get you a head start
189
+ > These step definitions are thin wrappers around the Capybara/Webrat API that lets you
190
+ > visit pages, interact with widgets and make assertions about page content.
191
+
192
+ > If you use these step definitions as basis for your features you will quickly end up
193
+ > with features that are:
194
+
195
+ > * Hard to maintain
196
+ > * Verbose to read
197
+
198
+ > A much better approach is to write your own higher level step definitions, following
199
+ > the advice in the following blog posts:
200
+
201
+ > * http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
202
+ > * http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/
203
+ > * http://elabs.se/blog/15-you-re-cuking-it-wrong
204
+
205
+
206
+ * **When ... within (.*[^:])**
207
+
208
+ You can append 'within [selector]' to any other web step
209
+ Example:
210
+
211
+ Then I should see "some text" within ".page_body"
212
+
213
+
214
+ * **Given I am on ...**
215
+
216
+
217
+
218
+
219
+ * **When I go to ...**
220
+
221
+
222
+
223
+
224
+ * **When I press "..."**
225
+
226
+
227
+
228
+
229
+ * **When I follow "..."**
230
+
231
+
232
+
233
+
234
+ * **When I fill in "..." with "..."**
235
+
236
+ Fill in text field
237
+
238
+
239
+ * **When I fill in "..." for "..."**
240
+
241
+ Fill in text field
242
+
243
+
244
+ * **When I select "..." from "..."**
245
+
246
+ Select from select box
247
+
248
+
249
+ * **When I check "..."**
250
+
251
+ Check a checkbox
252
+
253
+
254
+ * **When I uncheck "..."**
255
+
256
+ Uncheck a checkbox
257
+
258
+
259
+ * **When I choose "..."**
260
+
261
+ Select a radio button
262
+
263
+
264
+ * **When I attach the file "..." to "..."**
265
+
266
+
267
+
268
+
269
+ * **Then I should see "..."**
270
+
271
+ Checks that some text appears on the page
272
+
273
+ Note that this does not detect if the text might be hidden via CSS
274
+
275
+
276
+ * **Then I should see \/([^\/]*)\/**
277
+
278
+ Checks that a regexp appears on the page
279
+
280
+ Note that this does not detect if the text might be hidden via CSS
281
+
282
+
283
+ * **Then I should not see "..."**
284
+
285
+
286
+
287
+
288
+ * **Then I should not see \/([^\/]*)\/**
289
+
290
+
291
+
292
+
293
+ * **Then the "..." field( within ...)? should contain "..."**
294
+
295
+ Checks that a input field contains some value
296
+
297
+
298
+ * **Then the "..." field( within ...)? should not contain "..."**
299
+
300
+
301
+
302
+
303
+ * **Then the "..." field should have the error "..."**
304
+
305
+ checks that an input field was wrapped with a validation error
306
+
307
+
308
+ * **Then the "..." field should( not)? have an error**
309
+
310
+
311
+
312
+
313
+ * **Then the "..." field should have no error**
314
+
315
+
316
+
317
+
318
+ * **Then the radio button "..." should( not)? be (checked|selected)**
319
+
320
+
321
+
322
+
323
+ * **Then I should be on ...**
324
+
325
+
326
+
327
+
328
+ * **Then I should have the following query string:**
329
+
330
+ Example:
331
+
332
+ I should have the following query string:
333
+ | locale | de |
334
+ | currency_code | EUR |
335
+
336
+ Succeeds when the URL contains the given "locale" and "currency_code" params
337
+
338
+
339
+ * **Then show me the page**
340
+
341
+ Open the current Capybara page using the "launchy" gem
342
+
343
+
344
+ * **Then I should( not)? see a field "..."**
345
+
346
+ checks for the existance of a input field (given its id or label)
347
+
348
+
349
+ * **Then I should( not)? see the (number|amount) ([\-\d,\.]+)( (.*?))?**
350
+
351
+ Better way to test for a number of money amount than a `Then I should see`
352
+
353
+ Checks that there is unexpected minus sign, decimal places etc.
354
+
355
+ See [here](https://makandracards.com/makandra/1225-test-that-a-number-or-money-amount-is-shown-with-cucumber) for details
356
+
357
+
358
+ * **Then I should get a response with content-type "..."**
359
+
360
+ Checks "Content-Type" HTTP header
361
+
362
+
363
+ * **Then I should get a download with filename "..."**
364
+
365
+ Checks "Content-Disposition" HTTP header
366
+
367
+
368
+ * **Then "..." should be selected for "..."**
369
+
370
+ Checks that a certain option is selected for a text field
371
+
372
+
373
+ * **Then nothing should be selected for "..."?**
374
+
375
+
376
+
377
+
378
+ * **Then "..." should( not)? be an option for "..."( within "...")?**
379
+
380
+ Checks for the presence of an option in a select
381
+
382
+
383
+ * **Then I should see '([^']*)'( within '([^']*)')?**
384
+
385
+ Like `Then I should see`, but with single instead of double quotes. In case the string contains quotes as well.
386
+
387
+
388
+ * **Then I should see "..." in the HTML**
389
+
390
+ Check that the raw HTML contains a string
391
+
392
+
393
+ * **Then I should not see "..." in the HTML**
394
+
395
+
396
+
397
+
398
+ * **Then I should see an error**
399
+
400
+ Checks that status code is 400..599
401
+
402
+
403
+ * **When I reload the page**
404
+
405
+
406
+
407
+
408
+ * **Then "..." should( not)? be visible**
409
+
410
+ Checks that an element is actually visible, also considering styles
411
+ Within a selenium test, the browser is asked whether the element is really visible
412
+ In a non-selenium test, we only check for ".hidden", ".invisible" or "style: display:none"
413
+
414
+ More details [here](https://makandracards.com/makandra/1049-capybara-check-that-a-page-element-is-hidden-via-css)
415
+
416
+
417
+ * **When I click on "..."**
418
+
419
+ Click on some text that might not be a link
420
+
421
+
422
+ * **Then I should (not )?see an element "..."**
423
+
424
+ Example:
425
+
426
+ Then I should see an element ".page .container"
427
+
428
+
429
+ * **Then I should get a text response**
430
+
431
+ Checks that the result has content type text/plain
432
+
433
+
434
+ * **When I follow "..." inside any "..."**
435
+
436
+ Click a link within an element matching the given selector. Will try to be clever
437
+ and disregard elements that don't contain a matching link.
438
+
439
+ Example:
440
+
441
+ When I follow "Read more" inside any ".text_snippet"
442
+
443
+
444
+
445
+ * **Then I should( not)? see "..." inside any "..."**
446
+
447
+
448
+
449
+
450
+ * **When I fill in "..." with "..." inside any "..."**
82
451
 
83
- Most of cucumber-rails' original websteps plus some of our own.
452
+
84
453
 
85
- Note that cucumber-rails deprecated those a while ago (you can see the original deprecation notice at the top of [our web_steps](/makandra/spreewald/blob/master/lib/spreewald/web_steps.rb)). Make up your own mind whether you want to use them or not.
data/Rakefile CHANGED
@@ -1,2 +1,12 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+
4
+
5
+ task "update_readme" do
6
+ require 'support/documentation_generator'
7
+ readme = File.read('README.md')
8
+ start_of_steps_section = readme =~ /^## Steps/
9
+ length_of_steps_section = (readme[(start_of_steps_section+1)..-1] =~ /^##[^#]/) || readme.size - start_of_steps_section
10
+ readme[start_of_steps_section, length_of_steps_section] = "## Steps\n\n" + DocumentationGenerator::StepDefinitionsDirectory.new('lib/spreewald').format
11
+ File.open('README.md', 'w') { |f| f.write(readme) }
12
+ end
@@ -1,15 +1,21 @@
1
+ #
2
+
3
+ # Marks scenario as pending
1
4
  Then /^it should work$/ do
2
5
  pending
3
6
  end
4
7
 
8
+ # Starts debugger
5
9
  Then /^debugger$/ do
6
10
  debugger
7
11
  end
8
12
 
13
+ # Waits 2 seconds after each step
9
14
  AfterStep('@slow-motion') do
10
15
  sleep 2
11
16
  end
12
17
 
18
+ # Waits for keypress after each step
13
19
  AfterStep('@single-step') do
14
20
  print "Single Stepping. Hit enter to continue"
15
21
  STDIN.getc
@@ -4,10 +4,38 @@ Before do
4
4
  ActionMailer::Base.deliveries.clear
5
5
  end
6
6
 
7
- When /^I clear my emails$/ do
7
+ When /^I clear my e?mails$/ do
8
8
  ActionMailer::Base.deliveries.clear
9
9
  end
10
10
 
11
+ # Example:
12
+ #
13
+ # Then an email should have been sent with:
14
+ # """
15
+ # From: max.mustermann@example.com
16
+ # To: john.doe@example.com
17
+ # Subject: Unter anderem der Betreff kann auch "Anführungszeichen" enthalten
18
+ # Body: ...
19
+ # Attachments: ...
20
+ # """
21
+ #
22
+ # You can skip lines, of course.
23
+ Then /^(an|no) e?mail should have been sent with:$/ do |mode, raw_data|
24
+ raw_data.strip!
25
+ conditions = {}.tap do |hash|
26
+ raw_data.split("\n").each do |row|
27
+ if row.match(/^[a-z]+: /i)
28
+ key, value = row.split(": ", 2)
29
+ hash[key.downcase.to_sym] = value
30
+ end
31
+ end
32
+ end
33
+ @mail = MailFinder.find(conditions)
34
+ expectation = mode == 'no' ? 'should_not' : 'should'
35
+ @mail.send(expectation, be_present)
36
+ end
37
+
38
+ # nodoc
11
39
  Then /^(an|no) e?mail should have been sent((?: |and|with|from "[^"]+"|to "[^"]+"|the subject "[^"]+"|the body "[^"]+"|the attachments "[^"]+")+)$/ do |mode, query|
12
40
  conditions = {}
13
41
  conditions[:to] = $1 if query =~ /to "([^"]+)"/
@@ -22,6 +50,7 @@ Then /^(an|no) e?mail should have been sent((?: |and|with|from "[^"]+"|to "[^"]+
22
50
  @mail.send(expectation, be_present)
23
51
  end
24
52
 
53
+ # Only works after you have retrieved the mail using "Then an email should have been sent with:"
25
54
  When /^I follow the (first|second|third)? ?link in the e?mail$/ do |index_in_words|
26
55
  mail = @mail || ActionMailer::Base.deliveries.last
27
56
  index = { nil => 0, 'first' => 0, 'second' => 1, 'third' => 2 }[index_in_words]
@@ -32,37 +61,36 @@ Then /^no e?mail should have been sent$/ do
32
61
  ActionMailer::Base.deliveries.should be_empty
33
62
  end
34
63
 
64
+ # Checks that the last sent email includes some text
35
65
  Then /^I should see "([^\"]*)" in the e?mail$/ do |text|
36
66
  ActionMailer::Base.deliveries.last.body.should include(text)
37
67
  end
38
68
 
69
+ # Print all sent emails to STDOUT.
39
70
  Then /^show me the e?mails$/ do
40
71
  ActionMailer::Base.deliveries.each do |mail|
41
72
  p [mail.from, mail.to, mail.subject]
42
73
  end
43
74
  end
44
75
 
45
- Then /^(an|no) e?mail should have been sent with:$/ do |mode, raw_data|
46
- raw_data.strip!
47
- conditions = {}.tap do |hash|
48
- raw_data.split("\n").each do |row|
49
- if row.match(/^[a-z]+: /i)
50
- key, value = row.split(": ", 2)
51
- hash[key.downcase.to_sym] = value
52
- end
53
- end
54
- end
55
- @mail = MailFinder.find(conditions)
56
- expectation = mode == 'no' ? 'should_not' : 'should'
57
- @mail.send(expectation, be_present)
58
- end
59
76
 
77
+ # Only works after you've retrieved the email using "Then an email should have been sent with:"
78
+ #
79
+ # Example:
80
+ #
81
+ # And that mail should have the following lines in the body:
82
+ # """
83
+ # All of these lines
84
+ # need to be present
85
+ # """
60
86
  Then /^that e?mail should have the following lines in the body:$/ do |body|
61
87
  body.each do |line|
62
88
  @mail.body.should include(line.strip)
63
89
  end
64
90
  end
65
91
 
92
+ # Only works after you've retrieved the email using "Then an email should have been sent with:"
93
+ # Checks that the text should be included in the retrieved email
66
94
  Then /^that e?mail should have the following body:$/ do |body|
67
95
  @mail.body.should include(body.strip)
68
96
  end
@@ -1,3 +1,8 @@
1
+ # Check the content of tables in your HTML.
2
+ #
3
+ # See [this article](https://makandracards.com/makandra/763-cucumber-step-to-match-table-rows-with-capybara) for details.
4
+
5
+
1
6
  require 'spreewald_support/tolerance_for_selenium_sync_issues'
2
7
 
3
8
  module TableStepsHelper
@@ -1,13 +1,29 @@
1
+ # Steps to travel through time using [Timecop](https://github.com/jtrupiano/timecop).
2
+ #
3
+ # See [this article](https://makandracards.com/makandra/1222-useful-cucumber-steps-to-travel-through-time-with-timecop) for details.
4
+
5
+
1
6
  if defined?(Timecop)
2
7
 
8
+ # Example:
9
+ #
10
+ # Given the date is "2012-02-10"
11
+ # Given the time is "2012-02-10 13:40"
3
12
  When /^the (?:date|time) is "(\d{4}-\d{2}-\d{2}(?: \d{1,2}:\d{2})?)"$/ do |time|
4
13
  Timecop.travel Time.parse(time)
5
14
  end
6
15
 
16
+ # Example:
17
+ #
18
+ # Given the time is "13:40"
7
19
  When /^the time is "(\d{1,2}:\d{2})"$/ do |time|
8
20
  Timecop.travel Time.parse(time) # date will be today
9
21
  end
10
22
 
23
+ # Example:
24
+ #
25
+ # When it is 10 minutes later
26
+ # When it is a few hours earlier
11
27
  When /^it is (\d+|a|some|a few) (seconds?|minutes?|hours?|days?|weeks?|months?|years?) (later|earlier)$/ do |amount, unit, direction|
12
28
  amount = case amount
13
29
  when 'a'
@@ -1,34 +1,42 @@
1
- # Deprecation notice from the original web-steps:
1
+ # Most of cucumber-rails' original web steps plus a few of our own.
2
2
  #
3
- # This file was generated by Cucumber-Rails and is only here to get you a head start
4
- # These step definitions are thin wrappers around the Capybara/Webrat API that lets you
5
- # visit pages, interact with widgets and make assertions about page content.
3
+ # Note that cucumber-rails deprecated all its steps quite a while ago with the following
4
+ # deprecation notice. Decide for yourself whether you want to use them:
6
5
  #
7
- # If you use these step definitions as basis for your features you will quickly end up
8
- # with features that are:
6
+ # > This file was generated by Cucumber-Rails and is only here to get you a head start
7
+ # > These step definitions are thin wrappers around the Capybara/Webrat API that lets you
8
+ # > visit pages, interact with widgets and make assertions about page content.
9
9
  #
10
- # * Hard to maintain
11
- # * Verbose to read
10
+ # > If you use these step definitions as basis for your features you will quickly end up
11
+ # > with features that are:
12
12
  #
13
- # A much better approach is to write your own higher level step definitions, following
14
- # the advice in the following blog posts:
13
+ # > * Hard to maintain
14
+ # > * Verbose to read
15
15
  #
16
- # * http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
17
- # * http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/
18
- # * http://elabs.se/blog/15-you-re-cuking-it-wrong
16
+ # > A much better approach is to write your own higher level step definitions, following
17
+ # > the advice in the following blog posts:
18
+ #
19
+ # > * http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
20
+ # > * http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/
21
+ # > * http://elabs.se/blog/15-you-re-cuking-it-wrong
19
22
  #
20
23
 
21
24
  require 'spreewald_support/tolerance_for_selenium_sync_issues'
22
25
  require 'spreewald_support/path_selector_fallbacks'
26
+ require 'spreewald_support/step_fallback'
23
27
  require 'uri'
24
28
  require 'cgi'
25
29
 
26
- # Single-line step scoper
30
+
31
+ # You can append 'within [selector]' to any other web step
32
+ # Example:
33
+ #
34
+ # Then I should see "some text" within ".page_body"
27
35
  When /^(.*) within (.*[^:])$/ do |nested_step, parent|
28
36
  with_scope(parent) { step(nested_step) }
29
37
  end
30
38
 
31
- # Multi-line step scoper
39
+ # nodoc
32
40
  When /^(.*) within (.*[^:]):$/ do |nested_step, parent, table_or_string|
33
41
  with_scope(parent) { step("#{nested_step}:", table_or_string) }
34
42
  end
@@ -53,36 +61,42 @@ When /^(?:|I )follow "([^"]*)"$/ do |link|
53
61
  end
54
62
  end
55
63
 
64
+ # Fill in text field
56
65
  When /^(?:|I )fill in "([^"]*)" with "([^"]*)"$/ do |field, value|
57
66
  patiently do
58
67
  fill_in(field, :with => value)
59
68
  end
60
69
  end
61
70
 
71
+ # Fill in text field
62
72
  When /^(?:|I )fill in "([^"]*)" for "([^"]*)"$/ do |value, field|
63
73
  patiently do
64
74
  fill_in(field, :with => value)
65
75
  end
66
76
  end
67
77
 
78
+ # Select from select box
68
79
  When /^(?:|I )select "([^"]*)" from "([^"]*)"$/ do |value, field|
69
80
  patiently do
70
81
  select(value, :from => field)
71
82
  end
72
83
  end
73
84
 
85
+ # Check a checkbox
74
86
  When /^(?:|I )check "([^"]*)"$/ do |field|
75
87
  patiently do
76
88
  check(field)
77
89
  end
78
90
  end
79
91
 
92
+ # Uncheck a checkbox
80
93
  When /^(?:|I )uncheck "([^"]*)"$/ do |field|
81
94
  patiently do
82
95
  uncheck(field)
83
96
  end
84
97
  end
85
98
 
99
+ # Select a radio button
86
100
  When /^(?:|I )choose "([^"]*)"$/ do |field|
87
101
  patiently do
88
102
  choose(field)
@@ -95,12 +109,18 @@ When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"$/ do |path, field|
95
109
  end
96
110
  end
97
111
 
112
+ # Checks that some text appears on the page
113
+ #
114
+ # Note that this does not detect if the text might be hidden via CSS
98
115
  Then /^(?:|I )should see "([^"]*)"$/ do |text|
99
116
  patiently do
100
117
  page.should have_content(text)
101
118
  end
102
119
  end
103
120
 
121
+ # Checks that a regexp appears on the page
122
+ #
123
+ # Note that this does not detect if the text might be hidden via CSS
104
124
  Then /^(?:|I )should see \/([^\/]*)\/$/ do |regexp|
105
125
  regexp = Regexp.new(regexp)
106
126
  patiently do
@@ -121,6 +141,8 @@ Then /^(?:|I )should not see \/([^\/]*)\/$/ do |regexp|
121
141
  end
122
142
  end
123
143
 
144
+
145
+ # Checks that a input field contains some value
124
146
  Then /^the "([^"]*)" field(?: within (.*))? should contain "([^"]*)"$/ do |field, parent, value|
125
147
  patiently do
126
148
  with_scope(parent) do
@@ -141,6 +163,9 @@ Then /^the "([^"]*)" field(?: within (.*))? should not contain "([^"]*)"$/ do |f
141
163
  end
142
164
  end
143
165
  end
166
+
167
+
168
+ # checks that an input field was wrapped with a validation error
144
169
  Then /^the "([^"]*)" field should have the error "([^"]*)"$/ do |field, error_message|
145
170
  patiently do
146
171
  element = find_field(field)
@@ -177,6 +202,7 @@ Then /^the "([^"]*)" field should have no error$/ do |field|
177
202
  end
178
203
  end
179
204
 
205
+ # nodoc
180
206
  Then /^the "([^"]*)" checkbox(?: within (.*))? should be checked$/ do |label, parent|
181
207
  patiently do
182
208
  with_scope(parent) do
@@ -186,6 +212,7 @@ Then /^the "([^"]*)" checkbox(?: within (.*))? should be checked$/ do |label, pa
186
212
  end
187
213
  end
188
214
 
215
+ # nodoc
189
216
  Then /^the "([^"]*)" checkbox(?: within (.*))? should not be checked$/ do |label, parent|
190
217
  patiently do
191
218
  with_scope(parent) do
@@ -208,6 +235,13 @@ Then /^(?:|I )should be on (.+)$/ do |page_name|
208
235
  end
209
236
  end
210
237
 
238
+ # Example:
239
+ #
240
+ # I should have the following query string:
241
+ # | locale | de |
242
+ # | currency_code | EUR |
243
+ #
244
+ # Succeeds when the URL contains the given "locale" and "currency_code" params
211
245
  Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
212
246
  patiently do
213
247
  query = URI.parse(current_url).query
@@ -219,11 +253,13 @@ Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
219
253
  end
220
254
  end
221
255
 
256
+ # Open the current Capybara page using the "launchy" gem
222
257
  Then /^show me the page$/ do
223
258
  save_and_open_page
224
259
  end
225
260
 
226
261
 
262
+ # checks for the existance of a input field (given its id or label)
227
263
  Then /^I should( not)? see a field "([^"]*)"$/ do |negate, name|
228
264
  expectation = negate ? :should_not : :should
229
265
  patiently do
@@ -236,6 +272,11 @@ Then /^I should( not)? see a field "([^"]*)"$/ do |negate, name|
236
272
  end
237
273
  end
238
274
 
275
+ # Better way to test for a number of money amount than a `Then I should see`
276
+ #
277
+ # Checks that there is unexpected minus sign, decimal places etc.
278
+ #
279
+ # See [here](https://makandracards.com/makandra/1225-test-that-a-number-or-money-amount-is-shown-with-cucumber) for details
239
280
  Then /^I should( not)? see the (?:number|amount) ([\-\d,\.]+)(?: (.*?))?$/ do |negate, amount, unit|
240
281
  no_minus = amount.starts_with?('-') ? '' : '[^\\-]'
241
282
  nbsp = 0xC2.chr + 0xA0.chr
@@ -246,20 +287,20 @@ Then /^I should( not)? see the (?:number|amount) ([\-\d,\.]+)(?: (.*?))?$/ do |n
246
287
  end
247
288
  end
248
289
 
290
+ # Checks "Content-Type" HTTP header
249
291
  Then /^I should get a response with content-type "([^\"]*)"$/ do |expected_content_type|
250
292
  page.response_headers['Content-Type'].should =~ /\A#{Regexp.quote(expected_content_type)}($|;)/
251
293
  end
252
294
 
295
+ # Checks "Content-Disposition" HTTP header
253
296
  Then /^I should get a download with filename "([^\"]*)"$/ do |filename|
254
297
  page.response_headers['Content-Disposition'].should =~ /filename="#{filename}"$/
255
298
  end
256
299
 
257
-
258
- Then /^"([^"]*)" should be selected for "([^"]*)"(?: within "([^\"]*)")?$/ do |value, field, selector|
300
+ # Checks that a certain option is selected for a text field
301
+ Then /^"([^"]*)" should be selected for "([^"]*)"$/ do |value, field|
259
302
  patiently do
260
- with_scope(selector) do
261
- field_labeled(field).find(:xpath, ".//option[@selected = 'selected'][text() = '#{value}']").should be_present
262
- end
303
+ field_labeled(field).find(:xpath, ".//option[@selected = 'selected'][text() = '#{value}']").should be_present
263
304
  end
264
305
  end
265
306
 
@@ -270,23 +311,22 @@ Then /^nothing should be selected for "([^"]*)"?$/ do |field|
270
311
  end
271
312
  end
272
313
 
273
- Then /^"([^"]*)" should( not)? be an option for "([^"]*)"(?: within "([^\"]*)")?$/ do |value, negate, field, selector|
314
+ # Checks for the presence of an option in a select
315
+ Then /^"([^"]*)" should( not)? be an option for "([^"]*)"$/ do |value, negate, field|
274
316
  patiently do
275
- with_scope(selector) do
276
- expectation = negate ? :should_not : :should
277
- field_labeled(field).first(:xpath, ".//option[text() = '#{value}']").send(expectation, be_present)
278
- end
317
+ expectation = negate ? :should_not : :should
318
+ field_labeled(field).find(:xpath, ".//option[text() = '#{value}']").send(expectation, be_present)
279
319
  end
280
320
  end
281
321
 
282
- Then /^(?:|I )should see '([^']*)'(?: within '([^']*)')?$/ do |text, selector|
322
+ # Like `Then I should see`, but with single instead of double quotes. In case the string contains quotes as well.
323
+ Then /^(?:|I )should see '([^']*)'$/ do |text|
283
324
  patiently do
284
- with_scope(selector) do
285
- page.should have_content(text)
286
- end
325
+ page.should have_content(text)
287
326
  end
288
327
  end
289
328
 
329
+ # Check that the raw HTML contains a string
290
330
  Then /^I should see "([^\"]*)" in the HTML$/ do |text|
291
331
  patiently do
292
332
  page.body.should include(text)
@@ -299,10 +339,12 @@ Then /^I should not see "([^\"]*)" in the HTML$/ do |text|
299
339
  end
300
340
  end
301
341
 
342
+ # Checks that status code is 400..599
302
343
  Then /^I should see an error$/ do
303
344
  (400 .. 599).should include(page.status_code)
304
345
  end
305
346
 
347
+ #nodoc
306
348
  Then /^the window should be titled "([^"]*)"$/ do |title|
307
349
  page.should have_css('title', :text => title)
308
350
  end
@@ -311,6 +353,11 @@ When /^I reload the page$/ do
311
353
  visit current_path
312
354
  end
313
355
 
356
+ # Checks that an element is actually visible, also considering styles
357
+ # Within a selenium test, the browser is asked whether the element is really visible
358
+ # In a non-selenium test, we only check for ".hidden", ".invisible" or "style: display:none"
359
+ #
360
+ # More details [here](https://makandracards.com/makandra/1049-capybara-check-that-a-page-element-is-hidden-via-css)
314
361
  Then /^"([^\"]+)" should( not)? be visible$/ do |text, negate|
315
362
  case Capybara::current_driver
316
363
  when :selenium, :webkit
@@ -365,17 +412,21 @@ Then /^"([^\"]+)" should( not)? be visible$/ do |text, negate|
365
412
  end
366
413
  end
367
414
 
415
+ # Click on some text that might not be a link
368
416
  When /^I click on "([^\"]+)"$/ do |text|
369
417
  matcher = ['*', { :text => text }]
370
418
  patiently do
371
419
  element = page.find(:css, *matcher)
372
- while better_match = element.first(:css, *matcher)
420
+ while better_match = element.find(:css, *matcher)
373
421
  element = better_match
374
422
  end
375
423
  element.click
376
424
  end
377
425
  end
378
426
 
427
+ # Example:
428
+ #
429
+ # Then I should see an element ".page .container"
379
430
  Then /^I should (not )?see an element "([^"]*)"$/ do |negate, selector|
380
431
  expectation = negate ? :should_not : :should
381
432
  patiently do
@@ -383,10 +434,18 @@ Then /^I should (not )?see an element "([^"]*)"$/ do |negate, selector|
383
434
  end
384
435
  end
385
436
 
437
+ # Checks that the result has content type text/plain
386
438
  Then /^I should get a text response$/ do
387
439
  step 'I should get a response with content-type "text/plain"'
388
440
  end
389
441
 
442
+ # Click a link within an element matching the given selector. Will try to be clever
443
+ # and disregard elements that don't contain a matching link.
444
+ #
445
+ # Example:
446
+ #
447
+ # When I follow "Read more" inside any ".text_snippet"
448
+ #
390
449
  When /^I follow "([^"]*)" inside any "([^"]*)"$/ do |label, selector|
391
450
  node = first("#{selector} a", :text => label)
392
451
  node.click
@@ -0,0 +1,11 @@
1
+ module StepFallback
2
+ def step(*args)
3
+ if defined?(super)
4
+ super
5
+ else
6
+ When(*args)
7
+ end
8
+ end
9
+ end
10
+
11
+ World(StepFallback)
@@ -1,3 +1,3 @@
1
1
  module Spreewald
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.require_paths = ["lib"]
17
17
  gem.version = Spreewald::VERSION
18
18
 
19
- gem.add_runtime_dependency('cucumber-rails', '>=1.3.0')
19
+ gem.add_runtime_dependency('cucumber-rails')
20
20
  gem.add_runtime_dependency('cucumber')
21
21
  gem.add_runtime_dependency('capybara')
22
22
  end
@@ -0,0 +1,110 @@
1
+ module DocumentationGenerator
2
+
3
+ module CommentExtractor
4
+ def parse_and_format_comment(comment)
5
+ comment.strip!
6
+ comment_lines = comment.split("\n").take_while { |line| line =~ /^\s*#/ }
7
+ comment_lines && comment_lines.join("\n").gsub(/^\s*# ?/, '')
8
+ end
9
+ end
10
+
11
+ class StepDefinition
12
+
13
+ extend CommentExtractor
14
+
15
+ def initialize(definition, comment = nil)
16
+ @definition = definition
17
+ @comment = comment
18
+ end
19
+
20
+ def self.try_and_parse(code)
21
+ definition = code[/^\s*((When|Then|Given|AfterStep).*)do/, 1]
22
+ return unless definition
23
+ comment = parse_and_format_comment(code)
24
+ return if comment =~ /\bnodoc\b/
25
+ new(definition.strip, comment)
26
+ end
27
+
28
+ def format
29
+ <<-TEXT
30
+ * **#{format_definition}**
31
+
32
+ #{@comment.gsub(/^/, ' ')}
33
+ TEXT
34
+ end
35
+
36
+ def format_definition
37
+ if @definition =~ /AfterStep/
38
+ @definition[/@\w*/]
39
+ else
40
+ @definition.
41
+ gsub('/^', '').
42
+ gsub('$/', '').
43
+ gsub(' ?', ' ').
44
+ gsub(/\(\[\^\\?"\](\*|\+)\)/, '...').
45
+ gsub('(?:|I )', 'I ').
46
+ gsub('?:', '').
47
+ gsub(/\(\.(\+|\*)\)/, '...')
48
+ end
49
+ end
50
+ end
51
+
52
+ class StepDefinitionFile
53
+
54
+ include CommentExtractor
55
+
56
+ def initialize(filename)
57
+ @filename = filename
58
+ @code = File.read(filename)
59
+ @steps = []
60
+ extract_comment
61
+ add_steps
62
+ end
63
+
64
+ def extract_comment
65
+ @comment = parse_and_format_comment(@code)
66
+ end
67
+
68
+ def add_steps
69
+ @code.split("\n\n").each do |block|
70
+ step = StepDefinition.try_and_parse(block)
71
+ if step
72
+ @steps << step
73
+ end
74
+ end
75
+ end
76
+
77
+ def format
78
+ <<-TEXT
79
+ ### #{format_filename}
80
+
81
+ #{@comment}
82
+
83
+ #{format_steps}
84
+ TEXT
85
+ end
86
+
87
+ def format_filename
88
+ @filename.split('/').last
89
+ end
90
+
91
+ def format_steps
92
+ @steps.collect { |step| step.format }.join("\n\n")
93
+ end
94
+ end
95
+
96
+ class StepDefinitionsDirectory
97
+ def initialize(directory)
98
+ @step_definition_files = []
99
+ Dir["#{directory}/*.rb"].to_a.sort.each do |filename|
100
+ next if filename =~ /all_steps/
101
+ @step_definition_files << StepDefinitionFile.new(filename)
102
+ end
103
+ end
104
+
105
+ def format
106
+ @step_definition_files.collect { |step_definition_file| step_definition_file.format }.join("\n\n")
107
+ end
108
+ end
109
+
110
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spreewald
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tobias Kraze
@@ -26,12 +26,10 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- hash: 27
29
+ hash: 3
30
30
  segments:
31
- - 1
32
- - 3
33
31
  - 0
34
- version: 1.3.0
32
+ version: "0"
35
33
  type: :runtime
36
34
  version_requirements: *id001
37
35
  - !ruby/object:Gem::Dependency
@@ -89,9 +87,11 @@ files:
89
87
  - lib/spreewald_support/github.rb
90
88
  - lib/spreewald_support/mail_finder.rb
91
89
  - lib/spreewald_support/path_selector_fallbacks.rb
90
+ - lib/spreewald_support/step_fallback.rb
92
91
  - lib/spreewald_support/tolerance_for_selenium_sync_issues.rb
93
92
  - lib/spreewald_support/version.rb
94
93
  - spreewald.gemspec
94
+ - support/documentation_generator.rb
95
95
  has_rdoc: true
96
96
  homepage: https://github.com/makandra/spreewald
97
97
  licenses: []