flapjack 0.7.16 → 0.7.17

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.
@@ -23,33 +23,33 @@ module Flapjack
23
23
  end
24
24
 
25
25
  def status
26
- checks.collect {|c| {:entity => @entity, :check => c,
26
+ checks.collect {|c| {:entity => @entity.name, :check => c,
27
27
  :status => check_presenter(c).status } }
28
28
  end
29
29
 
30
30
  def outages(start_time, end_time)
31
31
  checks.collect {|c|
32
- {:entity => @entity, :check => c, :outages => check_presenter(c).outages(start_time, end_time)}
32
+ {:entity => @entity.name, :check => c, :outages => check_presenter(c).outages(start_time, end_time)}
33
33
  }
34
34
  end
35
35
 
36
36
  def unscheduled_maintenances(start_time, end_time)
37
37
  checks.collect {|c|
38
- {:entity => @entity, :check => c, :unscheduled_maintenances =>
38
+ {:entity => @entity.name, :check => c, :unscheduled_maintenances =>
39
39
  check_presenter(c).unscheduled_maintenances(start_time, end_time)}
40
40
  }
41
41
  end
42
42
 
43
43
  def scheduled_maintenances(start_time, end_time)
44
44
  checks.collect {|c|
45
- {:entity => @entity, :check => c, :scheduled_maintenances =>
45
+ {:entity => @entity.name, :check => c, :scheduled_maintenances =>
46
46
  check_presenter(c).scheduled_maintenances(start_time, end_time)}
47
47
  }
48
48
  end
49
49
 
50
50
  def downtime(start_time, end_time)
51
51
  checks.collect {|c|
52
- {:entity => @entity, :check => c, :downtime =>
52
+ {:entity => @entity.name, :check => c, :downtime =>
53
53
  check_presenter(c).downtime(start_time, end_time)}
54
54
  }
55
55
  end
@@ -72,4 +72,4 @@ module Flapjack
72
72
 
73
73
  end
74
74
 
75
- end
75
+ end
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rack'
4
+
5
+ module Rack
6
+ class JsonParamsParser < Struct.new(:app)
7
+ def call(env)
8
+ if env['rack.input'] and not input_parsed?(env) and type_match?(env)
9
+ env['rack.request.form_input'] = env['rack.input']
10
+ data = env['rack.input'].read
11
+ env['rack.input'].rewind
12
+ env['rack.request.form_hash'] = data.empty? ? {} : JSON.parse(data)
13
+ end
14
+ app.call(env)
15
+ end
16
+
17
+ def input_parsed? env
18
+ env['rack.request.form_input'].eql? env['rack.input']
19
+ end
20
+
21
+ def type_match? env
22
+ type = env['CONTENT_TYPE'] and
23
+ type.split(/\s*[;,]\s*/, 2).first.downcase == 'application/json'
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  module Flapjack
4
- VERSION = "0.7.16"
4
+ VERSION = "0.7.17"
5
5
  end
@@ -385,6 +385,27 @@ describe Flapjack::Data::EntityCheck, :redis => true do
385
385
  state.should == 'ok'
386
386
  end
387
387
 
388
+ it "does not update state with a repeated state value" do
389
+ ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
390
+ ec.update_state('critical', :summary => 'small problem')
391
+ changed_at = @redis.hget("check:#{name}:#{check}", 'last_change')
392
+ summary = @redis.hget("check:#{name}:#{check}", 'summary')
393
+
394
+ ec.update_state('critical', :summary => 'big problem')
395
+ new_changed_at = @redis.hget("check:#{name}:#{check}", 'last_change')
396
+ new_summary = @redis.hget("check:#{name}:#{check}", 'summary')
397
+
398
+ changed_at.should_not be_nil
399
+ new_changed_at.should_not be_nil
400
+ new_changed_at.should == changed_at
401
+
402
+ summary.should_not be_nil
403
+ new_summary.should_not be_nil
404
+ new_summary.should_not == summary
405
+ summary.should == 'small problem'
406
+ new_summary.should == 'big problem'
407
+ end
408
+
388
409
  def time_before(t, min, sec = 0)
389
410
  t - ((60 * min) + sec)
390
411
  end
@@ -52,8 +52,8 @@ describe Flapjack::Data::NotificationRule, :redis => true do
52
52
 
53
53
  expect {
54
54
  rule_data[:warning_blackhole] = true
55
- success = rule.update(rule_data)
56
- success.should be_true
55
+ errors = rule.update(rule_data)
56
+ errors.should be_nil
57
57
  }.to change { rule.warning_blackhole }.from(false).to(true)
58
58
  end
59
59
 
@@ -96,16 +96,21 @@ describe Flapjack::Data::NotificationRule, :redis => true do
96
96
 
97
97
  it "fails to add a notification rule with invalid data" do
98
98
  rule_data[:entities] = [1, {}]
99
- rule = Flapjack::Data::NotificationRule.add(rule_data, :redis => @redis)
100
- rule.should be_nil
99
+ rule_or_errors = Flapjack::Data::NotificationRule.add(rule_data, :redis => @redis)
100
+ rule_or_errors.should_not be_nil
101
+ rule_or_errors.should be_an(Array)
102
+ rule_or_errors.should have(1).error
103
+ rule_or_errors.should == ["Rule entities must be a list of strings"]
101
104
  end
102
105
 
103
106
  it "fails to update a notification rule with invalid data" do
104
107
  rule = Flapjack::Data::NotificationRule.add(rule_data, :redis => @redis)
105
108
  expect {
106
109
  rule_data[:entities] = [57]
107
- success = rule.update(rule_data)
108
- success.should be_false
110
+ errors = rule.update(rule_data)
111
+ errors.should_not be_nil
112
+ errors.should have(1).error
113
+ errors.should == ["Rule entities must be a list of strings"]
109
114
  }.not_to change { rule.entities }
110
115
  end
111
116
 
@@ -0,0 +1,709 @@
1
+ require 'spec_helper'
2
+ require 'flapjack/gateways/api'
3
+
4
+ describe 'Flapjack::Gateways::API::ContactMethods', :sinatra => true, :logger => true, :json => true do
5
+
6
+ def app
7
+ Flapjack::Gateways::API
8
+ end
9
+
10
+ let(:contact) { mock(Flapjack::Data::Contact, :id => '21') }
11
+ let(:contact_core) {
12
+ {'id' => contact.id,
13
+ 'first_name' => "Ada",
14
+ 'last_name' => "Lovelace",
15
+ 'email' => "ada@example.com",
16
+ 'tags' => ["legend", "first computer programmer"]
17
+ }
18
+ }
19
+
20
+ let(:media) {
21
+ {'email' => 'ada@example.com',
22
+ 'sms' => '04123456789'
23
+ }
24
+ }
25
+
26
+ let(:media_intervals) {
27
+ {'email' => 500,
28
+ 'sms' => 300
29
+ }
30
+ }
31
+
32
+ let(:redis) { mock(::Redis) }
33
+
34
+ let(:notification_rule) {
35
+ mock(Flapjack::Data::NotificationRule, :id => '1', :contact_id => '21')
36
+ }
37
+
38
+ let(:notification_rule_data) {
39
+ {"contact_id" => "21",
40
+ "entity_tags" => ["database","physical"],
41
+ "entities" => ["foo-app-01.example.com"],
42
+ "time_restrictions" => nil,
43
+ "warning_media" => ["email"],
44
+ "critical_media" => ["sms", "email"],
45
+ "warning_blackhole" => false,
46
+ "critical_blackhole" => false
47
+ }
48
+ }
49
+
50
+ before(:all) do
51
+ Flapjack::Gateways::API.class_eval {
52
+ set :raise_errors, true
53
+ }
54
+ Flapjack::Gateways::API.instance_variable_get('@middleware').delete_if {|m|
55
+ m[0] == Rack::FiberPool
56
+ }
57
+ end
58
+
59
+ before(:each) do
60
+ Flapjack::RedisPool.should_receive(:new).and_return(redis)
61
+ Flapjack::Gateways::API.instance_variable_set('@config', {})
62
+ Flapjack::Gateways::API.instance_variable_set('@logger', @logger)
63
+ Flapjack::Gateways::API.start
64
+ end
65
+
66
+ it "creates contacts from a submitted list" do
67
+ contacts = {'contacts' =>
68
+ [{"id" => "0362",
69
+ "first_name" => "John",
70
+ "last_name" => "Smith",
71
+ "email" => "johns@example.dom",
72
+ "media" => {"email" => "johns@example.dom",
73
+ "jabber" => "johns@conference.localhost"}},
74
+ {"id" => "0363",
75
+ "first_name" => "Jane",
76
+ "last_name" => "Jones",
77
+ "email" => "jane@example.dom",
78
+ "media" => {"email" => "jane@example.dom"}}
79
+ ]
80
+ }
81
+
82
+ Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([])
83
+ Flapjack::Data::Contact.should_receive(:add).twice
84
+
85
+ post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
86
+ last_response.status.should == 204
87
+ end
88
+
89
+ it "does not create contacts if the data is improperly formatted" do
90
+ Flapjack::Data::Contact.should_not_receive(:add)
91
+
92
+ post "/contacts", {'contacts' => ["Hello", "again"]}.to_json,
93
+ {'CONTENT_TYPE' => 'application/json'}
94
+ last_response.status.should == 403
95
+ end
96
+
97
+ it "does not create contacts if they don't contain an id" do
98
+ contacts = {'contacts' =>
99
+ [{"id" => "0362",
100
+ "first_name" => "John",
101
+ "last_name" => "Smith",
102
+ "email" => "johns@example.dom",
103
+ "media" => {"email" => "johns@example.dom",
104
+ "jabber" => "johns@conference.localhost"}},
105
+ {"first_name" => "Jane",
106
+ "last_name" => "Jones",
107
+ "email" => "jane@example.dom",
108
+ "media" => {"email" => "jane@example.dom"}}
109
+ ]
110
+ }
111
+
112
+ Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([])
113
+ Flapjack::Data::Contact.should_receive(:add)
114
+
115
+ post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
116
+ last_response.status.should == 204
117
+ end
118
+
119
+ it "updates a contact if it is already present" do
120
+ contacts = {'contacts' =>
121
+ [{"id" => "0362",
122
+ "first_name" => "John",
123
+ "last_name" => "Smith",
124
+ "email" => "johns@example.dom",
125
+ "media" => {"email" => "johns@example.dom",
126
+ "jabber" => "johns@conference.localhost"}},
127
+ {"id" => "0363",
128
+ "first_name" => "Jane",
129
+ "last_name" => "Jones",
130
+ "email" => "jane@example.dom",
131
+ "media" => {"email" => "jane@example.dom"}}
132
+ ]
133
+ }
134
+
135
+ existing = mock(Flapjack::Data::Contact)
136
+ existing.should_receive(:id).and_return("0363")
137
+ existing.should_receive(:update).with(contacts['contacts'][1])
138
+
139
+ Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([existing])
140
+ Flapjack::Data::Contact.should_receive(:add).with(contacts['contacts'][0], :redis => redis)
141
+
142
+ post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
143
+ last_response.status.should == 204
144
+ end
145
+
146
+ it "deletes a contact not found in a bulk update list" do
147
+ contacts = {'contacts' =>
148
+ [{"id" => "0363",
149
+ "first_name" => "Jane",
150
+ "last_name" => "Jones",
151
+ "email" => "jane@example.dom",
152
+ "media" => {"email" => "jane@example.dom"}}
153
+ ]
154
+ }
155
+
156
+ existing = mock(Flapjack::Data::Contact)
157
+ existing.should_receive(:id).twice.and_return("0362")
158
+ existing.should_receive(:delete!)
159
+
160
+ Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([existing])
161
+ Flapjack::Data::Contact.should_receive(:add).with(contacts['contacts'][0], :redis => redis)
162
+
163
+ post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
164
+ last_response.status.should == 204
165
+ end
166
+
167
+ it "returns all the contacts" do
168
+ contact.should_receive(:to_json).and_return(contact_core.to_json)
169
+ Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).
170
+ and_return([contact])
171
+
172
+ get '/contacts'
173
+ last_response.should be_ok
174
+ last_response.body.should be_json_eql([contact_core].to_json)
175
+ end
176
+
177
+ it "returns the core information of a specified contact" do
178
+ contact.should_receive(:to_json).and_return(contact_core.to_json)
179
+ Flapjack::Data::Contact.should_receive(:find_by_id).
180
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
181
+
182
+ get "/contacts/#{contact.id}"
183
+ last_response.should be_ok
184
+ last_response.body.should be_json_eql(contact_core.to_json)
185
+ end
186
+
187
+ it "does not return information for a contact that does not exist" do
188
+ Flapjack::Data::Contact.should_receive(:find_by_id).
189
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
190
+
191
+ get "/contacts/#{contact.id}"
192
+ last_response.should be_forbidden
193
+ end
194
+
195
+ it "lists a contact's notification rules" do
196
+ notification_rule_2 = mock(Flapjack::Data::NotificationRule, :id => '2', :contact_id => '21')
197
+ notification_rule.should_receive(:to_json).and_return('"rule_1"')
198
+ notification_rule_2.should_receive(:to_json).and_return('"rule_2"')
199
+ notification_rules = [ notification_rule, notification_rule_2 ]
200
+
201
+ contact.should_receive(:notification_rules).and_return(notification_rules)
202
+ Flapjack::Data::Contact.should_receive(:find_by_id).
203
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
204
+
205
+ get "/contacts/#{contact.id}/notification_rules"
206
+ last_response.should be_ok
207
+ last_response.body.should be_json_eql( '["rule_1", "rule_2"]' )
208
+ end
209
+
210
+ it "does not list notification rules for a contact that does not exist" do
211
+ Flapjack::Data::Contact.should_receive(:find_by_id).
212
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
213
+
214
+ get "/contacts/#{contact.id}/notification_rules"
215
+ last_response.should be_forbidden
216
+ end
217
+
218
+ it "returns a specified notification rule" do
219
+ notification_rule.should_receive(:to_json).and_return('"rule_1"')
220
+ Flapjack::Data::NotificationRule.should_receive(:find_by_id).
221
+ with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
222
+
223
+ get "/notification_rules/#{notification_rule.id}"
224
+ last_response.should be_ok
225
+ last_response.body.should be_json_eql('"rule_1"')
226
+ end
227
+
228
+ it "does not return a notification rule that does not exist" do
229
+ Flapjack::Data::NotificationRule.should_receive(:find_by_id).
230
+ with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(nil)
231
+
232
+ get "/notification_rules/#{notification_rule.id}"
233
+ last_response.should be_forbidden
234
+ end
235
+
236
+ # POST /notification_rules
237
+ it "creates a new notification rule" do
238
+ Flapjack::Data::Contact.should_receive(:find_by_id).
239
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
240
+ notification_rule.should_receive(:respond_to?).with(:critical_media).and_return(true)
241
+ notification_rule.should_receive(:to_json).and_return('"rule_1"')
242
+
243
+ # symbolize the keys
244
+ notification_rule_data_sym = notification_rule_data.inject({}){|memo,(k,v)|
245
+ memo[k.to_sym] = v; memo
246
+ }
247
+ notification_rule_data_sym.delete(:contact_id)
248
+
249
+ contact.should_receive(:add_notification_rule).
250
+ with(notification_rule_data_sym, :logger => @logger).and_return(notification_rule)
251
+
252
+ post "/notification_rules", notification_rule_data.to_json,
253
+ {'CONTENT_TYPE' => 'application/json'}
254
+ last_response.should be_ok
255
+ last_response.body.should be_json_eql('"rule_1"')
256
+ end
257
+
258
+ it "does not create a notification_rule for a contact that's not present" do
259
+ Flapjack::Data::Contact.should_receive(:find_by_id).
260
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
261
+
262
+ post "/notification_rules", notification_rule_data.to_json,
263
+ {'CONTENT_TYPE' => 'application/json'}
264
+ last_response.should be_forbidden
265
+ end
266
+
267
+ it "does not create a notification_rule if a rule id is provided" do
268
+ contact.should_not_receive(:add_notification_rule)
269
+
270
+ post "/notification_rules", notification_rule_data.merge(:id => 1).to_json,
271
+ {'CONTENT_TYPE' => 'application/json'}
272
+ last_response.status.should == 403
273
+ end
274
+
275
+ # PUT /notification_rules/RULE_ID
276
+ it "updates a notification rule" do
277
+ Flapjack::Data::Contact.should_receive(:find_by_id).
278
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
279
+ notification_rule.should_receive(:to_json).and_return('"rule_1"')
280
+ Flapjack::Data::NotificationRule.should_receive(:find_by_id).
281
+ with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
282
+
283
+ # symbolize the keys
284
+ notification_rule_data_sym = notification_rule_data.inject({}){|memo,(k,v)|
285
+ memo[k.to_sym] = v; memo
286
+ }
287
+ notification_rule_data_sym.delete(:contact_id)
288
+
289
+ notification_rule.should_receive(:update).with(notification_rule_data_sym, :logger => @logger).and_return(nil)
290
+
291
+ put "/notification_rules/#{notification_rule.id}", notification_rule_data.to_json,
292
+ {'CONTENT_TYPE' => 'application/json'}
293
+ last_response.should be_ok
294
+ last_response.body.should be_json_eql('"rule_1"')
295
+ end
296
+
297
+ it "does not update a notification rule that's not present" do
298
+ Flapjack::Data::NotificationRule.should_receive(:find_by_id).
299
+ with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(nil)
300
+
301
+ put "/notification_rules/#{notification_rule.id}", notification_rule_data
302
+ last_response.should be_forbidden
303
+ end
304
+
305
+ it "does not update a notification_rule for a contact that's not present" do
306
+ Flapjack::Data::NotificationRule.should_receive(:find_by_id).
307
+ with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
308
+ Flapjack::Data::Contact.should_receive(:find_by_id).
309
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
310
+
311
+ put "/notification_rules/#{notification_rule.id}", notification_rule_data.to_json,
312
+ {'CONTENT_TYPE' => 'application/json'}
313
+ last_response.should be_forbidden
314
+ end
315
+
316
+ # DELETE /notification_rules/RULE_ID
317
+ it "deletes a notification rule" do
318
+ notification_rule.should_receive(:contact_id).and_return(contact.id)
319
+ Flapjack::Data::NotificationRule.should_receive(:find_by_id).
320
+ with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
321
+ contact.should_receive(:delete_notification_rule).with(notification_rule)
322
+ Flapjack::Data::Contact.should_receive(:find_by_id).
323
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
324
+
325
+ delete "/notification_rules/#{notification_rule.id}"
326
+ last_response.status.should == 204
327
+ end
328
+
329
+ it "does not delete a notification rule that's not present" do
330
+ Flapjack::Data::NotificationRule.should_receive(:find_by_id).
331
+ with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(nil)
332
+
333
+ delete "/notification_rules/#{notification_rule.id}"
334
+ last_response.should be_forbidden
335
+ end
336
+
337
+ it "does not delete a notification rule if the contact is not present" do
338
+ notification_rule.should_receive(:contact_id).and_return(contact.id)
339
+ Flapjack::Data::NotificationRule.should_receive(:find_by_id).
340
+ with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
341
+ Flapjack::Data::Contact.should_receive(:find_by_id).
342
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
343
+
344
+ delete "/notification_rules/#{notification_rule.id}"
345
+ last_response.should be_forbidden
346
+ end
347
+
348
+ # GET /contacts/CONTACT_ID/media
349
+ it "returns the media of a contact" do
350
+ contact.should_receive(:media).and_return(media)
351
+ contact.should_receive(:media_intervals).and_return(media_intervals)
352
+ Flapjack::Data::Contact.should_receive(:find_by_id).
353
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
354
+ result = Hash[ *(media.keys.collect {|m|
355
+ [m, {'address' => media[m],
356
+ 'interval' => media_intervals[m] }]
357
+ }).flatten(1)].to_json
358
+
359
+ get "/contacts/#{contact.id}/media"
360
+ last_response.should be_ok
361
+ last_response.body.should be_json_eql(result)
362
+ end
363
+
364
+ it "does not return the media of a contact if the contact is not present" do
365
+ Flapjack::Data::Contact.should_receive(:find_by_id).
366
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
367
+
368
+ get "/contacts/#{contact.id}/media"
369
+ last_response.should be_forbidden
370
+ end
371
+
372
+ # GET /contacts/CONTACT_ID/media/MEDIA
373
+ it "returns the specified media of a contact" do
374
+ contact.should_receive(:media).and_return(media)
375
+ contact.should_receive(:media_intervals).and_return(media_intervals)
376
+ Flapjack::Data::Contact.should_receive(:find_by_id).
377
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
378
+
379
+ result = {'address' => media['sms'], 'interval' => media_intervals['sms']}
380
+
381
+ get "/contacts/#{contact.id}/media/sms"
382
+ last_response.should be_ok
383
+ last_response.body.should be_json_eql(result.to_json)
384
+ end
385
+
386
+ it "does not return the media of a contact if the contact is not present" do
387
+ Flapjack::Data::Contact.should_receive(:find_by_id).
388
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
389
+
390
+ get "/contacts/#{contact.id}/media/sms"
391
+ last_response.should be_forbidden
392
+ end
393
+
394
+ it "does not return the media of a contact if the media is not present" do
395
+ contact.should_receive(:media).and_return(media)
396
+ Flapjack::Data::Contact.should_receive(:find_by_id).
397
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
398
+
399
+ get "/contacts/#{contact.id}/media/telepathy"
400
+ last_response.should be_forbidden
401
+ end
402
+
403
+ # PUT, DELETE /contacts/CONTACT_ID/media/MEDIA
404
+ it "creates/updates a media of a contact" do
405
+ # as far as API is concerned these are the same -- contact.rb spec test
406
+ # may distinguish between them
407
+ alt_media = media.merge('sms' => '04987654321')
408
+ alt_media_intervals = media_intervals.merge('sms' => '200')
409
+
410
+ contact.should_receive(:set_address_for_media).with('sms', '04987654321')
411
+ contact.should_receive(:set_interval_for_media).with('sms', '200')
412
+ contact.should_receive(:media).and_return(alt_media)
413
+ contact.should_receive(:media_intervals).and_return(alt_media_intervals)
414
+ Flapjack::Data::Contact.should_receive(:find_by_id).
415
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
416
+
417
+ result = {'address' => alt_media['sms'], 'interval' => alt_media_intervals['sms']}
418
+
419
+ put "/contacts/#{contact.id}/media/sms", {:address => '04987654321', :interval => '200'}
420
+ last_response.should be_ok
421
+ last_response.body.should be_json_eql(result.to_json)
422
+ end
423
+
424
+ it "does not create a media of a contact that's not present" do
425
+ Flapjack::Data::Contact.should_receive(:find_by_id).
426
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
427
+
428
+ put "/contacts/#{contact.id}/media/sms", {:address => '04987654321', :interval => '200'}
429
+ last_response.should be_forbidden
430
+ end
431
+
432
+ it "does not create a media of a contact if no address is provided" do
433
+ Flapjack::Data::Contact.should_receive(:find_by_id).
434
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
435
+
436
+ put "/contacts/#{contact.id}/media/sms", {:interval => '200'}
437
+ last_response.should be_forbidden
438
+ end
439
+
440
+ it "creates a media of a contact even if no interval is provided" do
441
+ alt_media = media.merge('sms' => '04987654321')
442
+ alt_media_intervals = media_intervals.merge('sms' => nil)
443
+
444
+ contact.should_receive(:set_address_for_media).with('sms', '04987654321')
445
+ contact.should_receive(:set_interval_for_media).with('sms', nil)
446
+ contact.should_receive(:media).and_return(alt_media)
447
+ contact.should_receive(:media_intervals).and_return(alt_media_intervals)
448
+ Flapjack::Data::Contact.should_receive(:find_by_id).
449
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
450
+
451
+ put "/contacts/#{contact.id}/media/sms", {:address => '04987654321'}
452
+ last_response.should be_ok
453
+ end
454
+
455
+ it "deletes a media of a contact" do
456
+ contact.should_receive(:remove_media).with('sms')
457
+ Flapjack::Data::Contact.should_receive(:find_by_id).
458
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
459
+
460
+ delete "/contacts/#{contact.id}/media/sms"
461
+ last_response.status.should == 204
462
+ end
463
+
464
+ it "does not delete a media of a contact that's not present" do
465
+ Flapjack::Data::Contact.should_receive(:find_by_id).
466
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
467
+
468
+ delete "/contacts/#{contact.id}/media/sms"
469
+ last_response.should be_forbidden
470
+ end
471
+
472
+ # GET /contacts/CONTACT_ID/timezone
473
+ it "returns the timezone of a contact" do
474
+ contact.should_receive(:timezone).and_return(::ActiveSupport::TimeZone.new('Australia/Sydney'))
475
+ Flapjack::Data::Contact.should_receive(:find_by_id).
476
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
477
+
478
+ get "/contacts/#{contact.id}/timezone"
479
+ last_response.should be_ok
480
+ last_response.body.should be_json_eql('"Australia/Sydney"')
481
+ end
482
+
483
+ it "doesn't get the timezone of a contact that doesn't exist" do
484
+ Flapjack::Data::Contact.should_receive(:find_by_id).
485
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
486
+
487
+ get "/contacts/#{contact.id}/timezone"
488
+ last_response.should be_forbidden
489
+ end
490
+
491
+ # PUT /contacts/CONTACT_ID/timezone
492
+ it "sets the timezone of a contact" do
493
+ contact.should_receive(:timezone=).with('Australia/Perth')
494
+ contact.should_receive(:timezone).and_return(ActiveSupport::TimeZone.new('Australia/Perth'))
495
+ Flapjack::Data::Contact.should_receive(:find_by_id).
496
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
497
+
498
+ put "/contacts/#{contact.id}/timezone", {:timezone => 'Australia/Perth'}
499
+ last_response.should be_ok
500
+ end
501
+
502
+ it "doesn't set the timezone of a contact who can't be found" do
503
+ Flapjack::Data::Contact.should_receive(:find_by_id).
504
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
505
+
506
+ put "/contacts/#{contact.id}/timezone", {:timezone => 'Australia/Perth'}
507
+ last_response.should be_forbidden
508
+ end
509
+
510
+ # DELETE /contacts/CONTACT_ID/timezone
511
+ it "deletes the timezone of a contact" do
512
+ contact.should_receive(:timezone=).with(nil)
513
+ Flapjack::Data::Contact.should_receive(:find_by_id).
514
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
515
+
516
+ delete "/contacts/#{contact.id}/timezone"
517
+ last_response.status.should == 204
518
+ end
519
+
520
+ it "does not delete the timezone of a contact that's not present" do
521
+ Flapjack::Data::Contact.should_receive(:find_by_id).
522
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
523
+
524
+ delete "/contacts/#{contact.id}/timezone"
525
+ last_response.should be_forbidden
526
+ end
527
+
528
+ it "sets a single tag on a contact and returns current tags" do
529
+ contact.should_receive(:add_tags).with('web')
530
+ contact.should_receive(:tags).and_return(['web'])
531
+ Flapjack::Data::Contact.should_receive(:find_by_id).
532
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
533
+
534
+ post "contacts/#{contact.id}/tags", :tag => 'web'
535
+ last_response.should be_ok
536
+ last_response.body.should be_json_eql( ['web'].to_json )
537
+ end
538
+
539
+ it "does not set a single tag on a contact that's not found" do
540
+ Flapjack::Data::Contact.should_receive(:find_by_id).
541
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
542
+
543
+ post "contacts/#{contact.id}/tags", :tag => 'web'
544
+ last_response.should be_forbidden
545
+ end
546
+
547
+ it "sets multiple tags on a contact and returns current tags" do
548
+ contact.should_receive(:add_tags).with('web', 'app')
549
+ contact.should_receive(:tags).and_return(['web', 'app'])
550
+ Flapjack::Data::Contact.should_receive(:find_by_id).
551
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
552
+
553
+ post "contacts/#{contact.id}/tags", :tag => ['web', 'app']
554
+ last_response.should be_ok
555
+ last_response.body.should be_json_eql( ['web', 'app'].to_json )
556
+ end
557
+
558
+ it "does not set multiple tags on a contact that's not found" do
559
+ Flapjack::Data::Contact.should_receive(:find_by_id).
560
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
561
+
562
+ post "contacts/#{contact.id}/tags", :tag => ['web', 'app']
563
+ last_response.should be_forbidden
564
+ end
565
+
566
+ it "removes a single tag from a contact" do
567
+ contact.should_receive(:delete_tags).with('web')
568
+ Flapjack::Data::Contact.should_receive(:find_by_id).
569
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
570
+
571
+ delete "contacts/#{contact.id}/tags", :tag => 'web'
572
+ last_response.status.should == 204
573
+ end
574
+
575
+ it "does not remove a single tag from a contact that's not found" do
576
+ Flapjack::Data::Contact.should_receive(:find_by_id).
577
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
578
+
579
+ delete "contacts/#{contact.id}/tags", :tag => 'web'
580
+ last_response.should be_forbidden
581
+ end
582
+
583
+ it "removes multiple tags from a contact" do
584
+ contact.should_receive(:delete_tags).with('web', 'app')
585
+ Flapjack::Data::Contact.should_receive(:find_by_id).
586
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
587
+
588
+ delete "contacts/#{contact.id}/tags", :tag => ['web', 'app']
589
+ last_response.status.should == 204
590
+ end
591
+
592
+ it "does not remove multiple tags from a contact that's not found" do
593
+ Flapjack::Data::Contact.should_receive(:find_by_id).
594
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
595
+
596
+ delete "contacts/#{contact.id}/tags", :tag => ['web', 'app']
597
+ last_response.should be_forbidden
598
+ end
599
+
600
+ it "gets all tags on a contact" do
601
+ contact.should_receive(:tags).and_return(['web', 'app'])
602
+ Flapjack::Data::Contact.should_receive(:find_by_id).
603
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
604
+
605
+ get "contacts/#{contact.id}/tags"
606
+ last_response.should be_ok
607
+ last_response.body.should be_json_eql( ['web', 'app'].to_json )
608
+ end
609
+
610
+ it "does not get all tags on a contact that's not found" do
611
+ Flapjack::Data::Contact.should_receive(:find_by_id).
612
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
613
+
614
+ get "contacts/#{contact.id}/tags"
615
+ last_response.should be_forbidden
616
+ end
617
+
618
+ it "gets all entity tags for a contact" do
619
+ entity_1 = mock(Flapjack::Data::Entity)
620
+ entity_1.should_receive(:name).and_return('entity_1')
621
+ entity_2 = mock(Flapjack::Data::Entity)
622
+ entity_2.should_receive(:name).and_return('entity_2')
623
+ tag_data = [{:entity => entity_1, :tags => ['web']},
624
+ {:entity => entity_2, :tags => ['app']}]
625
+ contact.should_receive(:entities).with(:tags => true).
626
+ and_return(tag_data)
627
+
628
+ Flapjack::Data::Contact.should_receive(:find_by_id).
629
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
630
+
631
+ get "contacts/#{contact.id}/entity_tags"
632
+ last_response.should be_ok
633
+ tag_response = {'entity_1' => ['web'],
634
+ 'entity_2' => ['app']}
635
+ last_response.body.should be_json_eql( tag_response.to_json )
636
+ end
637
+
638
+ it "does not get all entity tags for a contact that's not found" do
639
+ Flapjack::Data::Contact.should_receive(:find_by_id).
640
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
641
+
642
+ get "contacts/#{contact.id}/entity_tags"
643
+ last_response.should be_forbidden
644
+ end
645
+
646
+ it "adds tags to multiple entities for a contact" do
647
+ entity_1 = mock(Flapjack::Data::Entity)
648
+ entity_1.should_receive(:name).twice.and_return('entity_1')
649
+ entity_1.should_receive(:add_tags).with('web')
650
+ entity_2 = mock(Flapjack::Data::Entity)
651
+ entity_2.should_receive(:name).twice.and_return('entity_2')
652
+ entity_2.should_receive(:add_tags).with('app')
653
+
654
+ entities = [{:entity => entity_1}, {:entity => entity_2}]
655
+ contact.should_receive(:entities).and_return(entities)
656
+ tag_data = [{:entity => entity_1, :tags => ['web']},
657
+ {:entity => entity_2, :tags => ['app']}]
658
+ contact.should_receive(:entities).with(:tags => true).and_return(tag_data)
659
+
660
+ Flapjack::Data::Contact.should_receive(:find_by_id).
661
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
662
+
663
+ post "contacts/#{contact.id}/entity_tags",
664
+ :entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
665
+ last_response.should be_ok
666
+ tag_response = {'entity_1' => ['web'],
667
+ 'entity_2' => ['app']}
668
+ last_response.body.should be_json_eql( tag_response.to_json )
669
+ end
670
+
671
+ it "does not add tags to multiple entities for a contact that's not found" do
672
+ Flapjack::Data::Contact.should_receive(:find_by_id).
673
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
674
+
675
+ post "contacts/#{contact.id}/entity_tags",
676
+ :entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
677
+ last_response.should be_forbidden
678
+ end
679
+
680
+ it "deletes tags from multiple entities for a contact" do
681
+ entity_1 = mock(Flapjack::Data::Entity)
682
+ entity_1.should_receive(:name).and_return('entity_1')
683
+ entity_1.should_receive(:delete_tags).with('web')
684
+ entity_2 = mock(Flapjack::Data::Entity)
685
+ entity_2.should_receive(:name).and_return('entity_2')
686
+ entity_2.should_receive(:delete_tags).with('app')
687
+
688
+ entities = [{:entity => entity_1}, {:entity => entity_2}]
689
+ contact.should_receive(:entities).and_return(entities)
690
+
691
+ Flapjack::Data::Contact.should_receive(:find_by_id).
692
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
693
+
694
+ delete "contacts/#{contact.id}/entity_tags",
695
+ :entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
696
+ last_response.status.should == 204
697
+ end
698
+
699
+ it "does not delete tags from multiple entities for a contact that's not found" do
700
+ Flapjack::Data::Contact.should_receive(:find_by_id).
701
+ with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
702
+
703
+ delete "contacts/#{contact.id}/entity_tags",
704
+ :entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
705
+ last_response.should be_forbidden
706
+ end
707
+
708
+
709
+ end