postmark 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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