postmark 1.8.1 → 1.21.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +8 -5
  4. data/CHANGELOG.rdoc +86 -0
  5. data/CONTRIBUTING.md +18 -0
  6. data/Gemfile +6 -5
  7. data/LICENSE +1 -1
  8. data/README.md +34 -607
  9. data/RELEASE.md +12 -0
  10. data/VERSION +1 -1
  11. data/gemfiles/Gemfile.legacy +5 -4
  12. data/lib/postmark.rb +1 -18
  13. data/lib/postmark/account_api_client.rb +55 -1
  14. data/lib/postmark/api_client.rb +145 -17
  15. data/lib/postmark/bounce.rb +0 -4
  16. data/lib/postmark/client.rb +12 -4
  17. data/lib/postmark/error.rb +127 -0
  18. data/lib/postmark/handlers/mail.rb +10 -4
  19. data/lib/postmark/helpers/message_helper.rb +4 -0
  20. data/lib/postmark/http_client.rb +20 -32
  21. data/lib/postmark/mail_message_converter.rb +18 -5
  22. data/lib/postmark/message_extensions/mail.rb +83 -8
  23. data/lib/postmark/version.rb +1 -1
  24. data/postmark.gemspec +1 -1
  25. data/postmark.png +0 -0
  26. data/spec/integration/account_api_client_spec.rb +42 -10
  27. data/spec/integration/api_client_hashes_spec.rb +32 -49
  28. data/spec/integration/api_client_messages_spec.rb +33 -52
  29. data/spec/integration/api_client_resources_spec.rb +12 -44
  30. data/spec/integration/mail_delivery_method_spec.rb +21 -23
  31. data/spec/spec_helper.rb +4 -7
  32. data/spec/support/custom_matchers.rb +44 -0
  33. data/spec/support/shared_examples.rb +16 -16
  34. data/spec/unit/postmark/account_api_client_spec.rb +239 -45
  35. data/spec/unit/postmark/api_client_spec.rb +792 -406
  36. data/spec/unit/postmark/bounce_spec.rb +40 -62
  37. data/spec/unit/postmark/client_spec.rb +0 -6
  38. data/spec/unit/postmark/error_spec.rb +231 -0
  39. data/spec/unit/postmark/handlers/mail_spec.rb +59 -27
  40. data/spec/unit/postmark/helpers/hash_helper_spec.rb +5 -6
  41. data/spec/unit/postmark/helpers/message_helper_spec.rb +60 -11
  42. data/spec/unit/postmark/http_client_spec.rb +76 -61
  43. data/spec/unit/postmark/inbound_spec.rb +34 -34
  44. data/spec/unit/postmark/inflector_spec.rb +11 -13
  45. data/spec/unit/postmark/json_spec.rb +2 -2
  46. data/spec/unit/postmark/mail_message_converter_spec.rb +250 -81
  47. data/spec/unit/postmark/message_extensions/mail_spec.rb +249 -38
  48. data/spec/unit/postmark_spec.rb +37 -37
  49. metadata +41 -11
@@ -6,11 +6,11 @@ describe Postmark::HashHelper do
6
6
  let(:target) { {"From" => "support@postmarkapp.com", "ReplyTo" => "contact@wildbit.com"} }
7
7
 
8
8
  it 'converts Hash keys to Postmark format' do
9
- subject.to_postmark(source).should == target
9
+ expect(subject.to_postmark(source)).to eq target
10
10
  end
11
11
 
12
12
  it 'acts idempotentely' do
13
- subject.to_postmark(target).should == target
13
+ expect(subject.to_postmark(target)).to eq target
14
14
  end
15
15
  end
16
16
 
@@ -19,16 +19,15 @@ describe Postmark::HashHelper do
19
19
  let(:target) { {:from => "support@postmarkapp.com", :reply_to => "contact@wildbit.com"} }
20
20
 
21
21
  it 'converts Hash keys to Ruby format' do
22
- subject.to_ruby(source).should == target
22
+ expect(subject.to_ruby(source)).to eq target
23
23
  end
24
24
 
25
25
  it 'has compatible mode' do
26
- subject.to_ruby(source, true).should == target.merge(source)
26
+ expect(subject.to_ruby(source, true)).to eq target.merge(source)
27
27
  end
28
28
 
29
29
  it 'acts idempotentely' do
30
- subject.to_ruby(target).should == target
30
+ expect(subject.to_ruby(target)).to eq target
31
31
  end
