blacklight 7.20.1 → 7.22.0

Sign up to get free protection for your applications and to get access to all the features.
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')