java_script_agent_spec.rb 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. require 'spec_helper'
  2. describe Agents::JavaScriptAgent do
  3. before do
  4. @valid_params = {
  5. :name => "somename",
  6. :options => {
  7. :code => "Agent.check = function() { this.createEvent({ 'message': 'hi' }); };",
  8. }
  9. }
  10. @agent = Agents::JavaScriptAgent.new(@valid_params)
  11. @agent.user = users(:jane)
  12. @agent.save!
  13. end
  14. describe "validations" do
  15. it "requires 'code'" do
  16. @agent.should be_valid
  17. @agent.options['code'] = ''
  18. @agent.should_not be_valid
  19. @agent.options.delete('code')
  20. @agent.should_not be_valid
  21. end
  22. end
  23. describe "#working?" do
  24. describe "when expected_update_period_in_days is set" do
  25. it "returns false when more than expected_update_period_in_days have passed since the last event creation" do
  26. @agent.options['expected_update_period_in_days'] = 1
  27. @agent.save!
  28. @agent.should_not be_working
  29. @agent.check
  30. @agent.reload.should be_working
  31. three_days_from_now = 3.days.from_now
  32. stub(Time).now { three_days_from_now }
  33. @agent.should_not be_working
  34. end
  35. end
  36. describe "when expected_receive_period_in_days is set" do
  37. it "returns false when more than expected_receive_period_in_days have passed since the last event was received" do
  38. @agent.options['expected_receive_period_in_days'] = 1
  39. @agent.save!
  40. @agent.should_not be_working
  41. Agents::JavaScriptAgent.async_receive @agent.id, [events(:bob_website_agent_event).id]
  42. @agent.reload.should be_working
  43. two_days_from_now = 2.days.from_now
  44. stub(Time).now { two_days_from_now }
  45. @agent.reload.should_not be_working
  46. end
  47. end
  48. end
  49. describe "executing code" do
  50. it "works by default" do
  51. @agent.options = @agent.default_options
  52. @agent.options['make_event'] = true;
  53. @agent.save!
  54. lambda {
  55. lambda {
  56. @agent.receive([events(:bob_website_agent_event)])
  57. @agent.check
  58. }.should_not change { AgentLog.count }
  59. }.should change { Event.count }.by(2)
  60. end
  61. describe "error handling" do
  62. it "should log an error when V8 has issues" do
  63. @agent.options['code'] = 'syntax error!'
  64. @agent.save!
  65. lambda {
  66. lambda {
  67. @agent.check
  68. }.should_not raise_error
  69. }.should change { AgentLog.count }.by(1)
  70. AgentLog.last.message.should =~ /Unexpected identifier/
  71. AgentLog.last.level.should == 4
  72. end
  73. it "should log an error when JavaScript throws" do
  74. @agent.options['code'] = 'Agent.check = function() { throw "oh no"; };'
  75. @agent.save!
  76. lambda {
  77. lambda {
  78. @agent.check
  79. }.should_not raise_error
  80. }.should change { AgentLog.count }.by(1)
  81. AgentLog.last.message.should =~ /oh no/
  82. AgentLog.last.level.should == 4
  83. end
  84. it "won't store NaNs" do
  85. @agent.options['code'] = 'Agent.check = function() { this.memory("foo", NaN); };'
  86. @agent.save!
  87. @agent.check
  88. @agent.memory['foo'].should == 'NaN' # string
  89. @agent.save!
  90. lambda { @agent.reload.memory }.should_not raise_error
  91. end
  92. end
  93. describe "creating events" do
  94. it "creates events with this.createEvent in the JavaScript environment" do
  95. @agent.options['code'] = 'Agent.check = function() { this.createEvent({ message: "This is an event!", stuff: { foo: 5 } }); };'
  96. @agent.save!
  97. lambda {
  98. lambda {
  99. @agent.check
  100. }.should_not change { AgentLog.count }
  101. }.should change { Event.count }.by(1)
  102. created_event = @agent.events.last
  103. created_event.payload.should == { 'message' => "This is an event!", 'stuff' => { 'foo' => 5 } }
  104. end
  105. end
  106. describe "logging" do
  107. it "can output AgentLogs with this.log and this.error in the JavaScript environment" do
  108. @agent.options['code'] = 'Agent.check = function() { this.log("woah"); this.error("WOAH!"); };'
  109. @agent.save!
  110. lambda {
  111. lambda {
  112. @agent.check
  113. }.should_not raise_error
  114. }.should change { AgentLog.count }.by(2)
  115. log1, log2 = AgentLog.last(2)
  116. log1.message.should == "woah"
  117. log1.level.should == 3
  118. log2.message.should == "WOAH!"
  119. log2.level.should == 4
  120. end
  121. end
  122. describe "getting incoming events" do
  123. it "can access incoming events in the JavaScript enviroment via this.incomingEvents" do
  124. event = Event.new
  125. event.agent = agents(:bob_rain_notifier_agent)
  126. event.payload = { :data => "Something you should know about" }
  127. event.save!
  128. event.reload
  129. @agent.options['code'] = <<-JS
  130. Agent.receive = function() {
  131. var events = this.incomingEvents();
  132. for(var i = 0; i < events.length; i++) {
  133. this.createEvent({ 'message': 'I got an event!', 'event_was': events[i].payload });
  134. }
  135. }
  136. JS
  137. @agent.save!
  138. lambda {
  139. lambda {
  140. @agent.receive([events(:bob_website_agent_event), event])
  141. }.should_not change { AgentLog.count }
  142. }.should change { Event.count }.by(2)
  143. created_event = @agent.events.first
  144. created_event.payload.should == { 'message' => "I got an event!", 'event_was' => { 'data' => "Something you should know about" } }
  145. end
  146. end
  147. describe "getting and setting memory, getting options" do
  148. it "can access options via this.options and work with memory via this.memory" do
  149. @agent.options['code'] = <<-JS
  150. Agent.check = function() {
  151. if (this.options('make_event')) {
  152. var callCount = this.memory('callCount') || 0;
  153. this.memory('callCount', callCount + 1);
  154. }
  155. };
  156. JS
  157. @agent.save!
  158. lambda {
  159. lambda {
  160. @agent.check
  161. @agent.memory['callCount'].should_not be_present
  162. @agent.options['make_event'] = true
  163. @agent.check
  164. @agent.memory['callCount'].should == 1
  165. @agent.check
  166. @agent.memory['callCount'].should == 2
  167. @agent.memory['callCount'] = 20
  168. @agent.check
  169. @agent.memory['callCount'].should == 21
  170. }.should_not change { AgentLog.count }
  171. }.should_not change { Event.count }
  172. end
  173. end
  174. end
  175. end