dotmailer 0.0.1 → 0.0.2

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.
@@ -0,0 +1,173 @@
1
+ require 'spec_helper'
2
+
3
+ describe DotMailer::ContactImport do
4
+ let(:client) { double 'client' }
5
+ let(:account) { double 'account', :client => client }
6
+
7
+ let(:contacts) do
8
+ [
9
+ { 'Email' => 'john.doe@example.com' }
10
+ ]
11
+ end
12
+
13
+ describe 'Class' do
14
+ subject { DotMailer::ContactImport }
15
+
16
+ describe '.import' do
17
+ let(:contact_import) { double 'contact import', :start => double }
18
+
19
+ before(:each) do
20
+ subject.stub :new => contact_import
21
+ end
22
+
23
+ it 'should create a new instance with the account and contacts' do
24
+ subject.should_receive(:new).with(account, contacts)
25
+
26
+ subject.import account, contacts
27
+ end
28
+
29
+ it 'should start the new contact import' do
30
+ contact_import.should_receive :start
31
+
32
+ subject.import account, contacts
33
+ end
34
+
35
+ it 'should return the contact import' do
36
+ subject.import(account, contacts).should == contact_import
37
+ end
38
+ end
39
+ end
40
+
41
+ subject { DotMailer::ContactImport.new(account, contacts) }
42
+
43
+ its(:id) { should be_nil }
44
+
45
+ describe '#start' do
46
+ before(:each) do
47
+ account.stub :data_fields => [double('data field', :name => 'CODE')]
48
+ end
49
+
50
+ context 'when the contacts include a non existent data field' do
51
+ let(:data_field_name) { 'UNKNOWN' }
52
+
53
+ let(:contacts) do
54
+ [
55
+ { 'Email' => 'john.doe@example.com', data_field_name => 'some value' }
56
+ ]
57
+ end
58
+
59
+ it 'should raise an UnknownDataField error with the data field name' do
60
+ expect { subject.start }.to raise_error(DotMailer::UnknownDataField, data_field_name)
61
+ end
62
+ end
63
+
64
+ let(:contacts_csv) { "Email\njohn.doe@example.com\n" }
65
+ let(:id) { double 'id' }
66
+ let(:response) { { 'id' => id, 'status' => 'NotFinished' } }
67
+
68
+ before(:each) do
69
+ client.stub :post_csv => response
70
+ end
71
+
72
+ it 'should call post_csv on the client with the contacts in CSV format' do
73
+ client.should_receive(:post_csv).with('/contacts/import', contacts_csv)
74
+
75
+ subject.start
76
+ end
77
+
78
+ it 'should set the id from the response' do
79
+ subject.start
80
+ subject.id.should == id
81
+ end
82
+ end
83
+
84
+ describe '#status' do
85
+ before(:each) do
86
+ subject.stub :id => id
87
+ end
88
+
89
+ context 'when the import has not started' do
90
+ let(:id) { nil }
91
+
92
+ its(:status) { should == 'NotStarted' }
93
+ end
94
+
95
+ context 'when the import has started' do
96
+ let(:id) { '12345' }
97
+ let(:status) { double 'status' }
98
+ let(:response) { { 'id' => id, 'status' => status } }
99
+
100
+ before(:each) do
101
+ client.stub :get => response
102
+ end
103
+
104
+ it 'should get the status from the client' do
105
+ client.should_receive(:get).with("/contacts/import/#{id}")
106
+
107
+ subject.status
108
+ end
109
+
110
+ it 'should return the status from the client' do
111
+ subject.status.should == status
112
+ end
113
+ end
114
+ end
115
+
116
+ describe '#finished?' do
117
+ context 'when the import status is not "Finished"' do
118
+ before(:each) do
119
+ subject.stub :status => 'NotFinished'
120
+ end
121
+
122
+ specify { subject.should_not be_finished }
123
+ end
124
+
125
+ context 'when the import status is "Finished"' do
126
+ before(:each) do
127
+ subject.stub :status => 'Finished'
128
+ end
129
+
130
+ specify { subject.should be_finished }
131
+ end
132
+ end
133
+
134
+ describe '#errors' do
135
+ let(:id) { '12345' }
136
+
137
+ before(:each) do
138
+ subject.stub :id => id
139
+ end
140
+
141
+ context 'when the import has no yet finished' do
142
+ before(:each) do
143
+ subject.stub :finished? => false
144
+ end
145
+
146
+ it 'should raise an ImportNotFinished error' do
147
+ expect { subject.errors }.to raise_error(DotMailer::ImportNotFinished)
148
+ end
149
+ end
150
+
151
+ context 'when the import has finished' do
152
+ before(:each) do
153
+ subject.stub :finished? => true
154
+ end
155
+
156
+ let(:errors) { double 'errors' }
157
+
158
+ before(:each) do
159
+ client.stub :get_csv => errors
160
+ end
161
+
162
+ it 'should call get_csv on the client with the import id in the path' do
163
+ client.should_receive(:get_csv).with("/contacts/import/#{id}/report-faults")
164
+
165
+ subject.errors
166
+ end
167
+
168
+ it 'should return the status from the client' do
169
+ subject.errors.should == errors
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,303 @@
1
+ require 'spec_helper'
2
+
3
+ describe DotMailer::Contact do
4
+ let(:client) { double 'client' }
5
+ let(:account) { double 'account', :client => client }
6
+
7
+ describe 'Class' do
8
+ subject { DotMailer::Contact }
9
+
10
+ describe '.find_by_email' do
11
+ let(:email) { 'john.doe@example.com' }
12
+ let(:response) { double 'response' }
13
+ let(:contact) { double 'contact' }
14
+
15
+ before(:each) do
16
+ client.stub :get => response
17
+ subject.stub :new => contact
18
+ end
19
+
20
+ it 'should get the contact from the client' do
21
+ client.should_receive(:get).with("/contacts/#{email}")
22
+
23
+ subject.find_by_email account, email
24
+ end
25
+
26
+ it 'should initialize a new Contact with the response from the client' do
27
+ subject.should_receive(:new).with(account, response)
28
+
29
+ subject.find_by_email account, email
30
+ end
31
+
32
+ it 'should return the new Contact object' do
33
+ subject.find_by_email(account, email).should == contact
34
+ end
35
+
36
+ context 'when the contact doesnt exist' do
37
+ before(:each) do
38
+ client.stub(:get).and_raise(DotMailer::NotFound)
39
+ end
40
+
41
+ it 'should return nil' do
42
+ subject.find_by_email(account, email).should be_nil
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '.find_by_id' do
48
+ let(:id) { 123 }
49
+ let(:contact) { double 'contact' }
50
+
51
+ before(:each) do
52
+ subject.stub :find_by_email => contact
53
+ end
54
+
55
+ it 'should call find_by_email with the id' do
56
+ subject.should_receive(:find_by_email).with(account, id)
57
+
58
+ subject.find_by_id account, id
59
+ end
60
+
61
+ it 'should return the contact from find_by_email' do
62
+ subject.find_by_id(account, id).should == contact
63
+ end
64
+ end
65
+
66
+ describe '.modified_since' do
67
+ let(:time) { Time.parse('1st March 2013 15:30:45 +00:00') }
68
+ let(:attributes) { double 'attributes' }
69
+ let(:response) { 3.times.map { attributes } }
70
+ let(:contact) { double 'contact' }
71
+
72
+ before(:each) do
73
+ client.stub :get => response
74
+ subject.stub :new => contact
75
+ end
76
+
77
+ it 'should call get on the client with a path containing the time in UTC XML schema format' do
78
+ client.should_receive(:get).with('/contacts/modified-since/2013-03-01T15:30:45Z')
79
+
80
+ subject.modified_since(account, time)
81
+ end
82
+
83
+ it 'should initialize some contacts' do
84
+ subject.should_receive(:new).exactly(3).times.with(account, attributes)
85
+
86
+ subject.modified_since(account, time)
87
+ end
88
+
89
+ it 'should return the contacts' do
90
+ subject.modified_since(account, time).should == 3.times.map { contact }
91
+ end
92
+ end
93
+ end
94
+
95
+ let(:id) { double 'id' }
96
+ let(:email) { double 'email' }
97
+ let(:opt_in_type) { double 'opt in type' }
98
+ let(:email_type) { double 'email type' }
99
+ let(:status) { double 'status' }
100
+
101
+ let(:attributes) do
102
+ {
103
+ 'id' => id,
104
+ 'email' => email,
105
+ 'optInType' => opt_in_type,
106
+ 'emailType' => email_type,
107
+ 'status' => status
108
+ }
109
+ end
110
+
111
+ subject { DotMailer::Contact.new(account, attributes) }
112
+
113
+ its(:id) { should == id }
114
+ its(:email) { should == email }
115
+ its(:opt_in_type) { should == opt_in_type }
116
+ its(:email_type) { should == email_type }
117
+ its(:status) { should == status }
118
+
119
+ it_should_have_assignable_attributes :email, :email_type
120
+
121
+ describe '#opt_in_type=' do
122
+ let(:value) { 'some opt in type' }
123
+
124
+ context 'when the opt in type exists' do
125
+ before(:each) do
126
+ DotMailer::OptInType.stub :exists? => true
127
+ end
128
+
129
+ it 'should change the opt in type' do
130
+ expect { subject.opt_in_type = value }.to \
131
+ change { subject.opt_in_type }.to(value)
132
+ end
133
+ end
134
+
135
+ context 'when the opt in type doesnt exist' do
136
+ before(:each) do
137
+ DotMailer::OptInType.stub :exists? => false
138
+ end
139
+
140
+ it 'should raise an UnknownOptInType error with the value' do
141
+ expect { subject.opt_in_type = value }.to \
142
+ raise_error(DotMailer::UnknownOptInType, value)
143
+ end
144
+ end
145
+ end
146
+
147
+ describe '#[]' do
148
+ let(:data_fields) { {} }
149
+
150
+ before(:each) do
151
+ subject.stub :data_fields => data_fields
152
+ end
153
+
154
+ context 'when the data field doesnt exist' do
155
+ let(:key) { 'UNKNOWN' }
156
+
157
+ it 'should raise an UnknownDataField error' do
158
+ expect { subject[key] }.to raise_error(DotMailer::UnknownDataField)
159
+ end
160
+ end
161
+
162
+ context 'when the data field does exist' do
163
+ let(:key) { double 'key' }
164
+ let(:value) { double 'value' }
165
+ let(:data_fields) { { key => value } }
166
+
167
+ specify { subject[key].should == value }
168
+ end
169
+ end
170
+
171
+ describe '#[]=' do
172
+ let(:new_value) { double 'new value' }
173
+
174
+ let(:data_fields) { {} }
175
+
176
+ before(:each) do
177
+ subject.stub :data_fields => data_fields
178
+ end
179
+
180
+ context 'when the data field doesnt exist' do
181
+ let(:key) { 'UNKNOWN' }
182
+
183
+ it 'should raise an UnknownDataField error' do
184
+ expect { subject[key] = new_value }.to raise_error(DotMailer::UnknownDataField)
185
+ end
186
+ end
187
+
188
+ context 'when the data field does exist' do
189
+ let(:key) { double 'key' }
190
+ let(:old_value) { double 'old value' }
191
+ let(:data_fields) { { key => old_value } }
192
+
193
+ specify do
194
+ expect { subject[key] = new_value }.to \
195
+ change { subject[key] }.from(old_value).to(new_value)
196
+ end
197
+ end
198
+ end
199
+
200
+ describe '#save' do
201
+ let(:id) { '12345' }
202
+ let(:key) { double 'key' }
203
+ let(:value) { 'some value' }
204
+ let(:data_fields) { { key => value } }
205
+
206
+ before(:each) do
207
+ client.stub :put_json
208
+ subject.stub :data_fields => data_fields
209
+ end
210
+
211
+ it 'should call put_json on the client with the id path' do
212
+ client.should_receive(:put_json).with("/contacts/#{id}", anything)
213
+
214
+ subject.save
215
+ end
216
+
217
+ it 'should call put_json on the client with the attributes in the correct format' do
218
+ client.should_receive(:put_json).with(anything, {
219
+ 'id' => id,
220
+ 'email' => email,
221
+ 'optInType' => opt_in_type,
222
+ 'emailType' => email_type,
223
+ 'status' => status,
224
+ 'dataFields' => [
225
+ { 'key' => key, 'value' => value }
226
+ ]
227
+ })
228
+
229
+ subject.save
230
+ end
231
+ end
232
+
233
+ describe '#subscribed?' do
234
+ context 'when the status is the SUBSCRIBED_STATUS' do
235
+ let(:status) { DotMailer::SUBSCRIBED_STATUS }
236
+
237
+ it { should be_subscribed }
238
+ end
239
+
240
+ context 'when the status is not the SUBSCRIBED_STATUS' do
241
+ let(:status) { 'Unsubscribed' }
242
+
243
+ it { should_not be_subscribed }
244
+ end
245
+ end
246
+
247
+ describe '#resubscribe' do
248
+ let(:return_url) { 'some return url' }
249
+ let(:client) { double 'client' }
250
+
251
+ before(:each) do
252
+ subject.stub :client => client
253
+ end
254
+
255
+ context 'when the contact is already subscribed' do
256
+ before(:each) do
257
+ subject.stub :subscribed? => true
258
+ end
259
+
260
+ it 'should not call put_json on the client' do
261
+ client.should_not_receive(:put_json)
262
+
263
+ subject.resubscribe return_url
264
+ end
265
+
266
+ it 'should return false' do
267
+ subject.resubscribe(return_url).should be_false
268
+ end
269
+ end
270
+
271
+ context 'when the contact is not subscribed' do
272
+ before(:each) do
273
+ client.stub :post_json
274
+ subject.stub :subscribed? => false
275
+ end
276
+
277
+ it 'should call post_json on the client with the correct path' do
278
+ client.should_receive(:post_json).with("/contacts/resubscribe", anything)
279
+
280
+ subject.resubscribe return_url
281
+ end
282
+
283
+ it 'should call post_json on the client with the contacts id and email address' do
284
+ client.should_receive(:post_json).with anything, hash_including(
285
+ 'UnsubscribedContact' => {
286
+ 'id' => id,
287
+ 'Email' => email
288
+ }
289
+ )
290
+
291
+ subject.resubscribe return_url
292
+ end
293
+
294
+ it 'should call post_json on the client with the return url' do
295
+ client.should_receive(:post_json).with anything, hash_including(
296
+ 'ReturnUrlToUseIfChallenged' => return_url
297
+ )
298
+
299
+ subject.resubscribe return_url
300
+ end
301
+ end
302
+ end
303
+ end