postmark 1.8.1 → 1.21.3

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