json-ld 3.1.1 → 3.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -2305,6 +2305,50 @@ describe JSON::LD::API do
2305
2305
  }
2306
2306
  }),
2307
2307
  processingMode: "json-ld-1.1"
2308
+ },
2309
+ "missing types": {
2310
+ input: %({
2311
+ "@context": {
2312
+ "ex": "http://example.com#",
2313
+ "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2314
+ },
2315
+ "@graph": [{
2316
+ "@id": "ex:graph1",
2317
+ "@graph": [{
2318
+ "@id": "ex:entity1",
2319
+ "@type": ["ex:Type1","ex:Type2"],
2320
+ "ex:title": "some title",
2321
+ "ex:multipleValues": "ex:One"
2322
+ }]
2323
+ }, {
2324
+ "@id": "ex:graph2",
2325
+ "@graph": [{
2326
+ "@id": "ex:entity1",
2327
+ "@type": "ex:Type3",
2328
+ "ex:tags": "tag1 tag2",
2329
+ "ex:multipleValues": ["ex:Two","ex:Three"]
2330
+ }]
2331
+ }]
2332
+ }),
2333
+ output: %({
2334
+ "@context": {
2335
+ "ex": "http://example.com#",
2336
+ "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2337
+ },
2338
+ "@id": "ex:entity1",
2339
+ "@type": ["ex:Type1", "ex:Type2", "ex:Type3"],
2340
+ "ex:multipleValues": ["ex:One", "ex:Two","ex:Three"],
2341
+ "ex:tags": "tag1 tag2",
2342
+ "ex:title": "some title"
2343
+ }),
2344
+ frame: %({
2345
+ "@context": {
2346
+ "ex": "http://example.com#",
2347
+ "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
2348
+ },
2349
+ "@id": "ex:entity1"
2350
+ }),
2351
+ processingMode: "json-ld-1.1"
2308
2352
  }
2309
2353
  }.each do |title, params|
2310
2354
  it title do
@@ -766,6 +766,187 @@ describe JSON::LD::API do
766
766
  end
767
767
  end
768
768
 
