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
@@ -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