From e24cd6dad76210463384cc7e305c8373fe76b5e1 Mon Sep 17 00:00:00 2001 From: Rishabh Jain Date: Mon, 13 May 2013 02:34:35 +0530 Subject: [PATCH] Specs for EventFormattingAgent,SentimentAgent and minor changes --- app/models/agents/event_formatting_agent.rb | 48 ++++--- app/models/agents/sentiment_agent.rb | 3 +- .../agents/event_formatting_agent_spec.rb | 119 ++++++++++++++++++ spec/models/agents/sentiment_agent_spec.rb | 76 +++++++++++ 4 files changed, 228 insertions(+), 18 deletions(-) create mode 100644 spec/models/agents/event_formatting_agent_spec.rb create mode 100644 spec/models/agents/sentiment_agent_spec.rb diff --git a/app/models/agents/event_formatting_agent.rb b/app/models/agents/event_formatting_agent.rb index d2c6d354..43661b48 100644 --- a/app/models/agents/event_formatting_agent.rb +++ b/app/models/agents/event_formatting_agent.rb @@ -7,28 +7,31 @@ module Agents For example if you have an event like { - :content => { - :text => "Lorem ipsum dolor sit amet" + :high => { + :celsius => "18", + :fahreinheit => "64" }, - :fields => "consectetur adipisicing elit", + :conditions => "Rain showers", :data => "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." } - And other agents which are receiving this event, say, Twilio Agent expects `message` key , and Digest Email Agent which expects a `subject` key, then you can reformat this event by filling `Options` in the following way. + And other agents which are receiving this event, say, Twilio Agent expects `message` key , and Digest Email Agent which expects a `subject` key, then you can reformat this event by filling `Instructions` in the following way. - message => $.content.text - subject => $.fields + message => "Today's conditions look like <$.conditions> and high temperaure is going to be <$.high.celsius> degree Celsius."" + subject => "$.data" - Values must be provided in JSONPath. You can add as many keys as you like. + JSONPaths must be between < and > . Make sure you dont use this symbols anywhere else. You can add as many keys as you like. - Then, event generated by Event Formatting Agent will be like + Event generated by Event Formatting Agent will be like { - :message => "Lorem ipsum dolor sit amet" - :subject => "consectetur adipisicing elit" + :message => "Today's conditions look like Rain showers and high temperaure is going to be 18 degree Celsius" + :subject => "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." } + `Mode` can only be `merge` or `clean`. If you want to retain original contents of events and only add add new keys, then use `merge` mode else use `clean` mode. + MD event_description <<-MD @@ -36,9 +39,18 @@ module Agents User defined MD + def validate_options + errors.add(:base,"instructions,mode,skip_agent and skip_created_at , all need to be present.") unless options[:instructions].present? and options[:mode].present? and options[:skip_agent].present? and options[:skip_created_at].present? + end + def default_options { - :message => "$.data.fields.content" + :instructions => { + :message => "You received a text <$.text> from <$.fields.from>", + :content => "Looks like the weather is going to be <$.fields.weather>"}, + :mode => "clean", + :skip_agent => "false", + :skip_created_at => "false" } end @@ -46,14 +58,16 @@ module Agents true end + def value_constructor(value,payload) + value.gsub(/<[^>]+>/).each {|jsonpath| Utils.values_at(payload,jsonpath[1..-2]).first.to_s} + end + def receive(incoming_events) incoming_events.each do |event| - formatted_event = {} - options.each_pair do |key,value| - formatted_event[key] = Utils.values_at event.payload,value - end - formatted_event[:agent] = Agent.find(event.agent_id).type.slice! 8..-1 - formatted_event[:created_at] = event.created_at + formatted_event = options[:mode].to_s == "merge" ? event.payload : {} + options[:instructions].each_pair {|key,value| formatted_event[key] = value_constructor value, event.payload} + formatted_event[:agent] = Agent.find(event.agent_id).type.slice!(8..-1) unless options[:skip_agent].to_s == "true" + formatted_event[:created_at] = event.created_at unless options[:skip_created_at].to_s == "true" create_event :payload => formatted_event end end diff --git a/app/models/agents/sentiment_agent.rb b/app/models/agents/sentiment_agent.rb index 7c71e57d..e7a476cc 100644 --- a/app/models/agents/sentiment_agent.rb +++ b/app/models/agents/sentiment_agent.rb @@ -44,7 +44,8 @@ module Agents create_event :payload => {:content => content, :valence => sent_values[0], :arousal => sent_values[1], - :dominance => sent_values[2]} + :dominance => sent_values[2], + :original_event => event.payload} end end end diff --git a/spec/models/agents/event_formatting_agent_spec.rb b/spec/models/agents/event_formatting_agent_spec.rb new file mode 100644 index 00000000..72cb77c2 --- /dev/null +++ b/spec/models/agents/event_formatting_agent_spec.rb @@ -0,0 +1,119 @@ +require 'spec_helper' + +describe Agents::EventFormattingAgent do + before do + @valid_params = { + :name => "somename", + :options => { + :instructions => { + :message => "Received <$.content.text.*> from <$.content.name> .", + :subject => "Weather looks like <$.conditions>" + }, + :mode => "clean", + :skip_agent => "false", + :skip_created_at => "false" + } + } + @checker = Agents::EventFormattingAgent.new(@valid_params) + @checker.user = users(:jane) + @checker.save! + + @event = Event.new + @event.agent = agents(:jane_weather_agent) + @event.created_at = Time.now + @event.payload = { + :content => { + :text => "Some Lorem Ipsum", + :name => "somevalue" + }, + :conditions => "someothervalue" + } + end + + describe "#receive" do + it "checks if clean mode is working fine" do + @checker.receive([@event]) + Event.last.payload[:content].should == nil + end + + it "checks if merge mode is working fine" do + @checker.options[:mode] = "merge" + @checker.receive([@event]) + Event.last.payload[:content].should_not == nil + end + + it "checks if skip_agent is working fine" do + @checker.receive([@event]) + Event.last.payload[:agent].should == "WeatherAgent" + @checker.options[:skip_agent] = "true" + @checker.receive([@event]) + Event.last.payload[:agent].should == nil + end + + it "checks if skip_created_at is working fine" do + @checker.receive([@event]) + Event.last.payload[:created_at].should_not == nil + @checker.options[:skip_created_at] = "true" + @checker.receive([@event]) + Event.last.payload[:created_at].should == nil + end + + it "checks if instructions are working fine" do + @checker.receive([@event]) + Event.last.payload[:message].should == "Received Some Lorem Ipsum from somevalue ." + Event.last.payload[:subject].should == "Weather looks like someothervalue" + end + + it "checks if it can handle multiple events" do + event1 = Event.new + event1.agent = agents(:bob_weather_agent) + event1.payload = { + :content => { + :text => "Some Lorem Ipsum", + :name => "somevalue" + }, + :conditions => "someothervalue" + } + + event2 = Event.new + event2.agent = agents(:bob_weather_agent) + event2.payload = { + :content => { + :text => "Some Lorem Ipsum", + :name => "somevalue" + }, + :conditions => "someothervalue" + } + + lambda { + @checker.receive([event2,event1]) + }.should change { Event.count }.by(2) + end + end + + describe "validation" do + before do + @checker.should be_valid + end + + it "should validate presence of instructions" do + @checker.options[:instructions] = "" + @checker.should_not be_valid + end + + it "should validate presence of mode" do + @checker.options[:mode] = "" + @checker.should_not be_valid + end + + it "should validate presence of skip_agent" do + @checker.options[:skip_agent] = "" + @checker.should_not be_valid + end + + it "should validate presence of skip_created_at" do + @checker.options[:skip_created_at] = "" + @checker.should_not be_valid + end + end +end \ No newline at end of file diff --git a/spec/models/agents/sentiment_agent_spec.rb b/spec/models/agents/sentiment_agent_spec.rb new file mode 100644 index 00000000..142abad8 --- /dev/null +++ b/spec/models/agents/sentiment_agent_spec.rb @@ -0,0 +1,76 @@ +require 'spec_helper' + +describe Agents::SentimentAgent do + before do + @valid_params = { + :name => "somename", + :options => { + :content => "$.message", + :expected_receive_period_in_days => 1 + } + } + + @checker = Agents::SentimentAgent.new(@valid_params) + @checker.user = users(:jane) + @checker.save! + + @event = Event.new + @event.agent = agents(:jane_weather_agent) + @event.payload = { + :message => "value1" + } + @event.save! + end + + describe "#working?" do + it "checks if events have been received within expected receive period" do + @checker.should_not be_working + Agents::SentimentAgent.async_receive @checker.id, [@event.id] + @checker.reload.should be_working + two_days_from_now = 2.days.from_now + stub(Time).now { two_days_from_now } + @checker.reload.should_not be_working + end + end + + describe "validation" do + before do + @checker.should be_valid + end + + it "should validate presence of content key" do + @checker.options[:content] = nil + @checker.should_not be_valid + end + + it "should validate presence of expected_receive_period_in_days key" do + @checker.options[:expected_receive_period_in_days] = nil + @checker.should_not be_valid + end + end + + describe "#receive" do + it "checks if content key is working fine" do + @checker.receive([@event]) + Event.last.payload[:content].should == "value1" + Event.last.payload[:original_event].should == {:message => "value1"} + end + it "should handle multiple events" do + event1 = Event.new + event1.agent = agents(:bob_weather_agent) + event1.payload = { + :message => "The quick brown fox jumps over the lazy dog" + } + + event2 = Event.new + event2.agent = agents(:jane_weather_agent) + event2.payload = { + :message => "The quick brown fox jumps over the lazy dog" + } + + lambda { + @checker.receive([@event,event1,event2]) + }.should change { Event.count }.by(3) + end + end +end \ No newline at end of file