postmark 1.10.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -43,11 +43,11 @@ describe Postmark::Bounce do
43
43
  end
44
44
 
45
45
  it 'allows to activate the bounce' do
46
- subject.can_activate?.should be_true
46
+ subject.can_activate?.should be true
47
47
  end
48
48
 
49
49
  it 'has an available dump' do
50
- subject.dump_available?.should be_true
50
+ subject.dump_available?.should be true
51
51
  end
52
52
 
53
53
  its(:type) { should eq bounce_data[:type] }
@@ -69,11 +69,11 @@ describe Postmark::Bounce do
69
69
  end
70
70
 
71
71
  it 'allows to activate the bounce' do
72
- subject.can_activate?.should be_true
72
+ subject.can_activate?.should be true
73
73
  end
74
74
 
75
75
  it 'has an available dump' do
76
- subject.dump_available?.should be_true
76
+ subject.dump_available?.should be true
77
77
  end
78
78
 
79
79
  its(:type) { should eq bounce_data[:type] }
@@ -93,7 +93,7 @@ describe Postmark::Bounce do
93
93
  let(:api_client) { Postmark.api_client }
94
94
 
95
95
  it "calls #dump_bounce on shared api_client instance" do
96
- Postmark.api_client.should_receive(:dump_bounce).with(bounce.id) { response }
96
+ expect(Postmark.api_client).to receive(:dump_bounce).with(bounce.id) { response }
97
97
  bounce.dump.should == bounce_body
98
98
  end
99
99
 
@@ -104,7 +104,7 @@ describe Postmark::Bounce do
104
104
  let(:api_client) { Postmark.api_client }
105
105
 
106
106
  it "calls #activate_bounce on shared api_client instance" do
107
- api_client.should_receive(:activate_bounce).with(bounce.id) { bounce_data }
107
+ expect(api_client).to receive(:activate_bounce).with(bounce.id) { bounce_data }
108
108
  bounce.activate.should be_a Postmark::Bounce
109
109
  end
110
110
 
@@ -114,7 +114,7 @@ describe Postmark::Bounce do
114
114
  let(:api_client) { Postmark.api_client }
115
115
 
116
116
  it "calls #get_bounce on shared api_client instance" do
117
- api_client.should_receive(:get_bounce).with(42) { bounce_data }
117
+ expect(api_client).to receive(:get_bounce).with(42) { bounce_data }
118
118
  Postmark::Bounce.find(42).should be_a Postmark::Bounce
119
119
  end
120
120
  end
@@ -125,8 +125,8 @@ describe Postmark::Bounce do
125
125
  let(:api_client) { Postmark.api_client }
126
126
 
127
127
  it "calls #get_bounces on shared api_client instance" do
128
- api_client.should_receive(:get_bounces) { response }
129
- Postmark::Bounce.all.should have(3).bounces
128
+ expect(api_client).to receive(:get_bounces) { response }
129
+ Postmark::Bounce.all.count.should eq(3)
130
130
  end
131
131
 
132
132
  end
@@ -137,7 +137,7 @@ describe Postmark::Bounce do
137
137
  let(:tags) { ["tag1", "tag2"] }
138
138
 
139
139
  it "calls #get_bounced_tags on shared api_client instance" do
140
- api_client.should_receive(:get_bounced_tags) { tags }
140
+ expect(api_client).to receive(:get_bounced_tags) { tags }
141
141
  Postmark::Bounce.tags.should == tags
142
142
  end
143
143
  end
