data_output_agent_spec.rb 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. # encoding: utf-8
  2. require 'spec_helper'
  3. describe Agents::DataOutputAgent do
  4. let(:agent) do
  5. _agent = Agents::DataOutputAgent.new(:name => 'My Data Output Agent')
  6. _agent.options = _agent.default_options.merge('secrets' => ['secret1', 'secret2'], 'events_to_show' => 3)
  7. _agent.options['template']['item']['pubDate'] = "{{date}}"
  8. _agent.user = users(:bob)
  9. _agent.sources << agents(:bob_website_agent)
  10. _agent.save!
  11. _agent
  12. end
  13. describe "#working?" do
  14. it "checks if events have been received within expected receive period" do
  15. expect(agent).not_to be_working
  16. Agents::DataOutputAgent.async_receive agent.id, [events(:bob_website_agent_event).id]
  17. expect(agent.reload).to be_working
  18. two_days_from_now = 2.days.from_now
  19. stub(Time).now { two_days_from_now }
  20. expect(agent.reload).not_to be_working
  21. end
  22. end
  23. describe "validation" do
  24. before do
  25. expect(agent).to be_valid
  26. end
  27. it "should validate presence and length of secrets" do
  28. agent.options[:secrets] = ""
  29. expect(agent).not_to be_valid
  30. agent.options[:secrets] = "foo"
  31. expect(agent).not_to be_valid
  32. agent.options[:secrets] = []
  33. expect(agent).not_to be_valid
  34. agent.options[:secrets] = ["hello"]
  35. expect(agent).to be_valid
  36. agent.options[:secrets] = ["hello", "world"]
  37. expect(agent).to be_valid
  38. end
  39. it "should validate presence of expected_receive_period_in_days" do
  40. agent.options[:expected_receive_period_in_days] = ""
  41. expect(agent).not_to be_valid
  42. agent.options[:expected_receive_period_in_days] = 0
  43. expect(agent).not_to be_valid
  44. agent.options[:expected_receive_period_in_days] = -1
  45. expect(agent).not_to be_valid
  46. end
  47. it "should validate presence of template and template.item" do
  48. agent.options[:template] = ""
  49. expect(agent).not_to be_valid
  50. agent.options[:template] = {}
  51. expect(agent).not_to be_valid
  52. agent.options[:template] = { 'item' => 'foo' }
  53. expect(agent).not_to be_valid
  54. agent.options[:template] = { 'item' => { 'title' => 'hi' } }
  55. expect(agent).to be_valid
  56. end
  57. end
  58. describe "#receive_web_request" do
  59. before do
  60. current_time = Time.now
  61. stub(Time).now { current_time }
  62. agents(:bob_website_agent).events.destroy_all
  63. end
  64. it "requires a valid secret" do
  65. content, status, content_type = agent.receive_web_request({ 'secret' => 'fake' }, 'get', 'text/xml')
  66. expect(status).to eq(401)
  67. expect(content).to eq("Not Authorized")
  68. content, status, content_type = agent.receive_web_request({ 'secret' => 'fake' }, 'get', 'application/json')
  69. expect(status).to eq(401)
  70. expect(content).to eq({ :error => "Not Authorized" })
  71. content, status, content_type = agent.receive_web_request({ 'secret' => 'secret1' }, 'get', 'application/json')
  72. expect(status).to eq(200)
  73. end
  74. describe "outputtng events as RSS and JSON" do
  75. let!(:event1) do
  76. agents(:bob_website_agent).create_event :payload => {
  77. "url" => "http://imgs.xkcd.com/comics/evolving.png",
  78. "title" => "Evolving",
  79. "hovertext" => "Biologists play reverse Pokemon, trying to avoid putting any one team member on the front lines long enough for the experience to cause evolution."
  80. }
  81. end
  82. let!(:event2) do
  83. agents(:bob_website_agent).create_event :payload => {
  84. "url" => "http://imgs.xkcd.com/comics/evolving2.png",
  85. "title" => "Evolving again",
  86. "date" => '',
  87. "hovertext" => "Something else"
  88. }
  89. end
  90. let!(:event3) do
  91. agents(:bob_website_agent).create_event :payload => {
  92. "url" => "http://imgs.xkcd.com/comics/evolving0.png",
  93. "title" => "Evolving yet again with a past date",
  94. "date" => '2014/05/05',
  95. "hovertext" => "Something else"
  96. }
  97. end
  98. it "can output RSS" do
  99. stub(agent).feed_link { "https://yoursite.com" }
  100. content, status, content_type = agent.receive_web_request({ 'secret' => 'secret1' }, 'get', 'text/xml')
  101. expect(status).to eq(200)
  102. expect(content_type).to eq('text/xml')
  103. expect(content.gsub(/\s+/, '')).to eq Utils.unindent(<<-XML).gsub(/\s+/, '')
  104. <?xml version="1.0" encoding="UTF-8" ?>
  105. <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  106. <channel>
  107. <atom:linkhref="https://yoursite.com/users/#{agent.user.id}/web_requests/#{agent.id}/secret1.xml" rel="self" type="application/rss+xml"/>
  108. <title>XKCD comics as a feed</title>
  109. <description>This is a feed of recent XKCD comics, generated by Huginn</description>
  110. <link>https://yoursite.com</link>
  111. <lastBuildDate>#{Time.now.rfc2822}</lastBuildDate>
  112. <pubDate>#{Time.now.rfc2822}</pubDate>
  113. <ttl>60</ttl>
  114. <item>
  115. <title>Evolving yet again with a past date</title>
  116. <description>Secret hovertext: Something else</description>
  117. <link>http://imgs.xkcd.com/comics/evolving0.png</link>
  118. <pubDate>#{Time.zone.parse(event3.payload['date']).rfc2822}</pubDate>
  119. <guid isPermaLink="false">#{event3.id}</guid>
  120. </item>
  121. <item>
  122. <title>Evolving again</title>
  123. <description>Secret hovertext: Something else</description>
  124. <link>http://imgs.xkcd.com/comics/evolving2.png</link>
  125. <pubDate>#{event2.created_at.rfc2822}</pubDate>
  126. <guid isPermaLink="false">#{event2.id}</guid>
  127. </item>
  128. <item>
  129. <title>Evolving</title>
  130. <description>Secret hovertext: Biologists play reverse Pokemon, trying to avoid putting any one team member on the front lines long enough for the experience to cause evolution.</description>
  131. <link>http://imgs.xkcd.com/comics/evolving.png</link>
  132. <pubDate>#{event1.created_at.rfc2822}</pubDate>
  133. <guid isPermaLink="false">#{event1.id}</guid>
  134. </item>
  135. </channel>
  136. </rss>
  137. XML
  138. end
  139. it "can output JSON" do
  140. agent.options['template']['item']['foo'] = "hi"
  141. content, status, content_type = agent.receive_web_request({ 'secret' => 'secret2' }, 'get', 'application/json')
  142. expect(status).to eq(200)
  143. expect(content).to eq({
  144. 'title' => 'XKCD comics as a feed',
  145. 'description' => 'This is a feed of recent XKCD comics, generated by Huginn',
  146. 'pubDate' => Time.now,
  147. 'items' => [
  148. {
  149. 'title' => 'Evolving yet again with a past date',
  150. 'description' => 'Secret hovertext: Something else',
  151. 'link' => 'http://imgs.xkcd.com/comics/evolving0.png',
  152. 'guid' => {"contents" => event3.id, "isPermaLink" => "false"},
  153. 'pubDate' => Time.zone.parse(event3.payload['date']).rfc2822,
  154. 'foo' => 'hi'
  155. },
  156. {
  157. 'title' => 'Evolving again',
  158. 'description' => 'Secret hovertext: Something else',
  159. 'link' => 'http://imgs.xkcd.com/comics/evolving2.png',
  160. 'guid' => {"contents" => event2.id, "isPermaLink" => "false"},
  161. 'pubDate' => event2.created_at.rfc2822,
  162. 'foo' => 'hi'
  163. },
  164. {
  165. 'title' => 'Evolving',
  166. 'description' => 'Secret hovertext: Biologists play reverse Pokemon, trying to avoid putting any one team member on the front lines long enough for the experience to cause evolution.',
  167. 'link' => 'http://imgs.xkcd.com/comics/evolving.png',
  168. 'guid' => {"contents" => event1.id, "isPermaLink" => "false"},
  169. 'pubDate' => event1.created_at.rfc2822,
  170. 'foo' => 'hi'
  171. }
  172. ]
  173. })
  174. end
  175. end
  176. describe "outputting nesting" do
  177. before do
  178. agent.options['template']['item']['enclosure'] = {
  179. "_attributes" => {
  180. "type" => "audio/mpeg",
  181. "url" => "{{media_url}}"
  182. }
  183. }
  184. agent.options['template']['item']['foo'] = {
  185. "_attributes" => {
  186. "attr" => "attr-value-{{foo}}"
  187. },
  188. "_contents" => "Foo: {{foo}}"
  189. }
  190. agent.options['template']['item']['nested'] = {
  191. "_attributes" => {
  192. "key" => "value"
  193. },
  194. "_contents" => {
  195. "title" => "some title"
  196. }
  197. }
  198. agent.options['template']['item']['simpleNested'] = {
  199. "title" => "some title",
  200. "complex" => {
  201. "_attributes" => {
  202. "key" => "value"
  203. },
  204. "_contents" => {
  205. "first" => {
  206. "_attributes" => {
  207. "a" => "b"
  208. },
  209. "_contents" => {
  210. "second" => "value"
  211. }
  212. }
  213. }
  214. }
  215. }
  216. agent.save!
  217. end
  218. let!(:event) do
  219. agents(:bob_website_agent).create_event :payload => {
  220. "url" => "http://imgs.xkcd.com/comics/evolving.png",
  221. "title" => "Evolving",
  222. "hovertext" => "Biologists play reverse Pokemon, trying to avoid putting any one team member on the front lines long enough for the experience to cause evolution.",
  223. "media_url" => "http://google.com/audio.mpeg",
  224. "foo" => 1
  225. }
  226. end
  227. it "can output JSON" do
  228. content, status, content_type = agent.receive_web_request({ 'secret' => 'secret2' }, 'get', 'application/json')
  229. expect(status).to eq(200)
  230. expect(content['items'].first).to eq(
  231. {
  232. 'title' => 'Evolving',
  233. 'description' => 'Secret hovertext: Biologists play reverse Pokemon, trying to avoid putting any one team member on the front lines long enough for the experience to cause evolution.',
  234. 'link' => 'http://imgs.xkcd.com/comics/evolving.png',
  235. 'guid' => {"contents" => event.id, "isPermaLink" => "false"},
  236. 'pubDate' => event.created_at.rfc2822,
  237. 'enclosure' => {
  238. "type" => "audio/mpeg",
  239. "url" => "http://google.com/audio.mpeg"
  240. },
  241. 'foo' => {
  242. 'attr' => 'attr-value-1',
  243. 'contents' => 'Foo: 1'
  244. },
  245. 'nested' => {
  246. "key" => "value",
  247. "title" => "some title"
  248. },
  249. 'simpleNested' => {
  250. "title" => "some title",
  251. "complex" => {
  252. "key"=>"value",
  253. "first" => {
  254. "a" => "b",
  255. "second"=>"value"
  256. }
  257. }
  258. }
  259. }
  260. )
  261. end
  262. it "can output RSS" do
  263. stub(agent).feed_link { "https://yoursite.com" }
  264. content, status, content_type = agent.receive_web_request({ 'secret' => 'secret1' }, 'get', 'text/xml')
  265. expect(status).to eq(200)
  266. expect(content_type).to eq('text/xml')
  267. expect(content.gsub(/\s+/, '')).to eq Utils.unindent(<<-XML).gsub(/\s+/, '')
  268. <?xml version="1.0" encoding="UTF-8" ?>
  269. <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  270. <channel>
  271. <atom:linkhref="https://yoursite.com/users/#{agent.user.id}/web_requests/#{agent.id}/secret1.xml" rel="self" type="application/rss+xml"/>
  272. <title>XKCD comics as a feed</title>
  273. <description>This is a feed of recent XKCD comics, generated by Huginn</description>
  274. <link>https://yoursite.com</link>
  275. <lastBuildDate>#{Time.now.rfc2822}</lastBuildDate>
  276. <pubDate>#{Time.now.rfc2822}</pubDate>
  277. <ttl>60</ttl>
  278. <item>
  279. <title>Evolving</title>
  280. <description>Secret hovertext: Biologists play reverse Pokemon, trying to avoid putting any one team member on the front lines long enough for the experience to cause evolution.</description>
  281. <link>http://imgs.xkcd.com/comics/evolving.png</link>
  282. <pubDate>#{event.created_at.rfc2822}</pubDate>
  283. <enclosure type="audio/mpeg" url="http://google.com/audio.mpeg" />
  284. <foo attr="attr-value-1">Foo: 1</foo>
  285. <nested key="value"><title>some title</title></nested>
  286. <simpleNested>
  287. <title>some title</title>
  288. <complex key="value">
  289. <first a="b">
  290. <second>value</second>
  291. </first>
  292. </complex>
  293. </simpleNested>
  294. <guid isPermaLink="false">#{event.id}</guid>
  295. </item>
  296. </channel>
  297. </rss>
  298. XML
  299. end
  300. end
  301. end
  302. end