32
32
  end
33
-
34
33
  end
@@ -80,48 +80,97 @@ describe Postmark::MessageHelper do
80
80
  message.merge(:track_opens => true)
81
81
  }
82
82
 
83
+ let(:message_with_open_tracking_false) {
84
+ message.merge(:track_opens => false)
85
+ }
86
+
83
87
  let(:postmark_message_with_open_tracking) {
84
88
  postmark_message.merge("TrackOpens" => true)
85
89
  }
86
90
 
91
+ let(:postmark_message_with_open_tracking_false) {
92
+ postmark_message.merge("TrackOpens" => false)
93
+ }
94
+
87
95
  it 'converts messages without custom headers and attachments correctly' do
88
- subject.to_postmark(message).should == postmark_message
96
+ expect(subject.to_postmark(message)).to eq postmark_message
89
97
  end
90
98
 
91
99
  it 'converts messages with custom headers and without attachments correctly' do
92
- subject.to_postmark(message_with_headers).should == postmark_message_with_headers
100
+ expect(subject.to_postmark(message_with_headers)).to eq postmark_message_with_headers
93
101
  end
94
102
 
95
103
  it 'converts messages with custom headers and attachments correctly' do
96
- subject.to_postmark(message_with_headers_and_attachments).should == postmark_message_with_headers_and_attachments
104
+ expect(subject.to_postmark(message_with_headers_and_attachments)).to eq postmark_message_with_headers_and_attachments
105
+ end
106
+
107
+ context 'open tracking' do
108
+
109
+ it 'converts messages with open tracking flag set to true correctly' do
110
+ expect(subject.to_postmark(message_with_open_tracking)).to eq(postmark_message_with_open_tracking)
111
+ end
112
+
113
+ it 'converts messages with open tracking flag set to false correctly' do
114
+ expect(subject.to_postmark(message_with_open_tracking_false)).to eq(postmark_message_with_open_tracking_false)
115
+ end
116
+
97
117
  end
98
118
 
99
- it 'includes open tracking flag when specified' do
100
- expect(subject.to_postmark(message_with_open_tracking)).to eq(postmark_message_with_open_tracking)
119
+ context 'metadata' do
120
+ it 'converts messages with metadata correctly' do
121
+ metadata = {"test" => "value"}
122
+ data= message.merge(:metadata => metadata)
123
+ expect(subject.to_postmark(data)).to include(postmark_message.merge("Metadata" => metadata))
124
+ end
101
125
  end
102
126
 
127
+ context 'link tracking' do
128
+ let(:message_with_link_tracking_html) { message.merge(:track_links => :html_only) }
129
+ let(:message_with_link_tracking_text) { message.merge(:track_links => :text_only) }
130
+ let(:message_with_link_tracking_all) { message.merge(:track_links => :html_and_text) }
131
+ let(:message_with_link_tracking_none) { message.merge(:track_links => :none) }
132
+
133
+ let(:postmark_message_with_link_tracking_html) { postmark_message.merge("TrackLinks" => 'HtmlOnly') }
134
+ let(:postmark_message_with_link_tracking_text) { postmark_message.merge("TrackLinks" => 'TextOnly') }
135
+ let(:postmark_message_with_link_tracking_all) { postmark_message.merge("TrackLinks" => 'HtmlAndText') }
136
+ let(:postmark_message_with_link_tracking_none) { postmark_message.merge("TrackLinks" => 'None') }
137
+
138
+ it 'converts html body link tracking to Postmark format' do
139
+ expect(subject.to_postmark(message_with_link_tracking_html)).to eq(postmark_message_with_link_tracking_html)
140
+ end
141
+
142
+ it 'converts text body link tracking to Postmark format' do
143
+ expect(subject.to_postmark(message_with_link_tracking_text)).to eq(postmark_message_with_link_tracking_text)
144
+ end
145
+
146
+ it 'converts html and text body link tracking to Postmark format' do
147
+ expect(subject.to_postmark(message_with_link_tracking_all)).to eq(postmark_message_with_link_tracking_all)
148
+ end
149
+
150
+ it 'converts no link tracking to Postmark format' do
151
+ expect(subject.to_postmark(message_with_link_tracking_none)).to eq(postmark_message_with_link_tracking_none)
152
+ end
153
+ end
103
154
  end
104
155
 
105
156
  describe ".headers_to_postmark" do
106
157
  it 'converts headers to Postmark format' do
