spreewald 2.99.3 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +40 -0
  3. data/CHANGELOG.md +45 -4
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +2 -2
  6. data/Gemfile.ruby245 +3 -0
  7. data/Gemfile.ruby245.lock +10 -1
  8. data/Gemfile.ruby266 +3 -0
  9. data/Gemfile.ruby266.lock +12 -2
  10. data/README.md +40 -32
  11. data/Rakefile +34 -19
  12. data/features/binary.feature +2 -2
  13. data/features/support/step_definitions/custom_steps.rb +10 -0
  14. data/lib/spreewald.rb +1 -0
  15. data/lib/spreewald/development_steps.rb +1 -8
  16. data/lib/spreewald/email_steps.rb +3 -43
  17. data/lib/spreewald/frame_steps.rb +77 -0
  18. data/lib/spreewald/web_steps.rb +17 -61
  19. data/lib/spreewald_support/mail_finder.rb +12 -13
  20. data/lib/spreewald_support/mail_to_plaintext_converter.rb +42 -0
  21. data/lib/spreewald_support/unsupported_email_header.rb +22 -0
  22. data/lib/spreewald_support/version.rb +1 -1
  23. data/spec/spreewald_support/mail_to_plaintext_converter_spec.rb +60 -0
  24. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/Gemfile +1 -1
  25. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/Gemfile.lock +14 -16
  26. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/README.rdoc +0 -0
  27. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/Rakefile +0 -0
  28. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/app +0 -0
  29. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/bin/bundle +0 -0
  30. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/bin/rails +0 -0
  31. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/bin/rake +0 -0
  32. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/bin/setup +0 -0
  33. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config.ru +0 -0
  34. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/application.rb +0 -0
  35. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/boot.rb +0 -0
  36. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/cucumber.yml +0 -0
  37. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/database.yml +0 -0
  38. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/environment.rb +0 -0
  39. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/environments/development.rb +0 -0
  40. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/environments/test.rb +0 -0
  41. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/initializers/backtrace_silencers.rb +0 -0
  42. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/initializers/cookies_serializer.rb +0 -0
  43. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/initializers/filter_parameter_logging.rb +0 -0
  44. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/initializers/inflections.rb +0 -0
  45. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/initializers/mime_types.rb +0 -0
  46. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/initializers/session_store.rb +0 -0
  47. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/initializers/silence_deprecation_warnings.rb +0 -0
  48. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/initializers/to_time_preserves_timezone.rb +0 -0
  49. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/initializers/wrap_parameters.rb +0 -0
  50. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/locales/en.yml +0 -0
  51. data/tests/{rails-3_capybara-1 → rails-4_capybara-2}/config/routes.rb +0 -0
  52. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/config/secrets.yml +0 -0
  53. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/db +0 -0
  54. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/browser_tab_steps.feature +0 -0
  55. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/development_steps.feature +0 -0
  56. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/email_steps.feature +0 -0
  57. data/tests/rails-4_capybara-2/features/iframe_steps.feature +1 -0
  58. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/overriding.feature +0 -0
  59. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/session_steps.feature +0 -0
  60. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/step_definitions/overriding_steps.rb +0 -0
  61. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/step_definitions/test_steps.rb +0 -0
  62. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/support/env.rb +0 -0
  63. data/tests/{rails-3_capybara-1 → rails-4_capybara-2}/features/support/paths.rb +0 -0
  64. data/tests/{rails-3_capybara-1 → rails-4_capybara-2}/features/support/selectors.rb +0 -0
  65. data/tests/rails-4_capybara-2/features/support/selenium.rb +1 -0
  66. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/table_steps.feature +0 -0
  67. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/time_steps.feature +0 -0
  68. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/features/web_steps.feature +0 -0
  69. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/lib/tasks/cucumber.rake +0 -0
  70. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/log/.keep +0 -0
  71. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/public/404.html +0 -0
  72. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/public/422.html +0 -0
  73. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/public/500.html +0 -0
  74. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/public/favicon.ico +0 -0
  75. data/tests/{rails-4_capybara-3 → rails-4_capybara-2}/public/fixture_files +0 -0
  76. data/tests/{rails-3_capybara-1 → rails-4_capybara-2}/script/cucumber +0 -0
  77. data/tests/rails-6_capybara-3/Gemfile.lock +2 -2
  78. data/tests/rails-6_capybara-3/app/mailers/spreewald_mailer.rb +16 -0
  79. data/tests/rails-6_capybara-3/features/iframe_steps.feature +1 -0
  80. data/tests/rails-6_capybara-3/features/support/selenium.rb +1 -0
  81. data/tests/shared/app/controllers/emails_controller.rb +20 -0
  82. data/tests/shared/app/controllers/iframes_controller.rb +11 -0
  83. data/tests/shared/app/controllers/static_pages_controller.rb +12 -8
  84. data/tests/shared/app/models/mailer.rb +32 -0
  85. data/tests/shared/app/views/forms/checkbox_form.html.haml +3 -0
  86. data/tests/shared/app/views/forms/disabled_elements.html.haml +1 -0
  87. data/tests/shared/app/views/forms/form1.html.haml +4 -1
  88. data/tests/shared/app/views/forms/invalid_form.html.haml +3 -0
  89. data/tests/shared/app/views/iframes/iframe_1_content.haml +12 -0
  90. data/tests/shared/app/views/iframes/iframe_2_content.haml +12 -0
  91. data/tests/shared/app/views/mailer/html_email_for_failed_test_without_header.haml +5 -0
  92. data/tests/shared/app/views/mailer/html_email_for_successful_test_without_header.haml +7 -0
  93. data/tests/shared/app/views/mailer/text_email_for_failed_test_without_header.text.erb +1 -0
  94. data/tests/shared/app/views/mailer/text_email_for_successful_test_without_header.text.erb +3 -0
  95. data/tests/shared/app/views/static_pages/iframe.haml +3 -0
  96. data/tests/shared/config/routes.rb +8 -0
  97. data/tests/shared/features/shared/email_steps.feature +172 -35
  98. data/tests/shared/features/shared/iframe_steps.feature +38 -0
  99. data/tests/shared/features/shared/step_definitions/test_steps.rb +5 -6
  100. data/tests/shared/features/shared/web_steps.feature +15 -10
  101. data/tests/shared/features/support/selenium.rb +10 -0
  102. metadata +137 -186
  103. data/.travis.yml +0 -29
  104. data/Gemfile.ruby218 +0 -7
  105. data/Gemfile.ruby218.lock +0 -58
  106. data/lib/spreewald/file_attachment_steps.rb +0 -22
  107. data/lib/spreewald/timecop_steps.rb +0 -9
  108. data/tests/rails-3_capybara-1/.ruby-version +0 -1
  109. data/tests/rails-3_capybara-1/Gemfile +0 -20
  110. data/tests/rails-3_capybara-1/Gemfile.lock +0 -182
  111. data/tests/rails-3_capybara-1/Rakefile +0 -18
  112. data/tests/rails-3_capybara-1/app +0 -1
  113. data/tests/rails-3_capybara-1/config.ru +0 -4
  114. data/tests/rails-3_capybara-1/config/application.rb +0 -29
  115. data/tests/rails-3_capybara-1/config/boot.rb +0 -15
  116. data/tests/rails-3_capybara-1/config/cucumber.yml +0 -1
  117. data/tests/rails-3_capybara-1/config/database.yml +0 -1
  118. data/tests/rails-3_capybara-1/config/environment.rb +0 -7
  119. data/tests/rails-3_capybara-1/config/initializers/backtrace_silencers.rb +0 -9
  120. data/tests/rails-3_capybara-1/config/initializers/inflections.rb +0 -12
  121. data/tests/rails-3_capybara-1/config/initializers/mime_types.rb +0 -7
  122. data/tests/rails-3_capybara-1/config/initializers/secret_token.rb +0 -9
  123. data/tests/rails-3_capybara-1/config/initializers/session_store.rb +0 -5
  124. data/tests/rails-3_capybara-1/db +0 -1
  125. data/tests/rails-3_capybara-1/features/shared +0 -1
  126. data/tests/rails-3_capybara-1/features/support/env.rb +0 -65
  127. data/tests/rails-3_capybara-1/features/support/selenium.rb +0 -3
  128. data/tests/rails-3_capybara-1/public +0 -1
  129. data/tests/rails-3_capybara-1/script/rails +0 -6
  130. data/tests/rails-3_capybara-2/.ruby-version +0 -1
  131. data/tests/rails-3_capybara-2/Gemfile +0 -21
  132. data/tests/rails-3_capybara-2/Gemfile.lock +0 -191
  133. data/tests/rails-3_capybara-2/Rakefile +0 -1
  134. data/tests/rails-3_capybara-2/app +0 -1
  135. data/tests/rails-3_capybara-2/config +0 -1
  136. data/tests/rails-3_capybara-2/config.ru +0 -1
  137. data/tests/rails-3_capybara-2/db +0 -1
  138. data/tests/rails-3_capybara-2/features +0 -1
  139. data/tests/rails-3_capybara-2/public +0 -1
  140. data/tests/rails-3_capybara-2/script +0 -1
  141. data/tests/rails-4_capybara-3/config/routes.rb +0 -1
  142. data/tests/rails-4_capybara-3/features/support/paths.rb +0 -1
  143. data/tests/rails-4_capybara-3/features/support/selectors.rb +0 -1
  144. data/tests/rails-4_capybara-3/features/support/selenium.rb +0 -3
  145. data/tests/rails-4_capybara-3/script/cucumber +0 -10
  146. data/tests/rails-6_capybara-3/features/support/selenium.rb +0 -3
