blacklight 8.0.1 → 8.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.env +1 -1
  3. data/.github/workflows/ruby.yml +17 -4
  4. data/.rubocop.yml +4 -0
  5. data/.rubocop_todo.yml +82 -73
  6. data/VERSION +1 -1
  7. data/app/assets/javascripts/blacklight/blacklight.esm.js +44 -21
  8. data/app/assets/javascripts/blacklight/blacklight.esm.js.map +1 -1
  9. data/app/assets/javascripts/blacklight/blacklight.js +44 -21
  10. data/app/assets/javascripts/blacklight/blacklight.js.map +1 -1
  11. data/app/assets/stylesheets/blacklight/_mixins.scss +1 -1
  12. data/app/builders/blacklight/action_builder.rb +1 -1
  13. data/app/components/blacklight/advanced_search_form_component.html.erb +3 -3
  14. data/app/components/blacklight/advanced_search_form_component.rb +3 -3
  15. data/app/components/blacklight/document/bookmark_component.html.erb +1 -6
  16. data/app/components/blacklight/facet_field_component.html.erb +2 -1
  17. data/app/components/blacklight/icons/legacy_icon_component.rb +1 -1
  18. data/app/components/blacklight/response/facet_group_component.html.erb +0 -1
  19. data/app/components/blacklight/response/pagination_component.html.erb +1 -1
  20. data/app/components/blacklight/response/pagination_component.rb +6 -1
  21. data/app/components/blacklight/search_bar_component.html.erb +2 -2
  22. data/app/components/blacklight/system/flash_message_component.html.erb +1 -1
  23. data/app/controllers/concerns/blacklight/bookmarks.rb +1 -1
  24. data/app/controllers/concerns/blacklight/token_based_user.rb +5 -19
  25. data/app/helpers/blacklight/url_helper_behavior.rb +3 -2
  26. data/app/javascript/blacklight/bookmark_toggle.js +1 -1
  27. data/app/javascript/blacklight/checkbox_submit.js +15 -10
  28. data/app/javascript/blacklight/index.js +10 -5
  29. data/app/javascript/blacklight/modal.js +27 -13
  30. data/app/javascript/blacklight/search_context.js +1 -0
  31. data/app/models/concerns/blacklight/document/active_model_shim.rb +10 -0
  32. data/app/models/search.rb +6 -1
  33. data/app/services/blacklight/field_retriever.rb +13 -11
  34. data/app/values/blacklight/types.rb +14 -0
  35. data/app/views/catalog/_advanced_search_form.html.erb +1 -1
  36. data/app/views/catalog/_citation.html.erb +1 -1
  37. data/app/views/catalog/_show_tools.html.erb +1 -1
  38. data/app/views/catalog/email.html.erb +2 -2
  39. data/app/views/catalog/sms.html.erb +2 -2
  40. data/app/views/kaminari/blacklight/_page.html.erb +1 -1
  41. data/blacklight.gemspec +2 -3
  42. data/config/locales/blacklight.ar.yml +0 -1
  43. data/config/locales/blacklight.ca.yml +0 -2
  44. data/config/locales/blacklight.de.yml +0 -1
  45. data/config/locales/blacklight.en.yml +1 -1
  46. data/config/locales/blacklight.es.yml +0 -1
  47. data/config/locales/blacklight.fr.yml +0 -1
  48. data/config/locales/blacklight.hu.yml +0 -1
  49. data/config/locales/blacklight.it.yml +0 -1
  50. data/config/locales/blacklight.nl.yml +0 -1
  51. data/config/locales/blacklight.pt-BR.yml +0 -1
  52. data/config/locales/blacklight.sq.yml +0 -1
  53. data/config/locales/blacklight.zh.yml +0 -1
  54. data/docker-compose.yml +0 -2
  55. data/lib/blacklight/component.rb +1 -1
  56. data/lib/blacklight/configuration.rb +7 -1
  57. data/lib/blacklight/engine.rb +12 -0
  58. data/lib/blacklight/solr/repository.rb +16 -2
  59. data/lib/blacklight/solr/response/params.rb +1 -1
  60. data/lib/blacklight/solr/search_builder_behavior.rb +3 -0
  61. data/lib/generators/blacklight/assets/importmap_generator.rb +2 -2
  62. data/lib/generators/blacklight/assets/sprockets_generator.rb +1 -1
  63. data/lib/generators/blacklight/assets_generator.rb +2 -4
  64. data/lib/generators/blacklight/install_generator.rb +1 -3
  65. data/lib/generators/blacklight/templates/catalog_controller.rb +1 -0
  66. data/lib/generators/blacklight/templates/solr/conf/solrconfig.xml +69 -0
  67. data/package.json +1 -1
  68. data/spec/components/blacklight/facet_component_spec.rb +11 -1
  69. data/spec/components/blacklight/facet_item_pivot_component_spec.rb +2 -2
  70. data/spec/components/blacklight/response/pagination_component_spec.rb +53 -0
  71. data/spec/components/blacklight/search_context/server_applied_params_component_spec.rb +11 -1
  72. data/spec/controllers/catalog_controller_spec.rb +2 -2
  73. data/spec/features/advanced_search_spec.rb +61 -0
  74. data/spec/features/axe_spec.rb +5 -0
  75. data/spec/features/citation_spec.rb +10 -0
  76. data/spec/features/sms_spec.rb +12 -0
  77. data/spec/helpers/blacklight_helper_spec.rb +10 -5
  78. data/spec/models/blacklight/configurable_spec.rb +1 -1
  79. data/spec/models/blacklight/solr/repository_spec.rb +27 -0
  80. data/spec/models/blacklight/solr/response_spec.rb +1 -1
  81. data/spec/models/blacklight/solr/search_builder_spec.rb +21 -0
  82. data/spec/models/solr_document_spec.rb +6 -2
  83. data/spec/services/blacklight/field_retriever_spec.rb +17 -0
  84. data/spec/spec_helper.rb +1 -2
  85. data/spec/support/view_component_test_helpers.rb +14 -0
  86. data/spec/test_app_templates/Gemfile.extra +0 -1
  87. data/spec/views/catalog/_paginate_compact.html.erb_spec.rb +2 -0
  88. data/template.demo.rb +7 -7
  89. metadata +15 -21