107
- subject.headers_to_postmark(headers).should == postmark_headers
158
+ expect(subject.headers_to_postmark(headers)).to eq postmark_headers
108
159
  end
109
160
 
110
161
  it 'accepts single header as a non-array' do
111
- subject.headers_to_postmark(headers.first).should == [postmark_headers.first]
162
+ expect(subject.headers_to_postmark(headers.first)).to eq [postmark_headers.first]
112
163
  end
113
164
  end
114
165
 
115
166
  describe ".attachments_to_postmark" do
116
-
117
167
  it 'converts attachments to Postmark format' do
118
- subject.attachments_to_postmark(attachments).should == postmark_attachments
168
+ expect(subject.attachments_to_postmark(attachments)).to eq postmark_attachments
119
169
  end
120
170
 
121
171
  it 'accepts single attachment as a non-array' do
122
- subject.attachments_to_postmark(attachments.first).should == [postmark_attachments.first]
172
+ expect(subject.attachments_to_postmark(attachments.first)).to eq [postmark_attachments.first]
123
173
  end
124
-
125
174
  end
126
175
 
127
176
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Postmark::HttpClient do
4
4
 
5
5
  def response_body(status, message = "")
6
- body = {"ErrorCode" => status, "Message" => message}.to_json
6
+ {"ErrorCode" => status, "Message" => message}.to_json
7
7
  end
8
8
 
9
9
  let(:api_token) { "provided-postmark-api-token" }
@@ -11,39 +11,40 @@ describe Postmark::HttpClient do
11
11
  subject { http_client }
12
12
 
13
13
  context "attr writers" do
14
- it { should respond_to(:api_token=) }
15
- it { should respond_to(:api_key=) }
14
+ it { expect(subject).to respond_to(:api_token=) }
15
+ it { expect(subject).to respond_to(:api_key=) }
16
16
  end
17
17
 
18
18
  context "attr readers" do
19
- it { should respond_to(:http) }
20
- it { should respond_to(:secure) }
21
- it { should respond_to(:api_token) }
22
- it { should respond_to(:api_key) }
23
- it { should respond_to(:proxy_host) }
24
- it { should respond_to(:proxy_port) }
25
- it { should respond_to(:proxy_user) }
26
- it { should respond_to(:proxy_pass) }
27
- it { should respond_to(:host) }
28
- it { should respond_to(:port) }
29
- it { should respond_to(:path_prefix) }
30
- it { should respond_to(:http_open_timeout) }
31
- it { should respond_to(:http_read_timeout) }
19
+ it { expect(subject).to respond_to(:http) }
20
+ it { expect(subject).to respond_to(:secure) }
21
+ it { expect(subject).to respond_to(:api_token) }
22
+ it { expect(subject).to respond_to(:api_key) }
23
+ it { expect(subject).to respond_to(:proxy_host) }
24
+ it { expect(subject).to respond_to(:proxy_port) }
25
+ it { expect(subject).to respond_to(:proxy_user) }
26
+ it { expect(subject).to respond_to(:proxy_pass) }
27
+ it { expect(subject).to respond_to(:host) }
28
+ it { expect(subject).to respond_to(:port) }
29
+ it { expect(subject).to respond_to(:path_prefix) }
30
+ it { expect(subject).to respond_to(:http_open_timeout) }
31
+ it { expect(subject).to respond_to(:http_read_timeout) }
32
+ it { expect(subject).to respond_to(:http_ssl_version) }
32
33
  end
33
34
 
34
35
  context "when it is created without options" do
35
- its(:api_token) { should eq api_token }
36
- its(:api_key) { should eq api_token }
37
- its(:host) { should eq 'api.postmarkapp.com' }
38
- its(:port) { should eq 443 }
39
- its(:secure) { should be_true }
40
- its(:path_prefix) { should eq '/' }
41
- its(:http_read_timeout) { should eq 15 }
42
- its(:http_open_timeout) { should eq 5 }
43
-
44
- it 'uses TLS encryption', :skip_ruby_version => ['1.8.7'] do
36
+ its(:api_token) { is_expected.to eq api_token }
37
+ its(:api_key) { is_expected.to eq api_token }
38
+ its(:host) { is_expected.to eq 'api.postmarkapp.com' }
39
+ its(:port) { is_expected.to eq 443 }
40
+ its(:secure) { is_expected.to be true }
41
+ its(:path_prefix) { is_expected.to eq '/' }
42
+ its(:http_read_timeout) { is_expected.to eq 15 }
43
+ its(:http_open_timeout) { is_expected.to eq 5 }
44
+
45
+ it 'does not provide a default which utilizes the Net::HTTP default', :skip_ruby_version => ['1.8.7'] do
45
46
  http_client = subject.http
