json-ld 3.2.4 → 3.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/json/ld/api.rb +807 -771
  4. data/lib/json/ld/compact.rb +304 -304
  5. data/lib/json/ld/conneg.rb +179 -161
  6. data/lib/json/ld/context.rb +2080 -1913
  7. data/lib/json/ld/expand.rb +745 -666
  8. data/lib/json/ld/extensions.rb +14 -13
  9. data/lib/json/ld/flatten.rb +257 -247
  10. data/lib/json/ld/format.rb +202 -194
  11. data/lib/json/ld/frame.rb +525 -502
  12. data/lib/json/ld/from_rdf.rb +223 -204
  13. data/lib/json/ld/html/nokogiri.rb +123 -121
  14. data/lib/json/ld/html/rexml.rb +151 -147
  15. data/lib/json/ld/reader.rb +107 -100
  16. data/lib/json/ld/resource.rb +224 -205
  17. data/lib/json/ld/streaming_reader.rb +574 -507
  18. data/lib/json/ld/streaming_writer.rb +93 -92
  19. data/lib/json/ld/to_rdf.rb +171 -169
  20. data/lib/json/ld/utils.rb +270 -264
  21. data/lib/json/ld/version.rb +24 -14
  22. data/lib/json/ld/writer.rb +334 -311
  23. data/lib/json/ld.rb +103 -96
  24. metadata +55 -198
  25. data/spec/api_spec.rb +0 -132
  26. data/spec/compact_spec.rb +0 -3482
  27. data/spec/conneg_spec.rb +0 -373
  28. data/spec/context_spec.rb +0 -2056
  29. data/spec/expand_spec.rb +0 -4496
  30. data/spec/flatten_spec.rb +0 -1203
  31. data/spec/format_spec.rb +0 -115
  32. data/spec/frame_spec.rb +0 -2541
  33. data/spec/from_rdf_spec.rb +0 -1072
  34. data/spec/matchers.rb +0 -20
  35. data/spec/rdfstar_spec.rb +0 -25
  36. data/spec/reader_spec.rb +0 -883
  37. data/spec/resource_spec.rb +0 -76
  38. data/spec/spec_helper.rb +0 -281
  39. data/spec/streaming_reader_spec.rb +0 -237
  40. data/spec/streaming_writer_spec.rb +0 -145
  41. data/spec/suite_compact_spec.rb +0 -22
  42. data/spec/suite_expand_spec.rb +0 -36
  43. data/spec/suite_flatten_spec.rb +0 -34
  44. data/spec/suite_frame_spec.rb +0 -29
  45. data/spec/suite_from_rdf_spec.rb +0 -22
  46. data/spec/suite_helper.rb +0 -411
  47. data/spec/suite_html_spec.rb +0 -22
  48. data/spec/suite_http_spec.rb +0 -35
  49. data/spec/suite_remote_doc_spec.rb +0 -22
  50. data/spec/suite_to_rdf_spec.rb +0 -30
  51. data/spec/support/extensions.rb +0 -44
  52. data/spec/test-files/test-1-compacted.jsonld +0 -10
  53. data/spec/test-files/test-1-context.jsonld +0 -7
  54. data/spec/test-files/test-1-expanded.jsonld +0 -5
  55. data/spec/test-files/test-1-input.jsonld +0 -10
  56. data/spec/test-files/test-1-rdf.ttl +0 -8
  57. data/spec/test-files/test-2-compacted.jsonld +0 -20
  58. data/spec/test-files/test-2-context.jsonld +0 -7
  59. data/spec/test-files/test-2-expanded.jsonld +0 -16
  60. data/spec/test-files/test-2-input.jsonld +0 -20
  61. data/spec/test-files/test-2-rdf.ttl +0 -14
  62. data/spec/test-files/test-3-compacted.jsonld +0 -11
  63. data/spec/test-files/test-3-context.jsonld +0 -8
  64. data/spec/test-files/test-3-expanded.jsonld +0 -10
  65. data/spec/test-files/test-3-input.jsonld +0 -11
  66. data/spec/test-files/test-3-rdf.ttl +0 -8
  67. data/spec/test-files/test-4-compacted.jsonld +0 -10
  68. data/spec/test-files/test-4-context.jsonld +0 -7
  69. data/spec/test-files/test-4-expanded.jsonld +0 -6
  70. data/spec/test-files/test-4-input.jsonld +0 -10
  71. data/spec/test-files/test-4-rdf.ttl +0 -5
  72. data/spec/test-files/test-5-compacted.jsonld +0 -13
  73. data/spec/test-files/test-5-context.jsonld +0 -7
  74. data/spec/test-files/test-5-expanded.jsonld +0 -9
  75. data/spec/test-files/test-5-input.jsonld +0 -13
  76. data/spec/test-files/test-5-rdf.ttl +0 -7
  77. data/spec/test-files/test-6-compacted.jsonld +0 -10
  78. data/spec/test-files/test-6-context.jsonld +0 -7
  79. data/spec/test-files/test-6-expanded.jsonld +0 -10
  80. data/spec/test-files/test-6-input.jsonld +0 -10
  81. data/spec/test-files/test-6-rdf.ttl +0 -6
  82. data/spec/test-files/test-7-compacted.jsonld +0 -23
  83. data/spec/test-files/test-7-context.jsonld +0 -4
  84. data/spec/test-files/test-7-expanded.jsonld +0 -20
  85. data/spec/test-files/test-7-input.jsonld +0 -23
  86. data/spec/test-files/test-7-rdf.ttl +0 -14
  87. data/spec/test-files/test-8-compacted.jsonld +0 -34
  88. data/spec/test-files/test-8-context.jsonld +0 -11
  89. data/spec/test-files/test-8-expanded.jsonld +0 -24
  90. data/spec/test-files/test-8-frame.jsonld +0 -18
  91. data/spec/test-files/test-8-framed.jsonld +0 -25
  92. data/spec/test-files/test-8-input.jsonld +0 -30
  93. data/spec/test-files/test-8-rdf.ttl +0 -15
  94. data/spec/test-files/test-9-compacted.jsonld +0 -20
  95. data/spec/test-files/test-9-context.jsonld +0 -13
  96. data/spec/test-files/test-9-expanded.jsonld +0 -14
  97. data/spec/test-files/test-9-input.jsonld +0 -12
  98. data/spec/to_rdf_spec.rb +0 -1684
  99. data/spec/writer_spec.rb +0 -427