@@ -0,0 +1,10 @@
1
+ Then /^the output should( not)? contain \/(.*)\/$/ do |negated, regexp|
2
+ output = all_commands.map { |c| c.output }.join("\n")
3
+ regexp = Regexp.new(regexp)
4
+
5
+ if negated
6
+ expect(output).not_to match(regexp)
7
+ else
8
+ expect(output).to match(regexp)
9
+ end
10
+ end
data/lib/spreewald.rb CHANGED
@@ -3,3 +3,4 @@
3
3
  require 'cucumber_priority'
4
4
  require "spreewald_support/version"
5
5
  require "spreewald_support/github"
6
+ require "spreewald_support/unsupported_email_header"
@@ -5,15 +5,8 @@ Then /^it should work(.+?)?$/ do |message|
5
5
  pending(message)
6
6
  end.overridable
7
7
 
8
- # nodoc
9
- Then 'debugger' do
10
- warn 'The step "Then debugger" will be removed in future versions of Spreewald. Please use "Then console" instead.'
11
- step 'console' # Alias
12
- end.overridable
13
-
14
8
  # Pauses test execution and opens an IRB shell with current context. Does not halt the application-
15
- # under-test. (Replaces the "Then debugger" step that has never been adequate
16
- # for its job)
9
+ # under-test.
17
10
  Then 'console' do