46
- http_client.ssl_version.should == :TLSv1
47
+ expect(http_client.ssl_version).to eq nil
47
48
  end
48
49
  end
49
50
 
@@ -54,10 +55,11 @@ describe Postmark::HttpClient do
54
55
  let(:proxy_user) { "provided proxy user" }
55
56
  let(:proxy_pass) { "provided proxy pass" }
56
57
  let(:host) { "providedhostname.org" }
57
- let(:port) { 443 }
58
+ let(:port) { 4443 }
58
59
  let(:path_prefix) { "/provided/path/prefix" }
59
60
  let(:http_open_timeout) { 42 }
60
61
  let(:http_read_timeout) { 42 }
62
+ let(:http_ssl_version) { :TLSv1_2}
61
63
 
62
64
  subject { Postmark::HttpClient.new(api_token,
63
65
  :secure => secure,
@@ -69,20 +71,36 @@ describe Postmark::HttpClient do
69
71
  :port => port,
70
72
  :path_prefix => path_prefix,
71
73
  :http_open_timeout => http_open_timeout,
72
- :http_read_timeout => http_read_timeout) }
73
-
74
- its(:api_token) { should eq api_token }
75
- its(:api_key) { should eq api_token }
76
- its(:secure) { should == secure }
77
- its(:proxy_host) { should == proxy_host }
78
- its(:proxy_port) { should == proxy_port }
79
- its(:proxy_user) { should == proxy_user }
80
- its(:proxy_pass) { should == proxy_pass }
81
- its(:host) { should == host }
82
- its(:port) { should == port }
83
- its(:path_prefix) { should == path_prefix }
84
- its(:http_open_timeout) { should == http_open_timeout }
85
- its(:http_read_timeout) { should == http_read_timeout }
74
+ :http_read_timeout => http_read_timeout,
75
+ :http_ssl_version => http_ssl_version) }
76
+
77
+ its(:api_token) { is_expected.to eq api_token }
78
+ its(:api_key) { is_expected.to eq api_token }
79
+ its(:secure) { is_expected.to eq secure }
80
+ its(:proxy_host) { is_expected.to eq proxy_host }
81
+ its(:proxy_port) { is_expected.to eq proxy_port }
82
+ its(:proxy_user) { is_expected.to eq proxy_user }
83
+ its(:proxy_pass) { is_expected.to eq proxy_pass }
84
+ its(:host) { is_expected.to eq host }
85
+ its(:port) { is_expected.to eq port }
86
+ its(:path_prefix) { is_expected.to eq path_prefix }
87
+ its(:http_open_timeout) { is_expected.to eq http_open_timeout }
88
+ its(:http_read_timeout) { is_expected.to eq http_read_timeout }
89
+ its(:http_ssl_version) { is_expected.to eq http_ssl_version }
90
+
91
+ it 'uses port 80 for plain HTTP connections' do
92
+ expect(Postmark::HttpClient.new(api_token, :secure => false).port).to eq(80)
93
+ end
94
+
95
+ it 'uses port 443 for secure HTTP connections' do
96
+ expect(Postmark::HttpClient.new(api_token, :secure => true).port).to eq(443)
97
+ end
98
+
99
+ it 'respects port over secure option' do
100
+ client = Postmark::HttpClient.new(api_token, :port => 80, :secure => true)
101
+ expect(client.port).to eq(80)
102
+ expect(client.protocol).to eq('https')
103
+ end
86
104
  end
87
105
 
88
106
  describe "#post" do
@@ -92,18 +110,17 @@ describe Postmark::HttpClient do
92
110
  it "sends a POST request to provided URI" do
93
111
  FakeWeb.register_uri(:post, target_url, :body => response_body(200))
94
112
  subject.post(target_path)
95
- FakeWeb.should have_requested(:post, target_url)
113
+ expect(FakeWeb.last_request.method).to eq('POST')
114
+ expect(FakeWeb.last_request.path).to eq('/' + target_path)
96
115
  end
97
116
 
98
117
  it "raises a custom error when API token authorization fails" do
