ddr-models 2.5.3 → 2.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/users/sessions_controller.rb +0 -5
  3. data/config/initializers/devise.rb +3 -2
  4. data/config/initializers/rsolr_monkey_patches.rb +7 -0
  5. data/config/initializers/subscriptions.rb +0 -2
  6. data/ddr-models.gemspec +2 -1
  7. data/lib/ddr/actions/virus_check.rb +0 -1
  8. data/lib/ddr/auth.rb +0 -4
  9. data/lib/ddr/auth/ability_definitions/role_based_ability_definitions.rb +9 -16
  10. data/lib/ddr/derivatives/generator.rb +0 -2
  11. data/lib/ddr/derivatives/png_generator.rb +2 -4
  12. data/lib/ddr/derivatives/ptif_generator.rb +6 -7
  13. data/lib/ddr/index/fields.rb +18 -2
  14. data/lib/ddr/jobs.rb +0 -4
  15. data/lib/ddr/managers.rb +0 -1
  16. data/lib/ddr/managers/derivatives_manager.rb +3 -4
  17. data/lib/ddr/managers/workflow_manager.rb +3 -0
  18. data/lib/ddr/models.rb +6 -3
  19. data/lib/ddr/models/base.rb +13 -0
  20. data/lib/ddr/models/has_admin_metadata.rb +4 -20
  21. data/lib/ddr/models/indexing.rb +16 -0
  22. data/lib/ddr/models/solr_document.rb +8 -0
  23. data/lib/ddr/models/version.rb +1 -1
  24. data/lib/ddr/models/year_facet.rb +60 -118
  25. data/spec/auth/ability_spec.rb +1 -1
  26. data/spec/auth/roles/role_spec.rb +9 -9
  27. data/spec/index/fields_spec.rb +96 -0
  28. data/spec/models/active_fedora_datastream_spec.rb +6 -5
  29. data/spec/models/has_admin_metadata_spec.rb +49 -125
  30. data/spec/models/indexing_spec.rb +50 -18
  31. data/spec/models/solr_document_spec.rb +28 -0
  32. data/spec/models/year_facet_spec.rb +49 -22
  33. data/spec/support/shared_examples_for_ddr_models.rb +54 -2
  34. metadata +21 -8
  35. data/lib/ddr/jobs/permanent_id.rb +0 -35
  36. data/lib/ddr/managers/permanent_id_manager.rb +0 -93
@@ -20,12 +20,14 @@ module Ddr
20
20
  ACCESS_ROLE => roles.to_json,
21
21
  ADMIN_SET => admin_set,
22
22
  ADMIN_SET_TITLE => admin_set_title,
23
+ ARRANGER_FACET => desc_metadata_values('arranger'),
23
24
  ASPACE_ID => aspace_id,
24
25
  ATTACHED_FILES_HAVING_CONTENT => attached_files_having_content.keys,
25
26
  BOX_NUMBER_FACET => desc_metadata_values('box_number'),
26
27
  CATEGORY_FACET => desc_metadata_values('category'),
27
28
  COLLECTION_TITLE => collection_title,
28
29
  COMPANY_FACET => desc_metadata_values('company'),
30
+ COMPOSER_FACET => desc_metadata_values('composer'),
29
31
  CONTRIBUTOR_FACET => contributor,
30
32
  CREATOR_FACET => creator,
31
33
  DATE_FACET => date,
@@ -34,33 +36,47 @@ module Ddr
34
36
  DISPLAY_FORMAT => display_format,
35
37
  DOI => adminMetadata.doi,
36
38
  EAD_ID => ead_id,
39
+ ENGRAVER_FACET => desc_metadata_values('engraver'),
37
40
  FOLDER_FACET => desc_metadata_values('folder'),
38
41
  FORMAT_FACET => format,
42
+ GENRE_FACET => desc_metadata_values('genre'),
39
43
  IDENTIFIER_ALL => all_identifiers,
44
+ ILLUSTRATED_FACET => desc_metadata_values('illustrated'),
45
+ ILLUSTRATOR_FACET => desc_metadata_values('illustrator'),
46
+ INSTRUMENTATION_FACET => desc_metadata_values('instrumentation'),
40
47
  INTERNAL_URI => internal_uri,
48
+ INTERVIEWER_NAME_FACET => desc_metadata_values('interviewer_name'),
41
49
  IS_LOCKED => is_locked,