@@ -0,0 +1,218 @@
1
+ require 'spec_helper'
2
+
3
+ describe(Postmark::Error) do
4
+ it { is_expected.to be_a(StandardError) }
5
+ end
6
+
7
+ describe(Postmark::HttpClientError) do
8
+ it { is_expected.to be_a(Postmark::Error) }
9
+ specify { expect(subject.retry?).to be true }
10
+ end
11
+
12
+ describe(Postmark::HttpServerError) do
13
+ it { is_expected.to be_a(Postmark::Error) }
14
+
15
+ describe '.build' do
16
+ context 'picks an appropriate subclass for code' do
17
+ subject { Postmark::HttpServerError.build(code, Postmark::Json.encode({})) }
18
+
19
+ context '401' do
20
+ let(:code) { '401' }
21
+
22
+ it { is_expected.to be_a(Postmark::InvalidApiKeyError) }
23
+ its(:status_code) { is_expected.to eq 401 }
24
+ end
25
+
26
+ context '422' do
27
+ let(:code) { '422' }
28
+
29
+ it { is_expected.to be_a(Postmark::ApiInputError) }
30
+ its(:status_code) { is_expected.to eq 422 }
31
+ end
32
+
33
+ context '500' do
34
+ let(:code) { '500' }
35
+
36
+ it { is_expected.to be_a(Postmark::InternalServerError) }
37
+ its(:status_code) { is_expected.to eq 500 }
38
+ end
39
+
40
+ context 'others' do
41
+ let(:code) { '999' }
42
+
43
+ it { is_expected.to be_a(Postmark::UnexpectedHttpResponseError) }
44
+ its(:status_code) { is_expected.to eq code.to_i }
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#retry?' do
50
+ it 'is true for 5XX status codes' do
51
+ (500...600).each do |code|
52
+ expect(Postmark::HttpServerError.new(code).retry?).to be true
53
+ end
54
+ end
55
+
56
+ it 'is false for other codes except 5XX' do
57
+ [200, 300, 400].each do |code|
58
+ expect(Postmark::HttpServerError.new(code).retry?).to be false
59
+ end
60
+ end
61
+ end
62
+
63
+ describe '#message ' do
64
+ it 'uses "Message" field on postmark response if available' do
65
+ data = { 'Message' => 'Postmark error message' }
66
+ error = Postmark::HttpServerError.new(502, Postmark::Json.encode(data), data)
67
+ expect(error.message).to eq data['Message']
68
+ end
69
+
70
+ it 'falls back to a message generated from status code' do
71
+ error = Postmark::HttpServerError.new(502, '<html>')
72
+ expect(error.message).to match(/The Postmark API responded with HTTP status \d+/)
73
+ end
74
+ end
75
+ end
76
+
77
+ describe(Postmark::ApiInputError) do
78
+ describe '.build' do
79
+ context 'picks an appropriate subclass for error code' do
80
+ let(:response) { { 'ErrorCode' => code } }
81
+
82
+ subject do
83
+ Postmark::ApiInputError.build(Postmark::Json.encode(response), response)
84
+ end
85
+
86
+ shared_examples_for 'api input error' do
87
+ its(:status_code) { is_expected. to eq 422 }
88
+ specify { expect(subject.retry?).to be false }
89
+ it { is_expected.to be_a(Postmark::ApiInputError) }
90
+ it { is_expected.to be_a(Postmark::HttpServerError) }
91
+ end
92
+
93
+ context '406' do
94
+ let(:code) { Postmark::ApiInputError::INACTIVE_RECIPIENT }
95
+
96
+ it { is_expected.to be_a(Postmark::InactiveRecipientError) }
97
+ it_behaves_like 'api input error'
98
+ end
99
+
100
+ context 'others' do
101
+ let(:code) { '9999' }
102
+
103
+ it_behaves_like 'api input error'
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ describe(Postmark::TimeoutError) do
110
+ it { is_expected.to be_a(Postmark::Error) }
111
+ specify { expect(subject.retry?).to be true }
112
+ end
113
+
114
+ describe(Postmark::UnknownMessageType) do
115
+ it 'exists for backward compatibility' do
116
+ is_expected.to be_a(Postmark::Error)
117
+ end
118
+ end
119
+
120
+ describe(Postmark::InvalidApiKeyError) do
121
+ it { is_expected.to be_a(Postmark::Error) }
122
+ end
123
+
124
+ describe(Postmark::InternalServerError) do
125
+ it { is_expected.to be_a(Postmark::Error) }
126
+ end
127
+
128
+ describe(Postmark::UnexpectedHttpResponseError) do
129
+ it { is_expected.to be_a(Postmark::Error) }
130
+ end
131
+
132
+ describe(Postmark::InactiveRecipientError) do
133
+ describe '.parse_recipients' do
134
+ let(:recipients) do
135
+ %w(nothing@wildbit.com noth.ing+2@wildbit.com noth.ing+2-1@wildbit.com)
136
+ end
137
+
138
+ subject { Postmark::InactiveRecipientError.parse_recipients(message) }
139
+
140
+ context '1/1 inactive' do
141
+ let(:message) do
142
+ 'You tried to send to a recipient that has been marked as ' \
143
+ "inactive.\nFound inactive addresses: #{recipients[0]}.\n" \
144
+ 'Inactive recipients are ones that have generated a hard ' \
145
+ 'bounce or a spam complaint.'
146
+ end
147
+
148
+ it { is_expected.to eq(recipients.take(1)) }
149
+ end
150
+
151
+ context 'i/n inactive, n > 1, i < n' do
152
+ let(:message) do
153
+ 'Message OK, but will not deliver to these inactive addresses: ' \
154
+ "#{recipients[0...2].join(', ')}. Inactive recipients are ones that " \
155
+ 'have generated a hard bounce or a spam complaint.'
156
+ end
157
+
158
+ it { is_expected.to eq(recipients.take(2)) }
159
+ end
160
+
161
+ context 'n/n inactive, n > 1' do
162
+ let(:message) do
163
+ 'You tried to send to recipients that have all been marked as ' \
164
+ "inactive.\nFound inactive addresses: #{recipients.join(', ')}.\n" \
165
+ 'Inactive recipients are ones that have generated a hard bounce or a spam complaint.'
166
+ end
167
+
168
+ it { is_expected.to eq(recipients) }
169
+ end
170
+
171
+ context 'unknown error format' do
172
+ let(:message) { recipients.join(', ') }
173
+
174
+ it { is_expected.to eq([]) }
175
+ end
176
+ end
177
+
178
+ describe '.new' do
179
+ let(:address) { 'user@example.org' }
180
+ let(:response) { { 'Message' => message } }
181
+
182
+ subject do
183
+ Postmark::InactiveRecipientError.new(
184
+ Postmark::ApiInputError::INACTIVE_RECIPIENT,
185
+ Postmark::Json.encode(response),
186
+ response)
187
+ end
188
+
189
+ let(:message) do
190
+ 'You tried to send to a recipient that has been marked as ' \
191
+ "inactive.\nFound inactive addresses: #{address}.\n" \
192
+ 'Inactive recipients are ones that have generated a hard ' \
193
+ 'bounce or a spam complaint.'
194
+ end
195
+
196
+ it 'parses recipients from json payload' do
197
+ expect(subject.recipients).to eq([address])
198
+ end
199
+ end
200
+ end
201
+
202
+ describe(Postmark::DeliveryError) do
203
+ it 'is an alias to Error for backwards compatibility' do
204
+ expect(subject.class).to eq(Postmark::Error)
205
+ end
206
+ end
207
+
208
+ describe(Postmark::InvalidMessageError) do
209
+ it 'is an alias to Error for backwards compatibility' do
210
+ expect(subject.class).to eq(Postmark::ApiInputError)
211
+ end
212
+ end
213
+
214
+ describe(Postmark::UnknownError) do
215
+ it 'is an alias for backwards compatibility' do
216
+ expect(subject.class).to eq(Postmark::UnexpectedHttpResponseError)
217
+ end
218
+ end
@@ -15,19 +15,19 @@ describe Mail::Postmark do
15
15
  end
