json-ld 3.1.1 → 3.1.6

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.
@@ -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