42
50
  LICENSE => license,
43
51
  LICENSE_DESCRIPTION => rightsMetadata.license.description.first,
44
52
  LICENSE_TITLE => rightsMetadata.license.title.first,
45
53
  LICENSE_URL => rightsMetadata.license.url.first,
54
+ LITHOGRAPHER_FACET => desc_metadata_values('lithographer'),
46
55
  LOCAL_ID => local_id,
56
+ LYRICIST_FACET => desc_metadata_values('lyricist'),
47
57
  MEDIUM_FACET => desc_metadata_values('medium'),
58
+ PERFORMER_FACET => desc_metadata_values('performer'),
48
59
  PERMANENT_ID => permanent_id,
49
60
  PERMANENT_URL => permanent_url,
50
61
  PLACEMENT_COMPANY_FACET => desc_metadata_values('placement_company'),
51
62
  POLICY_ROLE => roles.in_policy_scope.agents,
63
+ PRODUCER_FACET => desc_metadata_values('producer'),
52
64
  PRODUCT_FACET => desc_metadata_values('product'),
53
65
  PUBLICATION_FACET => desc_metadata_values('publication'),
54
66
  PUBLISHER_FACET => publisher,
55
67
  RESEARCH_HELP_CONTACT => research_help_contact,
56
68
  RESOURCE_ROLE => roles.in_resource_scope.agents,
69
+ ROLL_NUMBER_FACET => desc_metadata_values('roll_number'),
57
70
  SERIES_FACET => desc_metadata_values('series'),
58
71
  SETTING_FACET => desc_metadata_values('setting'),
59
72
  SPATIAL_FACET => desc_metadata_values('spatial'),
60
73
  SUBJECT_FACET => subject,
74
+ SUBSERIES_FACET => desc_metadata_values('subseries'),
75
+ TEMPORAL_FACET => desc_metadata_values('temporal'),
61
76
  TITLE => title_display,
62
77
  TONE_FACET => desc_metadata_values('tone'),
63
78
  TYPE_FACET => type,
79
+ VOLUME_FACET => desc_metadata_values('volume'),
64
80
  WORKFLOW_STATE => workflow_state,
65
81
  YEAR_FACET => year_facet,
66
82
  }
@@ -18,6 +18,14 @@ module Ddr::Models
18
18
  end
19
19
  raise NotFound, "SolrDocument not found for \"#{pid_or_uri}\"."
20
20
  end
21
+
22
+ def find_by_permanent_id(ark)
23
+ query = Ddr::Index::Query.new { where permanent_id: ark }
24
+ if doc = query.docs.first
25
+ return doc
26
+ end
27
+ raise NotFound, "SolrDocument not found for permanent id \"#{ark}\"."
28
+ end
21
29
  end
22
30
 
23
31
  def inspect
@@ -1,5 +1,5 @@
1
1
  module Ddr
2
2
  module Models
3
- VERSION = "2.5.3"
3
+ VERSION = "2.6.0.rc1"
4
4
  end
5
5
  end
@@ -1,153 +1,95 @@
1
1
  require "date"
2
+ require "edtf"
2
3
 
3
4
  module Ddr::Models
4
5
  class YearFacet
5
6
 
6
7
  EARLIEST_YEAR = 1000
8
+ LATEST_YEAR = Date.today.year + 100
9
+ VALID_YEARS = (EARLIEST_YEAR..LATEST_YEAR)
10
+ VALUE_SEP = /;/
7
11
 
8
12
  # Between 1965 and 1968
9
13
  BETWEEN = Regexp.new '\A([Bb]etween\s+)(\d{4})(\s+and\s+)(\d{4})\??\z'
10
14
 
