blacklight 9.0.0 → 9.2.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 +4 -4
- data/.env +3 -3
- data/.github/matrix.json +12 -18
- data/.github/workflows/build.yml +1 -1
- data/.github/workflows/lint.yml +2 -2
- data/.github/workflows/test.yml +6 -5
- data/.rubocop.yml +72 -7
- data/.rubocop_todo.yml +142 -268
- data/Gemfile +1 -1
- data/README.md +2 -9
- data/VERSION +1 -1
- data/app/assets/builds/blacklight.css +37 -23
- data/app/assets/images/blacklight/logo-dark.svg +184 -0
- data/app/assets/images/blacklight/logo.svg +184 -0
- data/app/assets/javascripts/blacklight/blacklight.esm.js +128 -45
- data/app/assets/javascripts/blacklight/blacklight.esm.js.map +1 -1
- data/app/assets/javascripts/blacklight/blacklight.js +128 -45
- data/app/assets/javascripts/blacklight/blacklight.js.map +1 -1
- data/app/assets/stylesheets/blacklight/_balanced_list.scss +1 -1
- data/app/assets/stylesheets/blacklight/_bootstrap_overrides.scss +17 -0
- data/app/assets/stylesheets/blacklight/_constraints.scss +2 -2
- data/app/assets/stylesheets/blacklight/_facets.scss +14 -10
- data/app/assets/stylesheets/blacklight/_header.scss +0 -4
- data/app/assets/stylesheets/blacklight/blacklight_defaults.scss +5 -9
- data/app/components/blacklight/facets/inclusive_constraint_component.html.erb +1 -1
- data/app/components/blacklight/icons/checkmark_component.rb +16 -0
- data/app/components/blacklight/icons/circle_half_component.rb +16 -0
- data/app/components/blacklight/icons/moon_stars_component.rb +17 -0
- data/app/components/blacklight/icons/sun_component.rb +16 -0
- data/app/components/blacklight/metadata_field_component.rb +3 -3
- data/app/components/blacklight/search_navbar_component.html.erb +1 -1
- data/app/components/blacklight/theme_switcher_component.html.erb +31 -0
- data/app/components/blacklight/theme_switcher_component.rb +6 -0
- data/app/components/blacklight/top_navbar_component.html.erb +1 -1
- data/app/controllers/concerns/blacklight/bookmarks.rb +8 -14
- data/app/controllers/concerns/blacklight/catalog.rb +9 -10
- data/app/controllers/concerns/blacklight/controller.rb +54 -11
- data/app/controllers/concerns/blacklight/controller_runtime.rb +42 -0
- data/app/controllers/concerns/blacklight/guest_user.rb +51 -0
- data/app/controllers/concerns/blacklight/search_context.rb +1 -1
- data/app/controllers/concerns/blacklight/search_history.rb +3 -1
- data/app/controllers/concerns/blacklight/searchable.rb +18 -0
- data/app/helpers/blacklight/layout_helper_behavior.rb +7 -0
- data/app/javascript/blacklight-frontend/color_theme_switcher.js +85 -0
- data/app/javascript/blacklight-frontend/index.js +2 -0
- data/app/models/concerns/blacklight/document/dublin_core.rb +2 -2
- data/app/models/concerns/blacklight/document.rb +1 -1
- data/app/models/concerns/blacklight/user.rb +36 -0
- data/app/presenters/blacklight/field_presenter.rb +1 -1
- data/app/presenters/blacklight/rendering/microdata.rb +1 -0
- data/app/services/blacklight/bookmarks_search_builder.rb +4 -4
- data/app/services/blacklight/search_service.rb +46 -33
- data/app/values/blacklight/types.rb +1 -1
- data/app/views/catalog/_email_form.html.erb +3 -3
- data/app/views/catalog/_home_text.html.erb +1 -1
- data/app/views/catalog/_sms_form.html.erb +4 -4
- data/app/views/catalog/index.rss.builder +4 -4
- data/app/views/catalog/opensearch.json.jbuilder +3 -0
- data/app/views/catalog/opensearch.xml.builder +2 -2
- data/app/views/layouts/blacklight/base.html.erb +13 -1
- data/app/views/shared/_user_util_links.html.erb +18 -5
- data/blacklight.gemspec +3 -3
- data/config/locales/blacklight.ar.yml +5 -0
- data/config/locales/blacklight.ca.yml +5 -0
- data/config/locales/blacklight.de.yml +6 -2
- data/config/locales/blacklight.en.yml +5 -0
- data/config/locales/blacklight.es.yml +5 -0
- data/config/locales/blacklight.fr.yml +5 -0
- data/config/locales/blacklight.hu.yml +5 -0
- data/config/locales/blacklight.it.yml +6 -2
- data/config/locales/blacklight.nl.yml +5 -0
- data/config/locales/blacklight.pt-BR.yml +6 -2
- data/config/locales/blacklight.sq.yml +5 -0
- data/config/locales/blacklight.zh.yml +5 -0
- data/lib/blacklight/abstract_repository.rb +2 -0
- data/lib/blacklight/component.rb +1 -1
- data/lib/blacklight/configuration/action_config_map_entry.rb +31 -0
- data/lib/blacklight/configuration/display_field.rb +1 -0
- data/lib/blacklight/configuration/field.rb +6 -6
- data/lib/blacklight/configuration/fields.rb +1 -1
- data/lib/blacklight/configuration/sort_field.rb +2 -2
- data/lib/blacklight/configuration.rb +30 -19
- data/lib/blacklight/engine.rb +9 -0
- data/lib/blacklight/log_subscriber.rb +25 -0
- data/lib/blacklight/parameters.rb +1 -1
- data/lib/blacklight/runtime_registry.rb +24 -0
- data/lib/blacklight/search_builder.rb +60 -20
- data/lib/blacklight/search_state.rb +4 -0
- data/lib/blacklight/solr/repository.rb +15 -10
- data/lib/blacklight/solr/request.rb +8 -1
- data/lib/blacklight/solr/response/group_response.rb +1 -1
- data/lib/blacklight/solr/response/spelling.rb +8 -8
- data/lib/blacklight/solr/response.rb +2 -21
- data/lib/blacklight/solr/search_builder_behavior.rb +3 -9
- data/lib/blacklight.rb +2 -2
- data/lib/generators/blacklight/assets/importmap_generator.rb +2 -2
- data/lib/generators/blacklight/assets_generator.rb +1 -1
- data/lib/generators/blacklight/controller_generator.rb +1 -1
- data/lib/generators/blacklight/document_generator.rb +1 -1
- data/lib/generators/blacklight/install_generator.rb +11 -4
- data/lib/generators/blacklight/models_generator.rb +1 -1
- data/lib/generators/blacklight/search_builder_generator.rb +1 -1
- data/lib/generators/blacklight/solr_generator.rb +1 -1
- data/lib/generators/blacklight/templates/catalog_controller.rb +20 -1
- data/lib/generators/blacklight/templates/solr/conf/schema.xml +264 -178
- data/lib/generators/blacklight/templates/solr/conf/solrconfig.xml +6 -14
- data/lib/generators/blacklight/test_support_generator.rb +1 -1
- data/lib/generators/blacklight/user_generator.rb +66 -5
- data/lib/railties/blacklight.rake +4 -4
- data/package.json +2 -2
- data/spec/components/blacklight/document/action_component_spec.rb +1 -1
- data/spec/components/blacklight/document/group_component_spec.rb +1 -1
- data/spec/components/blacklight/document_component_spec.rb +9 -9
- data/spec/components/blacklight/facet_component_spec.rb +2 -2
- data/spec/components/blacklight/facets/index_navigation_component_spec.rb +1 -2
- data/spec/components/blacklight/facets/list_component_spec.rb +1 -1
- data/spec/components/blacklight/facets/suggest_component_spec.rb +1 -2
- data/spec/components/blacklight/metadata_field_component_spec.rb +41 -0
- data/spec/components/blacklight/skip_link_component_spec.rb +2 -2
- data/spec/controllers/application_controller_spec.rb +94 -0
- data/spec/controllers/bookmarks_controller_spec.rb +18 -5
- data/spec/controllers/catalog_controller_spec.rb +7 -5
- data/spec/features/advanced_search_spec.rb +29 -16
- data/spec/features/alternate_controller_spec.rb +4 -4
- data/spec/features/axe_spec.rb +40 -22
- data/spec/features/bookmarks_spec.rb +13 -13
- data/spec/features/dark_mode_spec.rb +42 -0
- data/spec/features/did_you_mean_spec.rb +27 -27
- data/spec/features/facet_missing_spec.rb +3 -3
- data/spec/features/record_view_spec.rb +14 -14
- data/spec/features/search_context_spec.rb +8 -8
- data/spec/features/search_filters_spec.rb +16 -16
- data/spec/features/search_formats_spec.rb +2 -2
- data/spec/features/search_history_spec.rb +11 -11
- data/spec/features/search_pagination_spec.rb +31 -17
- data/spec/features/search_results_spec.rb +3 -3
- data/spec/features/search_sort_spec.rb +4 -4
- data/spec/features/search_spec.rb +20 -20
- data/spec/helpers/blacklight/url_helper_behavior_spec.rb +15 -15
- data/spec/helpers/blacklight_helper_spec.rb +1 -1
- data/spec/helpers/catalog_helper_spec.rb +7 -7
- data/spec/integration/generators/blacklight/user_generator_spec.rb +60 -0
- data/spec/lib/blacklight/runtime_registry_spec.rb +46 -0
- data/spec/lib/blacklight/search_state/pivot_filter_field_spec.rb +1 -1
- data/spec/models/blacklight/configurable_spec.rb +1 -1
- data/spec/models/blacklight/configuration_spec.rb +0 -19
- data/spec/models/blacklight/document/dublin_core_spec.rb +2 -2
- data/spec/models/blacklight/facet_paginator_spec.rb +1 -1
- data/spec/models/blacklight/search_builder_spec.rb +15 -3
- data/spec/models/blacklight/solr/repository_spec.rb +79 -2
- data/spec/models/blacklight/solr/search_builder_behavior_spec.rb +3 -5
- data/spec/models/blacklight/user_spec.rb +32 -5
- data/spec/models/bookmark_spec.rb +1 -1
- data/spec/models/record_mailer_spec.rb +8 -8
- data/spec/models/search_spec.rb +1 -1
- data/spec/models/solr_document_spec.rb +4 -0
- data/spec/presenters/blacklight/index_presenter_spec.rb +1 -0
- data/spec/presenters/blacklight/rendering/pipeline_spec.rb +1 -0
- data/spec/presenters/blacklight/show_presenter_spec.rb +1 -0
- data/spec/presenters/blacklight/thumbnail_presenter_spec.rb +1 -0
- data/spec/services/blacklight/search_service_spec.rb +7 -7
- data/spec/spec_helper.rb +3 -12
- data/spec/support/features/session_helpers.rb +13 -4
- data/spec/support/features/turbo_helpers.rb +14 -0
- data/spec/support/features.rb +2 -0
- data/spec/support/user_helpers.rb +24 -0
- data/spec/test_app_templates/Gemfile.extra +3 -0
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +1 -1
- data/spec/views/catalog/_document.html.erb_spec.rb +4 -4
- data/spec/views/catalog/_paginate_compact.html.erb_spec.rb +2 -2
- data/spec/views/catalog/_sort_and_per_page.html.erb_spec.rb +5 -5
- data/spec/views/catalog/index.html.erb_spec.rb +2 -2
- data/spec/views/catalog/show.html.erb_spec.rb +3 -4
- data/spec/views/shared/_user_util_links.html.erb_spec.rb +56 -0
- data/template.demo.rb +2 -1
- metadata +34 -22
- data/.hound.yml +0 -4
- data/.jshintrc +0 -22
- data/app/assets/images/blacklight/logo.png +0 -0
|
@@ -670,25 +670,6 @@ RSpec.describe Blacklight::Configuration, :api do
|
|
|
670
670
|
expect(config.view_config(action_name: :show)).to have_attributes config.show.to_h
|
|
671
671
|
end
|
|
672
672
|
|
|
673
|
-
it 'includes the default action mapping configuration' do
|
|
674
|
-
config.action_mapping.default.whatever = :some_value
|
|
675
|
-
|
|
676
|
-
expect(config.view_config(action_name: :show)).to have_attributes whatever: :some_value
|
|
677
|
-
end
|
|
678
|
-
|
|
679
|
-
it 'includes the action-specific mappings' do
|
|
680
|
-
config.action_mapping.foo.document_presenter_class = Blacklight::DocumentPresenter
|
|
681
|
-
|
|
682
|
-
expect(config.view_config(action_name: :foo)).to have_attributes config.action_mapping.foo.to_h
|
|
683
|
-
end
|
|
684
|
-
|
|
685
|
-
it 'allows the action mapping to specific a parent configuration with some more defaults' do
|
|
686
|
-
config.action_mapping.foo.parent_config = :bar
|
|
687
|
-
config.action_mapping.bar.whatever = :bar_value
|
|
688
|
-
|
|
689
|
-
expect(config.view_config(action_name: :foo)).to have_attributes whatever: :bar_value
|
|
690
|
-
end
|
|
691
|
-
|
|
692
673
|
context 'with the :citation action' do
|
|
693
674
|
it 'also includes the show config' do
|
|
694
675
|
expect(config.view_config(action_name: :citation)).to have_attributes config.show.to_h
|
|
@@ -25,8 +25,8 @@ RSpec.describe "Blacklight::Document::DublinCore" do
|
|
|
25
25
|
it "includes 'dc:'-prefixed semantic fields" do
|
|
26
26
|
data = { 'id' => '123456', 'title_tsim' => ['654321'] }
|
|
27
27
|
document = @mock_class.new(data)
|
|
28
|
-
expect(document.export_as_oai_dc_xml).to match
|
|
29
|
-
expect(document.export_as_oai_dc_xml).to match
|
|
28
|
+
expect(document.export_as_oai_dc_xml).to match 'xmlns:dc="http://purl.org/dc/elements/1.1/"'
|
|
29
|
+
expect(document.export_as_oai_dc_xml).to match '<dc:title>654321</dc:title>'
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it "works with multi-value fields" do
|
|
@@ -171,6 +171,6 @@ RSpec.describe Blacklight::FacetPaginator, :api do
|
|
|
171
171
|
# this method is just for API compatability with kaminari 0.16.1
|
|
172
172
|
subject { described_class.new([book], offset: 0, limit: nil).total_pages }
|
|
173
173
|
|
|
174
|
-
it { is_expected.to eq
|
|
174
|
+
it { is_expected.to eq(-1) }
|
|
175
175
|
end
|
|
176
176
|
end
|
|
@@ -137,15 +137,23 @@ RSpec.describe Blacklight::SearchBuilder, :api do
|
|
|
137
137
|
|
|
138
138
|
describe "#page" do
|
|
139
139
|
it "is the current user parameter page number" do
|
|
140
|
-
expect(subject.with(page: 2).
|
|
140
|
+
expect(subject.with(page: 2).page).to eq 2
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
it "is page 1 if not page number given" do
|
|
144
|
-
expect(subject.
|
|
144
|
+
expect(subject.page).to eq 1
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
it "coerces parameters to integers" do
|
|
148
|
-
expect(subject.with(page: '2b').
|
|
148
|
+
expect(subject.with(page: '2b').page).to eq 2
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'sets the page number' do
|
|
152
|
+
expect(subject.page(3).page).to eq 3
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it 'gracefully handles setting the page number with a nil value' do
|
|
156
|
+
expect(subject.page(nil).page).to eq 1
|
|
149
157
|
end
|
|
150
158
|
end
|
|
151
159
|
|
|
@@ -160,6 +168,10 @@ RSpec.describe Blacklight::SearchBuilder, :api do
|
|
|
160
168
|
expect(subject.rows(17).rows).to eq 17
|
|
161
169
|
end
|
|
162
170
|
|
|
171
|
+
it "gracefully hnadles setting the number of rows to a nil value" do
|
|
172
|
+
expect(subject.rows(nil).rows).to eq 10
|
|
173
|
+
end
|
|
174
|
+
|
|
163
175
|
it "is the per_page parameter" do
|
|
164
176
|
expect(subject.with(per_page: 5).rows).to eq 5
|
|
165
177
|
end
|
|
@@ -143,6 +143,31 @@ RSpec.describe Blacklight::Solr::Repository, :api do
|
|
|
143
143
|
allow(repository.connection).to receive(:send_and_receive).and_raise(rsolr_timeout)
|
|
144
144
|
expect { subject.search(params: {}) }.to raise_exception(Blacklight::Exceptions::RepositoryTimeout, /Timeout connecting to Solr instance/)
|
|
145
145
|
end
|
|
146
|
+
|
|
147
|
+
it "instruments the request with ActiveSupport::Notifications" do
|
|
148
|
+
allow(subject.connection).to receive(:send_and_receive).and_return(mock_response)
|
|
149
|
+
|
|
150
|
+
payload = nil
|
|
151
|
+
callback = ->(event) { payload = event.payload }
|
|
152
|
+
ActiveSupport::Notifications.subscribed(callback, "solr_request.blacklight") do
|
|
153
|
+
subject.search(params: {})
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
expect(payload).to include(path: 'select', method: :get)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "instruments a json query dsl request as post, regardless of http_method configuration" do
|
|
160
|
+
blacklight_config.http_method = :get
|
|
161
|
+
allow(subject.connection).to receive(:send_and_receive).and_return(mock_response)
|
|
162
|
+
|
|
163
|
+
payload = nil
|
|
164
|
+
callback = ->(event) { payload = event.payload }
|
|
165
|
+
ActiveSupport::Notifications.subscribed(callback, "solr_request.blacklight") do
|
|
166
|
+
subject.search(params: { json: { query: 'foo' } })
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
expect(payload).to include(method: :post)
|
|
170
|
+
end
|
|
146
171
|
end
|
|
147
172
|
|
|
148
173
|
describe "#build_solr_request" do
|
|
@@ -160,7 +185,11 @@ RSpec.describe Blacklight::Solr::Repository, :api do
|
|
|
160
185
|
end
|
|
161
186
|
|
|
162
187
|
describe "setting to post" do
|
|
163
|
-
let
|
|
188
|
+
let(:blacklight_config) do
|
|
189
|
+
config = Blacklight::Configuration.new
|
|
190
|
+
config.http_method = :post
|
|
191
|
+
config
|
|
192
|
+
end
|
|
164
193
|
|
|
165
194
|
it "keep value set to post" do
|
|
166
195
|
expect(blacklight_config.http_method).to eq :post
|
|
@@ -210,7 +239,11 @@ RSpec.describe Blacklight::Solr::Repository, :api do
|
|
|
210
239
|
end
|
|
211
240
|
|
|
212
241
|
describe "http_method configuration", :integration do
|
|
213
|
-
let
|
|
242
|
+
let(:blacklight_config) do
|
|
243
|
+
config = Blacklight::Configuration.new
|
|
244
|
+
config.http_method = :post
|
|
245
|
+
config
|
|
246
|
+
end
|
|
214
247
|
|
|
215
248
|
it "sends a post request to solr and get a response back" do
|
|
216
249
|
response = subject.search(params: { q: all_docs_query })
|
|
@@ -222,5 +255,49 @@ RSpec.describe Blacklight::Solr::Repository, :api do
|
|
|
222
255
|
subject { repository.ping }
|
|
223
256
|
|
|
224
257
|
it { is_expected.to be true }
|
|
258
|
+
|
|
259
|
+
it "instruments the request with ActiveSupport::Notifications" do
|
|
260
|
+
payload = nil
|
|
261
|
+
callback = ->(event) { payload = event.payload }
|
|
262
|
+
ActiveSupport::Notifications.subscribed(callback, "solr_request.blacklight") do
|
|
263
|
+
repository.ping
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
expect(payload).to include(path: 'admin/ping', method: :get)
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
describe "debug logging" do
|
|
271
|
+
let(:io) { StringIO.new }
|
|
272
|
+
let(:test_logger) { Logger.new(io, level: Logger::DEBUG) }
|
|
273
|
+
|
|
274
|
+
before do
|
|
275
|
+
allow(Blacklight).to receive(:logger).and_return(test_logger)
|
|
276
|
+
allow(subject.connection).to receive(:send_and_receive).and_return(mock_response)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "logs the solr query at debug, never at info" do
|
|
280
|
+
subject.search(params: { q: 'test' })
|
|
281
|
+
|
|
282
|
+
expect(io.string).to include("test")
|
|
283
|
+
expect(io.string).not_to include("INFO")
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it "does not log the full response by default" do
|
|
287
|
+
subject.search(params: { q: 'test' })
|
|
288
|
+
|
|
289
|
+
expect(io.string).not_to include("Solr response")
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
context "when BLACKLIGHT_VERBOSE_LOGGING is set" do
|
|
293
|
+
before { stub_const('BLACKLIGHT_VERBOSE_LOGGING', true) }
|
|
294
|
+
|
|
295
|
+
it "logs the full response at debug, never at info" do
|
|
296
|
+
subject.search(params: { q: 'test' })
|
|
297
|
+
|
|
298
|
+
expect(io.string).to include("Solr response")
|
|
299
|
+
expect(io.string).not_to include("INFO")
|
|
300
|
+
end
|
|
301
|
+
end
|
|
225
302
|
end
|
|
226
303
|
end
|
|
@@ -524,13 +524,11 @@ RSpec.describe Blacklight::Solr::SearchBuilderBehavior, :api do
|
|
|
524
524
|
end
|
|
525
525
|
|
|
526
526
|
describe "#add_facets_for_advanced_search_form" do
|
|
527
|
+
let(:user_params) do
|
|
528
|
+
Blacklight::SearchState.new({}, blacklight_config, mock_controller)
|
|
529
|
+
end
|
|
527
530
|
let(:solr_parameters) { Blacklight::Solr::Request.new }
|
|
528
531
|
let(:mock_controller) { instance_double(CatalogController, action_name: 'advanced_search') }
|
|
529
|
-
let(:mock_search_state) { instance_double(Blacklight::SearchState, controller: mock_controller) }
|
|
530
|
-
|
|
531
|
-
before do
|
|
532
|
-
allow(search_builder).to receive(:search_state).and_return(mock_search_state)
|
|
533
|
-
end
|
|
534
532
|
|
|
535
533
|
context "when action is advanced_search and form_solr_parameters are configured" do
|
|
536
534
|
before do
|
|
@@ -1,12 +1,36 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
RSpec.describe "Blacklight::User", :api do
|
|
4
|
-
subject {
|
|
4
|
+
subject { create_user email: 'xyz@example.com', password: 'xyz12345' }
|
|
5
5
|
|
|
6
6
|
def mock_bookmark document_id
|
|
7
7
|
Bookmark.new document_id: document_id, document_type: SolrDocument.to_s
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
describe ".blacklight_email_column" do
|
|
11
|
+
it "returns the email column the model actually has" do
|
|
12
|
+
expected = User.column_names.include?("email_address") ? :email_address : :email
|
|
13
|
+
expect(User.blacklight_email_column).to eq expected
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe ".create_guest_user!" do
|
|
18
|
+
it "creates a persisted user with a generated, unique identifier" do
|
|
19
|
+
guest = User.create_guest_user!
|
|
20
|
+
|
|
21
|
+
expect(guest).to be_persisted
|
|
22
|
+
expect(guest.public_send(User.blacklight_email_column)).to match(/^guest_.*@example\.com$/)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "generates a distinct identifier each time" do
|
|
26
|
+
one = User.create_guest_user!
|
|
27
|
+
two = User.create_guest_user!
|
|
28
|
+
|
|
29
|
+
expect(one.public_send(User.blacklight_email_column))
|
|
30
|
+
.not_to eq(two.public_send(User.blacklight_email_column))
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
10
34
|
describe "#bookmarks_for_documents" do
|
|
11
35
|
before do
|
|
12
36
|
subject.bookmarks << mock_bookmark(1)
|
|
@@ -47,12 +71,15 @@ RSpec.describe "Blacklight::User", :api do
|
|
|
47
71
|
end
|
|
48
72
|
|
|
49
73
|
describe '#to_s' do
|
|
50
|
-
it 'is the
|
|
51
|
-
|
|
74
|
+
it 'is the configured display key by default' do
|
|
75
|
+
display_key = User.column_names.include?("email_address") ? :email_address : :email
|
|
76
|
+
|
|
77
|
+
expect(subject.to_s).to eq subject.public_send(display_key)
|
|
52
78
|
end
|
|
53
79
|
|
|
54
|
-
context 'when no
|
|
55
|
-
let(:
|
|
80
|
+
context 'when no configured display key method is provided' do
|
|
81
|
+
let(:display_key) { User.column_names.include?("email_address") ? :email_address : :email }
|
|
82
|
+
let(:old_method) { subject.class.instance_method(display_key) }
|
|
56
83
|
|
|
57
84
|
before do
|
|
58
85
|
subject.class.send(:undef_method, old_method.name)
|
|
@@ -37,11 +37,11 @@ RSpec.describe RecordMailer do
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
it "starts the subject w/ Item Record:" do
|
|
40
|
-
expect(email.subject).to match
|
|
40
|
+
expect(email.subject).to match(/^Item Record:/)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
it "puts the title of the item in the subject" do
|
|
44
|
-
expect(email.subject).to
|
|
44
|
+
expect(email.subject).to include('The horn')
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
it "has the correct from address (w/o the port number)" do
|
|
@@ -49,9 +49,9 @@ RSpec.describe RecordMailer do
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
it "prints out the correct body" do
|
|
52
|
-
expect(email.body).to
|
|
53
|
-
expect(email.body).to
|
|
54
|
-
expect(email.body).to match
|
|
52
|
+
expect(email.body).to include('Title: The horn')
|
|
53
|
+
expect(email.body).to include('Author: Janetzky, Kurt')
|
|
54
|
+
expect(email.body).to match(/projectblacklight.org/)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
it "uses https URLs when protocol is set" do
|
|
@@ -104,9 +104,9 @@ RSpec.describe RecordMailer do
|
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
it "prints out the correct body" do
|
|
107
|
-
expect(@sms.body).to
|
|
108
|
-
expect(@sms.body).to
|
|
109
|
-
expect(@sms.body).to match
|
|
107
|
+
expect(@sms.body).to include('Title: The horn')
|
|
108
|
+
expect(@sms.body).to include('Author: Janetzky, Kurt')
|
|
109
|
+
expect(@sms.body).to match(/projectblacklight.org:3000/)
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
it "uses https URL when protocol is set" do
|
data/spec/models/search_spec.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
RSpec.describe Search do
|
|
4
4
|
let(:search) { described_class.new(user: user) }
|
|
5
|
-
let(:user) {
|
|
5
|
+
let(:user) { create_user email: 'xyz@example.com', password: 'xyz12345' }
|
|
6
6
|
let(:hash_params) { { q: "query", f: { facet: "filter" } } }
|
|
7
7
|
let(:query_params) { hash_params }
|
|
8
8
|
|
|
@@ -54,6 +54,7 @@ RSpec.describe SolrDocument, :api do
|
|
|
54
54
|
attribute :first_author, :select, 'author_tesim', by: :min
|
|
55
55
|
attribute :date, :date, field: 'date_dtsi'
|
|
56
56
|
attribute :time, :time, field: 'date_dtsi'
|
|
57
|
+
attribute :details, :json, 'details_ssi'
|
|
57
58
|
attribute :whatever, :string, default: ->(*) { 'default_value' }
|
|
58
59
|
end
|
|
59
60
|
end
|
|
@@ -61,6 +62,7 @@ RSpec.describe SolrDocument, :api do
|
|
|
61
62
|
doc_class.new(id: '123',
|
|
62
63
|
title_tesim: ['Good Omens'],
|
|
63
64
|
author_tesim: ['Neil Gaiman', 'Terry Pratchett'],
|
|
65
|
+
details_ssi: '{"pages":288}',
|
|
64
66
|
date_dtsi: '1990-01-01T17:23:13Z')
|
|
65
67
|
end
|
|
66
68
|
|
|
@@ -72,6 +74,8 @@ RSpec.describe SolrDocument, :api do
|
|
|
72
74
|
expect(document.date.to_s).to eq '1990-01-01'
|
|
73
75
|
expect(document.time).to be_a Time
|
|
74
76
|
expect(document.time.to_s).to eq '1990-01-01 17:23:13 UTC'
|
|
77
|
+
expect(document.details).to be_a Hash
|
|
78
|
+
expect(document.details).to eq({ 'pages' => 288 })
|
|
75
79
|
expect(document.whatever).to eq 'default_value'
|
|
76
80
|
end
|
|
77
81
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
RSpec.describe Blacklight::ThumbnailPresenter do
|
|
4
4
|
include Capybara::RSpecMatchers
|
|
5
|
+
|
|
5
6
|
let(:view_context) { double "View context" }
|
|
6
7
|
let(:config) { Blacklight::Configuration.new.view_config(:index) }
|
|
7
8
|
let(:presenter) { described_class.new(document, view_context, config) }
|
|
@@ -145,7 +145,7 @@ RSpec.describe Blacklight::SearchService, :api do
|
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
it 'has all facets specified in initializer' do
|
|
148
|
-
expect(@facets.keys).to include
|
|
148
|
+
expect(@facets.keys).to include(*blacklight_config.facet_fields.keys)
|
|
149
149
|
expect(@facets.none? { |_k, v| v.nil? }).to be true
|
|
150
150
|
end
|
|
151
151
|
|
|
@@ -379,40 +379,40 @@ RSpec.describe Blacklight::SearchService, :api do
|
|
|
379
379
|
end
|
|
380
380
|
|
|
381
381
|
it "returns the previous and next documents for a search" do
|
|
382
|
-
_response, docs = service.previous_and_next_documents_for_search(4, q: '')
|
|
382
|
+
_response, docs = service.previous_and_next_documents_for_search(4, { q: '' })
|
|
383
383
|
|
|
384
384
|
expect(docs.first.id).to eq @full_response.documents[3].id
|
|
385
385
|
expect(docs.last.id).to eq @full_response.documents[5].id
|
|
386
386
|
end
|
|
387
387
|
|
|
388
388
|
it "returns only the next document if the counter is 0" do
|
|
389
|
-
_response, docs = service.previous_and_next_documents_for_search(0, q: '')
|
|
389
|
+
_response, docs = service.previous_and_next_documents_for_search(0, { q: '' })
|
|
390
390
|
|
|
391
391
|
expect(docs.first).to be_nil
|
|
392
392
|
expect(docs.last.id).to eq @full_response.documents[1].id
|
|
393
393
|
end
|
|
394
394
|
|
|
395
395
|
it "returns only the previous document if the counter is the total number of documents" do
|
|
396
|
-
_response, docs = service.previous_and_next_documents_for_search(@full_response.total - 1, q: '')
|
|
396
|
+
_response, docs = service.previous_and_next_documents_for_search(@full_response.total - 1, { q: '' })
|
|
397
397
|
expect(docs.first.id).to eq @full_response.documents.slice(-2).id
|
|
398
398
|
expect(docs.last).to be_nil
|
|
399
399
|
end
|
|
400
400
|
|
|
401
401
|
it "returns an array of nil values if there is only one result" do
|
|
402
|
-
_response, docs = service.previous_and_next_documents_for_search(0, q: 'id:2007020969')
|
|
402
|
+
_response, docs = service.previous_and_next_documents_for_search(0, { q: 'id:2007020969' })
|
|
403
403
|
expect(docs.last).to be_nil
|
|
404
404
|
expect(docs.first).to be_nil
|
|
405
405
|
end
|
|
406
406
|
|
|
407
407
|
it 'returns only the unique key by default' do
|
|
408
|
-
_response, docs = service.previous_and_next_documents_for_search(0, q: '')
|
|
408
|
+
_response, docs = service.previous_and_next_documents_for_search(0, { q: '' })
|
|
409
409
|
expect(docs.last.to_h).to eq 'id' => @full_response.documents[1].id
|
|
410
410
|
end
|
|
411
411
|
|
|
412
412
|
it 'allows the query parameters to be customized using configuration' do
|
|
413
413
|
blacklight_config.document_pagination_params[:fl] = 'id,format'
|
|
414
414
|
|
|
415
|
-
_response, docs = service.previous_and_next_documents_for_search(0, q: '')
|
|
415
|
+
_response, docs = service.previous_and_next_documents_for_search(0, { q: '' })
|
|
416
416
|
|
|
417
417
|
expect(docs.last.to_h).to eq @full_response.documents[1].to_h.slice('id', 'format')
|
|
418
418
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -48,25 +48,16 @@ RSpec.configure do |config|
|
|
|
48
48
|
# When we're testing the API, only run the api tests
|
|
49
49
|
config.filter_run api: true if ENV['BLACKLIGHT_API_TEST'].present?
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
config.fixture_paths = [Rails.root.join("spec/fixtures")]
|
|
53
|
-
else
|
|
54
|
-
config.fixture_path = Rails.root.join("spec/fixtures")
|
|
55
|
-
end
|
|
51
|
+
config.fixture_paths = [Rails.root.join("spec/fixtures")]
|
|
56
52
|
|
|
57
53
|
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
|
58
54
|
# examples within a transaction, remove the following line or assign false
|
|
59
55
|
# instead of true.
|
|
60
56
|
config.use_transactional_fixtures = true
|
|
61
57
|
|
|
62
|
-
if defined? Devise::Test::ControllerHelpers
|
|
63
|
-
config.include Devise::Test::ControllerHelpers, type: :controller
|
|
64
|
-
else
|
|
65
|
-
config.include Devise::TestHelpers, type: :controller
|
|
66
|
-
config.include Devise::TestHelpers, type: :i18n
|
|
67
|
-
end
|
|
68
|
-
|
|
69
58
|
config.infer_spec_type_from_file_location!
|
|
59
|
+
config.include UserHelpers
|
|
60
|
+
config.include Devise::Test::ControllerHelpers, type: :controller if defined?(Devise)
|
|
70
61
|
config.include PresenterTestHelpers, type: :presenter
|
|
71
62
|
config.include ViewComponent::TestHelpers, type: :component
|
|
72
63
|
config.include ViewComponentTestHelpers, type: :component
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
module Features
|
|
5
5
|
module SessionHelpers
|
|
6
6
|
def sign_up_with(email, password)
|
|
7
|
+
return create_user(email: email, password: password) if respond_to?(:new_session_path)
|
|
8
|
+
|
|
7
9
|
Capybara.exact = true
|
|
8
10
|
visit new_user_registration_path
|
|
9
11
|
fill_in 'Email', with: email
|
|
@@ -14,10 +16,17 @@ module Features
|
|
|
14
16
|
|
|
15
17
|
def sign_in(login = 'user1')
|
|
16
18
|
email = "#{login}@#{login}.com"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
create_user(email: email, password: "password")
|
|
20
|
+
|
|
21
|
+
if respond_to?(:new_session_path)
|
|
22
|
+
visit new_session_path
|
|
23
|
+
fill_in("email_address", with: email)
|
|
24
|
+
fill_in("password", with: "password")
|
|
25
|
+
else
|
|
26
|
+
visit new_user_session_path
|
|
27
|
+
fill_in("user_email", with: email)
|
|
28
|
+
fill_in("user_password", with: "password")
|
|
29
|
+
end
|
|
21
30
|
|
|
22
31
|
if has_button? "Sign in"
|
|
23
32
|
click_on("Sign in")
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# spec/support/features/turbo_helpers.rb
|
|
4
|
+
module Features
|
|
5
|
+
module TurboHelpers
|
|
6
|
+
# Turbo Drive marks the document as busy for the duration of a visit. Capybara
|
|
7
|
+
# clicks return before the visit completes, so wait for the busy state to clear
|
|
8
|
+
# before making assertions that don't wait on their own (e.g. be_axe_clean).
|
|
9
|
+
def wait_for_turbo
|
|
10
|
+
page.has_css?('html[aria-busy]', visible: :all, wait: 0.5)
|
|
11
|
+
expect(page).to have_no_css('html[aria-busy]', visible: :all)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
data/spec/support/features.rb
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
require File.expand_path('features/search_helpers.rb', __dir__)
|
|
6
6
|
require File.expand_path('features/session_helpers.rb', __dir__)
|
|
7
|
+
require File.expand_path('features/turbo_helpers.rb', __dir__)
|
|
7
8
|
|
|
8
9
|
RSpec.configure do |config|
|
|
9
10
|
config.include Features::SearchHelpers, type: :feature
|
|
10
11
|
config.include Features::SessionHelpers, type: :feature
|
|
12
|
+
config.include Features::TurboHelpers, type: :feature
|
|
11
13
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module UserHelpers
|
|
4
|
+
def build_user(attributes = {})
|
|
5
|
+
User.new(user_attributes(attributes))
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def create_user(attributes = {})
|
|
9
|
+
User.create!(user_attributes(attributes))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def user_attributes(attributes = {})
|
|
13
|
+
attributes = attributes.dup
|
|
14
|
+
password = attributes.delete(:password) || "password"
|
|
15
|
+
email = attributes.delete(:email) || attributes.delete(:email_address) || "user@example.com"
|
|
16
|
+
email_attribute = User.column_names.include?("email_address") ? :email_address : :email
|
|
17
|
+
|
|
18
|
+
{
|
|
19
|
+
email_attribute => email,
|
|
20
|
+
password: password,
|
|
21
|
+
password_confirmation: attributes.delete(:password_confirmation) || password
|
|
22
|
+
}.merge(attributes)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -3,3 +3,6 @@ gem 'rails-controller-testing'
|
|
|
3
3
|
unless ENV['VIEW_COMPONENT_VERSION'].to_s == ""
|
|
4
4
|
gem 'view_component', ENV.fetch('VIEW_COMPONENT_VERSION')
|
|
5
5
|
end
|
|
6
|
+
|
|
7
|
+
# json 3.0's JSON.parse rejects ActiveSupport::JSON.decode's positional options hash; unfixed as of Rails 8.1.3.
|
|
8
|
+
gem 'json', '< 3.0'
|
|
@@ -15,7 +15,7 @@ class TestAppGenerator < Rails::Generators::Base
|
|
|
15
15
|
Bundler.with_unbundled_env do
|
|
16
16
|
run "bundle install"
|
|
17
17
|
end
|
|
18
|
-
options = '--devise'
|
|
18
|
+
options = Rails.gem_version >= Gem::Version.new('8.0.0') ? '--authentication' : '--devise'
|
|
19
19
|
if ENV['BLACKLIGHT_API_TEST'].present?
|
|
20
20
|
options += ' --skip-assets'
|
|
21
21
|
end
|
|
@@ -17,9 +17,9 @@ RSpec.describe "catalog/_document" do
|
|
|
17
17
|
stub_template "catalog/_b_default.html.erb" => "b_partial"
|
|
18
18
|
stub_template "catalog/_c_default.html.erb" => "c_partial"
|
|
19
19
|
render partial: "catalog/document", locals: { document: document, document_counter: 1, view_config: blacklight_config.index }
|
|
20
|
-
expect(rendered).to
|
|
21
|
-
expect(rendered).to
|
|
22
|
-
expect(rendered).to
|
|
20
|
+
expect(rendered).to include('a_partial')
|
|
21
|
+
expect(rendered).to include('b_partial')
|
|
22
|
+
expect(rendered).to include('c_partial')
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
context 'with a configured document component' do
|
|
@@ -39,7 +39,7 @@ RSpec.describe "catalog/_document" do
|
|
|
39
39
|
|
|
40
40
|
it 'renders the document component' do
|
|
41
41
|
render partial: "catalog/document", locals: { document: document, document_counter: 1, view_config: blacklight_config.index }
|
|
42
|
-
expect(rendered).to
|
|
42
|
+
expect(rendered).to include('blah')
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
RSpec.describe "catalog/_paginate_compact.html.erb" do
|
|
4
|
-
let(:user) {
|
|
4
|
+
let(:user) { create_user }
|
|
5
5
|
let(:blacklight_config) { Blacklight::Configuration.new }
|
|
6
6
|
|
|
7
7
|
before do
|
|
@@ -16,7 +16,7 @@ RSpec.describe "catalog/_paginate_compact.html.erb" do
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
it "renders ActiveRecord collections" do
|
|
19
|
-
50.times {
|
|
19
|
+
50.times { Bookmark.create!(user: user) }
|
|
20
20
|
render partial: 'catalog/paginate_compact', object: Bookmark.page(1).per(25)
|
|
21
21
|
expect(rendered).to have_css ".page-entries"
|
|
22
22
|
expect(rendered).to have_css "a[@rel=next]"
|
|
@@ -17,10 +17,10 @@ RSpec.describe "catalog/_sort_and_per_page" do
|
|
|
17
17
|
stub_template "catalog/_per_page_widget.html.erb" => "per_page_widget"
|
|
18
18
|
stub_template "catalog/_view_type_group.html.erb" => "view_type_group"
|
|
19
19
|
render
|
|
20
|
-
expect(rendered).to
|
|
21
|
-
expect(rendered).to
|
|
22
|
-
expect(rendered).to
|
|
23
|
-
expect(rendered).to
|
|
20
|
+
expect(rendered).to include('paginate_compact')
|
|
21
|
+
expect(rendered).to include('sort_widget')
|
|
22
|
+
expect(rendered).to include('per_page_widget')
|
|
23
|
+
expect(rendered).to include('view_type_group')
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
it "does not render the pagination controls with bad limit values" do
|
|
@@ -30,6 +30,6 @@ RSpec.describe "catalog/_sort_and_per_page" do
|
|
|
30
30
|
stub_template "catalog/_per_page_widget.html.erb" => "per_page_widget"
|
|
31
31
|
stub_template "catalog/_view_type_group.html.erb" => "view_type_group"
|
|
32
32
|
render
|
|
33
|
-
expect(rendered).not_to
|
|
33
|
+
expect(rendered).not_to include('paginate_compact')
|
|
34
34
|
end
|
|
35
35
|
end
|