@@ -100,6 +100,75 @@
100
100
  </arr>
101
101
  </requestHandler>
102
102
 
103
+ <requestHandler name="/advanced" class="solr.SearchHandler">
104
+ <!-- a lucene request handler for using the JSON Query DSL,
105
+ specifically for advanced search.
106
+ Using a separate requestHandler is a workaround to
107
+ https://issues.apache.org/jira/browse/SOLR-16916, although
108
+ it could be desirable for other reasons as well.
109
+ -->
110
+ <lst name="defaults">
111
+ <str name="defType">lucene</str>
112
+ <str name="echoParams">explicit</str>
113
+ <str name="df">title_tsim</str>
114
+ <str name="qf">
115
+ id
116
+ full_title_tsim
117
+ short_title_tsim
118
+ alternative_title_tsim
119
+ active_fedora_model_ssi
120
+ title_tsim
121
+ author_tsim
122
+ subject_tsim
123
+ all_text_timv
124
+ </str>
125
+ <str name="pf">
126
+ all_text_timv^10
127
+ </str>
128
+
129
+ <str name="author_qf">
130
+ author_tsim
131
+ </str>
132
+ <str name="author_pf">
133
+ </str>
134
+ <str name="title_qf">
135
+ title_tsim
136
+ full_title_tsim
137
+ short_title_tsim
138
+ alternative_title_tsim
139
+ </str>
140
+ <str name="title_pf">
141
+ </str>
142
+ <str name="subject_qf">
143
+ subject_tsim
144
+ </str>
145
+ <str name="subject_pf">
146
+ </str>
147
+
148
+ <str name="fl">
149
+ *,
150
+ score
151
+ </str>
152
+
153
+ <str name="facet">true</str>
154
+ <str name="facet.mincount">1</str>
155
+ <str name="facet.limit">10</str>
156
+ <str name="facet.field">active_fedora_model_ssi</str>
157
+ <str name="facet.field">subject_ssim</str>
158
+
159
+ <str name="spellcheck">true</str>
160
+ <str name="spellcheck.dictionary">default</str>
161
+ <str name="spellcheck.onlyMorePopular">true</str>
162
+ <str name="spellcheck.extendedResults">true</str>
163
+ <str name="spellcheck.collate">false</str>
164
+ <str name="spellcheck.count">5</str>
165
+
166
+ </lst>
167
+ <arr name="last-components">
168
+ <str>spellcheck</str>
169
+ </arr>
170
+ </requestHandler>
171
+
103
172
  <requestHandler name="permissions" class="solr.SearchHandler" >
