flapjack-diner 1.4.0 → 2.0.0.a4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -1
  4. data/README.md +620 -413
  5. data/flapjack-diner.gemspec +1 -1
  6. data/lib/flapjack-diner/argument_validator.rb +77 -7
  7. data/lib/flapjack-diner/configuration.rb +409 -0
  8. data/lib/flapjack-diner/index_range.rb +42 -0
  9. data/lib/flapjack-diner/log_formatter.rb +22 -0
  10. data/lib/flapjack-diner/query.rb +114 -0
  11. data/lib/flapjack-diner/relationships.rb +180 -0
  12. data/lib/flapjack-diner/request.rb +280 -0
  13. data/lib/flapjack-diner/resources.rb +64 -0
  14. data/lib/flapjack-diner/response.rb +91 -0
  15. data/lib/flapjack-diner/tools.rb +47 -251
  16. data/lib/flapjack-diner/utility.rb +16 -0
  17. data/lib/flapjack-diner/version.rb +1 -1
  18. data/lib/flapjack-diner.rb +54 -20
  19. data/spec/argument_validator_spec.rb +87 -28
  20. data/spec/flapjack-diner_spec.rb +42 -64
  21. data/spec/relationships_spec.rb +211 -0
  22. data/spec/resources/checks_spec.rb +219 -79
  23. data/spec/resources/contacts_spec.rb +179 -151
  24. data/spec/resources/events_spec.rb +208 -0
  25. data/spec/resources/maintenance_periods_spec.rb +177 -565
  26. data/spec/resources/media_spec.rb +157 -171
  27. data/spec/resources/metrics_spec.rb +45 -0
  28. data/spec/resources/rules_spec.rb +278 -0
  29. data/spec/resources/states_spec.rb +93 -0
  30. data/spec/resources/statistics_spec.rb +53 -0
  31. data/spec/resources/tags_spec.rb +243 -0
  32. data/spec/spec_helper.rb +16 -0
  33. data/spec/support/fixture_data.rb +541 -0
  34. metadata +33 -31
  35. data/.rubocop.yml +0 -21
  36. data/.rubocop_todo.yml +0 -135
  37. data/lib/flapjack-diner/resources/checks.rb +0 -64
  38. data/lib/flapjack-diner/resources/contacts.rb +0 -70
  39. data/lib/flapjack-diner/resources/entities.rb +0 -68
  40. data/lib/flapjack-diner/resources/maintenance_periods.rb +0 -82
  41. data/lib/flapjack-diner/resources/media.rb +0 -61
  42. data/lib/flapjack-diner/resources/notification_rules.rb +0 -66
  43. data/lib/flapjack-diner/resources/notifications.rb +0 -28
  44. data/lib/flapjack-diner/resources/pagerduty_credentials.rb +0 -59
  45. data/lib/flapjack-diner/resources/reports.rb +0 -33
  46. data/spec/pacts/flapjack-diner-flapjack.json +0 -4515
  47. data/spec/resources/entities_spec.rb +0 -181
  48. data/spec/resources/notification_rules_spec.rb +0 -341
  49. data/spec/resources/notifications_spec.rb +0 -208
  50. data/spec/resources/pagerduty_credentials_spec.rb +0 -237
  51. data/spec/resources/reports_spec.rb +0 -255
@@ -6,88 +6,143 @@ describe Flapjack::ArgumentValidator do
6
6
  context 'required' do
7
7
 
8
8
  let(:query) do
9
- {:entity => 'myservice', :check => 'HOST'}
9
+ {:name => 'HOST', :enabled => false}
10
10
  end
11
11
 
12
12
  subject { Flapjack::ArgumentValidator.new(query) }
13
13
 
14
- it 'does not raise an exception when query entity is valid' do
15
- expect { subject.validate(:query => :entity, :as => :required) }.not_to raise_exception
14
+ it 'does not raise an error when query entity is valid' do
15
+ expect {
16
+ subject.validate(:query => :name, :as => :required)
17
+ }.not_to raise_error
16
18
  end
17
19
 
18
20
  it 'raises ArgumentError when query entity is invalid' do
19
- query[:entity] = nil
20
- expect { subject.validate(:query => :entity, :as => :required) }.to raise_exception
21
+ query[:name] = nil
22
+ expect {
23
+ subject.validate(:query => :name, :as => :required)
24
+ }.to raise_error(ArgumentError)
21
25
  end
