From 12fed9ac5991f43103b35c747f8fcd277c04ed97 Mon Sep 17 00:00:00 2001 From: Chris Beer Date: Sun, 2 Feb 2014 09:06:44 -0800 Subject: [PATCH] Move url, path, and params helpers into Blacklight::UrlHelperBehavior --- .../blacklight/blacklight_helper_behavior.rb | 129 +----- .../blacklight/facets_helper_behavior.rb | 75 ---- app/helpers/blacklight/url_helper_behavior.rb | 201 +++++++++ app/helpers/blacklight_url_helper.rb | 3 + spec/helpers/blacklight_helper_spec.rb | 400 ------------------ spec/helpers/facets_helper_spec.rb | 127 ------ spec/helpers/url_helper_spec.rb | 360 ++++++++++++++++ 7 files changed, 565 insertions(+), 730 deletions(-) create mode 100644 app/helpers/blacklight/url_helper_behavior.rb create mode 100644 app/helpers/blacklight_url_helper.rb create mode 100644 spec/helpers/url_helper_spec.rb diff --git a/app/helpers/blacklight/blacklight_helper_behavior.rb b/app/helpers/blacklight/blacklight_helper_behavior.rb index 9ab7195174..2907e7e840 100644 --- a/app/helpers/blacklight/blacklight_helper_behavior.rb +++ b/app/helpers/blacklight/blacklight_helper_behavior.rb @@ -4,22 +4,17 @@ # Methods added to this helper will be available to all templates in the hosting application # module Blacklight::BlacklightHelperBehavior + include BlacklightUrlHelper include HashAsHiddenFieldsHelper include RenderConstraintsHelper include FacetsHelper - def application_name return Rails.application.config.application_name if Rails.application.config.respond_to? :application_name t('blacklight.application_name') end - # Provide the full, absolute url for an image - def asset_url(*args) - "#{request.protocol}#{request.host_with_port}#{asset_path(*args)}" - end - # Create links from a documents dynamically # provided export formats. Currently not used by standard BL layouts, # but available for your custom layouts to provide link rel alternates. @@ -442,33 +437,6 @@ def document_partial_path_templates end - # Search History and Saved Searches display - def link_to_previous_search(params) - link_to(render_search_to_s(params), catalog_index_path(params)) - end - - # - # link based helpers -> - # - - # create link to query (e.g. spelling suggestion) - def link_to_query(query) - p = params.except(:page, :action) - p[:q]=query - link_url = catalog_index_path(p) - link_to(query, link_url) - end - - ## - # Get the path to the search action with any parameters (e.g. view type) - # that should be persisted across search sessions. - def start_over_path query_params = params - h = { } - current_index_view_type = document_index_view_type(query_params) - h[:view] = current_index_view_type unless current_index_view_type == default_document_index_view_type - - search_action_url(h) - end def render_document_index_label doc, opts label = nil @@ -479,101 +447,6 @@ def render_document_index_label doc, opts render_field_value label end - # link_to_document(doc, :label=>'VIEW', :counter => 3) - # Use the catalog_path RESTful route to create a link to the show page for a specific item. - # catalog_path accepts a HashWithIndifferentAccess object. The solr query params are stored in the session, - # so we only need the +counter+ param here. We also need to know if we are viewing to document as part of search results. - def link_to_document(doc, opts={:label=>nil, :counter => nil}) - opts[:label] ||= document_show_link_field(doc) - label = render_document_index_label doc, opts - link_to label, doc, search_session_params(opts[:counter]).merge(opts.reject { |k,v| [:label, :counter].include? k }) - end - - def search_session_params counter - { :'data-counter' => counter, :'data-search_id' => current_search_session.try(:id) } - end - - # Create a link back to the index screen, keeping the user's facet, query and paging choices intact by using session. - # @example - # link_back_to_catalog(label: 'Back to Search') - # link_back_to_catalog(label: 'Back to Search', route_set: my_engine) - def link_back_to_catalog(opts={:label=>nil}) - scope = opts.delete(:route_set) || self - query_params = current_search_session.try(:query_params) || {} - link_url = scope.url_for(query_params) - label = opts.delete(:label) - - if link_url =~ /bookmarks/ - label ||= t('blacklight.back_to_bookmarks') - end - - label ||= t('blacklight.back_to_search') - - link_to label, link_url, opts - end - - # @overload params_for_search(source_params, params_to_merge) - # Merge the source params with the params_to_merge hash - # @param [Hash] Hash - # @param [Hash] Hash to merge into above - # @overload params_for_search(params_to_merge) - # Merge the current search parameters with the - # parameters provided. - # @param [Hash] Hash to merge into the parameters - # @overload params_for_search - # Returns the current search parameters after being sanitized by #sanitize_search_params - # @yield [params] The merged parameters hash before being sanitized - def params_for_search(*args, &block) - - source_params, params_to_merge = case args.length - when 0 - [params, {}] - when 1 - [params, args.first] - when 2 - [args.first, args.last] - else - raise ArgumentError.new "wrong number of arguments (#{args.length} for 0..2)" - end - - # params hash we'll return - my_params = source_params.dup.merge(params_to_merge.dup) - - if block_given? - yield my_params - end - - if my_params[:page] and (my_params[:per_page] != source_params[:per_page] or my_params[:sort] != source_params[:sort] ) - my_params[:page] = 1 - end - - sanitize_search_params(my_params) - end - - ## - # Sanitize the search parameters by removing unnecessary parameters - # from the provided parameters - # @param [Hash] Hash of parameters - def sanitize_search_params source_params - - my_params = source_params.reject { |k,v| v.nil? } - - my_params.except(:action, :controller, :id, :commit, :utf8) - - end - - def link_to_previous_document(previous_document) - link_to_unless previous_document.nil?, raw(t('views.pagination.previous')), previous_document, search_session_params(search_session[:counter].to_i - 1).merge(:class => "previous", :rel => 'prev') do - content_tag :span, raw(t('views.pagination.previous')), :class => 'previous' - end - end - - def link_to_next_document(next_document) - link_to_unless next_document.nil?, raw(t('views.pagination.next')), next_document, search_session_params(search_session[:counter].to_i + 1).merge(:class => "next", :rel => 'next') do - content_tag :span, raw(t('views.pagination.next')), :class => 'next' - end - end - # Use case, you want to render an html partial from an XML (say, atom) # template. Rails API kind of lets us down, we need to hack Rails internals # a bit. code taken from: diff --git a/app/helpers/blacklight/facets_helper_behavior.rb b/app/helpers/blacklight/facets_helper_behavior.rb index cd2103ef0f..8601e9273d 100644 --- a/app/helpers/blacklight/facets_helper_behavior.rb +++ b/app/helpers/blacklight/facets_helper_behavior.rb @@ -117,81 +117,6 @@ def render_facet_count(num, options = {}) content_tag("span", t('blacklight.search.facets.count', :number => num), :class => classes) end - # adds the value and/or field to params[:f] - # Does NOT remove request keys and otherwise ensure that the hash - # is suitable for a redirect. See - # add_facet_params_and_redirect - def add_facet_params(field, item, source_params = params) - - if item.respond_to? :field - field = item.field - end - - facet_config = facet_configuration_for_field(field) - - value = facet_value_for_facet_item(item) - - p = source_params.dup - p[:f] = (p[:f] || {}).dup # the command above is not deep in rails3, !@#$!@#$ - p[:f][field] = (p[:f][field] || []).dup - - if facet_config.single and not p[:f][field].empty? - p[:f][field] = [] - end - - p[:f][field].push(value) - - if item and item.respond_to?(:fq) and item.fq - item.fq.each do |f,v| - p = add_facet_params(f, v, p) - end - end - - p - end - - # Used in catalog/facet action, facets.rb view, for a click - # on a facet value. Add on the facet params to existing - # search constraints. Remove any paginator-specific request - # params, or other request params that should be removed - # for a 'fresh' display. - # Change the action to 'index' to send them back to - # catalog/index with their new facet choice. - def add_facet_params_and_redirect(field, item) - new_params = add_facet_params(field, item) - new_params.except! :page, :id - - # Delete any request params from facet-specific action, needed - # to redir to index action properly. - new_params.except! *Blacklight::Solr::FacetPaginator.request_keys.values - - # Force action to be index. - new_params[:action] = "index" - new_params - end - # copies the current params (or whatever is passed in as the 3rd arg) - # removes the field value from params[:f] - # removes the field if there are no more values in params[:f][field] - # removes additional params (page, id, etc..) - def remove_facet_params(field, item, source_params=params) - if item.respond_to? :field - field = item.field - end - - value = facet_value_for_facet_item(item) - - p = source_params.dup - # need to dup the facet values too, - # if the values aren't dup'd, then the values - # from the session will get remove in the show view... - p[:f] = (p[:f] || {}).dup - p[:f][field] = (p[:f][field] || []).dup - p.except! :page, :id, :counter, :commit - p[:f][field] = p[:f][field] - [value] - p[:f].delete(field) if p[:f][field].size == 0 - p - end - def facet_field_in_params? field params[:f] and params[:f][field] end diff --git a/app/helpers/blacklight/url_helper_behavior.rb b/app/helpers/blacklight/url_helper_behavior.rb new file mode 100644 index 0000000000..7d6b5eb6f2 --- /dev/null +++ b/app/helpers/blacklight/url_helper_behavior.rb @@ -0,0 +1,201 @@ +module Blacklight::UrlHelperBehavior + + # link_to_document(doc, :label=>'VIEW', :counter => 3) + # Use the catalog_path RESTful route to create a link to the show page for a specific item. + # catalog_path accepts a HashWithIndifferentAccess object. The solr query params are stored in the session, + # so we only need the +counter+ param here. We also need to know if we are viewing to document as part of search results. + def link_to_document(doc, opts={:label=>nil, :counter => nil}) + opts[:label] ||= document_show_link_field(doc) + label = render_document_index_label doc, opts + link_to label, doc, search_session_params(opts[:counter]).merge(opts.reject { |k,v| [:label, :counter].include? k }) + end + + def link_to_previous_document(previous_document) + link_to_unless previous_document.nil?, raw(t('views.pagination.previous')), previous_document, search_session_params(search_session[:counter].to_i - 1).merge(:class => "previous", :rel => 'prev') do + content_tag :span, raw(t('views.pagination.previous')), :class => 'previous' + end + end + + def link_to_next_document(next_document) + link_to_unless next_document.nil?, raw(t('views.pagination.next')), next_document, search_session_params(search_session[:counter].to_i + 1).merge(:class => "next", :rel => 'next') do + content_tag :span, raw(t('views.pagination.next')), :class => 'next' + end + end + + def search_session_params counter + { :'data-counter' => counter, :'data-search_id' => current_search_session.try(:id) } + end + + # + # link based helpers -> + # + + # create link to query (e.g. spelling suggestion) + def link_to_query(query) + p = params.except(:page, :action) + p[:q]=query + link_url = catalog_index_path(p) + link_to(query, link_url) + end + + ## + # Get the path to the search action with any parameters (e.g. view type) + # that should be persisted across search sessions. + def start_over_path query_params = params + h = { } + current_index_view_type = document_index_view_type(query_params) + h[:view] = current_index_view_type unless current_index_view_type == default_document_index_view_type + + search_action_url(h) + end + + # Create a link back to the index screen, keeping the user's facet, query and paging choices intact by using session. + # @example + # link_back_to_catalog(label: 'Back to Search') + # link_back_to_catalog(label: 'Back to Search', route_set: my_engine) + def link_back_to_catalog(opts={:label=>nil}) + scope = opts.delete(:route_set) || self + query_params = current_search_session.try(:query_params) || {} + link_url = scope.url_for(query_params) + label = opts.delete(:label) + + if link_url =~ /bookmarks/ + label ||= t('blacklight.back_to_bookmarks') + end + + label ||= t('blacklight.back_to_search') + + link_to label, link_url, opts + end + + # Search History and Saved Searches display + def link_to_previous_search(params) + link_to(render_search_to_s(params), catalog_index_path(params)) + end + + # @overload params_for_search(source_params, params_to_merge) + # Merge the source params with the params_to_merge hash + # @param [Hash] Hash + # @param [Hash] Hash to merge into above + # @overload params_for_search(params_to_merge) + # Merge the current search parameters with the + # parameters provided. + # @param [Hash] Hash to merge into the parameters + # @overload params_for_search + # Returns the current search parameters after being sanitized by #sanitize_search_params + # @yield [params] The merged parameters hash before being sanitized + def params_for_search(*args, &block) + + source_params, params_to_merge = case args.length + when 0 + [params, {}] + when 1 + [params, args.first] + when 2 + [args.first, args.last] + else + raise ArgumentError.new "wrong number of arguments (#{args.length} for 0..2)" + end + + # params hash we'll return + my_params = source_params.dup.merge(params_to_merge.dup) + + if block_given? + yield my_params + end + + if my_params[:page] and (my_params[:per_page] != source_params[:per_page] or my_params[:sort] != source_params[:sort] ) + my_params[:page] = 1 + end + + sanitize_search_params(my_params) + end + + ## + # Sanitize the search parameters by removing unnecessary parameters + # from the provided parameters + # @param [Hash] Hash of parameters + def sanitize_search_params source_params + + my_params = source_params.reject { |k,v| v.nil? } + + my_params.except(:action, :controller, :id, :commit, :utf8) + + end + + # adds the value and/or field to params[:f] + # Does NOT remove request keys and otherwise ensure that the hash + # is suitable for a redirect. See + # add_facet_params_and_redirect + def add_facet_params(field, item, source_params = params) + + if item.respond_to? :field + field = item.field + end + + facet_config = facet_configuration_for_field(field) + + value = facet_value_for_facet_item(item) + + p = source_params.dup + p[:f] = (p[:f] || {}).dup # the command above is not deep in rails3, !@#$!@#$ + p[:f][field] = (p[:f][field] || []).dup + + if facet_config.single and not p[:f][field].empty? + p[:f][field] = [] + end + + p[:f][field].push(value) + + if item and item.respond_to?(:fq) and item.fq + item.fq.each do |f,v| + p = add_facet_params(f, v, p) + end + end + + p + end + + # Used in catalog/facet action, facets.rb view, for a click + # on a facet value. Add on the facet params to existing + # search constraints. Remove any paginator-specific request + # params, or other request params that should be removed + # for a 'fresh' display. + # Change the action to 'index' to send them back to + # catalog/index with their new facet choice. + def add_facet_params_and_redirect(field, item) + new_params = add_facet_params(field, item) + new_params.except! :page, :id + + # Delete any request params from facet-specific action, needed + # to redir to index action properly. + new_params.except! *Blacklight::Solr::FacetPaginator.request_keys.values + + # Force action to be index. + new_params[:action] = "index" + new_params + end + # copies the current params (or whatever is passed in as the 3rd arg) + # removes the field value from params[:f] + # removes the field if there are no more values in params[:f][field] + # removes additional params (page, id, etc..) + def remove_facet_params(field, item, source_params=params) + if item.respond_to? :field + field = item.field + end + + value = facet_value_for_facet_item(item) + + p = source_params.dup + # need to dup the facet values too, + # if the values aren't dup'd, then the values + # from the session will get remove in the show view... + p[:f] = (p[:f] || {}).dup + p[:f][field] = (p[:f][field] || []).dup + p.except! :page, :id, :counter, :commit + p[:f][field] = p[:f][field] - [value] + p[:f].delete(field) if p[:f][field].size == 0 + p + end + +end \ No newline at end of file diff --git a/app/helpers/blacklight_url_helper.rb b/app/helpers/blacklight_url_helper.rb new file mode 100644 index 0000000000..a5c1498d4f --- /dev/null +++ b/app/helpers/blacklight_url_helper.rb @@ -0,0 +1,3 @@ +module BlacklightUrlHelper + include Blacklight::UrlHelperBehavior +end \ No newline at end of file diff --git a/spec/helpers/blacklight_helper_spec.rb b/spec/helpers/blacklight_helper_spec.rb index 915a8f9fe1..c989dc3ed0 100644 --- a/spec/helpers/blacklight_helper_spec.rb +++ b/spec/helpers/blacklight_helper_spec.rb @@ -1,66 +1,5 @@ require 'spec_helper' -def exportable_record -" - 01828cjm a2200409 a 4500 - a4768316 - SIRSI - sd fungnnmmned - 020117p20011990xxuzz h d - - - Music for horn - [sound recording] / - Brahms, Beethoven, von Krufft. - - - - [United States] : - Harmonia Mundi USA, - p2001. - - - - Greer, Lowell. - - - - Lubin, Steven. - - - - Chase, Stephanie, - 1957- - - - - Brahms, Johannes, - 1833-1897. - Trios, - piano, violin, horn, - op. 40, - E? major. - - - - Beethoven, Ludwig van, - 1770-1827. - Sonatas, - horn, piano, - op. 17, - F major. - - - - Krufft, Nikolaus von, - 1779-1818. - Sonata, - horn, piano, - F major. - -" -end - describe BlacklightHelper do include ERB::Util include BlacklightHelper @@ -93,334 +32,6 @@ def current_search_session end end - describe "link_back_to_catalog" do - let(:query_params) {{:q => "query", :f => "facets", :per_page => "10", :page => "2", :controller=>'catalog'}} - let(:bookmarks_query_params) {{ :page => "2", :controller=>'bookmarks'}} - - it "should build a link tag to catalog using session[:search] for query params" do - helper.stub(:current_search_session).and_return double(:query_params => query_params) - tag = helper.link_back_to_catalog - expect(tag).to match /q=query/ - expect(tag).to match /f=facets/ - expect(tag).to match /per_page=10/ - expect(tag).to match /page=2/ - end - - it "should build a link tag to bookmarks using session[:search] for query params" do - helper.stub(:current_search_session).and_return double(:query_params => bookmarks_query_params) - tag = helper.link_back_to_catalog - expect(tag).to match /Back to Bookmarks/ - expect(tag).to match /\/bookmarks/ - expect(tag).to match /page=2/ - end - - describe "when an alternate scope is passed in" do - let(:my_engine) { double("Engine") } - - it "should call url_for on the engine scope" do - helper.stub(:current_search_session).and_return double(:query_params => query_params) - expect(my_engine).to receive(:url_for).and_return(url_for(query_params)) - tag = helper.link_back_to_catalog(route_set: my_engine) - expect(tag).to match /Back to Search/ - expect(tag).to match /q=query/ - expect(tag).to match /f=facets/ - expect(tag).to match /per_page=10/ - expect(tag).to match /page=2/ - end - end - end - - describe "link_to_query" do - it "should build a link tag to catalog using query string (no other params)" do - query = "brilliant" - self.should_receive(:params).and_return({}) - tag = link_to_query(query) - expect(tag).to match /q=#{query}/ - expect(tag).to match />#{query}<\/a>/ - end - it "should build a link tag to catalog using query string and other existing params" do - query = "wonderful" - self.should_receive(:params).and_return({:qt => "title_search", :per_page => "50"}) - tag = link_to_query(query) - expect(tag).to match /qt=title_search/ - expect(tag).to match /per_page=50/ - end - it "should ignore existing :page param" do - query = "yes" - self.should_receive(:params).and_return({:page => "2", :qt => "author_search"}) - tag = link_to_query(query) - expect(tag).to match /qt=author_search/ - expect(tag).to_not match /page/ - end - it "should be html_safe" do - query = "brilliant" - self.should_receive(:params).and_return({:page => "2", :qt => "author_search"}) - tag = link_to_query(query) - expect(tag).to be_html_safe - end - end - - describe "sanitize_search_params" do - it "should strip nil values" do - result = sanitize_search_params(:a => nil, :b => 1) - expect(result).to_not have_key(:a) - expect(result[:b]).to eq 1 - end - - it "should remove blacklisted keys" do - result = sanitize_search_params(:action => true, :controller => true, :id => true, :commit => true, :utf8 => true) - expect(result).to be_empty - end - end - - describe "params_for_search" do - def params - { 'default' => 'params'} - end - - it "should default to using the controller's params" do - result = params_for_search - expect(result).to eq params - expect(params.object_id).to_not eq result.object_id - end - - it "should let you pass in params to merge into the controller's params" do - source_params = { :q => 'query'} - result = params_for_search( source_params ) - expect(result).to include(:q => 'query', 'default' => 'params') - end - - it "should not return blacklisted elements" do - source_params = { :action => 'action', :controller => 'controller', :id => "id", :commit => 'commit'} - result = params_for_search(source_params) - expect(result.keys).to_not include(:action, :controller, :commit, :id) - end - - it "should adjust the current page if the per_page changes" do - source_params = { :per_page => 20, :page => 5} - result = params_for_search(source_params, :per_page => 100) - expect(result[:page]).to eq 1 - end - - it "should not adjust the current page if the per_page is the same as it always was" do - source_params = { :per_page => 20, :page => 5} - result = params_for_search(source_params, :per_page => 20) - expect(result[:page]).to eq 5 - end - - it "should adjust the current page if the sort changes" do - source_params = { :sort => 'field_a', :page => 5} - result = params_for_search(source_params, :sort => 'field_b') - expect(result[:page]).to eq 1 - end - - it "should not adjust the current page if the sort is the same as it always was" do - source_params = { :sort => 'field_a', :page => 5} - result = params_for_search(source_params, :sort => 'field_a') - expect(result[:page]).to eq 5 - end - - describe "params_for_search with a block" do - it "should evalute the block and allow it to add or remove keys" do - result = params_for_search({:a => 1, :b => 2}, :c => 3) do |params| - params.except! :a, :b - params[:d] = 'd' - end - - result.keys.should_not include(:a, :b) - expect(result[:c]).to eq 3 - expect(result[:d]).to eq 'd' - end - - end - - end - - describe "render body class" do - it "should include a serialization of the current controller name" do - @controller = double("controller") - @controller.stub(:controller_name).and_return("123456") - @controller.stub(:action_name).and_return("abcdef") - - expect(render_body_class.split(' ')).to include('blacklight-123456') - end - - it "should include a serialization of the current action name" do - @controller = double("controller") - @controller.stub(:controller_name).and_return("123456") - @controller.stub(:action_name).and_return("abcdef") - - expect(render_body_class.split(' ')).to include('blacklight-123456-abcdef') - end - end - - describe "document_heading" do - - it "should consist of the show heading field when available" do - @document = SolrDocument.new('title_display' => "A Fake Document") - - expect(document_heading).to eq "A Fake Document" - end - - it "should fallback on the document id if no title is available" do - @document = SolrDocument.new(:id => '123456') - expect(document_heading).to eq '123456' - end - end - - describe "render_document_heading" do - it "should consist of #document_heading wrapped in a