104
173
  <lst name="defaults">
105
174
  <str name="facet">off</str>
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blacklight-frontend",
3
- "version": "8.0.1",
3
+ "version": "8.2.0",
4
4
  "description": "The frontend code and styles for Blacklight",
5
5
  "main": "app/assets/javascripts/blacklight",
6
6
  "module": "app/assets/javascripts/blacklight/blacklight.esm.js",
@@ -45,8 +45,18 @@ RSpec.describe Blacklight::FacetComponent, type: :component do
45
45
  Blacklight::Configuration::FacetField.new(key: 'field', partial: 'catalog/facet_partial').normalize!
46
46
  end
47
47
 
48
+ # Not sure why we need to re-implement rspec's stub_template, but
49
+ # we already were, and need a Rails 7.1+ safe alternate too
50
+ # https://github.com/rspec/rspec-rails/commit/4d65bea0619955acb15023b9c3f57a3a53183da8
51
+ # https://github.com/rspec/rspec-rails/issues/2696
48
52
  before do
49
- controller.view_context.view_paths.unshift(RSpec::Rails::ViewExampleGroup::StubResolverCache.resolver_for('catalog/_facet_partial.html.erb' => 'facet partial'))
53
+ replace_hash = { 'catalog/_facet_partial.html.erb' => 'facet partial' }
54
+
55
+ if ::Rails.version.to_f >= 7.1
56
+ controller.prepend_view_path(RSpec::Rails::ViewExampleGroup::StubResolverCache.resolver_for(replace_hash))
57
+ else
58
+ controller.view_context.view_paths.unshift(RSpec::Rails::ViewExampleGroup::StubResolverCache.resolver_for(replace_hash))
59
+ end
50
60
  end
51
61
 
52
62
  it 'renders the partial' do
@@ -35,13 +35,13 @@ RSpec.describe Blacklight::FacetItemPivotComponent, type: :component do
35
35
 
36
36
  it 'links to the facet and shows the number of hits' do
37
37
  expect(rendered).to have_selector 'li'
38
- expect(rendered).to have_link 'x', href: '/catalog?f%5Bz%5D=x'
38
+ expect(rendered).to have_link 'x', href: nokogiri_mediated_href(facet_item.href)
39
39
  expect(rendered).to have_selector '.facet-count', text: '10'
40
40
  end
41
41
 
42
42
  it 'has the facet hierarchy' do
43
43
  expect(rendered).to have_selector 'li ul.pivot-facet'
44
- expect(rendered).to have_link 'x:1', href: /f%5Bz%5D%5B%5D=x:1/
44
+ expect(rendered).to have_link 'x:1', href: nokogiri_mediated_href(facet_item.facet_item_presenters.first.href)
45
45
  end
46
46
 
