blacklight 7.22.2 → 7.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +29 -8
- data/VERSION +1 -1
- data/app/assets/stylesheets/blacklight/_facets.scss +6 -0
- data/app/components/blacklight/advanced_search_form_component.rb +5 -5
- data/app/components/blacklight/constraints_component.html.erb +8 -4
- data/app/components/blacklight/constraints_component.rb +43 -18
- data/app/components/blacklight/document/action_component.html.erb +1 -1
- data/app/components/blacklight/document/action_component.rb +10 -3
- data/app/components/blacklight/document/bookmark_component.rb +2 -2
- data/app/components/blacklight/document/citation_component.rb +1 -1
- data/app/components/blacklight/document/group_component.html.erb +1 -1
- data/app/components/blacklight/document/group_component.rb +2 -2
- data/app/components/blacklight/document/more_like_this_component.html.erb +1 -1
- data/app/components/blacklight/document/more_like_this_component.rb +1 -1
- data/app/components/blacklight/document/thumbnail_component.rb +1 -1
- data/app/components/blacklight/document_component.rb +2 -2
- data/app/components/blacklight/document_title_component.rb +3 -3
- data/app/components/blacklight/facet_field_checkboxes_component.rb +1 -1
- data/app/components/blacklight/facet_field_inclusive_constraint_component.html.erb +1 -1
- data/app/components/blacklight/facet_field_inclusive_constraint_component.rb +1 -1
- data/app/components/blacklight/facet_field_list_component.html.erb +1 -1
- data/app/components/blacklight/facet_field_list_component.rb +1 -1
- data/app/components/blacklight/facet_field_pagination_component.html.erb +4 -4
- data/app/components/blacklight/facet_item_component.rb +2 -2
- data/app/components/blacklight/facet_item_pivot_component.rb +2 -2
- data/app/components/blacklight/metadata_field_component.rb +2 -2
- data/app/components/blacklight/response/facet_group_component.html.erb +1 -1
- data/app/components/blacklight/response/facet_group_component.rb +1 -1
- data/app/components/blacklight/response/pagination_component.rb +1 -1
- data/app/components/blacklight/response/sort_component.html.erb +1 -1
- data/app/components/blacklight/response/spellcheck_component.rb +14 -3
- data/app/components/blacklight/response/view_type_button_component.rb +3 -3
- data/app/components/blacklight/response/view_type_component.rb +1 -1
- data/app/components/blacklight/search_bar_component.rb +2 -2
- data/app/components/blacklight/search_context_component.rb +3 -3
- data/app/components/blacklight/search_history_constraint_layout_component.rb +14 -0
- data/app/components/blacklight/start_over_button_component.rb +20 -0
- data/app/components/blacklight/system/dropdown_component.rb +1 -1
- data/app/controllers/concerns/blacklight/bookmarks.rb +1 -1
- data/app/controllers/concerns/blacklight/catalog.rb +2 -2
- data/app/controllers/concerns/blacklight/search_context.rb +1 -1
- data/app/helpers/blacklight/blacklight_helper_behavior.rb +12 -4
- data/app/helpers/blacklight/catalog_helper_behavior.rb +18 -7
- data/app/helpers/blacklight/render_partials_helper_behavior.rb +12 -1
- data/app/helpers/blacklight/search_history_constraints_helper_behavior.rb +30 -2
- data/app/helpers/blacklight/url_helper_behavior.rb +3 -1
- data/app/javascript/blacklight/modal.js +2 -2
- data/app/models/concerns/blacklight/configurable.rb +1 -1
- data/app/models/concerns/blacklight/document/active_model_shim.rb +1 -1
- data/app/models/concerns/blacklight/document/extensions.rb +1 -1
- data/app/models/concerns/blacklight/document/semantic_fields.rb +1 -1
- data/app/models/concerns/blacklight/document.rb +1 -1
- data/app/views/catalog/_email_form.html.erb +1 -1
- data/app/views/catalog/_search_results.html.erb +1 -1
- data/app/views/catalog/_sms_form.html.erb +3 -3
- data/app/views/catalog/_start_over.html.erb +1 -1
- data/app/views/layouts/blacklight/base.html.erb +1 -0
- data/blacklight.gemspec +3 -4
- data/lib/blacklight/configuration/fields.rb +1 -1
- data/lib/blacklight/configuration.rb +2 -1
- data/lib/blacklight/deprecations/engine_configuration.rb +66 -0
- data/lib/blacklight/engine.rb +21 -10
- data/lib/blacklight/exceptions.rb +3 -0
- data/lib/blacklight/search_state/filter_field.rb +4 -4
- data/lib/blacklight/solr/repository.rb +36 -12
- data/lib/blacklight/solr/search_builder_behavior.rb +1 -4
- data/lib/generators/blacklight/assets_generator.rb +14 -10
- data/spec/components/blacklight/constraints_component_spec.rb +68 -0
- data/spec/components/blacklight/document/action_component_spec.rb +2 -1
- data/spec/components/blacklight/document_component_spec.rb +1 -1
- data/spec/components/blacklight/response/spellcheck_component_spec.rb +73 -0
- data/spec/components/blacklight/start_over_button_component_spec.rb +38 -0
- data/spec/controllers/catalog_controller_spec.rb +1 -1
- data/spec/features/did_you_mean_spec.rb +21 -0
- data/spec/features/search_context_spec.rb +3 -1
- data/spec/helpers/blacklight/search_history_constraints_helper_behavior_spec.rb +2 -0
- data/spec/helpers/blacklight/url_helper_behavior_spec.rb +3 -3
- data/spec/helpers/blacklight_helper_spec.rb +8 -3
- data/spec/helpers/catalog_helper_spec.rb +6 -2
- data/spec/lib/blacklight/engine_spec.rb +41 -0
- data/spec/models/blacklight/facet_paginator_spec.rb +60 -15
- data/spec/models/blacklight/solr/repository_spec.rb +29 -21
- data/spec/models/blacklight/solr/response/facets_spec.rb +48 -10
- data/spec/presenters/blacklight/facet_item_presenter_spec.rb +1 -1
- data/spec/presenters/blacklight/field_presenter_spec.rb +2 -2
- data/spec/routing/search_history_spec.rb +9 -0
- data/spec/services/blacklight/search_service_spec.rb +8 -0
- data/spec/spec_helper.rb +2 -3
- data/spec/support/controller_level_helpers.rb +8 -0
- data/spec/views/catalog/_constraints.html.erb_spec.rb +1 -1
- data/spec/views/catalog/_index.html.erb_spec.rb +1 -1
- data/spec/views/catalog/_show.html.erb_spec.rb +1 -1
- data/spec/views/catalog/_show_sidebar.erb_spec.rb +1 -1
- data/spec/views/catalog/facet.json.jbuilder_spec.rb +1 -1
- data/spec/views/catalog/index.atom.builder_spec.rb +1 -0
- data/spec/views/catalog/index.html.erb_spec.rb +1 -0
- data/spec/views/catalog/index.json.jbuilder_spec.rb +1 -1
- data/spec/views/catalog/show.json.jbuilder_spec.rb +1 -1
- metadata +21 -22
data/lib/blacklight/engine.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require '
|
2
|
+
require 'blacklight/deprecations/engine_configuration'
|
3
|
+
require 'view_component'
|
3
4
|
|
4
5
|
module Blacklight
|
5
6
|
class Engine < Rails::Engine
|
@@ -22,14 +23,18 @@ module Blacklight
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
initializer "blacklight.assets.precompile" do
|
26
|
+
initializer "blacklight.assets.precompile" do
|
27
|
+
PRECOMPILE_ASSETS = %w(favicon.ico blacklight/blacklight.js blacklight/blacklight.js.map).freeze
|
28
|
+
|
26
29
|
# When Rails has been generated in API mode, it does not have sprockets available
|
27
|
-
if
|
28
|
-
|
30
|
+
if Rails.application.config.respond_to?(:assets)
|
31
|
+
Rails.application.config.assets.precompile += PRECOMPILE_ASSETS
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
32
|
-
|
35
|
+
bl_global_config = OpenStructWithHashAccess.new
|
36
|
+
|
37
|
+
bl_global_config.sms_mappings = {
|
33
38
|
'Virgin' => 'vmobl.com',
|
34
39
|
'AT&T' => 'txt.att.net',
|
35
40
|
'Verizon' => 'vtext.com',
|
@@ -41,14 +46,20 @@ module Blacklight
|
|
41
46
|
'Google Fi' => 'msg.fi.google.com'
|
42
47
|
}
|
43
48
|
|
44
|
-
|
49
|
+
bl_global_config.bookmarks_http_method = :post
|
45
50
|
|
46
|
-
|
51
|
+
bl_global_config.email_regexp = defined?(Devise) ? Devise.email_regexp : /\A[^@\s]+@[^@\s]+\z/
|
47
52
|
|
48
|
-
|
53
|
+
bl_global_config.facet_missing_param = '[* TO *]'
|
49
54
|
|
50
|
-
config
|
55
|
+
# Anything that goes into Blacklight::Engine.config is stored as a class
|
56
|
+
# variable on Railtie::Configuration. we're going to encapsulate all the
|
57
|
+
# Blacklight specific stuff in this single struct:
|
58
|
+
Blacklight::Engine.config.blacklight = bl_global_config
|
51
59
|
|
52
|
-
|
60
|
+
# Deprecate top-level access to legacy engine configuration
|
61
|
+
Blacklight::Deprecations::EngineConfiguration.deprecate_in(Blacklight::Engine.config)
|
62
|
+
|
63
|
+
config.action_dispatch.rescue_responses["Blacklight::Exceptions::RecordNotFound"] = :not_found
|
53
64
|
end
|
54
65
|
end
|
@@ -46,7 +46,7 @@ module Blacklight
|
|
46
46
|
|
47
47
|
if value == Blacklight::SearchState::FilterField::MISSING
|
48
48
|
url_key = "-#{key}"
|
49
|
-
value = Blacklight::Engine.config.facet_missing_param
|
49
|
+
value = Blacklight::Engine.config.blacklight.facet_missing_param
|
50
50
|
end
|
51
51
|
|
52
52
|
param = :f_inclusive if value.is_a?(Array)
|
@@ -82,7 +82,7 @@ module Blacklight
|
|
82
82
|
|
83
83
|
if value == Blacklight::SearchState::FilterField::MISSING
|
84
84
|
url_key = "-#{key}"
|
85
|
-
value = Blacklight::Engine.config.facet_missing_param
|
85
|
+
value = Blacklight::Engine.config.blacklight.facet_missing_param
|
86
86
|
end
|
87
87
|
|
88
88
|
param = :f_inclusive if value.is_a?(Array)
|
@@ -114,7 +114,7 @@ module Blacklight
|
|
114
114
|
params = search_state.params
|
115
115
|
f = Array(params.dig(:f, key))
|
116
116
|
f_inclusive = [params.dig(:f_inclusive, key)] if params.dig(:f_inclusive, key).present?
|
117
|
-
f_missing = [Blacklight::SearchState::FilterField::MISSING] if params.dig(:f, "-#{key}")&.any? { |v| v == Blacklight::Engine.config.facet_missing_param }
|
117
|
+
f_missing = [Blacklight::SearchState::FilterField::MISSING] if params.dig(:f, "-#{key}")&.any? { |v| v == Blacklight::Engine.config.blacklight.facet_missing_param }
|
118
118
|
|
119
119
|
f + (f_inclusive || []) + (f_missing || [])
|
120
120
|
end
|
@@ -133,7 +133,7 @@ module Blacklight
|
|
133
133
|
if value.is_a?(Array)
|
134
134
|
(params.dig(:f_inclusive, key) || []).to_set == value.to_set
|
135
135
|
elsif value == Blacklight::SearchState::FilterField::MISSING
|
136
|
-
(params.dig(:f, "-#{key}") || []).include?(Blacklight::Engine.config.facet_missing_param)
|
136
|
+
(params.dig(:f, "-#{key}") || []).include?(Blacklight::Engine.config.blacklight.facet_missing_param)
|
137
137
|
else
|
138
138
|
(params.dig(:f, key) || []).include?(value)
|
139
139
|
end
|
@@ -58,30 +58,40 @@ module Blacklight::Solr
|
|
58
58
|
# @return [Blacklight::Solr::Response] the solr response object
|
59
59
|
def send_and_receive(path, solr_params = {})
|
60
60
|
benchmark("Solr fetch", level: :debug) do
|
61
|
-
res =
|
62
|
-
connection.send_and_receive(
|
63
|
-
path,
|
64
|
-
data: { params: solr_params.to_hash.except(:json) }.merge(solr_params[:json]).to_json,
|
65
|
-
method: :post,
|
66
|
-
headers: { 'Content-Type' => 'application/json' }
|
67
|
-
)
|
68
|
-
else
|
69
|
-
key = blacklight_config.http_method == :post ? :data : :params
|
70
|
-
connection.send_and_receive(path, { key => solr_params.to_hash, method: blacklight_config.http_method })
|
71
|
-
end
|
72
|
-
|
61
|
+
res = connection.send_and_receive(path, build_solr_request(solr_params))
|
73
62
|
solr_response = blacklight_config.response_model.new(res, solr_params, document_model: blacklight_config.document_model, blacklight_config: blacklight_config)
|
74
63
|
|
75
64
|
Blacklight.logger&.debug("Solr query: #{blacklight_config.http_method} #{path} #{solr_params.to_hash.inspect}")
|
76
65
|
Blacklight.logger&.debug("Solr response: #{solr_response.inspect}") if defined?(::BLACKLIGHT_VERBOSE_LOGGING) && ::BLACKLIGHT_VERBOSE_LOGGING
|
77
66
|
solr_response
|
78
67
|
end
|
68
|
+
rescue *defined_rsolr_timeout_exceptions => e
|
69
|
+
raise Blacklight::Exceptions::RepositoryTimeout, "Timeout connecting to Solr instance using #{connection.inspect}: #{e.inspect}"
|
79
70
|
rescue Errno::ECONNREFUSED => e
|
71
|
+
# intended for and likely to be a RSolr::Error:ConnectionRefused, specifically.
|
80
72
|
raise Blacklight::Exceptions::ECONNREFUSED, "Unable to connect to Solr instance using #{connection.inspect}: #{e.inspect}"
|
81
73
|
rescue RSolr::Error::Http => e
|
82
74
|
raise Blacklight::Exceptions::InvalidRequest, e.message
|
83
75
|
end
|
84
76
|
|
77
|
+
# @return [Hash]
|
78
|
+
# @!visibility private
|
79
|
+
def build_solr_request(solr_params)
|
80
|
+
if solr_params[:json].present?
|
81
|
+
{
|
82
|
+
data: { params: solr_params.to_hash.except(:json) }.merge(solr_params[:json]).to_json,
|
83
|
+
method: :post,
|
84
|
+
headers: { 'Content-Type' => 'application/json' }
|
85
|
+
}
|
86
|
+
else
|
87
|
+
key = blacklight_config.http_method == :post ? :data : :params
|
88
|
+
{
|
89
|
+
key => solr_params.to_hash,
|
90
|
+
method: blacklight_config.http_method
|
91
|
+
}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
85
95
|
private
|
86
96
|
|
87
97
|
##
|
@@ -97,5 +107,19 @@ module Blacklight::Solr
|
|
97
107
|
def build_connection
|
98
108
|
RSolr.connect(connection_config.merge(adapter: connection_config[:http_adapter]))
|
99
109
|
end
|
110
|
+
|
111
|
+
# RSolr 2.4.0+ has a RSolr::Error::Timeout that we'd like to treat specially
|
112
|
+
# instead of lumping into RSolr::Error::Http. Before that we can not rescue
|
113
|
+
# specially, so return an empty array.
|
114
|
+
#
|
115
|
+
# @return [Array<Exception>] that can be used, with a splat, as argument
|
116
|
+
# to a ruby rescue
|
117
|
+
def defined_rsolr_timeout_exceptions
|
118
|
+
if defined?(RSolr::Error::Timeout)
|
119
|
+
[RSolr::Error::Timeout]
|
120
|
+
else
|
121
|
+
[]
|
122
|
+
end
|
123
|
+
end
|
100
124
|
end
|
101
125
|
end
|
@@ -355,10 +355,7 @@ module Blacklight::Solr
|
|
355
355
|
solr_field ||= facet_field
|
356
356
|
|
357
357
|
local_params = []
|
358
|
-
|
359
|
-
if use_local_params
|
360
|
-
local_params << "tag=#{facet_config.tag}" if facet_config && facet_config.tag
|
361
|
-
end
|
358
|
+
local_params << "tag=#{facet_config.tag}" if use_local_params && facet_config && facet_config.tag
|
362
359
|
|
363
360
|
if facet_config && facet_config.query
|
364
361
|
if facet_config.query[value]
|
@@ -11,15 +11,21 @@ module Blacklight
|
|
11
11
|
gem 'twitter-typeahead-rails', '0.11.1.pre.corejavascript'
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
def appease_rails7
|
15
|
+
return unless Rails.version > '7'
|
16
|
+
|
17
|
+
gem "sassc-rails", "~> 2.1"
|
17
18
|
|
19
|
+
remove_file 'app/javascript/application.js'
|
20
|
+
end
|
21
|
+
|
22
|
+
# Add sprockets javascript
|
23
|
+
def create_sprockets_javascript
|
18
24
|
create_file 'app/assets/javascripts/application.js' do
|
19
25
|
<<~CONTENT
|
20
26
|
//= require jquery3
|
21
27
|
//= require rails-ujs
|
22
|
-
//= require turbolinks
|
28
|
+
#{'//= require turbolinks' if Rails.version < '7'}
|
23
29
|
CONTENT
|
24
30
|
end
|
25
31
|
end
|
@@ -40,6 +46,7 @@ module Blacklight
|
|
40
46
|
# Ensure this method is idempotent
|
41
47
|
return if has_blacklight_assets?
|
42
48
|
|
49
|
+
gem 'jquery-rails'
|
43
50
|
contents = "\n//\n// Required by Blacklight\n"
|
44
51
|
contents += "//= require popper\n"
|
45
52
|
contents += "// Twitter Typeahead for autocomplete\n"
|
@@ -62,11 +69,6 @@ module Blacklight
|
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
65
|
-
# This is not a default in Rails 5.1+
|
66
|
-
def add_jquery
|
67
|
-
gem 'jquery-rails'
|
68
|
-
end
|
69
|
-
|
70
72
|
private
|
71
73
|
|
72
74
|
def turbolinks?
|
@@ -78,7 +80,9 @@ module Blacklight
|
|
78
80
|
end
|
79
81
|
|
80
82
|
def application_js
|
81
|
-
|
83
|
+
path = File.expand_path("app/assets/javascripts/application.js", destination_root)
|
84
|
+
|
85
|
+
File.exist?(path) ? File.read(path) : ''
|
82
86
|
end
|
83
87
|
end
|
84
88
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Blacklight::ConstraintsComponent, type: :component do
|
6
|
+
subject(:component) { described_class.new(**params) }
|
7
|
+
|
8
|
+
let(:rendered) { render_inline_to_capybara_node(component) }
|
9
|
+
|
10
|
+
let(:params) do
|
11
|
+
{ search_state: search_state }
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:blacklight_config) do
|
15
|
+
Blacklight::Configuration.new.tap do |config|
|
16
|
+
config.add_facet_field 'some_facet'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:search_state) { Blacklight::SearchState.new(query_params.with_indifferent_access, blacklight_config) }
|
21
|
+
let(:query_params) { {} }
|
22
|
+
|
23
|
+
context 'with a query' do
|
24
|
+
let(:query_params) { { q: 'some query' } }
|
25
|
+
|
26
|
+
it 'renders a start-over link' do
|
27
|
+
expect(rendered).to have_link 'Start Over', href: '/catalog'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'has a header' do
|
31
|
+
expect(rendered).to have_selector('h2', text: 'Search Constraints')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'wraps the output in a div' do
|
35
|
+
expect(rendered).to have_selector('div#appliedParams')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'renders the query' do
|
39
|
+
expect(rendered).to have_selector('.applied-filter.constraint', text: 'some query')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'with a facet' do
|
44
|
+
let(:query_params) { { f: { some_facet: ['some value'] } } }
|
45
|
+
|
46
|
+
it 'renders the query' do
|
47
|
+
expect(rendered).to have_selector('.constraint-value > .filter-name', text: 'Some Facet').and(have_selector('.constraint-value > .filter-value', text: 'some value'))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.for_search_history' do
|
52
|
+
subject(:component) { described_class.for_search_history(**params) }
|
53
|
+
|
54
|
+
let(:query_params) { { q: 'some query', f: { some_facet: ['some value'] } } }
|
55
|
+
|
56
|
+
it 'wraps the output in a span' do
|
57
|
+
expect(rendered).to have_selector('span .constraint')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'renders the search state as lightly-decorated text' do
|
61
|
+
expect(rendered).to have_selector('.constraint > .filter-values', text: 'some query').and(have_selector('.constraint', text: 'Some Facet:some value'))
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'omits the headers' do
|
65
|
+
expect(rendered).not_to have_selector('h2', text: 'Search Constraints')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -24,10 +24,11 @@ RSpec.describe Blacklight::Document::ActionComponent, type: :component do
|
|
24
24
|
|
25
25
|
it 'renders an action link' do
|
26
26
|
if Rails.version >= '6'
|
27
|
-
allow(view_context).to receive(:some_tool_solr_document_path).with(document, only_path: true).and_return('/asdf')
|
27
|
+
allow(view_context).to receive(:some_tool_solr_document_path).with(document, { only_path: true }).and_return('/asdf')
|
28
28
|
else
|
29
29
|
allow(view_context).to receive(:some_tool_solr_document_path).with(document).and_return('/asdf')
|
30
30
|
end
|
31
|
+
|
31
32
|
expect(rendered).to have_link 'Some tool', href: '/asdf'
|
32
33
|
end
|
33
34
|
|
@@ -28,7 +28,7 @@ RSpec.describe Blacklight::DocumentComponent, type: :component do
|
|
28
28
|
CatalogController.blacklight_config.deep_copy.tap do |config|
|
29
29
|
config.track_search_session = false
|
30
30
|
config.index.thumbnail_field = 'thumbnail_path_ss'
|
31
|
-
config.index.document_actions[:bookmark].partial = '/catalog/bookmark_control
|
31
|
+
config.index.document_actions[:bookmark].partial = '/catalog/bookmark_control'
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Blacklight::Response::SpellcheckComponent, type: :component do
|
6
|
+
subject(:render) { render_inline(instance) }
|
7
|
+
|
8
|
+
let(:spellcheck_options) { nil }
|
9
|
+
let(:instance) { described_class.new(response: response, options: spellcheck_options) }
|
10
|
+
let(:config) do
|
11
|
+
Blacklight::Configuration.new do |config|
|
12
|
+
config.spell_max = 5
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
allow(controller).to receive(:blacklight_config).and_return(config)
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when there are many results' do
|
21
|
+
let(:response) { instance_double(Blacklight::Solr::Response, total: 10, spelling: double(words: [1], collation: nil)) }
|
22
|
+
|
23
|
+
it "does not show suggestions" do
|
24
|
+
expect(render.to_html).to be_blank
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when there are only a few results' do
|
29
|
+
let(:word_suggestion) { 'yoshida' }
|
30
|
+
let(:response) { instance_double(Blacklight::Solr::Response, total: 4, spelling: double(words: [word_suggestion], collation: nil)) }
|
31
|
+
|
32
|
+
it "shows suggestions" do
|
33
|
+
expect(render.to_html).to include(word_suggestion)
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'and explicit spellcheck options' do
|
37
|
+
let(:explicit_option) { 'explicit option' }
|
38
|
+
let(:spellcheck_options) { [explicit_option] }
|
39
|
+
|
40
|
+
it "shows only explicit suggestions" do
|
41
|
+
expect(render.to_html).to include(explicit_option)
|
42
|
+
expect(render.to_html).not_to include(word_suggestion)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'and collations are present' do
|
47
|
+
let(:word_suggestion) { 'donotuse' }
|
48
|
+
let(:collated_suggestion) { 'yoshida Hajime' }
|
49
|
+
let(:response) { instance_double(Blacklight::Solr::Response, total: 4, spelling: double(words: [word_suggestion], collation: collated_suggestion)) }
|
50
|
+
|
51
|
+
it "shows only collated suggestions" do
|
52
|
+
expect(render.to_html).to include(collated_suggestion)
|
53
|
+
expect(render.to_html).not_to include(word_suggestion)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when there are no spelling suggestions' do
|
59
|
+
let(:response) { instance_double(Blacklight::Solr::Response, total: 4, spelling: double(words: [], collation: nil)) }
|
60
|
+
|
61
|
+
it "does not show suggestions" do
|
62
|
+
expect(render.to_html).to be_blank
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when spelling is not available' do
|
67
|
+
let(:response) { instance_double(Blacklight::Solr::Response, total: 4, spelling: nil) }
|
68
|
+
|
69
|
+
it "does not show suggestions" do
|
70
|
+
expect(render.to_html).to be_blank
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Blacklight::StartOverButtonComponent, type: :component do
|
6
|
+
subject(:render) { render_inline(instance) }
|
7
|
+
|
8
|
+
let(:instance) { described_class.new }
|
9
|
+
let(:blacklight_config) do
|
10
|
+
Blacklight::Configuration.new.configure do |config|
|
11
|
+
config.view = { list: nil, abc: nil }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
before do
|
16
|
+
allow(controller).to receive(:blacklight_config).and_return(blacklight_config)
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with the current view type' do
|
20
|
+
before do
|
21
|
+
controller.params[:view] = 'abc'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'is the catalog path' do
|
25
|
+
expect(render.css('a').first['href']).to eq '/catalog?view=abc'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when the current view type is the default' do
|
30
|
+
before do
|
31
|
+
controller.params[:view] = 'list'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'does not include the current view type' do
|
35
|
+
expect(render.css('a').first['href']).to eq '/catalog'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -788,7 +788,7 @@ RSpec.describe CatalogController, api: true do
|
|
788
788
|
describe "#add_show_tools_partial", api: false do
|
789
789
|
before do
|
790
790
|
described_class.blacklight_config.add_show_tools_partial(:like, callback: :perform_like, validator: :validate_like_params)
|
791
|
-
allow(controller).to receive(:solr_document_url).and_return('catalog/1')
|
791
|
+
allow(controller).to receive(:solr_document_url).and_return('http://test.host/catalog/1')
|
792
792
|
allow(controller).to receive(:action_documents).and_return(1)
|
793
793
|
Rails.application.routes.draw do
|
794
794
|
get 'catalog/like', as: :catalog_like
|
@@ -127,4 +127,25 @@ RSpec.describe "Did You Mean" do
|
|
127
127
|
click_button 'search'
|
128
128
|
expect(page).to have_content("Did you mean")
|
129
129
|
end
|
130
|
+
|
131
|
+
context 'spellcheck collations are enabled' do
|
132
|
+
before do
|
133
|
+
CatalogController.blacklight_config[:default_solr_params]["spellcheck.collate"] = true
|
134
|
+
end
|
135
|
+
|
136
|
+
after do
|
137
|
+
CatalogController.blacklight_config[:default_solr_params].delete("spellcheck.collate")
|
138
|
+
end
|
139
|
+
|
140
|
+
it "shows suggestions if there aren't many hits" do
|
141
|
+
fill_in "q", with: 'Yoshido Hajime'
|
142
|
+
click_button 'search'
|
143
|
+
|
144
|
+
expect(page).to have_content("Did you mean")
|
145
|
+
click_link 'yoshida Hajime'
|
146
|
+
within ("#sortAndPerPage") do
|
147
|
+
expect(page).to have_content "1 - 2 of 2"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
130
151
|
end
|
@@ -3,13 +3,14 @@
|
|
3
3
|
RSpec.describe "Search Results context", js: true do
|
4
4
|
it "passes the current search id through" do
|
5
5
|
search_for ''
|
6
|
-
search_id = Search.last.id.to_s
|
7
6
|
click_on 'Pluvial nectar of blessings'
|
7
|
+
search_id = Search.last.id.to_s
|
8
8
|
expect(page).to have_content "« Previous | 10 of 30 | Next »"
|
9
9
|
prev = page.find(".pagination-search-widgets .previous")
|
10
10
|
expect(prev['data-context-href']).to eq "/catalog/2003546302/track?counter=9&document_id=2003546302&search_id=#{search_id}"
|
11
11
|
|
12
12
|
click_on "« Previous"
|
13
|
+
expect(page).to have_content "U21.2 .W85 2003"
|
13
14
|
|
14
15
|
prev = page.find(".pagination-search-widgets .previous")
|
15
16
|
expect(prev['data-context-href']).to eq "/catalog/2004310986/track?counter=8&document_id=2004310986&search_id=#{search_id}"
|
@@ -48,6 +49,7 @@ RSpec.describe "Search Results context", js: true do
|
|
48
49
|
find_all('.index_title a').last.click
|
49
50
|
click_on "Next »"
|
50
51
|
|
52
|
+
expect(page).to have_content "Naqdī barā-yi tamām-i"
|
51
53
|
click_on "Back to Search"
|
52
54
|
expect(page).to have_content "11 - 20"
|
53
55
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe Blacklight::SearchHistoryConstraintsHelperBehavior do
|
4
|
+
around { |test| Deprecation.silence(described_class) { test.call } }
|
5
|
+
|
4
6
|
before(:all) do
|
5
7
|
@config = Blacklight::Configuration.new do |config|
|
6
8
|
config.add_search_field 'default_search_field', label: 'Default'
|
@@ -133,7 +133,7 @@ RSpec.describe Blacklight::UrlHelperBehavior do
|
|
133
133
|
|
134
134
|
it "calls url_for on the engine scope" do
|
135
135
|
expect(my_engine).to receive(:url_for)
|
136
|
-
.with(q: "query", f: "facets", controller: "catalog")
|
136
|
+
.with({ q: "query", f: "facets", controller: "catalog" })
|
137
137
|
.and_return('link-url')
|
138
138
|
expect(tag).to match /Back to Search/
|
139
139
|
expect(tag).to match /link-url/
|
@@ -292,12 +292,12 @@ RSpec.describe Blacklight::UrlHelperBehavior do
|
|
292
292
|
let(:document) { SolrDocument.new(id: 1) }
|
293
293
|
|
294
294
|
it "determines the correct route for the document class" do
|
295
|
-
allow(helper.main_app).to receive(:track_test_path).with(id: have_attributes(id: 1)).and_return('x')
|
295
|
+
allow(helper.main_app).to receive(:track_test_path).with({ id: have_attributes(id: 1) }).and_return('x')
|
296
296
|
expect(helper.session_tracking_path(document)).to eq 'x'
|
297
297
|
end
|
298
298
|
|
299
299
|
it "passes through tracking parameters" do
|
300
|
-
allow(helper.main_app).to receive(:track_test_path).with(id: have_attributes(id: 1), x: 1).and_return('x')
|
300
|
+
allow(helper.main_app).to receive(:track_test_path).with({ id: have_attributes(id: 1), x: 1 }).and_return('x')
|
301
301
|
expect(helper.session_tracking_path(document, x: 1)).to eq 'x'
|
302
302
|
end
|
303
303
|
|
@@ -82,7 +82,7 @@ RSpec.describe BlacklightHelper do
|
|
82
82
|
end
|
83
83
|
|
84
84
|
it "sends parameters" do
|
85
|
-
expect(presenter).to receive(:link_rel_alternates).with(unique: true).and_return(result)
|
85
|
+
expect(presenter).to receive(:link_rel_alternates).with({ unique: true }).and_return(result)
|
86
86
|
expect(helper.render_link_rel_alternates(document, unique: true)).to eq result
|
87
87
|
end
|
88
88
|
end
|
@@ -264,8 +264,13 @@ RSpec.describe BlacklightHelper do
|
|
264
264
|
expect(helper.should_show_spellcheck_suggestions?(response)).to be true
|
265
265
|
end
|
266
266
|
|
267
|
+
it "only shows suggestions from collations" do
|
268
|
+
response = double(total: 4, spelling: double(words: [], collation: { blah: 1 }))
|
269
|
+
expect(helper.should_show_spellcheck_suggestions?(response)).to be true
|
270
|
+
end
|
271
|
+
|
267
272
|
it "shows suggestions only if there are spelling suggestions available" do
|
268
|
-
response = double(total: 4, spelling: double(words: []))
|
273
|
+
response = double(total: 4, spelling: double(words: [], collation: nil))
|
269
274
|
expect(helper.should_show_spellcheck_suggestions?(response)).to be false
|
270
275
|
end
|
271
276
|
|
@@ -298,7 +303,7 @@ RSpec.describe BlacklightHelper do
|
|
298
303
|
describe "#render_document_index" do
|
299
304
|
it "renders the document index with the current view type" do
|
300
305
|
allow(helper).to receive_messages(document_index_view_type: :current_view)
|
301
|
-
allow(helper).to receive(:render_document_index_with_view).with(:current_view, [], a: 1, b: 2)
|
306
|
+
allow(helper).to receive(:render_document_index_with_view).with(:current_view, [], { a: 1, b: 2 })
|
302
307
|
helper.render_document_index [], a: 1, b: 2
|
303
308
|
end
|
304
309
|
end
|
@@ -369,7 +369,7 @@ RSpec.describe CatalogHelper do
|
|
369
369
|
end
|
370
370
|
|
371
371
|
describe "#render_search_to_page_title" do
|
372
|
-
subject { helper.render_search_to_page_title(params) }
|
372
|
+
subject { helper.render_search_to_page_title(Blacklight::SearchState.new(params, blacklight_config)) }
|
373
373
|
|
374
374
|
before do
|
375
375
|
allow(helper).to receive(:blacklight_config).and_return(blacklight_config)
|
@@ -377,7 +377,11 @@ RSpec.describe CatalogHelper do
|
|
377
377
|
allow(helper).to receive(:label_for_search_field).with(nil).and_return('')
|
378
378
|
end
|
379
379
|
|
380
|
-
let(:blacklight_config)
|
380
|
+
let(:blacklight_config) do
|
381
|
+
Blacklight::Configuration.new.tap do |config|
|
382
|
+
config.add_facet_field 'format'
|
383
|
+
end
|
384
|
+
end
|
381
385
|
|
382
386
|
context 'when the f param is an array' do
|
383
387
|
let(:params) { ActionController::Parameters.new(q: 'foobar', f: { format: ["Book"] }) }
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Blacklight::Engine do
|
4
|
+
[:bookmarks_http_method, :email_regexp, :facet_missing_param, :sms_mappings].each do |dep_key|
|
5
|
+
describe "config.#{dep_key}" do
|
6
|
+
subject { described_class.config }
|
7
|
+
|
8
|
+
let(:unlikely_value) { 'unlikely value' }
|
9
|
+
|
10
|
+
it 'is deprecated' do
|
11
|
+
allow(Deprecation).to receive(:warn)
|
12
|
+
subject.send(dep_key)
|
13
|
+
expect(Deprecation).to have_received(:warn)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'delegates to config.blacklight' do
|
17
|
+
allow(subject.blacklight).to receive(dep_key).and_return(unlikely_value)
|
18
|
+
expect(subject.send(dep_key)).to eql(unlikely_value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "config.#{dep_key}=" do
|
23
|
+
subject { described_class.config }
|
24
|
+
|
25
|
+
let(:unlikely_value) { 'unlikely value' }
|
26
|
+
|
27
|
+
it 'is deprecated' do
|
28
|
+
allow(Deprecation).to receive(:warn)
|
29
|
+
allow(subject.blacklight).to receive(:"#{dep_key}=").with(unlikely_value)
|
30
|
+
subject.send(:"#{dep_key}=", unlikely_value)
|
31
|
+
expect(Deprecation).to have_received(:warn)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'delegates to config.blacklight' do
|
35
|
+
allow(subject.blacklight).to receive(:"#{dep_key}=").with(unlikely_value)
|
36
|
+
subject.send(:"#{dep_key}=", unlikely_value)
|
37
|
+
expect(subject.blacklight).to have_received(:"#{dep_key}=").with(unlikely_value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|