769
+ context "RDF*" do
770
+ {
771
+ "subject-iii": {
772
+ input: RDF::Statement(
773
+ RDF::Statement(
774
+ RDF::URI('http://example/s1'),
775
+ RDF::URI('http://example/p1'),
776
+ RDF::URI('http://example/o1')),
777
+ RDF::URI('http://example/p'),
778
+ RDF::URI('http://example/o')),
779
+ output: %([{
780
+ "@id": {
781
+ "@id": "http://example/s1",
782
+ "http://example/p1": [{"@id": "http://example/o1"}]
783
+ },
784
+ "http://example/p": [{"@id": "http://example/o"}]
785
+ }])
786
+ },
787
+ "subject-iib": {
788
+ input: RDF::Statement(
789
+ RDF::Statement(
790
+ RDF::URI('http://example/s1'),
791
+ RDF::URI('http://example/p1'),
792
+ RDF::Node.new('o1')),
793
+ RDF::URI('http://example/p'),
794
+ RDF::URI('http://example/o')),
795
+ output: %([{
796
+ "@id": {
797
+ "@id": "http://example/s1",
798
+ "http://example/p1": [{"@id": "_:o1"}]
799
+ },
800
+ "http://example/p": [{"@id": "http://example/o"}]
801
+ }])
802
+ },
803
+ "subject-iil": {
804
+ input: RDF::Statement(
805
+ RDF::Statement(
806
+ RDF::URI('http://example/s1'),
807
+ RDF::URI('http://example/p1'),
808
+ RDF::Literal('o1')),
809
+ RDF::URI('http://example/p'),
810
+ RDF::URI('http://example/o')),
811
+ output: %([{
812
+ "@id": {
813
+ "@id": "http://example/s1",
814
+ "http://example/p1": [{"@value": "o1"}]
815
+ },
816
+ "http://example/p": [{"@id": "http://example/o"}]
817
+ }])
818
+ },
819
+ "subject-bii": {
820
+ input: RDF::Statement(
821
+ RDF::Statement(
822
+ RDF::Node('s1'),
823
+ RDF::URI('http://example/p1'),
824
+ RDF::URI('http://example/o1')),
825
+ RDF::URI('http://example/p'),
826
+ RDF::URI('http://example/o')),
827
+ output: %([{
828
+ "@id": {
829
+ "@id": "_:s1",
830
+ "http://example/p1": [{"@id": "http://example/o1"}]
831
+ },
832
+ "http://example/p": [{"@id": "http://example/o"}]
833
+ }])
834
+ },
835
+ "subject-bib": {
836
+ input: RDF::Statement(
837
+ RDF::Statement(
838
+ RDF::Node('s1'),
839
+ RDF::URI('http://example/p1'),
840
+ RDF::Node.new('o1')),
841
+ RDF::URI('http://example/p'), RDF::URI('http://example/o')),
842
+ output: %([{
843
+ "@id": {
844
+ "@id": "_:s1",
845
+ "http://example/p1": [{"@id": "_:o1"}]
846
+ },
847
+ "http://example/p": [{"@id": "http://example/o"}]
848
+ }])
849
+ },
850
+ "subject-bil": {
851
+ input: RDF::Statement(
852
+ RDF::Statement(
853
+ RDF::Node('s1'),
854
+ RDF::URI('http://example/p1'),
855
+ RDF::Literal('o1')),
856
+ RDF::URI('http://example/p'),
857
+ RDF::URI('http://example/o')),
858
+ output: %([{
859
+ "@id": {
860
+ "@id": "_:s1",
861
+ "http://example/p1": [{"@value": "o1"}]
862
+ },
863
+ "http://example/p": [{"@id": "http://example/o"}]
864
+ }])
865
+ },
866
+ "object-iii": {
867
+ input: RDF::Statement(
868
+ RDF::URI('http://example/s'),
869
+ RDF::URI('http://example/p'),
870
+ RDF::Statement(
871
+ RDF::URI('http://example/s1'),
872
+ RDF::URI('http://example/p1'),
873
+ RDF::URI('http://example/o1'))),
874
+ output: %([{
875
+ "@id": "http://example/s",
876
+ "http://example/p": [{
877
+ "@id": {
878
+ "@id": "http://example/s1",
879
+ "http://example/p1": [{"@id": "http://example/o1"}]
880
+ }
881
+ }]
882
+ }])
883
+ },
884
+ "object-iib": {
885
+ input: RDF::Statement(
886
+ RDF::URI('http://example/s'),
887
+ RDF::URI('http://example/p'),
888
+ RDF::Statement(
889
+ RDF::URI('http://example/s1'),
890
+ RDF::URI('http://example/p1'),
891
+ RDF::Node.new('o1'))),
892
+ output: %([{
893
+ "@id": "http://example/s",
894
+ "http://example/p": [{
895
+ "@id": {
896
+ "@id": "http://example/s1",
897
+ "http://example/p1": [{"@id": "_:o1"}]
898
+ }
899
+ }]
900
+ }])
901
+ },
902
+ "object-iil": {
903
+ input: RDF::Statement(
904
+ RDF::URI('http://example/s'),
905
+ RDF::URI('http://example/p'),
906
+ RDF::Statement(
907
+ RDF::URI('http://example/s1'),
908
+ RDF::URI('http://example/p1'),
909
+ RDF::Literal('o1'))),
910
+ output: %([{
911
+ "@id": "http://example/s",
912
+ "http://example/p": [{
913
+ "@id": {
914
+ "@id": "http://example/s1",
915
+ "http://example/p1": [{"@value": "o1"}]
916
+ }
917
+ }]
918
+ }])
919
+ },
920
+ "recursive-subject": {
921
+ input: RDF::Statement(
922
+ RDF::Statement(
923
+ RDF::Statement(
924
+ RDF::URI('http://example/s2'),
925
+ RDF::URI('http://example/p2'),
926
+ RDF::URI('http://example/o2')),
927
+ RDF::URI('http://example/p1'),
928
+ RDF::URI('http://example/o1')),
929
+ RDF::URI('http://example/p'),
930
+ RDF::URI('http://example/o')),
931
+ output: %([{
932
+ "@id": {
933
+ "@id": {
934
+ "@id": "http://example/s2",
935
+ "http://example/p2": [{"@id": "http://example/o2"}]
936
+ },
937
+ "http://example/p1": [{"@id": "http://example/o1"}]
938
+ },
939
+ "http://example/p": [{"@id": "http://example/o"}]
940
+ }])
941
+ },
942
+ }.each do |name, params|
943
+ it name do
944
+ graph = RDF::Graph.new {|g| g << params[:input]}
945
+ do_fromRdf(params.merge(input: graph, prefixes: {ex: 'http://example/'}))
946
+ end
947
+ end
948
+ end
949
+
769
950
  context "problems" do
