qa 3.1.0 → 4.0.0.rc1

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 (95) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +16 -548
  3. data/app/controllers/qa/linked_data_terms_controller.rb +64 -42
  4. data/app/controllers/qa/terms_controller.rb +14 -6
  5. data/app/models/qa/iri_template/url_config.rb +47 -0
  6. data/app/models/qa/iri_template/variable_map.rb +62 -0
  7. data/app/models/qa/linked_data/config/context_map.rb +77 -0
  8. data/app/models/qa/linked_data/config/context_property_map.rb +144 -0
  9. data/app/models/qa/linked_data/config/helper.rb +34 -0
  10. data/app/services/qa/iri_template_service.rb +31 -0
  11. data/{lib/qa/authorities → app/services/qa}/linked_data/authority_service.rb +3 -4
  12. data/app/services/qa/linked_data/authority_url_service.rb +48 -0
  13. data/app/services/qa/linked_data/deep_sort_service.rb +238 -0
  14. data/app/services/qa/linked_data/graph_service.rb +106 -0
  15. data/app/services/qa/linked_data/language_service.rb +30 -0
  16. data/app/services/qa/linked_data/language_sort_service.rb +81 -0
  17. data/app/services/qa/linked_data/mapper/context_mapper_service.rb +59 -0
  18. data/app/services/qa/linked_data/mapper/graph_mapper_service.rb +40 -0
  19. data/app/services/qa/linked_data/mapper/search_results_mapper_service.rb +70 -0
  20. data/config/authorities/linked_data/loc.json +5 -2
  21. data/config/authorities/linked_data/oclc_fast.json +3 -2
  22. data/config/initializers/linked_data_authorities.rb +1 -1
  23. data/config/locales/qa.en.yml +9 -0
  24. data/lib/generators/qa/install/templates/config/initializers/qa.rb +4 -0
  25. data/lib/qa.rb +8 -0
  26. data/lib/qa/authorities/assign_fast/generic_authority.rb +1 -1
  27. data/lib/qa/authorities/base.rb +0 -11
  28. data/lib/qa/authorities/crossref/generic_authority.rb +1 -1
  29. data/lib/qa/authorities/geonames.rb +1 -1
  30. data/lib/qa/authorities/getty/aat.rb +7 -2
  31. data/lib/qa/authorities/getty/tgn.rb +7 -2
  32. data/lib/qa/authorities/getty/ulan.rb +7 -2
  33. data/lib/qa/authorities/linked_data.rb +0 -1
  34. data/lib/qa/authorities/linked_data/config.rb +29 -28
  35. data/lib/qa/authorities/linked_data/config/search_config.rb +21 -79
  36. data/lib/qa/authorities/linked_data/config/term_config.rb +7 -77
  37. data/lib/qa/authorities/linked_data/find_term.rb +25 -17
  38. data/lib/qa/authorities/linked_data/generic_authority.rb +6 -5
  39. data/lib/qa/authorities/linked_data/rdf_helper.rb +6 -73
  40. data/lib/qa/authorities/linked_data/search_query.rb +54 -101
  41. data/lib/qa/authorities/loc/generic_authority.rb +4 -4
  42. data/lib/qa/authorities/web_service_base.rb +1 -8
  43. data/lib/qa/configuration.rb +7 -0
  44. data/lib/qa/version.rb +1 -1
  45. data/lib/tasks/mesh.rake +19 -18
  46. data/spec/controllers/linked_data_terms_controller_spec.rb +51 -1
  47. data/spec/controllers/terms_controller_spec.rb +15 -15
  48. data/spec/fixtures/authorities/linked_data/lod_encoding_config.json +2 -1
  49. data/spec/fixtures/authorities/linked_data/lod_full_config.json +56 -2
  50. data/spec/fixtures/authorities/linked_data/lod_full_config_1_0.json +164 -0
  51. data/spec/fixtures/authorities/linked_data/lod_lang_defaults.json +5 -4
  52. data/spec/fixtures/authorities/linked_data/lod_lang_multi_defaults.json +3 -2
  53. data/spec/fixtures/authorities/linked_data/lod_lang_no_defaults.json +3 -2
  54. data/spec/fixtures/authorities/linked_data/lod_lang_param.json +3 -2
  55. data/spec/fixtures/authorities/linked_data/lod_min_config.json +3 -2
  56. data/spec/fixtures/authorities/linked_data/lod_search_only_config.json +2 -1
  57. data/spec/fixtures/authorities/linked_data/lod_sort.json +2 -1
  58. data/spec/fixtures/authorities/linked_data/lod_term_id_param_config.json +2 -1
  59. data/spec/fixtures/authorities/linked_data/lod_term_only_config.json +2 -1
  60. data/spec/fixtures/authorities/linked_data/lod_term_uri_param_config.json +2 -1
  61. data/spec/fixtures/getty-error-response.txt +10 -0
  62. data/spec/fixtures/lod_2_ranked_2_unranked.nt +17 -0
  63. data/spec/fixtures/lod_3_ranked_varying_preds.nt +16 -0
  64. data/spec/fixtures/lod_lang_search_filtering.nt +11 -0
  65. data/spec/fixtures/lod_search_with_blanknode_subjects.nt +18 -0
  66. data/spec/fixtures/lod_term_with_blanknode_objects.nt +8 -0
  67. data/spec/lib/authorities/assign_fast_spec.rb +1 -0
  68. data/spec/lib/authorities/getty/aat_spec.rb +14 -2
  69. data/spec/lib/authorities/getty/tgn_spec.rb +14 -2
  70. data/spec/lib/authorities/getty/ulan_spec.rb +14 -2
  71. data/spec/lib/authorities/linked_data/authority_service_spec.rb +2 -1
  72. data/spec/lib/authorities/linked_data/config_spec.rb +284 -5
  73. data/spec/lib/authorities/linked_data/find_term_spec.rb +3 -1
  74. data/spec/lib/authorities/linked_data/generic_authority_spec.rb +92 -42
  75. data/spec/lib/authorities/linked_data/search_config_spec.rb +67 -160
  76. data/spec/lib/authorities/linked_data/search_query_spec.rb +3 -127
  77. data/spec/lib/authorities/linked_data/term_config_spec.rb +6 -134
  78. data/spec/lib/authorities/loc_spec.rb +9 -9
  79. data/spec/lib/configuration_spec.rb +20 -7
  80. data/spec/lib/tasks/mesh.rake_spec.rb +2 -2
  81. data/spec/models/iri_template/url_config_spec.rb +102 -0
  82. data/spec/models/iri_template/variable_map_spec.rb +105 -0
  83. data/spec/models/linked_data/config/context_map_spec.rb +148 -0
  84. data/spec/models/linked_data/config/context_property_map_spec.rb +286 -0
  85. data/spec/services/iri_template_service_spec.rb +69 -0
  86. data/spec/services/linked_data/authority_url_service_spec.rb +107 -0
  87. data/spec/services/linked_data/deep_sort_service_spec.rb +260 -0
  88. data/spec/services/linked_data/graph_service_spec.rb +232 -0
  89. data/spec/services/linked_data/language_service_spec.rb +66 -0
  90. data/spec/services/linked_data/language_sort_service_spec.rb +58 -0
  91. data/spec/services/linked_data/mapper/context_mapper_service_spec.rb +137 -0
  92. data/spec/services/linked_data/mapper/graph_mapper_service_spec.rb +110 -0
  93. data/spec/services/linked_data/mapper/search_results_mapper_service_spec.rb +109 -0
  94. data/spec/spec_helper.rb +10 -2
  95. metadata +81 -11
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Qa::LinkedData::LanguageService do
4
+ describe '.preferred_language' do
5
+ subject { described_class.preferred_language(user_language: user_language, authority_language: authority_language) }
6
+
7
+ let(:user_language) { nil }
8
+ let(:authority_language) { nil }
9
+
10
+ context 'when neither user nor authority language are passed in' do
11
+ it 'returns default language from Qa configuration' do
12
+ expect(subject).to match_array [:en]
13
+ end
14
+ end
15
+
16
+ context 'when authority language is passed in and user language is NOT passed in' do
17
+ let(:authority_language) { :fr }
18
+
19
+ it 'returns authority language' do
20
+ expect(subject).to match_array [:fr]
21
+ end
22
+ end
23
+
24
+ context 'when user and authority language are passed in' do
25
+ let(:user_language) { :de }
26
+ let(:authority_language) { :fr }
27
+
28
+ it 'returns user language' do
29
+ expect(subject).to match_array [:de]
30
+ end
31
+ end
32
+
33
+ context 'when multiple languages' do
34
+ let(:user_language) { [:de, :fr] }
35
+
36
+ it 'returns multiple languages' do
37
+ expect(subject).to match_array [:de, :fr]
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '.literal_has_language_marker?' do
43
+ subject { described_class.literal_has_language_marker? literal }
44
+
45
+ context "when doesn't respond to language" do
46
+ let(:literal) { RDF::Literal.new(123) }
47
+ it 'returns false' do
48
+ expect(subject).to eq false
49
+ end
50
+ end
51
+
52
+ context "when doesn't have language marker" do
53
+ let(:literal) { RDF::Literal.new('String without language') }
54
+ it 'returns false' do
55
+ expect(subject).to eq false
56
+ end
57
+ end
58
+
59
+ context "when has language marker" do
60
+ let(:literal) { RDF::Literal.new('String with language', language: :en) }
61
+ it 'returns true' do
62
+ expect(subject).to eq true
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Qa::LinkedData::LanguageSortService do
4
+ describe "#sort" do
5
+ subject { described_class.new(terms, preferred_language).sort }
6
+
7
+ let(:preferred_language) { nil }
8
+
9
+ context 'when sort values all have the same language marker' do
10
+ let(:term_1) { RDF::Literal.new("apple", language: :en) }
11
+ let(:term_2) { RDF::Literal.new("Banana", language: :en) }
12
+ let(:term_3) { RDF::Literal.new("carrot", language: :en) }
13
+ let(:terms) { [term_2, term_3, term_1] }
14
+
15
+ it "does alpha sort ignoring case" do
16
+ expected_results = [term_1, term_2, term_3]
17
+ expect(subject).to eq expected_results
18
+ end
19
+ end
20
+
21
+ # Sort the literals within their languages. (e.g. 'Kuh':de, 'Rind':de, 'bovine':en, 'cow':en, 'vache':fr, 'vaca')
22
+ context 'when sort values have the different language markers' do
23
+ let(:term_1) { RDF::Literal.new("Kuh", language: :de) }
24
+ let(:term_2) { RDF::Literal.new("Rind", language: :de) }
25
+ let(:term_3) { RDF::Literal.new("bovine", language: :en) }
26
+ let(:term_4) { RDF::Literal.new("cow", language: :en) }
27
+ let(:term_5) { RDF::Literal.new("vache", language: :fr) }
28
+ let(:term_6) { RDF::Literal.new("mucca") }
29
+ let(:term_7) { RDF::Literal.new("vaca") }
30
+ let(:terms) { [term_5, term_7, term_2, term_6, term_1, term_4, term_3] }
31
+
32
+ it "does alpha sort ignoring case" do
33
+ expected_results = [term_1, term_2, term_3, term_4, term_5, term_6, term_7]
34
+ expect(subject).to eq expected_results
35
+ end
36
+ end
37
+
38
+ # Sort the literals within their languages giving preference to one language. (e.g. 'bovine':en, 'cow':en, 'Kuh':de, 'Rind':de, 'vache':fr, 'vaca')
39
+ context 'when some of the sort values have the preferred language' do
40
+ let(:preferred_language) { :en }
41
+
42
+ let(:term_1) { RDF::Literal.new("bovine", language: :en) }
43
+ let(:term_2) { RDF::Literal.new("cow", language: :en) }
44
+ let(:term_3) { RDF::Literal.new("heffer", language: :en) }
45
+ let(:term_4) { RDF::Literal.new("Kuh", language: :de) }
46
+ let(:term_5) { RDF::Literal.new("Rind", language: :de) }
47
+ let(:term_6) { RDF::Literal.new("vache", language: :fr) }
48
+ let(:term_7) { RDF::Literal.new("mucca") }
49
+ let(:term_8) { RDF::Literal.new("vaca") }
50
+ let(:terms) { [term_7, term_5, term_3, term_2, term_1, term_6, term_4, term_8] }
51
+
52
+ it "does alpha sort ignoring case" do
53
+ expected_results = [term_1, term_2, term_3, term_4, term_5, term_6, term_7, term_8]
54
+ expect(subject).to eq expected_results
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Qa::LinkedData::Mapper::ContextMapperService do
4
+ subject { described_class.map_context(graph: graph, context_map: context_map, subject_uri: subject_uri) }
5
+
6
+ let(:graph) { instance_double(RDF::Graph) }
7
+ let(:context_map) { instance_double(Qa::LinkedData::Config::ContextMap) }
8
+ let(:subject_uri) { instance_double(RDF::URI) }
9
+
10
+ let(:context_properties) { [birth_date_property_map, death_date_property_map, occupation_property_map] }
11
+
12
+ let(:birth_date_property_map) { instance_double(Qa::LinkedData::Config::ContextPropertyMap) }
13
+ let(:death_date_property_map) { instance_double(Qa::LinkedData::Config::ContextPropertyMap) }
14
+ let(:occupation_property_map) { instance_double(Qa::LinkedData::Config::ContextPropertyMap) }
15
+
16
+ let(:group_id) { 'dates' }
17
+
18
+ let(:birth_date_values) { ['10/15/1943'] }
19
+ let(:death_date_values) { ['12/17/2018'] }
20
+ let(:occupation_values) { ['Actress', 'Director', 'Producer'] }
21
+
22
+ before do
23
+ allow(context_map).to receive(:properties).and_return(context_properties)
24
+ allow(context_map).to receive(:group_label).with('dates').and_return('Dates')
25
+
26
+ allow(birth_date_property_map).to receive(:label).and_return('Birth')
27
+ allow(birth_date_property_map).to receive(:values).with(graph, subject_uri).and_return(birth_date_values)
28
+ allow(birth_date_property_map).to receive(:group?).and_return(false)
29
+ allow(birth_date_property_map).to receive(:selectable?).and_return(false)
30
+ allow(birth_date_property_map).to receive(:drillable?).and_return(false)
31
+ allow(birth_date_property_map).to receive(:expand_uri?).and_return(false)
32
+
33
+ allow(death_date_property_map).to receive(:label).and_return('Death')
34
+ allow(death_date_property_map).to receive(:values).with(graph, subject_uri).and_return(death_date_values)
35
+ allow(death_date_property_map).to receive(:group?).and_return(false)
36
+ allow(death_date_property_map).to receive(:selectable?).and_return(false)
37
+ allow(death_date_property_map).to receive(:drillable?).and_return(false)
38
+ allow(death_date_property_map).to receive(:expand_uri?).and_return(false)
39
+
40
+ allow(occupation_property_map).to receive(:label).and_return('Occupation')
41
+ allow(occupation_property_map).to receive(:values).with(graph, subject_uri).and_return(occupation_values)
42
+ allow(occupation_property_map).to receive(:group?).and_return(false)
43
+ allow(occupation_property_map).to receive(:selectable?).and_return(false)
44
+ allow(occupation_property_map).to receive(:drillable?).and_return(false)
45
+ allow(occupation_property_map).to receive(:expand_uri?).and_return(false)
46
+ end
47
+
48
+ describe '.map_context' do
49
+ it 'sets the property labels from the property map' do
50
+ find_property_to_test(subject, 'Birth')
51
+ find_property_to_test(subject, 'Death')
52
+ find_property_to_test(subject, 'Occupation')
53
+ expect(subject.size).to be 3
54
+ end
55
+
56
+ it 'sets the property values from the graph' do
57
+ result = find_property_to_test(subject, 'Birth')
58
+ expect(result['values']).to match_array birth_date_values
59
+ result = find_property_to_test(subject, 'Death')
60
+ expect(result['values']).to match_array death_date_values
61
+ result = find_property_to_test(subject, 'Occupation')
62
+ expect(result['values']).to match_array occupation_values
63
+ end
64
+
65
+ context 'when group? is false' do
66
+ before { allow(birth_date_property_map).to receive(:group?).and_return(false) }
67
+ it 'does not include group in results' do
68
+ result = find_property_to_test(subject, 'Birth')
69
+ expect(result.key?('group')).to be false
70
+ end
71
+ end
72
+
73
+ context 'when group? is true' do
74
+ before do
75
+ allow(birth_date_property_map).to receive(:group?).and_return(true)
76
+ allow(birth_date_property_map).to receive(:group_id).and_return('dates')
77
+ allow(context_map).to receive(:group_label).with('dates').and_return('Dates')
78
+ end
79
+
80
+ it 'includes group in results' do
81
+ result = find_property_to_test(subject, 'Birth')
82
+ expect(result['group']).to eq 'Dates'
83
+ end
84
+ end
85
+
86
+ context 'when drillable? is false' do
87
+ before { allow(death_date_property_map).to receive(:drillable?).and_return(false) }
88
+ it 'includes drillable set to false' do
89
+ result = find_property_to_test(subject, 'Death')
90
+ expect(result['drillable']).to be false
91
+ end
92
+ end
93
+
94
+ context 'when drillable? is true' do
95
+ before { allow(death_date_property_map).to receive(:drillable?).and_return(true) }
96
+ it 'includes drillable set to true' do
97
+ result = find_property_to_test(subject, 'Death')
98
+ expect(result['drillable']).to be true
99
+ end
100
+ end
101
+
102
+ context 'when selectable? is false' do
103
+ before { allow(occupation_property_map).to receive(:selectable?).and_return(false) }
104
+ it 'includes selectable set to false' do
105
+ result = find_property_to_test(subject, 'Occupation')
106
+ expect(result['selectable']).to be false
107
+ end
108
+ end
109
+
110
+ context 'when selectable? is true' do
111
+ before { allow(occupation_property_map).to receive(:selectable?).and_return(true) }
112
+ it 'includes selectable set to true' do
113
+ result = find_property_to_test(subject, 'Occupation')
114
+ expect(result['selectable']).to be true
115
+ end
116
+ end
117
+
118
+ context 'when error occurs' do
119
+ let(:cause) { I18n.t('qa.linked_data.ldpath.parse_error') }
120
+ before { allow(occupation_property_map).to receive(:values).with(graph, subject_uri).and_raise(cause) }
121
+ it 'includes error message and empty value array' do
122
+ result = find_property_to_test(subject, 'Occupation')
123
+ expect(result.key?('error')).to be true
124
+ expect(result['error']).to eq cause
125
+ expect(result['values']).to match_array([])
126
+ end
127
+ end
128
+ end
129
+
130
+ def find_property_to_test(results, label)
131
+ results.each do |r|
132
+ next unless r['property'] == label
133
+ return r
134
+ end
135
+ raise "property (#{label}) to test not found"
136
+ end
137
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Qa::LinkedData::Mapper::GraphMapperService do
4
+ let(:graph) { Qa::LinkedData::GraphService.load_graph(url: 'http://local.data') }
5
+ let(:predicate_map) do
6
+ {
7
+ uri: :subject_uri,
8
+ id: RDF::URI.new('http://purl.org/dc/terms/identifier'),
9
+ label: RDF::URI.new('http://www.w3.org/2004/02/skos/core#prefLabel'),
10
+ altlabel: RDF::URI.new('http://www.w3.org/2004/02/skos/core#altLabel'),
11
+ sameas: RDF::URI.new('http://www.w3.org/2004/02/skos/core#sameAs'),
12
+ sort: RDF::URI.new('http://vivoweb.org/ontology/core#rank')
13
+ }
14
+ end
15
+
16
+ before do
17
+ stub_request(:get, 'http://local.data')
18
+ .to_return(status: 200, body: webmock_fixture('lod_3_ranked_varying_preds.nt'), headers: { 'Content-Type' => 'application/n-triples' })
19
+ end
20
+
21
+ describe '.map_values' do
22
+ subject { described_class.map_values(graph: graph, predicate_map: predicate_map, subject_uri: subject_uri) }
23
+
24
+ context 'when each predicate has one value' do
25
+ let(:subject_uri) { RDF::URI.new('http://id.worldcat.org/fast/530369') }
26
+
27
+ it 'maps graph values to predicates' do
28
+ expect(subject.count).to eq 6
29
+ expect(subject).to be_kind_of Hash
30
+ expect(subject.keys).to match_array [:uri, :id, :label, :altlabel, :sameas, :sort]
31
+
32
+ validate_entry(subject, :uri, [subject_uri.to_s], RDF::URI)
33
+ validate_entry(subject, :id, ['530369'], RDF::Literal)
34
+ validate_entry(subject, :label, ['Cornell University'], RDF::Literal)
35
+ validate_entry(subject, :altlabel, ['Ithaca (N.Y.). Cornell University'], RDF::Literal)
36
+ validate_entry(subject, :sameas, ['http://id.loc.gov/authorities/names/n79021621'], RDF::URI)
37
+ validate_entry(subject, :sort, ['1'], RDF::Literal)
38
+ end
39
+ end
40
+
41
+ context 'when some predicates have multiple values' do
42
+ let(:subject_uri) { RDF::URI.new('http://id.worldcat.org/fast/510103') }
43
+
44
+ it 'maps graph values to predicates' do
45
+ expect(subject.count).to eq 6
46
+ expect(subject).to be_kind_of Hash
47
+ expect(subject.keys).to match_array [:uri, :id, :label, :altlabel, :sameas, :sort]
48
+
49
+ validate_entry(subject, :uri, [subject_uri.to_s], RDF::URI)
50
+ validate_entry(subject, :id, ['510103'], RDF::Literal)
51
+ validate_entry(subject, :label, ['Cornell University. Libraries'], RDF::Literal)
52
+ validate_entry(subject, :altlabel, ['Cornell University. Central Libraries', 'Cornell University. John M. Olin Library', 'Cornell University. White Library'], RDF::Literal)
53
+ validate_entry(subject, :sameas, ['http://id.loc.gov/authorities/names/n50000040', 'https://viaf.org/viaf/147713418'], RDF::URI)
54
+ validate_entry(subject, :sort, ['2'], RDF::Literal)
55
+ end
56
+ end
57
+
58
+ context 'when some predicates has no values' do
59
+ let(:subject_uri) { RDF::URI.new('http://id.worldcat.org/fast/5140') }
60
+
61
+ it 'maps graph values to predicates' do
62
+ expect(subject.count).to eq 6
63
+ expect(subject).to be_kind_of Hash
64
+ expect(subject.keys).to match_array [:uri, :id, :label, :altlabel, :sameas, :sort]
65
+
66
+ validate_entry(subject, :uri, [subject_uri.to_s], RDF::URI)
67
+ validate_entry(subject, :id, ['5140'], RDF::Literal)
68
+ validate_entry(subject, :label, ['Cornell, Joseph'], RDF::Literal)
69
+ validate_entry(subject, :altlabel, [], NilClass)
70
+ validate_entry(subject, :sameas, [], NilClass)
71
+ validate_entry(subject, :sort, ['3'], RDF::Literal)
72
+ end
73
+ end
74
+
75
+ context 'when block is passed in' do
76
+ let(:subject_uri) { RDF::URI.new('http://id.worldcat.org/fast/5140') }
77
+ let(:context) do
78
+ { location: '42.4488° N, 76.4763° W' }
79
+ end
80
+ let(:subject) do
81
+ described_class.map_values(graph: graph, predicate_map: predicate_map, subject_uri: subject_uri) do |value_map|
82
+ value_map[:context] = context
83
+ value_map
84
+ end
85
+ end
86
+
87
+ it 'yields to passed in block' do
88
+ expect(subject.count).to eq 7
89
+ expect(subject).to be_kind_of Hash
90
+ expect(subject.keys).to match_array [:uri, :id, :label, :altlabel, :sameas, :sort, :context]
91
+
92
+ validate_entry(subject, :uri, [subject_uri.to_s], RDF::URI)
93
+ validate_entry(subject, :id, ['5140'], RDF::Literal)
94
+ validate_entry(subject, :label, ['Cornell, Joseph'], RDF::Literal)
95
+ validate_entry(subject, :altlabel, [], NilClass)
96
+ validate_entry(subject, :sameas, [], NilClass)
97
+ validate_entry(subject, :sort, ['3'], RDF::Literal)
98
+
99
+ expect(subject[:context]).to be_kind_of Hash
100
+ expect(subject[:context]).to include(context)
101
+ end
102
+ end
103
+ end
104
+
105
+ def validate_entry(results, key, values, entry_kind)
106
+ expect(results[key]).to be_kind_of Array
107
+ expect(results[key].first).to be_kind_of entry_kind
108
+ expect(results[key].map(&:to_s)).to match_array values
109
+ end
110
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Qa::LinkedData::Mapper::SearchResultsMapperService do
4
+ let(:graph) { Qa::LinkedData::GraphService.load_graph(url: 'http://local.data') }
5
+ let(:predicate_map) do
6
+ {
7
+ uri: :subject_uri,
8
+ id: RDF::URI.new('http://purl.org/dc/terms/identifier'),
9
+ label: RDF::URI.new('http://www.w3.org/2004/02/skos/core#prefLabel'),
10
+ altlabel: RDF::URI.new('http://www.w3.org/2004/02/skos/core#altLabel'),
11
+ sameas: RDF::URI.new('http://www.w3.org/2004/02/skos/core#sameAs'),
12
+ sort: RDF::URI.new('http://vivoweb.org/ontology/core#rank')
13
+ }
14
+ end
15
+ let(:subjects) { subject.map { |result| result[:uri].first.to_s } }
16
+
17
+ before do
18
+ stub_request(:get, 'http://local.data')
19
+ .to_return(status: 200, body: webmock_fixture('lod_2_ranked_2_unranked.nt'), headers: { 'Content-Type' => 'application/n-triples' })
20
+ end
21
+
22
+ describe '.map_values' do
23
+ subject { described_class.map_values(graph: graph, predicate_map: predicate_map, sort_key: sort_key) }
24
+
25
+ let(:sort_key) { :sort }
26
+ let(:expected530369) do
27
+ {
28
+ uri: [RDF::URI.new('http://id.worldcat.org/fast/530369')],
29
+ id: [RDF::Literal.new('530369')],
30
+ label: [RDF::Literal.new('Cornell University')],
31
+ altlabel: [RDF::Literal.new('Ithaca (N.Y.). Cornell University')],
32
+ sameas: [RDF::URI.new('http://id.loc.gov/authorities/names/n79021621')],
33
+ sort: [RDF::Literal.new('1')]
34
+ }
35
+ end
36
+ let(:expected5140) do
37
+ {
38
+ uri: [RDF::URI.new('http://id.worldcat.org/fast/5140')],
39
+ id: [RDF::Literal.new('5140')],
40
+ label: [RDF::Literal.new('Cornell, Joseph')],
41
+ altlabel: [RDF::URI.new('_:b0')],
42
+ sameas: [],
43
+ sort: [RDF::Literal.new('3')]
44
+ }
45
+ end
46
+
47
+ it 'maps all subjects with a sort predicate' do
48
+ expect(subject.count).to eq 2
49
+ expect(subject).to be_kind_of Array
50
+ expect(subjects).to eq ["http://id.worldcat.org/fast/530369", "http://id.worldcat.org/fast/5140"]
51
+
52
+ actual530369 = subject.first
53
+ actual5140 = subject.second
54
+ expect(actual530369).to eq expected530369
55
+ expect(actual5140).to eq expected5140
56
+ end
57
+
58
+ it 'does not include subjects missing sort predicate' do
59
+ expect(subjects).not_to include "http://id.worldcat.org/fast/510103"
60
+ expect(subjects).not_to include "_:b0"
61
+ end
62
+
63
+ context 'when context_map is passed in' do
64
+ subject { described_class.map_values(graph: graph, predicate_map: predicate_map, sort_key: sort_key, context_map: context_map) }
65
+
66
+ let(:context_map) { instance_double(Qa::LinkedData::Config::ContextMap) }
67
+ let(:context) do
68
+ { location: '42.4488° N, 76.4763° W' }
69
+ end
70
+ let(:expected530369_with_context) do
71
+ {
72
+ uri: [RDF::URI.new('http://id.worldcat.org/fast/530369')],
73
+ id: [RDF::Literal.new('530369')],
74
+ label: [RDF::Literal.new('Cornell University')],
75
+ altlabel: [RDF::Literal.new('Ithaca (N.Y.). Cornell University')],
76
+ sameas: [RDF::URI.new('http://id.loc.gov/authorities/names/n79021621')],
77
+ sort: [RDF::Literal.new('1')],
78
+ context: context
79
+ }
80
+ end
81
+ let(:expected5140_with_context) do
82
+ {
83
+ uri: [RDF::URI.new('http://id.worldcat.org/fast/5140')],
84
+ id: [RDF::Literal.new('5140')],
85
+ label: [RDF::Literal.new('Cornell, Joseph')],
86
+ altlabel: [RDF::URI.new('_:b0')],
87
+ sameas: [],
88
+ sort: [RDF::Literal.new('3')],
89
+ context: context
90
+ }
91
+ end
92
+
93
+ before do
94
+ allow(Qa::LinkedData::Mapper::ContextMapperService).to receive(:map_context).with(graph: anything, context_map: anything, subject_uri: anything).and_return(context)
95
+ end
96
+
97
+ it 'adds context if requested' do
98
+ expect(subject.count).to eq 2
99
+ expect(subject).to be_kind_of Array
100
+ expect(subjects).to eq ["http://id.worldcat.org/fast/530369", "http://id.worldcat.org/fast/5140"]
101
+
102
+ actual530369 = subject.first
103
+ actual5140 = subject.second
104
+ expect(actual530369).to eq expected530369_with_context
105
+ expect(actual5140).to eq expected5140_with_context
106
+ end
107
+ end
108
+ end
109
+ end