blacklight 7.13.2 → 7.15.2
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 +4 -4
- data/.github/workflows/ruby.yml +23 -3
- data/README.md +0 -2
- data/VERSION +1 -1
- data/app/assets/javascripts/blacklight/blacklight.js +4 -2
- data/app/assets/stylesheets/blacklight/_header.scss +0 -5
- data/app/assets/stylesheets/blacklight/_icons.scss +5 -1
- data/app/assets/stylesheets/blacklight/blacklight_defaults.scss +5 -1
- data/app/components/blacklight/advanced_search_form_component.html.erb +46 -0
- data/app/components/blacklight/advanced_search_form_component.rb +75 -0
- data/app/components/blacklight/constraint_component.html.erb +1 -1
- data/app/components/blacklight/constraint_layout_component.html.erb +1 -1
- data/app/components/blacklight/constraints_component.rb +42 -17
- data/app/components/blacklight/document/thumbnail_component.html.erb +2 -2
- data/app/components/blacklight/document/thumbnail_component.rb +5 -2
- data/app/components/blacklight/document_component.rb +7 -2
- data/app/components/blacklight/document_metadata_component.rb +1 -1
- data/app/components/blacklight/facet_field_checkboxes_component.html.erb +23 -0
- data/app/components/blacklight/facet_field_checkboxes_component.rb +24 -0
- data/app/components/blacklight/facet_field_inclusive_constraint_component.html.erb +6 -0
- data/app/components/blacklight/facet_field_inclusive_constraint_component.rb +29 -0
- data/app/components/blacklight/facet_field_list_component.html.erb +1 -0
- data/app/components/blacklight/facet_field_pagination_component.rb +1 -1
- data/app/components/blacklight/facet_item_component.rb +4 -2
- data/app/components/blacklight/hidden_search_state_component.rb +54 -0
- data/app/components/blacklight/search_bar_component.html.erb +4 -0
- data/app/components/blacklight/search_bar_component.rb +4 -2
- data/app/controllers/concerns/blacklight/bookmarks.rb +1 -1
- data/app/controllers/concerns/blacklight/catalog.rb +6 -0
- data/app/helpers/blacklight/component_helper_behavior.rb +1 -1
- data/app/helpers/blacklight/configuration_helper_behavior.rb +2 -2
- data/app/helpers/blacklight/facets_helper_behavior.rb +1 -1
- data/app/helpers/blacklight/hash_as_hidden_fields_helper_behavior.rb +2 -38
- data/app/helpers/blacklight/icon_helper_behavior.rb +1 -1
- data/app/helpers/blacklight/render_constraints_helper_behavior.rb +2 -2
- data/app/javascript/blacklight/button_focus.js +1 -0
- data/app/javascript/blacklight/modal.js +10 -4
- data/app/models/concerns/blacklight/suggest/response.rb +1 -1
- data/app/presenters/blacklight/clause_presenter.rb +37 -0
- data/app/presenters/blacklight/document_presenter.rb +5 -1
- data/app/presenters/blacklight/facet_field_presenter.rb +4 -0
- data/app/presenters/blacklight/facet_grouped_item_presenter.rb +45 -0
- data/app/presenters/blacklight/facet_item_presenter.rb +32 -20
- data/app/presenters/blacklight/field_presenter.rb +1 -1
- data/app/presenters/blacklight/inclusive_facet_item_presenter.rb +16 -0
- data/app/presenters/blacklight/rendering/helper_method.rb +4 -4
- data/app/presenters/blacklight/search_bar_presenter.rb +4 -0
- data/app/views/bookmarks/_tools.html.erb +1 -1
- data/app/views/catalog/_advanced_search_form.html.erb +7 -0
- data/app/views/catalog/_advanced_search_help.html.erb +24 -0
- data/app/views/catalog/_search_form.html.erb +1 -0
- data/app/views/catalog/_zero_results.html.erb +1 -1
- data/app/views/catalog/advanced_search.html.erb +17 -0
- data/blacklight.gemspec +5 -4
- data/config/i18n-tasks.yml +1 -0
- data/config/locales/blacklight.en.yml +17 -0
- data/lib/blacklight/configuration.rb +2 -1
- data/lib/blacklight/configuration/field.rb +1 -1
- data/lib/blacklight/configuration/sort_field.rb +1 -1
- data/lib/blacklight/open_struct_with_hash_access.rb +18 -1
- data/lib/blacklight/routes/searchable.rb +1 -0
- data/lib/blacklight/search_builder.rb +2 -0
- data/lib/blacklight/search_state.rb +5 -1
- data/lib/blacklight/search_state/filter_field.rb +17 -7
- data/lib/blacklight/solr/repository.rb +11 -2
- data/lib/blacklight/solr/search_builder_behavior.rb +87 -23
- data/package.json +1 -1
- data/spec/components/blacklight/advanced_search_form_component_spec.rb +51 -0
- data/spec/components/blacklight/constraint_layout_component_spec.rb +1 -1
- data/spec/components/blacklight/document_component_spec.rb +17 -0
- data/spec/components/blacklight/facet_field_checkboxes_component_spec.rb +55 -0
- data/spec/components/blacklight/facet_field_list_component_spec.rb +39 -4
- data/spec/components/blacklight/hidden_search_state_component_spec.rb +24 -0
- data/spec/controllers/catalog_controller_spec.rb +9 -0
- data/spec/features/advanced_search_spec.rb +67 -0
- data/spec/features/bookmarks_spec.rb +1 -9
- data/spec/features/facets_spec.rb +2 -17
- data/spec/features/search_filters_spec.rb +0 -20
- data/spec/helpers/blacklight/hash_as_hidden_fields_behavior_spec.rb +1 -0
- data/spec/helpers/blacklight/url_helper_behavior_spec.rb +1 -0
- data/spec/lib/blacklight/open_struct_with_hash_access_spec.rb +8 -0
- data/spec/lib/blacklight/search_state/filter_field_spec.rb +65 -0
- data/spec/models/blacklight/solr/repository_spec.rb +12 -0
- data/spec/models/blacklight/solr/response/facets_spec.rb +1 -1
- data/spec/models/blacklight/solr/search_builder_spec.rb +28 -0
- data/spec/presenters/blacklight/clause_presenter_spec.rb +34 -0
- data/spec/presenters/blacklight/document_presenter_spec.rb +13 -0
- data/spec/presenters/blacklight/facet_grouped_item_presenter_spec.rb +41 -0
- data/spec/spec_helper.rb +8 -3
- data/spec/test_app_templates/Gemfile.extra +1 -1
- data/spec/views/catalog/_document.html.erb_spec.rb +1 -0
- data/spec/views/catalog/_thumbnail.html.erb_spec.rb +2 -0
- metadata +66 -27
|
@@ -58,8 +58,17 @@ 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
|
-
|
|
62
|
-
|
|
61
|
+
res = if solr_params[:json].present?
|
|
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
|
|
63
72
|
|
|
64
73
|
solr_response = blacklight_config.response_model.new(res, solr_params, document_model: blacklight_config.document_model, blacklight_config: blacklight_config)
|
|
65
74
|
|
|
@@ -8,7 +8,8 @@ module Blacklight::Solr
|
|
|
8
8
|
:default_solr_parameters, :add_query_to_solr, :add_facet_fq_to_solr,
|
|
9
9
|
:add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr,
|
|
10
10
|
:add_sorting_to_solr, :add_group_config_to_solr,
|
|
11
|
-
:add_facet_paging_to_solr
|
|
11
|
+
:add_facet_paging_to_solr, :add_adv_search_clauses,
|
|
12
|
+
:add_additional_filters
|
|
12
13
|
]
|
|
13
14
|
end
|
|
14
15
|
|
|
@@ -61,12 +62,62 @@ module Blacklight::Solr
|
|
|
61
62
|
elsif search_field&.solr_local_parameters.present?
|
|
62
63
|
add_search_field_with_local_parameters(solr_parameters)
|
|
63
64
|
elsif search_state.query_param.is_a? Hash
|
|
64
|
-
|
|
65
|
-
elsif
|
|
65
|
+
add_additional_filters(solr_parameters, search_state.query_param)
|
|
66
|
+
elsif search_state.query_param
|
|
66
67
|
solr_parameters[:q] = search_state.query_param
|
|
67
68
|
end
|
|
68
69
|
end
|
|
69
70
|
|
|
71
|
+
def add_additional_filters(solr_parameters, additional_filters = nil)
|
|
72
|
+
q = additional_filters || @additional_filters
|
|
73
|
+
|
|
74
|
+
return if q.blank?
|
|
75
|
+
|
|
76
|
+
solr_parameters[:q] = if q.values.any?(&:blank?)
|
|
77
|
+
# if any field parameters are empty, exclude _all_ results
|
|
78
|
+
"{!lucene}NOT *:*"
|
|
79
|
+
else
|
|
80
|
+
"{!lucene}" + q.map do |field, values|
|
|
81
|
+
"#{field}:(#{Array(values).map { |x| solr_param_quote(x) }.join(' OR ')})"
|
|
82
|
+
end.join(" AND ")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
solr_parameters[:defType] = 'lucene'
|
|
86
|
+
solr_parameters[:spellcheck] = 'false'
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Transform "clause" parameters into the Solr JSON Query DSL
|
|
90
|
+
def add_adv_search_clauses(solr_parameters)
|
|
91
|
+
return if search_state.clause_params.blank?
|
|
92
|
+
|
|
93
|
+
defaults = { must: [], must_not: [], should: [] }
|
|
94
|
+
bool_query = (solr_parameters.dig(:json, :query, :bool) || {}).reverse_merge(defaults)
|
|
95
|
+
|
|
96
|
+
default_op = blacklight_params[:op]&.to_sym || :must
|
|
97
|
+
|
|
98
|
+
search_state.clause_params.each_value do |clause|
|
|
99
|
+
op, query = adv_search_clause(clause, default_op)
|
|
100
|
+
bool_query[op] << query if defaults.key?(op) && query
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
return if bool_query.values.all?(&:blank?)
|
|
104
|
+
|
|
105
|
+
solr_parameters[:mm] = 1 if default_op == :should
|
|
106
|
+
solr_parameters[:json] ||= { query: { bool: {} } }
|
|
107
|
+
solr_parameters[:json][:query] ||= { bool: {} }
|
|
108
|
+
solr_parameters[:json][:query][:bool] = bool_query.reject { |_k, v| v.blank? }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @return [Array] the first element is the query operator and the second is the value to add
|
|
112
|
+
def adv_search_clause(clause, default_op)
|
|
113
|
+
op = clause[:op]&.to_sym || default_op
|
|
114
|
+
field = (blacklight_config.search_fields || {})[clause[:field]] if clause[:field]
|
|
115
|
+
|
|
116
|
+
return unless field&.clause_params && clause[:query].present?
|
|
117
|
+
|
|
118
|
+
[op, field.clause_params.transform_values { |v| v.merge(query: clause[:query]) }]
|
|
119
|
+
end
|
|
120
|
+
|
|
70
121
|
##
|
|
71
122
|
# Add any existing facet limits, stored in app-level HTTP query
|
|
72
123
|
# as :f, to solr as appropriate :fq query.
|
|
@@ -84,8 +135,13 @@ module Blacklight::Solr
|
|
|
84
135
|
solr_parameters.merge!(subqueries) if subqueries
|
|
85
136
|
else
|
|
86
137
|
filter.values.reject(&:blank?).each do |value|
|
|
87
|
-
filter_query, subqueries =
|
|
88
|
-
|
|
138
|
+
filter_query, subqueries = if value.is_a?(Array)
|
|
139
|
+
facet_inclusive_value_to_fq_string(filter.key, value.reject(&:blank?))
|
|
140
|
+
else
|
|
141
|
+
facet_value_to_fq_string(filter.config.key, value)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
solr_parameters.append_filter_query filter_query
|
|
89
145
|
solr_parameters.merge!(subqueries) if subqueries
|
|
90
146
|
end
|
|
91
147
|
end
|
|
@@ -250,16 +306,17 @@ module Blacklight::Solr
|
|
|
250
306
|
|
|
251
307
|
##
|
|
252
308
|
# Convert a facet/value pair into a solr fq parameter
|
|
253
|
-
def facet_value_to_fq_string(facet_field, value)
|
|
309
|
+
def facet_value_to_fq_string(facet_field, value, use_local_params: true)
|
|
254
310
|
facet_config = blacklight_config.facet_fields[facet_field]
|
|
255
311
|
|
|
256
312
|
solr_field = facet_config.field if facet_config && !facet_config.query
|
|
257
313
|
solr_field ||= facet_field
|
|
258
314
|
|
|
259
315
|
local_params = []
|
|
260
|
-
local_params << "tag=#{facet_config.tag}" if facet_config && facet_config.tag
|
|
261
316
|
|
|
262
|
-
|
|
317
|
+
if use_local_params
|
|
318
|
+
local_params << "tag=#{facet_config.tag}" if facet_config && facet_config.tag
|
|
319
|
+
end
|
|
263
320
|
|
|
264
321
|
if facet_config && facet_config.query
|
|
265
322
|
if facet_config.query[value]
|
|
@@ -269,12 +326,34 @@ module Blacklight::Solr
|
|
|
269
326
|
'-*:*'
|
|
270
327
|
end
|
|
271
328
|
elsif value.is_a?(Range)
|
|
329
|
+
prefix = "{!#{local_params.join(' ')}}" unless local_params.empty?
|
|
272
330
|
"#{prefix}#{solr_field}:[#{value.first} TO #{value.last}]"
|
|
273
331
|
else
|
|
274
332
|
"{!term f=#{solr_field}#{(' ' + local_params.join(' ')) unless local_params.empty?}}#{convert_to_term_value(value)}"
|
|
275
333
|
end
|
|
276
334
|
end
|
|
277
335
|
|
|
336
|
+
def facet_inclusive_value_to_fq_string(facet_field, values)
|
|
337
|
+
return if values.blank?
|
|
338
|
+
|
|
339
|
+
return facet_value_to_fq_string(facet_field, values.first) if values.length == 1
|
|
340
|
+
|
|
341
|
+
facet_config = blacklight_config.facet_fields[facet_field]
|
|
342
|
+
|
|
343
|
+
local_params = []
|
|
344
|
+
local_params << "tag=#{facet_config.tag}" if facet_config && facet_config.tag
|
|
345
|
+
|
|
346
|
+
solr_filters = values.each_with_object({}).with_index do |(v, h), index|
|
|
347
|
+
h["f_inclusive.#{facet_field}.#{index}"] = facet_value_to_fq_string(facet_field, v, use_local_params: false)
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
filter_query = solr_filters.keys.map do |k|
|
|
351
|
+
"{!query v=$#{k}}"
|
|
352
|
+
end.join(' OR ')
|
|
353
|
+
|
|
354
|
+
["{!lucene#{(' ' + local_params.join(' ')) unless local_params.empty?}}#{filter_query}", solr_filters]
|
|
355
|
+
end
|
|
356
|
+
|
|
278
357
|
def convert_to_term_value(value)
|
|
279
358
|
if value.is_a?(DateTime) || value.is_a?(Time)
|
|
280
359
|
value.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
@@ -322,20 +401,5 @@ module Blacklight::Solr
|
|
|
322
401
|
# params!
|
|
323
402
|
solr_parameters["spellcheck.q"] ||= search_state.query_param
|
|
324
403
|
end
|
|
325
|
-
|
|
326
|
-
def add_multifield_search_query(solr_parameters)
|
|
327
|
-
q = search_state.query_param
|
|
328
|
-
solr_parameters[:q] = if q.values.any?(&:blank?)
|
|
329
|
-
# if any field parameters are empty, exclude _all_ results
|
|
330
|
-
"{!lucene}NOT *:*"
|
|
331
|
-
else
|
|
332
|
-
"{!lucene}" + q.map do |field, values|
|
|
333
|
-
"#{field}:(#{Array(values).map { |x| solr_param_quote(x) }.join(' OR ')})"
|
|
334
|
-
end.join(" AND ")
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
solr_parameters[:defType] = 'lucene'
|
|
338
|
-
solr_parameters[:spellcheck] = 'false'
|
|
339
|
-
end
|
|
340
404
|
end
|
|
341
405
|
end
|
data/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blacklight-frontend",
|
|
3
3
|
"version": "7.10.0",
|
|
4
|
-
"description": "[](https://travis-ci.com/projectblacklight/blacklight) [](http://badge.fury.io/rb/blacklight) [](https://coveralls.io/github/projectblacklight/blacklight?branch=master)",
|
|
5
5
|
"main": "app/assets/javascripts/blacklight",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"js-compile-bundle": "shx cat app/javascript/blacklight/core.js app/javascript/blacklight/autocomplete.js app/javascript/blacklight/bookmark_toggle.js app/javascript/blacklight/button_focus.js app/javascript/blacklight/checkbox_submit.js app/javascript/blacklight/facet_load.js app/javascript/blacklight/modal.js app/javascript/blacklight/search_context.js | shx sed \"s/^(import|export).*//\" | babel --filename app/javascript/blacklight/blacklight.js > app/assets/javascripts/blacklight/blacklight.js"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Blacklight::AdvancedSearchFormComponent, type: :component do
|
|
6
|
+
subject(:render) do
|
|
7
|
+
component.render_in(view_context)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let(:component) { described_class.new(url: '/whatever', response: response, params: params) }
|
|
11
|
+
let(:response) { Blacklight::Solr::Response.new({ facet_counts: { facet_fields: { format: { 'Book' => 10, 'CD' => 5 } } } }.with_indifferent_access, {}) }
|
|
12
|
+
let(:params) { {} }
|
|
13
|
+
|
|
14
|
+
let(:rendered) do
|
|
15
|
+
Capybara::Node::Simple.new(render)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
let(:view_context) { controller.view_context }
|
|
19
|
+
|
|
20
|
+
before do
|
|
21
|
+
allow(view_context).to receive(:facet_limit_for).and_return(nil)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'with additional parameters' do
|
|
25
|
+
let(:params) { { some: :parameter, an_array: [1, 2] } }
|
|
26
|
+
|
|
27
|
+
it 'adds additional parameters as hidden fields' do
|
|
28
|
+
expect(rendered).to have_field 'some', with: 'parameter', type: :hidden
|
|
29
|
+
expect(rendered).to have_field 'an_array[]', with: '1', type: :hidden
|
|
30
|
+
expect(rendered).to have_field 'an_array[]', with: '2', type: :hidden
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'has text fields for each search field' do
|
|
35
|
+
expect(rendered).to have_selector '.advanced-search-field', count: 4
|
|
36
|
+
expect(rendered).to have_field 'clause_0_field', with: 'all_fields', type: :hidden
|
|
37
|
+
expect(rendered).to have_field 'clause_1_field', with: 'title', type: :hidden
|
|
38
|
+
expect(rendered).to have_field 'clause_2_field', with: 'author', type: :hidden
|
|
39
|
+
expect(rendered).to have_field 'clause_3_field', with: 'subject', type: :hidden
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'has filters' do
|
|
43
|
+
expect(rendered).to have_selector '.blacklight-format'
|
|
44
|
+
expect(rendered).to have_field 'f_inclusive[format][]', with: 'Book'
|
|
45
|
+
expect(rendered).to have_field 'f_inclusive[format][]', with: 'CD'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'has a sort field' do
|
|
49
|
+
expect(rendered).to have_select 'sort', options: %w[relevance year author title]
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -33,6 +33,8 @@ RSpec.describe Blacklight::DocumentComponent, type: :component do
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
before do
|
|
36
|
+
# Every call to view_context returns a different object. This ensures it stays stable.
|
|
37
|
+
allow(controller).to receive(:view_context).and_return(view_context)
|
|
36
38
|
allow(controller).to receive(:current_or_guest_user).and_return(User.new)
|
|
37
39
|
allow(controller).to receive(:blacklight_config).and_return(blacklight_config)
|
|
38
40
|
allow(view_context).to receive(:search_session).and_return({})
|
|
@@ -149,4 +151,19 @@ RSpec.describe Blacklight::DocumentComponent, type: :component do
|
|
|
149
151
|
expect(rendered).to have_selector 'dd', text: 'Title'
|
|
150
152
|
expect(rendered).not_to have_selector 'dt', text: 'ISBN:'
|
|
151
153
|
end
|
|
154
|
+
|
|
155
|
+
context 'with a thumbnail component' do
|
|
156
|
+
let(:attr) { { thumbnail_component: thumbnail_component_class } }
|
|
157
|
+
let(:thumbnail_component_class) do
|
|
158
|
+
Class.new(ViewComponent::Base) do
|
|
159
|
+
def render_in(view_context)
|
|
160
|
+
view_context.capture { 'Thumb!' }
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it 'uses the provided thumbnail component' do
|
|
166
|
+
expect(rendered).to have_content 'Thumb!'
|
|
167
|
+
end
|
|
168
|
+
end
|
|
152
169
|
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Blacklight::FacetFieldCheckboxesComponent, type: :component do
|
|
6
|
+
subject(:render) do
|
|
7
|
+
render_inline(described_class.new(facet_field: facet_field))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let(:rendered) do
|
|
11
|
+
Capybara::Node::Simple.new(render)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
let(:facet_field) do
|
|
15
|
+
instance_double(
|
|
16
|
+
Blacklight::FacetFieldPresenter,
|
|
17
|
+
facet_field: Blacklight::Configuration::NullField.new(key: 'field'),
|
|
18
|
+
paginator: paginator,
|
|
19
|
+
key: 'field',
|
|
20
|
+
label: 'Field',
|
|
21
|
+
active?: false,
|
|
22
|
+
collapsed?: false,
|
|
23
|
+
modal_path: nil,
|
|
24
|
+
html_id: 'facet-field',
|
|
25
|
+
search_state: search_state
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
let(:paginator) do
|
|
30
|
+
instance_double(Blacklight::FacetPaginator, items: [
|
|
31
|
+
double(label: 'a', hits: 10, value: 'a'),
|
|
32
|
+
double(label: 'b', hits: 33, value: 'b'),
|
|
33
|
+
double(label: 'c', hits: 3, value: 'c')
|
|
34
|
+
])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
let(:search_state) { Blacklight::SearchState.new(params.with_indifferent_access, Blacklight::Configuration.new) }
|
|
38
|
+
let(:params) { { f: { field: ['a'] } } }
|
|
39
|
+
|
|
40
|
+
it 'renders a collapsible card' do
|
|
41
|
+
expect(rendered).to have_selector '.card'
|
|
42
|
+
expect(rendered).to have_button 'Field'
|
|
43
|
+
expect(rendered).to have_selector 'button[data-target="#facet-field"]'
|
|
44
|
+
expect(rendered).to have_selector '#facet-field.collapse.show'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'renders the facet items' do
|
|
48
|
+
expect(rendered).to have_selector 'ul.facet-values'
|
|
49
|
+
expect(rendered).to have_selector 'li', count: 3
|
|
50
|
+
|
|
51
|
+
expect(rendered).to have_field 'f_inclusive[field][]', with: 'a'
|
|
52
|
+
expect(rendered).to have_field 'f_inclusive[field][]', with: 'b'
|
|
53
|
+
expect(rendered).to have_field 'f_inclusive[field][]', with: 'c'
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -20,7 +20,8 @@ RSpec.describe Blacklight::FacetFieldListComponent, type: :component do
|
|
|
20
20
|
active?: false,
|
|
21
21
|
collapsed?: false,
|
|
22
22
|
modal_path: nil,
|
|
23
|
-
html_id: 'facet-field'
|
|
23
|
+
html_id: 'facet-field',
|
|
24
|
+
values: []
|
|
24
25
|
)
|
|
25
26
|
end
|
|
26
27
|
|
|
@@ -53,7 +54,8 @@ RSpec.describe Blacklight::FacetFieldListComponent, type: :component do
|
|
|
53
54
|
active?: true,
|
|
54
55
|
collapsed?: false,
|
|
55
56
|
modal_path: nil,
|
|
56
|
-
html_id: 'facet-field'
|
|
57
|
+
html_id: 'facet-field',
|
|
58
|
+
values: []
|
|
57
59
|
)
|
|
58
60
|
end
|
|
59
61
|
|
|
@@ -72,7 +74,8 @@ RSpec.describe Blacklight::FacetFieldListComponent, type: :component do
|
|
|
72
74
|
active?: false,
|
|
73
75
|
collapsed?: true,
|
|
74
76
|
modal_path: nil,
|
|
75
|
-
html_id: 'facet-field'
|
|
77
|
+
html_id: 'facet-field',
|
|
78
|
+
values: []
|
|
76
79
|
)
|
|
77
80
|
end
|
|
78
81
|
|
|
@@ -97,7 +100,8 @@ RSpec.describe Blacklight::FacetFieldListComponent, type: :component do
|
|
|
97
100
|
active?: false,
|
|
98
101
|
collapsed?: false,
|
|
99
102
|
modal_path: '/catalog/facet/modal',
|
|
100
|
-
html_id: 'facet-field'
|
|
103
|
+
html_id: 'facet-field',
|
|
104
|
+
values: []
|
|
101
105
|
)
|
|
102
106
|
end
|
|
103
107
|
|
|
@@ -105,4 +109,35 @@ RSpec.describe Blacklight::FacetFieldListComponent, type: :component do
|
|
|
105
109
|
expect(rendered).to have_link 'more Field', href: '/catalog/facet/modal'
|
|
106
110
|
end
|
|
107
111
|
end
|
|
112
|
+
|
|
113
|
+
context 'with inclusive facets' do
|
|
114
|
+
let(:facet_field) do
|
|
115
|
+
instance_double(
|
|
116
|
+
Blacklight::FacetFieldPresenter,
|
|
117
|
+
paginator: paginator,
|
|
118
|
+
facet_field: Blacklight::Configuration::NullField.new(key: 'field'),
|
|
119
|
+
key: 'field',
|
|
120
|
+
label: 'Field',
|
|
121
|
+
active?: false,
|
|
122
|
+
collapsed?: false,
|
|
123
|
+
modal_path: nil,
|
|
124
|
+
html_id: 'facet-field',
|
|
125
|
+
values: [%w[a b c]],
|
|
126
|
+
search_state: search_state
|
|
127
|
+
)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
let(:search_state) { Blacklight::SearchState.new(params.with_indifferent_access, Blacklight::Configuration.new) }
|
|
131
|
+
let(:params) { { f_inclusive: { field: %w[a b c] } } }
|
|
132
|
+
|
|
133
|
+
it 'displays the constraint above the list' do
|
|
134
|
+
expect(rendered).to have_content 'Any of:'
|
|
135
|
+
expect(rendered).to have_selector '.inclusive_or .facet-label', text: 'a'
|
|
136
|
+
expect(rendered).to have_link '[remove]', href: 'http://test.host/catalog?f_inclusive%5Bfield%5D%5B%5D=b&f_inclusive%5Bfield%5D%5B%5D=c'
|
|
137
|
+
expect(rendered).to have_selector '.inclusive_or .facet-label', text: 'b'
|
|
138
|
+
expect(rendered).to have_link '[remove]', href: 'http://test.host/catalog?f_inclusive%5Bfield%5D%5B%5D=a&f_inclusive%5Bfield%5D%5B%5D=c'
|
|
139
|
+
expect(rendered).to have_selector '.inclusive_or .facet-label', text: 'c'
|
|
140
|
+
expect(rendered).to have_link '[remove]', href: 'http://test.host/catalog?f_inclusive%5Bfield%5D%5B%5D=a&f_inclusive%5Bfield%5D%5B%5D=b'
|
|
141
|
+
end
|
|
142
|
+
end
|
|
108
143
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Blacklight::HiddenSearchStateComponent, type: :component do
|
|
4
|
+
subject(:render) { render_inline(instance) }
|
|
5
|
+
|
|
6
|
+
let(:params) do
|
|
7
|
+
{ q: "query",
|
|
8
|
+
search_field: "search_field",
|
|
9
|
+
per_page: 10,
|
|
10
|
+
extra_arbitrary_key: "arbitrary_value",
|
|
11
|
+
f: { field1: %w[a b], field2: ["z"] } }
|
|
12
|
+
end
|
|
13
|
+
let(:instance) { described_class.new(params: params) }
|
|
14
|
+
let(:generated) { Capybara::Node::Simple.new("<div>#{render.to_html}</div>") }
|
|
15
|
+
|
|
16
|
+
it "converts a hash with nested complex data to Rails-style hidden form fields" do
|
|
17
|
+
expect(generated).to have_selector("input[type='hidden'][name='q'][value='query']", visible: :hidden)
|
|
18
|
+
expect(generated).to have_selector("input[type='hidden'][name='per_page'][value='10']", visible: :hidden)
|
|
19
|
+
expect(generated).to have_selector("input[type='hidden'][name='extra_arbitrary_key'][value='arbitrary_value']", visible: :hidden)
|
|
20
|
+
expect(generated).to have_selector("input[type='hidden'][name='f[field2][]'][value='z']", visible: :hidden)
|
|
21
|
+
expect(generated).to have_selector("input[type='hidden'][name='f[field1][]'][value='a']", visible: :hidden)
|
|
22
|
+
expect(generated).to have_selector("input[type='hidden'][name='f[field1][]'][value='b']", visible: :hidden)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -301,6 +301,15 @@ RSpec.describe CatalogController, api: true do
|
|
|
301
301
|
end
|
|
302
302
|
end
|
|
303
303
|
|
|
304
|
+
describe 'GET advanced_search' do
|
|
305
|
+
it 'renders an advanced search form' do
|
|
306
|
+
get :advanced_search
|
|
307
|
+
expect(response).to be_successful
|
|
308
|
+
|
|
309
|
+
assert_facets_have_values(assigns(:response).aggregations)
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
304
313
|
# SHOW ACTION
|
|
305
314
|
describe "show action" do
|
|
306
315
|
describe "with format :html" do
|