22
26
 
23
27
  it 'handles arrays as query values valid' do
24
- expect { subject.validate(:query => [:entity, :check], :as => :required) }.not_to raise_exception
28
+ expect {
29
+ subject.validate(:query => [:name, :enabled], :as => :required)
30
+ }.not_to raise_error
25
31
  end
26
32
 
27
33
  it 'handles arrays as query values invalid' do
28
- query[:check] = nil
29
- expect { subject.validate(:query => [:entity, :check], :as => :required) }.to raise_exception
34
+ query[:name] = nil
35
+ expect {
36
+ subject.validate(:query => [:name, :enabled], :as => :required)
37
+ }.to raise_error(ArgumentError)
30
38
  end
31
39
  end
32
40
 
33
41
  context 'time' do
34
42
 
35
43
  let(:query) do
36
- {:start_time => Time.now, :duration => 10}
44
+ {:start_time => Time.now}
37
45
  end
38
46
 
39
47
  subject { Flapjack::ArgumentValidator.new(query) }
40
48
 
41
- it 'does not raise an exception when query start_time is valid' do
42
- expect { subject.validate(:query => :start_time, :as => :time) }.not_to raise_exception
49
+ it 'does not raise an error when query start_time is valid' do
50
+ expect {
51
+ subject.validate(:query => :start_time, :as => :time)
52
+ }.not_to raise_error
43
53
  end
44
54
 
45
- it 'raises an exception when query start_time is invalid' do
55
+ it 'raises an error when query start_time is invalid' do
46
56
  query[:start_time] = 1234
47
- expect { subject.validate(:query => :start_time, :as => :time) }.to raise_exception
57
+ expect {
58
+ subject.validate(:query => :start_time, :as => :time)
59
+ }.to raise_error(ArgumentError)
48
60
  end
49
61
 
50
62
  it 'handles arrays as query values valid' do
51
63
  query[:end_time] = Time.now
52
- expect { subject.validate(:query => [:start_time, :end_time], :as => :time) }.not_to raise_exception
64
+ expect {
65
+ subject.validate(:query => [:start_time, :end_time], :as => :time)
66
+ }.not_to raise_error
53
67
  end
54
68
 
55
69
  it 'handles arrays as query values invalid' do
56
70
  query[:end_time] = 3904
57
- expect { subject.validate(:query => [:start_time, :end_time], :as => :time) }.to raise_exception
71
+ expect {
72
+ subject.validate(:query => [:start_time, :end_time], :as => :time)
73
+ }.to raise_error(ArgumentError)
58
74
  end
59
75
 
60
76
  it 'handles dates as query values' do
61
77
  query[:end_time] = Date.today
62
- expect { subject.validate(:query => :end_time, :as => :time) }.not_to raise_exception
78
+ expect {
79
+ subject.validate(:query => :end_time, :as => :time)
80
+ }.not_to raise_error
63
81
  end
64
82
 
65
83
  it 'handles ISO 8601 strings as query values' do
66
84
  query[:end_time] = Time.now.iso8601
67
- expect { subject.validate(:query => :end_time, :as => :time) }.not_to raise_exception
85
+ expect {
86
+ subject.validate(:query => :end_time, :as => :time)
87
+ }.not_to raise_error
68
88
  end
69
89
 
70
- it 'raises an exception when invalid time strings are provided' do
90
+ it 'raises an error when invalid time strings are provided' do
71
91
  query[:end_time] = '2011-08-01T00:00'
72
- expect { subject.validate(:query => :end_time, :as => :time) }.to raise_exception
92
+ expect {
93
+ subject.validate(:query => :end_time, :as => :time)
94
+ }.to raise_error(ArgumentError)
73
95
  end
74
96
  end
75
97
 
76
98
  context 'integer via method missing' do
77
99
 
78
100
  let(:query) do
79
- {:start_time => Time.now, :duration => 10}
101
+ {:duration => 10}
80
102
  end
81
103
 
82
104
  subject { Flapjack::ArgumentValidator.new(query) }
83
105
 
84
- it 'does not raise an exception when query duration is valid' do
85
- expect { subject.validate(:query => :duration, :as => :integer) }.not_to raise_exception
106
+ it 'does not raise an error when query duration is valid' do
107
+ expect {
108
+ subject.validate(:query => :duration, :as => :integer)
109
+ }.not_to raise_error
86
110
  end
