require 'spec_helper' describe Wukong::Load::ElasticsearchLoader do let(:record) { {'text' => 'hi' } } let(:record_with_index) { {'text' => 'hi', '_index' => 'custom_index' } } let(:record_with_custom_index) { {'text' => 'hi', '_custom_index' => 'custom_index' } } let(:record_with_es_type) { {'text' => 'hi', '_es_type' => 'custom_es_type' } } let(:record_with_custom_es_type) { {'text' => 'hi', '_custom_es_type' => 'custom_es_type' } } let(:record_with_id) { {'text' => 'hi', '_id' => 'the_id' } } let(:record_with_custom_id) { {'text' => 'hi', '_custom_id' => 'the_id' } } it_behaves_like 'a processor', :named => :elasticsearch_loader context "without an Elasticsearch available" do before do Net::HTTP.should_receive(:new).and_raise(StandardError) end it "raises an error on setup" do expect { processor(:elasticsearch_loader).setup }.to raise_error(Wukong::Error) end end context "routes" do context "all records" do it "to a default index" do proc = processor(:elasticsearch_loader) proc.index_for(record).should == proc.index end it "to a given index" do processor(:elasticsearch_loader, :index => 'custom_index').index_for(record).should == 'custom_index' end it "to a default type" do proc = processor(:elasticsearch_loader) proc.es_type_for(record).should == proc.es_type end it "to a given type" do processor(:elasticsearch_loader, :es_type => 'custom_es_type').es_type_for(record).should == 'custom_es_type' end end context "records having a value for" do it "default index field to the given index" do processor(:elasticsearch_loader).index_for(record_with_index).should == 'custom_index' end it "given index field to the given index" do processor(:elasticsearch_loader, :index_field => '_custom_index').index_for(record_with_custom_index).should == 'custom_index' end it "default type field to the given type" do processor(:elasticsearch_loader).es_type_for(record_with_es_type).should == 'custom_es_type' end it "given type field to the given type" do processor(:elasticsearch_loader, :es_type_field => '_custom_es_type').es_type_for(record_with_custom_es_type).should == 'custom_es_type' end end end context "detects IDs" do it "based on the absence of a default ID field" do processor(:elasticsearch_loader).id_for(record).should be_nil end it "based on the value of a default ID field" do processor(:elasticsearch_loader).id_for(record_with_id).should == 'the_id' end it "based on the value of a custom ID field" do processor(:elasticsearch_loader, :id_field => '_custom_id').id_for(record_with_custom_id).should == 'the_id' end end context "having made a connection to the database" do let(:connection) { double() } let(:log) { double() } subject { processor(:elasticsearch_loader) } before do Net::HTTP.should_receive(:new).and_return(connection) subject.stub!(:log).and_return(log) end context "sends" do it "create requests on a record without an ID" do subject.should_receive(:request).with(Net::HTTP::Post, '/foo/bar', kind_of(Hash)) subject.load({'_index' => 'foo', '_es_type' => 'bar'}) end it "update requests on a record with an ID" do subject.should_receive(:request).with(Net::HTTP::Put, '/foo/bar/1', kind_of(Hash)) subject.load({'_index' => 'foo', '_es_type' => 'bar', '_id' => '1'}) end end context "receives" do let(:ok) do mock("Net::HTTPOK").tap do |response| response.stub!(:code).and_return('200') response.stub!(:body).and_return('{"ok": true}') end end let(:created) do mock("Net::HTTPCreated").tap do |response| response.stub!(:code).and_return('201') response.stub!(:body).and_return('{"created": true}') end end let(:not_found) do mock("Net::HTTPNotFound").tap do |response| response.stub!(:code).and_return('404') response.stub!(:body).and_return('{"error": "Not found"}') end end context "201 Created" do before { connection.should_receive(:request).with(kind_of(Net::HTTP::Post)).and_return(created) } it "by logging an INFO message" do log.should_receive(:info) subject.load(record) end end context "200 OK" do before { connection.should_receive(:request).with(kind_of(Net::HTTP::Put)).and_return(ok) } it "by logging an INFO message" do log.should_receive(:info) subject.load(record_with_id) end end context "an error response from Elasticsearch" do before { connection.should_receive(:request).with(kind_of(Net::HTTP::Post)).and_return(not_found) } it "by logging an ERROR message" do log.should_receive(:error) subject.load(record) end end end end end