osm 1.2.24 → 1.2.25

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,330 @@
1
+ module Osm
2
+
3
+ class Myscout
4
+
5
+ class ParentLoginHistory < Osm::Model
6
+ SORT_BY= [:last_name, :first_name, :member_id]
7
+
8
+ # @!attribute [rw] member_id
9
+ # @return [Fixnum] the id for the member
10
+ # @!attribute [rw] first_name
11
+ # @return [String] the member's first name
12
+ # @!attribute [rw] last_name
13
+ # @return [String] the member's last name
14
+ # @!attribute [rw] logins
15
+ # @return [Fixnum] the total number of logins
16
+ # @!attribute [rw] last_login
17
+ # @return [DateTime] the time and date of the last login
18
+
19
+ attribute :member_id, type: Integer
20
+ attribute :first_name, type: String
21
+ attribute :last_name, type: String
22
+ attribute :logins, type: Integer
23
+ attribute :last_login, type: DateTime
24
+
25
+ if ActiveModel::VERSION::MAJOR < 4
26
+ attr_accessible :member_id, :first_name, :last_name, :logins, :last_login
27
+ end
28
+
29
+ validates_presence_of :first_name
30
+ validates_presence_of :last_name
31
+ validates_numericality_of :member_id, only_integer: true, greater_than: 0
32
+ validates_numericality_of :logins, only_integer: true, greater_than_or_equal_to: 0
33
+
34
+
35
+ # @!method initialize
36
+ # Initialize a new Member
37
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
38
+
39
+
40
+ # Get parent login history
41
+ # @param [Osm::Api] api The api to use to make the request
42
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get login history for
43
+ # @!macro options_get
44
+ # @return [Array<Osm::Myscout::ParentLoginHistory>]
45
+ def self.get_for_section(api, section, options={})
46
+ section_id = section.to_i
47
+ require_ability_to(api, :read, :member, section, options)
48
+ cache_key = ['myscout', 'parent_login_history', section_id]
49
+
50
+ if !options[:no_cache] && cache_exist?(api, cache_key)
51
+ return cache_read(api, cache_key)
52
+ end
53
+
54
+ data = api.perform_query("ext/settings/parents/loginhistory/?action=getLoginHistory&sectionid=#{section_id}")
55
+ return [] unless data.is_a?(Hash)
56
+ data = data['items']
57
+ return [] unless data.is_a?(Array)
58
+
59
+ data.map! do |item|
60
+ new(
61
+ member_id: Osm::to_i_or_nil(item['scoutid']),
62
+ first_name: item['firstname'],
63
+ last_name: item['lastname'],
64
+ logins: Osm::to_i_or_nil(item['numlogins']),
65
+ last_login: get_last_login_date(item['lastlogin'],)
66
+ )
67
+ end
68
+
69
+ cache_write(api, cache_key, data)
70
+ return data
71
+ end
72
+
73
+ private
74
+ def self.get_last_login_date(date_str)
75
+ return nil if date_str.nil?
76
+ return nil if date_str.eql?('Invitation not sent')
77
+ Time.strptime(date_str, '%d/%m/%Y %H:%M')
78
+ end
79
+
80
+ end # class Myscout::ParentLoginHistory
81
+
82
+
83
+ class Template < Osm::Model
84
+ SORT_BY = [:key]
85
+
86
+ TEMPLATES = [
87
+ {title: "First payment email", id: "email-first", description: "This email is sent to the parents the first time that you request a payment from them. The message should introduce the system to them, explain the benefits that the parents and you get, and provide account details (by using the tags).", tags:[
88
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
89
+ {id: "SCHEDULE_NAME", required: true, description: "The name of the first payment schedule that you have asked the parents to pay."},
90
+ {id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the first payment schedule that you have asked the parents to pay."},
91
+ {id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
92
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
93
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
94
+ ]},
95
+ {title: "New schedule", id: "email-subsequent", description: "This email is sent every time you request the parents sign up to a payment schedule.", tags:[
96
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
97
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
98
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
99
+ {id: "SCHEDULE_NAME", required: true, description: "The name of the payment schedule that you have asked the parents to pay."},
100
+ {id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
101
+ {id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
102
+ ]},
103
+ {title: "New payment (direct debit already setup)", id: "email-specificpayment-dd", description: "This email is sent to parents (who have already set up a direct debit) when their child has been set to pay a payment on a schedule that contains optional payments (i.e. events). It should simply notify them of the upcoming payment and give a link to the system.", tags:[
104
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
105
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
106
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
107
+ {id: "PAYMENT_NAME", required: true, description: "The name of the specific payment (this is different to the schedule name)."},
108
+ {id: "PAYMENT_DATE", required: true, description: "The date the payment process will be initiated."},
109
+ {id: "PAYMENT_AMOUNT", required: true, description: "The amount that will be taken (a pound sign is automatically inserted)."},
110
+ {id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
111
+ {id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
112
+ {id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
113
+ ]},
114
+ {title: "Payment notification for overdue payment", id: "email-immediatepayment-dd", description: "This email is sent to parents who have an active direct debit when their child has been marked as requiring a payment in the past to let them know that they are being charged immediately.", tags:[
115
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
116
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
117
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
118
+ {id: "PAYMENT_NAME", required: true, description: "The name of the specific payment (this is different to the schedule name)."},
119
+ {id: "PAYMENT_DATE", required: false, description: "The date the payment process will be initiated."},
120
+ {id: "PAYMENT_AMOUNT", required: true, description: "The amount that will be taken (a pound sign is automatically inserted)."},
121
+ {id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
122
+ {id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
123
+ {id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
124
+ ]},
125
+ {title: "Immediate payment request for overdue payment", id: "email-immediatepayment-nodd", description: "This email is sent to parents who have not got an active direct debit when their child has been marked as requiring a payment in the past to let them know that they need to pay immediately.", tags:[
126
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
127
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
128
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
129
+ {id: "PAYMENT_NAME", required: true, description: "The name of the specific payment (this is different to the schedule name)."},
130
+ {id: "PAYMENT_DATE", required: false, description: "The date the payment process will be initiated."},
131
+ {id: "PAYMENT_AMOUNT", required: true, description: "The amount that will be taken (a pound sign is automatically inserted)."},
132
+ {id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
133
+ {id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
134
+ {id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
135
+ ]},
136
+ {title: "New payment (direct debit not setup)", id: "email-specificpayment-nodd", description: "This email is sent to parents (who have *not* set up a direct debit) when their child has been asked to pay for an individual entry on a schedule. The message should ask the parents to sign up to a direct debit, or optionally, remind them to pay you via cash/cheque etc.", tags:[
137
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
138
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
139
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
140
+ {id: "PAYMENT_NAME", required: true, description: "The name of the specific payment (this is different to the schedule name)."},
141
+ {id: "PAYMENT_DATE", required: true, description: "The date the payment is due."},
142
+ {id: "PAYMENT_AMOUNT", required: true, description: "The amount that will be taken (a pound sign is automatically inserted)."},
143
+ {id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
144
+ {id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
145
+ {id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
146
+ ]},
147
+ {title: "Payment initiated", id: "email-initiated", description: "This email is sent to parents when a payment is initiated by the system.", tags:[
148
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
149
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
150
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
151
+ {id: "PAYMENT_NAME", required: false, description: "The name of the specific payment (this is different to the schedule name)."},
152
+ {id: "PAYMENT_DATE", required: false, description: "The date the payment is due."},
153
+ {id: "PAYMENT_AMOUNT", required: false, description: "The amount that will be taken (a pound sign is automatically inserted)."},
154
+ {id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
155
+ {id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
156
+ {id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
157
+ ]},
158
+ {title: "Payment reminder", id: "email-paymentreminder", description: "This is send periodically after the due date when the payment has not been made. The frequency of the emails is configurable in the My.SCOUT section of the site.", tags:[
159
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
160
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
161
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
162
+ {id: "PAYMENT_NAME", required: false, description: "The name of the specific payment (this is different to the schedule name)."},
163
+ {id: "PAYMENT_DATE", required: false, description: "The date the payment is due."},
164
+ {id: "PAYMENT_AMOUNT", required: false, description: "The amount that will be taken (a pound sign is automatically inserted)."},
165
+ {id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
166
+ {id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
167
+ {id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
168
+ ]},
169
+ {title: "Introduction to payment system", id: "website-payments-index", description: "This text is shown on the parent website under the words \"What is this?\". It should be used to explain about this system and the benefits that the parents and leaders will get, and reassure the parents that it is a safe and secure system.", tags:[]},
170
+ {title: "Instructions to click Pay Now/Subscribe", id: "website-payments-schedule", description: "This text is shown on the parent website on a payment schedules pages, above the subscribe button. It should direct the parents to click the Subscribe button to set up a direct debit, or Pay falsew buttons to pay for things individually.", tags:[]},
171
+ {title: "Event invitation", id: "email-event", description: "This email is sent to the parents when you invite children to events in the Your Events area.", tags:[
172
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
173
+ {id: "EVENT_NAME", required: false, description: "The name of the event"},
174
+ {id: "EVENT_LOCATION", required: false, description: "The location of the event"},
175
+ {id: "EVENT_COST", required: false, description: "The cost of the event"},
176
+ {id: "EVENT_DATES", required: false, description: "The event dates - this will be formatted properly into \"DATE\", \"DATE at TIME\", \"From DATE to DATE\", \"From DATE at TIME to DATE at TIME\" etc."},
177
+ {id: "EVENT_DETAILS", required: false, description: "This is the \"Details for My.SCOUT\" section of the event"},
178
+ {id: "CONFIRMATION_DEADLINE", required: false, description: "The confirmation deadline - beyond which, parents will not be able to sign up through My.SCOUT"},
179
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
180
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
181
+ ]},
182
+ {title: "Event invitation reminder", id: "email-event-reminder", description: "This is a reminder email to ask the parents to let you know if their child is attending - the frequency and number of reminders is customisable in the My.SCOUT settings page.", tags:[
183
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the events page that avoids the need for the parents to login."},
184
+ {id: "EVENT_NAME", required: false, description: "The name of the event"},
185
+ {id: "EVENT_LOCATION", required: false, description: "The location of the event"},
186
+ {id: "EVENT_COST", required: false, description: "The cost of the event"},
187
+ {id: "EVENT_DATES", required: false, description: "The event dates - this will be formatted properly into \"on DATE\", \"on DATE at TIME\", \"from DATE to DATE\", \"from DATE at TIME to DATE at TIME\" etc."},
188
+ {id: "EVENT_DETAILS", required: false, description: "This is the \"Details for My.SCOUT\" section of the event"},
189
+ {id: "CONFIRMATION_DEADLINE", required: false, description: "The confirmation deadline - beyond which, parents will not be able to sign up through My.SCOUT"},
190
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
191
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
192
+ ]},
193
+ {title: "Event attendance reminder", id: "email-event-attendancereminder", description: "This is a reminder email to tell parents that their child is attending the event - the number of days before the event that this email is sent is customisable on a per-event basis on each event page.", tags:[
194
+ {id: "DIRECT_LINK", required: false, description: "A direct link to the events page that avoids the need for the parents to login."},
195
+ {id: "EVENT_NAME", required: false, description: "The name of the event"},
196
+ {id: "EVENT_LOCATION", required: false, description: "The location of the event"},
197
+ {id: "EVENT_DATES", required: false, description: "The event dates - this will be formatted properly into \"on DATE\", \"on DATE at TIME\", \"from DATE to DATE\", \"from DATE at TIME to DATE at TIME\" etc."},
198
+ {id: "EVENT_DETAILS", required: false, description: "This is the \"Details for My.SCOUT\" section of the event"},
199
+ {id: "CONFIRMATION_DEADLINE", required: false, description: "The confirmation deadline - beyond which, parents will not be able to sign up through My.SCOUT"},
200
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
201
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
202
+ ]},
203
+ {title: "Invitation to system", id: "email-invitation", description: "This email is sent to invite parents into the system - they will receive a private link that avoids the need to login.", tags:[
204
+ {id: "DIRECT_LINK", required: true, description: "A direct link into the parent system that avoids the need for the parents to login."},
205
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
206
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
207
+ ]},
208
+ {title: "Parent rota reminder email", id: "email-rota-reminder", description: "This email informs parents that they are signed up to the rota and is sent the day before the meeting", tags:[
209
+ {id: "PROGRAMME_TITLE", required: false, description: "The title of programme"},
210
+ {id: "PROGRAMME_falseTES", required: false, description: "falsetes for parents"},
211
+ {id: "PROGRAMME_WHEN", required: false, description: "Dates and if specified time of the programme meeting."},
212
+ {id: "DIRECT_LINK", required: false, description: "A direct link to the programme page that avoids the need for the parents to login."},
213
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
214
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
215
+ ]},
216
+ {title: "Badge awarded email", id: "email-badge-awarded", description: "This email is sent to parents whenever badges have been awarded.", tags:[
217
+ {id: "BADGE_LIST", required: true, description: "The list of badges that have been awarded."},
218
+ {id: "DIRECT_LINK", required: false, description: "A direct link to the badges page on My.SCOUT that avoids the need for the parents to login."},
219
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
220
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
221
+ ]},
222
+ {title: "Request for census information", id: "email-census", description: "This is only sent when a leader clicks the 'Send My.SCOUT email' button in the census aggregator pages.", tags:[
223
+ {id: "DIRECT_LINK", required: true, description: "A direct link to the census."},
224
+ {id: "MEMBER_FIRSTNAME", required: true, description: "The member's first name."},
225
+ {id: "MEMBER_LASTNAME", required: false, description:"The member's last name."},
226
+ ]},
227
+ {title: "Gift Aid Declaration", id: "email-giftaid", description: "This email asks parents to update their Gift Aid declaration details on My.SCOUT (this is a free feature for Gold users)", tags:[
228
+ {id: "DIRECT_LINK", required: false, description: "A direct link to the programme page that avoids the need for the parents to login."},
229
+ {id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
230
+ {id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
231
+ ]},
232
+ ]
233
+
234
+ VALID_TEMPLATE_IDS = TEMPLATES.map{ |t| t[:id] }
235
+
236
+
237
+ # Get a template
238
+ # @param [Osm::Api] api The api to use to make the request
239
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get login history for
240
+ # @param [String] id The ID of the template to get
241
+ # @!macro options_get
242
+ # @return [String, nil]
243
+ def self.get_template(api, section, id, options={})
244
+ fail ArgumentError, "Invalid template ID: #{id.inspect}" unless VALID_TEMPLATE_IDS.include?(id)
245
+
246
+ section_id = section.to_i
247
+ require_ability_to(api, :read, :user, section, options)
248
+ cache_key = ['myscout', 'template', section_id, id]
249
+
250
+ if !options[:no_cache] && cache_exist?(api, cache_key)
251
+ return cache_read(api, cache_key)
252
+ end
253
+
254
+ data = api.perform_query("ext/settings/parents/?action=getTemplate&key=#{id}&section_id=#{section_id}")
255
+ content = data.is_a?(Hash) ? data['data'] : ''
256
+ return nil if content.empty?
257
+
258
+ cache_write(api, cache_key, content)
259
+ return content
260
+ end
261
+
262
+ # Update a template in OSM
263
+ # @param [Osm::Api] api The api to use to make the request
264
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get login history for
265
+ # @param [String] id The ID of the template to get
266
+ # @param [String] content The new content of the template
267
+ # @return [Boolean] Wheter OSM reported the template as updated
268
+ def self.update_template(api, section, id, content)
269
+ fail ArgumentError, "Invalid template ID: #{id.inspect}" unless VALID_TEMPLATE_IDS.include?(id)
270
+
271
+ section_id = section.to_i
272
+ require_ability_to(api, :write, :user, section)
273
+
274
+ # Make sure required tags are present
275
+ tags = Osm::Myscout::Template::TEMPLATES.find{ |t| t[:id].eql?(id) }[:tags]
276
+ fail Osm::Error, "Couldn't find tags for template" if tags.nil?
277
+ tags.select{ |tag| tag[:required] }.each do |tag|
278
+ unless content.include?("[#{tag[:id]}]")
279
+ message = "Required tag [#{tag[:id]}] not found in template content."
280
+ fail ArgumentError, message
281
+ end
282
+ end
283
+
284
+ data = api.perform_query('ext/settings/parents/?action=updateTemplate', {
285
+ 'section_id' => section_id,
286
+ 'key' => id,
287
+ 'value' => content
288
+ })
289
+
290
+ if data.is_a?(Hash) && data['status'] && data['data']
291
+ cache_key = ['myscout', 'template', section_id, id]
292
+ cache_write(api, cache_key, content)
293
+ return true
294
+ end
295
+
296
+ return false
297
+ end
298
+
299
+ # Restore a template to OSM's default for it
300
+ # @param [Osm::Api] api The api to use to make the request
301
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get login history for
302
+ # @param [String] id The ID of the template to get
303
+ # @param [String] content The new content of the template
304
+ # @return [String, nil] The content of the template (nil if not restored)
305
+ def self.restore_template(api, section, id)
306
+ fail ArgumentError, "Invalid template ID: #{id.inspect}" unless VALID_TEMPLATE_IDS.include?(id)
307
+
308
+ section_id = section.to_i
309
+ require_ability_to(api, :write, :user, section)
310
+
311
+ data = api.perform_query('ext/settings/parents/?action=restoreTemplate', {
312
+ 'section_id' => section_id,
313
+ 'key' => id,
314
+ })
315
+
316
+ if data.is_a?(Hash) && data['status']
317
+ content = data['data']
318
+ cache_key = ['myscout', 'template', section_id, id]
319
+ cache_write(api, cache_key, content)
320
+ return content
321
+ end
322
+
323
+ return nil
324
+ end
325
+
326
+ end # class Myscout::Template
327
+
328
+ end
329
+
330
+ end
@@ -179,6 +179,11 @@ describe "API" do
179
179
  expect{ Osm::Api.authorize('email@example.com', 'password') }.to raise_error(Osm::Error, 'Error message')
180
180
  end
181
181
 
182
+ it "Raises an error if OSM returns an error (as a hash in a hash)" do
183
+ HTTParty.stub(:post) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>'{"error":{"message":"Error message"}}'}) }
184
+ expect{ Osm::Api.authorize('email@example.com', 'password') }.to raise_error(Osm::Error, 'Error message')
185
+ end
186
+
182
187
  it "Raises an error if OSM returns an error (as a plain string)" do
183
188
  HTTParty.stub(:post) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>'Error message'}) }
184
189
  expect{ Osm::Api.authorize('email@example.com', 'password') }.to raise_error(Osm::Error, 'Error message')
@@ -0,0 +1,539 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe "Email" do
5
+
6
+ describe "Get emails for contacts" do
7
+
8
+ it "Single member" do
9
+ @api.should_receive(:perform_query).with("/ext/members/email/?action=getSelectedEmailsFromContacts&sectionid=1&scouts=2", {"contactGroups" => '["contact_primary_member"]'}){
10
+ {
11
+ "emails"=>{
12
+ "2"=>{
13
+ "emails"=>["john@example.com"],
14
+ "firstname"=>"John",
15
+ "lastname"=>"Smith"
16
+ }
17
+ },
18
+ "count"=>1
19
+ }
20
+ }
21
+
22
+ result = Osm::Email.get_emails_for_contacts(@api, 1, :member, 2)
23
+ result.should == {
24
+ '2' => {
25
+ 'emails' => ['john@example.com'],
26
+ 'firstname' => 'John',
27
+ 'lastname' => 'Smith'
28
+ }
29
+ }
30
+ end
31
+
32
+ it "Several members" do
33
+ @api.should_receive(:perform_query).with("/ext/members/email/?action=getSelectedEmailsFromContacts&sectionid=1&scouts=2,3", {"contactGroups" => '["contact_primary_member"]'}){
34
+ {
35
+ "emails"=>{
36
+ "2"=>{
37
+ "emails"=>["john@example.com"],
38
+ "firstname"=>"John",
39
+ "lastname"=>"Smith"
40
+ },
41
+ "3"=>{
42
+ "emails"=>["jane@example.com","jane2@example.com"],
43
+ "firstname"=>"Jane",
44
+ "lastname"=>"Smith"
45
+ }
46
+ },
47
+ "count"=>3
48
+ }
49
+ }
50
+
51
+ result = Osm::Email.get_emails_for_contacts(@api, 1, :member, [2,3])
52
+ result.should == {
53
+ '2' => {
54
+ 'emails' => ['john@example.com'],
55
+ 'firstname' => 'John',
56
+ 'lastname' => 'Smith'
57
+ },
58
+ '3' => {
59
+ 'emails' => ['jane@example.com', 'jane2@example.com'],
60
+ 'firstname' => 'Jane',
61
+ 'lastname' => 'Smith'
62
+ }
63
+ }
64
+ end
65
+
66
+ it "Requires at least one contact" do
67
+ @api.should_not_receive(:perform_query)
68
+ expect{ Osm::Email.get_emails_for_contacts(@api, 1, [], [2]) }.to raise_error ArgumentError, "You must pass at least one contact"
69
+ end
70
+
71
+ it "Checks for invalid contacts" do
72
+ @api.should_not_receive(:perform_query)
73
+ expect{ Osm::Email.get_emails_for_contacts(@api, 1, [:invalid_contact], [2]) }.to raise_error ArgumentError, "Invalid contact - :invalid_contact"
74
+ end
75
+
76
+ it "Requires at least one member" do
77
+ @api.should_not_receive(:perform_query)
78
+ expect{ Osm::Email.get_emails_for_contacts(@api, 1, [:primary], []) }.to raise_error ArgumentError, "You must pass at least one member"
79
+ end
80
+
81
+ end # describe Get emails for conatcts
82
+
83
+ describe "Send email" do
84
+
85
+ it "With cc" do
86
+ @api.should_receive(:perform_query).with("ext/members/email/?action=send", {
87
+ 'sectionid' => 1,
88
+ 'emails' => '{"2":{"firstname":"John","lastname":"Smith","emails":["john@example.com"]}}',
89
+ 'scouts' => '2',
90
+ 'cc' => 'cc@example.com',
91
+ 'from' => 'Sender <from@example.com>',
92
+ 'subject' => 'Subject of email',
93
+ 'body' => 'Body of email',
94
+ }){ {'ok'=>true} }
95
+
96
+ Osm::Email.send_email(
97
+ @api,
98
+ 1,
99
+ {'2'=>{'firstname'=>'John', 'lastname'=>'Smith', 'emails'=>['john@example.com']}},
100
+ 'cc@example.com',
101
+ 'Sender <from@example.com>',
102
+ 'Subject of email',
103
+ 'Body of email',
104
+ ).should == true
105
+ end
106
+
107
+ it "Without cc" do
108
+ @api.should_receive(:perform_query).with("ext/members/email/?action=send", {
109
+ 'sectionid' => 1,
110
+ 'emails' => '{"2":{"firstname":"John","lastname":"Smith","emails":["john@example.com"]}}',
111
+ 'scouts' => '2',
112
+ 'cc' => '',
113
+ 'from' => 'Sender <from@example.com>',
114
+ 'subject' => 'Subject of email',
115
+ 'body' => 'Body of email',
116
+ }){ {'ok'=>true} }
117
+
118
+ Osm::Email.send_email(
119
+ @api,
120
+ 1,
121
+ {'2'=>{'firstname'=>'John', 'lastname'=>'Smith', 'emails'=>['john@example.com']}},
122
+ 'Sender <from@example.com>',
123
+ 'Subject of email',
124
+ 'Body of email',
125
+ ).should == true
126
+ end
127
+
128
+ it "To several members" do
129
+ @api.should_receive(:perform_query).with("ext/members/email/?action=send", {
130
+ 'sectionid' => 1,
131
+ 'emails' => '{"2":{"firstname":"John","lastname":"Smith","emails":["john@example.com"]},"3":{"firstname":"Jane","lastname":"Smith","emails":["jane@example.com"]}}',
132
+ 'scouts' => '2,3',
133
+ 'cc' => '',
134
+ 'from' => 'Sender <from@example.com>',
135
+ 'subject' => 'Subject of email',
136
+ 'body' => 'Body of email',
137
+ }){ {'ok'=>true} }
138
+
139
+ Osm::Email.send_email(
140
+ @api,
141
+ 1,
142
+ {'2'=>{'firstname'=>'John', 'lastname'=>'Smith', 'emails'=>['john@example.com']},'3'=>{'firstname'=>'Jane', 'lastname'=>'Smith', 'emails'=>['jane@example.com']}},
143
+ 'Sender <from@example.com>',
144
+ 'Subject of email',
145
+ 'Body of email',
146
+ ).should == true
147
+ end
148
+
149
+ end # describe Send email
150
+
151
+
152
+ describe "DeliveryReport" do
153
+
154
+ describe "Attribute validity -" do
155
+
156
+ before :each do
157
+ @report = Osm::Email::DeliveryReport.new(
158
+ id: 1,
159
+ section_id: 1,
160
+ sent_at: Time.new(2016, 10, 27, 13, 0),
161
+ subject: 'Subject line of email',
162
+ recipients: [],
163
+ )
164
+ end
165
+
166
+ %w{id section_id}.each do |attribute|
167
+ it attribute do
168
+ @report.send("#{attribute}=", 0)
169
+ @report.valid?.should == false
170
+ @report.errors.messages[attribute.to_sym].should == ["must be greater than 0"]
171
+ end
172
+ end
173
+
174
+ %w{sent_at subject}.each do |attribute|
175
+ it attribute do
176
+ @report.send("#{attribute}=", nil)
177
+ @report.valid?.should == false
178
+ @report.errors.messages[attribute.to_sym].should == ["can't be blank"]
179
+ end
180
+ end
181
+
182
+ describe "recipients" do
183
+
184
+ it "Empty array allowed" do
185
+ @report.recipients = []
186
+ @report.valid?.should == true
187
+ @report.errors.messages[:recipients].should == nil
188
+ end
189
+
190
+ it "Invalid item in array not allowed" do
191
+ @report.recipients = [Osm::Email::DeliveryReport::Recipient.new()]
192
+ @report.valid?.should == false
193
+ @report.errors.messages[:recipients].should == ["contains an invalid item"]
194
+ end
195
+
196
+ it "Something other than a recipient not allowed" do
197
+ @report.recipients = [Time.now]
198
+ @report.valid?.should == false
199
+ @report.errors.messages[:recipients].should == ["items in the Array must be a Osm::Email::DeliveryReport::Recipient"]
200
+ end
201
+
202
+ end # describe Email -> DeliveryReport : Invalid without : Recipients
203
+
204
+ end # describe Email -> DeliveryReport : Invalid without
205
+
206
+
207
+ it "Fetch delivery reports from OSM" do
208
+ response = [
209
+ {'id'=>"0", 'name'=>"ALL", 'type'=>"all", 'count'=>47},
210
+ {'id'=>123, 'name'=>'01/02/2003 04:05 - Subject of email - 1', 'type'=>'email', 'parent'=>'0', 'hascontent'=>true, 'errors'=>0, 'opens'=>0, 'warnings'=>0},
211
+ {'id'=>'123-1', 'name'=>'a@example.com - delivered', 'type'=>'oneEmail', 'status'=>'delivered', 'email'=>'a@example.com', 'email_key'=>'aexamplecom', 'hascontent'=>true, 'member_id'=>'12', 'parent'=>123, 'status_raw'=>'delivered'},
212
+ {'id'=>'123-2', 'name'=>'b@example.com - processed', 'type'=>'oneEmail', 'status'=>'processed', 'email'=>'b@example.com', 'email_key'=>'bexamplecom', 'hascontent'=>true, 'member_id'=>'23', 'parent'=>123, 'status_raw'=>'processed'},
213
+ {'id'=>'123-3', 'name'=>'c@example.com - bounced', 'type'=>'oneEmail', 'status'=>'bounced', 'email'=>'c@example.com', 'email_key'=>'cexamplecom', 'hascontent'=>true, 'member_id'=>'34', 'parent'=>123, 'status_raw'=>'bounced'},
214
+ ]
215
+
216
+ HTTParty.should_receive(:post).with('https://www.onlinescoutmanager.co.uk/ext/settings/emails/?action=getDeliveryReport&sectionid=1234', {:body => {
217
+ 'apiid' => @CONFIGURATION[:api][:osm][:id],
218
+ 'token' => @CONFIGURATION[:api][:osm][:token],
219
+ 'userid' => 'user_id',
220
+ 'secret' => 'secret',
221
+ }}).once { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>response.to_json}) }
222
+
223
+ reports = Osm::Email::DeliveryReport.get_for_section(@api, 1234)
224
+ reports.count.should == 1
225
+ report = reports[0]
226
+ report.id.should == 123
227
+ report.sent_at.should == Time.new(2003, 2, 1, 4, 5)
228
+ report.subject.should == 'Subject of email - 1'
229
+ report.section_id.should == 1234
230
+
231
+ report.recipients.count.should == 3
232
+ recipients = report.recipients.sort{ |a,b| a.id <=> b.id }
233
+ recipients[0].delivery_report.should == report
234
+ recipients[0].id.should == 1
235
+ recipients[0].member_id.should == 12
236
+ recipients[0].address.should == 'a@example.com'
237
+ recipients[0].status.should == :delivered
238
+ recipients[1].delivery_report.should == report
239
+ recipients[1].id.should == 2
240
+ recipients[1].member_id.should == 23
241
+ recipients[1].address.should == 'b@example.com'
242
+ recipients[1].status.should == :processed
243
+ recipients[2].delivery_report.should == report
244
+ recipients[2].id.should == 3
245
+ recipients[2].member_id.should == 34
246
+ recipients[2].address.should == 'c@example.com'
247
+ recipients[2].status.should == :bounced
248
+ end
249
+
250
+ it "Fetch email from OSM" do
251
+ email = Osm::Email::DeliveryReport::Email.new
252
+ report = Osm::Email::DeliveryReport.new(id: 3, section_id: 4)
253
+
254
+ Osm::Email::DeliveryReport::Email.should_receive(:fetch_from_osm).with(@api, 4, 3).once{ email }
255
+ report.get_email(@api).should == email
256
+ end
257
+
258
+ describe "Get recipients of a certain status -" do
259
+
260
+ before :each do
261
+ @processed_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :processed)
262
+ @delivered_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :delivered)
263
+ @bounced_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :bounced)
264
+
265
+ @reports = Osm::Email::DeliveryReport.new(recipients: [@processed_recipient, @delivered_recipient, @bounced_recipient])
266
+ end
267
+
268
+ %w{processed delivered bounced}.each do |status|
269
+ it status do
270
+ returned = @reports.send("#{status}_recipients")
271
+ returned.should == [instance_variable_get("@#{status}_recipient")]
272
+ end
273
+ end
274
+
275
+ end
276
+
277
+ describe "Check for recipients of a certain status -" do
278
+
279
+ before :each do
280
+ @processed_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :processed)
281
+ @delivered_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :delivered)
282
+ @bounced_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :bounced)
283
+ end
284
+
285
+ %w{processed delivered bounced}.each do |status|
286
+ it status do
287
+ reports = Osm::Email::DeliveryReport.new(recipients: [instance_variable_get("@#{status}_recipient")])
288
+ reports.send("#{status}_recipients?").should == true
289
+
290
+ reports.recipients = []
291
+ reports.send("#{status}_recipients?").should == false
292
+ end
293
+ end
294
+
295
+ end
296
+
297
+ it "Converts to a string" do
298
+ report = Osm::Email::DeliveryReport.new(sent_at: Time.new(2016, 4, 17, 11, 50, 45), subject: 'Subject line of email')
299
+ report.to_s.should == '17/04/2016 11:50 - Subject line of email'
300
+ end
301
+
302
+ it "Sorts by sent_at then id" do
303
+ report1 = Osm::Email::DeliveryReport.new(sent_at: Time.new(2016), id: 1)
304
+ report2 = Osm::Email::DeliveryReport.new(sent_at: Time.new(2017), id: 1)
305
+ report3 = Osm::Email::DeliveryReport.new(sent_at: Time.new(2017), id: 2)
306
+ reports = [report2, report3, report1]
307
+ reports.sort.should == [report1, report2, report3]
308
+ end
309
+
310
+
311
+ describe "Recipient" do
312
+
313
+ describe "Attribute validity -" do
314
+
315
+ before :each do
316
+ @recipient = Osm::Email::DeliveryReport::Recipient.new(
317
+ id: 1,
318
+ member_id: 1,
319
+ address: 'someone@example.com',
320
+ delivery_report: Osm::Email::DeliveryReport.new,
321
+ status: :processed
322
+ )
323
+ end
324
+
325
+ %w{id member_id}.each do |attribute|
326
+ it attribute do
327
+ @recipient.send("#{attribute}=", 0)
328
+ @recipient.valid?.should == false
329
+ @recipient.errors.messages[attribute.to_sym].should == ["must be greater than 0"]
330
+ end
331
+ end
332
+
333
+ it "address" do
334
+ @recipient.address = nil
335
+ @recipient.valid?.should == false
336
+ @recipient.errors.messages[:address].should == ["can't be blank"]
337
+ end
338
+
339
+ describe "status" do
340
+ [nil, :invalid].each do |status|
341
+ it "is #{status.inspect}" do
342
+ @recipient.status = status
343
+ @recipient.valid?.should == false
344
+ @recipient.errors.messages[:status].should == ["is not included in the list"]
345
+ end
346
+ end
347
+ end
348
+
349
+ end # describe Email -> DeliveryReport -> Recipient : invalid without
350
+
351
+ it "Fetch email from OSM" do
352
+ email = Osm::Email::DeliveryReport::Email.new
353
+ report = Osm::Email::DeliveryReport.new(id: 3, section_id: 4)
354
+ recipient = Osm::Email::DeliveryReport::Recipient.new(member_id: 456, address: 'd@example.com', delivery_report: report)
355
+
356
+ Osm::Email::DeliveryReport::Email.should_receive(:fetch_from_osm).with(@api, 4, 3, 456, 'd@example.com').once{ email }
357
+ recipient.get_email(@api).should == email
358
+ end
359
+
360
+
361
+ describe "Unblock address in OSM" do
362
+ it "Success" do
363
+ recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', status: :bounced, delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
364
+ @api.should_receive(:perform_query).once.with('ext/settings/emails/?action=unBlockEmail', {"section_id"=>1, "email"=>"a@example.com", "email_id"=>2}){ {'status'=>true} }
365
+ recipient.unblock_address(@api).should == true
366
+ end
367
+
368
+ it "Fails with error message" do
369
+ recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', status: :bounced, delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
370
+ @api.should_receive(:perform_query).once.with('ext/settings/emails/?action=unBlockEmail', {"section_id"=>1, "email"=>"a@example.com", "email_id"=>2}){ {'status'=>false, 'error'=>'Error message'} }
371
+ expect{ recipient.unblock_address(@api) }.to raise_error(Osm::Error, 'Error message')
372
+ end
373
+
374
+ it "Fails without error message" do
375
+ recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', status: :bounced, delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
376
+ @api.should_receive(:perform_query).once.with('ext/settings/emails/?action=unBlockEmail', {"section_id"=>1, "email"=>"a@example.com", "email_id"=>2}){ {'status'=>false} }
377
+ recipient.unblock_address(@api).should == false
378
+ end
379
+
380
+ it "Gets something other than a hash" do
381
+ recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', status: :bounced, delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
382
+ @api.should_receive(:perform_query).once.with('ext/settings/emails/?action=unBlockEmail', {"section_id"=>1, "email"=>"a@example.com", "email_id"=>2}){ [] }
383
+ recipient.unblock_address(@api).should == false
384
+ end
385
+
386
+ describe "Doesn't try to unblock when status is" do
387
+
388
+ before :each do
389
+ @recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
390
+ @api.should_not_receive(:perform_query)
391
+ end
392
+
393
+ (Osm::Email::DeliveryReport::VALID_STATUSES - [:bounced]).each do |status|
394
+ it status do
395
+ @recipient.status = status
396
+ @recipient.unblock_address(@api).should == true
397
+ end
398
+ end # each status
399
+ end
400
+
401
+ end # unlock address in OSM
402
+
403
+ describe "Check status helpers -" do
404
+ before :each do
405
+ @processed_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :processed)
406
+ @delivered_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :delivered)
407
+ @bounced_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :bounced)
408
+ end
409
+
410
+ it "processed?" do
411
+ @processed_recipient.processed?.should == true
412
+ @delivered_recipient.processed?.should == false
413
+ @bounced_recipient.processed?.should == false
414
+ end
415
+
416
+ it "delivered?" do
417
+ @processed_recipient.delivered?.should == false
418
+ @delivered_recipient.delivered?.should == true
419
+ @bounced_recipient.delivered?.should == false
420
+ end
421
+
422
+ it "bounced?" do
423
+ @processed_recipient.bounced?.should == false
424
+ @delivered_recipient.bounced?.should == false
425
+ @bounced_recipient.bounced?.should == true
426
+ end
427
+
428
+ end
429
+
430
+ it "Converts to a string" do
431
+ recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'recipient@example.com', status: :delivered)
432
+ recipient.to_s.should == 'recipient@example.com - delivered'
433
+ end
434
+
435
+ it "Sorts by delivery_report then id" do
436
+ report1 = Osm::Email::DeliveryReport.new(id: 1)
437
+ report2 = Osm::Email::DeliveryReport.new(id: 2)
438
+
439
+ recipient1 = Osm::Email::DeliveryReport::Recipient.new(delivery_report: report1, id: 1)
440
+ recipient2 = Osm::Email::DeliveryReport::Recipient.new(delivery_report: report2, id: 1)
441
+ recipient3 = Osm::Email::DeliveryReport::Recipient.new(delivery_report: report2, id: 2)
442
+
443
+ recipients = [recipient3, recipient1, recipient2]
444
+ recipients.sort.should == [recipient1, recipient2, recipient3]
445
+ end
446
+
447
+ end # describe Email -> DeliveryReport -> Recipient
448
+
449
+ describe "Email" do
450
+
451
+ describe "Attribute validity -" do
452
+ before :each do
453
+ @email = Osm::Email::DeliveryReport::Email.new(
454
+ to: 'to@example.com',
455
+ from: 'from@example.com',
456
+ subject: 'Subject of email',
457
+ body: 'Body of email message.',
458
+ )
459
+ end
460
+ %w{to from subject body}.each do |attribute|
461
+ it attribute do
462
+ @email.send("#{attribute}=", nil)
463
+ @email.valid?.should == false
464
+ @email.errors.messages[attribute.to_sym].should == ["can't be blank"]
465
+ end
466
+ end
467
+ end # describe Email -> DeliveryReport -> Email : invalid without
468
+
469
+ it "Converts to a string" do
470
+ email = Osm::Email::DeliveryReport::Email.new(
471
+ to: 'to@example.com',
472
+ from: '"Sender" <from@example.com>',
473
+ subject: 'What the email is about',
474
+ body: '<p>Hello person.</p>'
475
+ )
476
+ email.to_s.should == "To: to@example.com\nFrom: \"Sender\" <from@example.com>\n\nWhat the email is about\n\nHello person."
477
+ end
478
+
479
+ it "Sorts by subject then from then to" do
480
+ email1 = Osm::Email::DeliveryReport::Email.new(subject: 'a', from: 'a', to: 'a')
481
+ email2 = Osm::Email::DeliveryReport::Email.new(subject: 'b', from: 'a', to: 'a')
482
+ email3 = Osm::Email::DeliveryReport::Email.new(subject: 'b', from: 'b', to: 'a')
483
+ email4 = Osm::Email::DeliveryReport::Email.new(subject: 'b', from: 'b', to: 'b')
484
+
485
+ emails = [email2, email3, email4, email1]
486
+ emails.sort.should == [email1, email2, email3, email4]
487
+ end
488
+
489
+ describe "Fetch email from OSM" do
490
+
491
+ it "For a delivery report" do
492
+ @api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail&section_id=1&email_id=2&email=&member_id=').once{ {'data'=>{'to'=>'1 Recipient', 'from'=>'"From" <from@example.com>', 'subject'=>'Subject of email', 'sent'=>'16/04/2016 13:45'}, 'status'=>true, 'error'=>nil, 'meta'=>[]} }
493
+ @api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmailContent&section_id=1&email_id=2&email=&member_id=', {}, true).once{ 'This is the body of the email.' }
494
+
495
+ email = Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2)
496
+ email.to.should == '1 Recipient'
497
+ email.from.should == '"From" <from@example.com>'
498
+ email.subject.should == 'Subject of email'
499
+ email.body.should == 'This is the body of the email.'
500
+ end
501
+
502
+ it "For a recipient" do
503
+ @api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail&section_id=1&email_id=2&email=to@example.com&member_id=3').once{ {'data'=>{'to'=>'to@example.com', 'from'=>'"From" <from@example.com>', 'subject'=>'Subject of email', 'sent'=>'16/04/2016 13:45'}, 'status'=>true, 'error'=>nil, 'meta'=>[]} }
504
+ @api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmailContent&section_id=1&email_id=2&email=to@example.com&member_id=3', {}, true).once{ 'This is the body of the email.' }
505
+
506
+ email = Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2, 3, 'to@example.com')
507
+ email.to.should == 'to@example.com'
508
+ email.from.should == '"From" <from@example.com>'
509
+ email.subject.should == 'Subject of email'
510
+ email.body.should == 'This is the body of the email.'
511
+ end
512
+
513
+ describe "Error getting meta data" do
514
+
515
+ it "Didn't get a Hash" do
516
+ @api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail&section_id=1&email_id=2&email=&member_id=').once{ nil }
517
+ expect{ Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2) }.to raise_error Osm::Error, 'Unexpected format for response - got a NilClass'
518
+ end
519
+
520
+ it "Got an error from OSM" do
521
+ @api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail&section_id=1&email_id=2&email=&member_id=').once{ {'success'=>false, 'error'=>'Error message'} }
522
+ expect{ Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2) }.to raise_error Osm::Error, 'Error message'
523
+ end
524
+
525
+ end
526
+
527
+ it "Error getting body" do
528
+ @api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail&section_id=1&email_id=2&email=&member_id=').once{ {'data'=>{'to'=>'1 Recipient', 'from'=>'"From" <from@example.com>', 'subject'=>'Subject of email', 'sent'=>'16/04/2016 13:45'}, 'status'=>true, 'error'=>nil, 'meta'=>[]} }
529
+ @api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmailContent&section_id=1&email_id=2&email=&member_id=', {}, true).once{ raise Osm::Forbidden, 'Email not found' }
530
+ expect{ Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2) }.to raise_error Osm::Error, 'Email not found'
531
+ end
532
+
533
+ end # describe Email -> DeliveryReport -> Email : fetch email from osm
534
+
535
+ end # describe Email -> DeliveryReport -> Email
536
+
537
+ end # describe Email -> DeliveryReport
538
+
539
+ end