flapjack 0.6.61 → 0.7.0
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.
- data/Gemfile +2 -1
- data/README.md +8 -4
- data/features/events.feature +269 -146
- data/features/notification_rules.feature +93 -0
- data/features/steps/events_steps.rb +162 -21
- data/features/steps/notifications_steps.rb +1 -1
- data/features/steps/time_travel_steps.rb +30 -19
- data/features/support/env.rb +71 -1
- data/flapjack.gemspec +3 -0
- data/lib/flapjack/data/contact.rb +256 -57
- data/lib/flapjack/data/entity.rb +2 -1
- data/lib/flapjack/data/entity_check.rb +22 -7
- data/lib/flapjack/data/global.rb +1 -0
- data/lib/flapjack/data/message.rb +2 -0
- data/lib/flapjack/data/notification_rule.rb +172 -0
- data/lib/flapjack/data/tag.rb +7 -2
- data/lib/flapjack/data/tag_set.rb +16 -0
- data/lib/flapjack/executive.rb +147 -13
- data/lib/flapjack/filters/delays.rb +21 -9
- data/lib/flapjack/gateways/api.rb +407 -27
- data/lib/flapjack/gateways/pagerduty.rb +1 -1
- data/lib/flapjack/gateways/web.rb +50 -22
- data/lib/flapjack/gateways/web/views/self_stats.haml +2 -0
- data/lib/flapjack/utility.rb +10 -0
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/data/contact_spec.rb +103 -6
- data/spec/lib/flapjack/data/global_spec.rb +2 -0
- data/spec/lib/flapjack/data/message_spec.rb +6 -0
- data/spec/lib/flapjack/data/notification_rule_spec.rb +22 -0
- data/spec/lib/flapjack/data/notification_spec.rb +6 -0
- data/spec/lib/flapjack/gateways/api_spec.rb +727 -4
- data/spec/lib/flapjack/gateways/jabber_spec.rb +1 -0
- data/spec/lib/flapjack/gateways/web_spec.rb +11 -1
- data/spec/spec_helper.rb +10 -0
- data/tmp/notification_rules.rb +73 -0
- data/tmp/test_json_post.rb +16 -0
- data/tmp/test_notification_rules_api.rb +170 -0
- metadata +59 -2
@@ -37,7 +37,7 @@ module Flapjack
|
|
37
37
|
|
38
38
|
def start
|
39
39
|
@logger.info("starting")
|
40
|
-
while not test_pagerduty_connection do
|
40
|
+
while not test_pagerduty_connection and not @should_quit do
|
41
41
|
@logger.error("Can't connect to the pagerduty API, retrying after 10 seconds")
|
42
42
|
EM::Synchrony.sleep(10)
|
43
43
|
end
|
@@ -19,28 +19,21 @@ module Flapjack
|
|
19
19
|
|
20
20
|
class Web < Sinatra::Base
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
[s, h, b]
|
34
|
-
else
|
35
|
-
@logger.error e.message
|
36
|
-
@logger.error e.backtrace.join("\n")
|
37
|
-
[503, {}, ""]
|
38
|
-
end
|
22
|
+
rescue_exception = Proc.new do |env, e|
|
23
|
+
if settings.show_exceptions?
|
24
|
+
# ensure the sinatra error page shows properly
|
25
|
+
request = Sinatra::Request.new(env)
|
26
|
+
printer = Sinatra::ShowExceptions.new(proc{ raise e })
|
27
|
+
s, h, b = printer.call(env)
|
28
|
+
[s, h, b]
|
29
|
+
else
|
30
|
+
@logger.error e.message
|
31
|
+
@logger.error e.backtrace.join("\n")
|
32
|
+
[503, {}, ""]
|
39
33
|
end
|
40
|
-
|
41
|
-
# doesn't work with Rack::Test unless we wrap tests in EM.synchrony blocks
|
42
|
-
use Rack::FiberPool, :size => 25, :rescue_exception => rescue_exception
|
43
34
|
end
|
35
|
+
use Rack::FiberPool, :size => 25, :rescue_exception => rescue_exception
|
36
|
+
|
44
37
|
use Rack::MethodOverride
|
45
38
|
|
46
39
|
class << self
|
@@ -49,7 +42,13 @@ module Flapjack
|
|
49
42
|
|
50
43
|
@logger.info "starting web - class"
|
51
44
|
|
52
|
-
if @config && @config['access_log']
|
45
|
+
if accesslog = (@config && @config['access_log'])
|
46
|
+
if not File.directory?(File.dirname(accesslog))
|
47
|
+
puts "Parent directory for log file #{accesslog} doesn't exist"
|
48
|
+
puts "Exiting!"
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
53
52
|
access_logger = Flapjack::AsyncLogger.new(@config['access_log'])
|
54
53
|
use Flapjack::CommonLogger, access_logger
|
55
54
|
end
|
@@ -95,6 +94,35 @@ module Flapjack
|
|
95
94
|
haml :self_stats
|
96
95
|
end
|
97
96
|
|
97
|
+
get '/self_stats.json' do
|
98
|
+
self_stats
|
99
|
+
|
100
|
+
{
|
101
|
+
'events_queued' => @events_queued,
|
102
|
+
'failing_services' => @count,
|
103
|
+
'processed_events' => {
|
104
|
+
'all_time' => {
|
105
|
+
'total' => @event_counters['all'],
|
106
|
+
'ok' => @event_counters['ok'],
|
107
|
+
'failure' => @event_counters['failure'],
|
108
|
+
'action' => @event_counters['action'],
|
109
|
+
},
|
110
|
+
'instance' => {
|
111
|
+
'total' => @event_counters_instance['all'],
|
112
|
+
'ok' => @event_counters_instance['ok'],
|
113
|
+
'failure' => @event_counters_instance['failure'],
|
114
|
+
'action' => @event_counters_instance['action'],
|
115
|
+
'average' => @event_rate_all,
|
116
|
+
}
|
117
|
+
},
|
118
|
+
'total_keys' => @keys.length,
|
119
|
+
'uptime' => @uptime_string,
|
120
|
+
'boottime' => @boot_time,
|
121
|
+
'current_time' => Time.now,
|
122
|
+
'executive_instances' => @executive_instances,
|
123
|
+
}.to_json
|
124
|
+
end
|
125
|
+
|
98
126
|
get '/check' do
|
99
127
|
@entity = params[:entity]
|
100
128
|
@check = params[:check]
|
@@ -217,7 +245,7 @@ module Flapjack
|
|
217
245
|
@pagerduty_credentials = @contact.pagerduty_credentials
|
218
246
|
end
|
219
247
|
|
220
|
-
@entities_and_checks = @contact.
|
248
|
+
@entities_and_checks = @contact.entities(:checks => true).sort_by {|ec|
|
221
249
|
ec[:entity].name
|
222
250
|
}
|
223
251
|
|
data/lib/flapjack/utility.rb
CHANGED
@@ -42,5 +42,15 @@ module Flapjack
|
|
42
42
|
"#{tzname} (UTC#{tzoffset})"
|
43
43
|
end
|
44
44
|
|
45
|
+
def remove_utc_offset(time)
|
46
|
+
Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec)
|
47
|
+
end
|
48
|
+
|
49
|
+
def symbolize(obj)
|
50
|
+
return obj.inject({}){|memo,(k,v)| memo[k.to_sym] = symbolize(v); memo} if obj.is_a? Hash
|
51
|
+
return obj.inject([]){|memo,v | memo << symbolize(v); memo} if obj.is_a? Array
|
52
|
+
return obj
|
53
|
+
end
|
54
|
+
|
45
55
|
end
|
46
56
|
end
|
data/lib/flapjack/version.rb
CHANGED
@@ -1,10 +1,28 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
require 'active_support/time_with_zone'
|
4
|
+
require 'ice_cube'
|
5
|
+
|
3
6
|
require 'flapjack/data/contact'
|
4
7
|
require 'flapjack/data/entity_check'
|
8
|
+
require 'flapjack/data/notification_rule'
|
5
9
|
|
6
10
|
describe Flapjack::Data::Contact, :redis => true do
|
7
11
|
|
12
|
+
weekdays_8_18 = IceCube::Schedule.new(Time.local(2013,2,1,8,0,0), :duration => 60 * 60 * 10)
|
13
|
+
weekdays_8_18.add_recurrence_rule(IceCube::Rule.weekly.day(:monday, :tuesday, :wednesday, :thursday, :friday))
|
14
|
+
|
15
|
+
let(:notification_rule_data) {
|
16
|
+
{:entity_tags => ["database","physical"],
|
17
|
+
:entities => ["foo-app-01.example.com"],
|
18
|
+
:time_restrictions => [ weekdays_8_18.to_hash ],
|
19
|
+
:warning_media => ["email"],
|
20
|
+
:critical_media => ["sms", "email"],
|
21
|
+
:warning_blackhole => false,
|
22
|
+
:critical_blackhole => false
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
8
26
|
before(:each) do
|
9
27
|
Flapjack::Data::Contact.add({'id' => '362',
|
10
28
|
'first_name' => 'John',
|
@@ -42,14 +60,93 @@ describe Flapjack::Data::Contact, :redis => true do
|
|
42
60
|
contact.name.should == "John Johnson"
|
43
61
|
end
|
44
62
|
|
45
|
-
it "
|
46
|
-
Flapjack::Data::Contact.delete_all(:redis => @redis)
|
47
|
-
contact = Flapjack::Data::Contact.find_by_id('362', :redis => @redis)
|
48
|
-
contact.should be_nil
|
63
|
+
it "adds a contact with the same id as an existing one, clears notification rules" do
|
49
64
|
contact = Flapjack::Data::Contact.find_by_id('363', :redis => @redis)
|
50
|
-
contact.
|
65
|
+
contact.should_not be_nil
|
66
|
+
|
67
|
+
contact.add_notification_rule(notification_rule_data)
|
68
|
+
|
69
|
+
nr = contact.notification_rules
|
70
|
+
nr.should_not be_nil
|
71
|
+
nr.should have(1).notification_rule
|
72
|
+
|
73
|
+
Flapjack::Data::Contact.add({'id' => '363',
|
74
|
+
'first_name' => 'Smithy',
|
75
|
+
'last_name' => 'Smith',
|
76
|
+
'email' => 'smithys@example.com'},
|
77
|
+
:redis => @redis)
|
78
|
+
|
79
|
+
contact = Flapjack::Data::Contact.find_by_id('363', :redis => @redis)
|
80
|
+
contact.should_not be_nil
|
81
|
+
contact.name.should == 'Smithy Smith'
|
82
|
+
|
83
|
+
nr = contact.notification_rules
|
84
|
+
nr.should_not be_nil
|
85
|
+
nr.should be_empty
|
51
86
|
end
|
52
87
|
|
88
|
+
it "updates a contact, does not clear notification rules" do
|
89
|
+
contact = Flapjack::Data::Contact.find_by_id('363', :redis => @redis)
|
90
|
+
contact.should_not be_nil
|
91
|
+
|
92
|
+
contact.add_notification_rule(notification_rule_data)
|
93
|
+
|
94
|
+
nr = contact.notification_rules
|
95
|
+
nr.should_not be_nil
|
96
|
+
nr.should have(1).notification_rule
|
97
|
+
|
98
|
+
contact.update('first_name' => 'John',
|
99
|
+
'last_name' => 'Smith',
|
100
|
+
'email' => 'johns@example.com')
|
101
|
+
contact.name.should == 'John Smith'
|
102
|
+
|
103
|
+
nr = contact.notification_rules
|
104
|
+
nr.should_not be_nil
|
105
|
+
nr.should have(1).notification_rule
|
106
|
+
end
|
107
|
+
|
108
|
+
it "adds a notification rule for a contact" do
|
109
|
+
contact = Flapjack::Data::Contact.find_by_id('363', :redis => @redis)
|
110
|
+
contact.should_not be_nil
|
111
|
+
|
112
|
+
expect {
|
113
|
+
contact.add_notification_rule(notification_rule_data)
|
114
|
+
}.to change { contact.notification_rules.size }.from(0).to(1)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "removes a notification rule from a contact" do
|
118
|
+
contact = Flapjack::Data::Contact.find_by_id('363', :redis => @redis)
|
119
|
+
contact.should_not be_nil
|
120
|
+
|
121
|
+
rule = contact.add_notification_rule(notification_rule_data)
|
122
|
+
|
123
|
+
expect {
|
124
|
+
contact.delete_notification_rule(rule)
|
125
|
+
}.to change { contact.notification_rules.size }.from(1).to(0)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "deletes a contact by id, including linked entities, checks, tags and notification rules" do
|
129
|
+
contact = Flapjack::Data::Contact.find_by_id('362', :redis => @redis)
|
130
|
+
contact.add_tags('admin')
|
131
|
+
|
132
|
+
entity_name = 'abc-123'
|
133
|
+
|
134
|
+
entity = Flapjack::Data::Entity.add({'id' => '5000',
|
135
|
+
'name' => entity_name,
|
136
|
+
'contacts' => ['362']},
|
137
|
+
:redis => @redis)
|
138
|
+
|
139
|
+
expect {
|
140
|
+
expect {
|
141
|
+
expect {
|
142
|
+
contact.delete!
|
143
|
+
}.to change { Flapjack::Data::Contact.all(:redis => @redis).size }.by(-1)
|
144
|
+
}.to change { @redis.smembers('contact_tag:admin').size }.by(-1)
|
145
|
+
}.to change { entity.contacts.size }.by(-1)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "deletes all contacts"
|
149
|
+
|
53
150
|
it "returns a list of entities and their checks for a contact" do
|
54
151
|
entity_name = 'abc-123'
|
55
152
|
|
@@ -63,7 +160,7 @@ describe Flapjack::Data::Contact, :redis => true do
|
|
63
160
|
ec.update_state('ok', :timestamp => t, :summary => 'a')
|
64
161
|
|
65
162
|
contact = Flapjack::Data::Contact.find_by_id('362', :redis => @redis)
|
66
|
-
eandcs = contact.
|
163
|
+
eandcs = contact.entities(:checks => true)
|
67
164
|
eandcs.should_not be_nil
|
68
165
|
eandcs.should be_an(Array)
|
69
166
|
eandcs.should have(1).entity_and_checks
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'flapjack/data/notification_rule'
|
3
|
+
|
4
|
+
describe Flapjack::Data::NotificationRule do
|
5
|
+
|
6
|
+
it "checks that a notification rule exists"
|
7
|
+
|
8
|
+
it "returns a notification rule if it exists"
|
9
|
+
|
10
|
+
it "does not return a notification rule if it does not exist"
|
11
|
+
|
12
|
+
it "updates a notification rule"
|
13
|
+
|
14
|
+
it "checks whether tag or entity names match"
|
15
|
+
|
16
|
+
it "checks whether times match"
|
17
|
+
|
18
|
+
it "checks if blackhole settings for a rule match a severity level"
|
19
|
+
|
20
|
+
it "returns the media settings for a rule's severity level"
|
21
|
+
|
22
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'flapjack/gateways/api'
|
3
3
|
|
4
|
-
describe 'Flapjack::Gateways::API', :sinatra => true, :logger => true do
|
4
|
+
describe 'Flapjack::Gateways::API', :sinatra => true, :logger => true, :json => true do
|
5
5
|
|
6
6
|
def app
|
7
7
|
Flapjack::Gateways::API
|
@@ -14,11 +14,58 @@ describe 'Flapjack::Gateways::API', :sinatra => true, :logger => true do
|
|
14
14
|
let(:entity_name_esc) { URI.escape(entity_name) }
|
15
15
|
let(:check) { 'ping' }
|
16
16
|
|
17
|
+
let(:contact) { mock(Flapjack::Data::Contact, :id => '21') }
|
18
|
+
let(:contact_core) {
|
19
|
+
{'id' => contact.id,
|
20
|
+
'first_name' => "Ada",
|
21
|
+
'last_name' => "Lovelace",
|
22
|
+
'email' => "ada@example.com",
|
23
|
+
'tags' => ["legend", "first computer programmer"]
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
let(:media) {
|
28
|
+
{'email' => 'ada@example.com',
|
29
|
+
'sms' => '04123456789'
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
let(:media_intervals) {
|
34
|
+
{'email' => 500,
|
35
|
+
'sms' => 300
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
17
39
|
let(:entity_presenter) { mock(Flapjack::Gateways::API::EntityPresenter) }
|
18
40
|
let(:entity_check_presenter) { mock(Flapjack::Gateways::API::EntityCheckPresenter) }
|
19
41
|
|
20
42
|
let(:redis) { mock(::Redis) }
|
21
43
|
|
44
|
+
let(:notification_rule) {
|
45
|
+
mock(Flapjack::Data::NotificationRule, :id => '1', :contact_id => '21')
|
46
|
+
}
|
47
|
+
|
48
|
+
let(:notification_rule_data) {
|
49
|
+
{"contact_id" => "21",
|
50
|
+
"entity_tags" => ["database","physical"],
|
51
|
+
"entities" => ["foo-app-01.example.com"],
|
52
|
+
"time_restrictions" => nil,
|
53
|
+
"warning_media" => ["email"],
|
54
|
+
"critical_media" => ["sms", "email"],
|
55
|
+
"warning_blackhole" => false,
|
56
|
+
"critical_blackhole" => false
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
before(:all) do
|
61
|
+
Flapjack::Gateways::API.class_eval {
|
62
|
+
set :raise_errors, true
|
63
|
+
}
|
64
|
+
Flapjack::Gateways::API.instance_variable_get('@middleware').delete_if {|m|
|
65
|
+
m[0] == Rack::FiberPool
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
22
69
|
before(:each) do
|
23
70
|
Flapjack::RedisPool.should_receive(:new).and_return(redis)
|
24
71
|
Flapjack::Gateways::API.instance_variable_set('@config', {})
|
@@ -290,7 +337,7 @@ describe 'Flapjack::Gateways::API', :sinatra => true, :logger => true do
|
|
290
337
|
]
|
291
338
|
}
|
292
339
|
|
293
|
-
Flapjack::Data::Contact.should_receive(:
|
340
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([])
|
294
341
|
Flapjack::Data::Contact.should_receive(:add).twice
|
295
342
|
|
296
343
|
post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
|
@@ -298,7 +345,6 @@ describe 'Flapjack::Gateways::API', :sinatra => true, :logger => true do
|
|
298
345
|
end
|
299
346
|
|
300
347
|
it "does not create contacts if the data is improperly formatted" do
|
301
|
-
Flapjack::Data::Contact.should_not_receive(:delete_all)
|
302
348
|
Flapjack::Data::Contact.should_not_receive(:add)
|
303
349
|
|
304
350
|
post "/contacts", {'contacts' => ["Hello", "again"]}.to_json,
|
@@ -321,11 +367,688 @@ describe 'Flapjack::Gateways::API', :sinatra => true, :logger => true do
|
|
321
367
|
]
|
322
368
|
}
|
323
369
|
|
324
|
-
Flapjack::Data::Contact.should_receive(:
|
370
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([])
|
325
371
|
Flapjack::Data::Contact.should_receive(:add)
|
326
372
|
|
327
373
|
post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
|
328
374
|
last_response.status.should == 200
|
329
375
|
end
|
330
376
|
|
377
|
+
it "updates a contact if it is already present" do
|
378
|
+
contacts = {'contacts' =>
|
379
|
+
[{"id" => "0362",
|
380
|
+
"first_name" => "John",
|
381
|
+
"last_name" => "Smith",
|
382
|
+
"email" => "johns@example.dom",
|
383
|
+
"media" => {"email" => "johns@example.dom",
|
384
|
+
"jabber" => "johns@conference.localhost"}},
|
385
|
+
{"id" => "0363",
|
386
|
+
"first_name" => "Jane",
|
387
|
+
"last_name" => "Jones",
|
388
|
+
"email" => "jane@example.dom",
|
389
|
+
"media" => {"email" => "jane@example.dom"}}
|
390
|
+
]
|
391
|
+
}
|
392
|
+
|
393
|
+
existing = mock(Flapjack::Data::Contact)
|
394
|
+
existing.should_receive(:id).and_return("0363")
|
395
|
+
existing.should_receive(:update).with(contacts['contacts'][1])
|
396
|
+
|
397
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([existing])
|
398
|
+
Flapjack::Data::Contact.should_receive(:add).with(contacts['contacts'][0], :redis => redis)
|
399
|
+
|
400
|
+
post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
|
401
|
+
last_response.status.should == 200
|
402
|
+
end
|
403
|
+
|
404
|
+
it "deletes a contact not found in a bulk update list" do
|
405
|
+
contacts = {'contacts' =>
|
406
|
+
[{"id" => "0363",
|
407
|
+
"first_name" => "Jane",
|
408
|
+
"last_name" => "Jones",
|
409
|
+
"email" => "jane@example.dom",
|
410
|
+
"media" => {"email" => "jane@example.dom"}}
|
411
|
+
]
|
412
|
+
}
|
413
|
+
|
414
|
+
existing = mock(Flapjack::Data::Contact)
|
415
|
+
existing.should_receive(:id).twice.and_return("0362")
|
416
|
+
existing.should_receive(:delete!)
|
417
|
+
|
418
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([existing])
|
419
|
+
Flapjack::Data::Contact.should_receive(:add).with(contacts['contacts'][0], :redis => redis)
|
420
|
+
|
421
|
+
post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
|
422
|
+
last_response.status.should == 200
|
423
|
+
end
|
424
|
+
|
425
|
+
it "returns all the contacts" do
|
426
|
+
contact.should_receive(:to_json).and_return(contact_core.to_json)
|
427
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).
|
428
|
+
and_return([contact])
|
429
|
+
|
430
|
+
get '/contacts'
|
431
|
+
last_response.should be_ok
|
432
|
+
last_response.body.should be_json_eql([contact_core].to_json)
|
433
|
+
end
|
434
|
+
|
435
|
+
it "returns the core information of a specified contact" do
|
436
|
+
contact.should_receive(:to_json).and_return(contact_core.to_json)
|
437
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
438
|
+
with(contact.id, :redis => redis).and_return(contact)
|
439
|
+
|
440
|
+
get "/contacts/#{contact.id}"
|
441
|
+
last_response.should be_ok
|
442
|
+
last_response.body.should be_json_eql(contact_core.to_json)
|
443
|
+
end
|
444
|
+
|
445
|
+
it "does not return information for a contact that does not exist" do
|
446
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
447
|
+
with(contact.id, :redis => redis).and_return(nil)
|
448
|
+
|
449
|
+
get "/contacts/#{contact.id}"
|
450
|
+
last_response.should be_not_found
|
451
|
+
end
|
452
|
+
|
453
|
+
it "lists a contact's notification rules" do
|
454
|
+
notification_rule_2 = mock(Flapjack::Data::NotificationRule, :id => '2', :contact_id => '21')
|
455
|
+
notification_rule.should_receive(:to_json).and_return('"rule_1"')
|
456
|
+
notification_rule_2.should_receive(:to_json).and_return('"rule_2"')
|
457
|
+
notification_rules = [ notification_rule, notification_rule_2 ]
|
458
|
+
|
459
|
+
contact.should_receive(:notification_rules).and_return(notification_rules)
|
460
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
461
|
+
with(contact.id, :redis => redis).and_return(contact)
|
462
|
+
|
463
|
+
get "/contacts/#{contact.id}/notification_rules"
|
464
|
+
last_response.should be_ok
|
465
|
+
last_response.body.should be_json_eql( '["rule_1", "rule_2"]' )
|
466
|
+
end
|
467
|
+
|
468
|
+
it "does not list notification rules for a contact that does not exist" do
|
469
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
470
|
+
with(contact.id, :redis => redis).and_return(nil)
|
471
|
+
|
472
|
+
get "/contacts/#{contact.id}/notification_rules"
|
473
|
+
last_response.should be_not_found
|
474
|
+
end
|
475
|
+
|
476
|
+
it "returns a specified notification rule" do
|
477
|
+
notification_rule.should_receive(:to_json).and_return('"rule_1"')
|
478
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
479
|
+
with(notification_rule.id, :redis => redis).and_return(notification_rule)
|
480
|
+
|
481
|
+
get "/notification_rules/#{notification_rule.id}"
|
482
|
+
last_response.should be_ok
|
483
|
+
last_response.body.should be_json_eql('"rule_1"')
|
484
|
+
end
|
485
|
+
|
486
|
+
it "does not return a notification rule that does not exist" do
|
487
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
488
|
+
with(notification_rule.id, :redis => redis).and_return(nil)
|
489
|
+
|
490
|
+
get "/notification_rules/#{notification_rule.id}"
|
491
|
+
last_response.should be_not_found
|
492
|
+
end
|
493
|
+
|
494
|
+
# POST /notification_rules
|
495
|
+
it "creates a new notification rule" do
|
496
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
497
|
+
with(contact.id, :redis => redis).and_return(contact)
|
498
|
+
notification_rule.should_receive(:to_json).and_return('"rule_1"')
|
499
|
+
|
500
|
+
# symbolize the keys
|
501
|
+
notification_rule_data_sym = notification_rule_data.inject({}){|memo,(k,v)|
|
502
|
+
memo[k.to_sym] = v; memo
|
503
|
+
}
|
504
|
+
notification_rule_data_sym.delete(:contact_id)
|
505
|
+
|
506
|
+
contact.should_receive(:add_notification_rule).
|
507
|
+
with(notification_rule_data_sym).and_return(notification_rule)
|
508
|
+
|
509
|
+
post "/notification_rules", notification_rule_data.to_json,
|
510
|
+
{'CONTENT_TYPE' => 'application/json'}
|
511
|
+
last_response.should be_ok
|
512
|
+
last_response.body.should be_json_eql('"rule_1"')
|
513
|
+
end
|
514
|
+
|
515
|
+
it "does not create a notification_rule for a contact that's not present" do
|
516
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
517
|
+
with(contact.id, :redis => redis).and_return(nil)
|
518
|
+
|
519
|
+
post "/notification_rules", notification_rule_data.to_json,
|
520
|
+
{'CONTENT_TYPE' => 'application/json'}
|
521
|
+
last_response.should be_not_found
|
522
|
+
end
|
523
|
+
|
524
|
+
it "does not create a notification_rule if a rule id is provided" do
|
525
|
+
contact.should_not_receive(:add_notification_rule)
|
526
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
527
|
+
with(contact.id, :redis => redis).and_return(contact)
|
528
|
+
|
529
|
+
post "/notification_rules", notification_rule_data.merge(:id => 1).to_json,
|
530
|
+
{'CONTENT_TYPE' => 'application/json'}
|
531
|
+
last_response.status.should == 403
|
532
|
+
end
|
533
|
+
|
534
|
+
# PUT /notification_rules/RULE_ID
|
535
|
+
it "updates a notification rule" do
|
536
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
537
|
+
with(contact.id, :redis => redis).and_return(contact)
|
538
|
+
notification_rule.should_receive(:to_json).and_return('"rule_1"')
|
539
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
540
|
+
with(notification_rule.id, :redis => redis).and_return(notification_rule)
|
541
|
+
|
542
|
+
# symbolize the keys
|
543
|
+
notification_rule_data_sym = notification_rule_data.inject({}){|memo,(k,v)|
|
544
|
+
memo[k.to_sym] = v; memo
|
545
|
+
}
|
546
|
+
notification_rule_data_sym.delete(:contact_id)
|
547
|
+
|
548
|
+
notification_rule.should_receive(:update).with(notification_rule_data_sym)
|
549
|
+
|
550
|
+
put "/notification_rules/#{notification_rule.id}", notification_rule_data.to_json,
|
551
|
+
{'CONTENT_TYPE' => 'application/json'}
|
552
|
+
last_response.should be_ok
|
553
|
+
last_response.body.should be_json_eql('"rule_1"')
|
554
|
+
end
|
555
|
+
|
556
|
+
it "does not update a notification rule that's not present" do
|
557
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
558
|
+
with(contact.id, :redis => redis).and_return(contact)
|
559
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
560
|
+
with(notification_rule.id, :redis => redis).and_return(nil)
|
561
|
+
|
562
|
+
put "/notification_rules/#{notification_rule.id}", notification_rule_data
|
563
|
+
last_response.should be_not_found
|
564
|
+
end
|
565
|
+
|
566
|
+
it "does not update a notification_rule for a contact that's not present" do
|
567
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
568
|
+
with(contact.id, :redis => redis).and_return(nil)
|
569
|
+
|
570
|
+
put "/notification_rules/#{notification_rule.id}", notification_rule_data.to_json,
|
571
|
+
{'CONTENT_TYPE' => 'application/json'}
|
572
|
+
last_response.should be_not_found
|
573
|
+
end
|
574
|
+
|
575
|
+
# DELETE /notification_rules/RULE_ID
|
576
|
+
it "deletes a notification rule" do
|
577
|
+
notification_rule.should_receive(:contact_id).and_return(contact.id)
|
578
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
579
|
+
with(notification_rule.id, :redis => redis).and_return(notification_rule)
|
580
|
+
contact.should_receive(:delete_notification_rule).with(notification_rule)
|
581
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
582
|
+
with(contact.id, :redis => redis).and_return(contact)
|
583
|
+
|
584
|
+
delete "/notification_rules/#{notification_rule.id}"
|
585
|
+
last_response.status.should == 204
|
586
|
+
end
|
587
|
+
|
588
|
+
it "does not delete a notification rule that's not present" do
|
589
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
590
|
+
with(notification_rule.id, :redis => redis).and_return(nil)
|
591
|
+
|
592
|
+
delete "/notification_rules/#{notification_rule.id}"
|
593
|
+
last_response.should be_not_found
|
594
|
+
end
|
595
|
+
|
596
|
+
it "does not delete a notification rule if the contact is not present" do
|
597
|
+
notification_rule.should_receive(:contact_id).and_return(contact.id)
|
598
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
599
|
+
with(notification_rule.id, :redis => redis).and_return(notification_rule)
|
600
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
601
|
+
with(contact.id, :redis => redis).and_return(nil)
|
602
|
+
|
603
|
+
delete "/notification_rules/#{notification_rule.id}"
|
604
|
+
last_response.should be_not_found
|
605
|
+
end
|
606
|
+
|
607
|
+
# GET /contacts/CONTACT_ID/media
|
608
|
+
it "returns the media of a contact" do
|
609
|
+
contact.should_receive(:media).and_return(media)
|
610
|
+
contact.should_receive(:media_intervals).and_return(media_intervals)
|
611
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
612
|
+
with(contact.id, :redis => redis).and_return(contact)
|
613
|
+
result = Hash[ *(media.keys.collect {|m|
|
614
|
+
[m, {'address' => media[m],
|
615
|
+
'interval' => media_intervals[m] }]
|
616
|
+
}).flatten(1)].to_json
|
617
|
+
|
618
|
+
get "/contacts/#{contact.id}/media"
|
619
|
+
last_response.should be_ok
|
620
|
+
last_response.body.should be_json_eql(result)
|
621
|
+
end
|
622
|
+
|
623
|
+
it "does not return the media of a contact if the contact is not present" do
|
624
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
625
|
+
with(contact.id, :redis => redis).and_return(nil)
|
626
|
+
|
627
|
+
get "/contacts/#{contact.id}/media"
|
628
|
+
last_response.should be_not_found
|
629
|
+
end
|
630
|
+
|
631
|
+
# GET /contacts/CONTACT_ID/media/MEDIA
|
632
|
+
it "returns the specified media of a contact" do
|
633
|
+
contact.should_receive(:media).twice.and_return(media)
|
634
|
+
contact.should_receive(:media_intervals).and_return(media_intervals)
|
635
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
636
|
+
with(contact.id, :redis => redis).and_return(contact)
|
637
|
+
|
638
|
+
result = {'address' => media['sms'], 'interval' => media_intervals['sms']}
|
639
|
+
|
640
|
+
get "/contacts/#{contact.id}/media/sms"
|
641
|
+
last_response.should be_ok
|
642
|
+
last_response.body.should be_json_eql(result.to_json)
|
643
|
+
end
|
644
|
+
|
645
|
+
it "does not return the media of a contact if the contact is not present" do
|
646
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
647
|
+
with(contact.id, :redis => redis).and_return(nil)
|
648
|
+
|
649
|
+
get "/contacts/#{contact.id}/media/sms"
|
650
|
+
last_response.should be_not_found
|
651
|
+
end
|
652
|
+
|
653
|
+
it "does not return the media of a contact if the media is not present" do
|
654
|
+
contact.should_receive(:media).and_return(media)
|
655
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
656
|
+
with(contact.id, :redis => redis).and_return(contact)
|
657
|
+
|
658
|
+
get "/contacts/#{contact.id}/media/telepathy"
|
659
|
+
last_response.should be_not_found
|
660
|
+
end
|
661
|
+
|
662
|
+
# PUT, DELETE /contacts/CONTACT_ID/media/MEDIA
|
663
|
+
it "creates/updates a media of a contact" do
|
664
|
+
# as far as API is concerned these are the same -- contact.rb spec test
|
665
|
+
# may distinguish between them
|
666
|
+
alt_media = media.merge('sms' => '04987654321')
|
667
|
+
alt_media_intervals = media_intervals.merge('sms' => '200')
|
668
|
+
|
669
|
+
contact.should_receive(:set_address_for_media).with('sms', '04987654321')
|
670
|
+
contact.should_receive(:set_interval_for_media).with('sms', '200')
|
671
|
+
contact.should_receive(:media).and_return(alt_media)
|
672
|
+
contact.should_receive(:media_intervals).and_return(alt_media_intervals)
|
673
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
674
|
+
with(contact.id, :redis => redis).and_return(contact)
|
675
|
+
|
676
|
+
result = {'address' => alt_media['sms'], 'interval' => alt_media_intervals['sms']}
|
677
|
+
|
678
|
+
put "/contacts/#{contact.id}/media/sms", {:address => '04987654321', :interval => '200'}
|
679
|
+
last_response.should be_ok
|
680
|
+
last_response.body.should be_json_eql(result.to_json)
|
681
|
+
end
|
682
|
+
|
683
|
+
it "does not create a media of a contact that's not present" do
|
684
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
685
|
+
with(contact.id, :redis => redis).and_return(nil)
|
686
|
+
|
687
|
+
put "/contacts/#{contact.id}/media/sms", {:address => '04987654321', :interval => '200'}
|
688
|
+
last_response.should be_not_found
|
689
|
+
end
|
690
|
+
|
691
|
+
it "does not create a media of a contact if no address is provided" do
|
692
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
693
|
+
with(contact.id, :redis => redis).and_return(contact)
|
694
|
+
|
695
|
+
put "/contacts/#{contact.id}/media/sms", {:interval => '200'}
|
696
|
+
last_response.should be_forbidden
|
697
|
+
end
|
698
|
+
|
699
|
+
it "does not create a media of a contact if no interval is provided" do
|
700
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
701
|
+
with(contact.id, :redis => redis).and_return(contact)
|
702
|
+
|
703
|
+
put "/contacts/#{contact.id}/media/sms", {:address => '04987654321'}
|
704
|
+
last_response.should be_forbidden
|
705
|
+
end
|
706
|
+
|
707
|
+
it "deletes a media of a contact" do
|
708
|
+
contact.should_receive(:remove_media).with('sms')
|
709
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
710
|
+
with(contact.id, :redis => redis).and_return(contact)
|
711
|
+
|
712
|
+
delete "/contacts/#{contact.id}/media/sms"
|
713
|
+
last_response.status.should == 204
|
714
|
+
end
|
715
|
+
|
716
|
+
it "does not delete a media of a contact that's not present" do
|
717
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
718
|
+
with(contact.id, :redis => redis).and_return(nil)
|
719
|
+
|
720
|
+
delete "/contacts/#{contact.id}/media/sms"
|
721
|
+
last_response.should be_not_found
|
722
|
+
end
|
723
|
+
|
724
|
+
# GET /contacts/CONTACT_ID/timezone
|
725
|
+
it "returns the timezone of a contact" do
|
726
|
+
contact.should_receive(:timezone).and_return(::ActiveSupport::TimeZone.new('Australia/Sydney'))
|
727
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
728
|
+
with(contact.id, :redis => redis).and_return(contact)
|
729
|
+
|
730
|
+
get "/contacts/#{contact.id}/timezone"
|
731
|
+
last_response.should be_ok
|
732
|
+
last_response.body.should be_json_eql('"Australia/Sydney"')
|
733
|
+
end
|
734
|
+
|
735
|
+
it "doesn't get the timezone of a contact that doesn't exist" do
|
736
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
737
|
+
with(contact.id, :redis => redis).and_return(nil)
|
738
|
+
|
739
|
+
get "/contacts/#{contact.id}/timezone"
|
740
|
+
last_response.should be_not_found
|
741
|
+
end
|
742
|
+
|
743
|
+
# PUT /contacts/CONTACT_ID/timezone
|
744
|
+
it "sets the timezone of a contact" do
|
745
|
+
contact.should_receive(:timezone=).with('Australia/Perth')
|
746
|
+
contact.should_receive(:timezone).and_return(ActiveSupport::TimeZone.new('Australia/Perth'))
|
747
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
748
|
+
with(contact.id, :redis => redis).and_return(contact)
|
749
|
+
|
750
|
+
put "/contacts/#{contact.id}/timezone", {:timezone => 'Australia/Perth'}
|
751
|
+
last_response.should be_ok
|
752
|
+
end
|
753
|
+
|
754
|
+
it "doesn't set the timezone of a contact who can't be found" do
|
755
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
756
|
+
with(contact.id, :redis => redis).and_return(nil)
|
757
|
+
|
758
|
+
put "/contacts/#{contact.id}/timezone", {:timezone => 'Australia/Perth'}
|
759
|
+
last_response.should be_not_found
|
760
|
+
end
|
761
|
+
|
762
|
+
# DELETE /contacts/CONTACT_ID/timezone
|
763
|
+
it "deletes the timezone of a contact" do
|
764
|
+
contact.should_receive(:timezone=).with(nil)
|
765
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
766
|
+
with(contact.id, :redis => redis).and_return(contact)
|
767
|
+
|
768
|
+
delete "/contacts/#{contact.id}/timezone"
|
769
|
+
last_response.status.should == 204
|
770
|
+
end
|
771
|
+
|
772
|
+
it "does not delete the timezone of a contact that's not present" do
|
773
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
774
|
+
with(contact.id, :redis => redis).and_return(nil)
|
775
|
+
|
776
|
+
delete "/contacts/#{contact.id}/timezone"
|
777
|
+
last_response.should be_not_found
|
778
|
+
end
|
779
|
+
|
780
|
+
|
781
|
+
|
782
|
+
it "sets a single tag on an entity and returns current tags" do
|
783
|
+
entity.should_receive(:add_tags).with('web')
|
784
|
+
entity.should_receive(:tags).and_return(['web'])
|
785
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
786
|
+
with(entity_name, :redis => redis).and_return(entity)
|
787
|
+
|
788
|
+
post "entities/#{entity_name}/tags", :tag => 'web'
|
789
|
+
last_response.should be_ok
|
790
|
+
last_response.body.should be_json_eql( ['web'].to_json )
|
791
|
+
end
|
792
|
+
|
793
|
+
it "does not set a single tag on an entity that's not found" do
|
794
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
795
|
+
with(entity_name, :redis => redis).and_return(nil)
|
796
|
+
|
797
|
+
post "entities/#{entity_name}/tags", :tag => 'web'
|
798
|
+
last_response.should be_not_found
|
799
|
+
end
|
800
|
+
|
801
|
+
it "sets multiple tags on an entity and returns current tags" do
|
802
|
+
entity.should_receive(:add_tags).with('web', 'app')
|
803
|
+
entity.should_receive(:tags).and_return(['web', 'app'])
|
804
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
805
|
+
with(entity_name, :redis => redis).and_return(entity)
|
806
|
+
|
807
|
+
# NB submitted at a lower level as tag[]=web&tag[]=app
|
808
|
+
post "entities/#{entity_name}/tags", :tag => ['web', 'app']
|
809
|
+
last_response.should be_ok
|
810
|
+
last_response.body.should be_json_eql( ['web', 'app'].to_json )
|
811
|
+
end
|
812
|
+
|
813
|
+
it "does not set multiple tags on an entity that's not found" do
|
814
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
815
|
+
with(entity_name, :redis => redis).and_return(nil)
|
816
|
+
|
817
|
+
post "entities/#{entity_name}/tags", :tag => ['web', 'app']
|
818
|
+
last_response.should be_not_found
|
819
|
+
end
|
820
|
+
|
821
|
+
it "removes a single tag from an entity" do
|
822
|
+
entity.should_receive(:delete_tags).with('web')
|
823
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
824
|
+
with(entity_name, :redis => redis).and_return(entity)
|
825
|
+
|
826
|
+
delete "entities/#{entity_name}/tags", :tag => 'web'
|
827
|
+
last_response.status.should == 204
|
828
|
+
end
|
829
|
+
|
830
|
+
it "does not remove a single tag from an entity that's not found" do
|
831
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
832
|
+
with(entity_name, :redis => redis).and_return(nil)
|
833
|
+
|
834
|
+
delete "entities/#{entity_name}/tags", :tag => 'web'
|
835
|
+
last_response.should be_not_found
|
836
|
+
end
|
837
|
+
|
838
|
+
it "removes multiple tags from an entity" do
|
839
|
+
entity.should_receive(:delete_tags).with('web', 'app')
|
840
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
841
|
+
with(entity_name, :redis => redis).and_return(entity)
|
842
|
+
|
843
|
+
delete "entities/#{entity_name}/tags", :tag => ['web', 'app']
|
844
|
+
last_response.status.should == 204
|
845
|
+
end
|
846
|
+
|
847
|
+
it "does not remove multiple tags from an entity that's not found" do
|
848
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
849
|
+
with(entity_name, :redis => redis).and_return(nil)
|
850
|
+
|
851
|
+
delete "entities/#{entity_name}/tags", :tag => ['web', 'app']
|
852
|
+
last_response.should be_not_found
|
853
|
+
end
|
854
|
+
|
855
|
+
it "gets all tags on an entity" do
|
856
|
+
entity.should_receive(:tags).and_return(['web', 'app'])
|
857
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
858
|
+
with(entity_name, :redis => redis).and_return(entity)
|
859
|
+
|
860
|
+
get "entities/#{entity_name}/tags"
|
861
|
+
last_response.should be_ok
|
862
|
+
last_response.body.should be_json_eql( ['web', 'app'].to_json )
|
863
|
+
end
|
864
|
+
|
865
|
+
it "does not get all tags on an entity that's not found" do
|
866
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
867
|
+
with(entity_name, :redis => redis).and_return(nil)
|
868
|
+
|
869
|
+
get "entities/#{entity_name}/tags"
|
870
|
+
last_response.should be_not_found
|
871
|
+
end
|
872
|
+
|
873
|
+
|
874
|
+
it "sets a single tag on a contact and returns current tags" do
|
875
|
+
contact.should_receive(:add_tags).with('web')
|
876
|
+
contact.should_receive(:tags).and_return(['web'])
|
877
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
878
|
+
with(contact.id, :redis => redis).and_return(contact)
|
879
|
+
|
880
|
+
post "contacts/#{contact.id}/tags", :tag => 'web'
|
881
|
+
last_response.should be_ok
|
882
|
+
last_response.body.should be_json_eql( ['web'].to_json )
|
883
|
+
end
|
884
|
+
|
885
|
+
it "does not set a single tag on a contact that's not found" do
|
886
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
887
|
+
with(contact.id, :redis => redis).and_return(nil)
|
888
|
+
|
889
|
+
post "contacts/#{contact.id}/tags", :tag => 'web'
|
890
|
+
last_response.should be_not_found
|
891
|
+
end
|
892
|
+
|
893
|
+
it "sets multiple tags on a contact and returns current tags" do
|
894
|
+
contact.should_receive(:add_tags).with('web', 'app')
|
895
|
+
contact.should_receive(:tags).and_return(['web', 'app'])
|
896
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
897
|
+
with(contact.id, :redis => redis).and_return(contact)
|
898
|
+
|
899
|
+
post "contacts/#{contact.id}/tags", :tag => ['web', 'app']
|
900
|
+
last_response.should be_ok
|
901
|
+
last_response.body.should be_json_eql( ['web', 'app'].to_json )
|
902
|
+
end
|
903
|
+
|
904
|
+
it "does not set multiple tags on a contact that's not found" do
|
905
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
906
|
+
with(contact.id, :redis => redis).and_return(nil)
|
907
|
+
|
908
|
+
post "contacts/#{contact.id}/tags", :tag => ['web', 'app']
|
909
|
+
last_response.should be_not_found
|
910
|
+
end
|
911
|
+
|
912
|
+
it "removes a single tag from a contact" do
|
913
|
+
contact.should_receive(:delete_tags).with('web')
|
914
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
915
|
+
with(contact.id, :redis => redis).and_return(contact)
|
916
|
+
|
917
|
+
delete "contacts/#{contact.id}/tags", :tag => 'web'
|
918
|
+
last_response.status.should == 204
|
919
|
+
end
|
920
|
+
|
921
|
+
it "does not remove a single tag from a contact that's not found" do
|
922
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
923
|
+
with(contact.id, :redis => redis).and_return(nil)
|
924
|
+
|
925
|
+
delete "contacts/#{contact.id}/tags", :tag => 'web'
|
926
|
+
last_response.should be_not_found
|
927
|
+
end
|
928
|
+
|
929
|
+
it "removes multiple tags from a contact" do
|
930
|
+
contact.should_receive(:delete_tags).with('web', 'app')
|
931
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
932
|
+
with(contact.id, :redis => redis).and_return(contact)
|
933
|
+
|
934
|
+
delete "contacts/#{contact.id}/tags", :tag => ['web', 'app']
|
935
|
+
last_response.status.should == 204
|
936
|
+
end
|
937
|
+
|
938
|
+
it "does not remove multiple tags from a contact that's not found" do
|
939
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
940
|
+
with(contact.id, :redis => redis).and_return(nil)
|
941
|
+
|
942
|
+
delete "contacts/#{contact.id}/tags", :tag => ['web', 'app']
|
943
|
+
last_response.should be_not_found
|
944
|
+
end
|
945
|
+
|
946
|
+
it "gets all tags on a contact" do
|
947
|
+
contact.should_receive(:tags).and_return(['web', 'app'])
|
948
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
949
|
+
with(contact.id, :redis => redis).and_return(contact)
|
950
|
+
|
951
|
+
get "contacts/#{contact.id}/tags"
|
952
|
+
last_response.should be_ok
|
953
|
+
last_response.body.should be_json_eql( ['web', 'app'].to_json )
|
954
|
+
end
|
955
|
+
|
956
|
+
it "does not get all tags on a contact that's not found" do
|
957
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
958
|
+
with(contact.id, :redis => redis).and_return(nil)
|
959
|
+
|
960
|
+
get "contacts/#{contact.id}/tags"
|
961
|
+
last_response.should be_not_found
|
962
|
+
end
|
963
|
+
|
964
|
+
it "gets all entity tags for a contact" do
|
965
|
+
entity_1 = mock(Flapjack::Data::Entity)
|
966
|
+
entity_1.should_receive(:name).and_return('entity_1')
|
967
|
+
entity_2 = mock(Flapjack::Data::Entity)
|
968
|
+
entity_2.should_receive(:name).and_return('entity_2')
|
969
|
+
tag_data = [{:entity => entity_1, :tags => ['web']},
|
970
|
+
{:entity => entity_2, :tags => ['app']}]
|
971
|
+
contact.should_receive(:entities).with(:tags => true).
|
972
|
+
and_return(tag_data)
|
973
|
+
|
974
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
975
|
+
with(contact.id, :redis => redis).and_return(contact)
|
976
|
+
|
977
|
+
get "contacts/#{contact.id}/entity_tags"
|
978
|
+
last_response.should be_ok
|
979
|
+
tag_response = {'entity_1' => ['web'],
|
980
|
+
'entity_2' => ['app']}
|
981
|
+
last_response.body.should be_json_eql( tag_response.to_json )
|
982
|
+
end
|
983
|
+
|
984
|
+
it "does not get all entity tags for a contact that's not found" do
|
985
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
986
|
+
with(contact.id, :redis => redis).and_return(nil)
|
987
|
+
|
988
|
+
get "contacts/#{contact.id}/entity_tags"
|
989
|
+
last_response.should be_not_found
|
990
|
+
end
|
991
|
+
|
992
|
+
it "adds tags to multiple entities for a contact" do
|
993
|
+
entity_1 = mock(Flapjack::Data::Entity)
|
994
|
+
entity_1.should_receive(:name).twice.and_return('entity_1')
|
995
|
+
entity_1.should_receive(:add_tags).with('web')
|
996
|
+
entity_2 = mock(Flapjack::Data::Entity)
|
997
|
+
entity_2.should_receive(:name).twice.and_return('entity_2')
|
998
|
+
entity_2.should_receive(:add_tags).with('app')
|
999
|
+
|
1000
|
+
entities = [{:entity => entity_1}, {:entity => entity_2}]
|
1001
|
+
contact.should_receive(:entities).and_return(entities)
|
1002
|
+
tag_data = [{:entity => entity_1, :tags => ['web']},
|
1003
|
+
{:entity => entity_2, :tags => ['app']}]
|
1004
|
+
contact.should_receive(:entities).with(:tags => true).and_return(tag_data)
|
1005
|
+
|
1006
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
1007
|
+
with(contact.id, :redis => redis).and_return(contact)
|
1008
|
+
|
1009
|
+
post "contacts/#{contact.id}/entity_tags",
|
1010
|
+
:entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
|
1011
|
+
last_response.should be_ok
|
1012
|
+
tag_response = {'entity_1' => ['web'],
|
1013
|
+
'entity_2' => ['app']}
|
1014
|
+
last_response.body.should be_json_eql( tag_response.to_json )
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
it "does not add tags to multiple entities for a contact that's not found" do
|
1018
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
1019
|
+
with(contact.id, :redis => redis).and_return(nil)
|
1020
|
+
|
1021
|
+
post "contacts/#{contact.id}/entity_tags",
|
1022
|
+
:entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
|
1023
|
+
last_response.should be_not_found
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
it "deletes tags from multiple entities for a contact" do
|
1027
|
+
entity_1 = mock(Flapjack::Data::Entity)
|
1028
|
+
entity_1.should_receive(:name).and_return('entity_1')
|
1029
|
+
entity_1.should_receive(:delete_tags).with('web')
|
1030
|
+
entity_2 = mock(Flapjack::Data::Entity)
|
1031
|
+
entity_2.should_receive(:name).and_return('entity_2')
|
1032
|
+
entity_2.should_receive(:delete_tags).with('app')
|
1033
|
+
|
1034
|
+
entities = [{:entity => entity_1}, {:entity => entity_2}]
|
1035
|
+
contact.should_receive(:entities).and_return(entities)
|
1036
|
+
|
1037
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
1038
|
+
with(contact.id, :redis => redis).and_return(contact)
|
1039
|
+
|
1040
|
+
delete "contacts/#{contact.id}/entity_tags",
|
1041
|
+
:entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
|
1042
|
+
last_response.status.should == 204
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
it "does not delete tags from multiple entities for a contact that's not found" do
|
1046
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
1047
|
+
with(contact.id, :redis => redis).and_return(nil)
|
1048
|
+
|
1049
|
+
delete "contacts/#{contact.id}/entity_tags",
|
1050
|
+
:entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
|
1051
|
+
last_response.should be_not_found
|
1052
|
+
end
|
1053
|
+
|
331
1054
|
end
|