11
- # YYYx (192x)
12
- # YYYX (192X)
13
- # YYY? (192?)
14
- # YYY- (192-)
15
- # YYY-? (192-?)
16
- IN_DECADE = Regexp.new '\A(\d{3})([xX\-]\??|\?)\z'
17
-
18
- # YYxx (19xx)
19
- IN_CENTURY = Regexp.new '\A(\d{2})xx\z'
20
-
21
- # YYY0s (1920s)
22
- # YYY0s? (1920s?)
23
- DECADE = Regexp.new '\A(\d{3}0)s\??\z'
24
-
25
- # YYYY-MM (2010-01)
26
- # YYYY/MM (2010/01)
27
- YEAR_MONTH = Regexp.new '\A(\d{4})[/-](0[1-9]|1[0-2])\z'
28
-
29
- # YYYY-YYYY (1935-2010)
30
- # YYYY/YYYY (1935/2010)
31
- YEAR_RANGE = Regexp.new '\A(\d{4})[/-](\d{4})\z'
32
-
33
- # YYYY (1979)
34
- YEAR = Regexp.new '\A\d{4}\z'
35
-
36
- SQUARE_BRACKETS = Regexp.new '[\[\]]'
37
-
38
- # c. 1920
39
- # ca. 1920
40
- # c1920
15
+ # circa 1920, ca. 1920, c1920 => 1920
41
16
  CIRCA = Regexp.new '\b(circa\s+|ca?\.\s*|c(?=\d{4}[^\d]*))'
42
17
 
43
- class << self
44
- def call(obj)
45
- new(obj).values
46
- end
47
- end
48
-
49
- attr_reader :obj, :values
50
-
51
- def initialize(obj)
52
- @obj = obj
53
- @values = []
54
- facet_values
55
- end
56
-
57
- def facet_values
58
- obj.date.each do |date|
59
- date.split(/;/).each do |value|
60
- clean! value
61
- years = extract_years(value)
62
- validate! years
63
- values.push *years
64
- end
65
- end
66
- end
67
-
68
- def extract_years(value)
69
- years = match_years(value) || parse_year(value)
70
- Array(years)
71
- end
72
-
73
- def clean!(value)
74
- value.strip!
75
- value.gsub! SQUARE_BRACKETS, ""
76
- value.gsub! CIRCA, ""
77
- end
18
+ # 1935-1940 => 1935/1940
19
+ YEAR_RANGE = Regexp.new '(?<=\d{4})-(?=\d{4})'
78
20
 
79
- def validate!(years)
80
- years = years & valid_years.to_a
81
- end
21
+ # 1920s, 1920s?, 192u, 192-, 192-?, 192? => 192x
22
+ DECADE = Regexp.new '(?<=\A\d{3})(-\??|0s\??|u|\?)\z'
82
23
 
83
- def parse_year(value)
84
- Date.parse(value).year
85
- rescue ArgumentError
86
- nil
87
- end
24
+ # 2010/01 => 2010-01
25
+ MONTH = Regexp.new '(?<=\A\d{4})\/(?=\d{2}\z)'
88
26
 
89
- def valid_years
90
- (EARLIEST_YEAR..latest_year)
91
- end
27
+ # 193u/, 193x/ => 1930/
28
+ START_DECADE = Regexp.new '(?<=\d{3})[uxX](?=\/)'
92
29
 
93
- def latest_year
94
- Date.today.year + 100
95
- end
30
+ # /194x, /194u => /1949
31
+ END_DECADE = Regexp.new '(?<=\/\d{3})[uxX]'
96
32
 
97
- def match_years(value)
98
- result = match_year_range(value) ||
99
- match_year_month(value) ||
100
- match_year(value) ||
101
- match_in_decade(value) ||
102
- match_in_century(value) ||
103
- match_decade(value) ||
104
- match_between(value)
105
- first_year, last_year = Array(result).map(&:to_i)
106
- last_year ? (first_year..last_year) : first_year
107
- end
33
+ # 19uu => 19xx
34
+ CENTURY = Regexp.new '(?<=\A\d{2})uu(?=\z)'
108
35
 
109
- def match_year_range(value)
110
- if m = YEAR_RANGE.match(value)
111
- m[1, 2]
112
- end
36
+ def self.call(object)
37
+ new(object).call
113
38
  end
114
39
 
115
- def match_year_month(value)
116
- if m = YEAR_MONTH.match(value)
117
- m[1]
118
- end
119
- end
40
+ attr_reader :object
120
41
 
121
- def match_year(value)
122
- if m = YEAR.match(value)
123
- value
124
- end
42
+ def initialize(object)
43
+ @object = object
125
44
  end
126
45
 
