# frozen_string_literal: true require 'equivalent-xml' describe FacetsHelper do let(:blacklight_config) { Blacklight::Configuration.new } before(:each) do allow(helper).to receive(:blacklight_config).and_return blacklight_config end describe "has_facet_values?" do let(:empty) { double(:items => [], :name => 'empty') } it "is true if there are any facets to display" do a = double(:items => [1, 2], :name => 'a') b = double(:items => ['b', 'c'], :name => 'b') fields = [a, b, empty] expect(helper.has_facet_values?(fields)).to be true end it "is false if all facets are empty" do expect(helper.has_facet_values?([empty])).to be false end describe "different config" do let(:blacklight_config) { Blacklight::Configuration.new { |config| config.add_facet_field 'basic_field', :if => false } } it "is false if no facets are displayable" do a = double(:items => [1, 2], :name => 'basic_field') expect(helper.has_facet_values?([a])).to be false end end end describe "should_render_facet?" do let(:blacklight_config) do 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_custom_check config.add_facet_field 'helper_with_an_arg_show', :show => :my_custom_check_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 end it "renders facets with items" do a = double(:items => [1, 2], :name => 'basic_field') expect(helper.should_render_facet?(a)).to be true end it "does not render facets without items" do empty = double(:items => [], :name => 'basic_field') expect(helper.should_render_facet?(empty)).to be false end it "does not render facets where show is set to false" do a = double(:items => [1, 2], :name => 'no_show') expect(helper.should_render_facet?(a)).to be false end it "calls a helper to determine if it should render a field" do allow(controller).to receive_messages(:my_custom_check => true) a = double(:items => [1, 2], :name => 'helper_show') expect(helper.should_render_facet?(a)).to be true end it "calls a helper to determine if it should render a field" do a = double(:items => [1, 2], :name => 'helper_with_an_arg_show') allow(controller).to receive(:my_custom_check_with_an_arg).with(blacklight_config.facet_fields['helper_with_an_arg_show'], a).and_return(true) expect(helper.should_render_facet?(a)).to be true end it "evaluates 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 "should_collapse_facet?" do let(:blacklight_config) do Blacklight::Configuration.new do |config| config.add_facet_field 'basic_field' config.add_facet_field 'no_collapse', collapse: false end end it "is collapsed by default" do expect(helper.should_collapse_facet?(blacklight_config.facet_fields['basic_field'])).to be true end it "does not be collapsed if the configuration says so" do expect(helper.should_collapse_facet?(blacklight_config.facet_fields['no_collapse'])).to be false end it "does not be collapsed if it is in the params" do params[:f] = ActiveSupport::HashWithIndifferentAccess.new(basic_field: [1], no_collapse: [2]) expect(helper.should_collapse_facet?(blacklight_config.facet_fields['basic_field'])).to be false expect(helper.should_collapse_facet?(blacklight_config.facet_fields['no_collapse'])).to be false end end describe "facet_by_field_name" do it "retrieves the facet from the response given a string" do facet_config = double(query: nil, field: 'b', key: 'a') facet_field = double() allow(helper).to receive(:facet_configuration_for_field).with('b').and_return(facet_config) @response = instance_double(Blacklight::Solr::Response, aggregations: { 'b' => facet_field }) expect(helper.facet_by_field_name('b')).to eq facet_field end end describe "render_facet_partials" do let(:a) { double(:items => [1, 2]) } let(:b) { double(:items => ['b', 'c']) } it "tries to render all provided facets" do empty = double(:items => []) fields = [a, b, empty] expect(helper).to receive(:render_facet_limit).with(a, {}) expect(helper).to receive(:render_facet_limit).with(b, {}) expect(helper).to receive(:render_facet_limit).with(empty, {}) helper.render_facet_partials fields end it "defaults to the configured facets" do expect(helper).to receive(:facet_field_names) { [a, b] } expect(helper).to receive(:render_facet_limit).with(a, {}) expect(helper).to receive(:render_facet_limit).with(b, {}) helper.render_facet_partials end end describe "render_facet_limit" do let(:blacklight_config) do 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 end let(:mock_custom_facet) { double(:name => 'my_facet_field_with_custom_partial', :items => [1, 2, 3]) } it "sets basic local variables" do mock_facet = double(:name => 'basic_field', :items => [1, 2, 3]) expect(helper).to receive(:render).with(hash_including(:partial => 'facet_limit', :locals => { :solr_field => 'basic_field', :field_name => 'basic_field', :facet_field => helper.blacklight_config.facet_fields['basic_field'], :display_facet => mock_facet } )) helper.render_facet_limit(mock_facet) end it "renders a facet _not_ declared in the configuration" do mock_facet = double(:name => 'asdf', :items => [1, 2, 3]) expect(helper).to receive(:render).with(hash_including(:partial => 'facet_limit')) helper.render_facet_limit(mock_facet) end it "gets the partial name from the configuration" do expect(helper).to receive(:render).with(hash_including(:partial => 'custom_facet_partial')) helper.render_facet_limit(mock_custom_facet) end it "uses a partial layout for rendering the facet frame" do expect(helper).to receive(:render).with(hash_including(:layout => 'facet_layout')) helper.render_facet_limit(mock_custom_facet) end it "allows the caller to opt-out of facet layouts" do expect(helper).to receive(:render).with(hash_including(:layout => nil)) helper.render_facet_limit(mock_custom_facet, :layout => nil) end it "renders the facet_pivot partial for pivot facets" do mock_facet = double(:name => 'pivot_facet_field', :items => [1, 2, 3]) expect(helper).to receive(:render).with(hash_including(:partial => 'facet_pivot')) helper.render_facet_limit(mock_facet) end it "lets you override the rendered partial for pivot facets" do mock_facet = double(:name => 'my_pivot_facet_field_with_custom_partial', :items => [1, 2, 3]) expect(helper).to receive(:render).with(hash_including(:partial => 'custom_facet_partial')) helper.render_facet_limit(mock_facet) end end describe "render_facet_limit_list" do let(:f1) { Blacklight::Solr::Response::Facets::FacetItem.new(hits: '792', value: 'Book') } let(:f2) { Blacklight::Solr::Response::Facets::FacetItem.new(hits: '65', value: 'Musical Score') } let(:paginator) { Blacklight::Solr::FacetPaginator.new([f1, f2], limit: 10) } subject { helper.render_facet_limit_list(paginator, 'type_solr_field') } before do allow(helper).to receive(:search_action_path) do |*args| search_catalog_path *args end end it "draws a list of elements" do expect(subject).to have_selector 'li', count: 2 expect(subject).to have_selector 'li:first-child a.facet_select', text: 'Book' expect(subject).to have_selector 'li:nth-child(2) a.facet_select', text: 'Musical Score' end context "when one of the facet items is rendered as nil" do # An app may override render_facet_item to filter out some undesired facet items by returning nil. before { allow(helper).to receive(:render_facet_item).and_return('<a class="facet_select">Book</a>'.html_safe, nil) } it "draws a list of elements" do expect(subject).to have_selector 'li', count: 1 expect(subject).to have_selector 'li:first-child a.facet_select', text: 'Book' end end end describe "facet_field_in_params?" do it "checks if the facet field is selected in the user params" do allow(helper).to receive_messages(:params => { :f => { "some-field" => ["x"]}}) expect(helper.facet_field_in_params?("some-field")).to be_truthy expect(helper.facet_field_in_params?("other-field")).to_not be true end end describe "facet_params" do it "extracts the facet parameters for a field" do allow(helper).to receive_messages(params: { f: { "some-field" => ["x"] }}) expect(helper.facet_params("some-field")).to match_array ["x"] end it "uses the blacklight key to extract the right fields" do blacklight_config.add_facet_field "some-key", field: "some-field" allow(helper).to receive_messages(params: { f: { "some-key" => ["x"] }}) expect(helper.facet_params("some-key")).to match_array ["x"] expect(helper.facet_params("some-field")).to match_array ["x"] end end describe "facet_field_in_params?" do it "checks if any value is selected for a given facet" do allow(helper).to receive_messages(facet_params: ["x"]) expect(helper.facet_field_in_params?("some-facet")).to eq true end it "is false if no value for facet is selected" do allow(helper).to receive_messages(facet_params: nil) expect(helper.facet_field_in_params?("some-facet")).to eq false end end describe "facet_in_params?" do it "checks if a particular value is set in the facet params" do allow(helper).to receive_messages(facet_params: ["x"]) expect(helper.facet_in_params?("some-facet", "x")).to eq true expect(helper.facet_in_params?("some-facet", "y")).to eq false end it "is false if no value for facet is selected" do allow(helper).to receive_messages(facet_params: nil) expect(helper.facet_in_params?("some-facet", "x")).to eq false end end describe "render_facet_value" do let(:item) { double(:value => 'A', :hits => 10) } let(:search_state) { double(add_facet_params_and_redirect: { controller: 'catalog' }) } before do allow(helper).to receive(:facet_configuration_for_field).with('simple_field').and_return(double(:query => nil, :date => nil, :helper_method => nil, :single => false, :url_method => nil)) allow(helper).to receive(:facet_display_value).and_return('Z') allow(helper).to receive(:search_state).and_return(search_state) allow(helper).to receive(:search_action_path) do |*args| search_catalog_path *args end end describe "simple case" do let(:expected_html) { '<span class="facet-label"><a class="facet_select" href="/catalog">Z</a></span><span class="facet-count">10</span>' } it "uses facet_display_value" do result = helper.render_facet_value('simple_field', item) expect(result).to be_equivalent_to(expected_html).respecting_element_order end end describe "when :url_method is set" do let(:expected_html) { '<span class="facet-label"><a class="facet_select" href="/blabla">Z</a></span><span class="facet-count">10</span>' } it "uses that method" do allow(helper).to receive(:facet_configuration_for_field).with('simple_field').and_return(double(:query => nil, :date => nil, :helper_method => nil, :single => false, :url_method => :test_method)) allow(helper).to receive(:test_method).with('simple_field', item).and_return('/blabla') result = helper.render_facet_value('simple_field', item) expect(result).to be_equivalent_to(expected_html).respecting_element_order end end describe "when :suppress_link is set" do let(:expected_html) { '<span class="facet-label">Z</span><span class="facet-count">10</span>' } it "suppresses the link" do result = helper.render_facet_value('simple_field', item, :suppress_link => true) expect(result).to be_equivalent_to(expected_html).respecting_element_order end end end describe "#facet_display_value" do it "justs be the facet value for an ordinary facet" do allow(helper).to receive(:facet_configuration_for_field).with('simple_field').and_return(double(:query => nil, :date => nil, :helper_method => nil, :url_method => nil)) expect(helper.facet_display_value('simple_field', 'asdf')).to eq 'asdf' end it "allows you to pass in a :helper_method argument to the configuration" do allow(helper).to receive(:facet_configuration_for_field).with('helper_field').and_return(double(:query => nil, :date => nil, :url_method => nil, :helper_method => :my_facet_value_renderer)) allow(helper).to receive(:my_facet_value_renderer).with('qwerty').and_return('abc') expect(helper.facet_display_value('helper_field', 'qwerty')).to eq 'abc' end it "extracts the configuration label for a query facet" do allow(helper).to receive(:facet_configuration_for_field).with('query_facet').and_return(double(:query => { 'query_key' => { :label => 'XYZ'}}, :date => nil, :helper_method => nil, :url_method => nil)) expect(helper.facet_display_value('query_facet', 'query_key')).to eq 'XYZ' end it "localizes the label for date-type facets" do allow(helper).to receive(:facet_configuration_for_field).with('date_facet').and_return(double('date' => true, :query => nil, :helper_method => nil, :url_method => nil)) expect(helper.facet_display_value('date_facet', '2012-01-01')).to eq 'Sun, 01 Jan 2012 00:00:00 +0000' end it "localizes the label for date-type facets with the supplied localization options" do allow(helper).to receive(:facet_configuration_for_field).with('date_facet').and_return(double('date' => { :format => :short }, :query => nil, :helper_method => nil, :url_method => nil)) expect(helper.facet_display_value('date_facet', '2012-01-01')).to eq '01 Jan 00:00' end end describe "#facet_field_id" do it "is the parameterized version of the facet field" do expect(helper.facet_field_id double(key: 'some field')).to eq "facet-some-field" end end end