blacklight 7.20.1 → 7.22.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.babelrc +11 -0
  3. data/.docker/app/Dockerfile +3 -1
  4. data/.dockerignore +3 -0
  5. data/.env +2 -2
  6. data/.github/workflows/ruby.yml +3 -2
  7. data/Gemfile +1 -1
  8. data/README.md +1 -1
  9. data/VERSION +1 -1
  10. data/app/assets/javascripts/blacklight/blacklight.js +62 -32
  11. data/app/assets/stylesheets/blacklight/_constraints.scss +3 -1
  12. data/app/assets/stylesheets/blacklight/_controls.scss +2 -1
  13. data/app/components/blacklight/constraints_component.rb +3 -7
  14. data/app/components/blacklight/facet_field_checkboxes_component.rb +1 -1
  15. data/app/components/blacklight/facet_item_pivot_component.rb +1 -1
  16. data/app/components/blacklight/system/modal_component.html.erb +2 -2
  17. data/app/controllers/concerns/blacklight/catalog.rb +2 -2
  18. data/app/helpers/blacklight/facets_helper_behavior.rb +1 -1
  19. data/app/helpers/blacklight/render_partials_helper_behavior.rb +4 -1
  20. data/app/javascript/blacklight/core.js +8 -2
  21. data/app/javascript/blacklight/modal.js +20 -4
  22. data/app/models/concerns/blacklight/document/email.rb +18 -6
  23. data/app/models/concerns/blacklight/document/sms.rb +16 -4
  24. data/app/models/record_mailer.rb +9 -1
  25. data/app/presenters/blacklight/facet_item_presenter.rb +2 -0
  26. data/app/views/bookmarks/index.html.erb +1 -1
  27. data/app/views/catalog/_search_results.html.erb +1 -1
  28. data/app/views/record_mailer/sms_record.text.erb +1 -1
  29. data/config/locales/blacklight.de.yml +1 -1
  30. data/docker-compose.yml +5 -2
  31. data/lib/blacklight/configuration/facet_field.rb +2 -0
  32. data/lib/blacklight/configuration.rb +9 -0
  33. data/lib/blacklight/engine.rb +2 -0
  34. data/lib/blacklight/search_state/filter_field.rb +34 -19
  35. data/lib/blacklight/solr/response/facets.rb +14 -5
  36. data/lib/blacklight/solr/search_builder_behavior.rb +2 -14
  37. data/package.json +4 -2
  38. data/spec/controllers/catalog_controller_spec.rb +14 -2
  39. data/spec/features/axe_spec.rb +6 -7
  40. data/spec/features/facet_missing_spec.rb +12 -4
  41. data/spec/helpers/blacklight/facets_helper_behavior_spec.rb +7 -7
  42. data/spec/lib/blacklight/search_state/filter_field_spec.rb +3 -17
  43. data/spec/models/blacklight/configuration_spec.rb +92 -0
  44. data/spec/models/blacklight/document/email_spec.rb +32 -0
  45. data/spec/models/blacklight/document/sms_spec.rb +33 -0
  46. data/spec/models/blacklight/solr/response/facets_spec.rb +7 -1
  47. data/spec/models/blacklight/solr/search_builder_spec.rb +0 -13
  48. data/spec/models/record_mailer_spec.rb +30 -2
  49. data/spec/spec_helper.rb +3 -3
  50. data/tasks/blacklight.rake +5 -1
  51. metadata +8 -6
@@ -1,4 +1,4 @@
1
1
  <% @documents.each do |document| %>
2
- <%= document.to_sms_text %>
2
+ <%= document.to_sms_text(@config) %>
3
3
  <%= t('blacklight.sms.text.url', :url => polymorphic_url(document, @url_gen_params) ) %>
4
4
  <% end %>
@@ -232,7 +232,7 @@ de:
232
232
  entry_name:
233
233
  default:
234
234
  one: Eintrag
235
- other: Enträge
235
+ other: Einträge
236
236
  grouped:
237
237
  default: 'gruppiertes Ergebnis'
238
238
 
data/docker-compose.yml CHANGED
@@ -7,8 +7,9 @@ services:
7
7
  dockerfile: .docker/app/Dockerfile
8
8
  args:
9
9
  - ALPINE_RUBY_VERSION