47
47
  context 'with a selected facet' do
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Blacklight::Response::PaginationComponent, type: :component do
6
+ let(:render) do
7
+ with_request_url '/catalog?q=foo' do
8
+ render_inline(instance)
9
+ end
10
+ end
11
+
12
+ let(:instance) { described_class.new(response: response) }
13
+
14
+ context 'when there are many results' do
15
+ let(:response) { instance_double(Blacklight::Solr::Response, total: 10, current_page: 5, limit_value: 10_000, total_pages: 100) }
16
+
17
+ context 'with default config' do
18
+ before { render }
19
+
20
+ it "has links to deep pages" do
21
+ expect(page).not_to have_link '98'
22
+ expect(page).to have_link '99'
23
+ expect(page).to have_link '100'
24
+ expect(page).not_to have_link '101'
25
+ end
26
+ end
27
+
28
+ context 'when a different configuration that removes deep links is passed as a parameter' do
29
+ let(:instance) { described_class.new(response: response, left: 5, right: 0, outer_window: nil) }
30
+
31
+ before { render }
32
+
33
+ it "does not link to deep pages" do
34
+ expect(page).to have_link '1'
35
+ expect(page).not_to have_link '100'
36
+ end
37
+ end
38
+
39
+ context 'when a different configuration that removes deep links is configured in the controller' do
40
+ before do
41
+ allow(controller.blacklight_config.index)
42
+ .to receive(:pagination_options)
43
+ .and_return(theme: 'blacklight', left: 5, right: 0)
44
+ render
45
+ end
46
+
47
+ it "does not link to deep pages" do
48
+ expect(page).to have_link '1'
49
+ expect(page).not_to have_link '100'
50
+ end
51
+ end
52
+ end
53
+ end
@@ -10,7 +10,17 @@ RSpec.describe Blacklight::SearchContext::ServerAppliedParamsComponent, type: :c
10
10
  let(:view_context) { controller.view_context }
11
11
 
12
12
  before do
13
- view_context.view_paths.unshift(RSpec::Rails::ViewExampleGroup::StubResolverCache.resolver_for('application/_start_over.html.erb' => 'start over'))
13
+ # Not sure why we need to re-implement rspec's stub_template, but
14
+ # we already were, and need a Rails 7.1+ safe alternate too
15
+ # https://github.com/rspec/rspec-rails/commit/4d65bea0619955acb15023b9c3f57a3a53183da8
16
+ # https://github.com/rspec/rspec-rails/issues/2696
17
+ replace_hash = { 'application/_start_over.html.erb' => 'start over' }
18
+ if ::Rails.version.to_f >= 7.1
19
+ controller.prepend_view_path(RSpec::Rails::ViewExampleGroup::StubResolverCache.resolver_for(replace_hash))
20
+ else
21
+ view_context.view_paths.unshift(RSpec::Rails::ViewExampleGroup::StubResolverCache.resolver_for(replace_hash))
22
+ end
23
+
14
24
  allow(view_context).to receive(:current_search_session).and_return current_search_session
15
25
  allow(view_context).to receive(:link_back_to_catalog).with(any_args)
16
26
  end
@@ -54,7 +54,7 @@ RSpec.describe CatalogController, api: true do
54
54
  it "has no docs or facet values for query without results", integration: true do
55
55
  get :index, params: { q: 'sadfdsafasdfsadfsadfsadf' } # query for no results
56
56
  expect(assigns(:response).docs).to be_empty
57
- assigns(:response).aggregations.each do |_key, facet|
57
+ assigns(:response).aggregations.each_value do |facet|
58
58
  expect(facet.items).to be_empty
59
59
  end
60
60
  end
@@ -815,7 +815,7 @@ end
815
815
  def assert_facets_have_values(aggregations)
816
816
  expect(aggregations).not_to be_empty
817
817
  # should have at least one value for each facet
818
- aggregations.each do |_key, facet|
818
+ aggregations.each_value do |facet|
819
819
  expect(facet.items).to have_at_least(1).item
820
820
  end
821
821
  end
@@ -5,9 +5,27 @@ require 'spec_helper'
5
5
  RSpec.describe "Blacklight Advanced Search Form" do
6
6
  describe "advanced search form" do
7
7
  before do
8
+ CatalogController.blacklight_config.search_fields['all_fields']['clause_params'] = {
9
+ edismax: {}
10
+ }
11
+ CatalogController.blacklight_config.search_fields['author']['clause_params'] = {
12
+ edismax: { qf: '${author_qf}' }
13
+ }
14
+ CatalogController.blacklight_config.search_fields['title']['clause_params'] = {
15
+ edismax: { qf: '${title_qf}' }
16
+ }
17
+ CatalogController.blacklight_config.search_fields['subject']['clause_params'] = {
18
+ edismax: { qf: '${subject_qf}' }
19
+ }
8
20
  visit '/catalog/advanced?hypothetical_existing_param=true&q=ignore+this+existing+query'
