flapjack 0.7.16 → 0.7.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -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