qa 3.1.0 → 4.0.0.rc1

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