770
951
  {
771
952
  "xsd:boolean as value" => {
@@ -1,4 +1,4 @@
1
- require 'rspec/matchers' # @see http://rubygems.org/gems/rspec
1
+ require 'rspec/matchers' # @see https://rubygems.org/gems/rspec
2
2
  require_relative 'support/extensions'
3
3
 
4
4
  RSpec::Matchers.define :produce_jsonld do |expected, logger|
@@ -43,40 +43,39 @@ describe JSON::LD::Reader do
43
43
  {
44
44
  plain: %q({
45
45
  "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
46
- "@id": "_:bnode1",
47
- "@type": "foaf:Person",
48
- "foaf:homepage": "http://example.com/bob/",
49
- "foaf:name": "Bob"
50
- }),
51
- leading_comment: %q(
52
- // A comment before content
53
- {
54
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
55
- "@id": "_:bnode1",
56
- "@type": "foaf:Person",
57
- "foaf:homepage": "http://example.com/bob/",
58
- "foaf:name": "Bob"
59
- }
60
- ),
61
- script: %q(<script type="application/ld+json">
62
- {
63
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
64
- "@id": "_:bnode1",
65
- "@type": "foaf:Person",
66
- "foaf:homepage": "http://example.com/bob/",
67
- "foaf:name": "Bob"
68
- }
69
- </script>),
70
- script_comments: %q(<script type="application/ld+json">
71
- // A comment before content
72
- {
73
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
74
- "@id": "_:bnode1",
75
- "@type": "foaf:Person",
76
- "foaf:homepage": "http://example.com/bob/",
77
- "foaf:name": "Bob"
78
- }
79
- </script>),
46
+ "@id": "_:bnode1",
47
+ "@type": "foaf:Person",
48
+ "foaf:homepage": "http://example.com/bob/",
49
+ "foaf:name": "Bob"
50
+ }),
51
+ leading_comment: %q(
52
+ // A comment before content
53
+ {
54
+ "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
55
+ "@id": "_:bnode1",
56
+ "@type": "foaf:Person",
57
+ "foaf:homepage": "http://example.com/bob/",
58
+ "foaf:name": "Bob"
59
+ }),
60
+ script: %q(<script type="application/ld+json">
61
+ {
62
+ "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
63
+ "@id": "_:bnode1",
64
+ "@type": "foaf:Person",
65
+ "foaf:homepage": "http://example.com/bob/",
66
+ "foaf:name": "Bob"
67
+ }
68
+ </script>),
69
+ script_comments: %q(<script type="application/ld+json">
70
+ // A comment before content
71
+ {
72
+ "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
73
+ "@id": "_:bnode1",
74
+ "@type": "foaf:Person",
75
+ "foaf:homepage": "http://example.com/bob/",
76
+ "foaf:name": "Bob"
77
+ }
78
+ </script>),
80
79
  }.each do |variant, src|
81
80
  context variant do
82
81
  subject {src}
