blacklight 6.4.2 → 6.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4fea8f394ca9653526946ca4e4bfcf50cc4f78ef
4
- data.tar.gz: 59305f0d30b38edbb7bc622cc48de9f5b6fd2004
3
+ metadata.gz: a6689bf20317b8fb6bee88d3064ce8528fbfe2ec
4
+ data.tar.gz: 2a83b261f71d22b9959014af71f0cc64736bd228
5
5
  SHA512:
6
- metadata.gz: df80eb8cbd5f23b4752194861992190bfec55ec8400eb5509f0143233c2533117b2a042a5552859997620d8879d71b6e70917bdf3cec4797efa96a4ce9ad10d6
7
- data.tar.gz: 39069bcc1804d9199a7e3d3dbecf01343643a910bbb327a9c12680e8701c2599a623c26514b8f36b4365717117cfd26c2ec66fdf469ac89507690dc3c3ed012e
6
+ metadata.gz: 0e83db02e3fa34951449c29fcc84ea4e92395d90a914b0432f6a2494c52f12b0032f482fbd5fbd0f309c03457038546f4eee4273f9a26ca39869ccc09af92160
7
+ data.tar.gz: 6273e3a816b869b90ed3f4eb5e1dffcf2d15786687b806fd45c9b0c61e76894158d4b0a3a741e10fd06c94b865342edcfdb589ba959dfa3cf3857a85e3d53a00
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  .DS_Store
2
2
  *.sw[pon]
3
3
  .bundle
4
+ .byebug_history
4
5
  .rvmrc
5
6
  *.log
6
7
  Gemfile.lock
data/Gemfile CHANGED
@@ -11,10 +11,10 @@ group :test do
11
11
  end
12
12
 
13
13
  # BEGIN ENGINE_CART BLOCK
14
- # engine_cart: 0.8.0
15
- # engine_cart stanza: 0.8.0
14
+ # engine_cart: 0.10.0
15
+ # engine_cart stanza: 0.10.0
16
16
  # the below comes from engine_cart, a gem used to test this Rails engine gem in the context of a Rails app.
17
- file = File.expand_path("Gemfile", ENV['ENGINE_CART_DESTINATION'] || ENV['RAILS_ROOT'] || File.expand_path(".internal_test_app", File.dirname(__FILE__)))
17
+ file = File.expand_path('Gemfile', ENV['ENGINE_CART_DESTINATION'] || ENV['RAILS_ROOT'] || File.expand_path('.internal_test_app', File.dirname(__FILE__)))
18
18
  if File.exist?(file)
19
19
  begin
20
20
  eval_gemfile file
@@ -28,20 +28,19 @@ else
28
28
  if ENV['RAILS_VERSION']
29
29
  if ENV['RAILS_VERSION'] == 'edge'
30
30
  gem 'rails', github: 'rails/rails'
31
- ENV['ENGINE_CART_RAILS_OPTIONS']= "--edge --skip-turbolinks"
31
+ ENV['ENGINE_CART_RAILS_OPTIONS'] = '--edge --skip-turbolinks'
32
32
  else
33
33
  gem 'rails', ENV['RAILS_VERSION']
34
34
  end
35
35
  end
36
36
 
37
- if ENV['RAILS_VERSION'].nil? || ENV['RAILS_VERSION'] =~ /^5\.0/ || ENV['RAILS_VERSION'] == 'edge'
38
- # noop
39
- elsif ENV['RAILS_VERSION'] =~ /^4\.2/
40
- gem 'responders', "~> 2.0"
41
- gem 'sass-rails', ">= 5.0"
42
- else
43
- gem 'bootstrap-sass', '< 3.3.5' # 3.3.5 requires sass 3.3, incompatible with sass-rails 4.x
44
- gem 'sass-rails', "< 5.0"
37
+ case ENV['RAILS_VERSION']
38
+ when /^4.2/
39
+ gem 'responders', '~> 2.0'
40
+ gem 'sass-rails', '>= 5.0'
41
+ gem 'coffee-rails', '~> 4.1.0'
42
+ when /^4.[01]/
43
+ gem 'sass-rails', '< 5.0'
45
44
  end
46
45
  end
47
46
  # END ENGINE_CART BLOCK