" do - @document = SolrDocument.new('title_display' => "A Fake Document") - - expect(render_document_heading).to have_selector("h4", :text => "A Fake Document", :count => 1) - expect(render_document_heading).to be_html_safe - end - - it "should have a schema.org itemprop for name" do - @document = SolrDocument.new('title_display' => "A Fake Document") - - expect(render_document_heading).to have_selector("h4[@itemprop='name']", :text => "A Fake Document") - end - - it "should join the values if it is an array" do - @document = SolrDocument.new('title_display' => ["A Fake Document", 'Something Else']) - - expect(render_document_heading).to have_selector("h4", :text => "A Fake Document, Something Else", :count => 1) - expect(render_document_heading).to be_html_safe - end - end - - describe "document_show_html_title" do - it "should join the values if it is an array" do - @document = SolrDocument.new('title_display' => ["A Fake Document", 'Something Else']) - expect(document_show_html_title).to eq "A Fake Document, Something Else" - end - end - - describe "document_index_view_type" do - it "should default to 'list'" do - expect(document_index_view_type).to eq :list - end - - it "should pluck values out of params" do - blacklight_config.stub(:view) { { list: nil, asdf: nil} } - params[:view] = 'asdf' - expect(document_index_view_type).to eq :asdf - - params[:view] = 'not_in_list' - expect(document_index_view_type).to eq :list - end - - it "should pluck values from supplied params" do - blacklight_config.stub(:view) { { list: nil, asdf: nil} } - params[:view] = 'asdf' - expect(document_index_view_type(:view => 'list')).to eq :list - end - end - - describe "start_over_path" do - it 'should be the catalog path with the current view type' do - blacklight_config.stub(:view) { { list: nil, abc: nil} } - helper.stub(:blacklight_config => blacklight_config) - expect(helper.start_over_path(:view => 'abc')).to eq catalog_index_url(:view => 'abc') - end - - it 'should not include the current view type if it is the default' do - blacklight_config.stub(:view) { { list: nil, asdf: nil} } - helper.stub(:blacklight_config => blacklight_config) - expect(helper.start_over_path(:view => 'list')).to eq catalog_index_url - end - end - - describe "render_document_index" do - it "should render the document_list" do - @document_list = ['a', 'b'] - self.should_receive(:render).with(hash_including(:partial => 'document_gallery')) - render_document_index_with_view 'gallery', @document_list - end - - it "should fall back on more specific templates" do - ex = ActionView::MissingTemplate.new [], '', '', '','' - self.should_receive(:render).with(hash_including(:partial => 'document_gallery')).and_raise(ex) - self.should_receive(:render).with(hash_including(:partial => 'catalog/document_gallery')).and_raise(ex) - self.should_receive(:render).with(hash_including(:partial => 'catalog/document_list')) - render_document_index_with_view 'gallery', @document_list - end - end - - describe "document_partial_name" do - it "should default to 'default' when a format blank" do - expect(document_partial_name({})).to eq "default" - end - it "should handle normal formats correctly" do - expect(document_partial_name({"format" => "myformat"})).to eq "myformat" - end - it "should handle spaces correctly" do - expect(document_partial_name({"format" => "my format"})).to eq "my_format" - end - it "should handle capitalization correctly" do - expect(document_partial_name({"format" => "MyFormat"})).to eq "myformat" - end - it "should handle puncuation correctly" do - expect(document_partial_name({"format" => "My.Format"})).to eq "my_format" - end - it "should handle multi-valued fields correctly" do - expect(document_partial_name({"format" => ["My Format", "My OtherFormat"]})).to eq "my_format_my_otherformat" - end - it "should remove - characters because they will throw errors" do - expect(document_partial_name({"format" => "My-Format"})).to eq "my_format" - expect(document_partial_name({"format" => ["My-Format",["My Other-Format"]]})).to eq "my_format_my_other_format" - end - end - - describe "link_to_document" do - it "should consist of the document title wrapped in a " do - data = {'id'=>'123456','title_display'=>['654321'] } - @document = SolrDocument.new(data) - expect(link_to_document(@document, { :label => :title_display })).to have_selector("a", :text => '654321', :count => 1) - end - - it "should accept and return a string label" do - data = {'id'=>'123456','title_display'=>['654321'] } - @document = SolrDocument.new(data) - expect(link_to_document(@document, { :label => "title_display" })).to have_selector("a", :text => 'title_display', :count => 1) - end - - it "should accept and return a Proc" do - data = {'id'=>'123456','title_display'=>['654321'] } - @document = SolrDocument.new(data) - expect(link_to_document(@document, { :label => Proc.new { |doc, opts| doc.get(:id) + ": " + doc.get(:title_display) } })).to have_selector("a", :text => '123456: 654321', :count => 1) - end - it "should return id when label is missing" do - data = {'id'=>'123456'} - @document = SolrDocument.new(data) - expect(link_to_document(@document, { :label => :title_display })).to have_selector("a", :text => '123456', :count => 1) - end - - it "should be html safe" do - data = {'id'=>'123456'} - @document = SolrDocument.new(data) - expect(link_to_document(@document, { :label => :title_display })).to be_html_safe - end - - it "should convert the counter parameter into a data- attribute" do - data = {'id'=>'123456','title_display'=>['654321']} - @document = SolrDocument.new(data) - expect(link_to_document(@document, { :label => :title_display, :counter => 5 })).to match /data-counter="5"/ - end - - it "passes on the title attribute to the link_to_with_data method" do - @document = SolrDocument.new('id'=>'123456') - expect(link_to_document(@document,:label=>"Some crazy long label...",:title=>"Some crazy longer label")).to match(/title=\"Some crazy longer label\"/) - end - - it "doesn't add an erroneous title attribute if one isn't provided" do - @document = SolrDocument.new('id'=>'123456') - expect(link_to_document(@document,:label=>"Some crazy long label...")).to_not match(/title=/) - end - end - - describe "render_link_rel_alternates" do class MockDocumentAppHelper include Blacklight::Solr::Document @@ -605,7 +216,6 @@ def mock_document_app_helper_url *args end end - describe "render_document_show_field_value" do before do @config = Blacklight::Configuration.new.configure do |config| @@ -736,7 +346,6 @@ def mock_document_app_helper_url *args end end - describe "#should_render_show_field?" do it "should if the document has the field value" do doc = double() @@ -762,7 +371,6 @@ def mock_document_app_helper_url *args end end - describe "render_grouped_response?" do it "should check if the response ivar contains grouped data" do assign(:response, double("SolrResponse", :grouped? => true)) @@ -799,14 +407,6 @@ def mock_document_app_helper_url *args end end - describe "link_to_previous_search" do - it "should link to the given search parameters" do - params = {} - helper.should_receive(:render_search_to_s).with(params).and_return "link text" - expect(helper.link_to_previous_search({})).to eq helper.link_to("link text", catalog_index_path) - end - end - describe "should_show_spellcheck_suggestions?" do before :each do helper.stub spell_check_max: 5 diff --git a/spec/helpers/facets_helper_spec.rb b/spec/helpers/facets_helper_spec.rb index 018fc96a94..90d39c59b8 100644 --- a/spec/helpers/facets_helper_spec.rb +++ b/spec/helpers/facets_helper_spec.rb @@ -281,133 +281,6 @@ 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") - expect(result_params[:f]).to be_a_kind_of(Hash) - expect(result_params[:f]["facet_field"]).to be_a_kind_of(Array) - expect(result_params[:f]["facet_field"]).to eq ["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") - - expect(result_params[:f]).to be_a_kind_of(Hash) - - @params_existing_facets[:f].each_pair do |facet_field, value_list| - expect(result_params[:f][facet_field]).to be_a_kind_of(Array) - - if facet_field == 'facet_field_2' - expect(result_params[:f][facet_field]).to eq (@params_existing_facets[:f][facet_field] | ["new_facet_value"]) - else - expect(result_params[:f][facet_field]).to eq @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 - expect(result_params[key]).to eq 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') - - - expect(result_params[:f]['single_value_facet_field']).to have(1).item - expect(result_params[:f]['single_value_facet_field'].first).to eq '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)) - - expect(result_params[:f]['facet_field_1']).to 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)) - - expect(result_params[:f]['facet_field_1']).to be_blank - expect(result_params[:f]['facet_field_2']).to 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'})) - - expect(result_params[:f]['facet_field_1']).to include(123) - expect(result_params[:f]['facet_field_2']).to 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") - - expect(params[:action]).to eq "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| - expect(params.keys).to_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") - - expect(params.keys).to_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 - expect(value).to eq 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"]}}) diff --git a/spec/helpers/url_helper_spec.rb b/spec/helpers/url_helper_spec.rb new file mode 100644 index 0000000000..7c968bb6d0 --- /dev/null +++ b/spec/helpers/url_helper_spec.rb @@ -0,0 +1,360 @@ +require 'spec_helper' + +describe BlacklightHelper do + + let(:blacklight_config) do + @config ||= Blacklight::Configuration.new.configure do |config| + config.index.title_field = 'title_display' + config.index.display_type_field = 'format' + end + end + + before(:each) do + helper.stub(:search_action_url) do |*args| + catalog_index_url *args + end + + helper.stub(:blacklight_config).and_return blacklight_config + end + + def current_search_session + + end + + describe "link_back_to_catalog" do + let(:query_params) {{:q => "query", :f => "facets", :per_page => "10", :page => "2", :controller=>'catalog'}} + let(:bookmarks_query_params) {{ :page => "2", :controller=>'bookmarks'}} + + it "should build a link tag to catalog using session[:search] for query params" do + helper.stub(:current_search_session).and_return double(:query_params => query_params) + tag = helper.link_back_to_catalog + expect(tag).to match /q=query/ + expect(tag).to match /f=facets/ + expect(tag).to match /per_page=10/ + expect(tag).to match /page=2/ + end + + it "should build a link tag to bookmarks using session[:search] for query params" do + helper.stub(:current_search_session).and_return double(:query_params => bookmarks_query_params) + tag = helper.link_back_to_catalog + expect(tag).to match /Back to Bookmarks/ + expect(tag).to match /\/bookmarks/ + expect(tag).to match /page=2/ + end + + describe "when an alternate scope is passed in" do + let(:my_engine) { double("Engine") } + + it "should call url_for on the engine scope" do + helper.stub(:current_search_session).and_return double(:query_params => query_params) + expect(my_engine).to receive(:url_for).and_return(url_for(query_params)) + tag = helper.link_back_to_catalog(route_set: my_engine) + expect(tag).to match /Back to Search/ + expect(tag).to match /q=query/ + expect(tag).to match /f=facets/ + expect(tag).to match /per_page=10/ + expect(tag).to match /page=2/ + end + end + end + + describe "link_to_query" do + it "should build a link tag to catalog using query string (no other params)" do + query = "brilliant" + self.should_receive(:params).and_return({}) + tag = link_to_query(query) + expect(tag).to match /q=#{query}/ + expect(tag).to match />#{query}<\/a>/ + end + it "should build a link tag to catalog using query string and other existing params" do + query = "wonderful" + self.should_receive(:params).and_return({:qt => "title_search", :per_page => "50"}) + tag = link_to_query(query) + expect(tag).to match /qt=title_search/ + expect(tag).to match /per_page=50/ + end + it "should ignore existing :page param" do + query = "yes" + self.should_receive(:params).and_return({:page => "2", :qt => "author_search"}) + tag = link_to_query(query) + expect(tag).to match /qt=author_search/ + expect(tag).to_not match /page/ + end + it "should be html_safe" do + query = "brilliant" + self.should_receive(:params).and_return({:page => "2", :qt => "author_search"}) + tag = link_to_query(query) + expect(tag).to be_html_safe + end + end + + describe "sanitize_search_params" do + it "should strip nil values" do + result = sanitize_search_params(:a => nil, :b => 1) + expect(result).to_not have_key(:a) + expect(result[:b]).to eq 1 + end + + it "should remove blacklisted keys" do + result = sanitize_search_params(:action => true, :controller => true, :id => true, :commit => true, :utf8 => true) + expect(result).to be_empty + end + end + + describe "params_for_search" do + def params + { 'default' => 'params'} + end + + it "should default to using the controller's params" do + result = params_for_search + expect(result).to eq params + expect(params.object_id).to_not eq result.object_id + end + + it "should let you pass in params to merge into the controller's params" do + source_params = { :q => 'query'} + result = params_for_search( source_params ) + expect(result).to include(:q => 'query', 'default' => 'params') + end + + it "should not return blacklisted elements" do + source_params = { :action => 'action', :controller => 'controller', :id => "id", :commit => 'commit'} + result = params_for_search(source_params) + expect(result.keys).to_not include(:action, :controller, :commit, :id) + end + + it "should adjust the current page if the per_page changes" do + source_params = { :per_page => 20, :page => 5} + result = params_for_search(source_params, :per_page => 100) + expect(result[:page]).to eq 1 + end + + it "should not adjust the current page if the per_page is the same as it always was" do + source_params = { :per_page => 20, :page => 5} + result = params_for_search(source_params, :per_page => 20) + expect(result[:page]).to eq 5 + end + + it "should adjust the current page if the sort changes" do + source_params = { :sort => 'field_a', :page => 5} + result = params_for_search(source_params, :sort => 'field_b') + expect(result[:page]).to eq 1 + end + + it "should not adjust the current page if the sort is the same as it always was" do + source_params = { :sort => 'field_a', :page => 5} + result = params_for_search(source_params, :sort => 'field_a') + expect(result[:page]).to eq 5 + end + + describe "params_for_search with a block" do + it "should evalute the block and allow it to add or remove keys" do + result = params_for_search({:a => 1, :b => 2}, :c => 3) do |params| + params.except! :a, :b + params[:d] = 'd' + end + + result.keys.should_not include(:a, :b) + expect(result[:c]).to eq 3 + expect(result[:d]).to eq 'd' + end + + end + + end + + + describe "start_over_path" do + it 'should be the catalog path with the current view type' do + blacklight_config.stub(:view) { { list: nil, abc: nil} } + helper.stub(:blacklight_config => blacklight_config) + expect(helper.start_over_path(:view => 'abc')).to eq catalog_index_url(:view => 'abc') + end + + it 'should not include the current view type if it is the default' do + blacklight_config.stub(:view) { { list: nil, asdf: nil} } + helper.stub(:blacklight_config => blacklight_config) + expect(helper.start_over_path(:view => 'list')).to eq catalog_index_url + end + end + + describe "link_to_document" do + it "should consist of the document title wrapped in a " do + data = {'id'=>'123456','title_display'=>['654321'] } + @document = SolrDocument.new(data) + expect(link_to_document(@document, { :label => :title_display })).to have_selector("a", :text => '654321', :count => 1) + end + + it "should accept and return a string label" do + data = {'id'=>'123456','title_display'=>['654321'] } + @document = SolrDocument.new(data) + expect(link_to_document(@document, { :label => "title_display" })).to have_selector("a", :text => 'title_display', :count => 1) + end + + it "should accept and return a Proc" do + data = {'id'=>'123456','title_display'=>['654321'] } + @document = SolrDocument.new(data) + expect(link_to_document(@document, { :label => Proc.new { |doc, opts| doc.get(:id) + ": " + doc.get(:title_display) } })).to have_selector("a", :text => '123456: 654321', :count => 1) + end + + it "should return id when label is missing" do + data = {'id'=>'123456'} + @document = SolrDocument.new(data) + expect(link_to_document(@document, { :label => :title_display })).to have_selector("a", :text => '123456', :count => 1) + end + + it "should be html safe" do + data = {'id'=>'123456'} + @document = SolrDocument.new(data) + expect(link_to_document(@document, { :label => :title_display })).to be_html_safe + end + + it "should convert the counter parameter into a data- attribute" do + data = {'id'=>'123456','title_display'=>['654321']} + @document = SolrDocument.new(data) + expect(link_to_document(@document, { :label => :title_display, :counter => 5 })).to match /data-counter="5"/ + end + + it "passes on the title attribute to the link_to_with_data method" do + @document = SolrDocument.new('id'=>'123456') + expect(link_to_document(@document,:label=>"Some crazy long label...",:title=>"Some crazy longer label")).to match(/title=\"Some crazy longer label\"/) + end + + it "doesn't add an erroneous title attribute if one isn't provided" do + @document = SolrDocument.new('id'=>'123456') + expect(link_to_document(@document,:label=>"Some crazy long label...")).to_not match(/title=/) + end + end + + describe "link_to_previous_search" do + it "should link to the given search parameters" do + params = {} + helper.should_receive(:render_search_to_s).with(params).and_return "link text" + expect(helper.link_to_previous_search({})).to eq helper.link_to("link text", catalog_index_path) + 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") + expect(result_params[:f]).to be_a_kind_of(Hash) + expect(result_params[:f]["facet_field"]).to be_a_kind_of(Array) + expect(result_params[:f]["facet_field"]).to eq ["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") + + expect(result_params[:f]).to be_a_kind_of(Hash) + + @params_existing_facets[:f].each_pair do |facet_field, value_list| + expect(result_params[:f][facet_field]).to be_a_kind_of(Array) + + if facet_field == 'facet_field_2' + expect(result_params[:f][facet_field]).to eq (@params_existing_facets[:f][facet_field] | ["new_facet_value"]) + else + expect(result_params[:f][facet_field]).to eq @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 + expect(result_params[key]).to eq 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') + + + expect(result_params[:f]['single_value_facet_field']).to have(1).item + expect(result_params[:f]['single_value_facet_field'].first).to eq '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)) + + expect(result_params[:f]['facet_field_1']).to 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)) + + expect(result_params[:f]['facet_field_1']).to be_blank + expect(result_params[:f]['facet_field_2']).to 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'})) + + expect(result_params[:f]['facet_field_1']).to include(123) + expect(result_params[:f]['facet_field_2']).to 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") + + expect(params[:action]).to eq "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| + expect(params.keys).to_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") + + expect(params.keys).to_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 + expect(value).to eq added_facet_params[key] + end + end + end +end \ No newline at end of file