blacklight_range_limit 8.0.1 → 8.2.1

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +14 -46
  3. data/README.md +4 -4
  4. data/VERSION +1 -1
  5. data/app/assets/javascripts/blacklight_range_limit/range_limit_distro_facets.js +1 -1
  6. data/app/assets/javascripts/blacklight_range_limit/range_limit_plotting.js +27 -15
  7. data/app/assets/javascripts/blacklight_range_limit/range_limit_slider.js +29 -9
  8. data/app/components/blacklight_range_limit/range_facet_component.html.erb +48 -0
  9. data/app/components/blacklight_range_limit/range_facet_component.rb +29 -0
  10. data/app/components/blacklight_range_limit/range_form_component.html.erb +12 -0
  11. data/app/components/blacklight_range_limit/range_form_component.rb +46 -0
  12. data/app/components/blacklight_range_limit/range_segments_component.html.erb +3 -0
  13. data/app/components/blacklight_range_limit/range_segments_component.rb +26 -0
  14. data/app/helpers/range_limit_helper.rb +70 -79
  15. data/app/presenters/blacklight_range_limit/facet_field_presenter.rb +85 -0
  16. data/app/presenters/blacklight_range_limit/facet_item_presenter.rb +45 -0
  17. data/app/presenters/blacklight_range_limit/filter_field.rb +85 -0
  18. data/app/views/blacklight_range_limit/_range_segments.html.erb +7 -21
  19. data/app/views/blacklight_range_limit/range_segments.html.erb +1 -1
  20. data/app/views/catalog/range_limit_panel.html.erb +1 -0
  21. data/blacklight_range_limit.gemspec +1 -1
  22. data/config/locales/blacklight_range_limit.de.yml +13 -0
  23. data/config/locales/blacklight_range_limit.it.yml +13 -0
  24. data/lib/blacklight_range_limit/controller_override.rb +41 -24
  25. data/lib/blacklight_range_limit/engine.rb +4 -0
  26. data/lib/blacklight_range_limit/facet_field_config_override.rb +25 -0
  27. data/lib/blacklight_range_limit/range_limit_builder.rb +15 -39
  28. data/lib/blacklight_range_limit/segment_calculation.rb +2 -2
  29. data/lib/blacklight_range_limit.rb +31 -12
  30. data/lib/generators/blacklight_range_limit/install_generator.rb +3 -17
  31. data/solr/conf/schema.xml +0 -13
  32. data/solr/conf/solrconfig.xml +1 -0
  33. data/spec/components/range_facet_component_spec.rb +111 -0
  34. data/spec/features/a_javascript_spec.rb +4 -4
  35. data/spec/features/blacklight_range_limit_spec.rb +7 -6
  36. data/spec/helpers/blacklight_range_limit_helper_spec.rb +7 -7
  37. data/spec/presenters/facet_field_presenter_spec.rb +144 -0
  38. data/spec/presenters/facet_item_presenter_spec.rb +47 -0
  39. data/spec/presenters/filter_field_spec.rb +79 -0
  40. data/spec/spec_helper.rb +7 -0
  41. data/spec/support/presenter_test_helpers.rb +11 -0
  42. data/spec/test_app_templates/lib/generators/test_app_generator.rb +1 -1
  43. metadata +40 -17
  44. data/app/views/blacklight_range_limit/_range_limit_panel.html.erb +0 -90
  45. data/app/views/blacklight_range_limit/range_limit_panel.html.erb +0 -10
  46. data/lib/blacklight_range_limit/view_helper_override.rb +0 -100
  47. data/lib/generators/blacklight_range_limit/templates/search_history_controller.rb +0 -7
  48. data/spec/lib/blacklight_range_limit/view_helper_override_helper_spec.rb +0 -137
@@ -12,59 +12,35 @@ module BlacklightRangeLimit
12
12
 
13
13
  # Method added to to fetch proper things for date ranges.
14
14
  def add_range_limit_params(solr_params)
