email_spec 2.2.1 → 2.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11bdd9e521aecbb968f672214cc109869f111f1ac981b793e1a3c41bcf4691ce
4
- data.tar.gz: 7cd61105485eae764f8786ef4a3e2ccdbd9309f8d020f883177d8d62df7df184
3
+ metadata.gz: 4e0a37bd9d3d9eaa30f18b427930baa52d8b895b50d4d7b831650d621a9c955e
4
+ data.tar.gz: 4193090888bee1123f782507dc6c8496b9bca6ff0aea94612624a48f9d45d65b
5
5
  SHA512:
6
- metadata.gz: 540ed6ea489564623c0ab0c781c70842782b8485307cf70d7396fc0221896ac396cae83a58d72e64586bb879b58a68b3e93b61f24120586657fe9acaea9f9486
7
- data.tar.gz: 57b37098385ff0d8f545e385195693ddf67c04d03d4c37a9219cf4677d36cc2a880e0dea6bca6eed595ac977eb9afd1841062d180e47410ce5ec6fe20c1820fd
6
+ metadata.gz: 97b61a1089f4c29bdcfffca000405a5d66bc2430dca4c9e293090cea5a12ebae9bacc108c3663b9a3961a5f955d59a0870a28c53a19d0782ed9d66ff6cfea15a
7
+ data.tar.gz: b38641514a7ceace6ea75f178865dffd9b910cebbc2eb28fea8c1ea3a7f64786e248900f34dd881f722c251ceb12e5f52f071257cf10b15eb316ad1a2e9e9427
data/Changelog.md CHANGED
@@ -1,6 +1,20 @@
1
+ ## 2.3.0 2024-07-21
2
+
3
+ * [Support the specified name and address for bcc_to and cc_to matchers](https://github.com/email-spec/email-spec/pull/212)
4
+ * [Allow launchy 3.x versions](https://github.com/email-spec/email-spec/pull/226)
5
+ * [Replace deprecated/removed File.exists? alias](https://github.com/email-spec/email-spec/pull/223)
6
+ * [Extend have_body_text matcher to be able to specify which part in multipart to check](https://github.com/email-spec/email-spec/pull/196)
7
+
8
+ ## 2.2.2 2023-06-26
9
+
10
+ * [Defer accommodating different delivery methods to runtime](https://github.com/email-spec/email-spec/pull/224)
11
+
1
12
  ## 2.2.1 2022-09-12
2
13
 
3
- * [Patch for eager loading](https://github.com/email-spec/email-spec/pull/219)
14
+ * [Support to decode part in EmailSpec::MailExt#default_part_body](https://github.com/email-spec/email-spec/pull/211)
15
+ * [Drop rubyforge_project from gemspec](https://github.com/email-spec/email-spec/pull/215)
16
+ * [Avoid eagerly loading ActionMailer::Base](https://github.com/email-spec/email-spec/pull/219)
17
+ * [README: use SVG badges](https://github.com/email-spec/email-spec/pull/217)
4
18
 
5
19
  ## 2.2.0 2018-04-03
6
20
 
data/README.md CHANGED
@@ -302,6 +302,15 @@ expect(email).to have_body_text(/Hi Jojo Binks,/)
302
302
  ```
303
303
 
304
304
 
305
+ You can specify which part in multipart to check with `in_html_part` or
306
+ `in_text_part`.
307
+
308
+ ```ruby
309
+ email = UserMailer.("jojo@yahoo.com", "Jojo Binks")
310
+ expect(email).to have_body_text(/This is html/).in_html_part
311
+ expect(email).to have_body_text(/This is text/).in_text_part
312
+ ```
313
+
305
314
  ##### have_header(key, value)
306
315
 
307
316
  This checks that the expected key/value pair is in the headers of the email.
@@ -0,0 +1,226 @@
1
+ # Commonly used email steps
2
+ #
3
+ # To add your own steps make a custom_email_steps.rb
4
+ # The provided methods are:
5
+ #
6
+ # last_email_address
7
+ # reset_mailer
8
+ # open_last_email
9
+ # visit_in_email
10
+ # unread_emails_for
11
+ # mailbox_for
12
+ # current_email
13
+ # open_email
14
+ # read_emails_for
15
+ # find_email
16
+ #
17
+ # General form for email scenarios are:
18
+ # - clear the email queue (done automatically by email_spec)
19
+ # - execute steps that sends an email
20
+ # - check the user received an/no/[0-9] emails
21
+ # - open the email
22
+ # - inspect the email contents
23
+ # - interact with the email (e.g. click links)
24
+ #
25
+ # The Cucumber steps below are setup in this order.
26
+
27
+ module EmailHelpers
28
+ def current_email_address
29
+ # Replace with your a way to find your current email. e.g @current_user.email
30
+ # last_email_address will return the last email address used by email spec to find an email.
31
+ # Note that last_email_address will be reset after each Scenario.
32
+ last_email_address || "example@example.com"
33
+ end
34
+ end
35
+
36
+ World(EmailHelpers)
37
+
38
+ #
39
+ # Reset the e-mail queue within a scenario.
40
+ # This is done automatically before each scenario.
41
+ #
42
+
43
+ Given /^(?:a clear email queue|no emails have been sent)$/ do
44
+ reset_mailer
45
+ end
46
+
47
+ #
48
+ # Check how many emails have been sent/received
49
+ #
50
+
51
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails?$/ do |address, amount|
52
+ expect(unread_emails_for(address).size).to eql parse_email_count(amount)
53
+ end
54
+
55
+ Then /^(?:I|they|"([^"]*?)") should have (an|no|\d+) emails?$/ do |address, amount|
56
+ expect(mailbox_for(address).size).to eql parse_email_count(amount)
57
+ end
58
+
59
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails? with subject "([^"]*?)"$/ do |address, amount, subject|
60
+ expect(unread_emails_for(address).select { |m| m.subject =~ Regexp.new(Regexp.escape(subject)) }.size).to eql parse_email_count(amount)
61
+ end
62
+
63
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails? with subject \/([^"]*?)\/$/ do |address, amount, subject|
64
+ expect(unread_emails_for(address).select { |m| m.subject =~ Regexp.new(subject) }.size).to eql parse_email_count(amount)
65
+ end
66
+
67
+ Then /^(?:I|they|"([^"]*?)") should receive an email with the following body:$/ do |address, expected_body|
68
+ open_email(address, :with_text => expected_body)
69
+ end
70
+
71
+ #
72
+ # Accessing emails
73
+ #
74
+
75
+ # Opens the most recently received email
76
+ When /^(?:I|they|"([^"]*?)") opens? the email$/ do |address|
77
+ open_email(address)
78
+ end
79
+
80
+ When /^(?:I|they|"([^"]*?)") opens? the email with subject "([^"]*?)"$/ do |address, subject|
81
+ open_email(address, :with_subject => subject)
82
+ end
83
+
84
+ When /^(?:I|they|"([^"]*?)") opens? the email with subject \/([^"]*?)\/$/ do |address, subject|
85
+ open_email(address, :with_subject => Regexp.new(subject))
86
+ end
87
+
88
+ When /^(?:I|they|"([^"]*?)") opens? the email with text "([^"]*?)"$/ do |address, text|
89
+ open_email(address, :with_text => text)
90
+ end
91
+
92
+ When /^(?:I|they|"([^"]*?)") opens? the email with text \/([^"]*?)\/$/ do |address, text|
93
+ open_email(address, :with_text => Regexp.new(text))
94
+ end
95
+
96
+ #
97
+ # Inspect the Email Contents
98
+ #
99
+
100
+ Then /^(?:I|they) should see "([^"]*?)" in the email subject$/ do |text|
101
+ expect(current_email).to have_subject(text)
102
+ end
103
+
104
+ Then /^(?:I|they) should see \/([^"]*?)\/ in the email subject$/ do |text|
105
+ expect(current_email).to have_subject(Regexp.new(text))
106
+ end
107
+
108
+ Then /^(?:I|they) should not see "([^"]*?)" in the email subject$/ do |text|
109
+ expect(current_email).not_to have_subject(text)
110
+ end
111
+
112
+ Then /^(?:I|they) should not see \/([^"]*?)\/ in the email subject$/ do |text|
113
+ expect(current_email).not_to have_subject(Regexp.new(text))
114
+ end
115
+
116
+ Then /^(?:I|they) should see "([^"]*?)" in the email body$/ do |text|
117
+ expect(current_email.default_part_body.to_s).to include(text)
118
+ end
119
+
120
+ Then /^(?:I|they) should not see "([^"]*?)" in the email body$/ do |text|
121
+ expect(current_email.default_part_body.to_s).not_to include(text)
122
+ end
123
+
124
+ Then /^(?:I|they) should see \/([^"]*?)\/ in the email body$/ do |text|
125
+ expect(current_email.default_part_body.to_s).to match Regexp.new(text)
126
+ end
127
+
128
+ Then /^(?:I|they) should not see \/([^"]*?)\/ in the email body$/ do |text|
129
+ expect(current_email.default_part_body.to_s).not_to match Regexp.new(text)
130
+ end
131
+
132
+ Then /^(?:I|they) should see the email delivered from "([^"]*?)"$/ do |text|
133
+ expect(current_email).to be_delivered_from(text)
134
+ end
135
+
136
+ Then /^(?:I|they) should see the email reply to "([^"]*?)"$/ do |text|
137
+ expect(current_email).to have_reply_to(text)
138
+ end
139
+
140
+ Then /^(?:I|they) should see "([^\"]*)" in the email "([^"]*?)" header$/ do |text, name|
141
+ expect(current_email).to have_header(name, text)
142
+ end
143
+
144
+ Then /^(?:I|they) should see \/([^\"]*)\/ in the email "([^"]*?)" header$/ do |text, name|
145
+ expect(current_email).to have_header(name, Regexp.new(text))
146
+ end
147
+
148
+ Then /^I should see it is a multi\-part email$/ do
149
+ expect(current_email).to be_multipart
150
+ end
151
+
152
+ Then /^(?:I|they) should see "([^"]*?)" in the email html part body$/ do |text|
153
+ expect(current_email.html_part.body.to_s).to include(text)
154
+ end
155
+
156
+ Then /^(?:I|they) should see "([^"]*?)" in the email text part body$/ do |text|
157
+ expect(current_email.text_part.body.to_s).to include(text)
158
+ end
159
+
160
+ #
161
+ # Inspect the Email Attachments
162
+ #
163
+
164
+ Then /^(?:I|they) should see (an|no|\d+) attachments? with the email$/ do |amount|
165
+ expect(current_email_attachments.size).to eql parse_email_count(amount)
166
+ end
167
+
168
+ Then /^there should be (an|no|\d+) attachments? named "([^"]*?)"$/ do |amount, filename|
169
+ expect(current_email_attachments.select { |a| a.filename == filename }.size).to eql parse_email_count(amount)
170
+ end
171
+
172
+ Then /^attachment (\d+) should be named "([^"]*?)"$/ do |index, filename|
173
+ expect(current_email_attachments[(index.to_i - 1)].filename).to eql filename
174
+ end
175
+
176
+ Then /^there should be (an|no|\d+) attachments? of type "([^"]*?)"$/ do |amount, content_type|
177
+ expect(current_email_attachments.select { |a| a.content_type.include?(content_type) }.size).to eql parse_email_count(amount)
178
+ end
179
+
180
+ Then /^attachment (\d+) should be of type "([^"]*?)"$/ do |index, content_type|
181
+ expect(current_email_attachments[(index.to_i - 1)].content_type).to include(content_type)
182
+ end
183
+
184
+ Then /^all attachments should not be blank$/ do
185
+ current_email_attachments.each do |attachment|
186
+ expect(attachment.read.size).to_not eql 0
187
+ end
188
+ end
189
+
190
+ Then /^show me a list of email attachments$/ do
191
+ EmailSpec::EmailViewer::save_and_open_email_attachments_list(current_email)
192
+ end
193
+
194
+ #
195
+ # Interact with Email Contents
196
+ #
197
+
198
+ When /^(?:I|they|"([^"]*?)") follows? "([^"]*?)" in the email$/ do |address, link|
199
+ visit_in_email(link, address)
200
+ end
201
+
202
+ When /^(?:I|they) click the first link in the email$/ do
203
+ click_first_link_in_email
204
+ end
205
+
206
+ #
207
+ # Debugging
208
+ # These only work with Rails and OSx ATM since EmailViewer uses RAILS_ROOT and OSx's 'open' command.
209
+ # Patches accepted. ;)
210
+ #
211
+
212
+ Then /^save and open current email$/ do
213
+ EmailSpec::EmailViewer::save_and_open_email(current_email)
214
+ end
215
+
216
+ Then /^save and open all text emails$/ do
217
+ EmailSpec::EmailViewer::save_and_open_all_text_emails
218
+ end
219
+
220
+ Then /^save and open all html emails$/ do
221
+ EmailSpec::EmailViewer::save_and_open_all_html_emails
222
+ end
223
+
224
+ Then /^save and open all raw emails$/ do
225
+ EmailSpec::EmailViewer::save_and_open_all_raw_emails
226
+ end
@@ -0,0 +1,226 @@
1
+ # Commonly used email steps
2
+ #
3
+ # To add your own steps make a custom_email_steps.rb
4
+ # The provided methods are:
5
+ #
6
+ # last_email_address
7
+ # reset_mailer
8
+ # open_last_email
9
+ # visit_in_email
10
+ # unread_emails_for
11
+ # mailbox_for
12
+ # current_email
13
+ # open_email
14
+ # read_emails_for
15
+ # find_email
16
+ #
17
+ # General form for email scenarios are:
18
+ # - clear the email queue (done automatically by email_spec)
19
+ # - execute steps that sends an email
20
+ # - check the user received an/no/[0-9] emails
21
+ # - open the email
22
+ # - inspect the email contents
23
+ # - interact with the email (e.g. click links)
24
+ #
25
+ # The Cucumber steps below are setup in this order.
26
+
27
+ module EmailHelpers
28
+ def current_email_address
29
+ # Replace with your a way to find your current email. e.g @current_user.email
30
+ # last_email_address will return the last email address used by email spec to find an email.
31
+ # Note that last_email_address will be reset after each Scenario.
32
+ last_email_address || "example@example.com"
33
+ end
34
+ end
35
+
36
+ World(EmailHelpers)
37
+
38
+ #
39
+ # Reset the e-mail queue within a scenario.
40
+ # This is done automatically before each scenario.
41
+ #
42
+
43
+ Given /^(?:a clear email queue|no emails have been sent)$/ do
44
+ reset_mailer
45
+ end
46
+
47
+ #
48
+ # Check how many emails have been sent/received
49
+ #
50
+
51
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails?$/ do |address, amount|
52
+ expect(unread_emails_for(address).size).to eql parse_email_count(amount)
53
+ end
54
+
55
+ Then /^(?:I|they|"([^"]*?)") should have (an|no|\d+) emails?$/ do |address, amount|
56
+ expect(mailbox_for(address).size).to eql parse_email_count(amount)
57
+ end
58
+
59
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails? with subject "([^"]*?)"$/ do |address, amount, subject|
60
+ expect(unread_emails_for(address).select { |m| m.subject =~ Regexp.new(Regexp.escape(subject)) }.size).to eql parse_email_count(amount)
61
+ end
62
+
63
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails? with subject \/([^"]*?)\/$/ do |address, amount, subject|
64
+ expect(unread_emails_for(address).select { |m| m.subject =~ Regexp.new(subject) }.size).to eql parse_email_count(amount)
65
+ end
66
+
67
+ Then /^(?:I|they|"([^"]*?)") should receive an email with the following body:$/ do |address, expected_body|
68
+ open_email(address, :with_text => expected_body)
69
+ end
70
+
71
+ #
72
+ # Accessing emails
73
+ #
74
+
75
+ # Opens the most recently received email
76
+ When /^(?:I|they|"([^"]*?)") opens? the email$/ do |address|
77
+ open_email(address)
78
+ end
79
+
80
+ When /^(?:I|they|"([^"]*?)") opens? the email with subject "([^"]*?)"$/ do |address, subject|
81
+ open_email(address, :with_subject => subject)
82
+ end
83
+
84
+ When /^(?:I|they|"([^"]*?)") opens? the email with subject \/([^"]*?)\/$/ do |address, subject|
85
+ open_email(address, :with_subject => Regexp.new(subject))
86
+ end
87
+
88
+ When /^(?:I|they|"([^"]*?)") opens? the email with text "([^"]*?)"$/ do |address, text|
89
+ open_email(address, :with_text => text)
90
+ end
91
+
92
+ When /^(?:I|they|"([^"]*?)") opens? the email with text \/([^"]*?)\/$/ do |address, text|
93
+ open_email(address, :with_text => Regexp.new(text))
94
+ end
95
+
96
+ #
97
+ # Inspect the Email Contents
98
+ #
99
+
100
+ Then /^(?:I|they) should see "([^"]*?)" in the email subject$/ do |text|
101
+ expect(current_email).to have_subject(text)
102
+ end
103
+
104
+ Then /^(?:I|they) should see \/([^"]*?)\/ in the email subject$/ do |text|
105
+ expect(current_email).to have_subject(Regexp.new(text))
106
+ end
107
+
108
+ Then /^(?:I|they) should not see "([^"]*?)" in the email subject$/ do |text|
109
+ expect(current_email).not_to have_subject(text)
110
+ end
111
+
112
+ Then /^(?:I|they) should not see \/([^"]*?)\/ in the email subject$/ do |text|
113
+ expect(current_email).not_to have_subject(Regexp.new(text))
114
+ end
115
+
116
+ Then /^(?:I|they) should see "([^"]*?)" in the email body$/ do |text|
117
+ expect(current_email.default_part_body.to_s).to include(text)
118
+ end
119
+
120
+ Then /^(?:I|they) should not see "([^"]*?)" in the email body$/ do |text|
121
+ expect(current_email.default_part_body.to_s).not_to include(text)
122
+ end
123
+
124
+ Then /^(?:I|they) should see \/([^"]*?)\/ in the email body$/ do |text|
125
+ expect(current_email.default_part_body.to_s).to match Regexp.new(text)
126
+ end
127
+
128
+ Then /^(?:I|they) should not see \/([^"]*?)\/ in the email body$/ do |text|
129
+ expect(current_email.default_part_body.to_s).not_to match Regexp.new(text)
130
+ end
131
+
132
+ Then /^(?:I|they) should see the email delivered from "([^"]*?)"$/ do |text|
133
+ expect(current_email).to be_delivered_from(text)
134
+ end
135
+
136
+ Then /^(?:I|they) should see the email reply to "([^"]*?)"$/ do |text|
137
+ expect(current_email).to have_reply_to(text)
138
+ end
139
+
140
+ Then /^(?:I|they) should see "([^\"]*)" in the email "([^"]*?)" header$/ do |text, name|
141
+ expect(current_email).to have_header(name, text)
142
+ end
143
+
144
+ Then /^(?:I|they) should see \/([^\"]*)\/ in the email "([^"]*?)" header$/ do |text, name|
145
+ expect(current_email).to have_header(name, Regexp.new(text))
146
+ end
147
+
148
+ Then /^I should see it is a multi\-part email$/ do
149
+ expect(current_email).to be_multipart
150
+ end
151
+
152
+ Then /^(?:I|they) should see "([^"]*?)" in the email html part body$/ do |text|
153
+ expect(current_email.html_part.body.to_s).to include(text)
154
+ end
155
+
156
+ Then /^(?:I|they) should see "([^"]*?)" in the email text part body$/ do |text|
157
+ expect(current_email.text_part.body.to_s).to include(text)
158
+ end
159
+
160
+ #
161
+ # Inspect the Email Attachments
162
+ #
163
+
164
+ Then /^(?:I|they) should see (an|no|\d+) attachments? with the email$/ do |amount|
165
+ expect(current_email_attachments.size).to eql parse_email_count(amount)
166
+ end
167
+
168
+ Then /^there should be (an|no|\d+) attachments? named "([^"]*?)"$/ do |amount, filename|
169
+ expect(current_email_attachments.select { |a| a.filename == filename }.size).to eql parse_email_count(amount)
170
+ end
171
+
172
+ Then /^attachment (\d+) should be named "([^"]*?)"$/ do |index, filename|
173
+ expect(current_email_attachments[(index.to_i - 1)].filename).to eql filename
174
+ end
175
+
176
+ Then /^there should be (an|no|\d+) attachments? of type "([^"]*?)"$/ do |amount, content_type|
177
+ expect(current_email_attachments.select { |a| a.content_type.include?(content_type) }.size).to eql parse_email_count(amount)
178
+ end
179
+
180
+ Then /^attachment (\d+) should be of type "([^"]*?)"$/ do |index, content_type|
181
+ expect(current_email_attachments[(index.to_i - 1)].content_type).to include(content_type)
182
+ end
183
+
184
+ Then /^all attachments should not be blank$/ do
185
+ current_email_attachments.each do |attachment|
186
+ expect(attachment.read.size).to_not eql 0
187
+ end
188
+ end
189
+
190
+ Then /^show me a list of email attachments$/ do
191
+ EmailSpec::EmailViewer::save_and_open_email_attachments_list(current_email)
192
+ end
193
+
194
+ #
195
+ # Interact with Email Contents
196
+ #
197
+
198
+ When /^(?:I|they|"([^"]*?)") follows? "([^"]*?)" in the email$/ do |address, link|
199
+ visit_in_email(link, address)
200
+ end
201
+
202
+ When /^(?:I|they) click the first link in the email$/ do
203
+ click_first_link_in_email
204
+ end
205
+
206
+ #
207
+ # Debugging
208
+ # These only work with Rails and OSx ATM since EmailViewer uses RAILS_ROOT and OSx's 'open' command.
209
+ # Patches accepted. ;)
210
+ #
211
+
212
+ Then /^save and open current email$/ do
213
+ EmailSpec::EmailViewer::save_and_open_email(current_email)
214
+ end
215
+
216
+ Then /^save and open all text emails$/ do
217
+ EmailSpec::EmailViewer::save_and_open_all_text_emails
218
+ end
219
+
220
+ Then /^save and open all html emails$/ do
221
+ EmailSpec::EmailViewer::save_and_open_all_html_emails
222
+ end
223
+
224
+ Then /^save and open all raw emails$/ do
225
+ EmailSpec::EmailViewer::save_and_open_all_raw_emails
226
+ end
@@ -6,13 +6,13 @@ Given /^the (\w+) app is setup with the latest email steps$/ do |app_name|
6
6
  'email_steps.rb')
7
7
  latest_specs_path = File.join(root_dir, 'lib', 'generators', 'email_spec',
8
8
  'steps', 'templates','email_steps.rb')
9
- FileUtils.rm(email_specs_path) if File.exists?(email_specs_path)
9
+ FileUtils.rm(email_specs_path) if File.exist?(email_specs_path)
10
10
  FileUtils.cp_r(latest_specs_path, email_specs_path)
11
11
  end
12
12
 
13
13
  Then /^the (\w+) app should have the email steps in place$/ do |app_name|
14
14
  email_specs_path = "#{root_dir}/examples/#{app_name}_root/features/step_definitions/email_steps.rb"
15
- expect(File.exists?(email_specs_path)).to be true
15
+ expect(File.exist?(email_specs_path)).to be true
16
16
  end
17
17
 
18
18
  Then /^I should see the following summary report:$/ do |expected_report|
@@ -22,7 +22,7 @@ end
22
22
  Given /^the (\w+) app is setup with the latest generators$/ do |app_name|
23
23
  app_dir= File.join(root_dir,'examples',"#{app_name}_root")
24
24
  email_specs_path = File.join(app_dir,'features','step_definitions','email_steps.rb')
25
- FileUtils.rm(email_specs_path) if File.exists?(email_specs_path)
25
+ FileUtils.rm(email_specs_path) if File.exist?(email_specs_path)
26
26
 
27
27
  if app_name == 'rails4'
28
28
  #Testing using the gem
@@ -46,7 +46,7 @@ When /^I run "([^\"]*)" in the (\w+) app$/ do |cmd, app_name|
46
46
  app_specific_gemfile = File.join(app_path,'Gemfile')
47
47
  Dir.chdir(app_path) do
48
48
  #hack to fight competing bundles (email specs vs rails4_root's
49
- if File.exists? app_specific_gemfile
49
+ if File.exist? app_specific_gemfile
50
50
  orig_gemfile = ENV['BUNDLE_GEMFILE']
51
51
  ENV['BUNDLE_GEMFILE'] = app_specific_gemfile
52
52
  @output = `#{cmd}`
@@ -1,5 +1,5 @@
1
1
  module EmailSpec
2
- module MailerDeliveries
2
+ module Deliveries
3
3
  def all_emails
4
4
  deliveries
5
5
  end
@@ -9,7 +9,9 @@ module EmailSpec
9
9
  end
10
10
 
11
11
  def reset_mailer
12
- if defined?(ActionMailer) && ActionMailer::Base.delivery_method == :cache
12
+ if defined?(ActionMailer) && ActionMailer::Base.delivery_method == :activerecord
13
+ Email.delete_all
14
+ elsif defined?(ActionMailer) && ActionMailer::Base.delivery_method == :cache
13
15
  mailer.clear_cache
14
16
  else
15
17
  deliveries.clear
@@ -23,36 +25,22 @@ module EmailSpec
23
25
  protected
24
26
 
25
27
  def deliveries
26
- if ActionMailer::Base.delivery_method == :cache
28
+ if defined?(Pony)
29
+ Pony.deliveries
30
+ elsif ActionMailer::Base.delivery_method == :activerecord
31
+ Email.all.map { |email| parse_ar_to_mail(email) }
32
+ elsif ActionMailer::Base.delivery_method == :cache
27
33
  mailer.cached_deliveries
28
34
  else
29
35
  mailer.deliveries
30
36
  end
31
37
  end
32
- end
33
-
34
- module ARMailerDeliveries
35
- def all_emails
36
- Email.all.map{ |email| parse_to_mail(email) }
37
- end
38
38
 
39
- def last_email_sent
40
- if email = Email.last
41
- parse_to_mail(email)
42
- else
43
- raise("No email has been sent!")
44
- end
39
+ def mailer
40
+ ActionMailer::Base
45
41
  end
46
42
 
47
- def reset_mailer
48
- Email.delete_all
49
- end
50
-
51
- def mailbox_for(address)
52
- Email.all.select { |email| email.destinations.include?(address) }.map{ |email| parse_to_mail(email) }
53
- end
54
-
55
- def parse_to_mail(email)
43
+ def parse_ar_to_mail(email)
56
44
  Mail.read(email.mail)
57
45
  end
58
46
  end
@@ -68,24 +56,4 @@ module EmailSpec
68
56
  end
69
57
  end
70
58
  end
71
-
72
- module Deliveries
73
- if defined?(Pony)
74
- def deliveries; Pony::deliveries ; end
75
- include EmailSpec::MailerDeliveries
76
- else
77
- ActiveSupport.on_load(:action_mailer) do
78
- if delivery_method == :activerecord
79
- ::EmailSpec::Helpers.include EmailSpec::ARMailerDeliveries
80
- else
81
- ::EmailSpec::Deliveries.module_eval do
82
- def mailer
83
- ActionMailer::Base
84
- end
85
- end
86
- ::EmailSpec::Helpers.include ::EmailSpec::MailerDeliveries
87
- end
88
- end
89
- end
90
- end
91
59
  end
@@ -0,0 +1,45 @@
1
+ module EmailSpec
2
+ module Extractors
3
+ class Base
4
+ attr_accessor :mail
5
+
6
+ def initialize(mail)
7
+ @mail = mail
8
+ end
9
+
10
+ def call
11
+ part_body ? HTMLEntities.new.decode(part_body) : ''
12
+ end
13
+
14
+ private
15
+
16
+ def part_body
17
+ raise NotImplementedError
18
+ end
19
+ end
20
+
21
+ class DefaultPartBody < Base
22
+ private
23
+
24
+ def part_body
25
+ (mail.html_part || mail.text_part || mail).body
26
+ end
27
+ end
28
+
29
+ class HtmlPartBody < Base
30
+ private
31
+
32
+ def part_body
33
+ mail.html_part ? mail.html_part.body : nil
34
+ end
35
+ end
36
+
37
+ class TextPartBody < Base
38
+ private
39
+
40
+ def part_body
41
+ mail.text_part ? mail.text_part.body : nil
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,3 +1,5 @@
1
+ require_relative 'extractors'
2
+
1
3
  module EmailSpec
2
4
  module Matchers
3
5
  class EmailMatcher
@@ -128,7 +130,7 @@ module EmailSpec
128
130
 
129
131
  def matches?(email)
130
132
  @email = email
131
- @actual_recipients = address_array{ email.bcc }.sort
133
+ @actual_recipients = address_array { email[:bcc].formatted }.sort
132
134
  @actual_recipients == @expected_email_addresses
133
135
  end
134
136
 
@@ -162,7 +164,7 @@ module EmailSpec
162
164
 
163
165
  def matches?(email)
164
166
  @email = email
165
- @actual_recipients = address_array { email.cc }.sort
167
+ @actual_recipients = address_array { email[:cc].formatted }.sort
166
168
  @actual_recipients == @expected_email_addresses
167
169
  end
168
170
 
@@ -274,6 +276,7 @@ module EmailSpec
274
276
 
275
277
  def initialize(text)
276
278
  @expected_text = text
279
+ @extractor = EmailSpec::Extractors::DefaultPartBody
277
280
  end
278
281
 
279
282
  def description
@@ -284,13 +287,23 @@ module EmailSpec
284
287
  end
285
288
  end
286
289
 
290
+ def in_html_part
291
+ @extractor = EmailSpec::Extractors::HtmlPartBody
292
+ self
293
+ end
294
+
295
+ def in_text_part
296
+ @extractor = EmailSpec::Extractors::TextPartBody
297
+ self
298
+ end
299
+
287
300
  def matches?(email)
288
301
  if @expected_text.is_a?(String)
289
- @given_text = email.default_part_body.to_s.gsub(/\s+/, " ")
302
+ @given_text = @extractor.new(email).call.to_s.gsub(/\s+/, " ")
290
303
  @expected_text = @expected_text.gsub(/\s+/, " ")
291
304
  @given_text.include?(@expected_text)
292
305
  else
293
- @given_text = email.default_part_body.to_s
306
+ @given_text = @extractor.new(email).call.to_s
294
307
  !!(@given_text =~ @expected_text)
295
308
  end
296
309
  end
@@ -358,7 +371,14 @@ module EmailSpec
358
371
  alias negative_failure_message failure_message_when_negated
359
372
 
360
373
  def mail_headers_hash(email_headers)
361
- email_headers.fields.inject({}) { |hash, field| hash[field.field.class::FIELD_NAME] = field.to_s; hash }
374
+ email_headers.fields.inject({}) do |hash, field|
375
+ if field.field.class.const_defined?('FIELD_NAME')
376
+ hash[field.field.class::FIELD_NAME] = field.to_s
377
+ else
378
+ hash[field.field.class::NAME.downcase] = field.to_s
379
+ end
380
+ hash
381
+ end
362
382
  end
363
383
  end
364
384
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EmailSpec
2
- VERSION = '2.2.1'
4
+ VERSION = "2.3.0"
3
5
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support'
3
2
 
4
3
  describe EmailSpec::MailExt do
5
4
  describe "#default_part" do
@@ -40,8 +39,9 @@ describe EmailSpec::MailExt do
40
39
  it "decodes parts before return" do
41
40
  email = Mail.new(:body => "hello\r\nquoted-printable")
42
41
  email.content_transfer_encoding = 'quoted-printable'
43
- expect(email.encoded).to include("hello=0D\nquoted-printable")
44
- expect(email.default_part_body).to eq("hello\r\nquoted-printable")
42
+
43
+ expect(email.encoded).to include("hello\r\nquoted-printable=")
44
+ expect(email.default_part_body).to eq("hello\nquoted-printable")
45
45
  end
46
46
  end
47
47
 
@@ -137,7 +137,7 @@ describe EmailSpec::Matchers do
137
137
  end
138
138
 
139
139
  it "should not match when the email does not have a sender" do
140
- email = Mail::Message.new(:from => nil)
140
+ email = Mail::Message.new(:from => "johnshow@yahoo.com")
141
141
  expect(deliver_from("jimmy_bean@yahoo.com")).not_to match(email)
142
142
  end
143
143
 
@@ -178,6 +178,12 @@ describe EmailSpec::Matchers do
178
178
  expect(bcc_to("jimmy_bean@yahoo.com")).to match(email)
179
179
  end
180
180
 
181
+ it "should match when the email is set to deliver to the specified name and address" do
182
+ email = Mail::Message.new(:bcc => "Jimmy Bean <jimmy_bean@yahoo.com>")
183
+
184
+ expect(bcc_to("Jimmy Bean <jimmy_bean@yahoo.com>")).to match(email)
185
+ end
186
+
181
187
  it "should match when a list of emails is exact same as all of the email's recipients" do
182
188
  email = Mail::Message.new(:bcc => ["james@yahoo.com", "karen@yahoo.com"])
183
189
 
@@ -214,6 +220,12 @@ describe EmailSpec::Matchers do
214
220
  expect(cc_to("jimmy_bean@yahoo.com")).to match(email)
215
221
  end
216
222
 
223
+ it "should match when the email is set to deliver to the specified name and address" do
224
+ email = Mail::Message.new(:cc => "Jimmy Bean <jimmy_bean@yahoo.com>")
225
+
226
+ expect(cc_to("Jimmy Bean <jimmy_bean@yahoo.com>")).to match(email)
227
+ end
228
+
217
229
  it "should match when a list of emails is exact same as all of the email's recipients" do
218
230
  email = Mail::Message.new(:cc => ["james@yahoo.com", "karen@yahoo.com"])
219
231
 
@@ -454,6 +466,106 @@ describe EmailSpec::Matchers do
454
466
  end
455
467
  end
456
468
 
469
+ describe "#have_body_text", ".in_html_part" do
470
+ describe 'when html part is definded in mulitpart' do
471
+ it 'should match when the body matches regexp' do
472
+ email = Mail.new do
473
+ html_part do
474
+ body 'This is html'
475
+ end
476
+ end
477
+
478
+ expect(have_body_text(/This is html/).in_html_part).to match(email)
479
+ end
480
+ end
481
+
482
+ describe 'when text part is definded in mulitpart' do
483
+ it 'should not look at text part' do
484
+ email = Mail.new do
485
+ text_part do
486
+ body 'This is text'
487
+ end
488
+ end
489
+
490
+ expect(have_body_text(/This is text/).in_html_part).not_to match(email)
491
+ end
492
+ end
493
+
494
+ describe 'when html and text parts are definded in mulitpart' do
495
+ it 'should look at html part' do
496
+ email = Mail.new do
497
+ html_part do
498
+ body 'This is html'
499
+ end
500
+ text_part do
501
+ body 'This is text'
502
+ end
503
+ end
504
+
505
+ expect(have_body_text(/This is html/).in_html_part).to match(email)
506
+ expect(have_body_text(/This is text/).in_html_part).not_to match(email)
507
+ end
508
+ end
509
+
510
+ describe 'when nothing is defined in mulitpart' do
511
+ it 'should not look at any parts' do
512
+ email = Mail.new(body: 'This is body')
513
+
514
+ expect(have_body_text(/This is body/).in_html_part).not_to match(email)
515
+ end
516
+ end
517
+ end
518
+
519
+ describe "#have_body_text", ".in_text_part" do
520
+ describe 'when text part is definded in mulitpart' do
521
+ it 'should match when the body matches regexp' do
522
+ email = Mail.new do
523
+ text_part do
524
+ body 'This is text'
525
+ end
526
+ end
527
+
528
+ expect(have_body_text(/This is text/).in_text_part).to match(email)
529
+ end
530
+ end
531
+
532
+ describe 'when text and html parts are definded in mulitpart' do
533
+ it 'should look at text part' do
534
+ email = Mail.new do
535
+ text_part do
536
+ body 'This is text'
537
+ end
538
+
539
+ html_part do
540
+ body 'This is html'
541
+ end
542
+ end
543
+
544
+ expect(have_body_text(/This is text/).in_text_part).to match(email)
545
+ expect(have_body_text(/This is html/).in_text_part).not_to match(email)
546
+ end
547
+ end
548
+
549
+ describe 'when html part is definded in mulitpart' do
550
+ it 'should not look at html part' do
551
+ email = Mail.new do
552
+ html_part do
553
+ body "This is html"
554
+ end
555
+ end
556
+
557
+ expect(have_body_text(/This is html/).in_text_part).not_to match(email)
558
+ end
559
+ end
560
+
561
+ describe 'when nothing is defined in mulitpart' do
562
+ it 'should not look at any parts' do
563
+ email = Mail.new(body: 'This is body')
564
+
565
+ expect(have_body_text(/This is body/).in_text_part).not_to match(email)
566
+ end
567
+ end
568
+ end
457
569
  describe "#have_header" do
458
570
  describe "when regexps are used" do
459
571
  it "should match when header matches passed in regexp" do
data/spec/spec_helper.rb CHANGED
@@ -3,9 +3,6 @@ require 'action_mailer'
3
3
  require 'mail'
4
4
  require File.expand_path(File.dirname(__FILE__) + '/../lib/email_spec.rb')
5
5
 
6
- # Trigger loading ActionMailer::Base
7
- ActionMailer::Base
8
-
9
6
  RSpec.configure do |config|
10
7
  config.include EmailSpec::Helpers
11
8
  config.include EmailSpec::Matchers
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: email_spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Mabey
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-09-12 00:00:00.000000000 Z
13
+ date: 2024-07-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: htmlentities
@@ -30,16 +30,22 @@ dependencies:
30
30
  name: launchy
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
- - - "~>"
33
+ - - ">="
34
34
  - !ruby/object:Gem::Version
35
35
  version: '2.1'
36
+ - - "<"
37
+ - !ruby/object:Gem::Version
38
+ version: '4.0'
36
39
  type: :runtime
37
40
  prerelease: false
38
41
  version_requirements: !ruby/object:Gem::Requirement
39
42
  requirements:
40
- - - "~>"
43
+ - - ">="
41
44
  - !ruby/object:Gem::Version
42
45
  version: '2.1'
46
+ - - "<"
47
+ - !ruby/object:Gem::Version
48
+ version: '4.0'
43
49
  - !ruby/object:Gem::Dependency
44
50
  name: mail
45
51
  requirement: !ruby/object:Gem::Requirement
@@ -82,20 +88,6 @@ dependencies:
82
88
  - - "~>"
83
89
  - !ruby/object:Gem::Version
84
90
  version: 1.3.17
85
- - !ruby/object:Gem::Dependency
86
- name: actionmailer
87
- requirement: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - "~>"
90
- - !ruby/object:Gem::Version
91
- version: '4.2'
92
- type: :development
93
- prerelease: false
94
- version_requirements: !ruby/object:Gem::Requirement
95
- requirements:
96
- - - "~>"
97
- - !ruby/object:Gem::Version
98
- version: '4.2'
99
91
  - !ruby/object:Gem::Dependency
100
92
  name: rack-test
101
93
  requirement: !ruby/object:Gem::Requirement
@@ -227,6 +219,7 @@ files:
227
219
  - examples/rails4_root/features/delayed_job.feature
228
220
  - examples/rails4_root/features/errors.feature
229
221
  - examples/rails4_root/features/example.feature
222
+ - examples/rails4_root/features/step_definitions/email_steps.rb
230
223
  - examples/rails4_root/features/step_definitions/user_steps.rb
231
224
  - examples/rails4_root/features/step_definitions/web_steps.rb
232
225
  - examples/rails4_root/features/support/env.rb
@@ -260,6 +253,7 @@ files:
260
253
  - examples/sinatra_root/config.ru
261
254
  - examples/sinatra_root/features/errors.feature
262
255
  - examples/sinatra_root/features/example.feature
256
+ - examples/sinatra_root/features/step_definitions/email_steps.rb
263
257
  - examples/sinatra_root/features/step_definitions/user_steps.rb
264
258
  - examples/sinatra_root/features/step_definitions/web_steps.rb
265
259
  - examples/sinatra_root/features/support/env.rb
@@ -276,6 +270,7 @@ files:
276
270
  - lib/email_spec/deliveries.rb
277
271
  - lib/email_spec/email_viewer.rb
278
272
  - lib/email_spec/errors.rb
273
+ - lib/email_spec/extractors.rb
279
274
  - lib/email_spec/helpers.rb
280
275
  - lib/email_spec/mail_ext.rb
281
276
  - lib/email_spec/matchers.rb
@@ -309,7 +304,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
309
304
  - !ruby/object:Gem::Version
310
305
  version: '0'
311
306
  requirements: []
312
- rubygems_version: 3.3.21
307
+ rubygems_version: 3.5.10
313
308
  signing_key:
314
309
  specification_version: 4
315
310
  summary: Easily test email in RSpec, Cucumber or Minitest