10
- volumes:
11
- - .:/app
10
+ # mounting . is causing seg-fault on macosx
11
+ #volumes:
12
+ #- .:/app
12
13
  depends_on:
13
14
  - solr
14
15
  ports:
@@ -16,6 +17,8 @@ services:
16
17
  environment:
17
18
  - SOLR_URL # Set via environment variable or use default defined in .env file
18
19
  - RAILS_VERSION # Set via environment variable or use default defined in .env file
20
+ - SOLR_ENV=docker-compose
21
+ - ENGINE_CART_RAILS_OPTIONS=--skip-git --skip-listen --skip-spring --skip-keeps --skip-action-cable --skip-coffee --skip-test --skip-solr
19
22
 
20
23
  solr:
21
24
  environment:
@@ -58,6 +58,8 @@ module Blacklight
58
58
  # Rendering:
59
59
  # @!attribute presenter
60
60
  # @return [Blacklight::FacetFieldPresenter]
61
+ # @!attribute item_presenter
62
+ # @return [Blacklight::FacetItemPresenter]
61
63
  # @!attribute component
62
64
  # @return [Blacklight::FacetFieldListComponent]
63
65
  # @!attribute item_component
@@ -101,6 +101,9 @@ module Blacklight
101
101
  show: { top_level_config: :show },
102
102
  citation: { parent_config: :show }
103
103
  ),
104
+ # SMS and Email configurations.
105
+ sms: ViewConfig.new,
106
+ email: ViewConfig.new,
104
107
  # Configurations for specific types of index views
105
108
  view: NestedOpenStructWithHashAccess.new(ViewConfig,
106
109
  list: {},
@@ -167,6 +170,12 @@ module Blacklight
167
170
  # solr fields to use for sorting results
168
171
  define_field_access :sort_field
169
172
 
173
+ # solr fields to use in text message
174
+ define_field_access :sms_field
175
+
176
+ # solr fields to use in email message
177
+ define_field_access :email_field
178
+
170
179
  def initialize(hash = {})
171
180
  super(self.class.default_values.deep_dup.merge(hash))
172
181
  yield(self) if block_given?
@@ -48,5 +48,7 @@ module Blacklight
48
48
  config.action_dispatch.rescue_responses["Blacklight::Exceptions::RecordNotFound"] = :not_found
49
49
 
50
50
  config.enable_search_bar_autofocus = false
51
+
52
+ config.facet_missing_param = '[* TO *]'
51
53
  end
52
54
  end
@@ -4,6 +4,8 @@ module Blacklight
4
4
  class SearchState
5
5
  # Modeling access to filter query parameters
6
6
  class FilterField
7
+ MISSING = { missing: true }.freeze
8
+
7
9
  # @param [Blacklight::Configuration::FacetField] config
8
10
  attr_reader :config
9
11
 
@@ -25,7 +27,9 @@ module Blacklight
25
27
  def add(item)
26
28
  new_state = search_state.reset_search
27
29
 
28
- if item.respond_to?(:fq)
30
+ if item.try(:missing)
31
+ # if this is a 'missing' facet value, the :fq is only for backwards compatibility
32
+ elsif item.respond_to?(:fq)
29
33
  Array(item.fq).each do |f, v|
30
34
  new_state = new_state.filter(f).add(v)
31
35
  end
@@ -35,21 +39,28 @@ module Blacklight
35
39
  return new_state.filter(item.field).add(item)
36
40
  end
37
41
 
42
+ url_key = key
38
43
  params = new_state.params
39
44
  param = :f
40
45
  value = as_url_parameter(item)
46
+
47
+ if value == Blacklight::SearchState::FilterField::MISSING
48
+ url_key = "-#{key}"
49
+ value = Blacklight::Engine.config.facet_missing_param
50
+ end
51
+
41
52
  param = :f_inclusive if value.is_a?(Array)
42
53
 
43
54
  # value could be a string
44
55
  params[param] = (params[param] || {}).dup
45
56
 
46
57
  if value.is_a? Array
47
- params[param][key] = value
58
+ params[param][url_key] = value
48
59
  elsif config.single
49
- params[param][key] = [value]
60
+ params[param][url_key] = [value]
50
61
  else
51
- params[param][key] = Array(params[param][key] || []).dup
52
- params[param][key].push(value)
62
+ params[param][url_key] = Array(params[param][url_key] || []).dup
63
+ params[param][url_key].push(value)
53
64
  end
54
65
 
55
66
  new_state.reset(params)
@@ -63,19 +74,26 @@ module Blacklight
63
74
  return new_state.filter(item.field).remove(item)
64
75
  end
65
76
 
77
+ url_key = config.key
66
78
  params = new_state.params
67
79
 
68
80
  param = :f
69
81
  value = as_url_parameter(item)
82
+
83
+ if value == Blacklight::SearchState::FilterField::MISSING
84
+ url_key = "-#{key}"
85
+ value = Blacklight::Engine.config.facet_missing_param
86
+ end
87
+
70
88
  param = :f_inclusive if value.is_a?(Array)
71
89
 
72
90
  # need to dup the facet values too,
73
91
  # if the values aren't dup'd, then the values
74
92
  # from the session will get remove in the show view...
75
93
  params[param] = (params[param] || {}).dup
76
- params[param][key] = (params[param][key] || []).dup
94
+ params[param][url_key] = (params[param][url_key] || []).dup
77
95
 
78
- collection = params[param][key]
96
+ collection = params[param][url_key]
79
97
  # collection should be an array, because we link to ?f[key][]=value,
80
98
  # however, Facebook (and maybe some other PHP tools) tranform that parameters
81
99
  # into ?f[key][0]=value, which Rails interprets as a Hash.
@@ -84,18 +102,10 @@ module Blacklight
84
102
  collection = collection.values
85
103
  end
86
104
 
87
- params[param][key] = collection - Array(value)
88
- params[param].delete(key) if params[param][key].empty?
105
+ params[param][url_key] = collection - Array(value)
106
+ params[param].delete(url_key) if params[param][url_key].empty?
89
107
  params.delete(param) if params[param].empty?
90
108
 
91
- # Handle missing field queries.
92
- missing = I18n.t("blacklight.search.facets.missing")
93
- if (item.respond_to?(:fq) && item.fq == "-#{key}:[* TO *]") ||
94
- item == missing
95
- params[param].delete("-#{key}:")
96
- params[param].delete(key) if params[param][key] == [""]
97
- end
98
-
99
109
  new_state.reset(params)
100
110
  end
101
111
 
@@ -104,8 +114,9 @@ module Blacklight
104
114
  params = search_state.params
105
115
  f = Array(params.dig(:f, key))
106
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 }
107
118
 
