require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
require 'nokogiri'
require 'equivalent-xml'
describe FacetsHelper do
let(:blacklight_config) { Blacklight::Configuration.new }
before(:each) do
helper.stub(:blacklight_config).and_return blacklight_config
end
describe "has_facet_values?" do
it "should be true if there are any facets to display" do
a = double(:items => [1,2])
b = double(:items => ['b','c'])
empty = double(:items => [])
fields = [a,b,empty]
helper.has_facet_values?(fields).should be_true
end
it "should be false if all facets are empty" do
empty = double(:items => [])
fields = [empty]
helper.has_facet_values?(fields).should_not be_true
end
end
describe "should_render_facet?" do
before do
@config = Blacklight::Configuration.new do |config|
config.add_facet_field 'basic_field'
config.add_facet_field 'no_show', :show => false
config.add_facet_field 'helper_show', :show => :my_helper
config.add_facet_field 'helper_with_an_arg_show', :show => :my_helper_with_an_arg
config.add_facet_field 'lambda_show', :show => lambda { |context, config, field| true }
config.add_facet_field 'lambda_no_show', :show => lambda { |context, config, field| false }
end
helper.stub(:blacklight_config => @config)
end
it "should render facets with items" do
a = double(:items => [1,2], :name=>'basic_field')
helper.should_render_facet?(a).should == true
end
it "should not render facets without items" do
empty = double(:items => [], :name=>'basic_field')
helper.should_render_facet?(empty).should == false
end
it "should not render facets where show is set to false" do
a = double(:items => [1,2], :name=>'no_show')
helper.should_render_facet?(a).should == false
end
it "should call a helper to determine if it should render a field" do
helper.stub(:my_helper => true)
a = double(:items => [1,2], :name=>'helper_show')
expect(helper.should_render_facet?(a)).to be_true
end
it "should call a helper to determine if it should render a field" do
a = double(:items => [1,2], :name=>'helper_with_an_arg_show')
helper.should_receive(:my_helper_with_an_arg).with(a).and_return(true)
expect(helper.should_render_facet?(a)).to be_true
end
it "should evaluate a Proc to determine if it should render a field" do
a = double(:items => [1,2], :name=>'lambda_show')
expect(helper.should_render_facet?(a)).to be_true
a = double(:items => [1,2], :name=>'lambda_no_show')
expect(helper.should_render_facet?(a)).to be_false
end
end
describe "facet_by_field_name" do
it "should retrieve the facet from the response given a string" do
facet_config = double(:query => nil)
facet_field = double()
helper.should_receive(:facet_configuration_for_field).with(anything()).and_return(facet_config)
@response = double()
@response.should_receive(:facet_by_field_name).with('a').and_return(facet_field)
helper.facet_by_field_name('a').should == facet_field
end
it "should also work for facet query fields" do
facet_config = double(:query => {})
helper.should_receive(:facet_configuration_for_field).with('a_query_facet_field').and_return(facet_config)
helper.should_receive(:create_rsolr_facet_field_response_for_query_facet_field).with('a_query_facet_field', facet_config)
helper.facet_by_field_name 'a_query_facet_field'
end
describe "query facets" do
let(:facet_config) {
double(
:query => {
'a_simple_query' => { :fq => 'field:search', :label => 'A Human Readable label'},
'another_query' => { :fq => 'field:different_search', :label => 'Label'},
'without_results' => { :fq => 'field:without_results', :label => 'No results for this facet'}
}
)
}
before(:each) do
helper.should_receive(:facet_configuration_for_field).with(anything()).and_return(facet_config)
@response = double(:facet_queries => {
'field:search' => 10,
'field:different_search' => 2,
'field:not_appearing_in_the_config' => 50,
'field:without_results' => 0
})
end
it"should convert the query facets into a double RSolr FacetField" do
field = helper.facet_by_field_name('my_query_facet_field')
field.should be_a_kind_of Blacklight::SolrResponse::Facets::FacetField
field.name.should == 'my_query_facet_field'
field.items.length.should == 2
field.items.map { |x| x.value }.should_not include 'field:not_appearing_in_the_config'
facet_item = field.items.select { |x| x.value == 'a_simple_query' }.first
facet_item.value.should == 'a_simple_query'
facet_item.hits.should == 10
facet_item.label.should == 'A Human Readable label'
end
end
describe "pivot facets" do
let(:facet_config) {
double(:pivot => ['field_a', 'field_b'])
}
before(:each) do
helper.should_receive(:facet_configuration_for_field).with(anything()).and_return(facet_config)
@response = double(:facet_pivot => { 'field_a,field_b' => [{:field => 'field_a', :value => 'a', :count => 10, :pivot => [{:field => 'field_b', :value => 'b', :count => 2}]}]})
end
it "should convert the pivot facet into a double RSolr FacetField" do
field = helper.facet_by_field_name('my_pivot_facet_field')
field.should be_a_kind_of Blacklight::SolrResponse::Facets::FacetField
field.name.should == 'my_pivot_facet_field'
field.items.length.should == 1
field.items.first.should respond_to(:items)
field.items.first.items.length.should == 1
field.items.first.items.first.fq.should == { 'field_a' => 'a' }
end
end
end
describe "render_facet_partials" do
it "should try to render all provided facets " do
a = double(:items => [1,2])
b = double(:items => ['b','c'])
empty = double(:items => [])
fields = [a,b,empty]
helper.should_receive(:render_facet_limit).with(a, {})
helper.should_receive(:render_facet_limit).with(b, {})
helper.should_receive(:render_facet_limit).with(empty, {})
helper.render_facet_partials fields
end
it "should default to the configured facets" do
a = double(:items => [1,2])
b = double(:items => ['b','c'])
helper.should_receive(:facet_field_names) { [a,b] }
helper.should_receive(:render_facet_limit).with(a, {})
helper.should_receive(:render_facet_limit).with(b, {})
helper.render_facet_partials
end
end
describe "render_facet_limit" do
before do
@config = Blacklight::Configuration.new do |config|
config.add_facet_field 'basic_field'
config.add_facet_field 'pivot_facet_field', :pivot => ['a', 'b']
config.add_facet_field 'my_pivot_facet_field_with_custom_partial', :partial => 'custom_facet_partial', :pivot => ['a', 'b']
config.add_facet_field 'my_facet_field_with_custom_partial', :partial => 'custom_facet_partial'
end
helper.stub(:blacklight_config => @config)
@response = double()
end
it "should set basic local variables" do
@mock_facet = double(:name => 'basic_field', :items => [1,2,3])
helper.should_receive(:render).with(hash_including(:partial => 'facet_limit',
:locals => {
:solr_field => 'basic_field',
:solr_fname => 'basic_field',
:facet_field => helper.blacklight_config.facet_fields['basic_field'],
:display_facet => @mock_facet }
))
helper.render_facet_limit(@mock_facet)
end
it "should render a facet _not_ declared in the configuration" do
@mock_facet = double(:name => 'asdf', :items => [1,2,3])
helper.should_receive(:render).with(hash_including(:partial => 'facet_limit'))
helper.render_facet_limit(@mock_facet)
end
it "should get the partial name from the configuration" do
@mock_facet = double(:name => 'my_facet_field_with_custom_partial', :items => [1,2,3])
helper.should_receive(:render).with(hash_including(:partial => 'custom_facet_partial'))
helper.render_facet_limit(@mock_facet)
end
it "should use a partial layout for rendering the facet frame" do
@mock_facet = double(:name => 'my_facet_field_with_custom_partial', :items => [1,2,3])
helper.should_receive(:render).with(hash_including(:layout => 'facet_layout'))
helper.render_facet_limit(@mock_facet)
end
it "should allow the caller to opt-out of facet layouts" do
@mock_facet = double(:name => 'my_facet_field_with_custom_partial', :items => [1,2,3])
helper.should_receive(:render).with(hash_including(:layout => nil))
helper.render_facet_limit(@mock_facet, :layout => nil)
end
it "should render the facet_pivot partial for pivot facets" do
@mock_facet = double(:name => 'pivot_facet_field', :items => [1,2,3])
helper.should_receive(:render).with(hash_including(:partial => 'facet_pivot'))
helper.render_facet_limit(@mock_facet)
end
it "should let you override the rendered partial for pivot facets" do
@mock_facet = double(:name => 'my_pivot_facet_field_with_custom_partial', :items => [1,2,3])
helper.should_receive(:render).with(hash_including(:partial => 'custom_facet_partial'))
helper.render_facet_limit(@mock_facet)
end
it "should be deprecated when a string is passed" do
expect(@response).to receive(:facet_by_field_name)
expect(Blacklight::FacetsHelperBehavior.deprecation_behavior.first).to receive(:call)
helper.render_facet_limit('basic_field')
end
end
describe "add_facet_params" do
before do
@params_no_existing_facet = {:q => "query", :search_field => "search_field", :per_page => "50"}
@params_existing_facets = {:q => "query", :search_field => "search_field", :per_page => "50", :f => {"facet_field_1" => ["value1"], "facet_field_2" => ["value2", "value2a"]}}
end
it "should add facet value for no pre-existing facets" do
helper.stub(:params).and_return(@params_no_existing_facet)
result_params = helper.add_facet_params("facet_field", "facet_value")
result_params[:f].should be_a_kind_of(Hash)
result_params[:f]["facet_field"].should be_a_kind_of(Array)
result_params[:f]["facet_field"].should == ["facet_value"]
end
it "should add a facet param to existing facet constraints" do
helper.stub(:params).and_return(@params_existing_facets)
result_params = helper.add_facet_params("facet_field_2", "new_facet_value")
result_params[:f].should be_a_kind_of(Hash)
@params_existing_facets[:f].each_pair do |facet_field, value_list|
result_params[:f][facet_field].should be_a_kind_of(Array)
if facet_field == 'facet_field_2'
result_params[:f][facet_field].should == (@params_existing_facets[:f][facet_field] | ["new_facet_value"])
else
result_params[:f][facet_field].should == @params_existing_facets[:f][facet_field]
end
end
end
it "should leave non-facet params alone" do
[@params_existing_facets, @params_no_existing_facet].each do |params|
helper.stub(:params).and_return(params)
result_params = helper.add_facet_params("facet_field_2", "new_facet_value")
params.each_pair do |key, value|
next if key == :f
result_params[key].should == params[key]
end
end
end
it "should replace facets for facets configured as single" do
helper.should_receive(:facet_configuration_for_field).with('single_value_facet_field').and_return(double(:single => true))
params = { :f => { 'single_value_facet_field' => 'other_value'}}
helper.stub(:params).and_return params
result_params = helper.add_facet_params('single_value_facet_field', 'my_value')
result_params[:f]['single_value_facet_field'].length.should == 1
result_params[:f]['single_value_facet_field'].first.should == 'my_value'
end
it "should accept a FacetItem instead of a plain facet value" do
result_params = helper.add_facet_params('facet_field_1', double(:value => 123))
result_params[:f]['facet_field_1'].should include(123)
end
it "should defer to the field set on a FacetItem" do
result_params = helper.add_facet_params('facet_field_1', double(:field => 'facet_field_2', :value => 123))
result_params[:f]['facet_field_1'].should be_blank
result_params[:f]['facet_field_2'].should include(123)
end
it "should add any extra fq parameters from the FacetItem" do
result_params = helper.add_facet_params('facet_field_1', double(:value => 123, :fq => {'facet_field_2' => 'abc'}))
result_params[:f]['facet_field_1'].should include(123)
result_params[:f]['facet_field_2'].should include('abc')
end
end
describe "add_facet_params_and_redirect" do
before do
catalog_facet_params = {:q => "query",
:search_field => "search_field",
:per_page => "50",
:page => "5",
:f => {"facet_field_1" => ["value1"], "facet_field_2" => ["value2", "value2a"]},
Blacklight::Solr::FacetPaginator.request_keys[:offset] => "100",
Blacklight::Solr::FacetPaginator.request_keys[:sort] => "index",
:id => 'facet_field_name'
}
helper.stub(:params).and_return(catalog_facet_params)
end
it "should redirect to 'index' action" do
params = helper.add_facet_params_and_redirect("facet_field_2", "facet_value")
params[:action].should == "index"
end
it "should not include request parameters used by the facet paginator" do
params = helper.add_facet_params_and_redirect("facet_field_2", "facet_value")
bad_keys = Blacklight::Solr::FacetPaginator.request_keys.values + [:id]
bad_keys.each do |paginator_key|
params.keys.should_not include(paginator_key)
end
end
it 'should remove :page request key' do
params = helper.add_facet_params_and_redirect("facet_field_2", "facet_value")
params.keys.should_not include(:page)
end
it "should otherwise do the same thing as add_facet_params" do
added_facet_params = helper.add_facet_params("facet_field_2", "facet_value")
added_facet_params_from_facet_action = helper.add_facet_params_and_redirect("facet_field_2", "facet_value")
added_facet_params_from_facet_action.each_pair do |key, value|
next if key == :action
value.should == added_facet_params[key]
end
end
end
describe "remove_facet_params" do
end
describe "facet_field_in_params?" do
it "should check if the facet field is selected in the user params" do
helper.stub(:params => { :f => { "some-field" => ["x"]}})
expect(helper.facet_field_in_params?("some-field")).to be_true
expect(helper.facet_field_in_params?("other-field")).to_not be_true
end
end
describe "facet_in_params?" do
end
describe "render_facet_value" do
it "should use facet_display_value" do
helper.stub(:facet_configuration_for_field).with('simple_field').and_return(double(:query => nil, :date => nil, :helper_method => nil, :single => false))
helper.should_receive(:facet_display_value).and_return('Z')
helper.should_receive(:add_facet_params_and_redirect).and_return('link')
expected = Nokogiri::HTML "Z 10"
rendered = Nokogiri::HTML helper.render_facet_value('simple_field', double(:value => 'A', :hits => 10))
rendered.should be_equivalent_to(expected).respecting_element_order
end
it "should suppress the link" do
helper.stub(:facet_configuration_for_field).with('simple_field').and_return(double(:query => nil, :date => nil, :helper_method => nil, :single => false))
helper.should_receive(:facet_display_value).and_return('Z')
helper.should_receive(:add_facet_params_and_redirect).and_return('link')
helper.render_facet_value('simple_field', double(:value => 'A', :hits => 10), :suppress_link => true).should == "Z 10"
end
end
describe "#facet_display_value" do
it "should just be the facet value for an ordinary facet" do
helper.stub(:facet_configuration_for_field).with('simple_field').and_return(double(:query => nil, :date => nil, :helper_method => nil))
helper.facet_display_value('simple_field', 'asdf').should == 'asdf'
end
it "should allow you to pass in a :helper_method argument to the configuration" do
helper.stub(:facet_configuration_for_field).with('helper_field').and_return(double(:query => nil, :date => nil, :helper_method => :my_facet_value_renderer))
helper.should_receive(:my_facet_value_renderer).with('qwerty').and_return('abc')
helper.facet_display_value('helper_field', 'qwerty').should == 'abc'
end
it "should extract the configuration label for a query facet" do
helper.stub(:facet_configuration_for_field).with('query_facet').and_return(double(:query => { 'query_key' => { :label => 'XYZ'}}, :date => nil, :helper_method => nil))
helper.facet_display_value('query_facet', 'query_key').should == 'XYZ'
end
it "should localize the label for date-type facets" do
helper.stub(:facet_configuration_for_field).with('date_facet').and_return(double('date' => true, :query => nil, :helper_method => nil))
helper.facet_display_value('date_facet', '2012-01-01').should == 'Sun, 01 Jan 2012 00:00:00 +0000'
end
it "should localize the label for date-type facets with the supplied localization options" do
helper.stub(:facet_configuration_for_field).with('date_facet').and_return(double('date' => { :format => :short }, :query => nil, :helper_method => nil))
helper.facet_display_value('date_facet', '2012-01-01').should == '01 Jan 00:00'
end
end
end