87
111
 
88
- it 'raises an exception when query duration is invalid' do
112
+ it 'raises an error when query duration is invalid' do
89
113
  query[:duration] = '23'
90
- expect { subject.validate(:query => :duration, :as => :integer) }.to raise_exception
114
+ expect {
115
+ subject.validate(:query => :duration, :as => :integer)
116
+ }.to raise_error(ArgumentError)
117
+ end
118
+ end
119
+
120
+ context 'string via method missing' do
121
+
122
+ let(:query) do
123
+ {:name => 'Herbert'}
124
+ end
125
+
126
+ subject { Flapjack::ArgumentValidator.new(query) }
127
+
128
+ it 'does not raise an error when query name is valid' do
129
+ expect {
130
+ subject.validate(:query => :name, :as => :non_empty_string)
131
+ }.not_to raise_error
132
+ end
133
+
134
+ it 'raises an error when query name is empty' do
135
+ query[:name] = ''
136
+ expect {
137
+ subject.validate(:query => :name, :as => :non_empty_string)
138
+ }.to raise_error(ArgumentError)
139
+ end
140
+
141
+ it 'raises an error when query name is invalid' do
142
+ query[:name] = 23
143
+ expect {
144
+ subject.validate(:query => :name, :as => :non_empty_string)
145
+ }.to raise_error(ArgumentError)
91
146
  end
92
147
  end
93
148
 
@@ -99,13 +154,17 @@ describe Flapjack::ArgumentValidator do
99
154
 
100
155
  subject { Flapjack::ArgumentValidator.new(query) }
101
156
 
102
- it 'does not raise an exception when query start_time is valid' do
103
- expect { subject.validate(:query => :start_time, :as => [:time, :required]) }.not_to raise_exception
157
+ it 'does not raise an error when query start_time is valid' do
158
+ expect {
159
+ subject.validate(:query => :start_time, :as => [:time, :required])
160
+ }.not_to raise_error
104
161
  end
105
162
 
106
- it 'raises an exception when query start_time is invalid' do
163
+ it 'raises an error when query start_time is invalid' do
107
164
  query[:start_time] = nil
108
- expect { subject.validate(:query => :start_time, :as => [:time, :required]) }.to raise_exception
165
+ expect {
166
+ subject.validate(:query => :start_time, :as => [:time, :required])
167
+ }.to raise_error(ArgumentError)
109
168
  end
110
169
  end
111
170
  end
@@ -7,10 +7,6 @@ describe Flapjack::Diner do
7
7
 
8
8
  let(:time) { Time.now }
9
9
 
10
- def response_with_data(name, data = [])
11
- "{\"#{name}\":#{data.to_json}}"
12
- end
13
-
14
10
  before(:each) do
15
11
  Flapjack::Diner.base_uri(server)
16
12
  Flapjack::Diner.logger = nil
@@ -20,9 +16,9 @@ describe Flapjack::Diner do
20
16
  WebMock.reset!
21
17
  end
22
18
 
23
- context 'argument parsing' do
19
+ # context 'argument parsing' do
24
20
 
25
- end
21
+ # end
26
22
 
27
23
  context 'keys as strings' do
28
24
 
@@ -35,32 +31,16 @@ describe Flapjack::Diner do
35
31
  end
36
32
 
37
33
  it 'can return keys as strings' do
38
- data = [{
39
- :id => '21',
40
- :first_name => 'Ada',
41
- :last_name => 'Lovelace',
42
- :email => 'ada@example.com',
43
- :timezone => 'Europe/London',
44
- :tags => [ 'legend', 'first computer programmer' ],
45
- :links => {
46
- :entities => ['7', '12', '83'],
47
- :media => ['21_email', '21_sms'],
48
- :notification_rules => ['30fd36ae-3922-4957-ae3e-c8f6dd27e543']
49
- }
50
- }]
51
-
52
34
  req = stub_request(:get, "http://#{server}/contacts").to_return(
53
- :status => 200, :body => response_with_data('contacts', data))
35
+ :status => 200, :body => {:data => [contact_data]}.to_json)
54
36
 
55
37
  result = Flapjack::Diner.contacts