18
11
  require 'irb'
19
12
  ARGV.clear # IRB takes ARGV as its own arguments
@@ -30,10 +30,9 @@ end.overridable
30
30
  #
31
31
  # """
32
32
  #
33
- # Because of backwards-compatibility, the body currently only has to be a prefix
34
- # of the real body. However, this is deprecated and will be removed in a future
35
- # version. Use wildcards instead.
36
- # You may skip lines in the header, of course.
33
+ # You may skip lines in the header.
34
+ # Please note: In older versions of Spreewald, unmentioned body lines were skipped.
35
+ # Now you have to use the asterisk explicitly to omit lines in the body.
37
36
  Then /^(an?|no)( HTML| plain-text|) e?mail should have been sent with:$/ do |mode, type, raw_data|
38
37
  patiently do
39
38
  results = MailFinder.find(raw_data, type.strip)
@@ -70,26 +69,6 @@ ERROR
70
69
  end
71
70
  end.overridable
72
71
 
73
- # nodoc (deprecated)
74
- Then /^(an|no) e?mail should have been sent((?: |and|with|from "[^"]+"|bcc "[^"]+"|cc "[^"]+"|to "[^"]+"|the subject "[^"]+"|the body "[^"]+"|the attachments "[^"]+")+)$/ do |mode, query|
75
- warn "The step `an email should have been sent (from ...) (to ...) (cc ...) ...` has been deprecated in favor of `(an?|no)( HTML| plain-text|) e?mail should have been sent with:`"
76
- patiently do
77
- filename_method = Rails::VERSION::MAJOR < 3 ? 'original_filename' : 'filename'
78
- @mail = ActionMailer::Base.deliveries.find do |mail|
79
- [ query =~ /to "([^"]+)"/ && !mail.to.include?(MailFinder.resolve_email $1),
80
- query =~ /cc "([^"]+)"/ && !mail.cc.include?(MailFinder.resolve_email $1),
81
- query =~ /bcc "([^"]+)"/ && !mail.bcc.include?(MailFinder.resolve_email $1),
82
- query =~ /from "([^"]+)"/ && !mail.from.include?(MailFinder.resolve_email $1),
83
- query =~ /reply_to "([^"]+)"/ && !mail.reply_to.include?(MailFinder.resolve_email $1),
84
- query =~ /subject "([^"]+)"/ && !mail.subject.include?($1),
85
- query =~ /the attachments "([^"]+)"/ && $1.split(/\s*,\s*/).sort != Array(mail.attachments).collect(&:"#{filename_method}").sort
86
- ].none?
87
- end
88
- expectation = mode == 'no' ? 'not_to' : 'to'
89
- expect(@mail).send(expectation, be_present)
90
- end
91
- end.overridable
92
-
93
72
  # Please note that this step will only follow HTTP and HTTPS links.