15
- ranged_facet_configs =
16
- blacklight_config.facet_fields.select { |key, config| config.range }
17
- # In ruby 1.8, hash.select returns an array of pairs, in ruby 1.9
18
- # it returns a hash. Turn it into a hash either way.
19
- ranged_facet_configs = Hash[ ranged_facet_configs ] unless ranged_facet_configs.kind_of?(Hash)
20
-
21
- ranged_facet_configs.each_pair do |field_key, config|
22
- solr_params["stats"] = "true"
23
- solr_params["stats.field"] ||= []
24
- solr_params["stats.field"] << config.field
25
-
26
- range_config = BlacklightRangeLimit.range_config(blacklight_config, config.field)
27
-
28
- hash = blacklight_params["range"] && blacklight_params["range"][field_key] ?
29
- blacklight_params["range"][field_key] :
30
- {}
15
+ ranged_facet_configs = blacklight_config.facet_fields.select { |_key, config| config.range }
16
+ return solr_params unless ranged_facet_configs.any?
31
17
 
32
- if !hash["missing"].blank?
33
- # missing specified in request params
34
- solr_params[:fq] ||= []
35
- solr_params[:fq] << "-#{config.field}:[* TO *]"
18
+ solr_params["stats"] = "true"
19
+ solr_params["stats.field"] ||= []
36
20
 
37
- elsif !(hash["begin"].blank? && hash["end"].blank?)
38
- # specified in request params, begin and/or end, might just have one
39
- start = hash["begin"].blank? ? "*" : hash["begin"]
40
- finish = hash["end"].blank? ? "*" : hash["end"]
21
+ ranged_facet_configs.each do |field_key, config|
22
+ solr_params["stats.field"] << config.field
41
23
 
42
- solr_params[:fq] ||= []
43
- solr_params[:fq] << "#{config.field}: [#{start} TO #{finish}]"
24
+ range_config = config.range_config
25
+ next if range_config[:segments] == false
44
26
 
45
- if (range_config[:segments] != false && start != "*" && finish != "*")
46
- # Add in our calculated segments, can only do with both boundaries.
47
- add_range_segments_to_solr!(solr_params, field_key, start.to_i, finish.to_i)
48
- end
27
+ selected_value = search_state.filter(config.key).values.first
28
+ range = (selected_value if selected_value.is_a? Range) || range_config[:assumed_boundaries]
49
29
 
50
- elsif (range_config[:segments] != false &&
51
- boundaries = range_config[:assumed_boundaries])
52
- # assumed_boundaries in config
53
- add_range_segments_to_solr!(solr_params, field_key, boundaries[0], boundaries[1])
54
- end
30
+ add_range_segments_to_solr!(solr_params, field_key, range.first, range.last) if range.present?
55
31
  end
56
32
 
57
- return solr_params
33
+ solr_params
58
34
  end
59
35
 
60
36
 
61
37
  # Another processing method, this one is NOT included in default processing chain,
62
38
  # it is specifically swapped in *instead of* add_range_limit_params for
63
39
  # certain ajax requests that only want to fetch range limit segments for
64
- # ONE field.
40
+ # ONE field.
65
41
  #
66
42
  # It turns off facetting and sets rows to 0 as well, only results for
67
- # single specified field are needed.
43
+ # single specified field are needed.
68
44
  #
69
45
  # Specified field and parameters are specified in incoming parameters
70
46
  # range_field, range_start, range_end
@@ -80,7 +56,7 @@ module BlacklightRangeLimit
80
56
  solr_params.delete("facet.field".to_sym)
81
57
 
82
58
  # We don't need any actual rows either
83
- solr_params[:rows] = 0
59
+ solr_params[:rows] = 0
84
60
 
85
61
  return solr_params
86
62
  end
@@ -17,11 +17,11 @@ module BlacklightRangeLimit
17
17
 
18
18
  return solr_params unless field_config
19
19
 
20
- range_config = BlacklightRangeLimit.range_config(blacklight_config, facet_field)
20
+ range_config = field_config.range_config
21
21
 
22
22
  solr_params[:"facet.query"] ||= []
23
23
 
24
- boundaries = boundaries_for_range_facets(min, max, (range_config[:num_segments] || 10) )
24
+ boundaries = boundaries_for_range_facets(min, max, range_config[:num_segments] || 10)
25
25
 
26
26
  # Now make the boundaries into actual filter.queries.
27
27
  0.upto(boundaries.length - 2) do |index|
@@ -1,9 +1,12 @@
1
1
  # BlacklightRangeLimit
2
+ require 'deprecation'
2
3
 