@@ -0,0 +1,237 @@
1
+ # coding: utf-8
2
+ require_relative 'spec_helper'
3
+ require 'rdf/spec/reader'
4
+
5
+ describe JSON::LD::Reader do
6
+ let!(:doap) {File.expand_path("../../etc/doap.jsonld", __FILE__)}
7
+ let!(:doap_nt) {File.expand_path("../../etc/doap.nt", __FILE__)}
8
+ let!(:doap_count) {File.open(doap_nt).each_line.to_a.length}
9
+ let(:logger) {RDF::Spec.logger}
10
+
11
+ after(:each) {|example| puts logger.to_s if example.exception}
12
+
13
+ it_behaves_like 'an RDF::Reader' do
14
+ let(:reader_input) {File.read(doap)}
15
+ let(:reader) {JSON::LD::Reader.new(reader_input, stream: true)}
16
+ let(:reader_count) {doap_count}
17
+ end
18
+
19
+ context "when validating", pending: ("JRuby support for jsonlint" if RUBY_ENGINE == "jruby") do
20
+ it "detects invalid JSON" do
21
+ expect do |b|
22
+ described_class.new(StringIO.new(%({"a": "b", "a": "c"})), validate: true, logger: false).each_statement(&b)
23
+ end.to raise_error(RDF::ReaderError)
24
+ end
25
+ end
26
+
27
+ context :interface do
28
+ {
29
+ plain: %q({
30
+ "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
31
+ "@type": "foaf:Person",
32
+ "@id": "_:bnode1",
33
+ "foaf:homepage": "http://example.com/bob/",
34
+ "foaf:name": "Bob"
35
+ }),
36
+ leading_comment: %q(
37
+ // A comment before content
38
+ {
39
+ "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
40
+ "@type": "foaf:Person",
41
+ "@id": "_:bnode1",
42
+ "foaf:homepage": "http://example.com/bob/",
43
+ "foaf:name": "Bob"
44
+ }),
45
+ script: %q(<script type="application/ld+json">
46
+ {
47
+ "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
48
+ "@type": "foaf:Person",
49
+ "@id": "_:bnode1",
50
+ "foaf:homepage": "http://example.com/bob/",
51
+ "foaf:name": "Bob"
52
+ }
53
+ </script>),
54
+ script_comments: %q(<script type="application/ld+json">
55
+ // A comment before content
56
+ {
57
+ "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
58
+ "@type": "foaf:Person",
59
+ "@id": "_:bnode1",
60
+ "foaf:homepage": "http://example.com/bob/",
61
+ "foaf:name": "Bob"
62
+ }
63
+ </script>),
64
+ }.each do |variant, src|
65
+ context variant do
66
+ subject {src}
67
+
68
+ describe "#initialize" do
69
+ it "yields reader given string" do
70
+ inner = double("inner")
71
+ expect(inner).to receive(:called).with(JSON::LD::Reader)
72
+ JSON::LD::Reader.new(subject, stream: true) do |reader|
73
+ inner.called(reader.class)
74
+ end
75
+ end
76
+
77
+ it "yields reader given IO" do
78
+ inner = double("inner")
79
+ expect(inner).to receive(:called).with(JSON::LD::Reader)
80
+ JSON::LD::Reader.new(StringIO.new(subject), stream: true) do |reader|
81
+ inner.called(reader.class)
82
+ end
83
+ end
84
+
85
+ it "returns reader" do
86
+ expect(JSON::LD::Reader.new(subject, stream: true)).to be_a(JSON::LD::Reader)
87
+ end
88
+ end
89
+
90
+ describe "#each_statement" do
91
+ it "yields statements" do
92
+ inner = double("inner")
93
+ expect(inner).to receive(:called).with(RDF::Statement).exactly(3)
94
+ JSON::LD::Reader.new(subject, stream: true).each_statement do |statement|
95
+ inner.called(statement.class)
96
+ end
97
+ end
98
+ end
99
+
100
+ describe "#each_triple" do
101
+ it "yields statements" do
102
+ inner = double("inner")
103
+ expect(inner).to receive(:called).exactly(3)
104
+ JSON::LD::Reader.new(subject, stream: true).each_triple do |subject, predicate, object|
105
+ inner.called(subject.class, predicate.class, object.class)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ context "Selected toRdf tests" do
114
+ {
115
+ "e004": {
116
+ input: %({
117
+ "@context": {
118
+ "mylist1": {"@id": "http://example.com/mylist1", "@container": "@list"}
119
+ },
120
+ "@id": "http://example.org/id",
121
+ "mylist1": { "@list": [ ] },
122
+ "http://example.org/list1": { "@list": [ null ] },
123
+ "http://example.org/list2": { "@list": [ {"@value": null} ] }
124
+ }),
125
+ expect: %(
126
+ <http://example.org/id> <http://example.com/mylist1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
127
+ <http://example.org/id> <http://example.org/list1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
128
+ <http://example.org/id> <http://example.org/list2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
129
+ )
130
+ },
131
+ "e015": {
132
+ input: %({
133
+ "@context": {
134
+ "myset2": {"@id": "http://example.com/myset2", "@container": "@set" }
135
+ },
136
+ "@id": "http://example.org/id",
137
+ "myset2": [ [], { "@set": [ null ] }, [ null ] ]
138
+ }),
139
+ expect: %(
140
+ )
141
+ },
142
+ "in06": {
143
+ input: %({
144
+ "@context": {
145
+ "@version": 1.1,
146
+ "@vocab": "http://example.org/vocab#",
147
+ "@base": "http://example.org/base/",
148
+ "id": "@id",
149
+ "type": "@type",
150
+ "data": "@nest",
151
+ "links": "@nest",
152
+ "relationships": "@nest",
153
+ "self": {"@type": "@id"},
154
+ "related": {"@type": "@id"}
155
+ },
156
+ "data": [{
157
+ "type": "articles",
158
+ "id": "1",
159
+ "author": {
160
+ "data": { "type": "people", "id": "9" }
161
+ }
162
+ }]
163
+ }),
164
+ expect: %(
165
+ <http://example.org/base/1> <http://example.org/vocab#author> <http://example.org/base/9> .
166
+ <http://example.org/base/1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/vocab#articles> .
167
+ <http://example.org/base/9> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/vocab#people> .
168
+ ),
169
+ pending: "@nest defining @id"
170
+ }
171
+ }.each do |name, params|
172
+ it name do
173
+ run_to_rdf params
174
+ end
175
+ end
176
+ end
177
+
178
+ describe "test suite" do
179
+ require_relative 'suite_helper'
180
+ m = Fixtures::SuiteTest::Manifest.open("#{Fixtures::SuiteTest::STREAM_SUITE}stream-toRdf-manifest.jsonld")
181
+ describe m.name do
182
+ m.entries.each do |t|
183
+ specify "#{t.property('@id')}: #{t.name}#{' (negative test)' unless t.positiveTest?}" do
184
+ pending "Generalized RDF" if t.options[:produceGeneralizedRdf]
185
+ pending "@nest defining @id" if %w(#tin06).include?(t.property('@id'))
186
+ pending "double @reverse" if %w(#te043).include?(t.property('@id'))
187
+ pending "graph map containing named graph" if %w(#te084 #te087 #te098 #te101 #te105 #te106).include?(t.property('@id'))
188
+ pending "named graphs" if %w(#t0029 #te021).include?(t.property('@id'))
189
+
190
+ if %w(#t0118).include?(t.property('@id'))
191
+ expect {t.run self}.to write(/Statement .* is invalid/).to(:error)
192
+ elsif %w(#twf07).include?(t.property('@id'))
193
+ expect {t.run self}.to write(/skipping graph statement within invalid graph name/).to(:error)
194
+ elsif %w(#te075).include?(t.property('@id'))
195
+ expect {t.run self}.to write(/is invalid/).to(:error)
196
+ elsif %w(#te005 #tpr34 #tpr35 #tpr36 #tpr37 #tpr38 #tpr39 #te119 #te120).include?(t.property('@id'))
197
+ expect {t.run self}.to write("beginning with '@' are reserved for future use").to(:error)
198
+ elsif %w(#te068).include?(t.property('@id'))
199
+ expect {t.run self}.to write("[DEPRECATION]").to(:error)
200
+ elsif %w(#twf05).include?(t.property('@id'))
201
+ expect {t.run self}.to write("@language must be valid BCP47").to(:error)
202
+ else
203
+ expect {t.run self}.not_to write.to(:error)
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end unless ENV['CI']
209
+
210
+ def run_to_rdf(params)
211
+ input = params[:input]
212
+ logger.info("input: #{input}")
213
+ output = RDF::Repository.new
214
+ if params[:expect]
215
+ RDF::NQuads::Reader.new(params[:expect], validate: false) {|r| output << r}
216
+ logger.info("expect (quads): #{output.dump(:nquads, validate: false)}")
217
+ else
218
+ logger.info("expect: #{Regexp.new params[:exception]}")
219
+ end
220
+
221
+ graph = params[:graph] || RDF::Repository.new
222
+ pending params.fetch(:pending, "test implementation") if !input || params[:pending]
223
+ if params[:exception]
224
+ expect do |b|
225
+ JSON::LD::Reader.new(input, stream: true, validate: true, logger: false, **params).each_statement(&b)
226
+ end.to raise_error {|er| expect(er.message).to include params[:exception]}
227
+ else
228
+ if params[:write]
229
+ expect{JSON::LD::Reader.new(input, stream: true, logger: logger, **params) {|st| graph << st}}.to write(params[:write]).to(:error)
230
+ else
231
+ expect{JSON::LD::Reader.new(input, stream: true, logger: logger, **params) {|st| graph << st}}.not_to write.to(:error)
232
+ end
233
+ logger.info("results (quads): #{graph.dump(:nquads, validate: false)}")
234
+ expect(graph).to be_equivalent_graph(output, logger: logger, inputDocument: input)
235
+ end
236
+ end
237
+ end