post_agent_spec.rb 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. require 'spec_helper'
  2. require 'ostruct'
  3. describe Agents::PostAgent do
  4. before do
  5. @valid_options = {
  6. 'post_url' => "http://www.example.com",
  7. 'expected_receive_period_in_days' => 1,
  8. 'payload' => {
  9. 'default' => 'value'
  10. }
  11. }
  12. @valid_params = {
  13. name: "somename",
  14. options: @valid_options
  15. }
  16. @checker = Agents::PostAgent.new(@valid_params)
  17. @checker.user = users(:jane)
  18. @checker.save!
  19. @event = Event.new
  20. @event.agent = agents(:jane_weather_agent)
  21. @event.payload = {
  22. 'somekey' => 'somevalue',
  23. 'someotherkey' => {
  24. 'somekey' => 'value'
  25. }
  26. }
  27. @requests = 0
  28. @sent_requests = Hash.new { |hash, method| hash[method] = [] }
  29. stub_request(:any, /:/).to_return { |request|
  30. method = request.method
  31. @requests += 1
  32. @sent_requests[method] << req = OpenStruct.new(uri: request.uri)
  33. case method
  34. when :get, :delete
  35. req.data = request.uri.query
  36. else
  37. case request.headers['Content-Type'][/\A[^;\s]+/]
  38. when 'application/x-www-form-urlencoded'
  39. req.data = request.body
  40. when 'application/json'
  41. req.data = ActiveSupport::JSON.decode(request.body)
  42. else
  43. raise "unexpected Content-Type: #{content_type}"
  44. end
  45. end
  46. { status: 200, body: "ok" }
  47. }
  48. end
  49. it_behaves_like WebRequestConcern
  50. describe "making requests" do
  51. it "can make requests of each type" do
  52. %w[get put post patch delete].each.with_index(1) do |verb, index|
  53. @checker.options['method'] = verb
  54. expect(@checker).to be_valid
  55. @checker.check
  56. expect(@requests).to eq(index)
  57. expect(@sent_requests[verb.to_sym].length).to eq(1)
  58. end
  59. end
  60. end
  61. describe "#receive" do
  62. it "can handle multiple events and merge the payloads with options['payload']" do
  63. event1 = Event.new
  64. event1.agent = agents(:bob_weather_agent)
  65. event1.payload = {
  66. 'xyz' => 'value1',
  67. 'message' => 'value2',
  68. 'default' => 'value2'
  69. }
  70. expect {
  71. expect {
  72. @checker.receive([@event, event1])
  73. }.to change { @sent_requests[:post].length }.by(2)
  74. }.not_to change { @sent_requests[:get].length }
  75. expect(@sent_requests[:post][0].data).to eq(@event.payload.merge('default' => 'value').to_query)
  76. expect(@sent_requests[:post][1].data).to eq(event1.payload.to_query)
  77. end
  78. it "can make GET requests" do
  79. @checker.options['method'] = 'get'
  80. expect {
  81. expect {
  82. @checker.receive([@event])
  83. }.to change { @sent_requests[:get].length }.by(1)
  84. }.not_to change { @sent_requests[:post].length }
  85. expect(@sent_requests[:get][0].data).to eq(@event.payload.merge('default' => 'value').to_query)
  86. end
  87. it "can make a GET request merging params in post_url, payload and event" do
  88. @checker.options['method'] = 'get'
  89. @checker.options['post_url'] = "http://example.com/a/path?existing_param=existing_value"
  90. @event.payload = {
  91. "some_param" => "some_value",
  92. "another_param" => "another_value"
  93. }
  94. @checker.receive([@event])
  95. uri = @sent_requests[:get].first.uri
  96. # parameters are alphabetically sorted by Faraday
  97. expect(uri.request_uri).to eq("/a/path?another_param=another_value&default=value&existing_param=existing_value&some_param=some_value")
  98. end
  99. it "can skip merging the incoming event when no_merge is set, but it still interpolates" do
  100. @checker.options['no_merge'] = 'true'
  101. @checker.options['payload'] = {
  102. 'key' => 'it said: {{ someotherkey.somekey }}'
  103. }
  104. @checker.receive([@event])
  105. expect(@sent_requests[:post].first.data).to eq({ 'key' => 'it said: value' }.to_query)
  106. end
  107. it "interpolates when receiving a payload" do
  108. @checker.options['post_url'] = "https://{{ domain }}/{{ variable }}?existing_param=existing_value"
  109. @event.payload = {
  110. 'domain' => 'google.com',
  111. 'variable' => 'a_variable'
  112. }
  113. @checker.receive([@event])
  114. uri = @sent_requests[:post].first.uri
  115. expect(uri.scheme).to eq('https')
  116. expect(uri.host).to eq('google.com')
  117. expect(uri.path).to eq('/a_variable')
  118. expect(uri.query).to eq("existing_param=existing_value")
  119. end
  120. end
  121. describe "#check" do
  122. it "sends options['payload'] as a POST request" do
  123. expect {
  124. @checker.check
  125. }.to change { @sent_requests[:post].length }.by(1)
  126. expect(@sent_requests[:post][0].data).to eq(@checker.options['payload'].to_query)
  127. end
  128. it "sends options['payload'] as JSON as a POST request" do
  129. @checker.options['content_type'] = 'json'
  130. expect {
  131. @checker.check
  132. }.to change { @sent_requests[:post].length }.by(1)
  133. expect(@sent_requests[:post][0].data).to eq(@checker.options['payload'])
  134. end
  135. it "sends options['payload'] as a GET request" do
  136. @checker.options['method'] = 'get'
  137. expect {
  138. expect {
  139. @checker.check
  140. }.to change { @sent_requests[:get].length }.by(1)
  141. }.not_to change { @sent_requests[:post].length }
  142. expect(@sent_requests[:get][0].data).to eq(@checker.options['payload'].to_query)
  143. end
  144. end
  145. describe "#working?" do
  146. it "checks if events have been received within expected receive period" do
  147. expect(@checker).not_to be_working
  148. Agents::PostAgent.async_receive @checker.id, [@event.id]
  149. expect(@checker.reload).to be_working
  150. two_days_from_now = 2.days.from_now
  151. stub(Time).now { two_days_from_now }
  152. expect(@checker.reload).not_to be_working
  153. end
  154. end
  155. describe "validation" do
  156. before do
  157. expect(@checker).to be_valid
  158. end
  159. it "should validate presence of post_url" do
  160. @checker.options['post_url'] = ""
  161. expect(@checker).not_to be_valid
  162. end
  163. it "should validate presence of expected_receive_period_in_days" do
  164. @checker.options['expected_receive_period_in_days'] = ""
  165. expect(@checker).not_to be_valid
  166. end
  167. it "should validate method as post, get, put, patch, or delete, defaulting to post" do
  168. @checker.options['method'] = ""
  169. expect(@checker.method).to eq("post")
  170. expect(@checker).to be_valid
  171. @checker.options['method'] = "POST"
  172. expect(@checker.method).to eq("post")
  173. expect(@checker).to be_valid
  174. @checker.options['method'] = "get"
  175. expect(@checker.method).to eq("get")
  176. expect(@checker).to be_valid
  177. @checker.options['method'] = "patch"
  178. expect(@checker.method).to eq("patch")
  179. expect(@checker).to be_valid
  180. @checker.options['method'] = "wut"
  181. expect(@checker.method).to eq("wut")
  182. expect(@checker).not_to be_valid
  183. end
  184. it "should validate that no_merge is 'true' or 'false', if present" do
  185. @checker.options['no_merge'] = ""
  186. expect(@checker).to be_valid
  187. @checker.options['no_merge'] = "true"
  188. expect(@checker).to be_valid
  189. @checker.options['no_merge'] = "false"
  190. expect(@checker).to be_valid
  191. @checker.options['no_merge'] = false
  192. expect(@checker).to be_valid
  193. @checker.options['no_merge'] = true
  194. expect(@checker).to be_valid
  195. @checker.options['no_merge'] = 'blarg'
  196. expect(@checker).not_to be_valid
  197. end
  198. it "should validate payload as a hash, if present" do
  199. @checker.options['payload'] = ""
  200. expect(@checker).to be_valid
  201. @checker.options['payload'] = "hello"
  202. expect(@checker).not_to be_valid
  203. @checker.options['payload'] = ["foo", "bar"]
  204. expect(@checker).not_to be_valid
  205. @checker.options['payload'] = { 'this' => 'that' }
  206. expect(@checker).to be_valid
  207. end
  208. it "requires headers to be a hash, if present" do
  209. @checker.options['headers'] = [1,2,3]
  210. expect(@checker).not_to be_valid
  211. @checker.options['headers'] = "hello world"
  212. expect(@checker).not_to be_valid
  213. @checker.options['headers'] = ""
  214. expect(@checker).to be_valid
  215. @checker.options['headers'] = {}
  216. expect(@checker).to be_valid
  217. @checker.options['headers'] = { "Authorization" => "foo bar" }
  218. expect(@checker).to be_valid
  219. end
  220. end
  221. end