3
4
  module BlacklightRangeLimit
5
+ extend Deprecation
6
+
7
+ require 'blacklight_range_limit/facet_field_config_override'
4
8
  require 'blacklight_range_limit/range_limit_builder'
5
9
  require 'blacklight_range_limit/controller_override'
6
- require 'blacklight_range_limit/view_helper_override'
7
10
 
8
11
  require 'blacklight_range_limit/version'
9
12
  require 'blacklight_range_limit/engine'
@@ -22,24 +25,40 @@ module BlacklightRangeLimit
22
25
 
23
26
  # Add element to array only if it's not already there
24
27
  def self.safe_arr_add(array, element)
28
+ Deprecation.warn(BlacklightRangeLimit, 'BlacklightRangeLimit.safe_arr_add is deprecated without replacement')
25
29
  array << element unless array.include?(element)
26
30
  end
27
31
 
28
- # Convenience method for returning range config hash from
29
- # blacklight config, for a specific solr field, in a normalized
30
- # way.
31
- #
32
- # Returns false if range limiting not configured.
33
- # Returns hash even if configured to 'true'
34
- # for consistency.
35
32
  def self.range_config(blacklight_config, solr_field)
33
+ Deprecation.warn(BlacklightRangeLimit, 'BlacklightRangeLimit.range_config is deprecated without replacement')
36
34
  field = blacklight_config.facet_fields[solr_field.to_s]
37
35
 
38
- return false unless field && field.range
36
+ return false unless field&.range
39
37
 
40
- config = field.range
41
- config = { partial: field.partial } if config === true
38
+ if field.range == true
39
+ default_range_config
40
+ else
41
+ field.range.merge(partial: field.partial)
42
+ end
43
+ end
42
44
 
43
- config
45
+ def self.default_range_config
46
+ {
47
+ range: true,
48
+ range_config: {
49
+ num_segments: 10,
50
+ chart_js: true,
51
+ slider_js: true,
52
+ segments: true,
53
+ assumed_boundaries: nil,
54
+ maxlength: nil,
55
+ input_label_range_begin: nil,
56
+ input_label_range_end: nil
57
+ },
58
+ filter_class: BlacklightRangeLimit::FilterField,
59
+ presenter: BlacklightRangeLimit::FacetFieldPresenter,
60
+ item_presenter: BlacklightRangeLimit::FacetItemPresenter,
61
+ component: BlacklightRangeLimit::RangeFacetComponent
62
+ }
44
63
  end
45
64
  end
@@ -4,6 +4,8 @@ module BlacklightRangeLimit
4
4
  class InstallGenerator < Rails::Generators::Base
5
5
  source_root File.expand_path('../templates', __FILE__)
6
6
 
7
+ class_option :'builder-path', type: :string, default: 'app/models/search_builder.rb', aliases: "-b", desc: "Set the path, relative to Rails root, to the Blacklight app's search builder class"
8
+
7
9
  def copy_public_assets
8
10
  generate 'blacklight_range_limit:assets'
9
11
  end
@@ -15,7 +17,7 @@ module BlacklightRangeLimit
15
17
  end
16
18
 
17
19
  def install_search_builder
18
- path = 'app/models/search_builder.rb'
20
+ path = options[:'builder-path']
19
21
  if File.exist? path
20
22
  inject_into_file path, after: /include Blacklight::Solr::SearchBuilderBehavior.*$/ do
21
23
  "\n include BlacklightRangeLimit::RangeLimitBuilder\n"
@@ -25,22 +27,6 @@ module BlacklightRangeLimit
25
27
  end
26
28
  end
27
29
 
28
- # Adds range limit behavior to search history controller
29
- def install_search_history_controller
30
- path = 'app/controllers/search_history_controller.rb'
31
-
32
- # If local copy of search history controller exists, add range limit helpers
33
- if File.exist? path
34
- inject_into_file path, after: /include Blacklight::SearchHistory.*$/ do
35
- "\n helper BlacklightRangeLimit::ViewHelperOverride"\
36
- "\n helper RangeLimitHelper"
37
- end
38
- # Otherwise copies search history controller to application
39
- else
40
- copy_file 'search_history_controller.rb', path
41
- end
42
- end
43
-
44
30
  def install_routing_concern
