postmark 1.8.1 → 1.21.3

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.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +8 -5
  4. data/CHANGELOG.rdoc +86 -0
  5. data/CONTRIBUTING.md +18 -0
  6. data/Gemfile +6 -5
  7. data/LICENSE +1 -1
  8. data/README.md +34 -607
  9. data/RELEASE.md +12 -0
  10. data/VERSION +1 -1
  11. data/gemfiles/Gemfile.legacy +5 -4
  12. data/lib/postmark.rb +1 -18
  13. data/lib/postmark/account_api_client.rb +55 -1
  14. data/lib/postmark/api_client.rb +145 -17
  15. data/lib/postmark/bounce.rb +0 -4
  16. data/lib/postmark/client.rb +12 -4
  17. data/lib/postmark/error.rb +127 -0
  18. data/lib/postmark/handlers/mail.rb +10 -4
  19. data/lib/postmark/helpers/message_helper.rb +4 -0
  20. data/lib/postmark/http_client.rb +20 -32
  21. data/lib/postmark/mail_message_converter.rb +18 -5
  22. data/lib/postmark/message_extensions/mail.rb +83 -8
  23. data/lib/postmark/version.rb +1 -1
  24. data/postmark.gemspec +1 -1
  25. data/postmark.png +0 -0
  26. data/spec/integration/account_api_client_spec.rb +42 -10
  27. data/spec/integration/api_client_hashes_spec.rb +32 -49
  28. data/spec/integration/api_client_messages_spec.rb +33 -52
  29. data/spec/integration/api_client_resources_spec.rb +12 -44
  30. data/spec/integration/mail_delivery_method_spec.rb +21 -23
  31. data/spec/spec_helper.rb +4 -7
  32. data/spec/support/custom_matchers.rb +44 -0
  33. data/spec/support/shared_examples.rb +16 -16
  34. data/spec/unit/postmark/account_api_client_spec.rb +239 -45
  35. data/spec/unit/postmark/api_client_spec.rb +792 -406
  36. data/spec/unit/postmark/bounce_spec.rb +40 -62
  37. data/spec/unit/postmark/client_spec.rb +0 -6
  38. data/spec/unit/postmark/error_spec.rb +231 -0
  39. data/spec/unit/postmark/handlers/mail_spec.rb +59 -27
  40. data/spec/unit/postmark/helpers/hash_helper_spec.rb +5 -6
  41. data/spec/unit/postmark/helpers/message_helper_spec.rb +60 -11
  42. data/spec/unit/postmark/http_client_spec.rb +76 -61
  43. data/spec/unit/postmark/inbound_spec.rb +34 -34
  44. data/spec/unit/postmark/inflector_spec.rb +11 -13
  45. data/spec/unit/postmark/json_spec.rb +2 -2
  46. data/spec/unit/postmark/mail_message_converter_spec.rb +250 -81
  47. data/spec/unit/postmark/message_extensions/mail_spec.rb +249 -38
  48. data/spec/unit/postmark_spec.rb +37 -37
  49. metadata +41 -11
@@ -1,188 +1,247 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Postmark::ApiClient do
4
-
5
- let(:api_token) { "provided-api-token" }
6
- let(:max_retries) { 42 }
7
- let(:message_hash) {
8
- {
9
- :from => "support@postmarkapp.com"
10
- }
11
- }
4
+ let(:api_token) {"provided-api-token"}
5
+ let(:max_retries) {42}
6
+ let(:message_hash) {{:from => "support@postmarkapp.com"}}
12
7
  let(:message) {
13
8
  Mail.new do
14
9
  from "support@postmarkapp.com"
15
10
  delivery_method Mail::Postmark
16
11
  end
17
12
  }
13
+ let(:templated_message) do
14
+ Mail.new do
15
+ from "sheldon@bigbangtheory.com"
16
+ to "lenard@bigbangtheory.com"
17
+ template_alias "hello"
18
+ template_model :name => "Sheldon"
19
+ end
20
+ end
21
+ let(:http_client) {api_client.http_client}
18
22
 
19
- let(:api_client) { Postmark::ApiClient.new(api_token) }
20
- subject { api_client }
23
+ subject(:api_client) {Postmark::ApiClient.new(api_token)}
21
24
 
22
25
  context "attr readers" do
23
- it { should respond_to(:http_client) }
24
- it { should respond_to(:max_retries) }
26
+ it { expect(subject).to respond_to(:http_client) }
27
+ it { expect(subject).to respond_to(:max_retries) }
25
28
  end
26
29
 
27
30
  context "when it's created without options" do
28
-
29
- its(:max_retries) { should eq 3 }
30
-
31
+ it "max retries" do
32
+ expect(subject.max_retries).to eq 3
33
+ end
31
34
  end
32
35
 
33
36
  context "when it's created with user options" do
34
-
35
- subject { Postmark::ApiClient.new(api_token, :max_retries => max_retries,
36
- :foo => :bar)}
37
-
38
- its(:max_retries) { should eq max_retries }
37
+ subject {Postmark::ApiClient.new(api_token, :max_retries => max_retries, :foo => :bar)}
38
+ it "max_retries" do
39
+ expect(subject.max_retries).to eq max_retries
40
+ end
39
41
 
40
42
  it 'passes other options to HttpClient instance' do
41
- Postmark::HttpClient.should_receive(:new).with(api_token, :foo => :bar)
42
- subject.should be
43
+ allow(Postmark::HttpClient).to receive(:new).with(api_token, :foo => :bar)
44
+ expect(subject).to be
43
45
  end
44
-
45
46
  end
46
47
 
47
48
  describe "#api_token=" do
48
-
49
- let(:api_token) { "new-api-token-value" }
49
+ let(:api_token) {"new-api-token-value"}
50
50
 
51
51
  it 'assigns the api token to the http client instance' do
52
52
  subject.api_token = api_token
53
- subject.http_client.api_token.should == api_token
53
+ expect(subject.http_client.api_token).to eq api_token
54
54
  end
55
55
 
56
56
  it 'is aliased as api_key=' do
57
57
  subject.api_key = api_token
58
- subject.http_client.api_token.should == api_token
58
+ expect(subject.http_client.api_token).to eq api_token
59
59
  end
60
-
61
60
  end
62
61
 
63
62
  describe "#deliver" do
64
- let(:email) { Postmark::MessageHelper.to_postmark(message_hash) }
65
- let(:email_json) { Postmark::Json.encode(email) }
66
- let(:http_client) { subject.http_client }
67
- let(:response) { {"MessageID" => 42} }
63
+ let(:email) {Postmark::MessageHelper.to_postmark(message_hash)}
64
+ let(:email_json) {Postmark::Json.encode(email)}
65
+ let(:response) {{"MessageID" => 42}}
68
66
 
69
67
  it 'converts message hash to Postmark format and posts it to /email' do
70
- http_client.should_receive(:post).with('email', email_json) { response }
68
+ allow(http_client).to receive(:post).with('email', email_json) {response}
71
69
  subject.deliver(message_hash)
72
70
  end
73
71
 
74
72
  it 'retries 3 times' do
75
- 2.times do
76
- http_client.should_receive(:post).and_raise(Postmark::InternalServerError)
77
- end
78
- http_client.should_receive(:post) { response }
79
- expect { subject.deliver(message_hash) }.not_to raise_error
73
+ expect(http_client).to receive(:post).twice.and_raise(Postmark::InternalServerError)
74
+ expect(http_client).to receive(:post) {response}
75
+ expect {subject.deliver(message_hash)}.not_to raise_error
80
76
  end
81
77
 
82
78
  it 'converts response to ruby format' do
83
- http_client.should_receive(:post).with('email', email_json) { response }
84
- r = subject.deliver(message_hash)
85
- r.should have_key(:message_id)
79
+ expect(http_client).to receive(:post).with('email', email_json) {response}
80
+ expect(subject.deliver(message_hash)).to have_key(:message_id)
86
81
  end
87
82
  end
88
83
 
89
84
  describe "#deliver_in_batches" do
90
- let(:email) { Postmark::MessageHelper.to_postmark(message_hash) }
91
- let(:emails) { [email, email, email] }
92
- let(:emails_json) { Postmark::Json.encode(emails) }
93
- let(:http_client) { subject.http_client }
94
- let(:response) { [{'ErrorCode' => 0}, {'ErrorCode' => 0}, {'ErrorCode' => 0}] }
85
+ let(:email) {Postmark::MessageHelper.to_postmark(message_hash)}
86
+ let(:emails) {[email, email, email]}
87
+ let(:emails_json) {Postmark::Json.encode(emails)}
88
+ let(:response) {[{'ErrorCode' => 0}, {'ErrorCode' => 0}, {'ErrorCode' => 0}]}
95
89
 
96
90
  it 'turns array of messages into a JSON document and posts it to /email/batch' do
97
- http_client.should_receive(:post).with('email/batch', emails_json) { response }
91
+ expect(http_client).to receive(:post).with('email/batch', emails_json) {response}
98
92
  subject.deliver_in_batches([message_hash, message_hash, message_hash])