127
- def match_in_decade(value)
128
- if m = IN_DECADE.match(value)
129
- [ "#{m[1]}0", "#{m[1]}9" ]
46
+ def call
47
+ source_dates.each_with_object([]) do |date, facet_values|
48
+ date.split(VALUE_SEP).each do |value|
49
+ value.strip!
50
+ edtf_date = convert_to_edtf(value)
51
+ years = Array(edtf_years(edtf_date))
52
+ years.select! { |year| VALID_YEARS.include?(year) }
53
+ facet_values.push(*years)
54
+ end
130
55
  end
131
56
  end
132
57
 
133
- def match_in_century(value)
134
- if m = IN_CENTURY.match(value)
135
- [ "#{m[1]}00", "#{m[1]}99" ]
136
- end
137
- end
58
+ private
138
59
 
139
- def match_decade(value)
140
- if m = DECADE.match(value)
141
- [ m[1], m[1].sub(/0\z/, "9") ]
142
- end
60
+ def source_dates
61
+ object.descMetadata.date
143
62
  end
144
63
 
145
- def match_between(value)
64
+ def convert_to_edtf(value)
146
65
  if m = BETWEEN.match(value)
147
66
  value.sub! m[1], "" # [Bb]etween
148
- value.sub! m[3], "-" # and
149
- match_year_range(value)
67
+ value.sub! m[3], "/" # and
150
68
  end
69
+ substitutions.reduce(value) { |memo, (regexp, repl)| memo.gsub(regexp, repl) }
70
+ end
71
+
72
+ def substitutions
73
+ [
74
+ [ CIRCA, "" ],
75
+ [ YEAR_RANGE, "/" ],
76
+ [ DECADE, "x" ],
77
+ [ MONTH, "-" ],
78
+ [ START_DECADE, "0" ],
79
+ [ END_DECADE, "9" ],
80
+ [ CENTURY, "xx" ],
81
+ ]
82
+ end
83
+
84
+ def edtf_years(value)
85
+ case parsed = EDTF.parse!(value)
86
+ when Date, EDTF::Season
87
+ parsed.year
88
+ when EDTF::Set, EDTF::Interval, EDTF::Epoch
89
+ parsed.map(&:year).uniq
90
+ end
91
+ rescue ArgumentError # EDTF cannot parse
92
+ nil
151
93
  end
152
94
 
153
95
  end
@@ -297,7 +297,7 @@ module Ddr::Auth
297
297
  let(:cache_key) { obj }
298
298
  let(:perm_obj) { SolrDocument.new({"id"=>"test:1"}) }
299
299
  before do
300
- allow_any_instance_of(RoleBasedAbilityDefinitions).to receive(:permissions_doc).with(obj) { perm_obj }
300
+ allow(SolrDocument).to receive(:find).with("test:1") { perm_obj }
301
301
  end
302
302
  it_behaves_like "it has role based abilities"
303
303
  end
@@ -42,19 +42,19 @@ module Ddr::Auth
42
42
 
43
43
  describe "validation" do
44
44
  it "should require the presence of an agent" do
45
- expect { described_class.build(type: "Curator", scope: "resource") }.to raise_error
46
- expect { described_class.build(type: "Curator", agent: nil, scope: "resource") }.to raise_error
47
- expect { described_class.build(type: "Curator", agent: "", scope: "resource") }.to raise_error
45
+ expect { described_class.build(type: "Curator", scope: "resource") }.to raise_error(Ddr::Models::Error)
46
+ expect { described_class.build(type: "Curator", agent: nil, scope: "resource") }.to raise_error(Ddr::Models::Error)
47
+ expect { described_class.build(type: "Curator", agent: "", scope: "resource") }.to raise_error(Ddr::Models::Error)
48
48
  end
49
49
  it "should require a valid scope" do
50
- expect { described_class.build(type: "Curator", agent: agent, scope: "") }.to raise_error
51
- expect { described_class.build(type: "Curator", agent: agent, scope: "other") }.to raise_error
50
+ expect { described_class.build(type: "Curator", agent: agent, scope: "") }.to raise_error(Ddr::Models::Error)
51
+ expect { described_class.build(type: "Curator", agent: agent, scope: "other") }.to raise_error(Ddr::Models::Error)
52
52
  end
53
53
  it "should require a valid type" do