108
- f + (f_inclusive || [])
119
+ f + (f_inclusive || []) + (f_missing || [])
109
120
  end
110
121
  delegate :any?, to: :values
111
122
 
@@ -121,6 +132,8 @@ module Blacklight
121
132
 
122
133
  if value.is_a?(Array)
123
134
  (params.dig(:f_inclusive, key) || []).to_set == value.to_set
135
+ elsif value == Blacklight::SearchState::FilterField::MISSING
136
+ (params.dig(:f, "-#{key}") || []).include?(Blacklight::Engine.config.facet_missing_param)
124
137
  else
125
138
  (params.dig(:f, key) || []).include?(value)
126
139
  end
@@ -130,7 +143,9 @@ module Blacklight
130
143
 
131
144
  # TODO: this code is duplicated in Blacklight::FacetsHelperBehavior
132
145
  def as_url_parameter(item)
133
- if item.respond_to? :value
146
+ if item.respond_to?(:missing) && item.missing
147
+ Blacklight::SearchState::FilterField::MISSING
148
+ elsif item.respond_to? :value
134
149
  item.value
135
150
  else
136
151
  item
@@ -61,6 +61,10 @@ module Blacklight::Solr::Response::Facets
61
61
  @options[:data] || {}
62
62
  end
63
63
 
64
+ def response
65
+ @options[:response]
66
+ end
67
+
64
68
  def index?
65
69
  sort == 'index'
66
70
  end
@@ -171,7 +175,8 @@ module Blacklight::Solr::Response::Facets
171
175
  # legacy solr facet.missing serialization
172
176
  if value.nil?
173
177
  i.label = I18n.t(:"blacklight.search.fields.facet.missing.#{facet_field_name}", default: [:"blacklight.search.facets.missing"])
174
- i.fq = "-#{facet_field_name}:[* TO *]"
178
+ i.fq = "-#{facet_field_name}:[* TO *]" # this explicit fq is deprecated; the missing attribute below is a better thing to check for this case
179
+ i.value = Blacklight::SearchState::FilterField::MISSING
175
180
  i.missing = true
