require "rails_helper" describe Agents::KeyValueStoreAgent do let(:value_template) { "{{ _event_ | as_object }}" } let(:agent) do Agents::KeyValueStoreAgent.create!( name: "somename", options: { key: "{{ id }}", value: value_template, variable: "kvs", max_keys: 3, }, user: users(:jane) ) end let(:source_agent) do agents(:jane_weather_agent) end def create_event(payload) source_agent.events.create!(payload:) end let(:events) do [ create_event({ id: 1, name: "foo" }), create_event({ id: 2, name: "bar" }), create_event({ id: 3, name: "baz" }), create_event({ id: 1, name: "FOO" }), create_event({ id: 4, name: "quux" }), ] end describe "validation" do before do expect(agent).to be_valid end it "should validate key" do # empty key is OK agent.options[:key] = "" expect(agent).to be_valid agent.options.delete(:key) expect(agent).not_to be_valid end it "should validate value" do agent.options[:value] = "" expect(agent).to be_valid agent.options.delete(:value) expect(agent).not_to be_valid end it "should validate variable" do agent.options[:variable] = "1abc" expect(agent).not_to be_valid agent.options[:variable] = "" expect(agent).not_to be_valid agent.options[:variable] = {} expect(agent).not_to be_valid agent.options.delete(:variable) expect(agent).not_to be_valid end it "should validate max_keys" do agent.options.delete(:max_keys) expect(agent).to be_valid expect(agent.max_keys).to eq 100 agent.options[:max_keys] = 0 expect(agent).not_to be_valid end end describe "#receive" do it "receives and updates the storage" do agent.receive(events[0..2]) expect(agent.reload.memory).to match( { "1" => { id: 1, name: "foo" }, "2" => { id: 2, name: "bar" }, "3" => { id: 3, name: "baz" }, } ) agent.receive([events[3]]) expect(agent.reload.memory).to match( { "1" => { id: 1, name: "FOO" }, "2" => { id: 2, name: "bar" }, "3" => { id: 3, name: "baz" }, } ) agent.receive([events[4]]) # The key "bar" should have been removed because it is the oldest. expect(agent.reload.memory).to match( { "1" => { id: 1, name: "FOO" }, "3" => { id: 3, name: "baz" }, "4" => { id: 4, name: "quux" }, } ) expect { agent.receive([create_event({ name: "empty key" })]) }.not_to(change { agent.reload.memory }) end describe "empty value" do let(:value_template) { "{{ name | as_object }}" } it "deletes the key" do agent.receive(events[0..2]) expect(agent.reload.memory).to match( { "1" => "foo", "2" => "bar", "3" => "baz", } ) agent.receive([create_event({ id: 1, name: "" })]) expect(agent.reload.memory).to match( { "2" => "bar", "3" => "baz", } ) agent.receive([create_event({ id: 2, name: [] })]) expect(agent.reload.memory).to match( { "3" => "baz", } ) agent.receive([create_event({ id: 3, name: {} })]) expect(agent.reload.memory).to eq({}) end end describe "using _value_" do let(:value_template) { "{% if _value_ %}{{ _value_ }}, {% endif %}{{ name }}" } it "represents the existing value" do agent.receive(events[0..2]) expect(agent.reload.memory).to match( { "1" => "foo", "2" => "bar", "3" => "baz", } ) agent.receive([events[3]]) expect(agent.reload.memory).to match( { "1" => "foo, FOO", "2" => "bar", "3" => "baz", } ) end end end describe "control target" do let(:value_template) { "{{ name }}" } before do agent.receive(events[0..2]) end let!(:target_agent) do agents(:jane_website_agent).tap { |target_agent| target_agent.options[:url] = "https://example.com/{{ kvs['3'] }}" target_agent.controllers << agent target_agent.save! } end it "can refer to the storage" do expect(target_agent.interpolated[:url]).to eq "https://example.com/baz" end end end