54
- expect { described_class.build(agent: agent, scope: "policy") }.to raise_error
55
- expect { described_class.build(type: nil, agent: agent, scope: "policy") }.to raise_error
56
- expect { described_class.build(type: "", agent: agent, scope: "policy") }.to raise_error
57
- expect { described_class.build(type: "Invalid", agent: agent, scope: "policy") }.to raise_error
54
+ expect { described_class.build(agent: agent, scope: "policy") }.to raise_error(Ddr::Models::Error)
55
+ expect { described_class.build(type: nil, agent: agent, scope: "policy") }.to raise_error(Ddr::Models::Error)
56
+ expect { described_class.build(type: "", agent: agent, scope: "policy") }.to raise_error(Ddr::Models::Error)
57
+ expect { described_class.build(type: "Invalid", agent: agent, scope: "policy") }.to raise_error(Ddr::Models::Error)
58
58
  end
59
59
  end
60
60
 
@@ -56,6 +56,12 @@ module Ddr::Index
56
56
  its(:heading) { is_expected.to eq "admin_set" }
57
57
  end
58
58
 
59
+ describe "ARRANGER_FACET" do
60
+ subject { Fields::ARRANGER_FACET }
61
+ its(:label) { is_expected.to eq "Arranger Facet" }
62
+ its(:heading) { is_expected.to eq "arranger_facet" }
63
+ end
64
+
59
65
  describe "ASPACE_ID" do
60
66
  subject { Fields::ASPACE_ID }
61
67
  its(:label) { is_expected.to eq "ArchivesSpace ID" }
@@ -74,6 +80,12 @@ module Ddr::Index
74
80
  its(:heading) { is_expected.to eq "company_facet" }
75
81
  end
76
82
 
83
+ describe "COMPOSER_FACET" do
84
+ subject { Fields::COMPOSER_FACET }
85
+ its(:label) { is_expected.to eq "Composer Facet" }
86
+ its(:heading) { is_expected.to eq "composer_facet" }
87
+ end
88
+
77
89
  describe "DOI" do
78
90
  subject { Fields::DOI }
79
91
  its(:label) { is_expected.to eq "DOI" }
@@ -86,18 +98,66 @@ module Ddr::Index
86
98
  its(:heading) { is_expected.to eq "ead_id" }
87
99
  end
88
100
 
101
+ describe "ENGRAVER FACET" do
102
+ subject { Fields::ENGRAVER_FACET }
103
+ its(:label) { is_expected.to eq "Engraver Facet" }
104
+ its(:heading) { is_expected.to eq "engraver_facet" }
105
+ end
106
+
89
107
  describe "FOLDER_FACET" do
90
108
  subject { Fields::FOLDER_FACET }
91
109
  its(:label) { is_expected.to eq "Folder Facet" }
92
110
  its(:heading) { is_expected.to eq "folder_facet" }
93
111
  end
94
112
 
113
+ describe "GENRE_FACET" do
114
+ subject { Fields::GENRE_FACET }
115
+ its(:label) { is_expected.to eq "Genre Facet" }
116
+ its(:heading) { is_expected.to eq "genre_facet" }
117
+ end
118
+
95
119
  describe "LOCAL_ID" do
96
120
  subject { Fields::LOCAL_ID }
97
121
  its(:label) { is_expected.to eq "Local ID" }
98
122
  its(:heading) { is_expected.to eq "local_id" }
99
123
  end
100
124
 
125
+ describe "ILLUSTRATED_FACET" do
126
+ subject { Fields::ILLUSTRATED_FACET }
127
+ its(:label) { is_expected.to eq "Illustrated Facet" }
128
+ its(:heading) { is_expected.to eq "illustrated_facet" }
129
+ end
130
+
131
+ describe "ILLUSTRATOR_FACET" do
132
+ subject { Fields::ILLUSTRATOR_FACET }
133
+ its(:label) { is_expected.to eq "Illustrator Facet" }
134
+ its(:heading) { is_expected.to eq "illustrator_facet" }
135
+ end
136
+
137
+ describe "INSTRUMENTATION_FACET" do
138
+ subject { Fields::INSTRUMENTATION_FACET }
139
+ its(:label) { is_expected.to eq "Instrumentation Facet" }
140
+ its(:heading) { is_expected.to eq "instrumentation_facet" }
141
+ end
142
+
143
+ describe "INTERVIEWER_NAME_FACET" do
144
+ subject { Fields::INTERVIEWER_NAME_FACET }
145
+ its(:label) { is_expected.to eq "Interviewer Name Facet" }
146
+ its(:heading) { is_expected.to eq "interviewer_name_facet" }
147
+ end
148
+
149
+ describe "LITHOGRAPHER_FACET" do
150
+ subject { Fields::LITHOGRAPHER_FACET }
151
+ its(:label) { is_expected.to eq "Lithographer Facet" }
152
+ its(:heading) { is_expected.to eq "lithographer_facet" }
153
+ end
154
+
155
+ describe "LYRICIST_FACET" do
156
+ subject { Fields::LYRICIST_FACET }
157
+ its(:label) { is_expected.to eq "Lyricist Facet" }
158
+ its(:heading) { is_expected.to eq "lyricist_facet" }
159
+ end
160
+
101
161
  describe "MEDIUM_FACET" do