176
181
  end
177
182
 
@@ -179,7 +184,7 @@ module Blacklight::Solr::Response::Facets
179
184
  end
180
185
 
181
186
  options = facet_field_aggregation_options(facet_field_name)
182
- facet_field = FacetField.new(facet_field_name, items, options)
187
+ facet_field = FacetField.new(facet_field_name, items, options.merge(response: self))
183
188
 
184
189
  if values[nil]
185
190
  facet_field.missing = items.find(&:missing)
@@ -212,7 +217,9 @@ module Blacklight::Solr::Response::Facets
212
217
 
213
218
  items = items.sort_by(&:hits).reverse if facet_field.sort && facet_field.sort.to_sym == :count
214
219
 
215
- hash[field_name] = Blacklight::Solr::Response::Facets::FacetField.new field_name, items
220
+ facet_field = Blacklight::Solr::Response::Facets::FacetField.new field_name, items, response: response
221
+
222
+ hash[field_name] = facet_field
216
223
  end
217
224
  end
218
225
 
@@ -243,7 +250,9 @@ module Blacklight::Solr::Response::Facets
243
250
 
244
251
  # alias all the possible blacklight config names..
245
252
  blacklight_config.facet_fields.select { |_k, v| v.pivot && v.pivot.join(",") == field_name }.each_key do |key|
246
- hash[key] = Blacklight::Solr::Response::Facets::FacetField.new key, items
253
+ facet_field = Blacklight::Solr::Response::Facets::FacetField.new key, items, response: self
254
+
255
+ hash[key] = facet_field
247
256
  end
248
257
  end
249
258
  end
@@ -287,7 +296,7 @@ module Blacklight::Solr::Response::Facets
287
296
  i
288
297
  end
289
298
 
290
- options = facet_field_aggregation_options(facet_field_name).merge(data: data)
299
+ options = facet_field_aggregation_options(facet_field_name).merge(data: data, response: self)
291
300
  facet_field = FacetField.new(facet_field_name, items, options)
292
301
 
293
302
  facet_field.missing = Blacklight::Solr::Response::Facets::FacetItem.new(
@@ -10,7 +10,6 @@ module Blacklight::Solr
10
10
  :add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr,
11
11
  :add_sorting_to_solr, :add_group_config_to_solr,
12
12
  :add_facet_paging_to_solr, :add_adv_search_clauses,
13
- :add_missing_field_query,
14
13
  :add_additional_filters
15
14
  ]
16
15
  end
@@ -82,19 +81,6 @@ module Blacklight::Solr
82
81
  end
83
82
  end
84
83
 
85
- ##
86
- # Build and append a missing field query.
87
- ##
88
- def add_missing_field_query(solr_parameters)
89
- return unless solr_parameters["facet.missing"]
90
-
91
- solr_parameters[:fq] = [] if solr_parameters[:fq].blank?
92
-
93
- solr_parameters[:fq].append(*(blacklight_params["f"] || [])
94
- .select { |f| f.match(/^-/) }
95
- .map { |k, _v| "#{k}[* TO *]" })
96
- end
97
-
98
84
  def add_additional_filters(solr_parameters, additional_filters = nil)
99
85
  q = additional_filters || @additional_filters
100
86
 
@@ -384,6 +370,8 @@ module Blacklight::Solr
384
370
  elsif value.is_a?(Range)
385
371
  prefix = "{!#{local_params.join(' ')}}" unless local_params.empty?
386
372
  "#{prefix}#{solr_field}:[#{value.first} TO #{value.last}]"
373
+ elsif value == Blacklight::SearchState::FilterField::MISSING
374
+ "-#{solr_field}:[* TO *]"
387
375
  else
388
376
  "{!term f=#{solr_field}#{(' ' + local_params.join(' ')) unless local_params.empty?}}#{convert_to_term_value(value)}"
389
377
  end