94
73
  # Other links (such as mailto: or ftp:// links) are ignored.
95
74
  When /^I follow the (first|second|third)? ?link in the e?mail$/ do |index_in_words|
@@ -141,22 +120,3 @@ Then /^show me the e?mail( header)?s with:$/ do |only_header, raw_data|
141
120
 
142
121
  print MailFinder.show_mails(results.mails, only_header)
143
122
  end.overridable
144
-
145
- # nodoc (deprecated)
146
- Then /^that e?mail should( not)? have the following lines in the body:$/ do |negate, body|
147
- warn "The step /^that e?mail should( not)? have the following lines in the body:$/ has been deprecated in favor of the updated step /^(an?|no)( HTML| plain-text|) e?mail should have been sent with:$/."
148
- expectation = negate ? 'not_to' : 'to'
149
- mail = @mail || ActionMailer::Base.deliveries.last
150
- email_text_body = MailFinder.email_text_body(mail)
151
-
152
- body.to_s.strip.split(/\n/).each do |line|
153
- expect(email_text_body).send(expectation, include(line.strip))
154
- end
155
- end.overridable
156
-
157
- # nodoc (deprecated)
158
- Then /^that e?mail should have the following (?:|content in the )body:$/ do |body|
159
- warn "The step /^that e?mail should have the following( content in the)? body:$/ has been deprecated in favor of the updated step /^(an?|no)( HTML| plain-text|) e?mail should have been sent with:$/."
160
- mail = @mail || ActionMailer::Base.deliveries.last
161
- expect(MailFinder.email_text_body(mail)).to include(body.strip)
162
- end.overridable
@@ -0,0 +1,77 @@
1
+ # You can append `inside the [name or number] iframe` to any other step.
2
+ # Then the step will operate inside the given iframe.
3
+ # Examples:
4
+ #
5
+ # Then I should see "Kiwi" inside the 1st iframe
6
+ # Then I should see "Cherry" inside the fruits iframe
7
+ # When I press "Save" inside the 2nd iframe
8
+ #
9
+ When /^(.*?) inside the (.*?) iframe$/ do |nested_step, frame_identifier|
10
+ patiently do
11
+ frame = find_frame(frame_identifier)
12
+ page.within_frame(frame) do
13
+ step nested_step
14
+ end
15
+ end
16
+ end.overridable
17
+
18
+ # nodoc
19
+ When /^(.*?) inside the (.*?) iframe:$/ do |nested_step, frame_identifier, table_or_string|
20
+ patiently do
21
+ frame = find_frame(frame_identifier)
22
+ page.within_frame(frame) do
23
+ step("#{nested_step}:", table_or_string)
24
+ end
25
+ end
26
+ end.overridable
27
+
28
+ if Gem::Version.new(Capybara::VERSION) >= Gem::Version.new('3')
29
+
30
+ # This step will switch to the iframe identified by its name or number.
31
+ # All further steps will operate inside the iframe.
32
+ # To switch to operating on the main page again, use the step
33
+ # "I switch back to the whole page".
34
+ # Examples:
35
+ #
36
+ # When I switch to the 1st iframe
37
+ # When I switch to the fruits iframe
38
+ #
39
+ # Please note: This step is only available for Capybara >= 3.
40
+ When /^I switch to the (.*?) iframe$/ do |frame_identifier|
41
+ frame = find_frame(frame_identifier)
42
+ page.driver.switch_to_frame(frame)
43
+ end.overridable
44
+
45
+ # This step can be used to switch back to the whole page if you switched
46
+ # to operating inside an iframe before (step `I switch to the ... iframe`).
47
+ #
48
+ # Please note: This step is only available for Capybara >= 3.
49
+ When /^I switch back to the whole page$/ do
50
+ handle = page.driver.current_window_handle
51
+ page.driver.switch_to_window(handle)
52
+ end
53
+ end
54
+
55
+ module IframeStepsHelper
56
+ def find_frame(frame_identifier)
57
+ frame_id = convert_frame_identifier(frame_identifier)
58
+ case frame_id
59
+ when Integer
60
+ frames = page.find_all('iframe')
61
+ frames[frame_id]
62
+ when String
63
+ page.find("iframe[name='#{frame_id}']")
64
+ end
65
+ end
66
+
67
+ def convert_frame_identifier(frame_identifier)
68
+ number_regex = /\A(?<number>\d+)(st|nd|rd|th|\.)\z/
69
+ matches = frame_identifier.match(number_regex)
70
+ if matches && matches[:number]
71
+ matches[:number].to_i - 1 # selenium starts counting a 0
72
+ else
73
+ frame_identifier
74
+ end
75
+ end
76
+ end
77
+ World(IframeStepsHelper)
@@ -201,10 +201,10 @@ Then /^I should( not)? see a field "([^"]*)"$/ do |negate, name|
201
201
  expectation = negate ? :not_to : :to