56
38
  expect(req).to have_been_requested
57
39
  expect(result).not_to be_nil
58
40
  expect(result).to be_an_instance_of(Array)
59
41
  expect(result.length).to be(1)
60
- expect(result[0]).to be_an_instance_of(Hash)
61
- expect(result[0]).to have_key('id')
62
- expect(result[0]).to have_key('links')
63
- expect(result[0]['links']).to have_key('entities')
42
+ expect(result.first).to be_an_instance_of(Hash)
43
+ expect(result.first).to have_key('id')
64
44
  end
65
45
 
66
46
  end
@@ -73,65 +53,70 @@ describe Flapjack::Diner do
73
53
  Flapjack::Diner.logger = logger
74
54
  end
75
55
 
76
- it 'logs a GET request without a path' do
77
- response = response_with_data('entities')
78
- req = stub_request(:get, "http://#{server}/entities").
56
+ it "logs a GET request without a path" do
57
+ response = {:data => [contact_data]}.to_json
58
+ req = stub_request(:get, "http://#{server}/contacts").
79
59
  to_return(:body => response)
80
60
 
81
- expect(logger).to receive(:info).with("GET http://#{server}/entities")
82
- expect(logger).to receive(:info).with(' Response Code: 200')
83
- expect(logger).to receive(:info).with(" Response Body: #{response}")
61
+ expect(logger).to receive(:info).with(%r{\[Flapjack::Diner\] \[[^\]]+\] 200 "GET /contacts" - $})
84
62
 
85
- result = Flapjack::Diner.entities
63
+ result = Flapjack::Diner.contacts
86
64
  expect(req).to have_been_requested
87
65
  expect(result).not_to be_nil
88
66
  end
89
67
 
90
68
  it "logs a POST request" do
91
- req = stub_request(:post, "http://#{server}/test_notifications/entities/27").
92
- to_return(:status => 204)
93
- expect(logger).to receive(:info).with("POST http://#{server}/test_notifications/entities/27\n" +
94
- " Body: {:test_notifications=>[{:summary=>\"dealing with it\"}]}")
95
- expect(logger).to receive(:info).with(' Response Code: 204')
69
+ req_data = test_notification_json(test_notification_data).merge(
70
+ :relationships => {
71
+ :check => {
72
+ :data => {:type => 'check', :id => check_data[:id]}
73
+ }
74
+ }
75
+ )
76
+ resp_data = test_notification_json(test_notification_data)
77
+
78
+ response = {:data => resp_data}.to_json
79
+ req = stub_request(:post, "http://#{server}/test_notifications").
80
+ to_return(:status => 201, :body => response)
96
81
 
97
- result = Flapjack::Diner.create_test_notifications_entities(27, [{:summary => 'dealing with it'}])
82
+ expect(logger).to receive(:info).with(%r{\[Flapjack::Diner\] \[[^\]]+\] 201 "POST /test_notifications" - $})
83
+
84
+ result = Flapjack::Diner.create_test_notifications(test_notification_data.merge(:check => check_data[:id]))
98
85
  expect(req).to have_been_requested
99
- expect(result).to be_truthy
86
+ expect(result).to eq(resultify(resp_data))
100
87
  end
101
88
 
102
89
  it "logs a DELETE request" do
103
- req = stub_request(:delete, "http://#{server}/scheduled_maintenances/checks/example.com%3ASSH").
104
- with(:query => {:start_time => time.iso8601}).
90
+ req = stub_request(:delete, "http://#{server}/scheduled_maintenances/#{scheduled_maintenance_data[:id]}").
105
91
  to_return(:status => 204)
106
92
 
107
- expect(logger).to receive(:info).with("DELETE http://#{server}/scheduled_maintenances/checks/example.com:SSH?start_time=#{URI.encode_www_form_component(time.iso8601)}")
108
- expect(logger).to receive(:info).with(" Response Code: 204")
93
+ expect(logger).to receive(:info).
94
+ with(%r{\[Flapjack::Diner\] \[[^\]]+\] 204 "DELETE /scheduled_maintenances/#{scheduled_maintenance_data[:id]}" - $})
109
95
 
110
- result = Flapjack::Diner.delete_scheduled_maintenances_checks('example.com:SSH', :start_time => time)
96
+ result = Flapjack::Diner.delete_scheduled_maintenances(scheduled_maintenance_data[:id])
111
97
  expect(req).to have_been_requested