data/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "blacklight-frontend",
3
- "version": "7.20.1",
4
- "description": "[![Build Status](https://travis-ci.com/projectblacklight/blacklight.png?branch=master)](https://travis-ci.com/projectblacklight/blacklight) [![Gem Version](https://badge.fury.io/rb/blacklight.png)](http://badge.fury.io/rb/blacklight) [![Coverage Status](https://coveralls.io/repos/github/projectblacklight/blacklight/badge.svg?branch=master)](https://coveralls.io/github/projectblacklight/blacklight?branch=master)",
3
+ "version": "7.21.2",
4
+ "description": "[![Build Status](https://travis-ci.com/projectblacklight/blacklight.png?branch=main)](https://travis-ci.com/projectblacklight/blacklight) [![Gem Version](https://badge.fury.io/rb/blacklight.png)](http://badge.fury.io/rb/blacklight) [![Coverage Status](https://coveralls.io/repos/github/projectblacklight/blacklight/badge.svg?branch=main)](https://coveralls.io/github/projectblacklight/blacklight?branch=main)",
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"
@@ -23,8 +23,10 @@
23
23
  "devDependencies": {
24
24
  "@babel/cli": "^7.2.3",
25
25
  "@babel/core": "^7.2.3",
26
+ "@babel/preset-env": "^7.16.0",
26
27
  "shx": "^0.3.2"
27
28
  },