202
202
  patiently do
203
203
  begin
204
- # In old Capybaras find_field returns nil, so we assign it to `field`
205
- field = find_field(name)
204
+ # In old Capybaras find returns nil, so we assign it to `field`
205
+ field = find_with_disabled(:field, name)
206
206
  rescue Capybara::ElementNotFound
207
- # In Capybara 0.4+ #find_field raises an error instead of returning nil
207
+ # In Capybara 0.4+ #find raises an error instead of returning nil
208
208
  # We must explicitely reset the field variable from a previous patiently iteration
209
209
  field = nil
210
210
  end
@@ -327,7 +327,7 @@ end.overridable
327
327
  # Checks that an input field contains some value (allowing * as wildcard character)
328
328
  Then /^the "([^"]*)" field should (not )?contain "([^"]*)"$/ do |label, negate, expected_string|
329
329
  patiently do
330
- field = find_field(label)
330
+ field = find_with_disabled(:field, label)
331
331
  field_value = case field.tag_name
332
332
  when 'select'
333
333
  options = field.all('option')
@@ -347,7 +347,7 @@ end.overridable
347
347
  # Checks that a multiline textarea contains some value (allowing * as wildcard character)
348
348
  Then(/^the "(.*?)" field should (not )?contain:$/) do |label, negate, expected_string|
349
349
  patiently do
350
- field = find_field(label)
350
+ field = find_with_disabled(:field, label)
351
351
  expect(field.value.chomp).send(negate ? :not_to : :to, contain_with_wildcards(expected_string))
352
352
  end
353
353
  end.overridable
@@ -369,7 +369,7 @@ end.overridable
369
369
  # Checks that an input field was wrapped with a validation error
370
370
  Then /^the "([^"]*)" field should have the error "([^"]*)"$/ do |field, error_message|
371
371
  patiently do
372
- element = find_field(field)
372
+ element = find_with_disabled(:field, field)
373
373
  classes = element.find(:xpath, '..')[:class].split(' ')
374
374
 
375
375
  form_for_input = element.find(:xpath, 'ancestor::form[1]')
@@ -390,35 +390,17 @@ end.overridable
390
390
  Then /^the "([^\"]*)" field should( not)? have an error$/ do |label, negate|
391
391
  patiently do
392
392
  expectation = negate ? :not_to : :to
393
- field = find_field(label)
393
+ field = find_with_disabled(:field, label)
394
394
  expect(field[:id]).to be_present # prevent bad CSS selector if field lacks id
395
395
  expect(page).send(expectation, have_css(".field_with_errors ##{field[:id]}"))
396
396
  end
397
397
  end.overridable
398
398
 
399
- Then /^the "([^"]*)" field should have no error$/ do |field|
400
- warn 'The step /^the "([^"]*)" field should have no error$/ is deprecated and scheduled for removal. Use the step /^the "([^\"]*)" field should( not)? have an error$/ instead.'
401
- patiently do
402
- element = find_field(field)
403
- classes = element.find(:xpath, '..')[:class].split(' ')
404
- expect(classes).not_to include('field_with_errors')
405
- expect(classes).not_to include('error')
406
- end
407
- end.overridable
408
-
409
- Then /^the "([^"]*)" checkbox should( not)? be checked( and disabled)?$/ do |label, negate, disabled|
399
+ Then /^the "([^"]*)" checkbox should( not)? be checked?$/ do |label, negate|
410
400
  expectation = negate ? :not_to : :to