45
31
  route('concern :range_searchable, BlacklightRangeLimit::Routes::RangeSearchable.new')
46
32
  end
data/solr/conf/schema.xml CHANGED
@@ -175,16 +175,6 @@
175
175
  <dynamicField name="*_coordinate" type="tdouble" indexed="true" stored="false" />
176
176
 
177
177
 
178
- <!-- location (_ll...) -->
179
-
180
- <dynamicField name="*_lli" type="location" stored="false" indexed="true" multiValued="false"/>
181
- <dynamicField name="*_llim" type="location" stored="false" indexed="true" multiValued="true"/>
182
-
183
- <dynamicField name="*_lls" type="location" stored="true" indexed="false" multiValued="false"/>
184
- <dynamicField name="*_llsm" type="location" stored="true" indexed="false" multiValued="true"/>
185
- <dynamicField name="*_llsi" type="location" stored="true" indexed="true" multiValued="false"/>
186
- <dynamicField name="*_llsim" type="location" stored="true" indexed="true" multiValued="true"/>
187
-
188
178
  <dynamicField name="*_srpt" type="location_rpt" stored="true" indexed="true" multiValued="true" />
189
179
  <dynamicField name="*_bbox" type="bbox" stored="true" indexed="true" />
190
180
 
@@ -263,9 +253,6 @@
263
253
  -->
264
254
  <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
265
255
 
266
- <!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
267
- <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
268
-
269
256
  <!-- An alternative geospatial field type new to Solr 4. It supports multiValued and polygon shapes.
270
257
  For more information about this and other Spatial fields new to Solr 4, see:
271
258
  http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
@@ -19,6 +19,7 @@
19
19
  <!-- solr lib dirs -->
20
20
  <lib dir="${solr.install.dir:../../../..}/contrib/analysis-extras/lib" />
21
21
  <lib dir="${solr.install.dir:../../../..}/contrib/analysis-extras/lucene-libs" />
22
+ <lib dir="${solr.install.dir:../../../..}/modules/analysis-extras/lib" />
22
23
 
23
24
  <dataDir>${solr.data.dir:}</dataDir>
24
25
 
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe BlacklightRangeLimit::RangeFacetComponent, type: :component do
6
+ subject(:component) do
7
+ described_class.new(facet_field: facet_field)
8
+ end
9
+
10
+ let(:rendered) do
11
+ Capybara::Node::Simple.new(render_inline(component))
12
+ end
13
+
14
+ let(:facet_field) do
15
+ instance_double(
16
+ BlacklightRangeLimit::FacetFieldPresenter,
17
+ key: 'key',
18
+ html_id: 'id',
19
+ active?: false,
20
+ collapsed?: false,
21
+ in_modal?: false,
22
+ label: 'My facet field',
23
+ selected_range: nil,
24
+ selected_range_facet_item: nil,
25
+ missing_facet_item: nil,
26
+ missing_selected?: false,
27
+ min: nil,
28
+ max: nil,
29
+ search_state: Blacklight::SearchState.new({}, nil),
30
+ range_config: {},
31
+ modal_path: nil,
32
+ facet_field: facet_config,
33
+ **facet_field_params
34
+ )
35
+ end
36
+
37
+ let(:facet_config) do
38
+ Blacklight::Configuration::FacetField.new(key: 'key', item_presenter: BlacklightRangeLimit::FacetItemPresenter)
39
+ end
40
+
41
+ let(:facet_field_params) { {} }
42
+
43
+ before do
44
+ allow(component).to receive(:search_facet_path).and_return('/range/key')
45
+ end
46
+
47
+ it 'renders into the default facet layout' do
48
+ expect(rendered).to have_selector('h3', text: 'My facet field')
49
+ .and have_selector('div.collapse')
50
+ end
51
+
52
+ it 'renders a placeholder profile area' do
53
+ expect(rendered).to have_selector('div.profile', text: '')
54
+ end
55
+
56
+ context 'with range data' do
57
+ let(:facet_field_params) do
58
+ {
59
+ range_queries: [
60
+ OpenStruct.new(value: 100..199, hits: 5),
61
+ OpenStruct.new(value: 200..300, hits: 3)
62
+ ],
63
+ min: 100,
64
+ max: 300
65
+ }
66
+ end
67
+
68
+ it 'renders the range data into the profile' do
69
+ expect(rendered).to have_selector('.profile li', count: 2)
70
+ .and have_selector('.profile li', text: '100 to 199')
71
+ .and have_selector('.profile li', text: '200 to 300')
72
+ end
73
+ end
74
+
75
+ it 'renders a form for the range' do
76
+ expect(rendered).to have_selector('form[action="http://test.host/catalog"][method="get"]')
77
+ .and have_field('range[key][begin]')
78
+ .and have_field('range[key][end]')
79
+ end
80
+
81
+ it 'renders a link to the modal' do
82
+ expect(rendered).to have_link 'View larger', href: '/range/key'
83
+ end
84
+
85
+ context 'within a modal' do
86
+ let(:facet_field_params) { { in_modal?: true } }
87
+
88
+ it 'does not link to the modal' do
89
+ expect(rendered).not_to have_link 'View larger'
90
+ end
91
+ end
92
+
93
+ it 'does not render the missing link if there are no matching documents' do
94
+ expect(rendered).not_to have_link '[Missing]'
95
+ end
96
+
97
+ context 'with missing documents' do
98
+ let(:facet_field_params) { { missing_facet_item: facet_item } }
99
+ let(:facet_item) do
100
+ Blacklight::Solr::Response::Facets::FacetItem.new(
101
+ value: Blacklight::SearchState::FilterField::MISSING,
102
+ hits: 50
103
+ )
104
+ end
105
+
106
+ it 'renders a facet value for the documents that are missing the field data' do
107
+ expected_facet_query_param = Regexp.new(Regexp.escape({ f: { '-key': ['[* TO *]'] } }.to_param))
108
+ expect(rendered).to have_link '[Missing]', href: expected_facet_query_param
109
+ end
110
+ end
111
+ end
@@ -23,13 +23,13 @@ describe 'JavaScript', js: true do
23
23
 