29
+ "browserslist": "> 0.25%, not dead",
28
30
  "dependencies": {
29
31
  "bloodhound-js": "^1.2.3",
30
32
  "bootstrap": ">=4.3.1 <6.0.0",
@@ -501,6 +501,12 @@ RSpec.describe CatalogController, api: true do
501
501
  end
502
502
 
503
503
  describe "email", api: false do
504
+ let(:config) { Blacklight::Configuration.new }
505
+
506
+ before do
507
+ allow(controller).to receive(:blacklight_config).and_return(config)
508
+ end
509
+
504
510
  it "gives error if no TO parameter" do
505
511
  post :email, params: { id: doc_id }
506
512
  expect(request.flash[:error]).to eq "You must enter a recipient in order to send this message"
@@ -518,7 +524,7 @@ RSpec.describe CatalogController, api: true do
518
524
 
519
525
  it "redirects back to the record upon success" do
520
526
  allow(RecordMailer).to receive(:email_record)
521
- .with(anything, { to: 'test_email@projectblacklight.org', message: 'xyz' }, hash_including(host: 'test.host'))
527
+ .with(anything, { to: 'test_email@projectblacklight.org', message: 'xyz', config: config }, hash_including(host: 'test.host'))
522
528
  .and_return double(deliver: nil)
523
529
  post :email, params: { id: doc_id, to: 'test_email@projectblacklight.org', message: 'xyz' }
524
530
  expect(request.flash[:error]).to be_nil
@@ -533,6 +539,12 @@ RSpec.describe CatalogController, api: true do
533
539
  end
534
540
 
535
541
  describe "sms", api: false do
542
+ let(:config) { Blacklight::Configuration.new }
543
+
544
+ before do
545
+ allow(controller).to receive(:blacklight_config).and_return(config)
546
+ end
547
+
536
548
  it "gives error if no phone number is given" do
537
549
  post :sms, params: { id: doc_id, carrier: 'att' }
538
550
  expect(request.flash[:error]).to eq "You must enter a recipient's phone number in order to send this message"
@@ -562,7 +574,7 @@ RSpec.describe CatalogController, api: true do
562
574
  it "sends to the appropriate carrier email address" do
563
575
  expect(RecordMailer)
564
576
  .to receive(:sms_record)
565
- .with(anything, { to: '5555555555@txt.att.net' }, hash_including(host: 'test.host'))
577
+ .with(anything, { to: '5555555555@txt.att.net', config: config }, hash_including(host: 'test.host'))
566
578
  .and_return double(deliver: nil)
567
579
  post :sms, params: { id: doc_id, to: '5555555555', carrier: 'txt.att.net' }
568
580
  end
@@ -1,34 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe 'Accessibility testing', api: false, js: true do
4
- xit 'validates the home page' do
4
+ it 'validates the home page' do
5
5
  visit root_path
6
6
  expect(page).to be_accessible
7
7
  end
8
8
 
9
- xit 'validates the catalog page' do
9
+ it 'validates the catalog page' do
10
10
  visit root_path
11
11
  fill_in "q", with: 'history'
12
12
  click_button 'search'
13
13
 
14
- # aria-allowed-role doesn't like nav[role="region"]
15
- expect(page).to be_accessible(skipping: ['aria-allowed-role'])
14
+ expect(page).to be_accessible
16
15
 
17
16
  within '.card.blacklight-language_ssim' do
18
17
  click_button 'Language'
19
18
  click_link "Tibetan"
20
19
  end
21
20
 
22
- expect(page).to be_accessible(skipping: ['aria-allowed-role'])
21
+ expect(page).to be_accessible
23
22
  end
24
23
 
25
- xit 'validates the single results page' do
24
+ it 'validates the single results page' do
26
25
  visit solr_document_path('2007020969')
27
26
  expect(page).to be_accessible
28
27
  end
29
28
 
30
29
  def be_accessible(skipping: [])
31
30
  # typeahead does funny things with the search bar
32
- be_axe_clean.excluding('.tt-hint').skipping(skipping + [('color-contrast' if Bootstrap::VERSION < '5')])
31
+ be_axe_clean.excluding('.tt-hint').skipping(skipping + [('color-contrast' if Bootstrap::VERSION < '5')].compact)
33
32
  end
34
33
  end
@@ -32,8 +32,12 @@ RSpec.describe "Facet missing" do
32
32
  end
33
33
 
34
34
  context "unselecting the facet missing facet" do
35
- it "unselects the missig field facet" do
36
- visit root_path + "?f[-subject_geo_ssim:[* TO *]][]=&f[subject_geo_ssim][]="
35
+ it "unselects the missing field facet" do
36
+ visit root_path
37
+
38
+ within "#facet-subject_geo_ssim" do
39
+ click_link "[Missing]"
40
+ end
37
41
 
38
42
  within "#facet-subject_geo_ssim" do
39
43
  click_link "remove"
@@ -45,8 +49,12 @@ RSpec.describe "Facet missing" do
45
49
  end
46
50
 
47
51
  context "unselecting the facet missing constraint" do
48
- it "unselects the missig field facet" do
49
- visit root_path + "?f[-subject_geo_ssim:[* TO *]][]=&f[subject_geo_ssim][]="
52
+ it "unselects the missing field facet" do
53
+ visit root_path
54
+
55
+ within "#facet-subject_geo_ssim" do
56
+ click_link "[Missing]"
57
+ end
50
58
 
51
59
  within ".filter-subject_geo_ssim" do
52
60
  click_link "Remove constraint Region: [Missing]"
@@ -305,7 +305,7 @@ RSpec.describe Blacklight::FacetsHelperBehavior do
305
305
  let(:search_state) { double(has_facet?: false, add_facet_params_and_redirect: { controller: 'catalog' }) }
306
306
 
307
307
  before do
308
- allow(helper).to receive(:facet_configuration_for_field).with('simple_field').and_return(Blacklight::Configuration::FacetField.new(key: 'simple_field', query: nil, date: nil, helper_method: nil, single: false, url_method: nil))
308
+ allow(helper).to receive(:facet_configuration_for_field).with('simple_field').and_return(Blacklight::Configuration::FacetField.new(key: 'simple_field', query: nil, date: nil, helper_method: nil, single: false, url_method: nil, item_presenter: nil))
309
309
  allow(helper).to receive(:facet_display_value).and_return('Z')
310
310
  allow(helper).to receive(:search_state).and_return(search_state)
311
311
  allow(helper).to receive(:search_action_path) do |*args|
@@ -326,7 +326,7 @@ RSpec.describe Blacklight::FacetsHelperBehavior do
326
326
  let(:expected_html) { '<span class="facet-label"><a class="facet-select" rel="nofollow" href="/blabla">Z</a></span><span class="facet-count">10</span>' }
327
327
 
328
328
  it "uses that method" do
329
- allow(helper).to receive(:facet_configuration_for_field).with('simple_field').and_return(Blacklight::Configuration::FacetField.new(key: 'simple_field', query: nil, date: nil, helper_method: nil, single: false, url_method: :test_method))
329
+ allow(helper).to receive(:facet_configuration_for_field).with('simple_field').and_return(Blacklight::Configuration::FacetField.new(key: 'simple_field', query: nil, date: nil, helper_method: nil, single: false, url_method: :test_method, item_presenter: nil))
330
330
  allow(helper).to receive(:test_method).with('simple_field', item).and_return('/blabla')
331
331
  result = helper.render_facet_value('simple_field', item)
332
332
  expect(result).to be_equivalent_to(expected_html).respecting_element_order
@@ -345,28 +345,28 @@ RSpec.describe Blacklight::FacetsHelperBehavior do
345
345
 
346
346
  describe "#facet_display_value" do
347
347
  it "justs be the facet value for an ordinary facet" do
348
- allow(helper).to receive(:facet_configuration_for_field).with('simple_field').and_return(double(query: nil, date: nil, helper_method: nil, url_method: nil))
348
+ allow(helper).to receive(:facet_configuration_for_field).with('simple_field').and_return(double(query: nil, date: nil, helper_method: nil, url_method: nil, item_presenter: nil))
349
349
  expect(helper.facet_display_value('simple_field', 'asdf')).to eq 'asdf'
350
350
  end
351
351
 
352
352
  it "allows you to pass in a :helper_method argument to the configuration" do
353
- allow(helper).to receive(:facet_configuration_for_field).with('helper_field').and_return(double(query: nil, date: nil, url_method: nil, helper_method: :my_facet_value_renderer))
353
+ allow(helper).to receive(:facet_configuration_for_field).with('helper_field').and_return(double(query: nil, date: nil, url_method: nil, helper_method: :my_facet_value_renderer, item_presenter: nil))
354
354
  allow(helper).to receive(:my_facet_value_renderer).with('qwerty').and_return('abc')
355
355
  expect(helper.facet_display_value('helper_field', 'qwerty')).to eq 'abc'
356
356
  end
357
357
 
358
358
  it "extracts the configuration label for a query facet" do
359
- allow(helper).to receive(:facet_configuration_for_field).with('query_facet').and_return(double(query: { 'query_key' => { label: 'XYZ' } }, date: nil, helper_method: nil, url_method: nil))
359
+ allow(helper).to receive(:facet_configuration_for_field).with('query_facet').and_return(double(query: { 'query_key' => { label: 'XYZ' } }, date: nil, helper_method: nil, url_method: nil, item_presenter: nil))
360
360
  expect(helper.facet_display_value('query_facet', 'query_key')).to eq 'XYZ'
361
361
  end
362
362
 
363
363
  it "localizes the label for date-type facets" do
364
- allow(helper).to receive(:facet_configuration_for_field).with('date_facet').and_return(double('date' => true, :query => nil, :helper_method => nil, :url_method => nil))
364
+ allow(helper).to receive(:facet_configuration_for_field).with('date_facet').and_return(double('date' => true, :query => nil, :helper_method => nil, :url_method => nil, :item_presenter => nil))
365
365
  expect(helper.facet_display_value('date_facet', '2012-01-01')).to eq 'Sun, 01 Jan 2012 00:00:00 +0000'
366
366
  end
367
367
 
368
368
  it "localizes the label for date-type facets with the supplied localization options" do
369
- allow(helper).to receive(:facet_configuration_for_field).with('date_facet').and_return(double('date' => { format: :short }, :query => nil, :helper_method => nil, :url_method => nil))
369
+ allow(helper).to receive(:facet_configuration_for_field).with('date_facet').and_return(double('date' => { format: :short }, :query => nil, :helper_method => nil, :url_method => nil, :item_presenter => nil))
370
370
  expect(helper.facet_display_value('date_facet', '2012-01-01')).to eq '01 Jan 00:00'
371
371
  end
372
372
  end
@@ -162,28 +162,14 @@ RSpec.describe Blacklight::SearchState::FilterField do
162
162
 
163
163
  context "With facet.missing field" do
164
164
  let(:params) do
165
- { f: { some_field: [""], "-some_field:": [""] } }
165
+ { f: { "-some_field": ["[* TO *]"] } }
166
166
  end
167
167
 
168
168
  it "removes facet.missing facet params" do
169
169
  filter = search_state.filter("some_field")
170
- new_state = filter.remove(OpenStruct.new(fq: "-some_field:[* TO *]"))
170
+ new_state = filter.remove(OpenStruct.new(key: 'some_field', missing: true))
171
171
 
172
- expect(new_state.params).to eq("f" => {})
173
- end
174
- end
175
-
176
- context "With facet.missing field value" do
177
- let(:params) do
178
- { f: { some_field: [""], "-some_field:": [""] } }
179
- end
180
-
181
- it "removes facet.missing facet params" do
182
- missing = I18n.t("blacklight.search.facets.missing")
183
- filter = search_state.filter("some_field")
184
- new_state = filter.remove(missing)
185
-
186
- expect(new_state.params).to eq("f" => {})
172
+ expect(new_state.params).to eq({})
187
173
  end
188
174
  end
189
175
  end
@@ -543,6 +543,98 @@ RSpec.describe "Blacklight::Configuration", api: true do
543
543
  end
544
544
  end
545
545
 
546
+ describe "add_sms_field" do
547
+ it "takes hash form" do
548
+ config.add_sms_field("title_tsim", label: "Title")
549
+
550
+ expect(config.sms_fields["title_tsim"]).not_to be_nil
551
+ expect(config.sms_fields["title_tsim"].label).to eq "Title"
552
+ end
553
+
554
+ it "takes ShowField argument" do
555
+ config.add_sms_field("title_tsim", Blacklight::Configuration::SmsField.new(field: "title_display", label: "Title"))
556
+
557
+ expect(config.sms_fields["title_tsim"]).not_to be_nil
558
+ expect(config.sms_fields["title_tsim"].label).to eq "Title"
559
+ end
560
+
561
+ it "takes block form" do
562
+ config.add_sms_field("title_tsim") do |f|
563
+ f.label = "Title"
564
+ end
565
+
566
+ expect(config.sms_fields["title_tsim"]).not_to be_nil
567
+ expect(config.sms_fields["title_tsim"].label).to eq "Title"
568
+ end
569
+
570
+ it "creates default label humanized from field" do
571
+ config.add_sms_field("my_custom_field")
572
+
573
+ expect(config.sms_fields["my_custom_field"].label).to eq "My Custom Field"
574
+ end
575
+
576
+ it "raises on nil solr field name" do
577
+ expect { config.add_sms_field(nil) }.to raise_error ArgumentError
578
+ end
579
+
580
+ it "takes wild-carded field names and dereference them to solr fields" do
581
+ allow(config).to receive(:reflected_fields).and_return(
582
+ "some_field_display" => {},
583
+ "another_field_display" => {},
584
+ "a_facet_field" => {}
585
+ )
586
+ config.add_sms_field "*_display"
587
+
588
+ expect(config.sms_fields.keys).to eq %w[some_field_display another_field_display]
589
+ end
590
+ end
591
+
592
+ describe "add_email_field" do
593
+ it "takes hash form" do
594
+ config.add_email_field("title_tsim", label: "Title")
595
+
596
+ expect(config.email_fields["title_tsim"]).not_to be_nil
597
+ expect(config.email_fields["title_tsim"].label).to eq "Title"
598
+ end
599
+
600
+ it "takes ShowField argument" do
601
+ config.add_email_field("title_tsim", Blacklight::Configuration::EmailField.new(field: "title_display", label: "Title"))
602
+
603
+ expect(config.email_fields["title_tsim"]).not_to be_nil
604
+ expect(config.email_fields["title_tsim"].label).to eq "Title"
605
+ end
606
+
607
+ it "takes block form" do
608
+ config.add_email_field("title_tsim") do |f|
609
+ f.label = "Title"
610
+ end
611
+
612
+ expect(config.email_fields["title_tsim"]).not_to be_nil
613
+ expect(config.email_fields["title_tsim"].label).to eq "Title"
614
+ end
615
+
616
+ it "creates default label humanized from field" do
617
+ config.add_email_field("my_custom_field")
618
+
619
+ expect(config.email_fields["my_custom_field"].label).to eq "My Custom Field"
620
+ end
621
+
622
+ it "raises on nil solr field name" do
623
+ expect { config.add_email_field(nil) }.to raise_error ArgumentError
624
+ end
625
+
626
+ it "takes wild-carded field names and dereference them to solr fields" do
627
+ allow(config).to receive(:reflected_fields).and_return(
628
+ "some_field_display" => {},
629
+ "another_field_display" => {},
630
+ "a_facet_field" => {}
631
+ )
632
+ config.add_email_field "*_display"
633
+
634
+ expect(config.email_fields.keys).to eq %w[some_field_display another_field_display]
635
+ end
636
+ end
637
+
546
638
  describe "#default_search_field" do
547
639
  it "uses the field with a :default key" do
548
640
  config.add_search_field('search_field_1')