112
- expect(result).to be_truthy
98
+ expect(result).to be_a(TrueClass)
113
99
  end
114
100
 
115
101
  end
116
102
 
117
103
  context "problems" do
118
-
119
104
  it "raises an exception on network failure" do
120
- req = stub_request(:get, "http://#{server}/entities").to_timeout
105
+ req = stub_request(:get, "http://#{server}/contacts").to_timeout
121
106
 
122
107
  expect {
123
- Flapjack::Diner.entities
124
- }.to raise_error
108
+ Flapjack::Diner.contacts
109
+ }.to raise_error(Timeout::Error)
125
110
  expect(req).to have_been_requested
126
111
  end
127
112
 
128
113
  it "raises an exception on invalid JSON data" do
129
- req = stub_request(:get, "http://#{server}/entities").to_return(
114
+ req = stub_request(:get, "http://#{server}/contacts").to_return(
130
115
  :body => "{")
131
116
 
132
117
  expect {
133
- Flapjack::Diner.entities
134
- }.to raise_error
118
+ Flapjack::Diner.contacts
119
+ }.to raise_error(JSON::ParserError)
135
120
  expect(req).to have_been_requested
136
121
  end
137
122
 
@@ -139,26 +124,19 @@ describe Flapjack::Diner do
139
124
  req = stub_request(:get, /http:\/\/#{server}\/*/)
140
125
 
141
126
  expect {
142
- Flapjack::Diner.delete_scheduled_maintenances_checks('example.com:SSH', :start_time => nil)
143
- }.to raise_error
127
+ Flapjack::Diner.create_scheduled_maintenances
128
+ }.to raise_error(ArgumentError)
144
129
  expect(req).not_to have_been_requested
145
130
  end
146
131
 
147
132
  it "raises an exception if a time argument is provided with the wrong data type" do
148
- start_str = '2011-08-01T00:00:00+10:00'
149
- finish_str = 'yesterday'
150
-
151
- start = Time.iso8601(start_str)
152
-
153
133
  req = stub_request(:get, /http:\/\/#{server}\/*/)
154
134
 
155
135
  expect {
156
- Flapjack::Diner.downtime_report_checks('example.com:SSH',
157
- :start_time => start_time, :end_time => end_time)
158
- }.to raise_error
136
+ Flapjack::Diner.create_scheduled_maintenances(:start_time => Time.now,
137
+ :end_time => 'tomorrow')
138
+ }.to raise_error(ArgumentError)
159
139
  expect(req).not_to have_been_requested
160
140
  end
161
-
162
141
  end
163
-
164
142
  end