99
- FakeWeb.register_uri(:post, target_url, :body => response_body(401),
100
- :status => [ "401", "Unauthorized" ])
118
+ FakeWeb.register_uri(:post, target_url, :body => response_body(401), :status => [ "401", "Unauthorized" ])
101
119
  expect { subject.post(target_path) }.to raise_error Postmark::InvalidApiKeyError
102
120
  end
103
121
 
104
122
  it "raises a custom error when sent JSON was not valid" do
105
- FakeWeb.register_uri(:post, target_url, :body => response_body(422),
106
- :status => [ "422", "Invalid" ])
123
+ FakeWeb.register_uri(:post, target_url, :body => response_body(422), :status => [ "422", "Invalid" ])
107
124
  expect { subject.post(target_path) }.to raise_error Postmark::InvalidMessageError
108
125
  end
109
126
 
@@ -114,8 +131,7 @@ describe Postmark::HttpClient do
114
131
  end
115
132
 
116
133
  it "raises a custom error when the request times out" do
117
- subject.http.should_receive(:post).at_least(:once).
118
- and_raise(Timeout::Error)
134
+ expect(subject.http).to receive(:post).at_least(:once).and_raise(Timeout::Error)
119
135
  expect { subject.post(target_path) }.to raise_error Postmark::TimeoutError
120
136
  end
121
137
 
@@ -124,7 +140,7 @@ describe Postmark::HttpClient do
124
140
  :status => [ "485", "Custom HTTP response status" ])
125
141
  expect { subject.post(target_path) }.to raise_error Postmark::UnknownError
126
142
  end
127
-
143
+
128
144
  end
129
145
 
130
146
  describe "#get" do
@@ -134,18 +150,17 @@ describe Postmark::HttpClient do
134
150
  it "sends a GET request to provided URI" do
135
151
  FakeWeb.register_uri(:get, target_url, :body => response_body(200))
136
152
  subject.get(target_path)
137
- FakeWeb.should have_requested(:get, target_url)
153
+ expect(FakeWeb.last_request.method).to eq('GET')
154
+ expect(FakeWeb.last_request.path).to eq('/' + target_path)
138
155
  end
139
156
 
140
157
  it "raises a custom error when API token authorization fails" do
141
- FakeWeb.register_uri(:get, target_url, :body => response_body(401),
142
- :status => [ "401", "Unauthorized" ])
158
+ FakeWeb.register_uri(:get, target_url, :body => response_body(401), :status => [ "401", "Unauthorized" ])
143
159
  expect { subject.get(target_path) }.to raise_error Postmark::InvalidApiKeyError
144
160
  end
145
161
 
146
162
  it "raises a custom error when sent JSON was not valid" do
147
- FakeWeb.register_uri(:get, target_url, :body => response_body(422),
148
- :status => [ "422", "Invalid" ])
163
+ FakeWeb.register_uri(:get, target_url, :body => response_body(422), :status => [ "422", "Invalid" ])
149
164
  expect { subject.get(target_path) }.to raise_error Postmark::InvalidMessageError
150
165
  end
151
166
 
@@ -156,7 +171,7 @@ describe Postmark::HttpClient do
156
171
  end
157
172
 
158
173
  it "raises a custom error when the request times out" do
159
- subject.http.should_receive(:get).at_least(:once).and_raise(Timeout::Error)
174
+ expect(subject.http).to receive(:get).at_least(:once).and_raise(Timeout::Error)
160
175
  expect { subject.get(target_path) }.to raise_error Postmark::TimeoutError
161
176
  end
162
177
 
@@ -165,7 +180,7 @@ describe Postmark::HttpClient do
165
180
  :status => [ "485", "Custom HTTP response status" ])
166
181
  expect { subject.get(target_path) }.to raise_error Postmark::UnknownError
167
182
  end
168
-
183
+
169
184
  end
170
185
 
171
186
  describe "#put" do
@@ -175,7 +190,8 @@ describe Postmark::HttpClient do
175
190
  it "sends a PUT request to provided URI" do
176
191
  FakeWeb.register_uri(:put, target_url, :body => response_body(200))
177
192
  subject.put(target_path)
178
- FakeWeb.should have_requested(:put, target_url)
193
+ expect(FakeWeb.last_request.method).to eq('PUT')
194
+ expect(FakeWeb.last_request.path).to eq('/' + target_path)
179
195
  end
180
196
 
181
197
  it "raises a custom error when API token authorization fails" do
@@ -197,7 +213,7 @@ describe Postmark::HttpClient do
197
213
  end
198
214
 
199
215
  it "raises a custom error when the request times out" do