9
21
  end
10
22
 
23
+ after do
24
+ %w[all_fields author title subject].each do |field|
25
+ CatalogController.blacklight_config.search_fields[field].delete(:clause_params)
26
+ end
27
+ end
28
+
11
29
  it "has field and facet blocks" do
12
30
  expect(page).to have_selector('.query-criteria')
13
31
  expect(page).to have_selector('.limit-criteria')
@@ -45,6 +63,43 @@ RSpec.describe "Blacklight Advanced Search Form" do
45
63
  click_on 'advanced-search-submit'
46
64
  expect(page).to have_content 'Remove constraint Title: Medicine'
47
65
  expect(page).to have_content 'Strong Medicine speaks'
66
+ expect(page).to have_selector('article.document', count: 1)
67
+ end
68
+
69
+ it 'can limit to facets' do
70
+ fill_in 'Subject', with: 'Women'
71
+ click_on 'Language'
72
+ check 'Urdu 3'
73
+ click_on 'advanced-search-submit'
74
+ expect(page).to have_content 'Pākistānī ʻaurat dorāhe par'
75
+ expect(page).not_to have_content 'Ajikto kŭrŏk chŏrŏk sasimnikka : and 아직도 그럭 저럭 사십니까'
76
+ expect(page).to have_selector('article.document', count: 1)
77
+ end
78
+
79
+ it 'handles boolean queries' do
80
+ fill_in 'All Fields', with: 'history NOT strong'
81
+ click_on 'advanced-search-submit'
82
+ expect(page).to have_content('Ci an zhou bian')
83
+ expect(page).not_to have_content('Strong Medicine speaks')
84
+ expect(page).to have_selector('article.document', count: 10)
85
+ end
86
+
87
+ it 'handles queries in multiple fields with the ALL operator' do
88
+ fill_in 'All Fields', with: 'history'
89
+ fill_in 'Author', with: 'hearth'
90
+ click_on 'advanced-search-submit'
91
+ expect(page).to have_content('Strong Medicine speaks')
92
+ expect(page).to have_selector('article.document', count: 1)
93
+ end
94
+
95
+ it 'handles queries in multiple fields with the ANY operator' do
96
+ select 'any', from: 'op'
97
+ fill_in 'All Fields', with: 'history'
98
+ fill_in 'Subject', with: 'women'
99
+ click_on 'advanced-search-submit'
100
+ expect(page).to have_content('Ci an zhou bian')
101
+ expect(page).to have_content('Pākistānī ʻaurat dorāhe par')
102
+ expect(page).to have_selector('article.document', count: 10)
48
103
  end
49
104
  end
50
105
 
@@ -63,5 +118,11 @@ RSpec.describe "Blacklight Advanced Search Form" do
63
118
  expect(page.current_url).to match(/bread/)
64
119
  expect(page.current_url).not_to match(/medicine/)
65
120
  end
121
+
122
+ it "clears the prepopulated fields when the Start Over button is pressed" do
123
+ expect(page).to have_field 'Title', with: 'medicine'
124
+ click_on 'Start over'
125
+ expect(page).not_to have_field 'Title', with: 'medicine'
126
+ end
66
127
  end
67
128
  end
@@ -21,6 +21,11 @@ RSpec.describe 'Accessibility testing', api: false, js: true do
21
21
  expect(page).to be_accessible
22
22
  end
23
23
 
24
+ it 'validates the advanced search form' do
25
+ visit advanced_search_catalog_path
26
+ expect(page).to be_accessible
27
+ end
28
+
24
29
  it 'validates the single results page' do
25
30
  visit solr_document_path('2007020969')