411
401
 
412
- if disabled
413
- warn 'The step /^the "([^"]*)" checkbox should( not)? be checked( and disabled)?$/ will lose the `and disabled` modifier in Spreewald 3. In that version, the step will find a checkbox regardless of whether it is disabled.'
414
- end
415
-
416
402
  patiently do
417
- field = if Spreewald::Comparison.compare_versions(Capybara::VERSION, :<, "2.1")
418
- find_field(label)
419
- else
420
- find_field(label, :disabled => !!disabled)
421
- end
403
+ field = find_with_disabled(:field, label)
422
404
  expect(field).send expectation, be_checked
423
405
  end
424
406
  end.overridable
@@ -489,7 +471,7 @@ end.overridable
489
471
 
490
472
  Then /^nothing should be selected for "([^"]*)"$/ do |field|
491
473
  patiently do
492
- select = find_field(field)
474
+ select = find_with_disabled(:field, field)
493
475
  begin
494
476
  selected_option = select.find(:xpath, ".//option[@selected = 'selected']") || select.all(:css, 'option').first
495
477
  value = selected_option ? selected_option.value : nil
@@ -509,11 +491,11 @@ Then /^"([^"]*)" should( not)? be an option for "([^"]*)"$/ do |value, negate, f
509
491
  patiently do
510
492
  if negate
511
493
  begin
512
- expect(find_field(field)).to have_no_css(*finder_arguments)
494
+ expect(find_with_disabled(:field, field)).to have_no_css(*finder_arguments)
513
495
  rescue Capybara::ElementNotFound
514
496
  end
515
497
  else
516
- expect(find_field(field)).to have_css(*finder_arguments)
498
+ expect(find_with_disabled(:field, field)).to have_css(*finder_arguments)
517
499
  end
518
500
  end
519
501
  end.overridable
@@ -542,18 +524,12 @@ end.overridable
542
524
  # Within a selenium test, the browser is asked whether the element is really visible
543
525
  # In a non-selenium test, we only check for `.hidden`, `.invisible` or `style: display:none`
544
526
  #
545
- # 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. Note that the **not** option will be removed in future versions of Spreewald.
546
- #
547
527
  # More details [here](https://makandracards.com/makandra/1049-capybara-check-that-a-page-element-is-hidden-via-css)
548
- Then /^(the tag )?"([^\"]+)" should( not)? be visible$/ do |tag, selector_or_text, hidden|
549
- if hidden
550
- warn "The step 'Then ... should not be visible' is prone to misunderstandings. Please use 'Then ... should be hidden' or 'Then I should not see ...' instead."
551
- end
552
-
528
+ Then /^(the tag )?"([^\"]+)" should be visible$/ do |tag, selector_or_text|
553
529
  options = {}
554
530
  tag ? options.store(:selector, selector_or_text) : options.store(:text, selector_or_text)
555
531
 
556
- hidden ? assert_hidden(options) : assert_visible(options)
532
+ assert_visible(options)
557
533
  end.overridable
558
534
 
559
535
  # Checks that an element is actually present and hidden, also considering styles.
@@ -621,12 +597,6 @@ Then /^"([^"]*)" should link to "([^"]*)"$/ do |link_label, target|
621
597
  end
622
598
  end.overridable
623
599
 
624
- # Checks that the result has content type `text/plain`
625
- Then /^I should get a text response$/ do
626
- warn 'The step /^I should get a text response$/ is deprecated and scheduled for removal. Use `I should get a response with content-type "text/plain"` instead.'
627
- step 'I should get a response with content-type "text/plain"'
628
- end.overridable
629
-
630
600
  # Click a link within an element matching the given selector. Will try to be clever
631
601
  # and disregard elements that don't contain a matching link.
632
602
  #
@@ -695,11 +665,11 @@ end.overridable
695
665
  # Tests that a field with the given label is visible.
696
666
  Then /^the "([^\"]*)" field should( not)? be visible$/ do |label, hidden|
697
667
  if Spreewald::Comparison.compare_versions(Capybara::VERSION, :<, "2.1")
698
- field = find_field(label)
668
+ field = find_with_disabled(:field, label)
699
669
  else
700
670
  # Capybara 2.1+ won't usually interact with hidden elements,
701
671
  # but we can override this behavior by passing { visible: false }
702
- field = find_field(label, :visible => false)
672
+ field = find_with_disabled(:field, label, :visible => false)
703
673
  end
704
674
 
705
675
  selector = "##{field['id']}"
@@ -711,20 +681,6 @@ Then /^the "([^\"]*)" field should( not)? be visible$/ do |label, hidden|
711
681
  end
712
682
  end.overridable
713
683
 
714
- # Waits for the page to finish loading and AJAX requests to finish.
715
- #
716
- # More details [here](https://makandracards.com/makandra/12139-waiting-for-page-loads-and-ajax-requests-to-finish-with-capybara).
717
- When /^I wait for the page to load$/ do
718
- warn 'The step /^I wait for the page to load$/ is deprecated and scheduled for removal. Please see https://github.com/makandra/spreewald/issues/136'
719
- if javascript_capable?
720
- patiently do
721
- # when no jQuery is loaded, we assume there are no pending AJAX requests
722
- page.execute_script("return typeof jQuery === 'undefined' || $.active == 0;").should == true
723
- end
724
- end
725
- page.has_content? ''
726
- end.overridable
727
-
728
684
  # Performs HTTP basic authentication with the given credentials and visits the given path.
729
685
  #
730
686
  # More details [here](https://makandracards.com/makandra/971-perform-http-basic-authentication-in-cucumber).
@@ -761,7 +717,7 @@ end.overridable
761
717
  # Tests whether a select field is sorted. Uses Array#natural_sort, if defined;
762
718
  # Array#sort else.
763
719
  Then /^the "(.*?)" select should( not)? be sorted$/ do |label, negate|
764
- select = find_field(label)
720
+ select = find_with_disabled(:field, label)
765
721
  options = select.all('option').reject { |o| o.value.blank? }
766
722
  option_texts = options.collect(&:text)
767
723
 
@@ -1,20 +1,29 @@
1
1
  # coding: UTF-8
2
+ require "spreewald_support/mail_to_plaintext_converter"
3
+ require "forwardable"
2
4
 
3
5
  class MailFinder
6
+
4
7
  class << self
5
8
 
6
9
  attr_accessor :user_identity
7
10
 
8
11
  def find(raw_data, type = '')
9
- header, body = raw_data.split(/\n\n/, 2) # 2: maximum number of fields
12
+ header, body = raw_data.split(/\n\n/, 2).map(&:strip_heredoc) # 2: maximum number of fields
10
13
  conditions = {}
11
14
  header.split("\n").each do |row|
12
15
  if row.match(/^[A-Za-z\-]+: /i)
13
16
  key, value = row.split(": ", 2)
17
+ raise Spreewald::UnsupportedEmailHeader.new(key, value) unless Spreewald::SUPPORTED_EMAIL_HEADERS.include? key.strip
14
18
  conditions[key.strip.underscore.to_sym] = value.strip
15
19
  end
16
20
  end
17
21
 
22
+ # Interpret all lines as body if there are no header-link lines
23
+ if conditions.blank?
24
+ body = [header, body].join("\n\n")
25
+ end
26
+
18
27
  filename_method = Rails::VERSION::MAJOR < 3 ? 'original_filename' : 'filename'
19
28
  matching_header = ActionMailer::Base.deliveries.select do |mail|
20
29
  [ conditions[:to].nil? || mail.to.include?(resolve_email conditions[:to]),
@@ -58,15 +67,7 @@ class MailFinder
58
67
  end
59
68
 
60
69
  def email_text_body(mail, type = '')
61
- body = if mail.html_part && type != 'plain-text'
62
- dom = Nokogiri::HTML(mail.html_part.body.to_s)
63
- dom.at_css('body').text.gsub(/[\r\n]+/, "\n")
64
- elsif mail.text_part && type != 'HTML'
65
- mail.text_part.body.to_s
66
- else
67
- mail.body.to_s
68
- end
69
- body.gsub("\r\n", "\n") # The mail gem (>= 2.7.1) switched from \n to \r\n line breaks (LF to CRLF) in plain text mails.
70
+ Spreewald::MailToPlaintextConverter.new(mail, type).run
70
71
  end
71
72
 
72
73
  def show_mails(mails, only_header = false)
@@ -82,15 +83,13 @@ class MailFinder
82
83
  end
83
84
 
84
85
  def expected_body_regex(expected_body)
85
- # To stay backwards-compatible, this will only check whether an email
86
- # starts with the expected body.
87
86
  expected = '\A\n' + Regexp.quote(expected_body.strip) + '\n\Z'
88
87
  expected.gsub! '\n\*\n', '\n[\s\S]*\n'
89
88
  expected.gsub! '\*\n', '.*\n'
90
89
  expected.gsub! '\n\*', '\n.*'
91
90
 
92
91
  expected.gsub! '\A\n', '\A'
93
- expected.gsub! '\n\Z', '' # Change '' to '\Z' to force that the whole body matches
92
+ expected.gsub! '\n\Z', '\Z'
94
93
 
95
94
  Regexp.new(expected)
96
95
  end
@@ -0,0 +1,42 @@
1
+ require 'nokogiri'
2
+
3
+ module Spreewald
4
+ class MailToPlaintextConverter
5
+ def initialize(mail, type = '')
6
+ @mail = mail
7
+ @type = type
8
+ end
9
+
10
+ def run
11
+ body = ''
12
+ if mail.multipart?
13
+ body = if mail.html_part && type != 'plain-text'
14
+ text_from_html(mail.html_part.body.to_s)
15
+ elsif mail.text_part && type != 'HTML'
16
+ mail.text_part.body.to_s
17
+ else
18
+ mail.body.to_s
19
+ end
20
+ else
21
+ if body_text_html?
22
+ body = text_from_html(mail.body.to_s)
23
+ else
24
+ body = mail.body.to_s
25
+ end
26
+ end
27
+ body.gsub("\r\n", "\n") # The mail gem (>= 2.7.1) switched from \n to \r\n line breaks (LF to CRLF) in plain text mails.
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :mail, :type
33
+
34
+ def body_text_html?
35
+ mail.body.to_s.include? "<html>"
36
+ end
37
+
38
+ def text_from_html(html)
39
+ Nokogiri::HTML(html).at_css('body').text.gsub(/[\r\n]+/, "\n")
40
+ end
41
+ end
42
+ end