16
16
 
17
17
  it "wraps Postmark.send_through_postmark" do
18
- Postmark::ApiClient.any_instance.should_receive(:deliver_message).with(message)
18
+ allow_any_instance_of(Postmark::ApiClient).to receive(:deliver_message).with(message)
19
19
  message.delivery_method Mail::Postmark
20
20
  message.deliver
21
21
  end
22
22
 
23
23
  it "returns self by default" do
24
- Postmark::ApiClient.any_instance.should_receive(:deliver_message).with(message)
24
+ allow_any_instance_of(Postmark::ApiClient).to receive(:deliver_message).with(message)
25
25
  message.delivery_method Mail::Postmark
26
26
  message.deliver.should eq message
27
27
  end
28
28
 
29
29
  it "returns the actual response if :return_response setting is present" do
30
- Postmark::ApiClient.any_instance.should_receive(:deliver_message).with(message)
30
+ allow_any_instance_of(Postmark::ApiClient).to receive(:deliver_message).with(message)
31
31
  message.delivery_method Mail::Postmark, :return_response => true
32
32
  message.deliver.should eq message
33
33
  end
@@ -39,13 +39,13 @@ describe Mail::Postmark do
39
39
 
40
40
  it 'uses provided API token' do
41
41
  message.delivery_method Mail::Postmark, :api_token => 'api-token'
