| @@ -18,8 +18,15 @@ module Agents | ||
| 18 | 18 |  | 
| 19 | 19 | def handle_details_post(params) | 
| 20 | 20 | if params['payload'] | 
| 21 | - create_event(:payload => params['payload']) | |
| 22 | -        { :success => true } | |
| 21 | + json = interpolate_options(JSON.parse(params['payload'])) | |
| 22 | + if json['payloads'] && (json.keys - ['payloads']).length > 0 | |
| 23 | +          { :success => false, :error => "If you provide the 'payloads' key, please do not provide any other keys at the top level." } | |
| 24 | + else | |
| 25 | + [json['payloads'] || json].flatten.each do |payload| | |
| 26 | + create_event(:payload => payload) | |
| 27 | + end | |
| 28 | +          { :success => true } | |
| 29 | + end | |
| 23 | 30 | else | 
| 24 | 31 |          { :success => false, :error => "You must provide a JSON payload" } | 
| 25 | 32 | end | 
| @@ -1,4 +1,15 @@ | ||
| 1 | -<h3>Manually Create Events</h3> | |
| 1 | +<p> | |
| 2 | + Use this form to manually emit Events from this Agent (usually for testing). | |
| 3 | +</p> | |
| 4 | + | |
| 5 | +<p> | |
| 6 | + If you add a top-level key called <code>payloads</code> that points to an array of objects, they will be emitted as a series | |
| 7 | + of Events. Otherwise, everything entered will be emitted as a single Event. | |
| 8 | +</p> | |
| 9 | + | |
| 10 | +<p> | |
| 11 | + Liquid formatting is supported. | |
| 12 | +</p> | |
| 2 | 13 |  | 
| 3 | 14 | <h4 id='event-creation-status'></h4> | 
| 4 | 15 |  | 
| @@ -22,7 +33,7 @@ | ||
| 22 | 33 |        $.ajax({ | 
| 23 | 34 |          url: $form.attr('action'), | 
| 24 | 35 | method: "post", | 
| 25 | -        data: { payload: JSON.parse($form.find("textarea").val()) }, | |
| 36 | +        data: { payload: $form.find("textarea").val() }, | |
| 26 | 37 | dataType: "JSON", | 
| 27 | 38 |          success: function(json) { | 
| 28 | 39 |            if (json.success) { | 
| @@ -21,7 +21,7 @@ describe AgentsController do | ||
| 21 | 21 | describe "POST handle_details_post" do | 
| 22 | 22 | it "passes control to handle_details_post on the agent" do | 
| 23 | 23 | sign_in users(:bob) | 
| 24 | -      post :handle_details_post, :id => agents(:bob_manual_event_agent).to_param, :payload => { :foo => "bar" } | |
| 24 | +      post :handle_details_post, :id => agents(:bob_manual_event_agent).to_param, :payload => { :foo => "bar" }.to_json | |
| 25 | 25 |        expect(JSON.parse(response.body)).to eq({ "success" => true }) | 
| 26 | 26 |        expect(agents(:bob_manual_event_agent).events.last.payload).to eq({ 'foo' => "bar" }) | 
| 27 | 27 | end | 
| @@ -29,7 +29,7 @@ describe AgentsController do | ||
| 29 | 29 | it "can only be accessed by the Agent's owner" do | 
| 30 | 30 | sign_in users(:jane) | 
| 31 | 31 |        expect { | 
| 32 | -        post :handle_details_post, :id => agents(:bob_manual_event_agent).to_param, :payload => { :foo => :bar } | |
| 32 | +        post :handle_details_post, :id => agents(:bob_manual_event_agent).to_param, :payload => { :foo => :bar }.to_json | |
| 33 | 33 | }.to raise_error(ActiveRecord::RecordNotFound) | 
| 34 | 34 | end | 
| 35 | 35 | end | 
| @@ -0,0 +1,50 @@ | ||
| 1 | +require 'rails_helper' | |
| 2 | + | |
| 3 | +describe Agents::ManualEventAgent do | |
| 4 | + before do | |
| 5 | + @checker = Agents::ManualEventAgent.new(name: "My Manual Event Agent") | |
| 6 | + @checker.user = users(:jane) | |
| 7 | + @checker.save! | |
| 8 | + end | |
| 9 | + | |
| 10 | + describe "#handle_details_post" do | |
| 11 | + it "emits an event with the given payload" do | |
| 12 | +      expect { | |
| 13 | +        json = { 'foo' => "bar" }.to_json | |
| 14 | +        expect(@checker.handle_details_post({ 'payload' => json })).to eq({ success: true }) | |
| 15 | +      }.to change { @checker.events.count }.by(1) | |
| 16 | +      expect(@checker.events.last.payload).to eq({ 'foo' => 'bar' }) | |
| 17 | + end | |
| 18 | + | |
| 19 | + it "emits multiple events when given a magic 'payloads' key" do | |
| 20 | +      expect { | |
| 21 | +        json = { 'payloads' => [{ 'key' => 'value1' }, { 'key' => 'value2' }] }.to_json | |
| 22 | +        expect(@checker.handle_details_post({ 'payload' => json })).to eq({ success: true }) | |
| 23 | +      }.to change { @checker.events.count }.by(2) | |
| 24 | +      events = @checker.events.order('id desc') | |
| 25 | +      expect(events[0].payload).to eq({ 'key' => 'value2' }) | |
| 26 | +      expect(events[1].payload).to eq({ 'key' => 'value1' }) | |
| 27 | + end | |
| 28 | + | |
| 29 | + it "errors when given both payloads and other top-level keys" do | |
| 30 | +      expect { | |
| 31 | +        json = { 'key' => 'value2', 'payloads' => [{ 'key' => 'value1' }] }.to_json | |
| 32 | +        expect(@checker.handle_details_post({ 'payload' => json })).to eq({ success: false, error: "If you provide the 'payloads' key, please do not provide any other keys at the top level." }) | |
| 33 | +      }.to_not change { @checker.events.count } | |
| 34 | + end | |
| 35 | + | |
| 36 | + it "supports Liquid formatting" do | |
| 37 | +      expect { | |
| 38 | +        json = { 'key' => "{{ 'now' | date: '%Y' }}", 'nested' => { 'lowercase' => "{{ 'uppercase' | upcase }}" } }.to_json | |
| 39 | +        expect(@checker.handle_details_post({ 'payload' => json })).to eq({ success: true }) | |
| 40 | +      }.to change { @checker.events.count }.by(1) | |
| 41 | +      expect(@checker.events.last.payload).to eq({ 'key' => Time.now.year.to_s, 'nested' => { 'lowercase' => 'UPPERCASE' } }) | |
| 42 | + end | |
| 43 | + | |
| 44 | + it "errors when not given a JSON payload" do | |
| 45 | +      expect { | |
| 46 | +        expect(@checker.handle_details_post({ 'foo' =>'bar' })).to eq({ success: false, error: "You must provide a JSON payload" }) | |
| 47 | +      }.not_to change { @checker.events.count } | |
| 48 | + end | |
| 49 | + end | |
| 50 | +end |