200
- subject.http.should_receive(:put).at_least(:once).and_raise(Timeout::Error)
216
+ expect(subject.http).to receive(:put).at_least(:once).and_raise(Timeout::Error)
201
217
  expect { subject.put(target_path) }.to raise_error Postmark::TimeoutError
202
218
  end
203
219
 
@@ -206,6 +222,5 @@ describe Postmark::HttpClient do
206
222
  :status => [ "485", "Custom HTTP response status" ])
207
223
  expect { subject.put(target_path) }.to raise_error Postmark::UnknownError
208
224
  end
209
-
210
225
  end
211
- end
226
+ end
@@ -7,81 +7,81 @@ describe Postmark::Inbound do
7
7
  context "given a serialized inbound document" do
8
8
  subject { Postmark::Inbound.to_ruby_hash(example_inbound) }
9
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) }
10
+ it { expect(subject).to have_key(:from) }
11
+ it { expect(subject).to have_key(:from_full) }
12
+ it { expect(subject).to have_key(:to) }
13
+ it { expect(subject).to have_key(:to_full) }
14
+ it { expect(subject).to have_key(:cc) }
15
+ it { expect(subject).to have_key(:cc_full) }
16
+ it { expect(subject).to have_key(:reply_to) }
17
+ it { expect(subject).to have_key(:subject) }
18
+ it { expect(subject).to have_key(:message_id) }
19
+ it { expect(subject).to have_key(:date) }
20
+ it { expect(subject).to have_key(:mailbox_hash) }
21
+ it { expect(subject).to have_key(:text_body) }
22
+ it { expect(subject).to have_key(:html_body) }
23
+ it { expect(subject).to have_key(:tag) }
24
+ it { expect(subject).to have_key(:headers) }
25
+ it { expect(subject).to have_key(:attachments) }
26
26
 
27
27
  context "cc" do
28
28
  it 'has 2 CCs' do
29
- subject[:cc_full].count.should == 2
29
+ expect(subject[:cc_full].count).to eq 2
30
30
  end
31
31
 
32
32
  it 'stores CCs as an array of Ruby hashes' do
33
33
  cc = subject[:cc_full].last
34
- cc.should have_key(:email)
35
- cc.should have_key(:name)
34
+ expect(cc).to have_key(:email)
35
+ expect(cc).to have_key(:name)
36
36
  end
37
37
  end
38
38
 
39
39
  context "to" do
40
40
  it 'has 1 recipients' do
41
- subject[:to_full].count.should == 1
41
+ expect(subject[:to_full].count).to eq 1
42
42
  end
43
43
 
44
44
  it 'stores TOs as an array of Ruby hashes' do
45
45
  cc = subject[:to_full].last
46
- cc.should have_key(:email)
47
- cc.should have_key(:name)
46
+ expect(cc).to have_key(:email)
47
+ expect(cc).to have_key(:name)
48
48
  end
49
49
  end
50
50
 
51
51
  context "from" do
52
52
  it 'is a hash' do
53
- subject[:from_full].should be_a Hash
53
+ expect(subject[:from_full]).to be_a Hash
54
54
  end
55
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)
56
+ it 'has all required fields' do
57
+ expect(subject[:from_full]).to have_key(:email)
58
+ expect(subject[:from_full]).to have_key(:name)
59
59
  end
60
60
  end
61
61
 
62
62
  context "headers" do
63
63
  it 'has 8 headers' do
64
- subject[:headers].count.should == 8
64
+ expect(subject[:headers].count).to eq 8
65
65
  end
66
66
 
67
67
  it 'stores headers as an array of Ruby hashes' do
68
68
  header = subject[:headers].last
69
- header.should have_key(:name)
70
- header.should have_key(:value)
69
+ expect(header).to have_key(:name)
70
+ expect(header).to have_key(:value)
71
71
  end
72
72
  end
73
73
 
74
74
  context "attachments" do
75
75
  it 'has 2 attachments' do
76
- subject[:attachments].count.should == 2
76
+ expect(subject[:attachments].count).to eq 2
77
77
  end
78
78
 
79
79
  it 'stores attachemnts as an array of Ruby hashes' do
80
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)
81
+ expect(attachment).to have_key(:name)
82
+ expect(attachment).to have_key(:content)
83
+ expect(attachment).to have_key(:content_type)
84
+ expect(attachment).to have_key(:content_length)
85
85
  end
86
86
  end
87
87
  end