26
31
  expect(page).to be_accessible
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe 'Citation functionality' do
4
+ before { visit solr_document_path('2007020969') }
5
+
6
+ it 'displays the Cite modal with expected header' do
7
+ click_link 'Cite'
8
+ expect(find('div.modal-header')).to have_text 'Cite'
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe 'SMS functionality' do
4
+ before { visit solr_document_path('2007020969') }
5
+
6
+ it 'displays SMS modal with form' do
7
+ click_link 'SMS'
8
+ expect(find('div.modal-header')).to have_text 'SMS This'
9
+ fill_in 'Phone Number:', with: '555-555-5555'
10
+ select 'Verizon', from: 'Carrier'
11
+ end
12
+ end
@@ -185,12 +185,17 @@ RSpec.describe BlacklightHelper do
185
185
  blacklight_config.view.gallery(template: '/my/partial')
186
186
  end
187
187
 
188
- def stub_template(hash)
189
- view.view_paths.unshift(ActionView::FixtureResolver.new(hash))
190
- end
191
-
192
188
  it 'renders that template' do
193
- stub_template 'my/_partial.html.erb' => 'some content'
189
+ # Not sure why we need to re-implement rspec's stub_template, but
190
+ # we already were, and need a Rails 7.1+ safe alternate too
191
+ # https://github.com/rspec/rspec-rails/commit/4d65bea0619955acb15023b9c3f57a3a53183da8
192
+ # https://github.com/rspec/rspec-rails/issues/2696
193
+ replace_hash = { 'my/_partial.html.erb' => 'some content' }
194
+ if ::Rails.version.to_f >= 7.1
195
+ controller.prepend_view_path(RSpec::Rails::ViewExampleGroup::StubResolverCache.resolver_for(replace_hash))
196
+ else
197
+ view.view_paths.unshift(ActionView::FixtureResolver.new(replace_hash))
198
+ end
194
199
 
195
200
  response = helper.render_document_index_with_view :gallery, [obj1, obj1]
196
201
 
@@ -93,7 +93,7 @@ RSpec.describe "Blacklight::Configurable", api: true do
93
93
  instance.blacklight_config.bar << "123"
94
94
  expect(instance.blacklight_config).not_to eq klass.blacklight_config
95
95
  expect(klass.blacklight_config.foo).to eq "bar"
96
- expect(instance.blacklight_config.foo).to eq "bar"
96
+ expect(instance.blacklight_config.foo).to eq "bar"
97
97
  expect(klass.blacklight_config.bar).not_to include("123")
98
98
  expect(instance.blacklight_config.bar).to include("asd", "123")
99
99
  end
@@ -153,6 +153,33 @@ RSpec.describe Blacklight::Solr::Repository, api: true do
153
153
  expect(JSON.parse(actual_params[:data]).with_indifferent_access).to include(query: { bool: {} })
154
154
  expect(actual_params[:headers]).to include({ 'Content-Type' => 'application/json' })
155
155
  end
156
+
157
+ context "without a json solr path configured" do
158
+ before do
159
+ blacklight_config.json_solr_path = nil
160
+ end
161
+
162
+ it "uses the default solr path" do
163
+ blacklight_config.solr_path = 'xyz'
164
+ allow(subject.connection).to receive(:send_and_receive) do |path|
165
+ expect(path).to eq 'xyz'
166
+ end
167
+ subject.search(input_params)
168
+ end
169
+ end
170
+
171
+ context "with a json solr path configured" do
172
+ before do
173
+ blacklight_config.json_solr_path = 'my-great-json'
174
+ end
175
+
176
+ it "uses the configured json_solr_path" do
177
+ allow(subject.connection).to receive(:send_and_receive) do |path|
178
+ expect(path).to eq 'my-great-json'
179
+ end
180
+ subject.search(input_params)
181
+ end
182
+ end
156
183
  end
157
184
  end
158
185
 
@@ -48,7 +48,7 @@ RSpec.describe Blacklight::Solr::Response, api: true do
48
48
 
49
49
  expect(received).to eq expected
50
50
 
51
- r.aggregations.each do |_key, facet|
51
+ r.aggregations.each_value do |facet|
52
52
  expect(facet).to respond_to :name
