spreewald 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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: []