42
- Postmark::ApiClient.should_receive(:new).with('api-token', {}).and_return(double(:deliver_message => true))
42
+ expect(Postmark::ApiClient).to receive(:new).with('api-token', {}).and_return(double(:deliver_message => true))
43
43
  message.deliver
44
44
  end
45
45
 
46
46
  it 'uses API token provided as legacy api_key' do
47
47
  message.delivery_method Mail::Postmark, :api_key => 'api-token'
48
- Postmark::ApiClient.should_receive(:new).with('api-token', {}).and_return(double(:deliver_message => true))
48
+ expect(Postmark::ApiClient).to receive(:new).with('api-token', {}).and_return(double(:deliver_message => true))
49
49
  message.deliver
50
50
  end
51
51
  end
@@ -36,7 +36,7 @@ describe Postmark::HttpClient do
36
36
  its(:api_key) { should eq api_token }
37
37
  its(:host) { should eq 'api.postmarkapp.com' }
38
38
  its(:port) { should eq 443 }
39
- its(:secure) { should be_true }
39
+ its(:secure) { should be true }
40
40
  its(:path_prefix) { should eq '/' }
41
41
  its(:http_read_timeout) { should eq 15 }
42
42
  its(:http_open_timeout) { should eq 5 }
@@ -128,8 +128,7 @@ describe Postmark::HttpClient do
128
128
  end
129
129
 
130
130
  it "raises a custom error when the request times out" do
131
- subject.http.should_receive(:post).at_least(:once).
132
- and_raise(Timeout::Error)
131
+ expect(subject.http).to receive(:post).at_least(:once).and_raise(Timeout::Error)
133
132
  expect { subject.post(target_path) }.to raise_error Postmark::TimeoutError
134
133
  end
135
134
 
@@ -170,7 +169,7 @@ describe Postmark::HttpClient do
170
169
  end
171
170
 
172
171
  it "raises a custom error when the request times out" do
173
- subject.http.should_receive(:get).at_least(:once).and_raise(Timeout::Error)
172
+ expect(subject.http).to receive(:get).at_least(:once).and_raise(Timeout::Error)
174
173
  expect { subject.get(target_path) }.to raise_error Postmark::TimeoutError
175
174
  end
176
175
 
@@ -211,7 +210,7 @@ describe Postmark::HttpClient do
211
210
  end
212
211
 
213
212
  it "raises a custom error when the request times out" do
214
- subject.http.should_receive(:put).at_least(:once).and_raise(Timeout::Error)
213
+ expect(subject.http).to receive(:put).at_least(:once).and_raise(Timeout::Error)
215
214
  expect { subject.put(target_path) }.to raise_error Postmark::TimeoutError
216
215
  end
217
216
 
@@ -311,6 +311,12 @@ describe Postmark::MailMessageConverter do
311
311
  "TrackLinks" => 'None'})
312
312
  end
313
313
 