53
53
  expect(facet).to respond_to :sort
54
54
  expect(facet).to respond_to :offset
@@ -335,6 +335,7 @@ RSpec.describe Blacklight::Solr::SearchBuilderBehavior, api: true do
335
335
  qf: '$subject_qf',
336
336
  pf: '$subject_pf'
337
337
  }
338
+ blacklight_config.search_fields['subject'].clause_params = nil
338
339
  end
339
340
 
340
341
  it "looks up qt from field definition" do
@@ -374,6 +375,18 @@ RSpec.describe Blacklight::Solr::SearchBuilderBehavior, api: true do
374
375
  expect(key_value_pairs).to include("pf=$subject_pf")
375
376
  expect(key_value_pairs).to include("qf=$subject_qf")
376
377
  end
378
+
379
+ context 'when subject field uses JSON query DSL' do
380
+ before do
381
+ blacklight_config.search_fields['subject'].clause_params = {
382
+ edismax: {}
383
+ }
384
+ end
385
+
386
+ it "includes spellcheck.q, without LocalParams" do
387
+ expect(subject["spellcheck.q"]).to eq "wome"
388
+ end
389
+ end
377
390
  end
378
391
 
379
392
  describe "solr json query parameters from the fielded search" do
@@ -406,6 +419,14 @@ RSpec.describe Blacklight::Solr::SearchBuilderBehavior, api: true do
406
419
  it 'includes addtional clause parameters for the field' do
407
420
  expect(subject.dig(:json, :query, :bool, :must, 0, :edismax)).to include another: :parameter
408
421
  end
422
+
423
+ context 'with an empty search' do
424
+ let(:subject_search_params) { { commit: "search", search_field: "subject", action: "index", controller: "catalog", rows: "10", q: nil } }
425
+
426
+ it 'does not add nil query value clauses to json query' do
427
+ expect(subject).not_to have_key :json
428
+ end
429
+ end
409
430
  end
410
431
 
411
432
  describe "sorting" do
@@ -49,6 +49,7 @@ RSpec.describe SolrDocument, api: true do
49
49
  attribute :author, :array, 'author_tesim', of: :string
50
50
  attribute :first_author, :select, 'author_tesim', by: :min
51
51
  attribute :date, :date, field: 'date_dtsi'
52
+ attribute :time, :time, field: 'date_dtsi'
52
53
  attribute :whatever, :string, default: ->(*) { 'default_value' }
53
54
  end
54
55
  end
@@ -56,14 +57,17 @@ RSpec.describe SolrDocument, api: true do
56
57
  doc_class.new(id: '123',
57
58
  title_tesim: ['Good Omens'],
58
59
  author_tesim: ['Neil Gaiman', 'Terry Pratchett'],
59
- date_dtsi: '1990-01-01T00:00:00Z')
60
+ date_dtsi: '1990-01-01T17:23:13Z')
60
61
  end
61
62
 
62
63
  it "casts the attributes" do
63
64
  expect(document.title).to eq 'Good Omens'
64
65
  expect(document.author).to eq ['Neil Gaiman', 'Terry Pratchett']
65
66
  expect(document.first_author).to eq 'Neil Gaiman'
66
- expect(document.date).to eq Date.new(1990)
67
+ expect(document.date).to be_a Date
68
+ expect(document.date.to_s).to eq '1990-01-01'
69
+ expect(document.time).to be_a Time
70
+ expect(document.time.to_s).to eq '1990-01-01 17:23:13 UTC'
67
71
  expect(document.whatever).to eq 'default_value'
68
72
  end
69
73
 
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Blacklight::FieldRetriever, api: true do
4
+ let(:service) { described_class.new(document, blacklight_field_config) }
5
+
6
+ let(:blacklight_field_config) { Blacklight::Configuration::Field.new(field: 'author_field', highlight: true) }
7
+ let(:document) { SolrDocument.new({ 'id' => 'doc1', 'title_field' => 'doc1 title', 'author_field' => 'author_someone' }, 'highlighting' => { 'doc1' => { 'title_tsimext' => ['doc <em>1</em>'] } }) }
8
+ let(:view_context) { {} }
9
+
10
+ context "highlighting" do
11
+ describe '#fetch' do
12
+ it "retrieves an author even if it's not highlighted" do
13
+ expect(service.fetch).to eq(['author_someone'])
14
+ end
15
+ end
16
+ end
17
+ end
data/spec/spec_helper.rb CHANGED
@@ -17,7 +17,6 @@ EngineCart.load_application!
17
17
  require 'rspec/rails'