data/spec/expand_spec.rb DELETED
@@ -1,4496 +0,0 @@
1
- # coding: utf-8
2
- require_relative 'spec_helper'
3
-
4
- describe JSON::LD::API do
5
- let(:logger) {RDF::Spec.logger}
6
-
7
- describe ".expand" do
8
- {
9
- "empty doc": {
10
- input: {},
11
- output: []
12
- },
13
- "@list coercion": {
14
- input: %({
15
- "@context": {
16
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
17
- },
18
- "foo": [{"@value": "bar"}]
19
- }),
20
- output: %([{
21
- "http://example.com/foo": [{"@list": [{"@value": "bar"}]}]
22
- }])
23
- },
24
- "native values in list": {
25
- input: %({
26
- "http://example.com/foo": {"@list": [1, 2]}
27
- }),
28
- output: %([{
29
- "http://example.com/foo": [{"@list": [{"@value": 1}, {"@value": 2}]}]
30
- }])
31
- },
32
- "@graph": {
33
- input: %({
34
- "@context": {"ex": "http://example.com/"},
35
- "@graph": [
36
- {"ex:foo": {"@value": "foo"}},
37
- {"ex:bar": {"@value": "bar"}}
38
- ]
39
- }),
40
- output: %([
41
- {"http://example.com/foo": [{"@value": "foo"}]},
42
- {"http://example.com/bar": [{"@value": "bar"}]}
43
- ])
44
- },
45
- "@graph value (expands to array form)": {
46
- input: %({
47
- "@context": {"ex": "http://example.com/"},
48
- "ex:p": {
49
- "@id": "ex:Sub1",
50
- "@graph": {
51
- "ex:q": "foo"
52
- }
53
- }
54
- }),
55
- output: %([{
56
- "http://example.com/p": [{
57
- "@id": "http://example.com/Sub1",
58
- "@graph": [{
59
- "http://example.com/q": [{"@value": "foo"}]
60
- }]
61
- }]
62
- }])
63
- },
64
- "@type with CURIE": {
65
- input: %({
66
- "@context": {"ex": "http://example.com/"},
67
- "@type": "ex:type"
68
- }),
69
- output: %([
70
- {"@type": ["http://example.com/type"]}
71
- ])
72
- },
73
- "@type with CURIE and muliple values": {
74
- input: %({
75
- "@context": {"ex": "http://example.com/"},
76
- "@type": ["ex:type1", "ex:type2"]
77
- }),
78
- output: %([
79
- {"@type": ["http://example.com/type1", "http://example.com/type2"]}
80
- ])
81
- },
82
- "@value with false": {
83
- input: %({"http://example.com/ex": {"@value": false}}),
84
- output: %([{"http://example.com/ex": [{"@value": false}]}])
85
- },
86
- "compact IRI": {
87
- input: %({
88
- "@context": {"ex": "http://example.com/"},
89
- "ex:p": {"@id": "ex:Sub1"}
90
- }),
91
- output: %([{
92
- "http://example.com/p": [{"@id": "http://example.com/Sub1"}]
93
- }])
94
- },
95
- }.each_pair do |title, params|
96
- it(title) {run_expand params}
97
- end
98
-
99
- context "default language" do
100
- {
101
- "base": {
102
- input: %({
103
- "http://example/foo": "bar"
104
- }),
105
- output: %([{
106
- "http://example/foo": [{"@value": "bar", "@language": "en"}]
107
- }]),
108
- language: "en"
109
- },
110
- "override": {
111
- input: %({
112
- "@context": {"@language": null},
113
- "http://example/foo": "bar"
114
- }),
115
- output: %([{
116
- "http://example/foo": [{"@value": "bar"}]
117
- }]),
118
- language: "en"
119
- }
120
- }.each_pair do |title, params|
121
- it(title) {run_expand params}
122
- end
123
- end
124
-
125
- context "with relative IRIs" do
126
- {
127
- "base": {
128
- input: %({
129
- "@id": "",
130
- "@type": "http://www.w3.org/2000/01/rdf-schema#Resource"
131
- }),
132
- output: %([{
133
- "@id": "http://example.org/",
134
- "@type": ["http://www.w3.org/2000/01/rdf-schema#Resource"]
135
- }])
136
- },
137
- "relative": {
138
- input: %({
139
- "@id": "a/b",
140
- "@type": "http://www.w3.org/2000/01/rdf-schema#Resource"
141
- }),
142
- output: %([{
143
- "@id": "http://example.org/a/b",
144
- "@type": ["http://www.w3.org/2000/01/rdf-schema#Resource"]
145
- }])
146
- },
147
- "hash": {
148
- input: %({
149
- "@id": "#a",
150
- "@type": "http://www.w3.org/2000/01/rdf-schema#Resource"
151
- }),
152
- output: %([{
153
- "@id": "http://example.org/#a",
154
- "@type": ["http://www.w3.org/2000/01/rdf-schema#Resource"]
155
- }])
156
- },
157
- "unmapped @id": {
158
- input: %({
159
- "http://example.com/foo": {"@id": "bar"}
160
- }),
161
- output: %([{
162
- "http://example.com/foo": [{"@id": "http://example.org/bar"}]
163
- }])
164
- },
165
- "json-ld-syntax#66": {
166
- input: %({
167
- "@context": {
168
- "@base": "https://ex.org/",
169
- "u": {"@id": "urn:u:", "@type": "@id"}
170
- },
171
- "u": ["#Test", "#Test:2"]
172
- }),
173
- output: %([{
174
- "urn:u:": [
175
- {"@id": "https://ex.org/#Test"},
176
- {"@id": "https://ex.org/#Test:2"}
177
- ]
178
- }])
179
- }
180
- }.each do |title, params|
181
- it(title) {run_expand params.merge(base: "http://example.org/")}
182
- end
183
- end
184
-
185
- context "with relative property IRIs" do
186
- {
187
- "base": {
188
- input: %({
189
- "http://a/b": "foo"
190
- }),
191
- output: %([{
192
- "http://a/b": [{"@value": "foo"}]
193
- }])
194
- },
195
- "relative": {
196
- input: %({
197
- "a/b": "foo"
198
- }),
199
- output: %([])
200
- },
201
- "hash": {
202
- input: %({
203
- "#a": "foo"
204
- }),
205
- output: %([])
206
- },
207
- "dotseg": {
208
- input: %({
209
- "../a": "foo"
210
- }),
211
- output: %([])
212
- },
213
- }.each do |title, params|
214
- it(title) {run_expand params.merge(base: "http://example.org/")}
215
- end
216
-
217
- context "with @vocab" do
218
- {
219
- "base": {
220
- input: %({
221
- "@context": {"@vocab": "http://vocab/"},
222
- "http://a/b": "foo"
223
- }),
224
- output: %([{
225
- "http://a/b": [{"@value": "foo"}]
226
- }])
227
- },
228
- "relative": {
229
- input: %({
230
- "@context": {"@vocab": "http://vocab/"},
231
- "a/b": "foo"
232
- }),
233
- output: %([{
234
- "http://vocab/a/b": [{"@value": "foo"}]
235
- }])
236
- },
237
- "hash": {
238
- input: %({
239
- "@context": {"@vocab": "http://vocab/"},
240
- "#a": "foo"
241
- }),
242
- output: %([{
243
- "http://vocab/#a": [{"@value": "foo"}]
244
- }])
245
- },
246
- "dotseg": {
247
- input: %({
248
- "@context": {"@vocab": "http://vocab/"},
249
- "../a": "foo"
250
- }),
251
- output: %([{
252
- "http://vocab/../a": [{"@value": "foo"}]
253
- }])
254
- },
255
- }.each do |title, params|
256
- it(title) {run_expand params.merge(base: "http://example.org/")}
257
- end
258
- end
259
-
260
- context "with @vocab: ''" do
261
- {
262
- "base": {
263
- input: %({
264
- "@context": {"@vocab": ""},
265
- "http://a/b": "foo"
266
- }),
267
- output: %([{
268
- "http://a/b": [{"@value": "foo"}]
269
- }])
270
- },
271
- "relative": {
272
- input: %({
273
- "@context": {"@vocab": ""},
274
- "a/b": "foo"
275
- }),
276
- output: %([{
277
- "http://example.org/a/b": [{"@value": "foo"}]
278
- }])
279
- },
280
- "hash": {
281
- input: %({
282
- "@context": {"@vocab": ""},
283
- "#a": "foo"
284
- }),
285
- output: %([{
286
- "http://example.org/#a": [{"@value": "foo"}]
287
- }])
288
- },
289
- "dotseg": {
290
- input: %({
291
- "@context": {"@vocab": ""},
292
- "../a": "foo"
293
- }),
294
- output: %([{
295
- "http://example.org/../a": [{"@value": "foo"}]
296
- }])
297
- },
298
- "example": {
299
- input: %({
300
- "@context": {
301
- "@base": "http://example/document",
302
- "@vocab": ""
303
- },
304
- "@id": "http://example.org/places#BrewEats",
305
- "@type": "#Restaurant",
306
- "#name": "Brew Eats"
307
- }),
308
- output: %([{
309
- "@id": "http://example.org/places#BrewEats",
310
- "@type": ["http://example/document#Restaurant"],
311
- "http://example/document#name": [{"@value": "Brew Eats"}]
312
- }])
313
- }
314
- }.each do |title, params|
315
- it(title) {run_expand params.merge(base: "http://example.org/")}
316
- end
317
- end
318
-
319
- context "with @vocab: '/relative#'" do
320
- {
321
- "base": {
322
- input: %({
323
- "@context": {"@vocab": "/relative#"},
324
- "http://a/b": "foo"
325
- }),
326
- output: %([{
327
- "http://a/b": [{"@value": "foo"}]
328
- }])
329
- },
330
- "relative": {
331
- input: %({
332
- "@context": {"@vocab": "/relative#"},
333
- "a/b": "foo"
334
- }),
335
- output: %([{
336
- "http://example.org/relative#a/b": [{"@value": "foo"}]
337
- }])
338
- },
339
- "hash": {
340
- input: %({
341
- "@context": {"@vocab": "/relative#"},
342
- "#a": "foo"
343
- }),
344
- output: %([{
345
- "http://example.org/relative##a": [{"@value": "foo"}]
346
- }])
347
- },
348
- "dotseg": {
349
- input: %({
350
- "@context": {"@vocab": "/relative#"},
351
- "../a": "foo"
352
- }),
353
- output: %([{
354
- "http://example.org/relative#../a": [{"@value": "foo"}]
355
- }])
356
- },
357
- "example": {
358
- input: %({
359
- "@context": {
360
- "@base": "http://example/document",
361
- "@vocab": "/relative#"
362
- },
363
- "@id": "http://example.org/places#BrewEats",
364
- "@type": "Restaurant",
365
- "name": "Brew Eats"
366
- }),
367
- output: %([{
368
- "@id": "http://example.org/places#BrewEats",
369
- "@type": ["http://example/relative#Restaurant"],
370
- "http://example/relative#name": [{"@value": "Brew Eats"}]
371
- }])
372
- }
373
- }.each do |title, params|
374
- it(title) {run_expand params.merge(base: "http://example.org/")}
375
- end
376
- end
377
- end
378
-
379
- context "keyword aliasing" do
380
- {
381
- "@id": {
382
- input: %({
383
- "@context": {"id": "@id"},
384
- "id": "",
385
- "@type": "http://www.w3.org/2000/01/rdf-schema#Resource"
386
- }),
387
- output: %([{
388
- "@id": "",
389
- "@type":[ "http://www.w3.org/2000/01/rdf-schema#Resource"]
390
- }])
391
- },
392
- "@type": {
393
- input: %({
394
- "@context": {"type": "@type"},
395
- "type": "http://www.w3.org/2000/01/rdf-schema#Resource",
396
- "http://example.com/foo": {"@value": "bar", "type": "http://example.com/baz"}
397
- }),
398
- output: %([{
399
- "@type": ["http://www.w3.org/2000/01/rdf-schema#Resource"],
400
- "http://example.com/foo": [{"@value": "bar", "@type": "http://example.com/baz"}]
401
- }])
402
- },
403
- "@language": {
404
- input: %({
405
- "@context": {"language": "@language"},
406
- "http://example.com/foo": {"@value": "bar", "language": "baz"}
407
- }),
408
- output: %([{
409
- "http://example.com/foo": [{"@value": "bar", "@language": "baz"}]
410
- }])
411
- },
412
- "@value": {
413
- input: %({
414
- "@context": {"literal": "@value"},
415
- "http://example.com/foo": {"literal": "bar"}
416
- }),
417
- output: %([{
418
- "http://example.com/foo": [{"@value": "bar"}]
419
- }])
420
- },
421
- "@list": {
422
- input: %({
423
- "@context": {"list": "@list"},
424
- "http://example.com/foo": {"list": ["bar"]}
425
- }),
426
- output: %([{
427
- "http://example.com/foo": [{"@list": [{"@value": "bar"}]}]
428
- }])
429
- },
430
- }.each do |title, params|
431
- it(title) {run_expand params}
432
- end
433
- end
434
-
435
- context "native types" do
436
- {
437
- "true": {
438
- input: %({
439
- "@context": {"e": "http://example.org/vocab#"},
440
- "e:bool": true
441
- }),
442
- output: %([{
443
- "http://example.org/vocab#bool": [{"@value": true}]
444
- }])
445
- },
446
- "false": {
447
- input: %({
448
- "@context": {"e": "http://example.org/vocab#"},
449
- "e:bool": false
450
- }),
451
- output: %([{
452
- "http://example.org/vocab#bool": [{"@value": false}]
453
- }])
454
- },
455
- "double": {
456
- input: %({
457
- "@context": {"e": "http://example.org/vocab#"},
458
- "e:double": 1.23
459
- }),
460
- output: %([{
461
- "http://example.org/vocab#double": [{"@value": 1.23}]
462
- }])
463
- },
464
- "double-zero": {
465
- input: %({
466
- "@context": {"e": "http://example.org/vocab#"},
467
- "e:double-zero": 0.0e0
468
- }),
469
- output: %([{
470
- "http://example.org/vocab#double-zero": [{"@value": 0.0e0}]
471
- }])
472
- },
473
- "integer": {
474
- input: %({
475
- "@context": {"e": "http://example.org/vocab#"},
476
- "e:integer": 123
477
- }),
478
- output: %([{
479
- "http://example.org/vocab#integer": [{"@value": 123}]
480
- }])
481
- },
482
- }.each do |title, params|
483
- it(title) {run_expand params}
484
- end
485
-
486
- context "with @type: @none" do
487
- {
488
- "true": {
489
- input: %({
490
- "@context": {"e": {"@id": "http://example.org/vocab#bool", "@type": "@none"}},
491
- "e": true
492
- }),
493
- output:%( [{
494
- "http://example.org/vocab#bool": [{"@value": true}]
495
- }])
496
- },
497
- "false": {
498
- input: %({
499
- "@context": {"e": {"@id": "http://example.org/vocab#bool", "@type": "@none"}},
500
- "e": false
501
- }),
502
- output: %([{
503
- "http://example.org/vocab#bool": [{"@value": false}]
504
- }])
505
- },
506
- "double": {
507
- input: %({
508
- "@context": {"e": {"@id": "http://example.org/vocab#double", "@type": "@none"}},
509
- "e": 1.23
510
- }),
511
- output: %([{
512
- "http://example.org/vocab#double": [{"@value": 1.23}]
513
- }])
514
- },
515
- "double-zero": {
516
- input: %({
517
- "@context": {"e": {"@id": "http://example.org/vocab#double", "@type": "@none"}},
518
- "e": 0.0e0
519
- }),
520
- output: %([{
521
- "http://example.org/vocab#double": [{"@value": 0.0e0}]
522
- }])
523
- },
524
- "integer": {
525
- input: %({
526
- "@context": {"e": {"@id": "http://example.org/vocab#integer", "@type": "@none"}},
527
- "e": 123
528
- }),
529
- output: %([{
530
- "http://example.org/vocab#integer": [{"@value": 123}]
531
- }])
532
- },
533
- }.each do |title, params|
534
- it(title) {run_expand(processingMode: "json-ld-1.1", **params)}
535
- end
536
- end
537
-
538
- context "with @type: @id" do
539
- {
540
- "true": {
541
- input: %({
542
- "@context": {"e": {"@id": "http://example.org/vocab#bool", "@type": "@id"}},
543
- "e": true
544
- }),
545
- output:%( [{
546
- "http://example.org/vocab#bool": [{"@value": true}]
547
- }])
548
- },
549
- "false": {
550
- input: %({
551
- "@context": {"e": {"@id": "http://example.org/vocab#bool", "@type": "@id"}},
552
- "e": false
553
- }),
554
- output: %([{
555
- "http://example.org/vocab#bool": [{"@value": false}]
556
- }])
557
- },
558
- "double": {
559
- input: %({
560
- "@context": {"e": {"@id": "http://example.org/vocab#double", "@type": "@id"}},
561
- "e": 1.23
562
- }),
563
- output: %([{
564
- "http://example.org/vocab#double": [{"@value": 1.23}]
565
- }])
566
- },
567
- "double-zero": {
568
- input: %({
569
- "@context": {"e": {"@id": "http://example.org/vocab#double", "@type": "@id"}},
570
- "e": 0.0e0
571
- }),
572
- output: %([{
573
- "http://example.org/vocab#double": [{"@value": 0.0e0}]
574
- }])
575
- },
576
- "integer": {
577
- input: %({
578
- "@context": {"e": {"@id": "http://example.org/vocab#integer", "@type": "@id"}},
579
- "e": 123
580
- }),
581
- output: %([{
582
- "http://example.org/vocab#integer": [{"@value": 123}]
583
- }])
584
- },
585
- }.each do |title, params|
586
- it(title) {run_expand params}
587
- end
588
- end
589
-
590
- context "with @type: @vocab" do
591
- {
592
- "true": {
593
- input: %({
594
- "@context": {"e": {"@id": "http://example.org/vocab#bool", "@type": "@vocab"}},
595
- "e": true
596
- }),
597
- output:%( [{
598
- "http://example.org/vocab#bool": [{"@value": true}]
599
- }])
600
- },
601
- "false": {
602
- input: %({
603
- "@context": {"e": {"@id": "http://example.org/vocab#bool", "@type": "@vocab"}},
604
- "e": false
605
- }),
606
- output: %([{
607
- "http://example.org/vocab#bool": [{"@value": false}]
608
- }])
609
- },
610
- "double": {
611
- input: %({
612
- "@context": {"e": {"@id": "http://example.org/vocab#double", "@type": "@vocab"}},
613
- "e": 1.23
614
- }),
615
- output: %([{
616
- "http://example.org/vocab#double": [{"@value": 1.23}]
617
- }])
618
- },
619
- "double-zero": {
620
- input: %({
621
- "@context": {"e": {"@id": "http://example.org/vocab#double", "@type": "@vocab"}},
622
- "e": 0.0e0
623
- }),
624
- output: %([{
625
- "http://example.org/vocab#double": [{"@value": 0.0e0}]
626
- }])
627
- },
628
- "integer": {
629
- input: %({
630
- "@context": {"e": {"@id": "http://example.org/vocab#integer", "@type": "@vocab"}},
631
- "e": 123
632
- }),
633
- output: %([{
634
- "http://example.org/vocab#integer": [{"@value": 123}]
635
- }])
636
- },
637
- }.each do |title, params|
638
- it(title) {run_expand params}
639
- end
640
- end
641
- end
642
-
643
- context "with @type: @json" do
644
- {
645
- "true": {
646
- input: %({
647
- "@context": {
648
- "@version": 1.1,
649
- "e": {"@id": "http://example.org/vocab#bool", "@type": "@json"}
650
- },
651
- "e": true
652
- }),
653
- output:%( [{
654
- "http://example.org/vocab#bool": [{"@value": true, "@type": "@json"}]
655
- }])
656
- },
657
- "false": {
658
- input: %({
659
- "@context": {
660
- "@version": 1.1,
661
- "e": {"@id": "http://example.org/vocab#bool", "@type": "@json"}
662
- },
663
- "e": false
664
- }),
665
- output: %([{
666
- "http://example.org/vocab#bool": [{"@value": false, "@type": "@json"}]
667
- }])
668
- },
669
- "double": {
670
- input: %({
671
- "@context": {
672
- "@version": 1.1,
673
- "e": {"@id": "http://example.org/vocab#double", "@type": "@json"}
674
- },
675
- "e": 1.23
676
- }),
677
- output: %([{
678
- "http://example.org/vocab#double": [{"@value": 1.23, "@type": "@json"}]
679
- }])
680
- },
681
- "double-zero": {
682
- input: %({
683
- "@context": {
684
- "@version": 1.1,
685
- "e": {"@id": "http://example.org/vocab#double", "@type": "@json"}
686
- },
687
- "e": 0.0e0
688
- }),
689
- output: %([{
690
- "http://example.org/vocab#double": [{"@value": 0.0e0, "@type": "@json"}]
691
- }])
692
- },
693
- "integer": {
694
- input: %({
695
- "@context": {
696
- "@version": 1.1,
697
- "e": {"@id": "http://example.org/vocab#integer", "@type": "@json"}
698
- },
699
- "e": 123
700
- }),
701
- output: %([{
702
- "http://example.org/vocab#integer": [{"@value": 123, "@type": "@json"}]
703
- }])
704
- },
705
- "string": {
706
- input: %({
707
- "@context": {
708
- "@version": 1.1,
709
- "e": {"@id": "http://example.org/vocab#string", "@type": "@json"}
710
- },
711
- "e": "string"
712
- }),
713
- output: %([{
714
- "http://example.org/vocab#string": [{
715
- "@value": "string",
716
- "@type": "@json"
717
- }]
718
- }])
719
- },
720
- "null": {
721
- input: %({
722
- "@context": {
723
- "@version": 1.1,
724
- "e": {"@id": "http://example.org/vocab#null", "@type": "@json"}
725
- },
726
- "e": null
727
- }),
728
- output: %([{
729
- "http://example.org/vocab#null": [{
730
- "@value": null,
731
- "@type": "@json"
732
- }]
733
- }])
734
- },
735
- "object": {
736
- input: %({
737
- "@context": {
738
- "@version": 1.1,
739
- "e": {"@id": "http://example.org/vocab#object", "@type": "@json"}
740
- },
741
- "e": {"foo": "bar"}
742
- }),
743
- output: %([{
744
- "http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}]
745
- }])
746
- },
747
- "array": {
748
- input: %({
749
- "@context": {
750
- "@version": 1.1,
751
- "e": {"@id": "http://example.org/vocab#array", "@type": "@json"}
752
- },
753
- "e": [{"foo": "bar"}]
754
- }),
755
- output: %([{
756
- "http://example.org/vocab#array": [{"@value": [{"foo": "bar"}], "@type": "@json"}]
757
- }])
758
- },
759
- "Does not expand terms inside json": {
760
- input: %({
761
- "@context": {
762
- "@version": 1.1,
763
- "e": {"@id": "http://example.org/vocab#array", "@type": "@json"}
764
- },
765
- "e": [{"e": "bar"}]
766
- }),
767
- output: %([{
768
- "http://example.org/vocab#array": [{"@value": [{"e": "bar"}], "@type": "@json"}]
769
- }])
770
- },
771
- "Already expanded object": {
772
- input: %({
773
- "http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}]
774
- }),
775
- output: %([{
776
- "http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}]
777
- }]),
778
- processingMode: 'json-ld-1.1'
779
- },
780
- "Already expanded object with aliased keys": {
781
- input: %({
782
- "@context": {"@version": 1.1, "value": "@value", "type": "@type", "json": "@json"},
783
- "http://example.org/vocab#object": [{"value": {"foo": "bar"}, "type": "json"}]
784
- }),
785
- output: %([{
786
- "http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}]
787
- }])
788
- },
789
- }.each do |title, params|
790
- it(title) {run_expand params}
791
- end
792
- end
793
-
794
- context "coerced typed values" do
795
- {
796
- "boolean": {
797
- input: %({
798
- "@context": {"foo": {"@id": "http://example.org/foo", "@type": "http://www.w3.org/2001/XMLSchema#boolean"}},
799
- "foo": "true"
800
- }),
801
- output: %([{
802
- "http://example.org/foo": [{"@value": "true", "@type": "http://www.w3.org/2001/XMLSchema#boolean"}]
803
- }])
804
- },
805
- "date": {
806
- input: %({
807
- "@context": {"foo": {"@id": "http://example.org/foo", "@type": "http://www.w3.org/2001/XMLSchema#date"}},
808
- "foo": "2011-03-26"
809
- }),
810
- output: %([{
811
- "http://example.org/foo": [{"@value": "2011-03-26", "@type": "http://www.w3.org/2001/XMLSchema#date"}]
812
- }])
813
- },
814
- }.each do |title, params|
815
- it(title) {run_expand params}
816
- end
817
- end
818
-
819
- context "null" do
820
- {
821
- "value": {
822
- input: %({"http://example.com/foo": null}),
823
- output: []
824
- },
825
- "@value": {
826
- input: %({"http://example.com/foo": {"@value": null}}),
827
- output: []
828
- },
829
- "@value and non-null @type": {
830
- input: %({"http://example.com/foo": {"@value": null, "@type": "http://type"}}),
831
- output: []
832
- },
833
- "@value and non-null @language": {
834
- input: %({"http://example.com/foo": {"@value": null, "@language": "en"}}),
835
- output: []
836
- },
837
- "array with null elements": {
838
- input: %({"http://example.com/foo": [null]}),
839
- output: %([{"http://example.com/foo": []}])
840
- },
841
- "@set with null @value": {
842
- input: %({
843
- "http://example.com/foo": [
844
- {"@value": null, "@type": "http://example.org/Type"}
845
- ]
846
- }),
847
- output: %([{
848
- "http://example.com/foo": []
849
- }])
850
- }
851
- }.each do |title, params|
852
- it(title) {run_expand params}
853
- end
854
- end
855
-
856
- context "@direction" do
857
- {
858
- "value with coerced null direction": {
859
- input: %({
860
- "@context": {
861
- "@direction": "rtl",
862
- "ex": "http://example.org/vocab#",
863
- "ex:ltr": { "@direction": "ltr" },
864
- "ex:none": { "@direction": null }
865
- },
866
- "ex:rtl": "rtl",
867
- "ex:ltr": "ltr",
868
- "ex:none": "no direction"
869
- }),
870
- output: %([
871
- {
872
- "http://example.org/vocab#rtl": [{"@value": "rtl", "@direction": "rtl"}],
873
- "http://example.org/vocab#ltr": [{"@value": "ltr", "@direction": "ltr"}],
874
- "http://example.org/vocab#none": [{"@value": "no direction"}]
875
- }
876
- ])
877
- }
878
- }.each_pair do |title, params|
879
- it(title) {run_expand params}
880
- end
881
- end
882
-
883
- context "default language" do
884
- {
885
- "value with coerced null language": {
886
- input: %({
887
- "@context": {
888
- "@language": "en",
889
- "ex": "http://example.org/vocab#",
890
- "ex:german": { "@language": "de" },
891
- "ex:nolang": { "@language": null }
892
- },
893
- "ex:german": "german",
894
- "ex:nolang": "no language"
895
- }),
896
- output: %([
897
- {
898
- "http://example.org/vocab#german": [{"@value": "german", "@language": "de"}],
899
- "http://example.org/vocab#nolang": [{"@value": "no language"}]
900
- }
901
- ])
902
- },
903
- }.each do |title, params|
904
- it(title) {run_expand params}
905
- end
906
-
907
- context "and default direction" do
908
- {
909
- "value with coerced null direction": {
910
- input: %({
911
- "@context": {
912
- "@language": "en",
913
- "@direction": "rtl",
914
- "ex": "http://example.org/vocab#",
915
- "ex:ltr": { "@direction": "ltr" },
916
- "ex:none": { "@direction": null },
917
- "ex:german": { "@language": "de" },
918
- "ex:nolang": { "@language": null },
919
- "ex:german_ltr": { "@language": "de", "@direction": "ltr" },
920
- "ex:nolang_ltr": { "@language": null, "@direction": "ltr" },
921
- "ex:none_none": { "@language": null, "@direction": null },
922
- "ex:german_none": { "@language": "de", "@direction": null }
923
- },
924
- "ex:rtl": "rtl en",
925
- "ex:ltr": "ltr en",
926
- "ex:none": "no direction en",
927
- "ex:german": "german rtl",
928
- "ex:nolang": "no language rtl",
929
- "ex:german_ltr": "german ltr",
930
- "ex:nolang_ltr": "no language ltr",
931
- "ex:none_none": "no language or direction",
932
- "ex:german_none": "german no direction"
933
- }),
934
- output: %([
935
- {
936
- "http://example.org/vocab#rtl": [{"@value": "rtl en", "@language": "en", "@direction": "rtl"}],
937
- "http://example.org/vocab#ltr": [{"@value": "ltr en", "@language": "en", "@direction": "ltr"}],
938
- "http://example.org/vocab#none": [{"@value": "no direction en", "@language": "en"}],
939
- "http://example.org/vocab#german": [{"@value": "german rtl", "@language": "de", "@direction": "rtl"}],
940
- "http://example.org/vocab#nolang": [{"@value": "no language rtl", "@direction": "rtl"}],
941
- "http://example.org/vocab#german_ltr": [{"@value": "german ltr", "@language": "de", "@direction": "ltr"}],
942
- "http://example.org/vocab#nolang_ltr": [{"@value": "no language ltr", "@direction": "ltr"}],
943
- "http://example.org/vocab#none_none": [{"@value": "no language or direction"}],
944
- "http://example.org/vocab#german_none": [{"@value": "german no direction", "@language": "de"}]
945
- }
946
- ])
947
- }
948
- }.each_pair do |title, params|
949
- it(title) {run_expand params}
950
- end
951
- end
952
- end
953
-
954
- context "default vocabulary" do
955
- {
956
- "property": {
957
- input: %({
958
- "@context": {"@vocab": "http://example.com/"},
959
- "verb": {"@value": "foo"}
960
- }),
961
- output: %([{
962
- "http://example.com/verb": [{"@value": "foo"}]
963
- }])
964
- },
965
- "datatype": {
966
- input: %({
967
- "@context": {"@vocab": "http://example.com/"},
968
- "http://example.org/verb": {"@value": "foo", "@type": "string"}
969
- }),
970
- output: %([{
971
- "http://example.org/verb": [{"@value": "foo", "@type": "http://example.com/string"}]
972
- }])
973
- },
974
- "expand-0028": {
975
- input: %({
976
- "@context": {
977
- "@vocab": "http://example.org/vocab#",
978
- "date": { "@type": "dateTime" }
979
- },
980
- "@id": "example1",
981
- "@type": "test",
982
- "date": "2011-01-25T00:00:00Z",
983
- "embed": {
984
- "@id": "example2",
985
- "expandedDate": { "@value": "2012-08-01T00:00:00Z", "@type": "dateTime" }
986
- }
987
- }),
988
- output: %([
989
- {
990
- "@id": "http://foo/bar/example1",
991
- "@type": ["http://example.org/vocab#test"],
992
- "http://example.org/vocab#date": [
993
- {
994
- "@value": "2011-01-25T00:00:00Z",
995
- "@type": "http://example.org/vocab#dateTime"
996
- }
997
- ],
998
- "http://example.org/vocab#embed": [
999
- {
1000
- "@id": "http://foo/bar/example2",
1001
- "http://example.org/vocab#expandedDate": [
1002
- {
1003
- "@value": "2012-08-01T00:00:00Z",
1004
- "@type": "http://example.org/vocab#dateTime"
1005
- }
1006
- ]
1007
- }
1008
- ]
1009
- }
1010
- ])
1011
- }
1012
- }.each do |title, params|
1013
- it(title) {run_expand params.merge(base: "http://foo/bar/")}
1014
- end
1015
- end
1016
-
1017
- context "unmapped properties" do
1018
- {
1019
- "unmapped key": {
1020
- input: %({"foo": "bar"}),
1021
- output: []
1022
- },
1023
- "unmapped @type as datatype": {
1024
- input: %({
1025
- "http://example.com/foo": {"@value": "bar", "@type": "baz"}
1026
- }),
1027
- output: %([{
1028
- "http://example.com/foo": [{"@value": "bar", "@type": "http://example/baz"}]
1029
- }])
1030
- },
1031
- "unknown keyword": {
1032
- input: %({"@foo": "bar"}),
1033
- output: []
1034
- },
1035
- "value": {
1036
- input: %({
1037
- "@context": {"ex": {"@id": "http://example.org/idrange", "@type": "@id"}},
1038
- "@id": "http://example.org/Subj",
1039
- "idrange": "unmapped"
1040
- }),
1041
- output: []
1042
- },
1043
- "context reset": {
1044
- input: %({
1045
- "@context": {"ex": "http://example.org/", "prop": "ex:prop"},
1046
- "@id": "http://example.org/id1",
1047
- "prop": "prop",
1048
- "ex:chain": {
1049
- "@context": null,
1050
- "@id": "http://example.org/id2",
1051
- "prop": "prop"
1052
- }
1053
- }),
1054
- output: %([{
1055
- "@id": "http://example.org/id1",
1056
- "http://example.org/prop": [{"@value": "prop"}],
1057
- "http://example.org/chain": [{"@id": "http://example.org/id2"}]
1058
- }])
1059
- }
1060
- }.each do |title, params|
1061
- it(title) {run_expand params.merge(base: "http://example/")}
1062
- end
1063
- end
1064
-
1065
- context "@container: @index" do
1066
- {
1067
- "string annotation": {
1068
- input: %({
1069
- "@context": {
1070
- "container": {
1071
- "@id": "http://example.com/container",
1072
- "@container": "@index"
1073
- }
1074
- },
1075
- "@id": "http://example.com/annotationsTest",
1076
- "container": {
1077
- "en": "The Queen",
1078
- "de": [ "Die Königin", "Ihre Majestät" ]
1079
- }
1080
- }),
1081
- output: %([{
1082
- "@id": "http://example.com/annotationsTest",
1083
- "http://example.com/container": [
1084
- {"@value": "Die Königin", "@index": "de"},
1085
- {"@value": "Ihre Majestät", "@index": "de"},
1086
- {"@value": "The Queen", "@index": "en"}
1087
- ]
1088
- }])
1089
- },
1090
- }.each do |title, params|
1091
- it(title) {run_expand params}
1092
- end
1093
-
1094
- context "@index: property" do
1095
- {
1096
- "error if @version is json-ld-1.0": {
1097
- input: %({
1098
- "@context": {
1099
- "@vocab": "http://example.com/",
1100
- "container": {"@container": "@index", "@index": "prop"}
1101
- },
1102
- "@id": "http://example.com/annotationsTest",
1103
- "container": {
1104
- "en": "The Queen",
1105
- "de": [ "Die Königin", "Ihre Majestät" ]
1106
- }
1107
- }),
1108
- exception: JSON::LD::JsonLdError::InvalidTermDefinition,
1109
- processingMode: 'json-ld-1.0'
1110
- },
1111
- "error if @container does not include @index": {
1112
- input: %({
1113
- "@context": {
1114
- "@version": 1.1,
1115
- "@vocab": "http://example.com/",
1116
- "container": {"@index": "prop"}
1117
- },
1118
- "@id": "http://example.com/annotationsTest",
1119
- "container": {
1120
- "en": "The Queen",
1121
- "de": [ "Die Königin", "Ihre Majestät" ]
1122
- }
1123
- }),
1124
- exception: JSON::LD::JsonLdError::InvalidTermDefinition
1125
- },
1126
- "error if @index is a keyword": {
1127
- input: %({
1128
- "@context": {
1129
- "@version": 1.1,
1130
- "@vocab": "http://example.com/",
1131
- "container": {
1132
- "@id": "http://example.com/container",
1133
- "@container": "@index",
1134
- "@index": "@index"
1135
- }
1136
- },
1137
- "@id": "http://example.com/annotationsTest",
1138
- "container": {
1139
- "en": "The Queen",
1140
- "de": [ "Die Königin", "Ihre Majestät" ]
1141
- }
1142
- }),
1143
- exception: JSON::LD::JsonLdError::InvalidTermDefinition
1144
- },
1145
- "error if @index is not a string": {
1146
- input: %({
1147
- "@context": {
1148
- "@version": 1.1,
1149
- "@vocab": "http://example.com/",
1150
- "container": {
1151
- "@id": "http://example.com/container",
1152
- "@container": "@index",
1153
- "@index": true
1154
- }
1155
- },
1156
- "@id": "http://example.com/annotationsTest",
1157
- "container": {
1158
- "en": "The Queen",
1159
- "de": [ "Die Königin", "Ihre Majestät" ]
1160
- }
1161
- }),
1162
- exception: JSON::LD::JsonLdError::InvalidTermDefinition
1163
- },
1164
- "error if attempting to add property to value object": {
1165
- input: %({
1166
- "@context": {
1167
- "@version": 1.1,
1168
- "@vocab": "http://example.com/",
1169
- "container": {
1170
- "@id": "http://example.com/container",
1171
- "@container": "@index",
1172
- "@index": "prop"
1173
- }
1174
- },
1175
- "@id": "http://example.com/annotationsTest",
1176
- "container": {
1177
- "en": "The Queen",
1178
- "de": [ "Die Königin", "Ihre Majestät" ]
1179
- }
1180
- }),
1181
- exception: JSON::LD::JsonLdError::InvalidValueObject
1182
- },
1183
- "property-valued index expands to property value, instead of @index (value)": {
1184
- input: %({
1185
- "@context": {
1186
- "@version": 1.1,
1187
- "@base": "http://example.com/",
1188
- "@vocab": "http://example.com/",
1189
- "author": {"@type": "@id", "@container": "@index", "@index": "prop"}
1190
- },
1191
- "@id": "article",
1192
- "author": {
1193
- "regular": "person/1",
1194
- "guest": ["person/2", "person/3"]
1195
- }
1196
- }),
1197
- output: %([{
1198
- "@id": "http://example.com/article",
1199
- "http://example.com/author": [
1200
- {"@id": "http://example.com/person/1", "http://example.com/prop": [{"@value": "regular"}]},
1201
- {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@value": "guest"}]},
1202
- {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@value": "guest"}]}
1203
- ]
1204
- }])
1205
- },
1206
- "property-valued index appends to property value, instead of @index (value)": {
1207
- input: %({
1208
- "@context": {
1209
- "@version": 1.1,
1210
- "@base": "http://example.com/",
1211
- "@vocab": "http://example.com/",
1212
- "author": {"@type": "@id", "@container": "@index", "@index": "prop"}
1213
- },
1214
- "@id": "article",
1215
- "author": {
1216
- "regular": {"@id": "person/1", "http://example.com/prop": "foo"},
1217
- "guest": [
1218
- {"@id": "person/2", "prop": "foo"},
1219
- {"@id": "person/3", "prop": "foo"}
1220
- ]
1221
- }
1222
- }),
1223
- output: %([{
1224
- "@id": "http://example.com/article",
1225
- "http://example.com/author": [
1226
- {"@id": "http://example.com/person/1", "http://example.com/prop": [{"@value": "regular"}, {"@value": "foo"}]},
1227
- {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@value": "guest"}, {"@value": "foo"}]},
1228
- {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@value": "guest"}, {"@value": "foo"}]}
1229
- ]
1230
- }])
1231
- },
1232
- "property-valued index expands to property value, instead of @index (node)": {
1233
- input: %({
1234
- "@context": {
1235
- "@version": 1.1,
1236
- "@base": "http://example.com/",
1237
- "@vocab": "http://example.com/",
1238
- "author": {"@type": "@id", "@container": "@index", "@index": "prop"},
1239
- "prop": {"@type": "@vocab"}
1240
- },
1241
- "@id": "http://example.com/article",
1242
- "author": {
1243
- "regular": "person/1",
1244
- "guest": ["person/2", "person/3"]
1245
- }
1246
- }),
1247
- output: %([{
1248
- "@id": "http://example.com/article",
1249
- "http://example.com/author": [
1250
- {"@id": "http://example.com/person/1", "http://example.com/prop": [{"@id": "http://example.com/regular"}]},
1251
- {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@id": "http://example.com/guest"}]},
1252
- {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@id": "http://example.com/guest"}]}
1253
- ]
1254
- }])
1255
- },
1256
- "property-valued index appends to property value, instead of @index (node)": {
1257
- input: %({
1258
- "@context": {
1259
- "@version": 1.1,
1260
- "@base": "http://example.com/",
1261
- "@vocab": "http://example.com/",
1262
- "author": {"@type": "@id", "@container": "@index", "@index": "prop"},
1263
- "prop": {"@type": "@vocab"}
1264
- },
1265
- "@id": "http://example.com/article",
1266
- "author": {
1267
- "regular": {"@id": "person/1", "prop": "foo"},
1268
- "guest": [
1269
- {"@id": "person/2", "prop": "foo"},
1270
- {"@id": "person/3", "prop": "foo"}
1271
- ]
1272
- }
1273
- }),
1274
- output: %([{
1275
- "@id": "http://example.com/article",
1276
- "http://example.com/author": [
1277
- {"@id": "http://example.com/person/1", "http://example.com/prop": [{"@id": "http://example.com/regular"}, {"@id": "http://example.com/foo"}]},
1278
- {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@id": "http://example.com/guest"}, {"@id": "http://example.com/foo"}]},
1279
- {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@id": "http://example.com/guest"}, {"@id": "http://example.com/foo"}]}
1280
- ]
1281
- }])
1282
- },
1283
- "property-valued index does not output property for @none": {
1284
- input: %({
1285
- "@context": {
1286
- "@version": 1.1,
1287
- "@base": "http://example.com/",
1288
- "@vocab": "http://example.com/",
1289
- "author": {"@type": "@id", "@container": "@index", "@index": "prop"},
1290
- "prop": {"@type": "@vocab"}
1291
- },
1292
- "@id": "http://example.com/article",
1293
- "author": {
1294
- "@none": {"@id": "person/1"},
1295
- "guest": [
1296
- {"@id": "person/2"},
1297
- {"@id": "person/3"}
1298
- ]
1299
- }
1300
- }),
1301
- output: %([{
1302
- "@id": "http://example.com/article",
1303
- "http://example.com/author": [
1304
- {"@id": "http://example.com/person/1"},
1305
- {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@id": "http://example.com/guest"}]},
1306
- {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@id": "http://example.com/guest"}]}
1307
- ]
1308
- }])
1309
- },
1310
- }.each do |title, params|
1311
- it(title) {run_expand(validate: true, **params)}
1312
- end
1313
- end
1314
- end
1315
-
1316
- context "@container: @list" do
1317
- {
1318
- "empty": {
1319
- input: %({"http://example.com/foo": {"@list": []}}),
1320
- output: %([{"http://example.com/foo": [{"@list": []}]}])
1321
- },
1322
- "coerced empty": {
1323
- input: %({
1324
- "@context": {"http://example.com/foo": {"@container": "@list"}},
1325
- "http://example.com/foo": []
1326
- }),
1327
- output: %([{"http://example.com/foo": [{"@list": []}]}])
1328
- },
1329
- "coerced single element": {
1330
- input: %({
1331
- "@context": {"http://example.com/foo": {"@container": "@list"}},
1332
- "http://example.com/foo": [ "foo" ]
1333
- }),
1334
- output: %([{"http://example.com/foo": [{"@list": [{"@value": "foo"}]}]}])
1335
- },
1336
- "coerced multiple elements": {
1337
- input: %({
1338
- "@context": {"http://example.com/foo": {"@container": "@list"}},
1339
- "http://example.com/foo": [ "foo", "bar" ]
1340
- }),
1341
- output: %([{
1342
- "http://example.com/foo": [{"@list": [ {"@value": "foo"}, {"@value": "bar"} ]}]
1343
- }])
1344
- },
1345
- "native values in list": {
1346
- input: %({
1347
- "http://example.com/foo": {"@list": [1, 2]}
1348
- }),
1349
- output: %([{
1350
- "http://example.com/foo": [{"@list": [{"@value": 1}, {"@value": 2}]}]
1351
- }])
1352
- },
1353
- "explicit list with coerced @id values": {
1354
- input: %({
1355
- "@context": {"http://example.com/foo": {"@type": "@id"}},
1356
- "http://example.com/foo": {"@list": ["http://foo", "http://bar"]}
1357
- }),
1358
- output: %([{
1359
- "http://example.com/foo": [{"@list": [{"@id": "http://foo"}, {"@id": "http://bar"}]}]
1360
- }])
1361
- },
1362
- "explicit list with coerced datatype values": {
1363
- input: %({
1364
- "@context": {"http://example.com/foo": {"@type": "http://www.w3.org/2001/XMLSchema#date"}},
1365
- "http://example.com/foo": {"@list": ["2012-04-12"]}
1366
- }),
1367
- output: %([{
1368
- "http://example.com/foo": [{"@list": [{"@value": "2012-04-12", "@type": "http://www.w3.org/2001/XMLSchema#date"}]}]
1369
- }])
1370
- },
1371
- "expand-0004": {
1372
- input: %({
1373
- "@context": {
1374
- "mylist1": {"@id": "http://example.com/mylist1", "@container": "@list"},
1375
- "mylist2": {"@id": "http://example.com/mylist2", "@container": "@list"},
1376
- "myset2": {"@id": "http://example.com/myset2", "@container": "@set"},
1377
- "myset3": {"@id": "http://example.com/myset3", "@container": "@set"}
1378
- },
1379
- "http://example.org/property": { "@list": "one item" }
1380
- }),
1381
- output: %([
1382
- {
1383
- "http://example.org/property": [
1384
- {
1385
- "@list": [
1386
- {
1387
- "@value": "one item"
1388
- }
1389
- ]
1390
- }
1391
- ]
1392
- }
1393
- ])
1394
- },
1395
- "@list containing @list": {
1396
- input: %({
1397
- "http://example.com/foo": {"@list": [{"@list": ["baz"]}]}
1398
- }),
1399
- output: %([{
1400
- "http://example.com/foo": [{"@list": [{"@list": [{"@value": "baz"}]}]}]
1401
- }])
1402
- },
1403
- "@list containing empty @list": {
1404
- input: %({
1405
- "http://example.com/foo": {"@list": [{"@list": []}]}
1406
- }),
1407
- output: %([{
1408
- "http://example.com/foo": [{"@list": [{"@list": []}]}]
1409
- }])
1410
- },
1411
- "@list containing @list (with coercion)": {
1412
- input: %({
1413
- "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
1414
- "foo": [{"@list": ["baz"]}]
1415
- }),
1416
- output: %([{
1417
- "http://example.com/foo": [{"@list": [{"@list": [{"@value": "baz"}]}]}]
1418
- }])
1419
- },
1420
- "@list containing empty @list (with coercion)": {
1421
- input: %({
1422
- "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
1423
- "foo": [{"@list": []}]
1424
- }),
1425
- output: %([{
1426
- "http://example.com/foo": [{"@list": [{"@list": []}]}]
1427
- }])
1428
- },
1429
- "coerced @list containing an array": {
1430
- input: %({
1431
- "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
1432
- "foo": [["baz"]]
1433
- }),
1434
- output: %([{
1435
- "http://example.com/foo": [{"@list": [{"@list": [{"@value": "baz"}]}]}]
1436
- }])
1437
- },
1438
- "coerced @list containing an empty array": {
1439
- input: %({
1440
- "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
1441
- "foo": [[]]
1442
- }),
1443
- output: %([{
1444
- "http://example.com/foo": [{"@list": [{"@list": []}]}]
1445
- }])
1446
- },
1447
- "coerced @list containing deep arrays": {
1448
- input: %({
1449
- "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
1450
- "foo": [[["baz"]]]
1451
- }),
1452
- output: %([{
1453
- "http://example.com/foo": [{"@list": [{"@list": [{"@list": [{"@value": "baz"}]}]}]}]
1454
- }])
1455
- },
1456
- "coerced @list containing deep empty arrays": {
1457
- input: %({
1458
- "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
1459
- "foo": [[[]]]
1460
- }),
1461
- output: %([{
1462
- "http://example.com/foo": [{"@list": [{"@list": [{"@list": []}]}]}]
1463
- }]),
1464
- },
1465
- "coerced @list containing multiple lists": {
1466
- input: %({
1467
- "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
1468
- "foo": [["a"], ["b"]]
1469
- }),
1470
- output: %([{
1471
- "http://example.com/foo": [{"@list": [
1472
- {"@list": [{"@value": "a"}]},
1473
- {"@list": [{"@value": "b"}]}
1474
- ]}]
1475
- }])
1476
- },
1477
- "coerced @list containing mixed list values": {
1478
- input: %({
1479
- "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
1480
- "foo": [["a"], "b"]
1481
- }),
1482
- output: %([{
1483
- "http://example.com/foo": [{"@list": [
1484
- {"@list": [{"@value": "a"}]},
1485
- {"@value": "b"}
1486
- ]}]
1487
- }])
1488
- },
1489
- }.each do |title, params|
1490
- it(title) {run_expand params}
1491
- end
1492
- end
1493
-
1494
- context "@container: @set" do
1495
- {
1496
- "empty": {
1497
- input: %({"http://example.com/foo": {"@set": []}}),
1498
- output: %([{"http://example.com/foo": []}])
1499
- },
1500
- "coerced empty": {
1501
- input: %({
1502
- "@context": {"http://example.com/foo": {"@container": "@set"}},
1503
- "http://example.com/foo": []
1504
- }),
1505
- output: %([{
1506
- "http://example.com/foo": []
1507
- }])
1508
- },
1509
- "coerced single element": {
1510
- input: %({
1511
- "@context": {"http://example.com/foo": {"@container": "@set"}},
1512
- "http://example.com/foo": [ "foo" ]
1513
- }),
1514
- output: %([{
1515
- "http://example.com/foo": [ {"@value": "foo"} ]
1516
- }])
1517
- },
1518
- "coerced multiple elements": {
1519
- input: %({
1520
- "@context": {"http://example.com/foo": {"@container": "@set"}},
1521
- "http://example.com/foo": [ "foo", "bar" ]
1522
- }),
1523
- output: %([{
1524
- "http://example.com/foo": [ {"@value": "foo"}, {"@value": "bar"} ]
1525
- }])
1526
- },
1527
- "array containing set": {
1528
- input: %({
1529
- "http://example.com/foo": [{"@set": []}]
1530
- }),
1531
- output: %([{
1532
- "http://example.com/foo": []
1533
- }])
1534
- },
1535
- "Free-floating values in sets": {
1536
- input: %({
1537
- "@context": {"property": "http://example.com/property"},
1538
- "@graph": [{
1539
- "@set": [
1540
- "free-floating strings in set objects are removed",
1541
- {"@id": "http://example.com/free-floating-node"},
1542
- {
1543
- "@id": "http://example.com/node",
1544
- "property": "nodes with properties are not removed"
1545
- }
1546
- ]
1547
- }]
1548
- }),
1549
- output: %([{
1550
- "@id": "http://example.com/node",
1551
- "http://example.com/property": [
1552
- {
1553
- "@value": "nodes with properties are not removed"
1554
- }
1555
- ]
1556
- }])
1557
- }
1558
- }.each do |title, params|
1559
- it(title) {run_expand params}
1560
- end
1561
- end
1562
-
1563
- context "@container: @language" do
1564
- {
1565
- "simple map": {
1566
- input: %({
1567
- "@context": {
1568
- "vocab": "http://example.com/vocab/",
1569
- "label": {
1570
- "@id": "vocab:label",
1571
- "@container": "@language"
1572
- }
1573
- },
1574
- "@id": "http://example.com/queen",
1575
- "label": {
1576
- "en": "The Queen",
1577
- "de": [ "Die Königin", "Ihre Majestät" ]
1578
- }
1579
- }),
1580
- output: %([
1581
- {
1582
- "@id": "http://example.com/queen",
1583
- "http://example.com/vocab/label": [
1584
- {"@value": "Die Königin", "@language": "de"},
1585
- {"@value": "Ihre Majestät", "@language": "de"},
1586
- {"@value": "The Queen", "@language": "en"}
1587
- ]
1588
- }
1589
- ])
1590
- },
1591
- "simple map with @none": {
1592
- input: %({
1593
- "@context": {
1594
- "vocab": "http://example.com/vocab/",
1595
- "label": {
1596
- "@id": "vocab:label",
1597
- "@container": "@language"
1598
- }
1599
- },
1600
- "@id": "http://example.com/queen",
1601
- "label": {
1602
- "en": "The Queen",
1603
- "de": [ "Die Königin", "Ihre Majestät" ],
1604
- "@none": "The Queen"
1605
- }
1606
- }),
1607
- output: %([
1608
- {
1609
- "@id": "http://example.com/queen",
1610
- "http://example.com/vocab/label": [
1611
- {"@value": "The Queen"},
1612
- {"@value": "Die Königin", "@language": "de"},
1613
- {"@value": "Ihre Majestät", "@language": "de"},
1614
- {"@value": "The Queen", "@language": "en"}
1615
- ]
1616
- }
1617
- ])
1618
- },
1619
- "simple map with alias of @none": {
1620
- input: %({
1621
- "@context": {
1622
- "vocab": "http://example.com/vocab/",
1623
- "label": {
1624
- "@id": "vocab:label",
1625
- "@container": "@language"
1626
- },
1627
- "none": "@none"
1628
- },
1629
- "@id": "http://example.com/queen",
1630
- "label": {
1631
- "en": "The Queen",
1632
- "de": [ "Die Königin", "Ihre Majestät" ],
1633
- "none": "The Queen"
1634
- }
1635
- }),
1636
- output: %([
1637
- {
1638
- "@id": "http://example.com/queen",
1639
- "http://example.com/vocab/label": [
1640
- {"@value": "Die Königin", "@language": "de"},
1641
- {"@value": "Ihre Majestät", "@language": "de"},
1642
- {"@value": "The Queen", "@language": "en"},
1643
- {"@value": "The Queen"}
1644
- ]
1645
- }
1646
- ])
1647
- },
1648
- "simple map with default direction": {
1649
- input: %({
1650
- "@context": {
1651
- "@direction": "ltr",
1652
- "vocab": "http://example.com/vocab/",
1653
- "label": {
1654
- "@id": "vocab:label",
1655
- "@container": "@language"
1656
- }
1657
- },
1658
- "@id": "http://example.com/queen",
1659
- "label": {
1660
- "en": "The Queen",
1661
- "de": [ "Die Königin", "Ihre Majestät" ]
1662
- }
1663
- }),
1664
- output: %([
1665
- {
1666
- "@id": "http://example.com/queen",
1667
- "http://example.com/vocab/label": [
1668
- {"@value": "Die Königin", "@language": "de", "@direction": "ltr"},
1669
- {"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"},
1670
- {"@value": "The Queen", "@language": "en", "@direction": "ltr"}
1671
- ]
1672
- }
1673
- ])
1674
- },
1675
- "simple map with term direction": {
1676
- input: %({
1677
- "@context": {
1678
- "vocab": "http://example.com/vocab/",
1679
- "label": {
1680
- "@id": "vocab:label",
1681
- "@direction": "ltr",
1682
- "@container": "@language"
1683
- }
1684
- },
1685
- "@id": "http://example.com/queen",
1686
- "label": {
1687
- "en": "The Queen",
1688
- "de": [ "Die Königin", "Ihre Majestät" ]
1689
- }
1690
- }),
1691
- output: %([
1692
- {
1693
- "@id": "http://example.com/queen",
1694
- "http://example.com/vocab/label": [
1695
- {"@value": "Die Königin", "@language": "de", "@direction": "ltr"},
1696
- {"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"},
1697
- {"@value": "The Queen", "@language": "en", "@direction": "ltr"}
1698
- ]
1699
- }
1700
- ])
1701
- },
1702
- "simple map with overriding term direction": {
1703
- input: %({
1704
- "@context": {
1705
- "vocab": "http://example.com/vocab/",
1706
- "@direction": "rtl",
1707
- "label": {
1708
- "@id": "vocab:label",
1709
- "@direction": "ltr",
1710
- "@container": "@language"
1711
- }
1712
- },
1713
- "@id": "http://example.com/queen",
1714
- "label": {
1715
- "en": "The Queen",
1716
- "de": [ "Die Königin", "Ihre Majestät" ]
1717
- }
1718
- }),
1719
- output: %([
1720
- {
1721
- "@id": "http://example.com/queen",
1722
- "http://example.com/vocab/label": [
1723
- {"@value": "Die Königin", "@language": "de", "@direction": "ltr"},
1724
- {"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"},
1725
- {"@value": "The Queen", "@language": "en", "@direction": "ltr"}
1726
- ]
1727
- }
1728
- ])
1729
- },
1730
- "simple map with overriding null direction": {
1731
- input: %({
1732
- "@context": {
1733
- "vocab": "http://example.com/vocab/",
1734
- "@direction": "rtl",
1735
- "label": {
1736
- "@id": "vocab:label",
1737
- "@direction": null,
1738
- "@container": "@language"
1739
- }
1740
- },
1741
- "@id": "http://example.com/queen",
1742
- "label": {
1743
- "en": "The Queen",
1744
- "de": [ "Die Königin", "Ihre Majestät" ]
1745
- }
1746
- }),
1747
- output: %([
1748
- {
1749
- "@id": "http://example.com/queen",
1750
- "http://example.com/vocab/label": [
1751
- {"@value": "Die Königin", "@language": "de"},
1752
- {"@value": "Ihre Majestät", "@language": "de"},
1753
- {"@value": "The Queen", "@language": "en"}
1754
- ]
1755
- }
1756
- ])
1757
- },
1758
- "expand-0035": {
1759
- input: %({
1760
- "@context": {
1761
- "@vocab": "http://example.com/vocab/",
1762
- "@language": "it",
1763
- "label": {
1764
- "@container": "@language"
1765
- }
1766
- },
1767
- "@id": "http://example.com/queen",
1768
- "label": {
1769
- "en": "The Queen",
1770
- "de": [ "Die Königin", "Ihre Majestät" ]
1771
- },
1772
- "http://example.com/vocab/label": [
1773
- "Il re",
1774
- { "@value": "The king", "@language": "en" }
1775
- ]
1776
- }),
1777
- output: %([
1778
- {
1779
- "@id": "http://example.com/queen",
1780
- "http://example.com/vocab/label": [
1781
- {"@value": "Il re", "@language": "it"},
1782
- {"@value": "The king", "@language": "en"},
1783
- {"@value": "Die Königin", "@language": "de"},
1784
- {"@value": "Ihre Majestät", "@language": "de"},
1785
- {"@value": "The Queen", "@language": "en"}
1786
- ]
1787
- }
1788
- ])
1789
- }
1790
- }.each do |title, params|
1791
- it(title) {run_expand params}
1792
- end
1793
- end
1794
-
1795
- context "@container: @id" do
1796
- {
1797
- "Adds @id to object not having an @id": {
1798
- input: %({
1799
- "@context": {
1800
- "@vocab": "http://example/",
1801
- "idmap": {"@container": "@id"}
1802
- },
1803
- "idmap": {
1804
- "http://example.org/foo": {"label": "Object with @id <foo>"},
1805
- "_:bar": {"label": "Object with @id _:bar"}
1806
- }
1807
- }),
1808
- output: %([{
1809
- "http://example/idmap": [
1810
- {"http://example/label": [{"@value": "Object with @id _:bar"}], "@id": "_:bar"},
1811
- {"http://example/label": [{"@value": "Object with @id <foo>"}], "@id": "http://example.org/foo"}
1812
- ]
1813
- }])
1814
- },
1815
- "Retains @id in object already having an @id": {
1816
- input: %({
1817
- "@context": {
1818
- "@vocab": "http://example/",
1819
- "idmap": {"@container": "@id"}
1820
- },
1821
- "idmap": {
1822
- "http://example.org/foo": {"@id": "http://example.org/bar", "label": "Object with @id <foo>"},
1823
- "_:bar": {"@id": "_:foo", "label": "Object with @id _:bar"}
1824
- }
1825
- }),
1826
- output: %([{
1827
- "http://example/idmap": [
1828
- {"@id": "_:foo", "http://example/label": [{"@value": "Object with @id _:bar"}]},
1829
- {"@id": "http://example.org/bar", "http://example/label": [{"@value": "Object with @id <foo>"}]}
1830
- ]
1831
- }])
1832
- },
1833
- "Adds expanded @id to object": {
1834
- input: %({
1835
- "@context": {
1836
- "@vocab": "http://example/",
1837
- "idmap": {"@container": "@id"}
1838
- },
1839
- "idmap": {
1840
- "foo": {"label": "Object with @id <foo>"}
1841
- }
1842
- }),
1843
- output: %([{
1844
- "http://example/idmap": [
1845
- {"http://example/label": [{"@value": "Object with @id <foo>"}], "@id": "http://example.org/foo"}
1846
- ]
1847
- }]),
1848
- base: "http://example.org/"
1849
- },
1850
- "Raises InvalidContainerMapping if processingMode is 1.0": {
1851
- input: %({
1852
- "@context": {
1853
- "@vocab": "http://example/",
1854
- "idmap": {"@container": "@id"}
1855
- },
1856
- "idmap": {
1857
- "http://example.org/foo": {"label": "Object with @id <foo>"},
1858
- "_:bar": {"label": "Object with @id _:bar"}
1859
- }
1860
- }),
1861
- processingMode: 'json-ld-1.0',
1862
- exception: JSON::LD::JsonLdError::InvalidContainerMapping
1863
- },
1864
- "Does not add @id if it is @none, or expands to @none": {
1865
- input: %({
1866
- "@context": {
1867
- "@vocab": "http://example/",
1868
- "idmap": {"@container": "@id"},
1869
- "none": "@none"
1870
- },
1871
- "idmap": {
1872
- "@none": {"label": "Object with no @id"},
1873
- "none": {"label": "Another object with no @id"}
1874
- }
1875
- }),
1876
- output: %([{
1877
- "http://example/idmap": [
1878
- {"http://example/label": [{"@value": "Object with no @id"}]},
1879
- {"http://example/label": [{"@value": "Another object with no @id"}]}
1880
- ]
1881
- }])
1882
- }
1883
- }.each do |title, params|
1884
- it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
1885
- end
1886
- end
1887
-
1888
- context "@container: @type" do
1889
- {
1890
- "Adds @type to object not having an @type": {
1891
- input: %({
1892
- "@context": {
1893
- "@vocab": "http://example/",
1894
- "typemap": {"@container": "@type"}
1895
- },
1896
- "typemap": {
1897
- "http://example.org/foo": {"label": "Object with @type <foo>"},
1898
- "_:bar": {"label": "Object with @type _:bar"}
1899
- }
1900
- }),
1901
- output: %([{
1902
- "http://example/typemap": [
1903
- {"http://example/label": [{"@value": "Object with @type _:bar"}], "@type": ["_:bar"]},
1904
- {"http://example/label": [{"@value": "Object with @type <foo>"}], "@type": ["http://example.org/foo"]}
1905
- ]
1906
- }])
1907
- },
1908
- "Prepends @type in object already having an @type": {
1909
- input: %({
1910
- "@context": {
1911
- "@vocab": "http://example/",
1912
- "typemap": {"@container": "@type"}
1913
- },
1914
- "typemap": {
1915
- "http://example.org/foo": {"@type": "http://example.org/bar", "label": "Object with @type <foo>"},
1916
- "_:bar": {"@type": "_:foo", "label": "Object with @type _:bar"}
1917
- }
1918
- }),
1919
- output: %([{
1920
- "http://example/typemap": [
1921
- {
1922
- "@type": ["_:bar", "_:foo"],
1923
- "http://example/label": [{"@value": "Object with @type _:bar"}]
1924
- },
1925
- {
1926
- "@type": ["http://example.org/foo", "http://example.org/bar"],
1927
- "http://example/label": [{"@value": "Object with @type <foo>"}]
1928
- }
1929
- ]
1930
- }])
1931
- },
1932
- "Adds vocabulary expanded @type to object": {
1933
- input: %({
1934
- "@context": {
1935
- "@vocab": "http://example/",
1936
- "typemap": {"@container": "@type"}
1937
- },
1938
- "typemap": {
1939
- "Foo": {"label": "Object with @type <foo>"}
1940
- }
1941
- }),
1942
- output: %([{
1943
- "http://example/typemap": [
1944
- {"http://example/label": [{"@value": "Object with @type <foo>"}], "@type": ["http://example/Foo"]}
1945
- ]
1946
- }])
1947
- },
1948
- "Adds document expanded @type to object": {
1949
- input: %({
1950
- "@context": {
1951
- "@vocab": "http://example/",
1952
- "typemap": {"@container": "@type"},
1953
- "label": "http://example/label"
1954
- },
1955
- "typemap": {
1956
- "Foo": {"label": "Object with @type <foo>"}
1957
- }
1958
- }),
1959
- output: %([{
1960
- "http://example/typemap": [
1961
- {"http://example/label": [{"@value": "Object with @type <foo>"}], "@type": ["http://example/Foo"]}
1962
- ]
1963
- }])
1964
- },
1965
- "Does not add @type if it is @none, or expands to @none": {
1966
- input: %({
1967
- "@context": {
1968
- "@vocab": "http://example/",
1969
- "typemap": {"@container": "@type"},
1970
- "none": "@none"
1971
- },
1972
- "typemap": {
1973
- "@none": {"label": "Object with no @type"},
1974
- "none": {"label": "Another object with no @type"}
1975
- }
1976
- }),
1977
- output: %([{
1978
- "http://example/typemap": [
1979
- {"http://example/label": [{"@value": "Object with no @type"}]},
1980
- {"http://example/label": [{"@value": "Another object with no @type"}]}
1981
- ]
1982
- }])
1983
- },
1984
- "Raises InvalidContainerMapping if processingMode is 1.0": {
1985
- input: %({
1986
- "@context": {
1987
- "@vocab": "http://example/",
1988
- "typemap": {"@container": "@type"}
1989
- },
1990
- "typemap": {
1991
- "http://example.org/foo": {"label": "Object with @type <foo>"},
1992
- "_:bar": {"label": "Object with @type _:bar"}
1993
- }
1994
- }),
1995
- processingMode: 'json-ld-1.0',
1996
- exception: JSON::LD::JsonLdError::InvalidContainerMapping
1997
- },
1998
- }.each do |title, params|
1999
- it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
2000
- end
2001
- end
2002
-
2003
- context "@container: @graph" do
2004
- {
2005
- "Creates a graph object given a value": {
2006
- input: %({
2007
- "@context": {
2008
- "@vocab": "http://example.org/",
2009
- "input": {"@container": "@graph"}
2010
- },
2011
- "input": {
2012
- "value": "x"
2013
- }
2014
- }),
2015
- output: %([{
2016
- "http://example.org/input": [{
2017
- "@graph": [{
2018
- "http://example.org/value": [{"@value": "x"}]
2019
- }]
2020
- }]
2021
- }])
2022
- },
2023
- "Creates a graph object within an array given a value": {
2024
- input: %({
2025
- "@context": {
2026
- "@vocab": "http://example.org/",
2027
- "input": {"@container": ["@graph", "@set"]}
2028
- },
2029
- "input": {
2030
- "value": "x"
2031
- }
2032
- }),
2033
- output: %([{
2034
- "http://example.org/input": [{
2035
- "@graph": [{
2036
- "http://example.org/value": [{"@value": "x"}]
2037
- }]
2038
- }]
2039
- }])
2040
- },
2041
- "Creates an graph object if value is a graph": {
2042
- input: %({
2043
- "@context": {
2044
- "@vocab": "http://example.org/",
2045
- "input": {"@container": "@graph"}
2046
- },
2047
- "input": {
2048
- "@graph": {
2049
- "value": "x"
2050
- }
2051
- }
2052
- }),
2053
- output: %([{
2054
- "http://example.org/input": [{
2055
- "@graph": [{
2056
- "@graph": [{
2057
- "http://example.org/value": [{"@value": "x"}]
2058
- }]
2059
- }]
2060
- }]
2061
- }])
2062
- },
2063
- }.each do |title, params|
2064
- it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
2065
- end
2066
-
2067
- context "+ @index" do
2068
- {
2069
- "Creates a graph object given an indexed value": {
2070
- input: %({
2071
- "@context": {
2072
- "@vocab": "http://example.org/",
2073
- "input": {"@container": ["@graph", "@index"]}
2074
- },
2075
- "input": {
2076
- "g1": {"value": "x"}
2077
- }
2078
- }),
2079
- output: %([{
2080
- "http://example.org/input": [{
2081
- "@index": "g1",
2082
- "@graph": [{
2083
- "http://example.org/value": [{"@value": "x"}]
2084
- }]
2085
- }]
2086
- }])
2087
- },
2088
- "Creates a graph object given an indexed value with index @none": {
2089
- input: %({
2090
- "@context": {
2091
- "@vocab": "http://example.org/",
2092
- "input": {"@container": ["@graph", "@index"]}
2093
- },
2094
- "input": {
2095
- "@none": {"value": "x"}
2096
- }
2097
- }),
2098
- output: %([{
2099
- "http://example.org/input": [{
2100
- "@graph": [{
2101
- "http://example.org/value": [{"@value": "x"}]
2102
- }]
2103
- }]
2104
- }])
2105
- },
2106
- "Creates a graph object given an indexed value with index alias of @none": {
2107
- input: %({
2108
- "@context": {
2109
- "@vocab": "http://example.org/",
2110
- "input": {"@container": ["@graph", "@index"]},
2111
- "none": "@none"
2112
- },
2113
- "input": {
2114
- "none": {"value": "x"}
2115
- }
2116
- }),
2117
- output: %([{
2118
- "http://example.org/input": [{
2119
- "@graph": [{
2120
- "http://example.org/value": [{"@value": "x"}]
2121
- }]
2122
- }]
2123
- }])
2124
- },
2125
- "Creates a graph object given an indexed value with @set": {
2126
- input: %({
2127
- "@context": {
2128
- "@vocab": "http://example.org/",
2129
- "input": {"@container": ["@graph", "@index", "@set"]}
2130
- },
2131
- "input": {
2132
- "g1": {"value": "x"}
2133
- }
2134
- }),
2135
- output: %([{
2136
- "http://example.org/input": [{
2137
- "@index": "g1",
2138
- "@graph": [{
2139
- "http://example.org/value": [{"@value": "x"}]
2140
- }]
2141
- }]
2142
- }])
2143
- },
2144
- "Does not create a new graph object if indexed value is already a graph object": {
2145
- input: %({
2146
- "@context": {
2147
- "@vocab": "http://example.org/",
2148
- "input": {"@container": ["@graph", "@index"]}
2149
- },
2150
- "input": {
2151
- "g1": {
2152
- "@graph": {
2153
- "value": "x"
2154
- }
2155
- }
2156
- }
2157
- }),
2158
- output: %([{
2159
- "http://example.org/input": [{
2160
- "@index": "g1",
2161
- "@graph": [{
2162
- "http://example.org/value": [{"@value": "x"}]
2163
- }]
2164
- }]
2165
- }])
2166
- },
2167
- }.each do |title, params|
2168
- it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
2169
- end
2170
-
2171
- context "@index: property" do
2172
- {
2173
- "it expands to property value, instead of @index": {
2174
- input: %({
2175
- "@context": {
2176
- "@version": 1.1,
2177
- "@vocab": "http://example.org/",
2178
- "input": {"@container": ["@graph", "@index"], "@index": "prop"}
2179
- },
2180
- "input": {
2181
- "g1": {"value": "x"}
2182
- }
2183
- }),
2184
- output: %([{
2185
- "http://example.org/input": [{
2186
- "http://example.org/prop": [{"@value": "g1"}],
2187
- "@graph": [{
2188
- "http://example.org/value": [{"@value": "x"}]
2189
- }]
2190
- }]
2191
- }])
2192
- },
2193
- }.each do |title, params|
2194
- it(title) {run_expand(validate: true, **params)}
2195
- end
2196
- end
2197
- end
2198
-
2199
- context "+ @id" do
2200
- {
2201
- "Creates a graph object given an indexed value": {
2202
- input: %({
2203
- "@context": {
2204
- "@vocab": "http://example.org/",
2205
- "input": {"@container": ["@graph", "@id"]}
2206
- },
2207
- "input": {
2208
- "http://example.com/g1": {"value": "x"}
2209
- }
2210
- }),
2211
- output: %([{
2212
- "http://example.org/input": [{
2213
- "@id": "http://example.com/g1",
2214
- "@graph": [{
2215
- "http://example.org/value": [{"@value": "x"}]
2216
- }]
2217
- }]
2218
- }])
2219
- },
2220
- "Creates a graph object given an indexed value of @none": {
2221
- input: %({
2222
- "@context": {
2223
- "@vocab": "http://example.org/",
2224
- "input": {"@container": ["@graph", "@id"]}
2225
- },
2226
- "input": {
2227
- "@none": {"value": "x"}
2228
- }
2229
- }),
2230
- output: %([{
2231
- "http://example.org/input": [{
2232
- "@graph": [{
2233
- "http://example.org/value": [{"@value": "x"}]
2234
- }]
2235
- }]
2236
- }])
2237
- },
2238
- "Creates a graph object given an indexed value of alias of @none": {
2239
- input: %({
2240
- "@context": {
2241
- "@vocab": "http://example.org/",
2242
- "input": {"@container": ["@graph", "@id"]},
2243
- "none": "@none"
2244
- },
2245
- "input": {
2246
- "none": {"value": "x"}
2247
- }
2248
- }),
2249
- output: %([{
2250
- "http://example.org/input": [{
2251
- "@graph": [{
2252
- "http://example.org/value": [{"@value": "x"}]
2253
- }]
2254
- }]
2255
- }])
2256
- },
2257
- "Creates a graph object given an indexed value with @set": {
2258
- input: %({
2259
- "@context": {
2260
- "@vocab": "http://example.org/",
2261
- "input": {"@container": ["@graph", "@id", "@set"]}
2262
- },
2263
- "input": {
2264
- "http://example.com/g1": {"value": "x"}
2265
- }
2266
- }),
2267
- output: %([{
2268
- "http://example.org/input": [{
2269
- "@id": "http://example.com/g1",
2270
- "@graph": [{
2271
- "http://example.org/value": [{"@value": "x"}]
2272
- }]
2273
- }]
2274
- }])
2275
- },
2276
- "Does not create a new graph object if indexed value is already a graph object": {
2277
- input: %({
2278
- "@context": {
2279
- "@vocab": "http://example.org/",
2280
- "input": {"@container": ["@graph", "@id"]}
2281
- },
2282
- "input": {
2283
- "http://example.com/g1": {
2284
- "@graph": {
2285
- "value": "x"
2286
- }
2287
- }
2288
- }
2289
- }),
2290
- output: %([{
2291
- "http://example.org/input": [{
2292
- "@id": "http://example.com/g1",
2293
- "@graph": [{
2294
- "http://example.org/value": [{"@value": "x"}]
2295
- }]
2296
- }]
2297
- }])
2298
- },
2299
- }.each do |title, params|
2300
- it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
2301
- end
2302
- end
2303
- end
2304
-
2305
- context "@included" do
2306
- {
2307
- "Basic Included array": {
2308
- input: %({
2309
- "@context": {
2310
- "@version": 1.1,
2311
- "@vocab": "http://example.org/"
2312
- },
2313
- "prop": "value",
2314
- "@included": [{
2315
- "prop": "value2"
2316
- }]
2317
- }),
2318
- output: %([{
2319
- "http://example.org/prop": [{"@value": "value"}],
2320
- "@included": [{
2321
- "http://example.org/prop": [{"@value": "value2"}]
2322
- }]
2323
- }])
2324
- },
2325
- "Basic Included object": {
2326
- input: %({
2327
- "@context": {
2328
- "@version": 1.1,
2329
- "@vocab": "http://example.org/"
2330
- },
2331
- "prop": "value",
2332
- "@included": {
2333
- "prop": "value2"
2334
- }
2335
- }),
2336
- output: %([{
2337
- "http://example.org/prop": [{"@value": "value"}],
2338
- "@included": [{
2339
- "http://example.org/prop": [{"@value": "value2"}]
2340
- }]
2341
- }])
2342
- },
2343
- "Multiple properties mapping to @included are folded together": {
2344
- input: %({
2345
- "@context": {
2346
- "@version": 1.1,
2347
- "@vocab": "http://example.org/",
2348
- "included1": "@included",
2349
- "included2": "@included"
2350
- },
2351
- "included1": {"prop": "value1"},
2352
- "included2": {"prop": "value2"}
2353
- }),
2354
- output: %([{
2355
- "@included": [
2356
- {"http://example.org/prop": [{"@value": "value1"}]},
2357
- {"http://example.org/prop": [{"@value": "value2"}]}
2358
- ]
2359
- }])
2360
- },
2361
- "Included containing @included": {
2362
- input: %({
2363
- "@context": {
2364
- "@version": 1.1,
2365
- "@vocab": "http://example.org/"
2366
- },
2367
- "prop": "value",
2368
- "@included": {
2369
- "prop": "value2",
2370
- "@included": {
2371
- "prop": "value3"
2372
- }
2373
- }
2374
- }),
2375
- output: %([{
2376
- "http://example.org/prop": [{"@value": "value"}],
2377
- "@included": [{
2378
- "http://example.org/prop": [{"@value": "value2"}],
2379
- "@included": [{
2380
- "http://example.org/prop": [{"@value": "value3"}]
2381
- }]
2382
- }]
2383
- }])
2384
- },
2385
- "Property value with @included": {
2386
- input: %({
2387
- "@context": {
2388
- "@version": 1.1,
2389
- "@vocab": "http://example.org/"
2390
- },
2391
- "prop": {
2392
- "@type": "Foo",
2393
- "@included": {
2394
- "@type": "Bar"
2395
- }
2396
- }
2397
- }),
2398
- output: %([{
2399
- "http://example.org/prop": [{
2400
- "@type": ["http://example.org/Foo"],
2401
- "@included": [{
2402
- "@type": ["http://example.org/Bar"]
2403
- }]
2404
- }]
2405
- }])
2406
- },
2407
- "json.api example": {
2408
- input: %({
2409
- "@context": {
2410
- "@version": 1.1,
2411
- "@vocab": "http://example.org/vocab#",
2412
- "@base": "http://example.org/base/",
2413
- "id": "@id",
2414
- "type": "@type",
2415
- "data": "@nest",
2416
- "attributes": "@nest",
2417
- "links": "@nest",
2418
- "relationships": "@nest",
2419
- "included": "@included",
2420
- "self": {"@type": "@id"},
2421
- "related": {"@type": "@id"},
2422
- "comments": {
2423
- "@context": {
2424
- "data": null
2425
- }
2426
- }
2427
- },
2428
- "data": [{
2429
- "type": "articles",
2430
- "id": "1",
2431
- "attributes": {
2432
- "title": "JSON:API paints my bikeshed!"
2433
- },
2434
- "links": {
2435
- "self": "http://example.com/articles/1"
2436
- },
2437
- "relationships": {
2438
- "author": {
2439
- "links": {
2440
- "self": "http://example.com/articles/1/relationships/author",
2441
- "related": "http://example.com/articles/1/author"
2442
- },
2443
- "data": { "type": "people", "id": "9" }
2444
- },
2445
- "comments": {
2446
- "links": {
2447
- "self": "http://example.com/articles/1/relationships/comments",
2448
- "related": "http://example.com/articles/1/comments"
2449
- },
2450
- "data": [
2451
- { "type": "comments", "id": "5" },
2452
- { "type": "comments", "id": "12" }
2453
- ]
2454
- }
2455
- }
2456
- }],
2457
- "included": [{
2458
- "type": "people",
2459
- "id": "9",
2460
- "attributes": {
2461
- "first-name": "Dan",
2462
- "last-name": "Gebhardt",
2463
- "twitter": "dgeb"
2464
- },
2465
- "links": {
2466
- "self": "http://example.com/people/9"
2467
- }
2468
- }, {
2469
- "type": "comments",
2470
- "id": "5",
2471
- "attributes": {
2472
- "body": "First!"
2473
- },
2474
- "relationships": {
2475
- "author": {
2476
- "data": { "type": "people", "id": "2" }
2477
- }
2478
- },
2479
- "links": {
2480
- "self": "http://example.com/comments/5"
2481
- }
2482
- }, {
2483
- "type": "comments",
2484
- "id": "12",
2485
- "attributes": {
2486
- "body": "I like XML better"
2487
- },
2488
- "relationships": {
2489
- "author": {
2490
- "data": { "type": "people", "id": "9" }
2491
- }
2492
- },
2493
- "links": {
2494
- "self": "http://example.com/comments/12"
2495
- }
2496
- }]
2497
- }),
2498
- output: %([{
2499
- "@id": "http://example.org/base/1",
2500
- "@type": ["http://example.org/vocab#articles"],
2501
- "http://example.org/vocab#title": [{"@value": "JSON:API paints my bikeshed!"}],
2502
- "http://example.org/vocab#self": [{"@id": "http://example.com/articles/1"}],
2503
- "http://example.org/vocab#author": [{
2504
- "@id": "http://example.org/base/9",
2505
- "@type": ["http://example.org/vocab#people"],
2506
- "http://example.org/vocab#self": [{"@id": "http://example.com/articles/1/relationships/author"}],
2507
- "http://example.org/vocab#related": [{"@id": "http://example.com/articles/1/author"}]
2508
- }],
2509
- "http://example.org/vocab#comments": [{
2510
- "http://example.org/vocab#self": [{"@id": "http://example.com/articles/1/relationships/comments"}],
2511
- "http://example.org/vocab#related": [{"@id": "http://example.com/articles/1/comments"}]
2512
- }],
2513
- "@included": [{
2514
- "@id": "http://example.org/base/9",
2515
- "@type": ["http://example.org/vocab#people"],
2516
- "http://example.org/vocab#first-name": [{"@value": "Dan"}],
2517
- "http://example.org/vocab#last-name": [{"@value": "Gebhardt"}],
2518
- "http://example.org/vocab#twitter": [{"@value": "dgeb"}],
2519
- "http://example.org/vocab#self": [{"@id": "http://example.com/people/9"}]
2520
- }, {
2521
- "@id": "http://example.org/base/5",
2522
- "@type": ["http://example.org/vocab#comments"],
2523
- "http://example.org/vocab#body": [{"@value": "First!"}],
2524
- "http://example.org/vocab#author": [{
2525
- "@id": "http://example.org/base/2",
2526
- "@type": ["http://example.org/vocab#people"]
2527
- }],
2528
- "http://example.org/vocab#self": [{"@id": "http://example.com/comments/5"}]
2529
- }, {
2530
- "@id": "http://example.org/base/12",
2531
- "@type": ["http://example.org/vocab#comments"],
2532
- "http://example.org/vocab#body": [{"@value": "I like XML better"}],
2533
- "http://example.org/vocab#author": [{
2534
- "@id": "http://example.org/base/9",
2535
- "@type": ["http://example.org/vocab#people"]
2536
- }],
2537
- "http://example.org/vocab#self": [{"@id": "http://example.com/comments/12"}]
2538
- }]
2539
- }])
2540
- },
2541
- "Error if @included value is a string": {
2542
- input: %({
2543
- "@context": {
2544
- "@version": 1.1,
2545
- "@vocab": "http://example.org/"
2546
- },
2547
- "@included": "string"
2548
- }),
2549
- exception: JSON::LD::JsonLdError::InvalidIncludedValue
2550
- },
2551
- "Error if @included value is a value object": {
2552
- input: %({
2553
- "@context": {
2554
- "@version": 1.1,
2555
- "@vocab": "http://example.org/"
2556
- },
2557
- "@included": {"@value": "value"}
2558
- }),
2559
- exception: JSON::LD::JsonLdError::InvalidIncludedValue
2560
- },
2561
- "Error if @included value is a list object": {
2562
- input: %({
2563
- "@context": {
2564
- "@version": 1.1,
2565
- "@vocab": "http://example.org/"
2566
- },
2567
- "@included": {"@list": ["value"]}
2568
- }),
2569
- exception: JSON::LD::JsonLdError::InvalidIncludedValue
2570
- },
2571
- }.each do |title, params|
2572
- it(title) {run_expand(params)}
2573
- end
2574
- end
2575
-
2576
- context "@nest" do
2577
- {
2578
- "Expands input using @nest": {
2579
- input: %({
2580
- "@context": {"@vocab": "http://example.org/"},
2581
- "p1": "v1",
2582
- "@nest": {
2583
- "p2": "v2"
2584
- }
2585
- }),
2586
- output: %([{
2587
- "http://example.org/p1": [{"@value": "v1"}],
2588
- "http://example.org/p2": [{"@value": "v2"}]
2589
- }])
2590
- },
2591
- "Expands input using aliased @nest": {
2592
- input: %({
2593
- "@context": {
2594
- "@vocab": "http://example.org/",
2595
- "nest": "@nest"
2596
- },
2597
- "p1": "v1",
2598
- "nest": {
2599
- "p2": "v2"
2600
- }
2601
- }),
2602
- output: %([{
2603
- "http://example.org/p1": [{"@value": "v1"}],
2604
- "http://example.org/p2": [{"@value": "v2"}]
2605
- }])
2606
- },
2607
- "Appends nested values when property at base and nested": {
2608
- input: %({
2609
- "@context": {
2610
- "@vocab": "http://example.org/",
2611
- "nest": "@nest"
2612
- },
2613
- "p1": "v1",
2614
- "nest": {
2615
- "p2": "v3"
2616
- },
2617
- "p2": "v2"
2618
- }),
2619
- output: %([{
2620
- "http://example.org/p1": [{"@value": "v1"}],
2621
- "http://example.org/p2": [
2622
- {"@value": "v2"},
2623
- {"@value": "v3"}
2624
- ]
2625
- }])
2626
- },
2627
- "Appends nested values from all @nest aliases in term order": {
2628
- input: %({
2629
- "@context": {
2630
- "@vocab": "http://example.org/",
2631
- "nest1": "@nest",
2632
- "nest2": "@nest"
2633
- },
2634
- "p1": "v1",
2635
- "nest2": {
2636
- "p2": "v4"
2637
- },
2638
- "p2": "v2",
2639
- "nest1": {
2640
- "p2": "v3"
2641
- }
2642
- }),
2643
- output: %([{
2644
- "http://example.org/p1": [{"@value": "v1"}],
2645
- "http://example.org/p2": [
2646
- {"@value": "v2"},
2647
- {"@value": "v3"},
2648
- {"@value": "v4"}
2649
- ]
2650
- }])
2651
- },
2652
- "Nested nested containers": {
2653
- input: %({
2654
- "@context": {
2655
- "@vocab": "http://example.org/"
2656
- },
2657
- "p1": "v1",
2658
- "@nest": {
2659
- "p2": "v3",
2660
- "@nest": {
2661
- "p2": "v4"
2662
- }
2663
- },
2664
- "p2": "v2"
2665
- }),
2666
- output: %([{
2667
- "http://example.org/p1": [{"@value": "v1"}],
2668
- "http://example.org/p2": [
2669
- {"@value": "v2"},
2670
- {"@value": "v3"},
2671
- {"@value": "v4"}
2672
- ]
2673
- }])
2674
- },
2675
- "Arrays of nested values": {
2676
- input: %({
2677
- "@context": {
2678
- "@vocab": "http://example.org/",
2679
- "nest": "@nest"
2680
- },
2681
- "p1": "v1",
2682
- "nest": {
2683
- "p2": ["v4", "v5"]
2684
- },
2685
- "p2": ["v2", "v3"]
2686
- }),
2687
- output: %([{
2688
- "http://example.org/p1": [{"@value": "v1"}],
2689
- "http://example.org/p2": [
2690
- {"@value": "v2"},
2691
- {"@value": "v3"},
2692
- {"@value": "v4"},
2693
- {"@value": "v5"}
2694
- ]
2695
- }])
2696
- },
2697
- "A nest of arrays": {
2698
- input: %({
2699
- "@context": {
2700
- "@vocab": "http://example.org/",
2701
- "nest": "@nest"
2702
- },
2703
- "p1": "v1",
2704
- "nest": [{
2705
- "p2": "v4"
2706
- }, {
2707
- "p2": "v5"
2708
- }],
2709
- "p2": ["v2", "v3"]
2710
- }),
2711
- output: %([{
2712
- "http://example.org/p1": [{"@value": "v1"}],
2713
- "http://example.org/p2": [
2714
- {"@value": "v2"},
2715
- {"@value": "v3"},
2716
- {"@value": "v4"},
2717
- {"@value": "v5"}
2718
- ]
2719
- }])
2720
- },
2721
- "@nest MUST NOT have a string value": {
2722
- input: %({
2723
- "@context": {"@vocab": "http://example.org/"},
2724
- "@nest": "This should generate an error"
2725
- }),
2726
- exception: JSON::LD::JsonLdError::InvalidNestValue
2727
- },
2728
- "@nest MUST NOT have a boolen value": {
2729
- input: %({
2730
- "@context": {"@vocab": "http://example.org/"},
2731
- "@nest": true
2732
- }),
2733
- exception: JSON::LD::JsonLdError::InvalidNestValue
2734
- },
2735
- "@nest MUST NOT have a numeric value": {
2736
- input: %({
2737
- "@context": {"@vocab": "http://example.org/"},
2738
- "@nest": 1
2739
- }),
2740
- exception: JSON::LD::JsonLdError::InvalidNestValue
2741
- },
2742
- "@nest MUST NOT have a value object value": {
2743
- input: %({
2744
- "@context": {"@vocab": "http://example.org/"},
2745
- "@nest": {"@value": "This should generate an error"}
2746
- }),
2747
- exception: JSON::LD::JsonLdError::InvalidNestValue
2748
- },
2749
- "@nest in term definition MUST NOT be a non-@nest keyword": {
2750
- input: %({
2751
- "@context": {
2752
- "@vocab": "http://example.org/",
2753
- "nest": {"@nest": "@id"}
2754
- },
2755
- "nest": "This should generate an error"
2756
- }),
2757
- exception: JSON::LD::JsonLdError::InvalidNestValue
2758
- },
2759
- "@nest in term definition MUST NOT have a boolen value": {
2760
- input: %({
2761
- "@context": {
2762
- "@vocab": "http://example.org/",
2763
- "nest": {"@nest": true}
2764
- },
2765
- "nest": "This should generate an error"
2766
- }),
2767
- exception: JSON::LD::JsonLdError::InvalidNestValue
2768
- },
2769
- "@nest in term definition MUST NOT have a numeric value": {
2770
- input: %({
2771
- "@context": {
2772
- "@vocab": "http://example.org/",
2773
- "nest": {"@nest": 123}
2774
- },
2775
- "nest": "This should generate an error"
2776
- }),
2777
- exception: JSON::LD::JsonLdError::InvalidNestValue
2778
- },
2779
- "Nested @container: @list": {
2780
- input: %({
2781
- "@context": {
2782
- "@vocab": "http://example.org/",
2783
- "list": {"@container": "@list", "@nest": "nestedlist"},
2784
- "nestedlist": "@nest"
2785
- },
2786
- "nestedlist": {
2787
- "list": ["a", "b"]
2788
- }
2789
- }),
2790
- output: %([{
2791
- "http://example.org/list": [{"@list": [
2792
- {"@value": "a"},
2793
- {"@value": "b"}
2794
- ]}]
2795
- }])
2796
- },
2797
- "Nested @container: @index": {
2798
- input: %({
2799
- "@context": {
2800
- "@vocab": "http://example.org/",
2801
- "index": {"@container": "@index", "@nest": "nestedindex"},
2802
- "nestedindex": "@nest"
2803
- },
2804
- "nestedindex": {
2805
- "index": {
2806
- "A": "a",
2807
- "B": "b"
2808
- }
2809
- }
2810
- }),
2811
- output: %([{
2812
- "http://example.org/index": [
2813
- {"@value": "a", "@index": "A"},
2814
- {"@value": "b", "@index": "B"}
2815
- ]
2816
- }])
2817
- },
2818
- "Nested @container: @language": {
2819
- input: %({
2820
- "@context": {
2821
- "@vocab": "http://example.org/",
2822
- "container": {"@container": "@language", "@nest": "nestedlanguage"},
2823
- "nestedlanguage": "@nest"
2824
- },
2825
- "nestedlanguage": {
2826
- "container": {
2827
- "en": "The Queen",
2828
- "de": "Die Königin"
2829
- }
2830
- }
2831
- }),
2832
- output: %([{
2833
- "http://example.org/container": [
2834
- {"@value": "Die Königin", "@language": "de"},
2835
- {"@value": "The Queen", "@language": "en"}
2836
- ]
2837
- }])
2838
- },
2839
- "Nested @container: @type": {
2840
- input: %({
2841
- "@context": {
2842
- "@vocab": "http://example/",
2843
- "typemap": {"@container": "@type", "@nest": "nestedtypemap"},
2844
- "nestedtypemap": "@nest"
2845
- },
2846
- "nestedtypemap": {
2847
- "typemap": {
2848
- "http://example.org/foo": {"label": "Object with @type <foo>"},
2849
- "_:bar": {"label": "Object with @type _:bar"}
2850
- }
2851
- }
2852
- }),
2853
- output: %([{
2854
- "http://example/typemap": [
2855
- {"http://example/label": [{"@value": "Object with @type _:bar"}], "@type": ["_:bar"]},
2856
- {"http://example/label": [{"@value": "Object with @type <foo>"}], "@type": ["http://example.org/foo"]}
2857
- ]
2858
- }])
2859
- },
2860
- "Nested @container: @id": {
2861
- input: %({
2862
- "@context": {
2863
- "@vocab": "http://example/",
2864
- "idmap": {"@container": "@id", "@nest": "nestedidmap"},
2865
- "nestedidmap": "@nest"
2866
- },
2867
- "nestedidmap": {
2868
- "idmap": {
2869
- "http://example.org/foo": {"label": "Object with @id <foo>"},
2870
- "_:bar": {"label": "Object with @id _:bar"}
2871
- }
2872
- }
2873
- }),
2874
- output: %([{
2875
- "http://example/idmap": [
2876
- {"http://example/label": [{"@value": "Object with @id _:bar"}], "@id": "_:bar"},
2877
- {"http://example/label": [{"@value": "Object with @id <foo>"}], "@id": "http://example.org/foo"}
2878
- ]
2879
- }])
2880
- },
2881
- "Nest term an invalid keyword": {
2882
- input: %({
2883
- "@context": {
2884
- "term": {"@id": "http://example/term", "@nest": "@id"}
2885
- }
2886
- }),
2887
- exception: JSON::LD::JsonLdError::InvalidNestValue
2888
- },
2889
- "Nest in @reverse": {
2890
- input: %({
2891
- "@context": {
2892
- "term": {"@reverse": "http://example/term", "@nest": "@nest"}
2893
- }
2894
- }),
2895
- exception: JSON::LD::JsonLdError::InvalidReverseProperty
2896
- },
2897
- "Raises InvalidTermDefinition if processingMode is 1.0": {
2898
- input: %({
2899
- "@context": {
2900
- "@vocab": "http://example.org/",
2901
- "list": {"@container": "@list", "@nest": "nestedlist"},
2902
- "nestedlist": "@nest"
2903
- },
2904
- "nestedlist": {
2905
- "list": ["a", "b"]
2906
- }
2907
- }),
2908
- processingMode: 'json-ld-1.0',
2909
- validate: true,
2910
- exception: JSON::LD::JsonLdError::InvalidTermDefinition
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
- }
2932
- }.each do |title, params|
2933
- it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
2934
- end
2935
- end
2936
-
2937
- context "scoped context" do
2938
- {
2939
- "adding new term": {
2940
- input: %({
2941
- "@context": {
2942
- "@vocab": "http://example/",
2943
- "foo": {"@context": {"bar": "http://example.org/bar"}}
2944
- },
2945
- "foo": {
2946
- "bar": "baz"
2947
- }
2948
- }),
2949
- output: %([
2950
- {
2951
- "http://example/foo": [{"http://example.org/bar": [{"@value": "baz"}]}]
2952
- }
2953
- ])
2954
- },
2955
- "overriding a term": {
2956
- input: %({
2957
- "@context": {
2958
- "@vocab": "http://example/",
2959
- "foo": {"@context": {"bar": {"@type": "@id"}}},
2960
- "bar": {"@type": "http://www.w3.org/2001/XMLSchema#string"}
2961
- },
2962
- "foo": {
2963
- "bar": "http://example/baz"
2964
- }
2965
- }),
2966
- output: %([
2967
- {
2968
- "http://example/foo": [{"http://example/bar": [{"@id": "http://example/baz"}]}]
2969
- }
2970
- ])
2971
- },
2972
- "property and value with different terms mapping to the same expanded property": {
2973
- input: %({
2974
- "@context": {
2975
- "@vocab": "http://example/",
2976
- "foo": {"@context": {"Bar": {"@id": "bar"}}}
2977
- },
2978
- "foo": {
2979
- "Bar": "baz"
2980
- }
2981
- }),
2982
- output: %([
2983
- {
2984
- "http://example/foo": [{
2985
- "http://example/bar": [
2986
- {"@value": "baz"}
2987
- ]}
2988
- ]
2989
- }
2990
- ])
2991
- },
2992
- "deep @context affects nested nodes": {
2993
- input: %({
2994
- "@context": {
2995
- "@vocab": "http://example/",
2996
- "foo": {"@context": {"baz": {"@type": "@vocab"}}}
2997
- },
2998
- "foo": {
2999
- "bar": {
3000
- "baz": "buzz"
3001
- }
3002
- }
3003
- }),
3004
- output: %([
3005
- {
3006
- "http://example/foo": [{
3007
- "http://example/bar": [{
3008
- "http://example/baz": [{"@id": "http://example/buzz"}]
3009
- }]
3010
- }]
3011
- }
3012
- ])
3013
- },
3014
- "scoped context layers on intemediate contexts": {
3015
- input: %({
3016
- "@context": {
3017
- "@vocab": "http://example/",
3018
- "b": {"@context": {"c": "http://example.org/c"}}
3019
- },
3020
- "a": {
3021
- "@context": {"@vocab": "http://example.com/"},
3022
- "b": {
3023
- "a": "A in example.com",
3024
- "c": "C in example.org"
3025
- },
3026
- "c": "C in example.com"
3027
- },
3028
- "c": "C in example"
3029
- }),
3030
- output: %([{
3031
- "http://example/a": [{
3032
- "http://example.com/c": [{"@value": "C in example.com"}],
3033
- "http://example/b": [{
3034
- "http://example.com/a": [{"@value": "A in example.com"}],
3035
- "http://example.org/c": [{"@value": "C in example.org"}]
3036
- }]
3037
- }],
3038
- "http://example/c": [{"@value": "C in example"}]
3039
- }])
3040
- },
3041
- "Raises InvalidTermDefinition if processingMode is 1.0": {
3042
- input: %({
3043
- "@context": {
3044
- "@vocab": "http://example/",
3045
- "foo": {"@context": {"bar": "http://example.org/bar"}}
3046
- },
3047
- "foo": {
3048
- "bar": "baz"
3049
- }
3050
- }),
3051
- processingMode: 'json-ld-1.0',
3052
- validate: true,
3053
- exception: JSON::LD::JsonLdError::InvalidTermDefinition
3054
- },
3055
- "Scoped on id map": {
3056
- input: %({
3057
- "@context": {
3058
- "@version": 1.1,
3059
- "schema": "http://schema.org/",
3060
- "name": "schema:name",
3061
- "body": "schema:articleBody",
3062
- "words": "schema:wordCount",
3063
- "post": {
3064
- "@id": "schema:blogPost",
3065
- "@container": "@id",
3066
- "@context": {
3067
- "@base": "http://example.com/posts/"
3068
- }
3069
- }
3070
- },
3071
- "@id": "http://example.com/",
3072
- "@type": "schema:Blog",
3073
- "name": "World Financial News",
3074
- "post": {
3075
- "1/en": {
3076
- "body": "World commodities were up today with heavy trading of crude oil...",
3077
- "words": 1539
3078
- },
3079
- "1/de": {
3080
- "body": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl...",
3081
- "words": 1204
3082
- }
3083
- }
3084
- }),
3085
- output: %([{
3086
- "@id": "http://example.com/",
3087
- "@type": ["http://schema.org/Blog"],
3088
- "http://schema.org/name": [{"@value": "World Financial News"}],
3089
- "http://schema.org/blogPost": [{
3090
- "@id": "http://example.com/posts/1/en",
3091
- "http://schema.org/articleBody": [
3092
- {"@value": "World commodities were up today with heavy trading of crude oil..."}
3093
- ],
3094
- "http://schema.org/wordCount": [{"@value": 1539}]
3095
- }, {
3096
- "@id": "http://example.com/posts/1/de",
3097
- "http://schema.org/articleBody": [
3098
- {"@value": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."}
3099
- ],
3100
- "http://schema.org/wordCount": [{"@value": 1204}]
3101
- }]
3102
- }])
3103
- }
3104
- }.each do |title, params|
3105
- it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
3106
- end
3107
- end
3108
-
3109
- context "scoped context on @type" do
3110
- {
3111
- "adding new term": {
3112
- input: %({
3113
- "@context": {
3114
- "@vocab": "http://example/",
3115
- "Foo": {"@context": {"bar": "http://example.org/bar"}}
3116
- },
3117
- "a": {"@type": "Foo", "bar": "baz"}
3118
- }),
3119
- output: %([
3120
- {
3121
- "http://example/a": [{
3122
- "@type": ["http://example/Foo"],
3123
- "http://example.org/bar": [{"@value": "baz"}]
3124
- }]
3125
- }
3126
- ])
3127
- },
3128
- "overriding a term": {
3129
- input: %({
3130
- "@context": {
3131
- "@vocab": "http://example/",
3132
- "Foo": {"@context": {"bar": {"@type": "@id"}}},
3133
- "bar": {"@type": "http://www.w3.org/2001/XMLSchema#string"}
3134
- },
3135
- "a": {"@type": "Foo", "bar": "http://example/baz"}
3136
- }),
3137
- output: %([
3138
- {
3139
- "http://example/a": [{
3140
- "@type": ["http://example/Foo"],
3141
- "http://example/bar": [{"@id": "http://example/baz"}]
3142
- }]
3143
- }
3144
- ])
3145
- },
3146
- "alias of @type": {
3147
- input: %({
3148
- "@context": {
3149
- "@vocab": "http://example/",
3150
- "type": "@type",
3151
- "Foo": {"@context": {"bar": "http://example.org/bar"}}
3152
- },
3153
- "a": {"type": "Foo", "bar": "baz"}
3154
- }),
3155
- output: %([
3156
- {
3157
- "http://example/a": [{
3158
- "@type": ["http://example/Foo"],
3159
- "http://example.org/bar": [{"@value": "baz"}]
3160
- }]
3161
- }
3162
- ])
3163
- },
3164
- "deep @context does not affect nested nodes": {
3165
- input: %({
3166
- "@context": {
3167
- "@vocab": "http://example/",
3168
- "Foo": {"@context": {"baz": {"@type": "@vocab"}}}
3169
- },
3170
- "@type": "Foo",
3171
- "bar": {"baz": "buzz"}
3172
- }),
3173
- output: %([
3174
- {
3175
- "@type": ["http://example/Foo"],
3176
- "http://example/bar": [{
3177
- "http://example/baz": [{"@value": "buzz"}]
3178
- }]
3179
- }
3180
- ])
3181
- },
3182
- "scoped context layers on intemediate contexts": {
3183
- input: %({
3184
- "@context": {
3185
- "@vocab": "http://example/",
3186
- "B": {"@context": {"c": "http://example.org/c"}}
3187
- },
3188
- "a": {
3189
- "@context": {"@vocab": "http://example.com/"},
3190
- "@type": "B",
3191
- "a": "A in example.com",
3192
- "c": "C in example.org"
3193
- },
3194
- "c": "C in example"
3195
- }),
3196
- output: %([{
3197
- "http://example/a": [{
3198
- "@type": ["http://example/B"],
3199
- "http://example.com/a": [{"@value": "A in example.com"}],
3200
- "http://example.org/c": [{"@value": "C in example.org"}]
3201
- }],
3202
- "http://example/c": [{"@value": "C in example"}]
3203
- }])
3204
- },
3205
- "with @container: @type": {
3206
- input: %({
3207
- "@context": {
3208
- "@vocab": "http://example/",
3209
- "typemap": {"@container": "@type"},
3210
- "Type": {"@context": {"a": "http://example.org/a"}}
3211
- },
3212
- "typemap": {
3213
- "Type": {"a": "Object with @type <Type>"}
3214
- }
3215
- }),
3216
- output: %([{
3217
- "http://example/typemap": [
3218
- {"http://example.org/a": [{"@value": "Object with @type <Type>"}], "@type": ["http://example/Type"]}
3219
- ]
3220
- }])
3221
- },
3222
- "orders lexicographically": {
3223
- input: %({
3224
- "@context": {
3225
- "@vocab": "http://example/",
3226
- "t1": {"@context": {"foo": {"@id": "http://example.com/foo"}}},
3227
- "t2": {"@context": {"foo": {"@id": "http://example.org/foo", "@type": "@id"}}}
3228
- },
3229
- "@type": ["t2", "t1"],
3230
- "foo": "urn:bar"
3231
- }),
3232
- output: %([{
3233
- "@type": ["http://example/t2", "http://example/t1"],
3234
- "http://example.org/foo": [
3235
- {"@id": "urn:bar"}
3236
- ]
3237
- }])
3238
- },
3239
- "Raises InvalidTermDefinition if processingMode is 1.0": {
3240
- input: %({
3241
- "@context": {
3242
- "@vocab": "http://example/",
3243
- "Foo": {"@context": {"bar": "http://example.org/bar"}}
3244
- },
3245
- "a": {"@type": "Foo", "bar": "baz"}
3246
- }),
3247
- processingMode: 'json-ld-1.0',
3248
- validate: true,
3249
- exception: JSON::LD::JsonLdError::InvalidTermDefinition
3250
- },
3251
- }.each do |title, params|
3252
- it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
3253
- end
3254
- end
3255
-
3256
- context "@reverse" do
3257
- {
3258
- "@container: @reverse": {
3259
- input: %({
3260
- "@context": {
3261
- "@vocab": "http://example/",
3262
- "rev": { "@reverse": "forward", "@type": "@id"}
3263
- },
3264
- "@id": "http://example/one",
3265
- "rev": "http://example/two"
3266
- }),
3267
- output: %([{
3268
- "@id": "http://example/one",
3269
- "@reverse": {
3270
- "http://example/forward": [
3271
- {
3272
- "@id": "http://example/two"
3273
- }
3274
- ]
3275
- }
3276
- }])
3277
- },
3278
- "expand-0037": {
3279
- input: %({
3280
- "@context": {
3281
- "name": "http://xmlns.com/foaf/0.1/name"
3282
- },
3283
- "@id": "http://example.com/people/markus",
3284
- "name": "Markus Lanthaler",
3285
- "@reverse": {
3286
- "http://xmlns.com/foaf/0.1/knows": {
3287
- "@id": "http://example.com/people/dave",
3288
- "name": "Dave Longley"
3289
- }
3290
- }
3291
- }),
3292
- output: %([
3293
- {
3294
- "@id": "http://example.com/people/markus",
3295
- "@reverse": {
3296
- "http://xmlns.com/foaf/0.1/knows": [
3297
- {
3298
- "@id": "http://example.com/people/dave",
3299
- "http://xmlns.com/foaf/0.1/name": [
3300
- {
3301
- "@value": "Dave Longley"
3302
- }
3303
- ]
3304
- }
3305
- ]
3306
- },
3307
- "http://xmlns.com/foaf/0.1/name": [
3308
- {
3309
- "@value": "Markus Lanthaler"
3310
- }
3311
- ]
3312
- }
3313
- ])
3314
- },
3315
- "expand-0043": {
3316
- input: %({
3317
- "@context": {
3318
- "name": "http://xmlns.com/foaf/0.1/name",
3319
- "isKnownBy": { "@reverse": "http://xmlns.com/foaf/0.1/knows" }
3320
- },
3321
- "@id": "http://example.com/people/markus",
3322
- "name": "Markus Lanthaler",
3323
- "@reverse": {
3324
- "isKnownBy": [
3325
- {
3326
- "@id": "http://example.com/people/dave",
3327
- "name": "Dave Longley"
3328
- },
3329
- {
3330
- "@id": "http://example.com/people/gregg",
3331
- "name": "Gregg Kellogg"
3332
- }
3333
- ]
3334
- }
3335
- }),
3336
- output: %([
3337
- {
3338
- "@id": "http://example.com/people/markus",
3339
- "http://xmlns.com/foaf/0.1/knows": [
3340
- {
3341
- "@id": "http://example.com/people/dave",
3342
- "http://xmlns.com/foaf/0.1/name": [
3343
- {
3344
- "@value": "Dave Longley"
3345
- }
3346
- ]
3347
- },
3348
- {
3349
- "@id": "http://example.com/people/gregg",
3350
- "http://xmlns.com/foaf/0.1/name": [
3351
- {
3352
- "@value": "Gregg Kellogg"
3353
- }
3354
- ]
3355
- }
3356
- ],
3357
- "http://xmlns.com/foaf/0.1/name": [
3358
- {
3359
- "@value": "Markus Lanthaler"
3360
- }
3361
- ]
3362
- }
3363
- ])
3364
- },
3365
- "@reverse object with an @id property": {
3366
- input: %({
3367
- "@id": "http://example/foo",
3368
- "@reverse": {
3369
- "@id": "http://example/bar"
3370
- }
3371
- }),
3372
- exception: JSON::LD::JsonLdError::InvalidReversePropertyMap,
3373
- },
3374
- "Explicit and implicit @reverse in same object": {
3375
- input: %({
3376
- "@context": {
3377
- "fooOf": {"@reverse": "ex:foo", "@type": "@id"}
3378
- },
3379
- "@id": "ex:s",
3380
- "fooOf": "ex:o1",
3381
- "@reverse": {
3382
- "ex:bar": {"@id": "ex:o2"}
3383
- }
3384
- }),
3385
- output: %([{
3386
- "@id": "ex:s",
3387
- "@reverse": {
3388
- "ex:bar": [{"@id": "ex:o2"}],
3389
- "ex:foo": [{"@id": "ex:o1"}]
3390
- }
3391
- }])
3392
- },
3393
- "Two properties both with @reverse": {
3394
- input: %({
3395
- "@context": {
3396
- "fooOf": {"@reverse": "ex:foo", "@type": "@id"},
3397
- "barOf": {"@reverse": "ex:bar", "@type": "@id"}
3398
- },
3399
- "@id": "ex:s",
3400
- "fooOf": "ex:o1",
3401
- "barOf": "ex:o2"
3402
- }),
3403
- output: %([{
3404
- "@id": "ex:s",
3405
- "@reverse": {
3406
- "ex:bar": [{"@id": "ex:o2"}],
3407
- "ex:foo": [{"@id": "ex:o1"}]
3408
- }
3409
- }])
3410
- },
3411
- }.each do |title, params|
3412
- it(title) {run_expand params}
3413
- end
3414
- end
3415
-
3416
- context "JSON-LD-star" do
3417
- {
3418
- "node with embedded subject without rdfstar option": {
3419
- input: %({
3420
- "@id": {
3421
- "@id": "ex:rei",
3422
- "ex:prop": "value"
3423
- },
3424
- "ex:prop": "value2"
3425
- }),
3426
- exception: JSON::LD::JsonLdError::InvalidIdValue
3427
- },
3428
- "node object with @annotation property is ignored without rdfstar option": {
3429
- input: %({
3430
- "@id": "ex:bob",
3431
- "ex:knows": {
3432
- "@id": "ex:fred",
3433
- "@annotation": {
3434
- "ex:certainty": 0.8
3435
- }
3436
- }
3437
- }),
3438
- output: %([{
3439
- "@id": "ex:bob",
3440
- "ex:knows": [{"@id": "ex:fred"}]
3441
- }])
3442
- },
3443
- "value object with @annotation property is ignored without rdfstar option": {
3444
- input: %({
3445
- "@id": "ex:bob",
3446
- "ex:age": {
3447
- "@value": 23,
3448
- "@annotation": {
3449
- "ex:certainty": 0.8
3450
- }
3451
- }
3452
- }),
3453
- output: %([{
3454
- "@id": "ex:bob",
3455
- "ex:age": [{"@value": 23}]
3456
- }])
3457
- },
3458
- }.each do |title, params|
3459
- it(title) {run_expand params}
3460
- end
3461
-
3462
- {
3463
- "node with embedded subject having no @id": {
3464
- input: %({
3465
- "@id": {
3466
- "ex:prop": "value"
3467
- },
3468
- "ex:prop": "value2"
3469
- }),
3470
- output: %([{
3471
- "@id": {
3472
- "ex:prop": [{"@value": "value"}]
3473
- },
3474
- "ex:prop": [{"@value": "value2"}]
3475
- }])
3476
- },
3477
- "node with embedded subject having IRI @id": {
3478
- input: %({
3479
- "@id": {
3480
- "@id": "ex:rei",
3481
- "ex:prop": "value"
3482
- },
3483
- "ex:prop": "value2"
3484
- }),
3485
- output: %([{
3486
- "@id": {
3487
- "@id": "ex:rei",
3488
- "ex:prop": [{"@value": "value"}]
3489
- },
3490
- "ex:prop": [{"@value": "value2"}]
3491
- }])
3492
- },
3493
- "node with embedded subject having BNode @id": {
3494
- input: %({
3495
- "@id": {
3496
- "@id": "_:rei",
3497
- "ex:prop": "value"
3498
- },
3499
- "ex:prop": "value2"
3500
- }),
3501
- output: %([{
3502
- "@id": {
3503
- "@id": "_:rei",
3504
- "ex:prop": [{"@value": "value"}]
3505
- },
3506
- "ex:prop": [{"@value": "value2"}]
3507
- }])
3508
- },
3509
- "node with embedded subject having a type": {
3510
- input: %({
3511
- "@id": {
3512
- "@id": "ex:rei",
3513
- "@type": "ex:Type"
3514
- },
3515
- "ex:prop": "value2"
3516
- }),
3517
- output: %([{
3518
- "@id": {
3519
- "@id": "ex:rei",
3520
- "@type": ["ex:Type"]
3521
- },
3522
- "ex:prop": [{"@value": "value2"}]
3523
- }])
3524
- },
3525
- "node with embedded subject having an IRI value": {
3526
- input: %({
3527
- "@id": {
3528
- "@id": "ex:rei",
3529
- "ex:prop": {"@id": "ex:value"}
3530
- },
3531
- "ex:prop": "value2"
3532
- }),
3533
- output: %([{
3534
- "@id": {
3535
- "@id": "ex:rei",
3536
- "ex:prop": [{"@id": "ex:value"}]
3537
- },
3538
- "ex:prop": [{"@value": "value2"}]
3539
- }])
3540
- },
3541
- "node with embedded subject having an BNode value": {
3542
- input: %({
3543
- "@id": {
3544
- "@id": "ex:rei",
3545
- "ex:prop": {"@id": "_:value"}
3546
- },
3547
- "ex:prop": "value2"
3548
- }),
3549
- output: %([{
3550
- "@id": {
3551
- "@id": "ex:rei",
3552
- "ex:prop": [{"@id": "_:value"}]
3553
- },
3554
- "ex:prop": [{"@value": "value2"}]
3555
- }])
3556
- },
3557
- "node with recursive embedded subject": {
3558
- input: %({
3559
- "@id": {
3560
- "@id": {
3561
- "@id": "ex:rei",
3562
- "ex:prop": "value3"
3563
- },
3564
- "ex:prop": "value"
3565
- },
3566
- "ex:prop": "value2"
3567
- }),
3568
- output: %([{
3569
- "@id": {
3570
- "@id": {
3571
- "@id": "ex:rei",
3572
- "ex:prop": [{"@value": "value3"}]
3573
- },
3574
- "ex:prop": [{"@value": "value"}]
3575
- },
3576
- "ex:prop": [{"@value": "value2"}]
3577
- }])
3578
- },
3579
- "illegal node with subject having no property": {
3580
- input: %({
3581
- "@id": {
3582
- "@id": "ex:rei"
3583
- },
3584
- "ex:prop": "value3"
3585
- }),
3586
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3587
- },
3588
- "illegal node with subject having multiple properties": {
3589
- input: %({
3590
- "@id": {
3591
- "@id": "ex:rei",
3592
- "ex:prop": ["value1", "value2"]
3593
- },
3594
- "ex:prop": "value3"
3595
- }),
3596
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3597
- },
3598
- "illegal node with subject having multiple types": {
3599
- input: %({
3600
- "@id": {
3601
- "@id": "ex:rei",
3602
- "@type": ["ex:Type1", "ex:Type2"]
3603
- },
3604
- "ex:prop": "value3"
3605
- }),
3606
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3607
- },
3608
- "illegal node with subject having type and property": {
3609
- input: %({
3610
- "@id": {
3611
- "@id": "ex:rei",
3612
- "@type": "ex:Type",
3613
- "ex:prop": "value"
3614
- },
3615
- "ex:prop": "value2"
3616
- }),
3617
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3618
- },
3619
- "node with embedded object": {
3620
- input: %({
3621
- "@id": "ex:subj",
3622
- "ex:value": {
3623
- "@id": {
3624
- "@id": "ex:rei",
3625
- "ex:prop": "value"
3626
- }
3627
- }
3628
- }),
3629
- output: %([{
3630
- "@id": "ex:subj",
3631
- "ex:value": [{
3632
- "@id": {
3633
- "@id": "ex:rei",
3634
- "ex:prop": [{"@value": "value"}]
3635
- }
3636
- }]
3637
- }])
3638
- },
3639
- "node with embedded object having properties": {
3640
- input: %({
3641
- "@id": "ex:subj",
3642
- "ex:value": {
3643
- "@id": {
3644
- "@id": "ex:rei",
3645
- "ex:prop": "value"
3646
- },
3647
- "ex:prop": "value2"
3648
- }
3649
- }),
3650
- output: %([{
3651
- "@id": "ex:subj",
3652
- "ex:value": [{
3653
- "@id": {
3654
- "@id": "ex:rei",
3655
- "ex:prop": [{"@value": "value"}]
3656
- },
3657
- "ex:prop": [{"@value": "value2"}]
3658
- }]
3659
- }])
3660
- },
3661
- "node with recursive embedded object": {
3662
- input: %({
3663
- "@id": "ex:subj",
3664
- "ex:value": {
3665
- "@id": {
3666
- "@id": {
3667
- "@id": "ex:rei",
3668
- "ex:prop": "value3"
3669
- },
3670
- "ex:prop": "value"
3671
- },
3672
- "ex:prop": "value2"
3673
- }
3674
- }),
3675
- output: %([{
3676
- "@id": "ex:subj",
3677
- "ex:value": [{
3678
- "@id": {
3679
- "@id": {
3680
- "@id": "ex:rei",
3681
- "ex:prop": [{"@value": "value3"}]
3682
- },
3683
- "ex:prop":[{"@value": "value"}]
3684
- },
3685
- "ex:prop": [{"@value": "value2"}]
3686
- }]
3687
- }])
3688
- },
3689
- "node with @annotation property on value object": {
3690
- input: %({
3691
- "@id": "ex:bob",
3692
- "ex:age": {
3693
- "@value": 23,
3694
- "@annotation": {"ex:certainty": 0.8}
3695
- }
3696
- }),
3697
- output: %([{
3698
- "@id": "ex:bob",
3699
- "ex:age": [{
3700
- "@value": 23,
3701
- "@annotation": [{"ex:certainty": [{"@value": 0.8}]}]
3702
- }]
3703
- }])
3704
- },
3705
- "node with @annotation property on node object": {
3706
- input: %({
3707
- "@id": "ex:bob",
3708
- "ex:name": "Bob",
3709
- "ex:knows": {
3710
- "@id": "ex:fred",
3711
- "ex:name": "Fred",
3712
- "@annotation": {"ex:certainty": 0.8}
3713
- }
3714
- }),
3715
- output: %([{
3716
- "@id": "ex:bob",
3717
- "ex:name": [{"@value": "Bob"}],
3718
- "ex:knows": [{
3719
- "@id": "ex:fred",
3720
- "ex:name": [{"@value": "Fred"}],
3721
- "@annotation": [{"ex:certainty": [{"@value": 0.8}]}]
3722
- }]
3723
- }])
3724
- },
3725
- "node with @annotation property multiple values": {
3726
- input: %({
3727
- "@id": "ex:bob",
3728
- "ex:name": "Bob",
3729
- "ex:knows": {
3730
- "@id": "ex:fred",
3731
- "ex:name": "Fred",
3732
- "@annotation": [{
3733
- "ex:certainty": 0.8
3734
- }, {
3735
- "ex:source": {"@id": "http://example.org/"}
3736
- }]
3737
- }
3738
- }),
3739
- output: %([{
3740
- "@id": "ex:bob",
3741
- "ex:name": [{"@value": "Bob"}],
3742
- "ex:knows": [{
3743
- "@id": "ex:fred",
3744
- "ex:name": [{"@value": "Fred"}],
3745
- "@annotation": [{
3746
- "ex:certainty": [{"@value": 0.8}]
3747
- }, {
3748
- "ex:source": [{"@id": "http://example.org/"}]
3749
- }]
3750
- }]
3751
- }])
3752
- },
3753
- "node with @annotation property that is on the top-level is invalid": {
3754
- input: %({
3755
- "@id": "ex:bob",
3756
- "ex:name": "Bob",
3757
- "@annotation": {"ex:prop": "value2"}
3758
- }),
3759
- exception: JSON::LD::JsonLdError::InvalidAnnotation
3760
- },
3761
- "node with @annotation property on a top-level graph node is invalid": {
3762
- input: %({
3763
- "@id": "ex:bob",
3764
- "ex:name": "Bob",
3765
- "@graph": {
3766
- "@id": "ex:fred",
3767
- "ex:name": "Fred",
3768
- "@annotation": {"ex:prop": "value2"}
3769
- }
3770
- }),
3771
- exception: JSON::LD::JsonLdError::InvalidAnnotation
3772
- },
3773
- "node with @annotation property having @id is invalid": {
3774
- input: %({
3775
- "@id": "ex:bob",
3776
- "ex:knows": {
3777
- "@id": "ex:fred",
3778
- "@annotation": {
3779
- "@id": "ex:invalid-ann-id",
3780
- "ex:prop": "value2"
3781
- }
3782
- }
3783
- }),
3784
- exception: JSON::LD::JsonLdError::InvalidAnnotation
3785
- },
3786
- "node with @annotation property with value object value is invalid": {
3787
- input: %({
3788
- "@id": "ex:bob",
3789
- "ex:knows": {
3790
- "@id": "fred",
3791
- "@annotation": "value2"
3792
- }
3793
- }),
3794
- exception: JSON::LD::JsonLdError::InvalidAnnotation
3795
- },
3796
- "node with @annotation on a list": {
3797
- input: %({
3798
- "@id": "ex:bob",
3799
- "ex:knows": {
3800
- "@list": [{"@id": "ex:fred"}],
3801
- "@annotation": {"ex:prop": "value2"}
3802
- }
3803
- }),
3804
- exception: JSON::LD::JsonLdError::InvalidSetOrListObject
3805
- },
3806
- "node with @annotation on a list value": {
3807
- input: %({
3808
- "@id": "ex:bob",
3809
- "ex:knows": {
3810
- "@list": [
3811
- {
3812
- "@id": "ex:fred",
3813
- "@annotation": {"ex:prop": "value2"}
3814
- }
3815
- ]
3816
- }
3817
- }),
3818
- exception: JSON::LD::JsonLdError::InvalidAnnotation
3819
- },
3820
- "node with @annotation property on a top-level @included node is invalid": {
3821
- input: %({
3822
- "@id": "ex:bob",
3823
- "ex:name": "Bob",
3824
- "@included": [{
3825
- "@id": "ex:fred",
3826
- "ex:name": "Fred",
3827
- "@annotation": {"ex:prop": "value2"}
3828
- }]
3829
- }),
3830
- exception: JSON::LD::JsonLdError::InvalidAnnotation
3831
- },
3832
- "node with @annotation property on embedded subject": {
3833
- input: %({
3834
- "@id": {
3835
- "@id": "ex:rei",
3836
- "ex:prop": {"@id": "_:value"}
3837
- },
3838
- "ex:prop": {
3839
- "@value": "value2",
3840
- "@annotation": {"ex:certainty": 0.8}
3841
- }
3842
- }),
3843
- output: %([{
3844
- "@id": {
3845
- "@id": "ex:rei",
3846
- "ex:prop": [{"@id": "_:value"}]
3847
- },
3848
- "ex:prop": [{
3849
- "@value": "value2",
3850
- "@annotation": [{
3851
- "ex:certainty": [{"@value": 0.8}]
3852
- }]
3853
- }]
3854
- }])
3855
- },
3856
- "node with @annotation property on embedded object": {
3857
- input: %({
3858
- "@id": "ex:subj",
3859
- "ex:value": {
3860
- "@id": {
3861
- "@id": "ex:rei",
3862
- "ex:prop": "value"
3863
- },
3864
- "@annotation": {"ex:certainty": 0.8}
3865
- }
3866
- }),
3867
- output: %([{
3868
- "@id": "ex:subj",
3869
- "ex:value": [{
3870
- "@id": {
3871
- "@id": "ex:rei",
3872
- "ex:prop": [{"@value": "value"}]
3873
- },
3874
- "@annotation": [{
3875
- "ex:certainty": [{"@value": 0.8}]
3876
- }]
3877
- }]
3878
- }])
3879
- },
3880
- "embedded node with reverse relationship": {
3881
- input: %({
3882
- "@context": {
3883
- "rel": {"@reverse": "ex:rel"}
3884
- },
3885
- "@id": {
3886
- "@id": "ex:rei",
3887
- "rel": {"@id": "ex:value"}
3888
- },
3889
- "ex:prop": "value2"
3890
- }),
3891
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3892
- },
3893
- "embedded node with expanded reverse relationship": {
3894
- input: %({
3895
- "@id": {
3896
- "@id": "ex:rei",
3897
- "@reverse": {
3898
- "ex:rel": {"@id": "ex:value"}
3899
- }
3900
- },
3901
- "ex:prop": "value2"
3902
- }),
3903
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3904
- },
3905
- "embedded node used as subject in reverse relationship": {
3906
- input: %({
3907
- "@context": {
3908
- "rel": {"@reverse": "ex:rel"}
3909
- },
3910
- "@id": {
3911
- "@id": "ex:rei",
3912
- "ex:prop": {"@id": "ex:value"}
3913
- },
3914
- "rel": {"@id": "ex:value2"}
3915
- }),
3916
- output: %([{
3917
- "@id": {
3918
- "@id": "ex:rei",
3919
- "ex:prop": [{"@id": "ex:value"}]
3920
- },
3921
- "@reverse": {
3922
- "ex:rel": [{"@id": "ex:value2"}]
3923
- }
3924
- }])
3925
- },
3926
- "embedded node used as object in reverse relationship": {
3927
- input: %({
3928
- "@context": {
3929
- "rel": {"@reverse": "ex:rel"}
3930
- },
3931
- "@id": "ex:subj",
3932
- "rel": {
3933
- "@id": {
3934
- "@id": "ex:rei",
3935
- "ex:prop": {"@id": "ex:value"}
3936
- },
3937
- "ex:prop": {"@id": "ex:value2"}
3938
- }
3939
- }),
3940
- output: %([{
3941
- "@id": "ex:subj",
3942
- "@reverse": {
3943
- "ex:rel": [{
3944
- "@id": {
3945
- "@id": "ex:rei",
3946
- "ex:prop": [{"@id": "ex:value"}]
3947
- },
3948
- "ex:prop": [{"@id": "ex:value2"}]
3949
- }]
3950
- }
3951
- }])
3952
- },
3953
- "node with @annotation property on node object with reverse relationship": {
3954
- input: %({
3955
- "@context": {
3956
- "knownBy": {"@reverse": "ex:knows"}
3957
- },
3958
- "@id": "ex:bob",
3959
- "ex:name": "Bob",
3960
- "knownBy": {
3961
- "@id": "ex:fred",
3962
- "ex:name": "Fred",
3963
- "@annotation": {"ex:certainty": 0.8}
3964
- }
3965
- }),
3966
- output: %([{
3967
- "@id": "ex:bob",
3968
- "ex:name": [{"@value": "Bob"}],
3969
- "@reverse": {
3970
- "ex:knows": [{
3971
- "@id": "ex:fred",
3972
- "ex:name": [{"@value": "Fred"}],
3973
- "@annotation": [{"ex:certainty": [{"@value": 0.8}]}]
3974
- }]
3975
- }
3976
- }])
3977
- },
3978
- "reverse relationship inside annotation": {
3979
- input: %({
3980
- "@context": {
3981
- "claims": {"@reverse": "ex:claims", "@type": "@id"}
3982
- },
3983
- "@id": "ex:bob",
3984
- "ex:knows": {
3985
- "@id": "ex:jane",
3986
- "@annotation": {
3987
- "ex:certainty": 0.8,
3988
- "claims": "ex:sue"
3989
- }
3990
- }
3991
- }),
3992
- output: %([{
3993
- "@id": "ex:bob",
3994
- "ex:knows": [{
3995
- "@id": "ex:jane",
3996
- "@annotation": [{
3997
- "ex:certainty": [{"@value": 0.8}],
3998
- "@reverse": {
3999
- "ex:claims": [{"@id": "ex:sue"}]
4000
- }
4001
- }]
4002
- }]
4003
- }])
4004
- },
4005
- }.each do |title, params|
4006
- it(title) {run_expand params.merge(rdfstar: true)}
4007
- end
4008
- end
4009
-
4010
- begin
4011
- require 'nokogiri'
4012
- rescue LoadError
4013
- end
4014
- require 'rexml/document'
4015
-
4016
- context "html" do
4017
- %w(Nokogiri REXML).each do |impl|
4018
- next unless Module.constants.map(&:to_s).include?(impl)
4019
- context impl do
4020
- let(:library) {impl.downcase.to_s.to_sym}
4021
-
4022
- {
4023
- "Expands embedded JSON-LD script element": {
4024
- input: %(
4025
- <html>
4026
- <head>
4027
- <script type="application/ld+json">
4028
- {
4029
- "@context": {
4030
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4031
- },
4032
- "foo": [{"@value": "bar"}]
4033
- }
4034
- </script>
4035
- </head>
4036
- </html>),
4037
- output: %([{
4038
- "http://example.com/foo": [{"@list": [{"@value": "bar"}]}]
4039
- }])
4040
- },
4041
- "Expands first script element": {
4042
- input: %(
4043
- <html>
4044
- <head>
4045
- <script type="application/ld+json">
4046
- {
4047
- "@context": {
4048
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4049
- },
4050
- "foo": [{"@value": "bar"}]
4051
- }
4052
- </script>
4053
- <script type="application/ld+json">
4054
- {
4055
- "@context": {"ex": "http://example.com/"},
4056
- "@graph": [
4057
- {"ex:foo": {"@value": "foo"}},
4058
- {"ex:bar": {"@value": "bar"}}
4059
- ]
4060
- }
4061
- </script>
4062
- </head>
4063
- </html>),
4064
- output: %([{
4065
- "http://example.com/foo": [{"@list": [{"@value": "bar"}]}]
4066
- }])
4067
- },
4068
- "Expands targeted script element": {
4069
- input: %(
4070
- <html>
4071
- <head>
4072
- <script id="first" type="application/ld+json">
4073
- {
4074
- "@context": {
4075
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4076
- },
4077
- "foo": [{"@value": "bar"}]
4078
- }
4079
- </script>
4080
- <script id="second" type="application/ld+json">
4081
- {
4082
- "@context": {"ex": "http://example.com/"},
4083
- "@graph": [
4084
- {"ex:foo": {"@value": "foo"}},
4085
- {"ex:bar": {"@value": "bar"}}
4086
- ]
4087
- }
4088
- </script>
4089
- </head>
4090
- </html>),
4091
- output: %([
4092
- {"http://example.com/foo": [{"@value": "foo"}]},
4093
- {"http://example.com/bar": [{"@value": "bar"}]}
4094
- ]),
4095
- base: "http://example.org/doc#second"
4096
- },
4097
- "Expands all script elements with extractAllScripts option": {
4098
- input: %(
4099
- <html>
4100
- <head>
4101
- <script type="application/ld+json">
4102
- {
4103
- "@context": {
4104
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4105
- },
4106
- "foo": [{"@value": "bar"}]
4107
- }
4108
- </script>
4109
- <script type="application/ld+json">
4110
- {
4111
- "@context": {"ex": "http://example.com/"},
4112
- "@graph": [
4113
- {"ex:foo": {"@value": "foo"}},
4114
- {"ex:bar": {"@value": "bar"}}
4115
- ]
4116
- }
4117
- </script>
4118
- </head>
4119
- </html>),
4120
- output: %([
4121
- {"http://example.com/foo": [{"@list": [{"@value": "bar"}]}]},
4122
- {
4123
- "@graph": [{
4124
- "http://example.com/foo": [{"@value": "foo"}]
4125
- }, {
4126
- "http://example.com/bar": [{"@value": "bar"}]
4127
- }]
4128
- }
4129
- ]),
4130
- extractAllScripts: true
4131
- },
4132
- "Expands multiple scripts where one is an array": {
4133
- input: %(
4134
- <html>
4135
- <head>
4136
- <script type="application/ld+json">
4137
- {
4138
- "@context": {
4139
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4140
- },
4141
- "foo": [{"@value": "bar"}]
4142
- }
4143
- </script>
4144
- <script type="application/ld+json">
4145
- [
4146
- {"@context": {"ex": "http://example.com/"}, "ex:foo": {"@value": "foo"}},
4147
- {"@context": {"ex": "http://example.com/"}, "ex:bar": {"@value": "bar"}}
4148
- ]
4149
- </script>
4150
- </head>
4151
- </html>),
4152
- output: %([
4153
- {"http://example.com/foo": [{"@list": [{"@value": "bar"}]}]},
4154
- {"http://example.com/foo": [{"@value": "foo"}]},
4155
- {"http://example.com/bar": [{"@value": "bar"}]}
4156
- ]),
4157
- extractAllScripts: true
4158
- },
4159
- "Errors no script element": {
4160
- input: %(<html><head></head></html>),
4161
- exception: JSON::LD::JsonLdError::LoadingDocumentFailed
4162
- },
4163
- "Expands as empty with no script element and extractAllScripts": {
4164
- input: %(<html><head></head></html>),
4165
- output: %([]),
4166
- extractAllScripts: true
4167
- },
4168
- "Expands script element with HTML character references": {
4169
- input: %(
4170
- <html>
4171
- <head>
4172
- <script type="application/ld+json">
4173
- {
4174
- "@context": {"@vocab": "http://example/"},
4175
- "foo": "&lt;&amp;&gt;"
4176
- }
4177
- </script>
4178
- </head>
4179
- </html>),
4180
- output: %([{
4181
- "http://example/foo": [{"@value": "&lt;&amp;&gt;"}]
4182
- }])
4183
- },
4184
- "Expands embedded JSON-LD script element relative to document base": {
4185
- input: %(
4186
- <html>
4187
- <head>
4188
- <script type="application/ld+json">
4189
- {
4190
- "@context": {
4191
- "foo": {"@id": "http://example.com/foo"}
4192
- },
4193
- "@id": "",
4194
- "foo": [{"@value": "bar"}]
4195
- }
4196
- </script>
4197
- </head>
4198
- </html>),
4199
- output: %([{
4200
- "@id": "http://example.org/doc",
4201
- "http://example.com/foo": [{"@value": "bar"}]
4202
- }]),
4203
- base: "http://example.org/doc"
4204
- },
4205
- "Expands embedded JSON-LD script element relative to HTML base": {
4206
- input: %(
4207
- <html>
4208
- <head>
4209
- <base href="http://example.org/base" />
4210
- <script type="application/ld+json">
4211
- {
4212
- "@context": {
4213
- "foo": {"@id": "http://example.com/foo"}
4214
- },
4215
- "@id": "",
4216
- "foo": [{"@value": "bar"}]
4217
- }
4218
- </script>
4219
- </head>
4220
- </html>),
4221
- output: %([{
4222
- "@id": "http://example.org/base",
4223
- "http://example.com/foo": [{"@value": "bar"}]
4224
- }]),
4225
- base: "http://example.org/doc"
4226
- },
4227
- "Expands embedded JSON-LD script element relative to relative HTML base": {
4228
- input: %(
4229
- <html>
4230
- <head>
4231
- <base href="base" />
4232
- <script type="application/ld+json">
4233
- {
4234
- "@context": {
4235
- "foo": {"@id": "http://example.com/foo"}
4236
- },
4237
- "@id": "",
4238
- "foo": [{"@value": "bar"}]
4239
- }
4240
- </script>
4241
- </head>
4242
- </html>),
4243
- output: %([{
4244
- "@id": "http://example.org/base",
4245
- "http://example.com/foo": [{"@value": "bar"}]
4246
- }]),
4247
- base: "http://example.org/doc"
4248
- },
4249
- "Errors if no element found at target": {
4250
- input: %(
4251
- <html>
4252
- <head>
4253
- <script id="first" type="application/ld+json">
4254
- {
4255
- "@context": {
4256
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4257
- },
4258
- "foo": [{"@value": "bar"}]
4259
- }
4260
- </script>
4261
- <script id="second" type="application/ld+json">
4262
- {
4263
- "@context": {"ex": "http://example.com/"},
4264
- "@graph": [
4265
- {"ex:foo": {"@value": "foo"}},
4266
- {"ex:bar": {"@value": "bar"}}
4267
- ]
4268
- }
4269
- </script>
4270
- </head>
4271
- </html>),
4272
- base: "http://example.org/doc#third",
4273
- exception: JSON::LD::JsonLdError::LoadingDocumentFailed
4274
- },
4275
- "Errors if targeted element is not a script element": {
4276
- input: %(
4277
- <html>
4278
- <head>
4279
- <pre id="first" type="application/ld+json">
4280
- {
4281
- "@context": {
4282
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4283
- },
4284
- "foo": [{"@value": "bar"}]
4285
- }
4286
- </pre>
4287
- </head>
4288
- </html>),
4289
- base: "http://example.org/doc#first",
4290
- exception: JSON::LD::JsonLdError::LoadingDocumentFailed
4291
- },
4292
- "Errors if targeted element does not have type application/ld+json": {
4293
- input: %(
4294
- <html>
4295
- <head>
4296
- <script id="first" type="application/json">
4297
- {
4298
- "@context": {
4299
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4300
- },
4301
- "foo": [{"@value": "bar"}]
4302
- }
4303
- </script>
4304
- </head>
4305
- </html>),
4306
- base: "http://example.org/doc#first",
4307
- exception: JSON::LD::JsonLdError::LoadingDocumentFailed
4308
- },
4309
- "Errors if uncommented script text contains comment": {
4310
- input: %(
4311
- <html>
4312
- <head>
4313
- <script type="application/ld+json">
4314
- <!--
4315
- {
4316
- "@context": {
4317
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4318
- },
4319
- "foo": [{"@value": "<!-- -->"}]
4320
- }
4321
- -->
4322
- </script>
4323
- </head>
4324
- </html>),
4325
- exception: JSON::LD::JsonLdError::InvalidScriptElement,
4326
- not: :rexml
4327
- },
4328
- "Errors if end comment missing": {
4329
- input: %(
4330
- <html>
4331
- <head>
4332
- <script type="application/ld+json">
4333
- <!--
4334
- {
4335
- "@context": {
4336
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4337
- },
4338
- "foo": [{"@value": "bar"}]
4339
- }
4340
- </script>
4341
- </head>
4342
- </html>),
4343
- exception: JSON::LD::JsonLdError::InvalidScriptElement,
4344
- not: :rexml
4345
- },
4346
- "Errors if start comment missing": {
4347
- input: %(
4348
- <html>
4349
- <head>
4350
- <script type="application/ld+json">
4351
- {
4352
- "@context": {
4353
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
4354
- },
4355
- "foo": [{"@value": "bar"}]
4356
- }
4357
- -->
4358
- </script>
4359
- </head>
4360
- </html>),
4361
- exception: JSON::LD::JsonLdError::InvalidScriptElement
4362
- },
4363
- "Errors if uncommented script is not valid JSON": {
4364
- input: %(
4365
- <html>
4366
- <head>
4367
- <script type="application/ld+json">
4368
- foo
4369
- </script>
4370
- </head>
4371
- </html>),
4372
- exception: JSON::LD::JsonLdError::InvalidScriptElement
4373
- },
4374
- }.each do |title, params|
4375
- it(title) do
4376
- skip "rexml" if params[:not] == library
4377
- params = params.merge(input: StringIO.new(params[:input]))
4378
- params[:input].send(:define_singleton_method, :content_type) {"text/html"}
4379
- run_expand params.merge(validate: true, library: library)
4380
- end
4381
- end
4382
- end
4383
- end
4384
- end
4385
-
4386
- context "deprectaions" do
4387
- {
4388
- "blank node property": {
4389
- input: %({"_:bn": "value"}),
4390
- output: %([{"_:bn": [{"@value": "value"}]}])
4391
- }
4392
- }.each do |name, params|
4393
- it "deprecation on #{name} when validating" do
4394
- run_expand(params.merge(validate: true, write: "[DEPRECATION]"))
4395
- end
4396
-
4397
- it "no deprecation on #{name} when not validating" do
4398
- run_expand(params.merge(validate: false))
4399
- end
4400
- end
4401
- end
4402
-
4403
- context "exceptions" do
4404
- {
4405
- "non-null @value and null @type": {
4406
- input: %({"http://example.com/foo": {"@value": "foo", "@type": null}}),
4407
- exception: JSON::LD::JsonLdError::InvalidTypeValue
4408
- },
4409
- "non-null @value and null @language": {
4410
- input: %({"http://example.com/foo": {"@value": "foo", "@language": null}}),
4411
- exception: JSON::LD::JsonLdError::InvalidLanguageTaggedString
4412
- },
4413
- "value with null language": {
4414
- input: %({
4415
- "@context": {"@language": "en"},
4416
- "http://example.org/nolang": {"@value": "no language", "@language": null}
4417
- }),
4418
- exception: JSON::LD::JsonLdError::InvalidLanguageTaggedString
4419
- },
4420
- "colliding keywords": {
4421
- input: %({
4422
- "@context": {
4423
- "id": "@id",
4424
- "ID": "@id"
4425
- },
4426
- "id": "http://example/foo",
4427
- "ID": "http://example/bar"
4428
- }),
4429
- exception: JSON::LD::JsonLdError::CollidingKeywords,
4430
- },
4431
- "@language and @type": {
4432
- input: %({
4433
- "ex:p": {
4434
- "@value": "v",
4435
- "@type": "ex:t",
4436
- "@language": "en"
4437
- }
4438
- }),
4439
- exception: JSON::LD::JsonLdError::InvalidValueObject,
4440
- processingMode: 'json-ld-1.1'
4441
- },
4442
- "@direction and @type": {
4443
- input: %({
4444
- "ex:p": {
4445
- "@value": "v",
4446
- "@type": "ex:t",
4447
- "@direction": "rtl"
4448
- }
4449
- }),
4450
- exception: JSON::LD::JsonLdError::InvalidValueObject,
4451
- processingMode: 'json-ld-1.1'
4452
- },
4453
- }.each do |title, params|
4454
- it(title) {run_expand params}
4455
- end
4456
- end
4457
-
4458
- context "problem cases" do
4459
- {
4460
- "toRdf/0118": {
4461
- input: %({
4462
- "@context": {"term": "_:term", "termId": { "@id": "term", "@type": "@id" }},
4463
- "termId": "term:AppendedToBlankNode"
4464
- }),
4465
- output: %([{
4466
- "_:term": [{"@id": "_:termAppendedToBlankNode"}]
4467
- }])
4468
- },
4469
- }.each do |title, params|
4470
- it(title) {run_expand params}
4471
- end
4472
- end
4473
- end
4474
-
4475
- def run_expand(params)
4476
- input, output = params[:input], params[:output]
4477
- params[:base] ||= nil
4478
- input = ::JSON.parse(input) if input.is_a?(String)
4479
- output = ::JSON.parse(output) if output.is_a?(String)
4480
- pending params.fetch(:pending, "test implementation") unless input
4481
- if params[:exception]
4482
- expect {JSON::LD::API.expand(input, **params)}.to raise_error(params[:exception])
4483
- else
4484
- jld = nil
4485
- if params[:write]
4486
- expect{jld = JSON::LD::API.expand(input, logger: logger, **params)}.to write(params[:write]).to(:error)
4487
- else
4488
- expect{jld = JSON::LD::API.expand(input, logger: logger, **params)}.not_to write.to(:error)
4489
- end
4490
- expect(jld).to produce_jsonld(output, logger)
4491
-
4492
- # Also expect result to produce itself
4493
- expect(output).to produce_jsonld(output, logger)
4494
- end
4495
- end
4496
- end