99
93
  end
100
94
 
101
95
  it 'converts response to ruby format' do
102
- http_client.should_receive(:post).with('email/batch', emails_json) { response }
96
+ expect(http_client).to receive(:post).with('email/batch', emails_json) {response}
103
97
  response = subject.deliver_in_batches([message_hash, message_hash, message_hash])
104
- response.first.should have_key(:error_code)
98
+ expect(response.first).to have_key(:error_code)
105
99
  end
106
100
  end
107
101
 
108
102
  describe "#deliver_message" do
109
- let(:email) { message.to_postmark_hash }
110
- let(:email_json) { Postmark::Json.encode(email) }
111
- let(:http_client) { subject.http_client }
103
+ let(:email) {message.to_postmark_hash}
104
+ let(:email_json) {Postmark::Json.encode(email)}
105
+
106
+ it 'raises an error when given a templated message' do
107
+ expect { subject.deliver_message(templated_message) }.
108
+ to raise_error(ArgumentError, /Please use Postmark::ApiClient\#deliver_message_with_template/)
109
+ end
112
110
 
113
111
  it 'turns message into a JSON document and posts it to /email' do
114
- http_client.should_receive(:post).with('email', email_json)
112
+ expect(http_client).to receive(:post).with('email', email_json)
115
113
  subject.deliver_message(message)
116
114
  end
117
115
 
118
116
  it "retries 3 times" do
119
117
  2.times do
120
- http_client.should_receive(:post).and_raise(Postmark::InternalServerError)
118
+ expect(http_client).to receive(:post).and_raise(Postmark::InternalServerError)
121
119
  end
122
- http_client.should_receive(:post)
123
- expect { subject.deliver_message(message) }.not_to raise_error
120
+ expect(http_client).to receive(:post)
121
+ expect {subject.deliver_message(message)}.not_to raise_error
124
122
  end
125
123
 
126
124
  it "retries on timeout" do
127
- http_client.should_receive(:post).and_raise(Postmark::TimeoutError)
128
- http_client.should_receive(:post)
129
- expect { subject.deliver_message(message) }.not_to raise_error
125
+ expect(http_client).to receive(:post).and_raise(Postmark::TimeoutError)
126
+ expect(http_client).to receive(:post)
127
+ expect {subject.deliver_message(message)}.not_to raise_error
130
128
  end
131
129
 
132
130
  it "proxies errors" do
133
- http_client.stub(:post).and_raise(Postmark::TimeoutError)
134
- expect { subject.deliver_message(message) }.to raise_error(Postmark::TimeoutError)
131
+ allow(http_client).to receive(:post).and_raise(Postmark::TimeoutError)
132
+ expect {subject.deliver_message(message)}.to raise_error(Postmark::TimeoutError)
133
+ end
134
+ end
135
+
136
+ describe "#deliver_message_with_template" do
137
+ let(:email) {templated_message.to_postmark_hash}
138
+ let(:email_json) {Postmark::Json.encode(email)}
139
+
140
+ it 'raises an error when given a non-templated message' do
141
+ expect { subject.deliver_message_with_template(message) }.
142
+ to raise_error(ArgumentError, 'Templated delivery requested, but the template is missing.')
143
+ end
144
+
145
+ it 'turns message into a JSON document and posts it to /email' do
146
+ expect(http_client).to receive(:post).with('email/withTemplate', email_json)
147
+ subject.deliver_message_with_template(templated_message)
148
+ end
149
+
150
+ it "retries 3 times" do
151
+ 2.times do
152
+ expect(http_client).to receive(:post).and_raise(Postmark::InternalServerError)
153
+ end
154
+ expect(http_client).to receive(:post)
155
+ expect {subject.deliver_message_with_template(templated_message)}.not_to raise_error
135
156
  end
136
157
 
158
+ it "retries on timeout" do
159
+ expect(http_client).to receive(:post).and_raise(Postmark::TimeoutError)
160
+ expect(http_client).to receive(:post)
161
+ expect {subject.deliver_message_with_template(templated_message)}.not_to raise_error
162
+ end
163
+
164
+ it "proxies errors" do
165
+ allow(http_client).to receive(:post).and_raise(Postmark::TimeoutError)
166
+ expect {subject.deliver_message_with_template(templated_message)}.to raise_error(Postmark::TimeoutError)
167
+ end
137
168
  end
138
169
 
139
170
  describe "#deliver_messages" do
171
+ let(:email) {message.to_postmark_hash}
172
+ let(:emails) {[email, email, email]}
173
+ let(:emails_json) {Postmark::Json.encode(emails)}
174
+ let(:response) {[{}, {}, {}]}
140
175
 
141
- let(:email) { message.to_postmark_hash }
142
- let(:emails) { [email, email, email] }
143
- let(:emails_json) { Postmark::Json.encode(emails) }
144
- let(:http_client) { subject.http_client }
145
- let(:response) { [{}, {}, {}] }
176
+ it 'raises an error when given a templated message' do
177
+ expect { subject.deliver_messages([templated_message]) }.
178
+ to raise_error(ArgumentError, /Please use Postmark::ApiClient\#deliver_messages_with_templates/)
179
+ end
146
180
 
147
181
  it 'turns array of messages into a JSON document and posts it to /email/batch' do
148
- http_client.should_receive(:post).with('email/batch', emails_json) { response }
182
+ expect(http_client).to receive(:post).with('email/batch', emails_json) {response}
149
183
  subject.deliver_messages([message, message, message])
150
184
  end
151
185
 
152
- it "should retry 3 times" do
186
+ it "retry 3 times" do
153
187
  2.times do
154
- http_client.should_receive(:post).and_raise(Postmark::InternalServerError)
188
+ expect(http_client).to receive(:post).and_raise(Postmark::InternalServerError)
155
189
  end
156
- http_client.should_receive(:post) { response }
157
- expect { subject.deliver_messages([message, message, message]) }.not_to raise_error
190
+ expect(http_client).to receive(:post) {response}
191
+ expect {subject.deliver_messages([message, message, message])}.not_to raise_error
192
+ end
193
+
194
+ it "retry on timeout" do
195
+ expect(http_client).to receive(:post).and_raise(Postmark::TimeoutError)
196
+ expect(http_client).to receive(:post) {response}
197
+ expect {subject.deliver_messages([message, message, message])}.not_to raise_error
198
+ end
199
+ end
200
+
201
+ describe "#deliver_messages_with_templates" do
202
+ let(:email) {templated_message.to_postmark_hash}
203
+ let(:emails) {[email, email, email]}
204
+ let(:emails_json) {Postmark::Json.encode(emails)}
205
+ let(:response) {[{}, {}, {}]}
206
+ let(:messages) { Array.new(3) { templated_message } }
207
+
208
+ it 'raises an error when given a templated message' do
209
+ expect { subject.deliver_messages_with_templates([message]) }.
210
+ to raise_error(ArgumentError, 'Templated delivery requested, but one or more messages lack templates.')
211
+ end
212
+
213
+ it 'turns array of messages into a JSON document and posts it to /email/batch' do
214
+ expect(http_client).to receive(:post).with('email/batchWithTemplates', emails_json) {response}
215
+ subject.deliver_messages_with_templates(messages)
158
216
  end
159
217
 
160
- it "should retry on timeout" do
161
- http_client.should_receive(:post).and_raise(Postmark::TimeoutError)
162
- http_client.should_receive(:post) { response }
163
- expect { subject.deliver_messages([message, message, message]) }.not_to raise_error
218
+ it "retry 3 times" do
219
+ 2.times do
220
+ expect(http_client).to receive(:post).and_raise(Postmark::InternalServerError)
221
+ end
222
+ expect(http_client).to receive(:post) {response}
223
+ expect {subject.deliver_messages_with_templates(messages)}.not_to raise_error
164
224
  end
165
225
 
226
+ it "retry on timeout" do
227
+ expect(http_client).to receive(:post).and_raise(Postmark::TimeoutError)
228
+ expect(http_client).to receive(:post) {response}
229
+ expect {subject.deliver_messages_with_templates(messages)}.not_to raise_error
230
+ end
166
231
  end
167
232
 
168
233
  describe "#delivery_stats" do
169
- let(:http_client) { subject.http_client }
170
- let(:response) { {"Bounces" => [{"Foo" => "Bar"}]} }
234
+ let(:response) {{"Bounces" => [{"Foo" => "Bar"}]}}
171
235
 
172
236
  it 'requests data at /deliverystats' do
173
- http_client.should_receive(:get).with("deliverystats") { response }
174
- subject.delivery_stats.should have_key(:bounces)
237
+ expect(http_client).to receive(:get).with("deliverystats") {response}
238
+ expect(subject.delivery_stats).to have_key(:bounces)
175
239
  end
176
240
  end
177
241
 
178
242
  describe '#messages' do
179
-
180
243
  context 'given outbound' do
181
-
182
- let(:response) {
183
- {'TotalCount' => 5,
184
- 'Messages' => [{}].cycle(5).to_a}
185
- }
244
+ let(:response) {{'TotalCount' => 5, 'Messages' => [{}].cycle(5).to_a}}
186
245
 
187
246
  it 'returns an enumerator' do
188
247
  expect(subject.messages).to be_kind_of(Enumerable)
@@ -193,62 +252,46 @@ describe Postmark::ApiClient do
193
252
  with('messages/outbound', an_instance_of(Hash)).and_return(response)
194
253
  expect(subject.messages.count).to eq(5)
195
254
  end
196
-
197
255
  end
198
256
 
199
257
  context 'given inbound' do
200
-
201
- let(:response) {
202
- {'TotalCount' => 5,
203
- 'InboundMessages' => [{}].cycle(5).to_a}
204
- }
258
+ let(:response) {{'TotalCount' => 5, 'InboundMessages' => [{}].cycle(5).to_a}}
205
259
 
206
260
  it 'returns an enumerator' do
207
261
  expect(subject.messages(:inbound => true)).to be_kind_of(Enumerable)
208
262
  end
209
263
 
210
264
  it 'loads inbound messages' do
211
- allow(subject.http_client).to receive(:get).
212
- with('messages/inbound', an_instance_of(Hash)).and_return(response)
265
+ allow(subject.http_client).to receive(:get).with('messages/inbound', an_instance_of(Hash)).and_return(response)
213
266
  expect(subject.messages(:inbound => true).count).to eq(5)
214
267
  end
215
-
216
268
  end
217
-
218
269
  end
219
270
 
220
271
  describe '#get_messages' do
221
- let(:http_client) { subject.http_client }
222
-
223
272
  context 'given outbound' do
224
- let(:response) { {"TotalCount" => 1, "Messages" => [{}]} }
273
+ let(:response) {{"TotalCount" => 1, "Messages" => [{}]}}
225
274
 
226
275
  it 'requests data at /messages/outbound' do
227
- http_client.should_receive(:get).
228
- with('messages/outbound', :offset => 50, :count => 50).
229
- and_return(response)
276
+ expect(http_client).to receive(:get).
277
+ with('messages/outbound', :offset => 50, :count => 50).
278
+ and_return(response)
230
279
  subject.get_messages(:offset => 50, :count => 50)
231
280
  end
232
-
233
281
  end
234
282
 
235
283
  context 'given inbound' do
236
- let(:response) { {"TotalCount" => 1, "InboundMessages" => [{}]} }
284
+ let(:response) {{"TotalCount" => 1, "InboundMessages" => [{}]}}
237
285
 
238
286
  it 'requests data at /messages/inbound' do
239
- http_client.should_receive(:get).
240
- with('messages/inbound', :offset => 50, :count => 50).
241
- and_return(response)
242
- subject.get_messages(:inbound => true, :offset => 50, :count => 50).
243
- should be_an(Array)
287
+ expect(http_client).to receive(:get).with('messages/inbound', :offset => 50, :count => 50).and_return(response)
288
+ expect(subject.get_messages(:inbound => true, :offset => 50, :count => 50)).to be_an(Array)
244
289
  end
245
-
246
290
  end
247
291
  end
248
292
 
249
293
  describe '#get_messages_count' do
250
-
251
- let(:response) { {'TotalCount' => 42} }
294
+ let(:response) {{'TotalCount' => 42}}
252
295
 
253
296
  context 'given outbound' do
254
297
 
@@ -262,75 +305,64 @@ describe Postmark::ApiClient do
262
305
  end
263
306
 
264
307
  context 'given inbound' do
265
-
266
308
  it 'requests and returns inbound messages count' do
267
309
  allow(subject.http_client).to receive(:get).
268
310
  with('messages/inbound', an_instance_of(Hash)).and_return(response)
269
311
  expect(subject.get_messages_count(:inbound => true)).to eq(42)
270
312
  end
271
-
272
313
  end
273
314
 
274
315
  end
275
316
 
276
317
  describe '#get_message' do
277
- let(:id) { '8ad0e8b0-xxxx-xxxx-951d-223c581bb467' }
278
- let(:http_client) { subject.http_client }
279
- let(:response) { {"To" => "leonard@bigbangtheory.com"} }
318
+ let(:id) {'8ad0e8b0-xxxx-xxxx-951d-223c581bb467'}
319
+ let(:response) {{"To" => "leonard@bigbangtheory.com"}}
280
320
 
281
321
  context 'given outbound' do
282
-
283
322
  it 'requests a single message by id at /messages/outbound/:id/details' do
284
- http_client.should_receive(:get).
285
- with("messages/outbound/#{id}/details", {}).
286
- and_return(response)
287
- subject.get_message(id).should have_key(:to)
323
+ expect(http_client).to receive(:get).
324
+ with("messages/outbound/#{id}/details", {}).
325
+ and_return(response)
326
+ expect(subject.get_message(id)).to have_key(:to)
288
327
  end
289
-
290
328
  end
291
329
 
292
330
  context 'given inbound' do
293
-
294
331
  it 'requests a single message by id at /messages/inbound/:id/details' do
295
- http_client.should_receive(:get).
296
- with("messages/inbound/#{id}/details", {}).
297
- and_return(response)
298
- subject.get_message(id, :inbound => true).should have_key(:to)
332
+ expect(http_client).to receive(:get).
333
+ with("messages/inbound/#{id}/details", {}).
334
+ and_return(response)
335
+ expect(subject.get_message(id, :inbound => true)).to have_key(:to)
299
336
  end
300
-
301
337
  end
302
338
  end
303
339
 
304
340
  describe '#dump_message' do
305
- let(:id) { '8ad0e8b0-xxxx-xxxx-951d-223c581bb467' }
306
- let(:http_client) { subject.http_client }
307
- let(:response) { {"Body" => "From: <leonard@bigbangtheory.com> \r\n ..."} }
341
+ let(:id) {'8ad0e8b0-xxxx-xxxx-951d-223c581bb467'}
342
+ let(:response) {{"Body" => "From: <leonard@bigbangtheory.com> \r\n ..."}}
308
343
 
309
344
  context 'given outbound' do
310
345
 
311
346
  it 'requests a single message by id at /messages/outbound/:id/dump' do
312
- http_client.should_receive(:get).
313
- with("messages/outbound/#{id}/dump", {}).
314
- and_return(response)
315
- subject.dump_message(id).should have_key(:body)
347
+ expect(http_client).to receive(:get).
348
+ with("messages/outbound/#{id}/dump", {}).
349
+ and_return(response)
350
+ expect(subject.dump_message(id)).to have_key(:body)
316
351
  end
317
352
 
318
353
  end
319
354
 
320
355
  context 'given inbound' do
321
-
322
356
  it 'requests a single message by id at /messages/inbound/:id/dump' do
323
- http_client.should_receive(:get).
324
- with("messages/inbound/#{id}/dump", {}).
325
- and_return(response)
326
- subject.dump_message(id, :inbound => true).should have_key(:body)
357
+ expect(http_client).to receive(:get).
358
+ with("messages/inbound/#{id}/dump", {}).
359
+ and_return(response)
360
+ expect(subject.dump_message(id, :inbound => true)).to have_key(:body)
327
361
  end
328
-
329
362
  end
330
363
  end
331
364
 
332
365
  describe '#bounces' do
333
-
334
366
  it 'returns an Enumerator' do
335
367
  expect(subject.bounces).to be_kind_of(Enumerable)
336
368
  end
@@ -341,63 +373,48 @@ describe Postmark::ApiClient do
341
373
  and_return('TotalCount' => 1, 'Bounces' => [{}])
342
374
  expect(subject.bounces.first(5).count).to eq(1)
343
375
  end
344
-
345
376
  end
346
377
 
347
378
  describe "#get_bounces" do
348
- let(:http_client) { subject.http_client }
349
- let(:options) { {:foo => :bar} }
350
- let(:response) { {"Bounces" => []} }
379
+ let(:options) {{:foo => :bar}}
380
+ let(:response) {{"Bounces" => []}}
351
381
 
352
382
  it 'requests data at /bounces' do
353
- allow(http_client).to receive(:get).with("bounces", options) { response }
383
+ allow(http_client).to receive(:get).with("bounces", options) {response}
354
384
  expect(subject.get_bounces(options)).to be_an(Array)
355
385
  expect(subject.get_bounces(options).count).to be_zero
356
386
  end
357
387
  end
358
388
 
359
- describe "#get_bounced_tags" do
360
- let(:http_client) { subject.http_client }
361
-
362
- it 'requests data at /bounces/tags' do
363
- http_client.should_receive(:get).with("bounces/tags")
364
- subject.get_bounced_tags
365
- end
366
- end
367
-
368
389
  describe "#get_bounce" do
369
- let(:http_client) { subject.http_client }
370
- let(:id) { 42 }
390
+ let(:id) {42}
371
391
 
372
392
  it 'requests a single bounce by ID at /bounces/:id' do
373
- http_client.should_receive(:get).with("bounces/#{id}")
393
+ expect(http_client).to receive(:get).with("bounces/#{id}")
374
394
  subject.get_bounce(id)
375
395
  end
376
396
  end
377
397
 
378
398
  describe "#dump_bounce" do
379
- let(:http_client) { subject.http_client }
380
- let(:id) { 42 }
399
+ let(:id) {42}
381
400
 
382
401
  it 'requests a specific bounce data at /bounces/:id/dump' do
383
- http_client.should_receive(:get).with("bounces/#{id}/dump")
402
+ expect(http_client).to receive(:get).with("bounces/#{id}/dump")
384
403
  subject.dump_bounce(id)
385
404
  end
386
405
  end
387
406
 
388
407
  describe "#activate_bounce" do
389
- let(:http_client) { subject.http_client }
390
- let(:id) { 42 }
391
- let(:response) { {"Bounce" => {}} }
408
+ let(:id) {42}
409
+ let(:response) {{"Bounce" => {}}}
392
410
 
393
411
  it 'activates a specific bounce by sending a PUT request to /bounces/:id/activate' do
394
- http_client.should_receive(:put).with("bounces/#{id}/activate") { response }
412
+ expect(http_client).to receive(:put).with("bounces/#{id}/activate") {response}
395
413
  subject.activate_bounce(id)
396
414
  end
397
415
  end
398
416
 
399
417
  describe '#opens' do
400
-
401
418
  it 'returns an Enumerator' do
402
419
  expect(subject.opens).to be_kind_of(Enumerable)
403
420
  end
@@ -408,39 +425,69 @@ describe Postmark::ApiClient do
408
425
  and_return('TotalCount' => 1, 'Opens' => [{}])
409
426
  expect(subject.opens.first(5).count).to eq(1)
410
427
  end
428
+ end
411
429
 
430
+ describe '#clicks' do
431
+ it 'returns an Enumerator' do
432
+ expect(subject.clicks).to be_kind_of(Enumerable)
433
+ end
434
+
435
+ it 'performs a GET request to /clicks/tags' do
436
+ allow(subject.http_client).to receive(:get).
437
+ with('messages/outbound/clicks', an_instance_of(Hash)).
438
+ and_return('TotalCount' => 1, 'Clicks' => [{}])
439
+ expect(subject.clicks.first(5).count).to eq(1)
440
+ end
412
441
  end
413
442
 
414
443
  describe '#get_opens' do
415
- let(:http_client) { subject.http_client }
416
- let(:options) { {:offset => 5} }
417
- let(:response) { {'Opens' => [], 'TotalCount' => 0} }
444
+ let(:options) {{:offset => 5}}
445
+ let(:response) {{'Opens' => [], 'TotalCount' => 0}}
418
446
 
419
447
  it 'performs a GET request to /messages/outbound/opens' do
420
- allow(http_client).to receive(:get).with('messages/outbound/opens', options) { response }
448
+ allow(http_client).to receive(:get).with('messages/outbound/opens', options) {response}
421
449
  expect(subject.get_opens(options)).to be_an(Array)
422
450
  expect(subject.get_opens(options).count).to be_zero
423
451
  end
424
452
  end
425
453
 
454
+ describe '#get_clicks' do
455
+ let(:options) {{:offset => 5}}
456
+ let(:response) {{'Clicks' => [], 'TotalCount' => 0}}
457
+
458
+ it 'performs a GET request to /messages/outbound/clicks' do
459
+ allow(http_client).to receive(:get).with('messages/outbound/clicks', options) {response}
460
+ expect(subject.get_clicks(options)).to be_an(Array)
461
+ expect(subject.get_clicks(options).count).to be_zero
462
+ end
463
+ end
464
+
426
465
  describe '#get_opens_by_message_id' do
427
- let(:http_client) { subject.http_client }
428
- let(:message_id) { 42 }
429
- let(:options) { {:offset => 5} }
430
- let(:response) { {'Opens' => [], 'TotalCount' => 0} }
466
+ let(:message_id) {42}
467
+ let(:options) {{:offset => 5}}
468
+ let(:response) {{'Opens' => [], 'TotalCount' => 0}}
431
469
 
432
470
  it 'performs a GET request to /messages/outbound/opens' do
433
- allow(http_client).
434
- to receive(:get).with("messages/outbound/opens/#{message_id}",
435
- options).
436
- and_return(response)
471
+ allow(http_client).to receive(:get).with("messages/outbound/opens/#{message_id}", options).and_return(response)
437
472
  expect(subject.get_opens_by_message_id(message_id, options)).to be_an(Array)
438
473
  expect(subject.get_opens_by_message_id(message_id, options).count).to be_zero
439
474
  end
440
475
  end
441
476
 
477
+ describe '#get_clicks_by_message_id' do
478
+ let(:message_id) {42}
479
+ let(:options) {{:offset => 5}}
480
+ let(:response) {{'Clicks' => [], 'TotalCount' => 0}}
481
+
482
+ it 'performs a GET request to /messages/outbound/clicks' do
483
+ allow(http_client).to receive(:get).with("messages/outbound/clicks/#{message_id}", options).and_return(response)
484
+ expect(subject.get_clicks_by_message_id(message_id, options)).to be_an(Array)
485
+ expect(subject.get_clicks_by_message_id(message_id, options).count).to be_zero
486
+ end
487
+ end
488
+
442
489
  describe '#opens_by_message_id' do
443
- let(:message_id) { 42 }
490
+ let(:message_id) {42}
444
491
 
445
492
  it 'returns an Enumerator' do
446
493
  expect(subject.opens_by_message_id(message_id)).to be_kind_of(Enumerable)
@@ -454,26 +501,41 @@ describe Postmark::ApiClient do
454
501
  end
455
502
  end
456
503
 
457
- describe '#create_trigger' do
458
- let(:http_client) { subject.http_client }
459
- let(:options) { {:foo => 'bar'} }
460
- let(:response) { {'Foo' => 'Bar'} }
504
+ describe '#clicks_by_message_id' do
505
+ let(:message_id) {42}
506
+
507
+ it 'returns an Enumerator' do
508
+ expect(subject.clicks_by_message_id(message_id)).to be_kind_of(Enumerable)
509
+ end
461
510
 
462
- it 'performs a POST request to /triggers/tags with given options' do
463
- allow(http_client).to receive(:post).with('triggers/tags',
464
- {'Foo' => 'bar'}.to_json)
465
- subject.create_trigger(:tags, options)
511
+ it 'performs a GET request to /clicks/tags' do
512
+ allow(subject.http_client).to receive(:get).
513
+ with("messages/outbound/clicks/#{message_id}", an_instance_of(Hash)).
514
+ and_return('TotalCount' => 1, 'Clicks' => [{}])
515
+ expect(subject.clicks_by_message_id(message_id).first(5).count).to eq(1)
466
516
  end
517
+ end
467
518
 
468
- it 'symbolizes response keys' do
469
- allow(http_client).to receive(:post).and_return(response)
470
- expect(subject.create_trigger(:tags, options)).to eq(:foo => 'Bar')
519
+ describe '#create_trigger' do
520
+ context 'inbound rules' do
521
+ let(:options) {{:rule => 'example.com'}}
522
+ let(:response) {{'Rule' => 'example.com'}}
523
+
524
+ it 'performs a POST request to /triggers/inboundrules with given options' do
525
+ allow(http_client).to receive(:post).with('triggers/inboundrules',
526
+ {'Rule' => 'example.com'}.to_json)
527
+ subject.create_trigger(:inbound_rules, options)
528
+ end
529
+
530
+ it 'symbolizes response keys' do
531
+ allow(http_client).to receive(:post).and_return(response)
532
+ expect(subject.create_trigger(:inbound_rules, options)).to eq(:rule => 'example.com')
533
+ end
471
534
  end
472
535
  end
473
536
 
474
537
  describe '#get_trigger' do
475
- let(:http_client) { subject.http_client }
476
- let(:id) { 42 }
538
+ let(:id) {42}
477
539
 
478
540
  it 'performs a GET request to /triggers/tags/:id' do
479
541
  allow(http_client).to receive(:get).with("triggers/tags/#{id}")
@@ -486,52 +548,51 @@ describe Postmark::ApiClient do
486
548
  end
487
549
  end
488
550
 
489
- describe '#update_trigger' do
490
- let(:http_client) { subject.http_client }
491
- let(:options) { {:foo => 'bar'} }
492
- let(:id) { 42 }
551
+ describe '#delete_trigger' do
552
+ context 'tags' do
553
+ let(:id) {42}
493
554
 
494
- it 'performs a PUT request to /triggers/tags/:id' do
495
- allow(http_client).to receive(:put).with("triggers/tags/#{id}",
496
- {'Foo' => 'bar'}.to_json)
497
- subject.update_trigger(:tags, id, options)
498
- end
555
+ it 'performs a DELETE request to /triggers/tags/:id' do
556
+ allow(http_client).to receive(:delete).with("triggers/tags/#{id}")
557
+ subject.delete_trigger(:tags, id)
558
+ end
499
559
 
500
- it 'symbolizes response keys' do
501
- allow(http_client).to receive(:put).and_return('Foo' => 'Bar')
502
- expect(subject.update_trigger(:tags, id, options)).to eq(:foo => 'Bar')
560
+ it 'symbolizes response keys' do
561
+ allow(http_client).to receive(:delete).and_return('Foo' => 'Bar')
562
+ expect(subject.delete_trigger(:tags, id)).to eq(:foo => 'Bar')
563
+ end
503
564
  end
504
- end
505
565
 
506
- describe '#delete_trigger' do
507
- let(:http_client) { subject.http_client }
508
- let(:id) { 42 }
566
+ context 'inbound rules' do
567
+ let(:id) {42}
509
568
 
510
- it 'performs a DELETE request to /triggers/tags/:id' do
511
- allow(http_client).to receive(:delete).with("triggers/tags/#{id}")
512
- subject.delete_trigger(:tags, id)
513
- end
569
+ it 'performs a DELETE request to /triggers/inboundrules/:id' do
570
+ allow(http_client).to receive(:delete).with("triggers/inboundrules/#{id}")
571
+ subject.delete_trigger(:inbound_rules, id)
572
+ end
514
573
 
515
- it 'symbolizes response keys' do
516
- allow(http_client).to receive(:delete).and_return('Foo' => 'Bar')
517
- expect(subject.delete_trigger(:tags, id)).to eq(:foo => 'Bar')
574
+ it 'symbolizes response keys' do
575
+ allow(http_client).to receive(:delete).and_return('Rule' => 'example.com')
576
+ expect(subject.delete_trigger(:tags, id)).to eq(:rule => 'example.com')
577
+ end
518
578
  end
519
579
  end
520
580
 
521
581
  describe '#get_triggers' do
522
- let(:http_client) { subject.http_client }
523
- let(:options) { {:offset => 5} }
524
- let(:response) { {'Tags' => [], 'TotalCount' => 0} }
582
+ let(:options) {{:offset => 5}}
525
583
 
526
- it 'performs a GET request to /triggers/tags' do
527
- allow(http_client).to receive(:get).with('triggers/tags', options) { response }
528
- expect(subject.get_triggers(:tags, options)).to be_an(Array)
529
- expect(subject.get_triggers(:tags, options).count).to be_zero
584
+ context 'inbound rules' do
585
+ let(:response) {{'InboundRules' => [], 'TotalCount' => 0}}
586
+
587
+ it 'performs a GET request to /triggers/inboundrules' do
588
+ allow(http_client).to receive(:get).with('triggers/inboundrules', options) {response}
589
+ expect(subject.get_triggers(:inbound_rules, options)).to be_an(Array)
590
+ expect(subject.get_triggers(:inbound_rules, options).count).to be_zero
591
+ end
530
592
  end
531
593
  end
532
594
 
533
595
  describe '#triggers' do
534
-
535
596
  it 'returns an Enumerator' do
536
597
  expect(subject.triggers(:tags)).to be_kind_of(Enumerable)
537
598
  end
@@ -542,58 +603,54 @@ describe Postmark::ApiClient do
542
603
  and_return('TotalCount' => 1, 'Tags' => [{}])
543
604
  expect(subject.triggers(:tags).first(5).count).to eq(1)
544
605
  end
545
-
546
606
  end
547
607
 
548
608
  describe "#server_info" do
549
- let(:http_client) { subject.http_client }
550
- let(:response) { {"Name" => "Testing",
551
- "Color" => "blue",
552
- "InboundHash" => "c2425d77f74f8643e5f6237438086c81",
553
- "SmtpApiActivated" => true} }
609
+ let(:response) {{"Name" => "Testing",
610
+ "Color" => "blue",
611
+ "InboundHash" => "c2425d77f74f8643e5f6237438086c81",
612
+ "SmtpApiActivated" => true}}
554
613
 
555
614
  it 'requests server info from Postmark and converts it to ruby format' do
556
- http_client.should_receive(:get).with('server') { response }
557
- subject.server_info.should have_key(:inbound_hash)
615
+ expect(http_client).to receive(:get).with('server') {response}
616
+ expect(subject.server_info).to have_key(:inbound_hash)
558
617
  end
559
618
  end
560
619
 
561
620
  describe "#update_server_info" do
562
- let(:http_client) { subject.http_client }
563
- let(:response) { {"Name" => "Testing",
564
- "Color" => "blue",
565
- "InboundHash" => "c2425d77f74f8643e5f6237438086c81",
566
- "SmtpApiActivated" => false} }
567
- let(:update) { {:smtp_api_activated => false} }
621
+ let(:response) {{"Name" => "Testing",
622
+ "Color" => "blue",
623
+ "InboundHash" => "c2425d77f74f8643e5f6237438086c81",
624
+ "SmtpApiActivated" => false}}
625
+ let(:update) {{:smtp_api_activated => false}}
568
626
 
569
627
  it 'updates server info in Postmark and converts it to ruby format' do
570
- http_client.should_receive(:put).with('server', anything) { response }
571
- subject.update_server_info(update)[:smtp_api_activated].should be_false
628
+ expect(http_client).to receive(:put).with('server', anything) {response}
629
+ expect(subject.update_server_info(update)[:smtp_api_activated]).to be false
572
630
  end
573
631
  end
574
632
 
575
633
  describe '#get_templates' do
576
- let(:http_client) { subject.http_client }
577
634
  let(:response) do
578
635
  {
579
- 'TotalCount' => 31,
580
- 'Templates' => [
581
- {
582
- 'Active' => true,
583
- 'TemplateId' => 123,
584
- 'Name' => 'ABC'
585
- },
586
- {
587
- 'Active' => true,
588
- 'TemplateId' => 456,
589
- 'Name' => 'DEF'
590
- }
591
- ]
636
+ 'TotalCount' => 31,
637
+ 'Templates' => [
638
+ {
639
+ 'Active' => true,
640
+ 'TemplateId' => 123,
641
+ 'Name' => 'ABC'
642
+ },
643
+ {
644
+ 'Active' => true,
645
+ 'TemplateId' => 456,
646
+ 'Name' => 'DEF'
647
+ }
648
+ ]
592
649
  }
593
650
  end
594
651
 
595
652
  it 'gets templates info and converts it to ruby format' do
596
- http_client.should_receive(:get).with('templates', :offset => 0, :count => 2).and_return(response)
653
+ expect(http_client).to receive(:get).with('templates', :offset => 0, :count => 2).and_return(response)
597
654
 
598
655
  count, templates = subject.get_templates(:count => 2)
599
656
 
@@ -617,21 +674,20 @@ describe Postmark::ApiClient do
617
674
  end
618
675
 
619
676
  describe '#get_template' do
620
- let(:http_client) { subject.http_client }
621
677
  let(:response) do
622
678
  {
623
- 'Name' => 'Template Name',
624
- 'TemplateId' => 123,
625
- 'Subject' => 'Subject',
626
- 'HtmlBody' => 'Html',
627
- 'TextBody' => 'Text',
628
- 'AssociatedServerId' => 456,
629
- 'Active' => true
679
+ 'Name' => 'Template Name',
680
+ 'TemplateId' => 123,
681
+ 'Subject' => 'Subject',
682
+ 'HtmlBody' => 'Html',
683
+ 'TextBody' => 'Text',
684
+ 'AssociatedServerId' => 456,
685
+ 'Active' => true
630
686
  }
631
687
  end
632
688
 
633
689
  it 'gets single template and converts it to ruby format' do
634
- http_client.should_receive(:get).with('templates/123').and_return(response)
690
+ expect(http_client).to receive(:get).with('templates/123').and_return(response)
635
691
 
636
692
  template = subject.get_template('123')
637
693
 
@@ -642,19 +698,18 @@ describe Postmark::ApiClient do
642
698
  end
643
699
 
644
700
  describe '#create_template' do
645
- let(:http_client) { subject.http_client }
646
701
  let(:response) do
647
702
  {
648
- 'TemplateId' => 123,
649
- 'Name' => 'template name',
650
- 'Active' => true
703
+ 'TemplateId' => 123,
704
+ 'Name' => 'template name',
705
+ 'Active' => true
651
706
  }
652
707
  end
653
708
 
654
709
  it 'performs a POST request to /templates with the given attributes' do
655
- expected_json = { 'Name' => 'template name' }.to_json
656
-
657
- http_client.should_receive(:post).with('templates', expected_json).and_return(response)
710
+ expect(http_client).to receive(:post).
711
+ with('templates', json_representation_of('Name' => 'template name')).
712
+ and_return(response)
658
713
 
659
714
  template = subject.create_template(:name => 'template name')
660
715
 
@@ -664,19 +719,18 @@ describe Postmark::ApiClient do
664
719
  end
665
720
 
666
721
  describe '#update_template' do
667
- let(:http_client) { subject.http_client }
668
722
  let(:response) do
669
723
  {
670
- 'TemplateId' => 123,
671
- 'Name' => 'template name',
672
- 'Active' => true
724
+ 'TemplateId' => 123,
725
+ 'Name' => 'template name',
726
+ 'Active' => true
673
727
  }
674
728
  end
675
729
 
676
730
  it 'performs a PUT request to /templates with the given attributes' do
677
- expected_json = { 'Name' => 'template name' }.to_json
678
-
679
- http_client.should_receive(:put).with('templates/123', expected_json).and_return(response)
731
+ expect(http_client).to receive(:put).
732
+ with('templates/123', json_representation_of('Name' => 'template name')).
733
+ and_return(response)
680
734
 
681
735
  template = subject.update_template(123, :name => 'template name')
682
736
 
@@ -686,16 +740,15 @@ describe Postmark::ApiClient do
686
740
  end
687
741
 
688
742
  describe '#delete_template' do
689
- let(:http_client) { subject.http_client }
690
743
  let(:response) do
691
744
  {
692
- 'ErrorCode' => 0,
693
- 'Message' => 'Template 123 removed.'
745
+ 'ErrorCode' => 0,
746
+ 'Message' => 'Template 123 removed.'
694
747
  }
695
748
  end
696
749
 
697
750
  it 'performs a DELETE request to /templates/:id' do
698
- http_client.should_receive(:delete).with('templates/123').and_return(response)
751
+ expect(http_client).to receive(:delete).with('templates/123').and_return(response)
699
752
 
700
753
  resp = subject.delete_template(123)
701
754
 
@@ -704,48 +757,45 @@ describe Postmark::ApiClient do
704
757
  end
705
758
 
706
759
  describe '#validate_template' do
707
- let(:http_client) { subject.http_client }
708
-
709
760
  context 'when template is valid' do
710
761
  let(:response) do
711
762
  {
712
- 'AllContentIsValid' => true,
713
- 'HtmlBody' => {
714
- 'ContentIsValid' => true,
715
- 'ValidationErrors' => [],
716
- 'RenderedContent' => '<html><head></head><body>MyName_Value</body></html>'
717
- },
718
- 'TextBody' => {
719
- 'ContentIsValid' => true,
720
- 'ValidationErrors' => [],
721
- 'RenderedContent' => 'MyName_Value'
722
- },
723
- 'Subject' => {
724
- 'ContentIsValid' => true,
725
- 'ValidationErrors' => [],
726
- 'RenderedContent' => 'MyName_Value'
727
- },
728
- 'SuggestedTemplateModel' => {
729
- 'MyName' => 'MyName_Value'
730
- }
763
+ 'AllContentIsValid' => true,
764
+ 'HtmlBody' => {
765
+ 'ContentIsValid' => true,
766
+ 'ValidationErrors' => [],
767
+ 'RenderedContent' => '<html><head></head><body>MyName_Value</body></html>'
768
+ },
769
+ 'TextBody' => {
770
+ 'ContentIsValid' => true,
771
+ 'ValidationErrors' => [],
772
+ 'RenderedContent' => 'MyName_Value'
773
+ },
774
+ 'Subject' => {
775
+ 'ContentIsValid' => true,
776
+ 'ValidationErrors' => [],
777
+ 'RenderedContent' => 'MyName_Value'
778
+ },
779
+ 'SuggestedTemplateModel' => {
780
+ 'MyName' => 'MyName_Value'
781
+ }
731
782
  }
732
783
  end
733
784
 
734
785
  it 'performs a POST request and returns unmodified suggested template model' do
735
- expected_template_json = {
736
- 'HtmlBody' => '{{MyName}}',
737
- 'TextBody' => '{{MyName}}',
738
- 'Subject' => '{{MyName}}'
739
- }.to_json
740
-
741
- http_client.should_receive(:post).with('templates/validate', expected_template_json).and_return(response)
786
+ expect(http_client).to receive(:post).
787
+ with('templates/validate',
788
+ json_representation_of('HtmlBody' => '{{MyName}}',
789
+ 'TextBody' => '{{MyName}}',
790
+ 'Subject' => '{{MyName}}')).
791
+ and_return(response)
742
792
 
743
793
  resp = subject.validate_template(:html_body => '{{MyName}}',
744
794
  :text_body => '{{MyName}}',
745
795
  :subject => '{{MyName}}')
746
796
 
747
- expect(resp[:all_content_is_valid]).to be_true
748
- expect(resp[:html_body][:content_is_valid]).to be_true
797
+ expect(resp[:all_content_is_valid]).to be true
798
+ expect(resp[:html_body][:content_is_valid]).to be true
749
799
  expect(resp[:html_body][:validation_errors]).to be_empty
750
800
  expect(resp[:suggested_template_model]['MyName']).to eq('MyName_Value')
751
801
  end
@@ -754,48 +804,46 @@ describe Postmark::ApiClient do
754
804
  context 'when template is invalid' do
755
805
  let(:response) do
756
806
  {
757
- 'AllContentIsValid' => false,
758
- 'HtmlBody' => {
759
- 'ContentIsValid' => false,
760
- 'ValidationErrors' => [
761
- {
762
- 'Message' => 'The \'each\' block being opened requires a model path to be specified in the form \'{#each <name>}\'.',
763
- 'Line' => 1,
764
- 'CharacterPosition' => 1
765
- }
766
- ],
767
- 'RenderedContent' => nil
768
- },
769
- 'TextBody' => {
770
- 'ContentIsValid' => true,
771
- 'ValidationErrors' => [],
772
- 'RenderedContent' => 'MyName_Value'
773
- },
774
- 'Subject' => {
775
- 'ContentIsValid' => true,
776
- 'ValidationErrors' => [],
777
- 'RenderedContent' => 'MyName_Value'
778
- },
779
- 'SuggestedTemplateModel' => nil
807
+ 'AllContentIsValid' => false,
808
+ 'HtmlBody' => {
809
+ 'ContentIsValid' => false,
810
+ 'ValidationErrors' => [
811
+ {
812
+ 'Message' => 'The \'each\' block being opened requires a model path to be specified in the form \'{#each <name>}\'.',
813
+ 'Line' => 1,
814
+ 'CharacterPosition' => 1
815
+ }
816
+ ],
817
+ 'RenderedContent' => nil
818
+ },
819
+ 'TextBody' => {
820
+ 'ContentIsValid' => true,
821
+ 'ValidationErrors' => [],
822
+ 'RenderedContent' => 'MyName_Value'
823
+ },
824
+ 'Subject' => {
825
+ 'ContentIsValid' => true,
826
+ 'ValidationErrors' => [],
827
+ 'RenderedContent' => 'MyName_Value'
828
+ },
829
+ 'SuggestedTemplateModel' => nil
780
830
  }
781
831
  end
782
832
 
783
833
  it 'performs a POST request and returns validation errors' do
784
- expected_template_json = {
785
- 'HtmlBody' => '{{#each}}',
786
- 'TextBody' => '{{MyName}}',
787
- 'Subject' => '{{MyName}}'
788
- }.to_json
789
-
790
- http_client.should_receive(:post).with('templates/validate', expected_template_json).and_return(response)
834
+ expect(http_client).
835
+ to receive(:post).with('templates/validate',
836
+ json_representation_of('HtmlBody' => '{{#each}}',
837
+ 'TextBody' => '{{MyName}}',
838
+ 'Subject' => '{{MyName}}')).and_return(response)
791
839
 
792
840
  resp = subject.validate_template(:html_body => '{{#each}}',
793
841
  :text_body => '{{MyName}}',
794
842
  :subject => '{{MyName}}')
795
843
 
796
- expect(resp[:all_content_is_valid]).to be_false
797
- expect(resp[:text_body][:content_is_valid]).to be_true
798
- expect(resp[:html_body][:content_is_valid]).to be_false
844
+ expect(resp[:all_content_is_valid]).to be false
845
+ expect(resp[:text_body][:content_is_valid]).to be true
846
+ expect(resp[:html_body][:content_is_valid]).to be false
799
847
  expect(resp[:html_body][:validation_errors].first[:character_position]).to eq(1)
800
848
  expect(resp[:html_body][:validation_errors].first[:message]).to eq('The \'each\' block being opened requires a model path to be specified in the form \'{#each <name>}\'.')
801
849
  end
@@ -803,108 +851,446 @@ describe Postmark::ApiClient do
803
851
  end
804
852
 
805
853
  describe "#deliver_with_template" do
806
- let(:email) { Postmark::MessageHelper.to_postmark(message_hash) }
807
- let(:email_json) { Postmark::Json.encode(email) }
808
- let(:http_client) { subject.http_client }
809
- let(:response) { {"MessageID" => 42} }
854
+ let(:email) {Postmark::MessageHelper.to_postmark(message_hash)}
855
+ let(:response) {{"MessageID" => 42}}
810
856
 
811
857
  it 'converts message hash to Postmark format and posts it to /email/withTemplate' do
812
- http_client.should_receive(:post).with('email/withTemplate', email_json) { response }
858
+ expect(http_client).to receive(:post).with('email/withTemplate', json_representation_of(email)) {response}
813
859
  subject.deliver_with_template(message_hash)
814
860
  end
815
861
 
816
862
  it 'retries 3 times' do
817
863
  2.times do
818
- http_client.should_receive(:post).and_raise(Postmark::InternalServerError)
864
+ expect(http_client).to receive(:post).and_raise(Postmark::InternalServerError, 500)
819
865
  end
820
- http_client.should_receive(:post) { response }
821
- expect { subject.deliver_with_template(message_hash) }.not_to raise_error
866
+ expect(http_client).to receive(:post) {response}
867
+ expect {subject.deliver_with_template(message_hash)}.not_to raise_error
822
868
  end
823
869
 
824
870
  it 'converts response to ruby format' do
825
- http_client.should_receive(:post).with('email/withTemplate', email_json) { response }
826
- r = subject.deliver_with_template(message_hash)
827
- r.should have_key(:message_id)
871
+ expect(http_client).to receive(:post).with('email/withTemplate', json_representation_of(email)) {response}
872
+ expect(subject.deliver_with_template(message_hash)).to have_key(:message_id)
873
+ end
874
+ end
875
+
876
+ describe '#deliver_in_batches_with_templates' do
877
+ let(:max_batch_size) {50}
878
+ let(:factor) {3.5}
879
+ let(:postmark_response) do
880
+ {
881
+ 'ErrorCode' => 0,
882
+ 'Message' => 'OK',
883
+ 'SubmittedAt' => '2018-03-14T09:56:50.4288265-04:00',
884
+ 'To' => 'recipient@example.org'
885
+ }
886
+ end
887
+
888
+ let(:message_hashes) do
889
+ Array.new((factor * max_batch_size).to_i) do
890
+ {
891
+ :template_id => 42,
892
+ :alias => 'alias',
893
+ :template_model => {:Foo => 'attr_value'},
894
+ :from => 'sender@example.org',
895
+ :to => 'recipient@example.org'
896
+ }
897
+ end
898
+ end
899
+
900
+ before {subject.max_batch_size = max_batch_size}
901
+
902
+ it 'performs a total of (bath_size / max_batch_size) requests' do
903
+ expect(http_client).
904
+ to receive(:post).with('email/batchWithTemplates', a_postmark_json).
905
+ at_most(factor.to_i).times do
906
+ Array.new(max_batch_size) {postmark_response}
907
+ end
908
+
909
+ expect(http_client).
910
+ to receive(:post).with('email/batchWithTemplates', a_postmark_json).
911
+ exactly((factor - factor.to_i).ceil).times do
912
+ response = Array.new(((factor - factor.to_i) * max_batch_size).to_i) do
913
+ postmark_response
914
+ end
915
+ response
916
+ end
917
+
918
+ response = subject.deliver_in_batches_with_templates(message_hashes)
919
+ expect(response).to be_an Array
920
+ expect(response.size).to eq message_hashes.size
921
+
922
+ response.each do |message_status|
923
+ expect(message_status).to have_key(:error_code)
924
+ expect(message_status).to have_key(:message)
925
+ expect(message_status).to have_key(:to)
926
+ expect(message_status).to have_key(:submitted_at)
927
+ end
828
928
  end
829
929
  end
830
930
 
831
931
  describe '#get_stats_totals' do
832
932
  let(:response) do
833
933
  {
834
- "Sent" => 615,
835
- "BounceRate" => 10.406,
934
+ "Sent" => 615,
935
+ "BounceRate" => 10.406,
836
936
  }
837
937
  end
838
- let(:http_client) { subject.http_client }
839
938
 
840
939
  it 'converts response to ruby format' do
841
- http_client.should_receive(:get).with('stats/outbound', { :tag => 'foo' }) { response }
842
- r = subject.get_stats_totals(:tag => 'foo')
843
- r.should have_key(:sent)
844
- r.should have_key(:bounce_rate)
940
+ expect(http_client).to receive(:get).with('stats/outbound', {:tag => 'foo'}) {response}
941
+ response = subject.get_stats_totals(:tag => 'foo')
942
+ expect(response).to have_key(:sent)
943
+ expect(response).to have_key(:bounce_rate)
845
944
  end
846
945
  end
847
946
 
848
947
  describe '#get_stats_counts' do
849
948
  let(:response) do
850
949
  {
851
- "Days" => [
852
- {
853
- "Date" => "2014-01-01",
854
- "Sent" => 140
855
- },
856
- {
857
- "Date" => "2014-01-02",
858
- "Sent" => 160
859
- },
860
- {
861
- "Date" => "2014-01-04",
862
- "Sent" => 50
863
- },
864
- {
865
- "Date" => "2014-01-05",
866
- "Sent" => 115
867
- }
868
- ],
869
- "Sent" => 615
950
+ "Days" => [
951
+ {
952
+ "Date" => "2014-01-01",
953
+ "Sent" => 140
954
+ },
955
+ {
956
+ "Date" => "2014-01-02",
957
+ "Sent" => 160
958
+ },
959
+ {
960
+ "Date" => "2014-01-04",
961
+ "Sent" => 50
962
+ },
963
+ {
964
+ "Date" => "2014-01-05",
965
+ "Sent" => 115
966
+ }
967
+ ],
968
+ "Sent" => 615
870
969
  }
871
970
  end
872
- let(:http_client) { subject.http_client }
873
971
 
874
972
  it 'converts response to ruby format' do
875
- http_client.should_receive(:get).with('stats/outbound/sends', { :tag => 'foo' }) { response }
876
- r = subject.get_stats_counts(:sends, :tag => 'foo')
877
- r.should have_key(:days)
878
- r.should have_key(:sent)
973
+ expect(http_client).to receive(:get).with('stats/outbound/sends', {:tag => 'foo'}) {response}
974
+ response = subject.get_stats_counts(:sends, :tag => 'foo')
975
+ expect(response).to have_key(:days)
976
+ expect(response).to have_key(:sent)
879
977
 
880
- first_day = r[:days].first
881
-
882
- first_day.should have_key(:date)
883
- first_day.should have_key(:sent)
978
+ first_day = response[:days].first
979
+ expect(first_day).to have_key(:date)
980
+ expect(first_day).to have_key(:sent)
884
981
  end
885
982
 
886
983
  it 'uses fromdate that is passed in' do
887
- http_client.should_receive(:get).with('stats/outbound/sends', { :tag => 'foo', :fromdate => '2015-01-01' }) { response }
888
- r = subject.get_stats_counts(:sends, :tag => 'foo', :fromdate => '2015-01-01')
889
- r.should have_key(:days)
890
- r.should have_key(:sent)
891
-
892
- first_day = r[:days].first
984
+ expect(http_client).to receive(:get).with('stats/outbound/sends', {:tag => 'foo', :fromdate => '2015-01-01'}) {response}
985
+ response = subject.get_stats_counts(:sends, :tag => 'foo', :fromdate => '2015-01-01')
986
+ expect(response).to have_key(:days)
987
+ expect(response).to have_key(:sent)
893
988
 
894
- first_day.should have_key(:date)
895
- first_day.should have_key(:sent)
989
+ first_day = response[:days].first
990
+ expect(first_day).to have_key(:date)
991
+ expect(first_day).to have_key(:sent)
896
992
  end
897
993
 
898
994
  it 'uses stats type that is passed in' do
899
- http_client.should_receive(:get).with('stats/outbound/opens/readtimes', { :tag => 'foo', :type => :readtimes }) { response }
900
- r = subject.get_stats_counts(:opens, :type => :readtimes, :tag => 'foo')
901
- r.should have_key(:days)
902
- r.should have_key(:sent)
995
+ expect(http_client).to receive(:get).with('stats/outbound/opens/readtimes', {:tag => 'foo', :type => :readtimes}) {response}
996
+ response = subject.get_stats_counts(:opens, :type => :readtimes, :tag => 'foo')
997
+ expect(response).to have_key(:days)
998
+ expect(response).to have_key(:sent)
999
+
1000
+ first_day = response[:days].first
1001
+ expect(first_day).to have_key(:date)
1002
+ expect(first_day).to have_key(:sent)
1003
+ end
1004
+ end
1005
+
1006
+ describe '#get_message_streams' do
1007
+ subject(:result) { api_client.get_message_streams(:offset => 22, :count => 33) }
1008
+
1009
+ before do
1010
+ allow(http_client).to receive(:get).
1011
+ with('message-streams', :offset => 22, :count => 33).
1012
+ and_return({ 'TotalCount' => 1, 'MessageStreams' => [{'Name' => 'abc'}]})
1013
+ end
1014
+
1015
+ it { is_expected.to be_an(Array) }
1016
+
1017
+ describe 'returned item' do
1018
+ subject { result.first }
1019
+
1020
+ it { is_expected.to match(:name => 'abc') }
1021
+ end
1022
+ end
1023
+
1024
+ describe '#message_streams' do
1025
+ subject { api_client.message_streams }
1026
+
1027
+ it { is_expected.to be_kind_of(Enumerable) }
1028
+
1029
+ it 'requests data at /message-streams' do
1030
+ allow(http_client).to receive(:get).
1031
+ with('message-streams', anything).
1032
+ and_return('TotalCount' => 1, 'MessageStreams' => [{}])
1033
+ expect(subject.first(5).count).to eq(1)
1034
+ end
1035
+ end
1036
+
1037
+ describe '#get_message_stream' do
1038
+ subject(:result) { api_client.get_message_stream(123) }
1039
+
1040
+ before do
1041
+ allow(http_client).to receive(:get).
1042
+ with('message-streams/123').
1043
+ and_return({
1044
+ 'Id' => 'xxx',
1045
+ 'Name' => 'My Stream',
1046
+ 'ServerID' => 321,
1047
+ 'MessageStreamType' => 'Transactional'
1048
+ })
1049
+ end
1050
+
1051
+ it {
1052
+ is_expected.to match(
1053
+ :id => 'xxx',
1054
+ :name => 'My Stream',
1055
+ :server_id => 321,
1056
+ :message_stream_type => 'Transactional'
1057
+ )
1058
+ }
1059
+ end
1060
+
1061
+ describe '#create_message_stream' do
1062
+ subject { api_client.create_message_stream(attrs) }
1063
+
1064
+ let(:attrs) do
1065
+ {
1066
+ :name => 'My Stream',
1067
+ :id => 'my-stream',
1068
+ :message_stream_type => 'Broadcasts'
1069
+ }
1070
+ end
1071
+
1072
+ let(:response) do
1073
+ {
1074
+ 'Name' => 'My Stream',
1075
+ 'Id' => 'my-stream',
1076
+ 'MessageStreamType' => 'Broadcasts',
1077
+ 'ServerId' => 222,
1078
+ 'CreatedAt' => '2020-04-01T03:33:33.333-03:00'
1079
+ }
1080
+ end
1081
+
1082
+ before do
1083
+ allow(http_client).to receive(:post) { response }
1084
+ end
1085
+
1086
+ specify do
1087
+ expect(http_client).to receive(:post).
1088
+ with('message-streams',
1089
+ json_representation_of({
1090
+ 'Name' => 'My Stream',
1091
+ 'Id' => 'my-stream',
1092
+ 'MessageStreamType' => 'Broadcasts'
1093
+ }))
1094
+ subject
1095
+ end
1096
+
1097
+ it {
1098
+ is_expected.to match(
1099
+ :id => 'my-stream',
1100
+ :name => 'My Stream',
1101
+ :server_id => 222,
1102
+ :message_stream_type => 'Broadcasts',
1103
+ :created_at => '2020-04-01T03:33:33.333-03:00'
1104
+ )
1105
+ }
1106
+ end
1107
+
1108
+ describe '#update_message_stream' do
1109
+ subject { api_client.update_message_stream('xxx', attrs) }
1110
+
1111
+ let(:attrs) do
1112
+ {
1113
+ :name => 'My Stream XXX'
1114
+ }
1115
+ end
1116
+
1117
+ let(:response) do
1118
+ {
1119
+ 'Name' => 'My Stream XXX',
1120
+ 'Id' => 'xxx',
1121
+ 'MessageStreamType' => 'Broadcasts',
1122
+ 'ServerId' => 222,
1123
+ 'CreatedAt' => '2020-04-01T03:33:33.333-03:00'
1124
+ }
1125
+ end
1126
+
1127
+ before do
1128
+ allow(http_client).to receive(:patch) { response }
1129
+ end
1130
+
1131
+ specify do
1132
+ expect(http_client).to receive(:patch).
1133
+ with('message-streams/xxx',
1134
+ match_json({
1135
+ :Name => 'My Stream XXX',
1136
+ }))
1137
+ subject
1138
+ end
1139
+
1140
+ it {
1141
+ is_expected.to match(
1142
+ :id => 'xxx',
1143
+ :name => 'My Stream XXX',
1144
+ :server_id => 222,
1145
+ :message_stream_type => 'Broadcasts',
1146
+ :created_at => '2020-04-01T03:33:33.333-03:00'
1147
+ )
1148
+ }
1149
+ end
1150
+
1151
+ describe '#create_suppressions' do
1152
+ let(:email_addresses) { nil }
1153
+ let(:message_stream_id) { 'outbound' }
1154
+
1155
+ subject { api_client.create_suppressions(message_stream_id, email_addresses) }
1156
+
1157
+ context '1 email address as string' do
1158
+ let(:email_addresses) { 'A@example.com' }
1159
+
1160
+ specify do
1161
+ expect(http_client).to receive(:post).
1162
+ with('message-streams/outbound/suppressions',
1163
+ match_json({
1164
+ :Suppressions => [
1165
+ { :EmailAddress => 'A@example.com' }
1166
+ ]}))
1167
+ subject
1168
+ end
1169
+ end
1170
+
1171
+ context '1 email address as string & non-default stream' do
1172
+ let(:email_addresses) { 'A@example.com' }
1173
+ let(:message_stream_id) { 'xxxx' }
1174
+
1175
+ specify do
1176
+ expect(http_client).to receive(:post).
1177
+ with('message-streams/xxxx/suppressions',
1178
+ match_json({
1179
+ :Suppressions => [
1180
+ { :EmailAddress => 'A@example.com' }
1181
+ ]}))
1182
+ subject
1183
+ end
1184
+ end
903
1185
 
904
- first_day = r[:days].first
1186
+ context '1 email address as array of strings' do
1187
+ let(:email_addresses) { ['A@example.com'] }
1188
+
1189
+ specify do
1190
+ expect(http_client).to receive(:post).
1191
+ with('message-streams/outbound/suppressions',
1192
+ match_json({
1193
+ :Suppressions => [
1194
+ { :EmailAddress => 'A@example.com' }
1195
+ ]}))
1196
+ subject
1197
+ end
1198
+ end
1199
+
1200
+ context 'many email addresses as array of strings' do
1201
+ let(:email_addresses) { ['A@example.com', 'B@example.com'] }
1202
+
1203
+ specify do
1204
+ expect(http_client).to receive(:post).
1205
+ with('message-streams/outbound/suppressions',
1206
+ match_json({
1207
+ :Suppressions => [
1208
+ { :EmailAddress => 'A@example.com' },
1209
+ { :EmailAddress => 'B@example.com' }
1210
+ ]}))
1211
+ subject
1212
+ end
1213
+ end
1214
+ end
1215
+
1216
+ describe '#delete_suppressions' do
1217
+ let(:email_addresses) { nil }
1218
+ let(:message_stream_id) { 'outbound' }
1219
+
1220
+ subject { api_client.delete_suppressions(message_stream_id, email_addresses) }
1221
+
1222
+ context '1 email address as string' do
1223
+ let(:email_addresses) { 'A@example.com' }
1224
+
1225
+ specify do
1226
+ expect(http_client).to receive(:post).
1227
+ with('message-streams/outbound/suppressions/delete',
1228
+ match_json({
1229
+ :Suppressions => [
1230
+ { :EmailAddress => 'A@example.com' },
1231
+ ]}))
1232
+ subject
1233
+ end
1234
+ end
1235
+
1236
+ context '1 email address as string & non-default stream' do
1237
+ let(:email_addresses) { 'A@example.com' }
1238
+ let(:message_stream_id) { 'xxxx' }
1239
+
1240
+ specify do
1241
+ expect(http_client).to receive(:post).
1242
+ with('message-streams/xxxx/suppressions/delete',
1243
+ match_json({
1244
+ :Suppressions => [
1245
+ { :EmailAddress => 'A@example.com' }
1246
+ ]}))
1247
+ subject
1248
+ end
1249
+ end
1250
+
1251
+ context '1 email address as array of strings' do
1252
+ let(:email_addresses) { ['A@example.com'] }
1253
+
1254
+ specify do
1255
+ expect(http_client).to receive(:post).
1256
+ with('message-streams/outbound/suppressions/delete',
1257
+ match_json({
1258
+ :Suppressions => [
1259
+ { :EmailAddress => 'A@example.com' }
1260
+ ]}))
1261
+ subject
1262
+ end
1263
+ end
1264
+
1265
+ context 'many email addresses as array of strings' do
1266
+ let(:email_addresses) { ['A@example.com', 'B@example.com'] }
1267
+
1268
+ specify do
1269
+ expect(http_client).to receive(:post).
1270
+ with('message-streams/outbound/suppressions/delete',
1271
+ match_json({
1272
+ :Suppressions => [
1273
+ { :EmailAddress => 'A@example.com' },
1274
+ { :EmailAddress => 'B@example.com' }
1275
+ ]}))
1276
+ subject
1277
+ end
1278
+ end
1279
+ end
1280
+
1281
+ describe '#dump_suppressions' do
1282
+ let(:message_stream_id) { 'xxxx' }
1283
+
1284
+ subject { api_client.dump_suppressions(message_stream_id, :count => 123) }
1285
+
1286
+ before do
1287
+ allow(http_client).to receive(:get).and_return({'TotalCount' => 0, 'Suppressions' => []})
1288
+ end
905
1289
 
906
- first_day.should have_key(:date)
907
- first_day.should have_key(:sent)
1290
+ specify do
1291
+ expect(http_client).to receive(:get).
1292
+ with('message-streams/xxxx/suppressions/dump', { :count => 123, :offset => 0 })
1293
+ subject
908
1294
  end
909
1295
  end
910
1296
  end