314
+ it 'converts link tracking options when set via header' do
315
+ msg = mail_html_message
316
+ msg[:track_links] = :html_and_text
317
+ expect(subject.new(msg).run).to include('TrackLinks' => 'HtmlAndText')
318
+ end
319
+
314
320
  end
315
321
 
316
322
  it 'correctly decodes unicode in messages transfered as quoted-printable' do
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Mail::Message do
4
4
  before do
5
- Kernel.stub(:warn)
5
+ allow(Kernel).to receive(:warn)
6
6
  end
7
7
 
8
8
  let(:mail_message) do
@@ -147,7 +147,7 @@ describe Mail::Message do
147
147
  end
148
148
 
149
149
  it "is deprecated" do
150
- Kernel.should_receive(:warn).with(/deprecated/)
150
+ expect(Kernel).to receive(:warn).with(/deprecated/)
151
151
  mail_message.postmark_attachments = attached_hash
152
152
  end
153
153
  end
@@ -161,12 +161,12 @@ describe Mail::Message do
161
161
  'Content' => ''} }
162
162
 
163
163
  before do
164
- attached_file.stub(:is_a?) { |arg| arg == File ? true : false }
165
- attached_file.stub(:path) { '/tmp/file.jpeg' }
164
+ allow(attached_file).to receive(:is_a?) { |arg| arg == File ? true : false }
165
+ allow(attached_file).to receive(:path) { '/tmp/file.jpeg' }
166
166
  end
167
167
 
168
168
  it "supports multiple attachment formats" do
169
- IO.should_receive(:read).with("/tmp/file.jpeg").and_return("")
169
+ expect(IO).to receive(:read).with("/tmp/file.jpeg").and_return("")
170
170
 
171
171
  mail_message.postmark_attachments = [attached_hash, attached_file]
172
172
  attachments = mail_message.export_attachments
@@ -177,7 +177,7 @@ describe Mail::Message do
177
177
 
178
178
  it "is deprecated" do
179
179
  mail_message.postmark_attachments = attached_hash
180
- Kernel.should_receive(:warn).with(/deprecated/)
180
+ expect(Kernel).to receive(:warn).with(/deprecated/)
181
181
  mail_message.postmark_attachments
182
182
  end
183
183
  end
@@ -99,7 +99,7 @@ describe Postmark do
99
99
  context "when shared client instance does not exist" do
100
100
 
101
101
  it 'creates a new instance of Postmark::ApiClient' do
102
- Postmark::ApiClient.should_receive(:new).
102
+ allow(Postmark::ApiClient).to receive(:new).
103
103
  with(api_token,
104
104
  :secure => secure,
105
105
  :proxy_host => proxy_host,
@@ -127,12 +127,12 @@ describe Postmark do
127
127
  end
128
128
 
129
129
  it 'delegates the method to the shared api client instance' do
130
- api_client.should_receive(:deliver_message).with(message)
130
+ allow(api_client).to receive(:deliver_message).with(message)
131
131
  subject.deliver_message(message)
132
132
  end
133
133
 
134
134
  it 'is also accessible as .send_through_postmark' do
135
- api_client.should_receive(:deliver_message).with(message)
135
+ allow(api_client).to receive(:deliver_message).with(message)
136
136
  subject.send_through_postmark(message)
137
137
  end
138
138
  end
@@ -146,7 +146,7 @@ describe Postmark do
146
146
  end
147
147
 
148
148
  it 'delegates the method to the shared api client instance' do
149
- api_client.should_receive(:deliver_messages).with(message)
149
+ allow(api_client).to receive(:deliver_messages).with(message)
150
150
  subject.deliver_messages(message)
151
151
  end
152
152
  end
@@ -159,7 +159,7 @@ describe Postmark do
159
159
  end
160
160
 
161
161
  it 'delegates the method to the shared api client instance' do
162
- api_client.should_receive(:delivery_stats)
162
+ allow(api_client).to receive(:delivery_stats)
163
163
  subject.delivery_stats
164
164
  end
165
165
  end