18
18
  require 'rspec/collection_matchers'
19
19
  require 'capybara/rails'
20
- require 'webdrivers'
21
20
  require 'selenium-webdriver'
22
21
  require 'equivalent-xml'
23
22
  require 'axe-rspec'
@@ -35,7 +34,7 @@ Capybara.register_driver :headless_chrome do |app|
35
34
  opts.args << '--no-sandbox'
36
35
  opts.args << '--window-size=1280,1696'
37
36
  end
38
- Capybara::Selenium::Driver.new(app, browser: :chrome, capabilities: capabilities)
37
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: capabilities)
39
38
  end
40
39
 
41
40
  # Requires supporting ruby files with custom matchers and macros, etc,
@@ -18,4 +18,18 @@ module ViewComponentTestHelpers
18
18
 
19
19
  ApplicationController.new.extend(Rails.application.routes.url_helpers)
20
20
  end
21
+
22
+ # Nokogiri 1.15.0 upgrades the vendored libxml2 from v2.10.4 to v2.11.3
23
+ # libxml2 v2.11.0 introduces a change to parsing HTML href attributes
24
+ # in nokogiri < 1.15, brackets in href attributes are escaped:
25
+ # - <a class="facet-select" rel="nofollow" href="/catalog?f%5Bz%5D%5B%5D=x:1">x:1</a>
26
+ # in nokogiri >= 1.15, brackets in href attributes are not escaped:
27
+ # - <a class="facet-select" rel="nofollow" href="/catalog?f[z][]=x:1">x:1</a>
28
+ # until we can spec a minimum nokogiri version of 1.15.0, we need to see how
29
+ # the installed version parsed the html
30
+ def nokogiri_mediated_href(href)
31
+ start = "<a href=\"".length
32
+ stop = -"\"></a>".length
33
+ Nokogiri::HTML.fragment("<a href=\"#{href}\"></a>").to_s[start...stop]
34
+ end
21
35
  end
@@ -1,5 +1,4 @@
1
1
  gem 'rails-controller-testing'
2
- gem 'thor', '~> 0.20' if /^5.[12]/.match?(ENV['RAILS_VERSION'])
3
2
 
4
3
  unless ENV['VIEW_COMPONENT_VERSION'].to_s == ""
5
4
  gem 'view_component', ENV.fetch('VIEW_COMPONENT_VERSION')
@@ -2,9 +2,11 @@
2
2
 
3
3
  RSpec.describe "catalog/_paginate_compact.html.erb" do
4
4
  let(:user) { User.new { |u| u.save(validate: false) } }
5
+ let(:blacklight_config) { Blacklight::Configuration.new }
5
6
 
6
7
  before do
7
8
  controller.request.path_parameters[:action] = 'index'
9
+ allow(controller).to receive(:blacklight_config).and_return(blacklight_config)
8
10
  end
9
11
 
10
12
  it "renders paginatable arrays" do
data/template.demo.rb CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  gem 'blacklight', '>= 7.0'
4
4
 
5
- run "bundle install"
5
+ after_bundle do
6
+ # run the blacklight install generator
7
+ options = ENV.fetch("BLACKLIGHT_INSTALL_OPTIONS", '--devise --marc')
6
8
 
7
- # run the blacklight install generator
8
- options = ENV.fetch("BLACKLIGHT_INSTALL_OPTIONS", '--devise --marc')
9
+ generate 'blacklight:install', options
9
10
 
10
- generate 'blacklight:install', options
11
-
12
- # run the database migrations
13
- rake "db:migrate"
11
+ # run the database migrations
12
+ rake "db:migrate"
13
+ end