require 'spec_helper' describe "Search features" do describe Riak::Client do before :each do @client = Riak::Client.new @http = mock(Riak::Client::HTTPBackend) @client.stub!(:http).and_return(@http) end describe "searching" do it "should exclude the index from the URL when not specified" do @http.should_receive(:get).with(200, "/solr", "select", hash_including("q" => "foo"), {}).and_return({:code => 200, :headers => {"content-type"=>["application/json"]}, :body => "{}"}) @client.search("foo") end it "should include extra options in the query string" do @http.should_receive(:get).with(200, "/solr", "select", hash_including('rows' => 30), {}).and_return({:code => 200, :headers => {"content-type"=>["application/json"]}, :body => "{}"}) @client.search("foo", 'rows' => 30) end it "should include the index in the URL when specified" do @http.should_receive(:get).with(200, "/solr", "search", "select", hash_including("q" => "foo"), {}).and_return({:code => 200, :headers => {"content-type"=>["application/json"]}, :body => "{}"}) @client.search("search", "foo") end it "should vivify JSON responses" do @http.should_receive(:get).and_return({:code => 200, :headers => {"content-type"=>["application/json"]}, :body => '{"response":{"docs":["foo"]}}'}) @client.search("foo").should == {"response" => {"docs" => ["foo"]}} end it "should return non-JSON responses raw" do @http.should_receive(:get).and_return({:code => 200, :headers => {"content-type"=>["text/plain"]}, :body => '{"response":{"docs":["foo"]}}'}) @client.search("foo").should == '{"response":{"docs":["foo"]}}' end end describe "indexing documents" do it "should exclude the index from the URL when not specified" do @http.should_receive(:post).with(200, "/solr", "update", anything, anything).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""}) @client.index({:id => 1, :field => "value"}) end it "should include the index in the URL when specified" do @http.should_receive(:post).with(200, "/solr", "foo", "update", anything, anything).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""}) @client.index("foo", {:id => 1, :field => "value"}) end it "should raise an error when documents do not contain an id" do @http.stub!(:post).and_return(true) lambda { @client.index({:field => "value"}) }.should raise_error(ArgumentError) lambda { @client.index({:id => 1, :field => "value"}) }.should_not raise_error(ArgumentError) end it "should build a Solr request" do expect_update_body('1value') @client.index({'id' => 1, 'field' => "value"}) end it "should include multiple documents in the request" do expect_update_body('1value2bar') @client.index({'id' => 1, 'field' => "value"}, {'id' => 2, 'foo' => "bar"}) end end describe "removing documents" do it "should exclude the index from the URL when not specified" do @http.should_receive(:post).with(200, "/solr","update", anything, anything).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""}) @client.remove({:id => 1}) end it "should include the index in the URL when specified" do @http.should_receive(:post).with(200, "/solr", "foo", "update", anything, anything).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""}) @client.remove("foo", {:id => 1}) end it "should raise an error when document specifications don't include an id or query" do @http.stub!(:post).and_return({:code => 200}) lambda { @client.remove({:foo => "bar"}) }.should raise_error(ArgumentError) lambda { @client.remove({:id => 1}) }.should_not raise_error end it "should build a Solr request" do expect_update_body('1') @client.remove(:id => 1) expect_update_body('title:old') @client.remove(:query => "title:old") end it "should include multiple specs in the request" do expect_update_body('1title:old') @client.remove({:id => 1}, {:query => "title:old"}) end end def expect_update_body(body, index=nil) args = [200, "/solr", index, "update", body, {"Content-Type" => "text/xml"}].compact @http.should_receive(:post).with(*args).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""}) end end describe Riak::Bucket do before :each do @client = Riak::Client.new @bucket = Riak::Bucket.new(@client, "foo") end def load_without_index_hook @bucket.instance_variable_set(:@props, {"precommit" => []}) end def load_with_index_hook @bucket.instance_variable_set(:@props, {"precommit" => [{"mod" => "riak_search_kv_hook", "fun" => "precommit"}]}) end it "should detect whether the indexing hook is installed" do load_without_index_hook @bucket.is_indexed?.should be_false load_with_index_hook @bucket.is_indexed?.should be_true end describe "enabling indexing" do it "should add the index hook when not present" do load_without_index_hook @bucket.should_receive(:props=).with({"precommit" => [Riak::Bucket::SEARCH_PRECOMMIT_HOOK]}) @bucket.enable_index! end it "should not modify the precommit when the hook is present" do load_with_index_hook @bucket.should_not_receive(:props=) @bucket.enable_index! end end describe "disabling indexing" do it "should remove the index hook when present" do load_with_index_hook @bucket.should_receive(:props=).with({"precommit" => []}) @bucket.disable_index! end it "should not modify the precommit when the hook is missing" do load_without_index_hook @bucket.should_not_receive(:props=) @bucket.disable_index! end end end describe Riak::MapReduce do before :each do @client = Riak::Client.new @mr = Riak::MapReduce.new(@client) end describe "using a search query as inputs" do it "should accept a bucket name and query" do @mr.search("foo", "bar OR baz") @mr.inputs.should == {:module => "riak_search", :function => "mapred_search", :arg => ["foo", "bar OR baz"]} end it "should accept a Riak::Bucket and query" do @mr.search(Riak::Bucket.new(@client, "foo"), "bar OR baz") @mr.inputs.should == {:module => "riak_search", :function => "mapred_search", :arg => ["foo", "bar OR baz"]} end it "should emit the Erlang function and arguments" do @mr.search("foo", "bar OR baz") @mr.to_json.should include('"inputs":{') @mr.to_json.should include('"module":"riak_search"') @mr.to_json.should include('"function":"mapred_search"') @mr.to_json.should include('"arg":["foo","bar OR baz"]') end end end end