@@ -0,0 +1,211 @@
1
+ require 'spec_helper'
2
+ require 'flapjack-diner'
3
+
4
+ describe Flapjack::Diner::Relationships, :pact => true do
5
+
6
+ before(:each) do
7
+ Flapjack::Diner.base_uri('localhost:19081')
8
+ Flapjack::Diner.logger = nil
9
+ end
10
+
11
+ it 'adds a tag to a check' do
12
+ flapjack.given("a check and a tag exist").
13
+ upon_receiving("a POST request adding a tag to a check").
14
+ with(:method => :post, :path => "/checks/#{check_data[:id]}/relationships/tags",
15
+ :headers => {'Content-Type' => 'application/vnd.api+json'},
16
+ :body => {:data => [{:id => tag_data[:id], :type => 'tag'}]}).
17
+ will_respond_with(:status => 204,
18
+ :body => '')
19
+
20
+ result = Flapjack::Diner.create_check_link_tags(check_data[:id], tag_data[:id])
21
+ expect(result).to be true
22
+ end
23
+
24
+ it 'adds two tags to a check' do
25
+ flapjack.given("a check and two tags exist").
26
+ upon_receiving("a POST request adding two tags to a check").
27
+ with(:method => :post, :path => "/checks/#{check_data[:id]}/relationships/tags",
28
+ :headers => {'Content-Type' => 'application/vnd.api+json'},
29
+ :body => {:data => [{:id => tag_data[:id], :type => 'tag'},
30
+ {:id => tag_2_data[:id], :type => 'tag'}]}).
31
+ will_respond_with(:status => 204,
32
+ :body => '')
33
+
34
+ result = Flapjack::Diner.create_check_link_tags(check_data[:id],
35
+ tag_data[:id], tag_2_data[:id])
36
+ expect(result).to be true
37
+ end
38
+
39
+ it 'gets tags for a check' do
40
+ flapjack.given("a check with a tag exists").
41
+ upon_receiving("a GET request for all tags on a check").
42
+ with(:method => :get, :path => "/checks/#{check_data[:id]}/tags").
43
+ will_respond_with(
44
+ :status => 200,
45
+ :headers => {'Content-Type' => 'application/vnd.api+json; supported-ext=bulk; charset=utf-8'},
46
+ :body => {:data => [{:id => tag_data[:id], :type => 'tag'}]})
47
+
48
+ result = Flapjack::Diner.check_link_tags(check_data[:id])
49
+ expect(result).to eq([{:id => tag_data[:id], :type => 'tag'}])
50
+ end
51
+
52
+ it 'gets tags for a check with full tag records' do
53
+ included_data = [
54
+ tag_json(tag_data)
55
+ ]
56
+
57
+ flapjack.given("a check with a tag exists").
58
+ upon_receiving("a GET request for all tags on a check, with full tag records").
59
+ with(:method => :get,
60
+ :path => "/checks/#{check_data[:id]}/tags",
61
+ :query => "include=tags").
62
+ will_respond_with(
63
+ :status => 200,
64
+ :headers => {'Content-Type' => 'application/vnd.api+json; supported-ext=bulk; charset=utf-8'},
65
+ :body => {:data => [{:id => tag_data[:id], :type => 'tag'}],
66
+ :included => included_data})
67
+
68
+ result = Flapjack::Diner.check_link_tags(check_data[:id], :include => 'tags')
69
+ expect(result).to eq([{:id => tag_data[:id], :type => 'tag'}])
70
+ expect(Flapjack::Diner.context[:included]).to eq('tag' => {tag_data[:id] => resultify(included_data[0])})
71
+ end
72
+
73
+ it 'gets tags for a check with full tag and rule record' do
74
+ included_data = [
75
+ tag_json(tag_data),
76
+ rule_json(rule_data)
77
+ ]
78
+
79
+ flapjack.given("a check with a tag and a rule exists").
80
+ upon_receiving("a GET request for all tags on a check, with full tag and rule records").
81
+ with(:method => :get,
82
+ :path => "/checks/#{check_data[:id]}/tags",
83
+ :query => 'include=tags.rules').
84
+ will_respond_with(
85
+ :status => 200,
86
+ :headers => {'Content-Type' => 'application/vnd.api+json; supported-ext=bulk; charset=utf-8'},
87
+ :body => {:data => [{:id => tag_data[:id], :type => 'tag'}],
88
+ :included => included_data})
89
+
90
+ result = Flapjack::Diner.check_link_tags(check_data[:id], :include => 'rules')
91
+ expect(result).to eq([{:id => tag_data[:id], :type => 'tag'}])
92
+ expect(Flapjack::Diner.context[:included]).to eq(
93
+ 'tag' => {tag_data[:id] => resultify(included_data[0])},
94
+ 'rule' => {rule_data[:id] => resultify(included_data[1])}
95
+ )
96
+ end
97
+
98
+ it 'updates tags for a check' do
99
+ flapjack.given("a check and a tag exist").
100
+ upon_receiving("a PATCH request updating tags for a check").
101
+ with(:method => :patch, :path => "/checks/#{check_data[:id]}/relationships/tags",
102
+ :headers => {'Content-Type' => 'application/vnd.api+json'},
103
+ :body => {:data => [{:id => tag_data[:id], :type => 'tag'}]}).
104
+ will_respond_with(:status => 204,
105
+ :body => '')
106
+
107
+ result = Flapjack::Diner.update_check_link_tags(check_data[:id],
108
+ tag_data[:id])
109
+ expect(result).to be true
110
+ end
111
+
112
+ it 'clears all tags from a check' do
113
+ flapjack.given("a check and a tag exist").
114
+ upon_receiving("a PATCH request clearing tags for a check").
115
+ with(:method => :patch, :path => "/checks/#{check_data[:id]}/relationships/tags",
116
+ :headers => {'Content-Type' => 'application/vnd.api+json'},
117
+ :body => {:data => []}).
118
+ will_respond_with(:status => 204,
119
+ :body => '')
120
+
121
+ result = Flapjack::Diner.update_check_link_tags(check_data[:id], [])
122
+ expect(result).to be true
123
+ end
124
+
125
+ it 'deletes a tag from a check' do
126
+ flapjack.given("a check with a tag exists").
127
+ upon_receiving("a DELETE request deleting a tag from a check").
128
+ with(:method => :delete, :path => "/checks/#{check_data[:id]}/relationships/tags",
129
+ :headers => {'Content-Type' => 'application/vnd.api+json'},
130
+ :body => {:data => [{:id => tag_data[:id], :type => 'tag'}]}).
131
+ will_respond_with(:status => 204,
132
+ :body => '')
133
+
134
+ result = Flapjack::Diner.delete_check_link_tags(check_data[:id],
135
+ tag_data[:id])
136
+ expect(result).to be true
137
+ end
138
+
139
+ it 'deletes two tags from a check' do
140
+ flapjack.given("a check with two tags exists").
141
+ upon_receiving("a DELETE request deleting two tags from a check").
142
+ with(:method => :delete, :path => "/checks/#{check_data[:id]}/relationships/tags",
143
+ :headers => {'Content-Type' => 'application/vnd.api+json'},
144
+ :body => {:data => [{:id => tag_data[:id], :type => 'tag'},
145
+ {:id => tag_2_data[:id], :type => 'tag'}]}).
146
+ will_respond_with(:status => 204,
147
+ :body => '')
148
+
149
+ result = Flapjack::Diner.delete_check_link_tags(check_data[:id],
150
+ tag_data[:id], tag_2_data[:id])
151
+ expect(result).to be true
152
+ end
153
+
154
+ it 'gets the contact for a medium' do
155
+ flapjack.given("a contact with a medium exists").
156
+ upon_receiving("a GET request for a medium's contact").
157
+ with(:method => :get, :path => "/media/#{email_data[:id]}/contact").
158
+ will_respond_with(
159
+ :status => 200,
160
+ :headers => {'Content-Type' => 'application/vnd.api+json; supported-ext=bulk; charset=utf-8'},
161
+ :body => {:data => {:id => contact_data[:id], :type => 'contact'}})
162
+
163
+ result = Flapjack::Diner.medium_link_contact(email_data[:id])
164
+ expect(result).to eq(:id => contact_data[:id], :type => 'contact')
165
+ end
166
+
167
+ it "doesn't duplicate linked data references in included data" do
168
+ resp_check = check_json(check_data)
169
+ resp_check[:relationships] = {
170
+ :current_state => {
171
+ :data => {:type => 'state', :id => state_data[:id]}
172
+ },
173
+ :latest_notifications => {
174
+ :data => [{:type => 'state', :id => state_data[:id]}]
175
+ }
176
+ }
177
+
178
+ sd = state_data.delete_if {|k, _| [:created_at, :updated_at].include?(k)}
179
+
180
+ included_data = [
181
+ resp_check,
182
+ state_json(sd)
183
+ ]
184
+
185
+ flapjack.given("a check with a tag, current state and a latest notification exists").
186
+ upon_receiving("a GET request for a check (via tag)'s state and notifications").
187
+ with(:method => :get,
188
+ :path => "/tags/#{tag_data[:id]}/checks",
189
+ :query => 'include=checks.current_state%2Cchecks.latest_notifications').
190
+ will_respond_with(
191
+ :status => 200,
192
+ :headers => {'Content-Type' => 'application/vnd.api+json; supported-ext=bulk; charset=utf-8'},
193
+ :body => {
194
+ :data => [
195
+ {:id => check_data[:id], :type => 'check'},
196
+ ],
197
+ :included => included_data
198
+ })
199
+
200
+ result = Flapjack::Diner.tag_link_checks(tag_data[:id],
201
+ :include => ['checks.current_state', 'checks.latest_notifications'])
202
+ expect(result).to eq([
203
+ {:id => check_data[:id], :type => 'check'}
204
+ ])
205
+ expect(Flapjack::Diner.context[:included]).to eq(
206
+ 'check' => {check_data[:id] => resultify(resp_check)},
207
+ 'state' => {sd[:id] => resultify(state_json(sd))}
208
+ )
209
+ end
210
+
211
+ end