data/VERSION CHANGED
@@ -1 +1 @@
1
- 6.4.2
1
+ 6.5.0
@@ -1,7 +1,7 @@
1
1
  .twitter-typeahead {
2
2
  float: left;
3
3
  width: 100%;
4
- z-index: 500;
4
+ z-index: $zindex-typeahead;
5
5
 
6
6
  input.tt-input.form-control {
7
7
  width: 100%;
@@ -4,3 +4,4 @@ $logo_image: 'blacklight/logo.png' !default;
4
4
 
5
5
  /* label (field names) */
6
6
  $field_name_color: $text-muted !default;
7
+ $zindex-typeahead: $zindex-dropdown;
@@ -15,6 +15,7 @@ module Blacklight::Bookmarks
15
15
 
16
16
  before_action :verify_user
17
17
 
18
+ blacklight_config.http_method = Blacklight::Engine.config.bookmarks_http_method
18
19
  blacklight_config.add_results_collection_tool(:clear_bookmarks_widget)
19
20
 
20
21
  blacklight_config.show.document_actions[:bookmark].if = false if blacklight_config.show.document_actions[:bookmark]
@@ -83,7 +84,7 @@ module Blacklight::Bookmarks
83
84
  end
84
85
 
85
86
  if request.xhr?
86
- success ? render(json: { bookmarks: { count: current_or_guest_user.bookmarks.count }}) : render(:text => "", :status => "500")
87
+ success ? render(json: { bookmarks: { count: current_or_guest_user.bookmarks.count }}) : render(plain: "", status: "500")
87
88
  else
88
89
  if @bookmarks.any? && success
89
90
  flash[:notice] = I18n.t('blacklight.bookmarks.add.success', :count => @bookmarks.length)
@@ -114,16 +115,13 @@ module Blacklight::Bookmarks
114
115
  # Deprecated in Rails 5.0
115
116
  redirect_to :back, notice: I18n.t('blacklight.bookmarks.remove.success')
116
117
  end
118
+ elsif request.xhr?
119
+ head 500 # ajaxy request needs no redirect and should not have flash set
120
+ elsif respond_to? :redirect_back
121
+ redirect_back fallback_location: bookmarks_path, flash: { error: I18n.t('blacklight.bookmarks.remove.failure') }
117
122
  else
118
- if request.xhr?
119
- # ajaxy request needs no redirect and should not have flash set
120
- render(:text => "", :status => "500")
121
- elsif respond_to? :redirect_back
122
- redirect_back fallback_location: bookmarks_path, flash: { error: I18n.t('blacklight.bookmarks.remove.failure') }
123
- else
124
- # Deprecated in Rails 5.0
125
- redirect_to :back, flash: { error: I18n.t('blacklight.bookmarks.remove.failure') }
126
- end
123
+ # Deprecated in Rails 5.0
124
+ redirect_to :back, flash: { error: I18n.t('blacklight.bookmarks.remove.failure') }
127
125
  end
128
126
  end
129
127
 
@@ -43,11 +43,9 @@ module Blacklight::Catalog
43
43
  # to add responses for formats other than html or json see _Blacklight::Document::Export_
44
44
  def show
45
45
  @response, @document = fetch params[:id]
46
-
47
46
  respond_to do |format|
48
47
  format.html { setup_next_and_previous_documents }
49
48
  format.json { render json: { response: { document: @document } } }
50
-
51
49
  additional_export_formats(@document, format)
52
50
  end
53
51
  end
@@ -71,15 +69,11 @@ module Blacklight::Catalog
71
69
  @facet = blacklight_config.facet_fields[params[:id]]
72
70
  @response = get_facet_field_response(@facet.key, params)
73
71
  @display_facet = @response.aggregations[@facet.key]
74
-
75
72
  @pagination = facet_paginator(@facet, @display_facet)
76
-
77
-
78
73
  respond_to do |format|
79
74
  # Draw the facet selector for users who have javascript disabled:
80
75
  format.html
81
76
  format.json
82
-
83
77
  # Draw the partial for the "more" facet modal window:
84
78
  format.js { render :layout => false }
85
79
  end
@@ -88,12 +82,8 @@ module Blacklight::Catalog
88
82
  # method to serve up XML OpenSearch description and JSON autocomplete response
89
83
  def opensearch
90
84
  respond_to do |format|
91
- format.xml do
92
- render :layout => false
93
- end
94
- format.json do
95
- render :json => get_opensearch_response
96
- end
85
+ format.xml { render layout: false }
86
+ format.json { render json: get_opensearch_response }
97
87
  end
98
88
  end
99
89
 
@@ -107,7 +97,7 @@ module Blacklight::Catalog
107
97
 
108
98
  ##
109
99
  # Check if any search parameters have been set
110
- # @return [Boolean]
100
+ # @return [Boolean]
111
101
  def has_search_parameters?
112
102
  !params[:q].blank? or !params[:f].blank? or !params[:search_field].blank?
113
103
  end
@@ -129,13 +119,10 @@ module Blacklight::Catalog
129
119
  ##
130
120
  # Render additional response formats for the index action, as provided by the
131
121
  # blacklight configuration
132
- #
133
- # example:
134
- #
135
- # config.index.respond_to.txt = Proc.new { render text: "A list of docs." }
136
- #
137
- # Make sure your format has a well known mime-type or is registered in
138
- # config/initializers/mime_types.rb
122
+ # @param [Hash] format
123
+ # @note Make sure your format has a well known mime-type or is registered in config/initializers/mime_types.rb
124
+ # @example
125
+ # config.index.respond_to.txt = Proc.new { render plain: "A list of docs." }
139
126
  def additional_response_formats format
140
127
  blacklight_config.index.respond_to.each do |key, config|
141
128
  format.send key do
@@ -160,7 +147,7 @@ module Blacklight::Catalog
160
147
  # the document extension framework. See _Blacklight::Document::Export_
161
148
  def additional_export_formats(document, format)
162
149
  document.export_formats.each_key do | format_name |
163
- format.send(format_name.to_sym) { render text: document.export_as(format_name), layout: false }
150
+ format.send(format_name.to_sym) { render body: document.export_as(format_name), layout: false }
164
151
  end
165
152
  end
166
153
 
@@ -169,7 +156,6 @@ module Blacklight::Catalog
169
156
  def document_export_formats format
170
157
  format.any do
171
158
  format_name = params.fetch(:format, '').to_sym
172
-
173
159
  if @response.export_formats.include? format_name
174
160
  render_document_export_format format_name
175
161
  else
@@ -181,11 +167,11 @@ module Blacklight::Catalog
181
167
  ##
182
168
  # Render the document export formats for a response
183
169
  # First, try to render an appropriate template (e.g. index.endnote.erb)
184
- # If that fails, just concatenate the document export responses with a newline.
170
+ # If that fails, just concatenate the document export responses with a newline.
185
171
  def render_document_export_format format_name
186
172
  render
187
173
  rescue ActionView::MissingTemplate
188
- render text: @response.documents.map { |x| x.export_as(format_name) if x.exports_as? format_name }.compact.join("\n"), layout: false
174
+ render plain: @response.documents.map { |x| x.export_as(format_name) if x.exports_as? format_name }.compact.join("\n"), layout: false
189
175
  end
190
176
 
191
177
  # Overrides the Blacklight::Controller provided #search_action_url.
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
  module Blacklight::CatalogHelperBehavior
3
3
 
4
- def rss_feed_link_tag
5
- auto_discovery_link_tag(:rss, feed_link_url('rss'), title: t('blacklight.search.rss_feed'))
4
+ # @param [Hash] options
5
+ # @option options :route_set the route scope to use when constructing the link
6
+ def rss_feed_link_tag(options = {})
7
+ auto_discovery_link_tag(:rss, feed_link_url('rss', options), title: t('blacklight.search.rss_feed'))
6
8
  end
7
9
 
8
- def atom_feed_link_tag
9
- auto_discovery_link_tag(:atom, feed_link_url('atom'), title: t('blacklight.search.atom_feed'))
10
+ # @param [Hash] options
11
+ # @option options :route_set the route scope to use when constructing the link
12
+ def atom_feed_link_tag(options = {})
13
+ auto_discovery_link_tag(:atom, feed_link_url('atom', options), title: t('blacklight.search.atom_feed'))
10
14
  end
11
15
 
12
16
  ##
@@ -285,7 +289,11 @@ module Blacklight::CatalogHelperBehavior
285
289
 
286
290
  private
287
291
 
288
- def feed_link_url(format)
289
- url_for search_state.to_h.merge(format: format)
292
+ # @param [String] format
293
+ # @param [Hash] options
294
+ # @option options :route_set the route scope to use when constructing the link
295
+ def feed_link_url(format, options = {})
296
+ scope = options.delete(:route_set) || self
297
+ scope.url_for search_state.to_h.merge(format: format)
290
298
  end
291
299
  end
@@ -2,7 +2,7 @@
2
2
  # == Transformation conventions
3
3
  # The main use case for extensions is for transforming a Document to another
4
4
  # format. Either to another type of Ruby object, or to an exportable string in
5
- # a certain format.
5
+ # a certain format.
6
6
  #
7
7
  # The convention for methods contained in extensions that transform to a ruby
8
8
  # object is "to_*". For instance, "to_marc" would return a Ruby Marc object.
@@ -20,7 +20,7 @@
20
20
  # If an extension advertises what export formats it can provide, than those
21
21
  # formats will automatically be delivered by the Blacklight catalog/show
22
22
  # controller, and potentially automatically advertised in various places
23
- # that advertise available formats. (HTML link rel=alternate; Atom
23
+ # that advertise available formats. (HTML link rel=alternate; Atom
24
24
  # link rel=alterate; etc).
25
25
  #
26
26
  # Export formats are 'registered' by calling the #will_export_as method
@@ -40,21 +40,21 @@
40
40
  #
41
41
  module Blacklight::Document::Export
42
42
 
43
- ##
43
+ ##
44
44
  # Register exportable formats supported by the individual document.
45
45
  # Usually called by an extension in it's self.extended method, to
46
- # register the formats that extension can export.
47
- #
46
+ # register the formats that extension can export.
47
+ #
48
48
  # some_document.will_export_as(:some_format, "application/type") means
49
49
  # that the document (usually via an extension) has a method
50
50
  # "export_as_some_format" which returns a String of content that
51
- # is described by the mime content_type given.
52
- #
51
+ # is described by the mime content_type given.
52
+ #
53
53
  # The format name should ideally _already_ be registered with
54
54
  # Rails Mime::Type, in your application initializer, representing
55
55
  # the content type given. However, this method will attempt to
56
56
  # register it using Mime::Type.register_alias if it's not previously
57
- # registered. This is a bit sketchy though.
57
+ # registered. This is a bit sketchy though.
58
58
  def will_export_as(short_name, content_type = nil)
59
59
  #Lookup in Rails Mime::Type, register if needed, otherwise take
60
60
  # content-type from registration if needed.
@@ -62,34 +62,32 @@ module Blacklight::Document::Export
62
62
  content_type ||= Mime[short_name.to_sym]
63
63
  else
64
64
  # not registered, we need to register. Use register_alias to be least
65
- # likely to interfere with host app.
65
+ # likely to interfere with host app.
66
66
  Mime::Type.register_alias(content_type, short_name)
67
67
  end
68
68
 
69
69
  export_formats[short_name] = { content_type: content_type }
70
70
  end
71
-
71
+
72
72
  # Collects formats that this doc can export as.
73
- # Returns a hash, keys are format short-names that can
74
- # be exported. Hash includes:
75
- # :content-type => mime-content-type
76
- # maybe more later
77
73
  # To see if a given export format is supported by this document,
78
74
  # simply call document.export_formats.keys.include?(:my_format)
79
- # Then call #export_as! to do the export.
75
+ # Then call #export_as! to do the export.
76
+ # @return [Hash{Symbol=>Hash{Symbol=>String}}] keys are format short-names that can be exported, values are Hashes
77
+ # @example { :marc => { content_type: 'application/marc' } }
80
78
  def export_formats
81
79
  @export_formats ||= {}
82
80
  end
83
-
81
+
84
82
  # Call with a format shortname, export_as(:marc), simply returns
85
83
  # #export_as_marc . Later we may expand the design to allow you
86
84
  # to register an arbitrary method name instead of insisting
87
85
  # on the convention, so clients should call this method so
88
- # they'll still keep working if we do that.
86
+ # they'll still keep working if we do that.
89
87
  def export_as(short_name)
90
88
  send("export_as_#{short_name}")
91
89
  end
92
-
90
+
93
91
  def exports_as? short_name
94
92
  respond_to? "export_as_#{short_name}"
95
93
  end
data/app/models/search.rb CHANGED
@@ -1,26 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
  class Search < ActiveRecord::Base
3
-
4
3
  belongs_to_arguments = { optional: true } if Rails.version >= '5.0.0'
5
4
 
6
5
  belongs_to :user, belongs_to_arguments
7
6
 
8
7
  serialize :query_params
9
8
 
10
- if Blacklight::Utils.needs_attr_accessible?
11
- attr_accessible :query_params
12
- end
9
+ attr_accessible :query_params if Blacklight::Utils.needs_attr_accessible?
13
10
 
14
11
  # A Search instance is considered a saved search if it has a user_id.
15
12
  def saved?
16
13
  self.user_id?
17
14
  end
18
-
15
+
19
16
  # delete old, unsaved searches
20
17
  def self.delete_old_searches(days_old)
21
18
  raise ArgumentError, 'days_old is expected to be a number' unless days_old.is_a?(Numeric)
22
19
  raise ArgumentError, 'days_old is expected to be greater than 0' if days_old <= 0
23
- self.destroy_all(['created_at < ? AND user_id IS NULL', Time.zone.today - days_old])
20
+ self.where(['created_at < ? AND user_id IS NULL', Time.zone.today - days_old]).destroy_all
24
21
  end
25
-
26
22
  end
@@ -22,7 +22,7 @@
22
22
  <%- @searches.each do |search| -%>
23
23
  <tr>
24
24
  <td><%= link_to_previous_search(search.query_params) %></td>
25
- <td><%= button_to t('blacklight.saved_searches.delete'), blacklight.forget_search_path(search.id) %></td>
25
+ <td><%= button_to t('blacklight.saved_searches.delete'), blacklight.forget_search_path(search.id), :class => 'btn btn-danger' %></td>
26
26
  </tr>
27
27
  <%- end -%>
28
28
  </table>
data/blacklight.gemspec CHANGED
@@ -40,6 +40,6 @@ Gem::Specification.new do |s|
40
40
  s.add_development_dependency "rspec-collection_matchers", ">= 1.0"
41
41
  s.add_development_dependency "capybara", '~> 2.6.0'
42
42
  s.add_development_dependency "poltergeist"
43
- s.add_development_dependency 'engine_cart', '~> 0.8.0'
43
+ s.add_development_dependency 'engine_cart', '~> 0.10'
44
44
  s.add_development_dependency "equivalent-xml"
45
45
  end
@@ -42,5 +42,6 @@ module Blacklight
42
42
  'Cricket' => 'mms.mycricket.com'
43
43
  }
44
44
 
45
+ config.bookmarks_http_method = :post
45
46
  end
46
47
  end
@@ -1,6 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe BookmarksController do
4
+ describe '#blacklight_config' do
5
+ it 'uses POST requests for querying solr' do
6
+ expect(@controller.blacklight_config.http_method).to eq :post
7
+ end
8
+ end
9
+
4
10
  # jquery 1.9 ajax does error callback if 200 returns empty body. so use 204 instead.
5
11
  describe "update" do
6
12
  it "has a 200 status code when creating a new one" do
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  describe CatalogController do
3
+ let(:doc_id) { '2007020969' }
4
+ let(:mock_response) { double() }
5
+ let(:mock_document) { double() }
4
6
 
5
7
  describe "index action" do
6
- describe "with format :html" do
8
+ context "with format :html" do
7
9
  let(:user_query) { 'history' } # query that will get results
8
10
 
9
11
  it "has no search history if no search criteria" do
@@ -42,19 +44,18 @@ describe CatalogController do
42
44
  page = 2
43
45
  get :index, params: { page: page }
44
46
  expect(assigns(:response).docs).to_not be_empty
45
- expect(assigns(:response).params[:start].to_i).to eq (page-1) * @controller.blacklight_config[:default_solr_params][:rows]
47
+ expect(assigns(:response).params[:start].to_i).to eq (page-1) * controller.blacklight_config[:default_solr_params][:rows]
46
48
  assert_facets_have_values(assigns(:response).aggregations)
47
49
  end
48
50
 
49
51
  it "has no docs or facet values for query without results", :integration => true do
50
52
  get :index, params: { q: 'sadfdsafasdfsadfsadfsadf' } # query for no results
51
-
52
53
  expect(assigns(:response).docs).to be_empty
53
54
  assigns(:response).aggregations.each do |key, facet|
54
55
  expect(facet.items).to be_empty
55
56
  end
56
57
  end
57
-
58
+
58
59
  it "shows 0 results when the user asks for an invalid value to a custom facet query", :integration => true do
59
60
  get :index, params: { f: { example_query_facet_field: 'bogus' } } # bogus custom facet value
60
61
  expect(assigns(:response).docs).to be_empty
@@ -66,7 +67,7 @@ describe CatalogController do
66
67
  get :index, params: { f: {example_query_facet_field: 'years_5' } } # valid custom facet value with NO results
67
68
  expect(assigns(:response).docs).to be_empty
68
69
  end
69
-
70
+
70
71
  it "has a spelling suggestion for an appropriately poor query", :integration => true do
71
72
  get :index, params: { q: 'boo' }
72
73
  expect(assigns(:response).spelling.words).to_not be_nil
@@ -80,7 +81,6 @@ describe CatalogController do
80
81
  get :index, params: { q: user_query }
81
82
  expect(session[:search]).to_not be_nil
82
83
  expect(session[:search].keys).to include 'id'
83
-
84
84
  search = Search.find(session[:search]['id'])
85
85
  expect(search.query_params['q']).to eq user_query
86
86
  end
@@ -125,8 +125,8 @@ describe CatalogController do
125
125
  expect(response).to be_success
126
126
  end
127
127
  let(:json) { JSON.parse(response.body)['response'] }
128
- let(:pages) { json["pages"] }
129
- let(:docs) { json["docs"] }
128
+ let(:pages) { json["pages"] }
129
+ let(:docs) { json["docs"] }
130
130
  let(:facets) { json["facets"] }
131
131
 
132
132
  it "gets the pages" do
@@ -161,8 +161,8 @@ describe CatalogController do
161
161
  let(:blacklight_config) { Blacklight::Configuration.new }
162
162
 
163
163
  before :each do
164
- allow(@controller).to receive_messages blacklight_config: blacklight_config
165
- allow(@controller).to receive_messages search_results: [double, double]
164
+ allow(controller).to receive_messages blacklight_config: blacklight_config
165
+ allow(controller).to receive_messages search_results: [double, double]
166
166
  end
167
167
 
168
168
  it "does not render when the config is false" do
@@ -178,33 +178,29 @@ describe CatalogController do
178
178
  end
179
179
 
180
180
  it "passes a hash to the render call" do
181
- blacklight_config.index.respond_to.yaml = { nothing: true, layout: false }
181
+ blacklight_config.index.respond_to.yaml = { inline: '', layout: false }
182
182
  get :index, params: { format: 'yaml' }
183
183
  expect(response.body).to be_blank
184
184
  end
185
185
 
186
186
  it "evaluates a proc" do
187
- blacklight_config.index.respond_to.yaml = lambda { render text: "" }
187
+ blacklight_config.index.respond_to.yaml = lambda { render plain: "" }
188
188
  get :index, params: { format: 'yaml' }
189
189
  expect(response.body).to be_empty
190
190
  end
191
191
 
192
192
  it "with a symbol, it should call a controller method" do
193
193
  expect(subject).to receive(:render_some_yaml) do
194
- subject.render nothing: true, layout: false
194
+ subject.head :ok, layout: false
195
195
  end
196
-
197
196
  blacklight_config.index.respond_to.yaml = :render_some_yaml
198
197
  get :index, params: { format: 'yaml' }
199
198
  expect(response.body).to be_blank
200
199
  end
201
200
  end
202
-
203
201
  end # describe index action
204
202
 
205
203
  describe "track action" do
206
- doc_id = '2007020969'
207
-
208
204
  it "persists the search session id value into session[:search]" do
209
205
  put :track, params: { id: doc_id, counter: 3, search_id: "123" }
210
206
  expect(session[:search]['id']).to eq "123"
@@ -214,7 +210,7 @@ describe CatalogController do
214
210
  put :track, params: { id: doc_id, counter: 3 }
215
211
  expect(session[:search]['counter']).to eq "3"
216
212
  end
217
-
213
+
218
214
  it "records the current per_page setting" do
219
215
  put :track, params: { id: doc_id, counter: 3, per_page: 15 }
220
216
  expect(session[:search]['per_page']).to eq "15"
@@ -243,9 +239,6 @@ describe CatalogController do
243
239
 
244
240
  # SHOW ACTION
245
241
  describe "show action" do
246
-
247
- doc_id = '2007020969'
248
-
249
242
  describe "with format :html" do
250
243
  it "gets document", :integration => true do
251
244
  get :show, params: { id: doc_id }
@@ -261,50 +254,48 @@ describe CatalogController do
261
254
  expect(json["response"]["document"].keys).to match_array(["author_t", "opensearch_display", "marc_display", "published_display", "author_display", "lc_callnum_display", "title_t", "pub_date", "pub_date_sort", "subtitle_display", "format", "url_suppl_display", "material_type_display", "title_display", "subject_addl_t", "subject_t", "isbn_t", "id", "title_addl_t", "subject_geo_facet", "subject_topic_facet", "author_addl_t", "language_facet", "subtitle_t", "timestamp"])
262
255
  end
263
256
  end
264
-
257
+
265
258
  describe "previous/next documents" do
259
+ let(:search_session) { { :id => current_search.id } }
260
+ let(:current_search) { Search.create(:query_params => { :q => ""}) }
266
261
  before do
267
- @mock_response = double()
268
- @mock_document = double()
269
- allow(@mock_document).to receive_messages(:export_formats => {})
270
- allow(controller).to receive_messages(fetch: [@mock_response, @mock_document],
271
- :get_previous_and_next_documents_for_search => [double(:total => 5), [double("a"), @mock_document, double("b")]])
272
-
273
- current_search = Search.create(:query_params => { :q => ""})
274
- allow(controller).to receive_messages(:current_search_session => current_search)
275
-
276
- @search_session = { :id => current_search.id }
262
+ allow(mock_document).to receive_messages(:export_formats => {})
263
+ allow(controller).to receive_messages(
264
+ fetch: [mock_response, mock_document],
265
+ get_previous_and_next_documents_for_search: [double(:total => 5), [double("a"), mock_document, double("b")]],
266
+ current_search_session: current_search
267
+ )
268
+ end
269
+ it "sets previous document if counter present in session" do
270
+ session[:search] = search_session.merge('counter' => 2)
271
+ get :show, params: { id: doc_id }
272
+ expect(assigns[:previous_document]).to_not be_nil
273
+ end
274
+ it "does not set previous or next document if session is blank" do
275
+ get :show, params: { id: doc_id }
276
+ expect(assigns[:previous_document]).to be_nil
277
+ expect(assigns[:next_document]).to be_nil
278
+ end
279
+ it "does not set previous or next document if session[:search]['counter'] is nil" do
280
+ session[:search] = {}
281
+ get :show, params: { id: doc_id }
282
+ expect(assigns[:previous_document]).to be_nil
283
+ expect(assigns[:next_document]).to be_nil
284
+ end
285
+ it "sets next document if counter present in session" do
286
+ session[:search] = search_session.merge('counter' => 2)
287
+ get :show, params: { id: doc_id }
288
+ expect(assigns[:next_document]).to_not be_nil
277
289
  end
278
- it "sets previous document if counter present in session" do
279
- session[:search] = @search_session.merge('counter' => 2)
280
- get :show, params: { id: doc_id }
281
- expect(assigns[:previous_document]).to_not be_nil
282
- end
283
- it "does not set previous or next document if session is blank" do
284
- get :show, params: { id: doc_id }
285
- expect(assigns[:previous_document]).to be_nil
286
- expect(assigns[:next_document]).to be_nil
287
- end
288
- it "does not set previous or next document if session[:search]['counter'] is nil" do
289
- session[:search] = {}
290
- get :show, params: { id: doc_id }
291
- expect(assigns[:previous_document]).to be_nil
292
- expect(assigns[:next_document]).to be_nil
293
- end
294
- it "sets next document if counter present in session" do
295
- session[:search] = @search_session.merge('counter' => 2)
296
- get :show, params: { id: doc_id }
297
- expect(assigns[:next_document]).to_not be_nil
298
- end
299
290
 
300
- it "does not break if solr returns an exception" do
301
- allow(controller).to receive(:get_previous_and_next_documents_for_search) {
302
- raise Blacklight::Exceptions::InvalidRequest.new "Error"
303
- }
304
- get :show, params: { id: doc_id }
305
- expect(assigns[:previous_document]).to be_nil
306
- expect(assigns[:next_document]).to be_nil
307
- end
291
+ it "does not break if solr returns an exception" do
292
+ allow(controller).to receive(:get_previous_and_next_documents_for_search) {
293
+ raise Blacklight::Exceptions::InvalidRequest.new "Error"
294
+ }
295
+ get :show, params: { id: doc_id }
296
+ expect(assigns[:previous_document]).to be_nil
297
+ expect(assigns[:next_document]).to be_nil
298
+ end
308
299
  end
309
300
 
310
301
  # NOTE: status code is always 200 in isolation mode ...
@@ -312,96 +303,61 @@ describe CatalogController do
312
303
  get :show, params: { id: doc_id }
313
304
  expect(response).to be_success
314
305
  end
306
+
315
307
  it "renders show.html.erb" do
316
- @mock_response = double()
317
- @mock_document = double()
318
- allow(@mock_document).to receive_messages(:export_formats => {})
319
- allow(controller).to receive_messages(fetch: [@mock_response, @mock_document])
308
+ allow(mock_document).to receive_messages(:export_formats => {})
309
+ allow(controller).to receive_messages(fetch: [mock_response, mock_document])
320
310
  get :show, params: { id: doc_id }
321
311
  expect(response).to render_template(:show)
322
312
  end
323
313
 
324
314
  describe "@document" do
325
315
  before do
326
- @mock_response = double()
327
- allow(@mock_response).to receive_messages(documents: [SolrDocument.new(id: 'my_fake_doc')])
328
- @mock_document = double()
329
- allow(controller).to receive_messages(:find => @mock_response )
330
- end
331
- before(:each) do
316
+ allow(mock_response).to receive_messages(documents: [SolrDocument.new(id: 'my_fake_doc')])
317
+ allow(controller).to receive_messages(:find => mock_response )
332
318
  get :show, params: { id: doc_id }
333
- @document = assigns[:document]
334
319
  end
335
320
  it "is a SolrDocument" do
336
- expect(@document).to be_instance_of(SolrDocument)
321
+ expect(assigns[:document]).to be_instance_of(SolrDocument)
337
322
  end
338
323
  end
339
-
324
+
340
325
  describe "with dynamic export formats" do
341
326
  render_views
342
327
  module FakeExtension
343
328
  def self.extended(document)
344
329
  document.will_export_as(:mock, "application/mock")
345
330
  end
346
-
331
+
347
332
  def export_as_mock
348
333
  "mock_export"
349
334
  end
350
335
  end
351
-
352
- before do
353
- @mock_response = double()
354
- allow(@mock_response).to receive_messages(:docs => [{ :id => 'my_fake_doc' }])
355
- @mock_document = double()
356
- allow(controller).to receive_messages(find: @mock_response)
357
- end
358
336
 
359
- before(:each) do
360
-
361
- # Rails3 needs this to propertly setup a new mime type and
362
- # render the results.
363
- ActionController.add_renderer :double do |template, options|
364
- send_data "mock_export", :type => Mime::MOCK
365
- end
337
+ before do
338
+ allow(mock_response).to receive_messages(:documents => [SolrDocument.new(id: 'my_fake_doc')])
339
+ allow(controller).to receive_messages(:find => mock_response,
340
+ :get_single_doc_via_search => mock_document)
366
341
  Mime::Type.register "application/mock", :mock
367
-
368
342
  SolrDocument.use_extension(FakeExtension)
369
343
  end
370
-
371
- before do
372
- @mock_response = double()
373
- allow(@mock_response).to receive_messages(:documents => [SolrDocument.new(id: 'my_fake_doc')])
374
- @mock_document = double()
375
- allow(controller).to receive_messages(:find => @mock_response,
376
- :get_single_doc_via_search => @mock_document)
377
-
378
- allow(controller).to receive_messages(:find => @mock_response,
379
- :get_single_doc_via_search => @mock_document)
380
- end
381
344
 
382
345
  it "responds to an extension-registered format properly" do
383
346
  get :show, params: { id: doc_id, format: 'mock' }
384
347
  expect(response).to be_success
385
348
  expect(response.body).to match /mock_export/
386
349
  end
387
-
388
350
 
389
- after(:each) do
390
- # remove the fake extension
391
- SolrDocument.registered_extensions.pop
351
+ after do
352
+ SolrDocument.registered_extensions.pop # remove the fake extension
392
353
  end
393
354
  end # dynamic export formats
394
-
395
355
  end # describe show action
396
356
 
397
357
  describe "opensearch" do
398
358
  before do
399
- @mock_response = double()
400
- @mock_document = double()
401
- allow(@mock_response).to receive_messages(documents: [SolrDocument.new(id: 'my_fake_doc'), SolrDocument.new(id: 'my_other_doc')])
402
- @mock_document = double()
403
- allow(controller).to receive_messages(find: @mock_response)
404
-
359
+ allow(mock_response).to receive_messages(documents: [SolrDocument.new(id: 'my_fake_doc'), SolrDocument.new(id: 'my_other_doc')])
360
+ allow(controller).to receive_messages(find: mock_response)
405
361
  end
406
362
  it "returns an opensearch description" do
407
363
  get :opensearch, params: { format: 'xml' }
@@ -414,7 +370,6 @@ describe CatalogController do
414
370
  end
415
371
 
416
372
  describe "email/sms" do
417
- doc_id = '2007020969'
418
373
  let(:mock_response) { double(documents: [SolrDocument.new(id: 'my_fake_doc'), SolrDocument.new(id: 'my_other_doc')]) }
419
374
  before do
420
375
  allow(controller).to receive_messages(find: mock_response)
@@ -436,10 +391,9 @@ describe CatalogController do
436
391
  expect(request.flash[:error]).to be_nil
437
392
  end
438
393
  it "redirects back to the record upon success" do
439
- mock_mailer = double
440
- allow(mock_mailer).to receive(:deliver)
441
- allow(RecordMailer).to receive(:email_record).with(anything, { :to => 'test_email@projectblacklight.org', :message => 'xyz' }, hash_including(:host => 'test.host')).and_return mock_mailer
442
-
394
+ allow(RecordMailer).to receive(:email_record)
395
+ .with(anything, { :to => 'test_email@projectblacklight.org', :message => 'xyz' }, hash_including(:host => 'test.host'))
396
+ .and_return double(deliver: nil)
443
397
  post :email, params: { id: doc_id, to: 'test_email@projectblacklight.org', message: 'xyz' }
444
398
  expect(request.flash[:error]).to be_nil
445
399
  expect(request).to redirect_to(solr_document_path(doc_id))
@@ -450,6 +404,7 @@ describe CatalogController do
450
404
  expect(request.flash[:success]).to eq "Email Sent"
451
405
  end
452
406
  end
407
+
453
408
  describe "sms" do
454
409
  it "gives error if no phone number is given" do
455
410
  post :sms, params: { id: doc_id, carrier: 'att' }
@@ -473,9 +428,10 @@ describe CatalogController do
473
428
  expect(request).to redirect_to(solr_document_path(doc_id))
474
429
  end
475
430
  it "sends to the appropriate carrier email address" do
476
- mock_mailer = double
477
- allow(mock_mailer).to receive(:deliver)
478
- expect(RecordMailer).to receive(:sms_record).with(anything, { to: '5555555555@txt.att.net' }, hash_including(:host => 'test.host')).and_return mock_mailer
431
+ expect(RecordMailer)
432
+ .to receive(:sms_record)
433
+ .with(anything, { to: '5555555555@txt.att.net' }, hash_including(:host => 'test.host'))
434
+ .and_return double(:deliver => nil)
479
435
  post :sms, params: { id: doc_id, to: '5555555555', carrier: 'txt.att.net' }
480
436
  end
481
437
  it "redirects back to the record upon success" do
@@ -483,7 +439,6 @@ describe CatalogController do
483
439
  expect(request.flash[:error]).to eq nil
484
440
  expect(request).to redirect_to(solr_document_path(doc_id))
485
441
  end
486
-
487
442
  it "renders sms_success template for XHR requests" do
488
443
  post :sms, xhr: true, params: { id: doc_id, to: '5555555555', carrier: 'txt.att.net' }
489
444
  expect(request).to render_template 'sms_success'
@@ -494,19 +449,17 @@ describe CatalogController do
494
449
 
495
450
  describe "errors" do
496
451
  it "returns status 404 for a record that doesn't exist" do
497
- @mock_response = double(documents: [])
498
- allow(controller).to receive_messages(:find => @mock_response)
452
+ allow(controller).to receive_messages(:find => double(documents: []))
499
453
  get :show, params: { id: "987654321" }
500
454
  expect(response.status).to eq 404
501
- expect(response.content_type).to eq Mime::HTML
455
+ expect(response.content_type).to eq Mime[:html]
502
456
  end
503
- it "returns status 404 for a record that doesn't exist even for non-html format" do
504
- @mock_response = double(documents: [])
505
- allow(controller).to receive_messages(:find => @mock_response)
506
457
 
458
+ it "returns status 404 for a record that doesn't exist even for non-html format" do
459
+ allow(controller).to receive_messages(:find => double(documents: []))
507
460
  get :show, params: { id: "987654321", format: "xml" }
508
461
  expect(response.status).to eq 404
509
- expect(response.content_type).to eq Mime::XML
462
+ expect(response.content_type).to eq Mime[:xml]
510
463
  end
511
464
 
512
465
  it "redirects the user to the root url for a bad search" do
@@ -529,7 +482,6 @@ describe CatalogController do
529
482
  allow(controller).to receive(:flash).and_return(:notice => I18n.t('blacklight.search.errors.request_error'))
530
483
  expect { get :index, params: { q: '+' } }.to raise_error Blacklight::Exceptions::InvalidRequest
531
484
  end
532
-
533
485
  end
534
486
 
535
487
  context "without a user authentication provider" do
@@ -578,7 +530,6 @@ describe CatalogController do
578
530
  session[:history] = []
579
531
  controller.send(:add_to_search_history, double(:id => 1))
580
532
  expect(session[:history]).to have(1).item
581
-
582
533
  controller.send(:add_to_search_history, double(:id => 2))
583
534
  expect(session[:history]).to have(2).items
584
535
  expect(session[:history].first).to eq 2
@@ -587,13 +538,11 @@ describe CatalogController do
587
538
  it "removes searches from the list when the list gets too big" do
588
539
  allow(controller).to receive(:blacklight_config).and_return(double(:search_history_window => 5))
589
540
  session[:history] = (0..4).to_a.reverse
590
-
591
541
  expect(session[:history]).to have(5).items
592
542
  controller.send(:add_to_search_history, double(:id => 5))
593
543
  controller.send(:add_to_search_history, double(:id => 6))
594
544
  controller.send(:add_to_search_history, double(:id => 7))
595
545
  expect(session[:history]).to include(*(3..7).to_a)
596
-
597
546
  end
598
547
  end
599
548
 
@@ -654,45 +603,42 @@ describe CatalogController do
654
603
 
655
604
  describe "#add_show_tools_partial" do
656
605
  before do
657
- CatalogController.add_show_tools_partial(:like, callback: :perform_like, validator: :validate_like_params)
658
- allow(controller).to receive(:perform_like)
606
+ described_class.add_show_tools_partial(:like, callback: :perform_like, validator: :validate_like_params)
659
607
  allow(controller).to receive(:solr_document_url).and_return('catalog/1')
660
- allow(controller).to receive(:action_documents).and_return([SolrDocument.new])
608
+ allow(controller).to receive(:action_documents).and_return(1)
661
609
  Rails.application.routes.draw do
662
610
  get 'catalog/like', as: :catalog_like
663
611
  end
664
612
  end
665
613
 
666
614
  after do
667
- CatalogController.blacklight_config.show.document_actions.delete(:like)
615
+ described_class.blacklight_config.show.document_actions.delete(:like)
668
616
  Rails.application.reload_routes!
669
617
  end
670
618
 
671
619
  it "adds the action to a list" do
672
- expect(CatalogController.blacklight_config.show.document_actions).to have_key(:like)
620
+ expect(described_class.blacklight_config.show.document_actions).to have_key(:like)
673
621
  end
674
622
 
675
623
  it "defines the action method" do
676
- expect(controller.respond_to?(:like)).to be true
624
+ expect(controller).to respond_to(:like)
677
625
  end
678
626
 
679
627
  describe "when posting to the action" do
680
- describe "with success" do
681
- before do
682
- allow(controller).to receive(:validate_like_params).and_return(true)
683
- post :like
684
- end
628
+ context 'with valid params' do
685
629
  it "calls the supplied method on post" do
686
- expect(controller).to have_received(:perform_like)
630
+ expect(controller).to receive(:validate_like_params).and_return(true)
631
+ expect(controller).to receive(:perform_like)
632
+ post :like
687
633
  end
688
634
  end
689
635
 
690
- describe "with failure" do
691
- describe "with invalid params" do
692
- before { allow(controller).to receive(:validate_like_params).and_return(false) }
693
- it "does not call the supplied method if validation failed" do
694
- expect(controller).not_to have_received(:perform_like)
695
- end
636
+ context "with failure on invalid params" do
637
+ it "does not call the supplied method" do
638
+ expect(controller).to receive(:validate_like_params).and_return(false)
639
+ expect(controller).not_to receive(:perform_like)
640
+ skip 'Clarify expectations on validator failure: 400? 500? Set a specific error key/msg? Render the same template anyway?'
641
+ post :like
696
642
  end
697
643
  end
698
644
  end
@@ -713,7 +659,6 @@ describe CatalogController do
713
659
  end
714
660
  end
715
661
 
716
-
717
662
  # there must be at least one facet, and each facet must have at least one value
718
663
  def assert_facets_have_values(aggregations)
719
664
  expect(aggregations).to_not be_empty
@@ -129,6 +129,42 @@ describe CatalogHelper do
129
129
  end
130
130
  end
131
131
 
132
+ describe "rss_feed_link_tag" do
133
+ context "when an alternate scope is passed in" do
134
+ let(:my_engine) { double("Engine") }
135
+ let(:query_params) { { controller: 'catalog', action: 'index' } }
136
+ let(:config) { Blacklight::Configuration.new }
137
+ let(:search_state) { Blacklight::SearchState.new(query_params, config) }
138
+
139
+ it "calls url_for on the engine scope" do
140
+ allow(helper).to receive(:search_state).and_return search_state
141
+ expect(my_engine).to receive(:url_for).and_return(url_for(query_params))
142
+ tag = helper.rss_feed_link_tag(route_set: my_engine)
143
+ expect(tag).to match /title="RSS for results"/
144
+ expect(tag).to match /rel="alternate"/
145
+ expect(tag).to match %r{type="application/rss\+xml"}
146
+ end
147
+ end
148
+ end
149
+
150
+ describe "atom_feed_link_tag" do
151
+ context "when an alternate scope is passed in" do
152
+ let(:my_engine) { double("Engine") }
153
+ let(:query_params) { { controller: 'catalog', action: 'index' } }
154
+ let(:config) { Blacklight::Configuration.new }
155
+ let(:search_state) { Blacklight::SearchState.new(query_params, config) }
156
+
157
+ it "calls url_for on the engine scope" do
158
+ allow(helper).to receive(:search_state).and_return search_state
159
+ expect(my_engine).to receive(:url_for).and_return(url_for(query_params))
160
+ tag = helper.atom_feed_link_tag(route_set: my_engine)
161
+ expect(tag).to match /title="Atom for results"/
162
+ expect(tag).to match /rel="alternate"/
163
+ expect(tag).to match %r{type="application/atom\+xml"}
164
+ end
165
+ end
166
+ end
167
+
132
168
  describe "should_autofocus_on_search_box?" do
133
169
  it "is focused if we're on a catalog-like index page without query or facet parameters" do
134
170
  allow(helper).to receive_messages(controller: CatalogController.new, action_name: "index", has_search_parameters?: false)
@@ -68,7 +68,7 @@ describe "Blacklight::Configuration" do
68
68
 
69
69
  @config.index.respond_to.csv = { :layout => false }
70
70
 
71
- @config.index.respond_to.yaml = lambda { render text: "" }
71
+ @config.index.respond_to.yaml = lambda { render plain: "" }
72
72
 
73
73
  expect(@config.index.respond_to.keys).to eq [:xml, :csv, :yaml]
74
74
  end
@@ -1,38 +1,14 @@
1
1
  # Backport the Rails 5 controller test methods to Rails 4
2
2
  module BackportTest
3
- def delete(*args)
4
- (action, rest) = *args
5
- rest ||= {}
6
- if rest[:xhr]
7
- @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
3
+ [:delete, :get, :post, :put, :patch].each do |http_action|
4
+ define_method(http_action) do |*args|
5
+ (action, rest) = *args
6
+ rest ||= {}
7
+ if rest[:xhr]
8
+ @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
9
+ @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
10
+ end
11
+ super(action, rest[:params])
8
12
  end
9
- super(action, rest[:params])
10
- end
11
-
12
- def get(*args)
13
- (action, rest) = *args
14
- rest ||= {}
15
- if rest[:xhr]
16
- @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
17
- end
18
- super(action, rest[:params])
19
- end
20
-
21
- def post(*args)
22
- (action, rest) = *args
23
- rest ||= {}
24
- if rest[:xhr]
25
- @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
26
- end
27
- super(action, rest[:params])
28
- end
29
-
30
- def put(*args)
31
- (action, rest) = *args
32
- rest ||= {}
33
- if rest[:xhr]
34
- @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
35
- end
36
- super(action, rest[:params])
37
13
  end
38
14
  end
data/template.demo.rb CHANGED
@@ -1,4 +1,3 @@
1
- # frozen_string_literal: true
2
1
  gem "blacklight", ">= 6.1"
3
2
  gem "jettywrapper", ">= 2.0"
4
3
  gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blacklight
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.4.2
4
+ version: 6.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Rochkind
@@ -17,7 +17,7 @@ authors:
17
17
  autorequire:
18
18
  bindir: exe
19
19
  cert_chain: []
20
- date: 2016-08-15 00:00:00.000000000 Z
20
+ date: 2016-08-22 00:00:00.000000000 Z
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
23
  name: rails
@@ -233,14 +233,14 @@ dependencies:
233
233
  requirements:
234
234
  - - "~>"
235
235
  - !ruby/object:Gem::Version
236
- version: 0.8.0
236
+ version: '0.10'
237
237
  type: :development
238
238
  prerelease: false
239
239
  version_requirements: !ruby/object:Gem::Requirement
240
240
  requirements:
241
241
  - - "~>"
242
242
  - !ruby/object:Gem::Version
243
- version: 0.8.0
243
+ version: '0.10'
244
244
  - !ruby/object:Gem::Dependency
245
245
  name: equivalent-xml
246
246
  requirement: !ruby/object:Gem::Requirement