102
162
  subject { Fields::MEDIUM_FACET }
103
163
  its(:label) { is_expected.to eq "Medium Facet" }
@@ -116,6 +176,12 @@ module Ddr::Index
116
176
  its(:heading) { is_expected.to eq "modification_date" }
117
177
  end
118
178
 
179
+ describe "PERFORMER_FACET" do
180
+ subject { Fields::PERFORMER_FACET }
181
+ its(:label) { is_expected.to eq "Performer Facet" }
182
+ its(:heading) { is_expected.to eq "performer_facet" }
183
+ end
184
+
119
185
  describe "PERMANENT_ID" do
120
186
  subject { Fields::PERMANENT_ID }
121
187
  its(:label) { is_expected.to eq "Permanent ID" }
@@ -134,6 +200,12 @@ module Ddr::Index
134
200
  its(:heading) { is_expected.to eq "placement_company_facet" }
135
201
  end
136
202
 
203
+ describe "PRODUCER_FACET" do
204
+ subject { Fields::PRODUCER_FACET }
205
+ its(:label) { is_expected.to eq "Producer Facet" }
206
+ its(:heading) { is_expected.to eq "producer_facet" }
207
+ end
208
+
137
209
  describe "PRODUCT_FACET" do
138
210
  subject { Fields::PRODUCT_FACET }
139
211
  its(:label) { is_expected.to eq "Product Facet" }
@@ -146,12 +218,24 @@ module Ddr::Index
146
218
  its(:heading) { is_expected.to eq "publication_facet" }
147
219
  end
148
220
 
221
+ describe "ROLL_NUMBER_FACET" do
222
+ subject { Fields::ROLL_NUMBER_FACET }
223
+ its(:label) { is_expected.to eq "Roll Number Facet" }
224
+ its(:heading) { is_expected.to eq "roll_number_facet" }
225
+ end
226
+
149
227
  describe "SETTING_FACET" do
150
228
  subject { Fields::SETTING_FACET }
151
229
  its(:label) { is_expected.to eq "Setting Facet" }
152
230
  its(:heading) { is_expected.to eq "setting_facet" }
153
231
  end
154
232
 
233
+ describe "SUBSERIES_FACET" do
234
+ subject { Fields::SUBSERIES_FACET }
235
+ its(:label) { is_expected.to eq "Subseries Facet" }
236
+ its(:heading) { is_expected.to eq "subseries_facet" }
237
+ end
238
+
155
239
  describe "TECHMD_COLOR_SPACE" do
156
240
  subject { Fields::TECHMD_COLOR_SPACE }
157
241
  its(:label) { is_expected.to eq "Color Space" }
@@ -242,11 +326,23 @@ module Ddr::Index
242
326
  its(:heading) { is_expected.to eq "well_formed" }
243
327
  end
244
328
 
329
+ describe "TEMPORAL_FACET" do
330
+ subject { Fields::TEMPORAL_FACET }
331
+ its(:label) { is_expected.to eq "Temporal Facet" }
332
+ its(:heading) { is_expected.to eq "temporal_facet" }
333
+ end
334
+
245
335
  describe "TONE_FACET" do
246
336
  subject { Fields::TONE_FACET }
247
337
  its(:label) { is_expected.to eq "Tone Facet" }
248
338
  its(:heading) { is_expected.to eq "tone_facet" }
249
339
  end
340
+
341
+ describe "VOLUME_FACET" do
342
+ subject { Fields::VOLUME_FACET }
343
+ its(:label) { is_expected.to eq "Volume Facet" }
344
+ its(:heading) { is_expected.to eq "volume_facet" }
345
+ end
250
346
  end
251
347
 
252
348
  end