json-ld 3.1.0 → 3.1.5

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.
@@ -2909,6 +2909,26 @@ describe JSON::LD::API do
2909
2909
  validate: true,
2910
2910
  exception: JSON::LD::JsonLdError::InvalidTermDefinition
2911
2911
  },
2912
+ "Applies property scoped contexts which are aliases of @nest": {
2913
+ input: %({
2914
+ "@context": {
2915
+ "@version": 1.1,
2916
+ "@vocab": "http://example.org/",
2917
+ "nest": {
2918
+ "@id": "@nest",
2919
+ "@context": {
2920
+ "@vocab": "http://example.org/nest/"
2921
+ }
2922
+ }
2923
+ },
2924
+ "nest": {
2925
+ "property": "should be in /nest"
2926
+ }
2927
+ }),
2928
+ output: %([{
2929
+ "http://example.org/nest/property": [{"@value": "should be in /nest"}]
2930
+ }])
2931
+ }
2912
2932
  }.each do |title, params|
2913
2933
  it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
2914
2934
  end
@@ -3366,7 +3386,7 @@ describe JSON::LD::API do
3366
3386
  %w(Nokogiri REXML).each do |impl|
3367
3387
  next unless Module.constants.map(&:to_s).include?(impl)
3368
3388
  context impl do
3369
- before(:all) {@library = impl.downcase.to_s.to_sym}
3389
+ let(:library) {impl.downcase.to_s.to_sym}
3370
3390
 
3371
3391
  {
3372
3392
  "Expands embedded JSON-LD script element": {
@@ -3505,9 +3525,9 @@ describe JSON::LD::API do
3505
3525
  ]),
3506
3526
  extractAllScripts: true
3507
3527
  },
3508
- "Expands as empty with no script element": {
3528
+ "Errors no script element": {
3509
3529
  input: %(<html><head></head></html>),
3510
- output: %([])
3530
+ exception: JSON::LD::JsonLdError::LoadingDocumentFailed
3511
3531
  },
3512
3532
  "Expands as empty with no script element and extractAllScripts": {
3513
3533
  input: %(<html><head></head></html>),
@@ -3619,7 +3639,7 @@ describe JSON::LD::API do
3619
3639
  </head>
3620
3640
  </html>),
3621
3641
  base: "http://example.org/doc#third",
3622
- exception: JSON::LD::JsonLdError::InvalidScriptElement
3642
+ exception: JSON::LD::JsonLdError::LoadingDocumentFailed
3623
3643
  },
3624
3644
  "Errors if targeted element is not a script element": {
3625
3645
  input: %(
@@ -3636,7 +3656,7 @@ describe JSON::LD::API do
3636
3656
  </head>
3637
3657
  </html>),
3638
3658
  base: "http://example.org/doc#first",
3639
- exception: JSON::LD::JsonLdError::InvalidScriptElement
3659
+ exception: JSON::LD::JsonLdError::LoadingDocumentFailed
3640
3660
  },
3641
3661
  "Errors if targeted element does not have type application/ld+json": {
3642
3662
  input: %(
@@ -3653,7 +3673,7 @@ describe JSON::LD::API do
3653
3673
  </head>
3654
3674
  </html>),
3655
3675
  base: "http://example.org/doc#first",
3656
- exception: JSON::LD::JsonLdError::InvalidScriptElement
3676
+ exception: JSON::LD::JsonLdError::LoadingDocumentFailed
3657
3677
  },
3658
3678
  "Errors if uncommented script text contains comment": {
3659
3679
  input: %(
@@ -3722,10 +3742,10 @@ describe JSON::LD::API do
3722
3742
  },
3723
3743
  }.each do |title, params|
3724
3744
  it(title) do
3725
- skip "rexml" if params[:not] == @library
3726
- params[:input] = StringIO.new(params[:input])
3745
+ skip "rexml" if params[:not] == library
3746
+ params = params.merge(input: StringIO.new(params[:input]))
3727
3747
  params[:input].send(:define_singleton_method, :content_type) {"text/html"}
3728
- run_expand params.merge(validate: true, library: @library)
3748
+ run_expand params.merge(validate: true, library: library)
3729
3749
  end
3730
3750
  end
3731
3751
  end
@@ -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
@@ -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