24
24
  context 'when assumed boundaries configured' do
25
25
  before do
26
- CatalogController.blacklight_config.facet_fields['pub_date_si'].range = {
27
- assumed_boundaries: [1990, 2000]
26
+ CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config = {
27
+ assumed_boundaries: 1990...2000
28
28
  }
29
29
  end
30
30
 
31
31
  after do
32
- CatalogController.blacklight_config.facet_fields['pub_date_si'].range = true
32
+ CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config = {}
33
33
  end
34
34
 
35
35
  it 'should show the range limit with set boundaries' do
@@ -48,7 +48,7 @@ describe 'JavaScript', js: true do
48
48
  click_button 'Publication Date Sort'
49
49
 
50
50
  within 'ul.subsection.missing' do
51
- expect(page).to have_link 'Unknown'
51
+ expect(page).to have_link '[Missing]'
52
52
  end
53
53
  end
54
54
  end
@@ -14,9 +14,10 @@ describe "Blacklight Range Limit" do
14
14
  it "should provide distribution information" do
15
15
  visit search_catalog_path
16
16
  click_link 'View distribution'
17
-
18
- expect(page).to have_content("1500 to 1599 0")
19
- expect(page).to have_content("2000 to 2008 12")
17
+ expect(page).to have_selector('a.facet-select', text: "1500 to 1599")
18
+ expect(page.find('a.facet-select', text: "1500 to 1599").ancestor('li')).to have_selector('span.facet-count', text: "0")
19
+ expect(page).to have_selector('a.facet-select', text: "2000 to 2008")
20
+ expect(page.find('a.facet-select', text: "2000 to 2008").ancestor('li')).to have_selector('span.facet-count', text: "12")
20
21
  end
21
22
 
22
23
  it "should limit appropriately" do
@@ -25,7 +26,7 @@ describe "Blacklight Range Limit" do
25
26
  click_link '2000 to 2008'
26
27
 
27
28
  within '.blacklight-pub_date_si' do
28
- expect(page).to have_content "2000 to 2008 [remove] 12"
29
+ expect(page).to have_content "2000 to 2008✖[remove]12"
29
30
  end
30
31
 
31
32
  within '.constraints-container' do
@@ -39,7 +40,7 @@ describe "Blacklight Range Limit" do
39
40
  visit search_catalog_path(page: 2)
40
41
  click_link 'View distribution'
41
42
  click_link '2000 to 2008'
42
- click_button 'Apply'
43
+ click_button 'Apply', match: :first
43
44
  expect(page.current_url).not_to include('page')
44
45
  end
45
46
 
@@ -67,7 +68,7 @@ describe "Blacklight Range Limit with configured input labels" do
67
68
  before do
68
69
  CatalogController.blacklight_config = Blacklight::Configuration.new
69
70
  CatalogController.configure_blacklight do |config|
70
- config.add_facet_field 'pub_date_si', range: {
71
+ config.add_facet_field 'pub_date_si', **CatalogController.default_range_config, range_config: {
71
72
  input_label_range_begin: 'from publication date',
72
73
  input_label_range_end: 'to publication date',
73
74
  maxlength: 6
@@ -1,6 +1,11 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe "Blacklight Range Limit Helper" do
4
+ let(:config) { Blacklight::Configuration.new }
5
+ before do
6
+ allow(helper).to receive(:blacklight_config).and_return(config)
7
+ allow(helper).to receive(:search_state).and_return(Blacklight::SearchState.new({}, config))
8
+ end
4
9
 
5
10
  it "should render range text fields with/without labels" do
6
11
  begin_html = Capybara.string(helper.render_range_input('pub_date', 'begin'))
@@ -17,21 +22,16 @@ describe "Blacklight Range Limit Helper" do
17
22
  end
18
23
 
19
24
  context "when building requests" do
20
- let(:config) { Blacklight::Configuration.new }
21
- before do
22
- allow(helper).to receive(:blacklight_config).and_return(config)
23
- end
24
-
25
25
  it "should exclude page when adding a range" do
26
26
  params = { q: '', page: '2' }
27
27
  updated_params = helper.add_range('test', '1900', '1995', params)
28
- expect(updated_params).not_to include(:page)
28
+ expect(updated_params.to_h).not_to include(:page)
29
29
  end
30
30
 
31
31
  it "should exclude page when adding a missing range" do
32
32
  params = { q: '', page: '2' }
33
33
  updated_params = helper.add_range_missing('test', params)
34
- expect(updated_params).not_to include(:page)
34
+ expect(updated_params.to_h).not_to include(:page)
35
35
  end
36
36
  end
37
37
  end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe BlacklightRangeLimit::FacetFieldPresenter, type: :presenter do
6
+ subject(:presenter) do
7
+ described_class.new(facet_field, display_facet, view_context, search_state)
8
+ end
9
+ let(:view_context) { controller.view_context }
10
+ let(:search_state) { Blacklight::SearchState.new(params, blacklight_config, view_context) }
11
+
12
+ let(:facet_field) do
13
+ Blacklight::Configuration::FacetField.new(
14
+ key: 'field_key',
15
+ field: 'some_field',
16
+ filter_class: BlacklightRangeLimit::FilterField
17
+ )
18
+ end
19
+ let(:blacklight_config) do
20
+ Blacklight::Configuration.new.tap { |x| x.facet_fields['field_key'] = facet_field }
21
+ end
22
+ let(:params) { {} }
23
+
24
+ let(:display_facet) do
25
+ instance_double(Blacklight::Solr::Response::Facets::FacetField, items: [], response: response)
26
+ end
27
+ let(:response) do
28
+ Blacklight::Solr::Response.new(
29
+ {
30
+ response: { numFound: 5 },
31
+ stats: {
32
+ stats_fields: {
33
+ some_field: some_field_stats
34
+ }
35
+ }
36
+ },
37
+ nil
38
+ )
39
+ end
40
+
41
+ let(:some_field_stats) { {} }
42
+
43
+ describe '#range_queries' do
44
+ let(:response) do
45
+ {
46
+ 'facet_counts' => {
47
+ 'facet_queries' => {
48
+ 'some_field:[150 TO 199]' => 15,
49
+ 'some_field:[100 TO 149]' => 5,
50
+ 'some_field:[200 TO 249]' => 4,
51
+ 'irrelevant_field:[A TO C]' => 18
52
+ }
53
+ }
54
+ }
55
+ end
56
+
57
+ it 'extracts range data from the facet queries response' do
58
+ expect(presenter.range_queries.count).to eq 3
59
+ expect(presenter.range_queries.map(&:value)).to eq [100..149, 150..199, 200..249]
60
+ end
61
+ end
62
+
63
+ describe '#min' do
64
+ let(:some_field_stats) do
65
+ {
66
+ max: 999.00,
67
+ min: 700.0000,
68
+ missing: 0
69
+ }
70
+ end
71
+
72
+ it 'extracts the min stat, stringifies it (for some reason), and truncates it' do
73
+ expect(presenter.min).to eq '700'
74
+ end
75
+
76
+ context 'when all documents in the response are missing data' do
77
+ let(:some_field_stats) do
78
+ {
79
+ max: -345,
80
+ min: -999,
81
+ missing: 5
82
+ }
83
+ end
84
+
85
+ it 'returns nil' do
86
+ expect(presenter.min).to be_nil
87
+ end
88
+ end
89
+ end
90
+
91
+ describe '#max' do
92
+ let(:some_field_stats) do
93
+ {
94
+ max: 999.00,
95
+ min: 700.0000,
96
+ missing: 0
97
+ }
98
+ end
99
+
100
+ it 'extracts the ,ax stat, stringifies it (for some reason), and truncates it' do
101
+ expect(presenter.max).to eq '999'
102
+ end
103
+
104
+ context 'when all documents in the response are missing data' do
105
+ let(:some_field_stats) do
106
+ {
107
+ max: -345,
108
+ min: -999,
109
+ missing: 5
110
+ }
111
+ end
112
+
113
+ it 'returns nil' do
114
+ expect(presenter.max).to be_nil
115
+ end
116
+ end
117
+ end
118
+
119
+ describe '#missing_facet_item' do
120
+ let(:some_field_stats) do
121
+ {
122
+ missing: 5
123
+ }
124
+ end
125
+
126
+ it 'extracts the missing stat' do
127
+ expect(presenter.missing_facet_item.hits).to eq 5
128
+ end
129
+ end
130
+
131
+ describe '#selected_range' do
132
+ it 'returns nil if no range is selected' do
133
+ expect(presenter.selected_range).to eq nil
134
+ end
135
+
136
+ context 'with a user-selected range' do
137
+ let(:params) { { range: { field_key: { begin: 100, end: 250 } } } }
138
+
139
+ it 'returns the selected range' do
140
+ expect(presenter.selected_range).to eq 100..250
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe BlacklightRangeLimit::FacetItemPresenter, type: :presenter do
6
+ subject(:presenter) do
7
+ described_class.new(facet_item, facet_config, view_context, facet_field, search_state)
8
+ end
9
+
10
+ let(:facet_item) { instance_double(Blacklight::Solr::Response::Facets::FacetItem) }
11
+ let(:filter_field) { instance_double(Blacklight::SearchState::FilterField, include?: true) }
12
+ let(:facet_config) { Blacklight::Configuration::FacetField.new(key: 'key') }
13
+ let(:facet_field) { instance_double(Blacklight::Solr::Response::Facets::FacetField) }
14
+ let(:view_context) { controller.view_context }
15
+ let(:search_state) { instance_double(Blacklight::SearchState, filter: filter_field) }
16
+
17
+ describe '#label' do
18
+ context 'with a single value' do
19
+ let(:facet_item) { 'blah' }
20
+
21
+ it 'uses the normal logic for item values' do
22
+ expect(presenter.label).to eq 'blah'
23
+ end
24
+ end
25
+
26
+ context 'with a range' do
27
+ let(:facet_item) { 1234..2345 }
28
+
29
+ it 'translates the range into some nice, human-readable html' do
30
+ expect(Capybara.string(presenter.label))
31
+ .to have_text('1234 to 2345')
32
+ .and have_css('span.from[data-blrl-begin=1234]', text: '1234')
33
+ .and have_css('span.to[data-blrl-end=2345]', text: '2345')
34
+ end
35
+ end
36
+
37
+ context 'with a range that has the same start + end values' do
38
+ let(:facet_item) { 2021..2021 }
39
+
40
+ it 'translates the range into some nice, human-readable html' do
41
+ expect(Capybara.string(presenter.label))
42
+ .to have_text('2021')
43
+ .and have_css('span.single[data-blrl-single=2021]', text: '2021')
44
+ end
45
+ end
46
+ end
47
+ end