postmark 0.9.19 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +8 -0
- data/CHANGELOG.rdoc +20 -0
- data/Gemfile +6 -0
- data/README.md +351 -91
- data/VERSION +1 -1
- data/lib/postmark.rb +40 -132
- data/lib/postmark/api_client.rb +162 -0
- data/lib/postmark/bounce.rb +20 -17
- data/lib/postmark/handlers/mail.rb +10 -3
- data/lib/postmark/helpers/hash_helper.rb +35 -0
- data/lib/postmark/helpers/message_helper.rb +62 -0
- data/lib/postmark/http_client.rb +44 -28
- data/lib/postmark/inbound.rb +21 -0
- data/lib/postmark/inflector.rb +28 -0
- data/lib/postmark/message_extensions/mail.rb +50 -5
- data/lib/postmark/message_extensions/shared.rb +23 -28
- data/lib/postmark/version.rb +1 -1
- data/postmark.gemspec +4 -7
- data/spec/data/empty.gif +0 -0
- data/spec/integration/api_client_hashes_spec.rb +101 -0
- data/spec/integration/api_client_messages_spec.rb +127 -0
- data/spec/integration/mail_delivery_method_spec.rb +80 -0
- data/spec/spec_helper.rb +15 -5
- data/spec/support/helpers.rb +11 -0
- data/spec/{shared_examples.rb → support/shared_examples.rb} +0 -0
- data/spec/unit/postmark/api_client_spec.rb +246 -0
- data/spec/unit/postmark/bounce_spec.rb +142 -0
- data/spec/unit/postmark/handlers/mail_spec.rb +39 -0
- data/spec/unit/postmark/helpers/hash_helper_spec.rb +34 -0
- data/spec/unit/postmark/helpers/message_helper_spec.rb +115 -0
- data/spec/unit/postmark/http_client_spec.rb +204 -0
- data/spec/unit/postmark/inbound_spec.rb +88 -0
- data/spec/unit/postmark/inflector_spec.rb +35 -0
- data/spec/unit/postmark/json_spec.rb +37 -0
- data/spec/unit/postmark/message_extensions/mail_spec.rb +205 -0
- data/spec/unit/postmark_spec.rb +164 -0
- metadata +45 -93
- data/lib/postmark/attachments_fix_for_mail.rb +0 -48
- data/lib/postmark/message_extensions/tmail.rb +0 -115
- data/spec/bounce_spec.rb +0 -53
- data/spec/postmark_spec.rb +0 -253
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Postmark::Inbound do
|
4
|
+
# http://developer.postmarkapp.com/developer-inbound-parse.html#example-hook
|
5
|
+
let(:example_inbound) { '{"From":"myUser@theirDomain.com","FromFull":{"Email":"myUser@theirDomain.com","Name":"John Doe"},"To":"451d9b70cf9364d23ff6f9d51d870251569e+ahoy@inbound.postmarkapp.com","ToFull":[{"Email":"451d9b70cf9364d23ff6f9d51d870251569e+ahoy@inbound.postmarkapp.com","Name":""}],"Cc":"\"Full name\" <sample.cc@emailDomain.com>, \"Another Cc\" <another.cc@emailDomain.com>","CcFull":[{"Email":"sample.cc@emailDomain.com","Name":"Full name"},{"Email":"another.cc@emailDomain.com","Name":"Another Cc"}],"ReplyTo":"myUsersReplyAddress@theirDomain.com","Subject":"This is an inbound message","MessageID":"22c74902-a0c1-4511-804f2-341342852c90","Date":"Thu, 5 Apr 2012 16:59:01 +0200","MailboxHash":"ahoy","TextBody":"[ASCII]","HtmlBody":"[HTML(encoded)]","Tag":"","Headers":[{"Name":"X-Spam-Checker-Version","Value":"SpamAssassin 3.3.1 (2010-03-16) onrs-ord-pm-inbound1.wildbit.com"},{"Name":"X-Spam-Status","Value":"No"},{"Name":"X-Spam-Score","Value":"-0.1"},{"Name":"X-Spam-Tests","Value":"DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_PASS"},{"Name":"Received-SPF","Value":"Pass (sender SPF authorized) identity=mailfrom; client-ip=209.85.160.180; helo=mail-gy0-f180.google.com; envelope-from=myUser@theirDomain.com; receiver=451d9b70cf9364d23ff6f9d51d870251569e+ahoy@inbound.postmarkapp.com"},{"Name":"DKIM-Signature","Value":"v=1; a=rsa-sha256; c=relaxed\/relaxed; d=wildbit.com; s=google; h=mime-version:reply-to:date:message-id:subject:from:to:cc :content-type; bh=cYr\/+oQiklaYbBJOQU3CdAnyhCTuvemrU36WT7cPNt0=; b=QsegXXbTbC4CMirl7A3VjDHyXbEsbCUTPL5vEHa7hNkkUTxXOK+dQA0JwgBHq5C+1u iuAJMz+SNBoTqEDqte2ckDvG2SeFR+Edip10p80TFGLp5RucaYvkwJTyuwsA7xd78NKT Q9ou6L1hgy\/MbKChnp2kxHOtYNOrrszY3JfQM="},{"Name":"MIME-Version","Value":"1.0"},{"Name":"Message-ID","Value":"<CAGXpo2WKfxHWZ5UFYCR3H_J9SNMG+5AXUovfEFL6DjWBJSyZaA@mail.gmail.com>"}],"Attachments":[{"Name":"myimage.png","Content":"[BASE64-ENCODED CONTENT]","ContentType":"image/png","ContentLength":4096},{"Name":"mypaper.doc","Content":"[BASE64-ENCODED CONTENT]","ContentType":"application/msword","ContentLength":16384}]}' }
|
6
|
+
|
7
|
+
context "given a serialized inbound document" do
|
8
|
+
subject { Postmark::Inbound.to_ruby_hash(example_inbound) }
|
9
|
+
|
10
|
+
it { should have_key(:from) }
|
11
|
+
it { should have_key(:from_full) }
|
12
|
+
it { should have_key(:to) }
|
13
|
+
it { should have_key(:to_full) }
|
14
|
+
it { should have_key(:cc) }
|
15
|
+
it { should have_key(:cc_full) }
|
16
|
+
it { should have_key(:reply_to) }
|
17
|
+
it { should have_key(:subject) }
|
18
|
+
it { should have_key(:message_id) }
|
19
|
+
it { should have_key(:date) }
|
20
|
+
it { should have_key(:mailbox_hash) }
|
21
|
+
it { should have_key(:text_body) }
|
22
|
+
it { should have_key(:html_body) }
|
23
|
+
it { should have_key(:tag) }
|
24
|
+
it { should have_key(:headers) }
|
25
|
+
it { should have_key(:attachments) }
|
26
|
+
|
27
|
+
context "cc" do
|
28
|
+
it 'has 2 CCs' do
|
29
|
+
subject[:cc_full].count.should == 2
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'stores CCs as an array of Ruby hashes' do
|
33
|
+
cc = subject[:cc_full].last
|
34
|
+
cc.should have_key(:email)
|
35
|
+
cc.should have_key(:name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "to" do
|
40
|
+
it 'has 1 recipients' do
|
41
|
+
subject[:to_full].count.should == 1
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'stores TOs as an array of Ruby hashes' do
|
45
|
+
cc = subject[:to_full].last
|
46
|
+
cc.should have_key(:email)
|
47
|
+
cc.should have_key(:name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "from" do
|
52
|
+
it 'is a hash' do
|
53
|
+
subject[:from_full].should be_a Hash
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should have all required fields' do
|
57
|
+
subject[:from_full].should have_key(:email)
|
58
|
+
subject[:from_full].should have_key(:name)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "headers" do
|
63
|
+
it 'has 8 headers' do
|
64
|
+
subject[:headers].count.should == 8
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'stores headers as an array of Ruby hashes' do
|
68
|
+
header = subject[:headers].last
|
69
|
+
header.should have_key(:name)
|
70
|
+
header.should have_key(:value)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "attachments" do
|
75
|
+
it 'has 2 attachments' do
|
76
|
+
subject[:attachments].count.should == 2
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'stores attachemnts as an array of Ruby hashes' do
|
80
|
+
attachment = subject[:attachments].last
|
81
|
+
attachment.should have_key(:name)
|
82
|
+
attachment.should have_key(:content)
|
83
|
+
attachment.should have_key(:content_type)
|
84
|
+
attachment.should have_key(:content_length)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Postmark::Inflector do
|
4
|
+
|
5
|
+
describe ".to_postmark" do
|
6
|
+
it 'converts rubyish underscored format to camel cased symbols accepted by the Postmark API' do
|
7
|
+
subject.to_postmark(:foo_bar).should == 'FooBar'
|
8
|
+
subject.to_postmark(:_bar).should == 'Bar'
|
9
|
+
subject.to_postmark(:really_long_long_long_long_symbol).should == 'ReallyLongLongLongLongSymbol'
|
10
|
+
subject.to_postmark(:foo_bar_1).should == 'FooBar1'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'accepts strings as well' do
|
14
|
+
subject.to_postmark('foo_bar').should == 'FooBar'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'acts idempotentely' do
|
18
|
+
subject.to_postmark('FooBar').should == 'FooBar'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe ".to_ruby" do
|
23
|
+
it 'converts camel cased symbols returned by the Postmark API to underscored Ruby symbols' do
|
24
|
+
subject.to_ruby('FooBar').should == :foo_bar
|
25
|
+
subject.to_ruby('LongTimeAgoInAFarFarGalaxy').should == :long_time_ago_in_a_far_far_galaxy
|
26
|
+
subject.to_ruby('MessageID').should == :message_id
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'acts idempotentely' do
|
30
|
+
subject.to_ruby(:foo_bar).should == :foo_bar
|
31
|
+
subject.to_ruby(:foo_bar_1).should == :foo_bar_1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Postmark::Json do
|
4
|
+
let(:data) { {"bar" => "foo", "foo" => "bar"} }
|
5
|
+
|
6
|
+
shared_examples "json parser" do
|
7
|
+
it 'encodes and decodes data correctly' do
|
8
|
+
hash = Postmark::Json.decode(Postmark::Json.encode(data))
|
9
|
+
hash.should have_key("bar")
|
10
|
+
hash.should have_key("foo")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "given response parser is JSON" do
|
15
|
+
before do
|
16
|
+
Postmark.response_parser_class = :Json
|
17
|
+
end
|
18
|
+
|
19
|
+
it_behaves_like "json parser"
|
20
|
+
end
|
21
|
+
|
22
|
+
context "given response parser is ActiveSupport::JSON" do
|
23
|
+
before do
|
24
|
+
Postmark.response_parser_class = :ActiveSupport
|
25
|
+
end
|
26
|
+
|
27
|
+
it_behaves_like "json parser"
|
28
|
+
end
|
29
|
+
|
30
|
+
context "given response parser is Yajl", :skip_for_platform => 'java' do
|
31
|
+
before do
|
32
|
+
Postmark.response_parser_class = :Yajl
|
33
|
+
end
|
34
|
+
|
35
|
+
it_behaves_like "json parser"
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mail::Message do
|
4
|
+
before do
|
5
|
+
Kernel.stub(:warn)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:mail_message) do
|
9
|
+
Mail.new do
|
10
|
+
from "sheldon@bigbangtheory.com"
|
11
|
+
to "lenard@bigbangtheory.com"
|
12
|
+
subject "Hello!"
|
13
|
+
body "Hello Sheldon!"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:tagged_mail_message) do
|
18
|
+
Mail.new do
|
19
|
+
from "sheldon@bigbangtheory.com"
|
20
|
+
to "lenard@bigbangtheory.com"
|
21
|
+
subject "Hello!"
|
22
|
+
body "Hello Sheldon!"
|
23
|
+
tag "sheldon"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:mail_message_without_body) do
|
28
|
+
Mail.new do
|
29
|
+
from "sheldon@bigbangtheory.com"
|
30
|
+
to "lenard@bigbangtheory.com"
|
31
|
+
subject "Hello!"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:mail_html_message) do
|
36
|
+
mail = Mail.new do
|
37
|
+
from "sheldon@bigbangtheory.com"
|
38
|
+
to "lenard@bigbangtheory.com"
|
39
|
+
subject "Hello!"
|
40
|
+
content_type 'text/html; charset=UTF-8'
|
41
|
+
body "<b>Hello Sheldon!</b>"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
let(:mail_multipart_message) do
|
46
|
+
mail = Mail.new do
|
47
|
+
from "sheldon@bigbangtheory.com"
|
48
|
+
to "lenard@bigbangtheory.com"
|
49
|
+
subject "Hello!"
|
50
|
+
text_part do
|
51
|
+
body "Hello Sheldon!"
|
52
|
+
end
|
53
|
+
html_part do
|
54
|
+
body "<b>Hello Sheldon!</b>"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
let(:mail_message_with_attachment) do
|
60
|
+
Mail.new do
|
61
|
+
from "sheldon@bigbangtheory.com"
|
62
|
+
to "lenard@bigbangtheory.com"
|
63
|
+
subject "Hello!"
|
64
|
+
body "Hello Sheldon!"
|
65
|
+
add_file empty_gif_path
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#html?" do
|
70
|
+
it 'is true for html only email' do
|
71
|
+
mail_html_message.should be_html
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#body_html" do
|
76
|
+
it 'returns html body if present' do
|
77
|
+
mail_html_message.body_html.should == "<b>Hello Sheldon!</b>"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#body_text" do
|
82
|
+
it 'returns text body if present' do
|
83
|
+
mail_message.body_text.should == "Hello Sheldon!"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#postmark_attachments=" do
|
88
|
+
let(:attached_hash) { {'Name' => 'picture.jpeg',
|
89
|
+
'ContentType' => 'image/jpeg'} }
|
90
|
+
|
91
|
+
it "stores attachments as an array" do
|
92
|
+
mail_message.postmark_attachments = attached_hash
|
93
|
+
mail_message.instance_variable_get(:@_attachments).should include(attached_hash)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "is deprecated" do
|
97
|
+
Kernel.should_receive(:warn).with(/deprecated/)
|
98
|
+
mail_message.postmark_attachments = attached_hash
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#postmark_attachments" do
|
103
|
+
let(:attached_file) { mock("file") }
|
104
|
+
let(:attached_hash) { {'Name' => 'picture.jpeg',
|
105
|
+
'ContentType' => 'image/jpeg'} }
|
106
|
+
let(:exported_file) { {'Name' => 'file.jpeg',
|
107
|
+
'ContentType' => 'application/octet-stream',
|
108
|
+
'Content' => ''} }
|
109
|
+
|
110
|
+
before do
|
111
|
+
attached_file.stub(:is_a?) { |arg| arg == File ? true : false }
|
112
|
+
attached_file.stub(:path) { '/tmp/file.jpeg' }
|
113
|
+
end
|
114
|
+
|
115
|
+
it "supports multiple attachment formats" do
|
116
|
+
IO.should_receive(:read).with("/tmp/file.jpeg").and_return("")
|
117
|
+
|
118
|
+
mail_message.postmark_attachments = [attached_hash, attached_file]
|
119
|
+
attachments = mail_message.export_attachments
|
120
|
+
|
121
|
+
attachments.should include(attached_hash)
|
122
|
+
attachments.should include(exported_file)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "is deprecated" do
|
126
|
+
mail_message.postmark_attachments = attached_hash
|
127
|
+
Kernel.should_receive(:warn).with(/deprecated/)
|
128
|
+
mail_message.postmark_attachments
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#export_attachments" do
|
133
|
+
let(:file_data) { 'binarydatahere' }
|
134
|
+
let(:exported_data) do
|
135
|
+
{'Name' => 'face.jpeg',
|
136
|
+
'Content' => "YmluYXJ5ZGF0YWhlcmU=\n",
|
137
|
+
'ContentType' => 'image/jpeg'}
|
138
|
+
end
|
139
|
+
|
140
|
+
it "exports native attachments" do
|
141
|
+
mail_message.attachments["face.jpeg"] = file_data
|
142
|
+
mail_message.export_attachments.should include(exported_data)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "still supports the deprecated attachments API" do
|
146
|
+
mail_message.attachments["face.jpeg"] = file_data
|
147
|
+
mail_message.postmark_attachments = exported_data
|
148
|
+
mail_message.export_attachments.should == [exported_data, exported_data]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#to_postmark_hash" do
|
153
|
+
it 'converts plain text messages correctly' do
|
154
|
+
mail_message.to_postmark_hash.should == {
|
155
|
+
"From" => "sheldon@bigbangtheory.com",
|
156
|
+
"Subject" => "Hello!",
|
157
|
+
"TextBody" => "Hello Sheldon!",
|
158
|
+
"To" => "lenard@bigbangtheory.com"}
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'converts tagged text messages correctly' do
|
162
|
+
tagged_mail_message.to_postmark_hash.should == {
|
163
|
+
"From" => "sheldon@bigbangtheory.com",
|
164
|
+
"Subject" => "Hello!",
|
165
|
+
"TextBody" => "Hello Sheldon!",
|
166
|
+
"Tag" => "sheldon",
|
167
|
+
"To"=>"lenard@bigbangtheory.com"}
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'converts plain text messages without body correctly' do
|
171
|
+
mail_message_without_body.to_postmark_hash.should == {
|
172
|
+
"From" => "sheldon@bigbangtheory.com",
|
173
|
+
"Subject" => "Hello!",
|
174
|
+
"To" => "lenard@bigbangtheory.com"}
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'converts html messages correctly' do
|
178
|
+
mail_html_message.to_postmark_hash.should == {
|
179
|
+
"From" => "sheldon@bigbangtheory.com",
|
180
|
+
"Subject" => "Hello!",
|
181
|
+
"HtmlBody" => "<b>Hello Sheldon!</b>",
|
182
|
+
"To" => "lenard@bigbangtheory.com"}
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'converts multipart messages correctly' do
|
186
|
+
mail_multipart_message.to_postmark_hash.should == {
|
187
|
+
"From" => "sheldon@bigbangtheory.com",
|
188
|
+
"Subject" => "Hello!",
|
189
|
+
"HtmlBody" => "<b>Hello Sheldon!</b>",
|
190
|
+
"TextBody" => "Hello Sheldon!",
|
191
|
+
"To" => "lenard@bigbangtheory.com"}
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'converts messages with attachments correctly' do
|
195
|
+
mail_message_with_attachment.to_postmark_hash.should == {
|
196
|
+
"From" => "sheldon@bigbangtheory.com",
|
197
|
+
"Subject" => "Hello!",
|
198
|
+
"Attachments" => [{"Name"=>"empty.gif",
|
199
|
+
"Content"=>encoded_empty_gif_data,
|
200
|
+
"ContentType"=>"image/gif"}],
|
201
|
+
"TextBody"=>"Hello Sheldon!",
|
202
|
+
"To"=>"lenard@bigbangtheory.com"}
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Postmark do
|
4
|
+
let(:api_key) { mock }
|
5
|
+
let(:secure) { mock }
|
6
|
+
let(:proxy_host) { mock }
|
7
|
+
let(:proxy_port) { mock }
|
8
|
+
let(:proxy_user) { mock }
|
9
|
+
let(:proxy_pass) { mock }
|
10
|
+
let(:host) { mock }
|
11
|
+
let(:port) { mock }
|
12
|
+
let(:path_prefix) { mock }
|
13
|
+
let(:max_retries) { mock }
|
14
|
+
|
15
|
+
before do
|
16
|
+
subject.api_key = api_key
|
17
|
+
subject.secure = secure
|
18
|
+
subject.proxy_host = proxy_host
|
19
|
+
subject.proxy_port = proxy_port
|
20
|
+
subject.proxy_user = proxy_user
|
21
|
+
subject.proxy_pass = proxy_pass
|
22
|
+
subject.host = host
|
23
|
+
subject.port = port
|
24
|
+
subject.path_prefix = path_prefix
|
25
|
+
subject.max_retries = max_retries
|
26
|
+
end
|
27
|
+
|
28
|
+
context "attr readers" do
|
29
|
+
it { should respond_to(:secure) }
|
30
|
+
it { should respond_to(:api_key) }
|
31
|
+
it { should respond_to(:proxy_host) }
|
32
|
+
it { should respond_to(:proxy_port) }
|
33
|
+
it { should respond_to(:proxy_user) }
|
34
|
+
it { should respond_to(:proxy_pass) }
|
35
|
+
it { should respond_to(:host) }
|
36
|
+
it { should respond_to(:port) }
|
37
|
+
it { should respond_to(:path_prefix) }
|
38
|
+
it { should respond_to(:http_open_timeout) }
|
39
|
+
it { should respond_to(:http_read_timeout) }
|
40
|
+
it { should respond_to(:max_retries) }
|
41
|
+
end
|
42
|
+
|
43
|
+
context "attr writers" do
|
44
|
+
it { should respond_to(:secure=) }
|
45
|
+
it { should respond_to(:api_key=) }
|
46
|
+
it { should respond_to(:proxy_host=) }
|
47
|
+
it { should respond_to(:proxy_port=) }
|
48
|
+
it { should respond_to(:proxy_user=) }
|
49
|
+
it { should respond_to(:proxy_pass=) }
|
50
|
+
it { should respond_to(:host=) }
|
51
|
+
it { should respond_to(:port=) }
|
52
|
+
it { should respond_to(:path_prefix=) }
|
53
|
+
it { should respond_to(:http_open_timeout=) }
|
54
|
+
it { should respond_to(:http_read_timeout=) }
|
55
|
+
it { should respond_to(:max_retries=) }
|
56
|
+
it { should respond_to(:response_parser_class=) }
|
57
|
+
it { should respond_to(:api_client=) }
|
58
|
+
end
|
59
|
+
|
60
|
+
describe ".response_parser_class" do
|
61
|
+
|
62
|
+
after do
|
63
|
+
subject.instance_variable_set(:@response_parser_class, nil)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns :ActiveSupport when ActiveSupport::JSON is available" do
|
67
|
+
subject.response_parser_class.should == :ActiveSupport
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns :Json when ActiveSupport::JSON is not available" do
|
71
|
+
hide_const("ActiveSupport::JSON")
|
72
|
+
subject.response_parser_class.should == :Json
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe ".configure" do
|
78
|
+
|
79
|
+
it 'yields itself to the block' do
|
80
|
+
expect { |b| subject.configure(&b) }.to yield_with_args(subject)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe ".api_client" do
|
86
|
+
let(:api_client) { mock }
|
87
|
+
|
88
|
+
context "when shared client instance already exists" do
|
89
|
+
|
90
|
+
it 'returns the existing instance' do
|
91
|
+
subject.instance_variable_set(:@api_client, api_client)
|
92
|
+
subject.api_client.should == api_client
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when shared client instance does not exist" do
|
98
|
+
|
99
|
+
it 'creates a new instance of Postmark::ApiClient' do
|
100
|
+
Postmark::ApiClient.should_receive(:new).
|
101
|
+
with(api_key,
|
102
|
+
:secure => secure,
|
103
|
+
:proxy_host => proxy_host,
|
104
|
+
:proxy_port => proxy_port,
|
105
|
+
:proxy_user => proxy_user,
|
106
|
+
:proxy_pass => proxy_pass,
|
107
|
+
:host => host,
|
108
|
+
:port => port,
|
109
|
+
:path_prefix => path_prefix,
|
110
|
+
:max_retries => max_retries).
|
111
|
+
and_return(api_client)
|
112
|
+
subject.api_client.should == api_client
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
describe ".deliver_message" do
|
120
|
+
let(:api_client) { mock }
|
121
|
+
let(:message) { mock }
|
122
|
+
|
123
|
+
before do
|
124
|
+
subject.api_client = api_client
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'delegates the method to the shared api client instance' do
|
128
|
+
api_client.should_receive(:deliver_message).with(message)
|
129
|
+
subject.deliver_message(message)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'is also accessible as .send_through_postmark' do
|
133
|
+
api_client.should_receive(:deliver_message).with(message)
|
134
|
+
subject.send_through_postmark(message)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe ".deliver_messages" do
|
139
|
+
let(:api_client) { mock }
|
140
|
+
let(:message) { mock }
|
141
|
+
|
142
|
+
before do
|
143
|
+
subject.api_client = api_client
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'delegates the method to the shared api client instance' do
|
147
|
+
api_client.should_receive(:deliver_messages).with(message)
|
148
|
+
subject.deliver_messages(message)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe ".delivery_stats" do
|
153
|
+
let(:api_client) { mock }
|
154
|
+
|
155
|
+
before do
|
156
|
+
subject.api_client = api_client
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'delegates the method to the shared api client instance' do
|
160
|
+
api_client.should_receive(:delivery_stats)
|
161
|
+
subject.delivery_stats
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|