json-ld 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/History.markdown +3 -0
  2. data/VERSION +1 -1
  3. data/bin/jsonld +134 -0
  4. data/lib/json/ld/api.rb +4 -4
  5. data/lib/json/ld/frame.rb +2 -1
  6. data/lib/json/ld/from_rdf.rb +1 -1
  7. data/spec/api_spec.rb +66 -0
  8. data/spec/compact_spec.rb +420 -0
  9. data/spec/evaluation_context_spec.rb +1039 -0
  10. data/spec/expand_spec.rb +625 -0
  11. data/spec/format_spec.rb +71 -0
  12. data/spec/frame_spec.rb +542 -0
  13. data/spec/from_rdf_spec.rb +316 -0
  14. data/spec/matchers.rb +67 -0
  15. data/spec/reader_spec.rb +79 -0
  16. data/spec/spec_helper.rb +56 -0
  17. data/spec/suite_helper.rb +184 -0
  18. data/spec/suite_spec.rb +104 -0
  19. data/spec/support/extensions.rb +10 -0
  20. data/spec/test-files/test-1-automatic.json +10 -0
  21. data/spec/test-files/test-1-compacted.json +10 -0
  22. data/spec/test-files/test-1-context.json +7 -0
  23. data/spec/test-files/test-1-expanded.json +5 -0
  24. data/spec/test-files/test-1-input.json +10 -0
  25. data/spec/test-files/test-1-normalized.json +8 -0
  26. data/spec/test-files/test-1-rdf.ttl +7 -0
  27. data/spec/test-files/test-2-automatic.json +27 -0
  28. data/spec/test-files/test-2-compacted.json +20 -0
  29. data/spec/test-files/test-2-context.json +7 -0
  30. data/spec/test-files/test-2-expanded.json +16 -0
  31. data/spec/test-files/test-2-input.json +20 -0
  32. data/spec/test-files/test-2-normalized.json +32 -0
  33. data/spec/test-files/test-2-rdf.ttl +14 -0
  34. data/spec/test-files/test-3-compacted.json +11 -0
  35. data/spec/test-files/test-3-context.json +8 -0
  36. data/spec/test-files/test-3-expanded.json +10 -0
  37. data/spec/test-files/test-3-input.json +11 -0
  38. data/spec/test-files/test-3-normalized.json +13 -0
  39. data/spec/test-files/test-3-rdf.ttl +7 -0
  40. data/spec/test-files/test-4-automatic.json +10 -0
  41. data/spec/test-files/test-4-compacted.json +10 -0
  42. data/spec/test-files/test-4-context.json +7 -0
  43. data/spec/test-files/test-4-expanded.json +6 -0
  44. data/spec/test-files/test-4-input.json +10 -0
  45. data/spec/test-files/test-4-rdf.ttl +5 -0
  46. data/spec/test-files/test-5-automatic.json +13 -0
  47. data/spec/test-files/test-5-compacted.json +13 -0
  48. data/spec/test-files/test-5-context.json +7 -0
  49. data/spec/test-files/test-5-expanded.json +9 -0
  50. data/spec/test-files/test-5-input.json +13 -0
  51. data/spec/test-files/test-5-rdf.ttl +6 -0
  52. data/spec/test-files/test-6-automatic.json +10 -0
  53. data/spec/test-files/test-6-compacted.json +10 -0
  54. data/spec/test-files/test-6-context.json +7 -0
  55. data/spec/test-files/test-6-expanded.json +10 -0
  56. data/spec/test-files/test-6-input.json +10 -0
  57. data/spec/test-files/test-6-rdf.ttl +5 -0
  58. data/spec/test-files/test-7-automatic.json +20 -0
  59. data/spec/test-files/test-7-compacted.json +23 -0
  60. data/spec/test-files/test-7-context.json +4 -0
  61. data/spec/test-files/test-7-expanded.json +20 -0
  62. data/spec/test-files/test-7-input.json +23 -0
  63. data/spec/test-files/test-7-rdf.ttl +13 -0
  64. data/spec/test-files/test-8-automatic.json +1 -0
  65. data/spec/test-files/test-8-compacted.json +34 -0
  66. data/spec/test-files/test-8-context.json +11 -0
  67. data/spec/test-files/test-8-expanded.json +24 -0
  68. data/spec/test-files/test-8-frame.json +18 -0
  69. data/spec/test-files/test-8-framed.json +29 -0
  70. data/spec/test-files/test-8-input.json +30 -0
  71. data/spec/test-files/test-8-rdf.ttl +15 -0
  72. data/spec/test-files/test-9-compacted.json +20 -0
  73. data/spec/test-files/test-9-context.json +13 -0
  74. data/spec/test-files/test-9-expanded.json +14 -0
  75. data/spec/test-files/test-9-input.json +12 -0
  76. data/spec/to_rdf_spec.rb +640 -0
  77. data/spec/writer_spec.rb +161 -0
  78. metadata +150 -22
@@ -0,0 +1,71 @@
1
+ # coding: utf-8
2
+ $:.unshift "."
3
+ require 'spec_helper'
4
+ require 'rdf/spec/format'
5
+
6
+ describe JSON::LD::Format do
7
+ before :each do
8
+ @format_class = JSON::LD::Format
9
+ end
10
+
11
+ it_should_behave_like RDF_Format
12
+
13
+ describe ".for" do
14
+ formats = [
15
+ :jsonld,
16
+ "etc/doap.jsonld",
17
+ {:file_name => 'etc/doap.jsonld'},
18
+ {:file_extension => 'jsonld'},
19
+ {:content_type => 'application/ld+json'},
20
+ {:content_type => 'application/x-ld+json'},
21
+ ].each do |arg|
22
+ it "discovers with #{arg.inspect}" do
23
+ RDF::Format.for(arg).should == @format_class
24
+ end
25
+ end
26
+
27
+ {
28
+ :jsonld => '{"@context" => "foo"}',
29
+ :context => %({\n"@context": {),
30
+ :id => %({\n"@id": {),
31
+ :type => %({\n"@type": {),
32
+ }.each do |sym, str|
33
+ it "detects #{sym}" do
34
+ @format_class.for {str}.should == @format_class
35
+ end
36
+ end
37
+
38
+ it "should discover 'jsonld'" do
39
+ RDF::Format.for(:jsonld).reader.should == JSON::LD::Reader
40
+ end
41
+ end
42
+
43
+ describe "#to_sym" do
44
+ specify {@format_class.to_sym.should == :jsonld}
45
+ end
46
+
47
+ describe ".detect" do
48
+ {
49
+ :jsonld => '{"@context" => "foo"}',
50
+ }.each do |sym, str|
51
+ it "detects #{sym}" do
52
+ @format_class.detect(str).should be_true
53
+ end
54
+ end
55
+
56
+ {
57
+ :n3 => "@prefix foo: <bar> .\nfoo:bar = {<a> <b> <c>} .",
58
+ :nquads => "<a> <b> <c> <d> . ",
59
+ :rdfxml => '<rdf:RDF about="foo"></rdf:RDF>',
60
+ :rdfa => '<div about="foo"></div>',
61
+ :microdata => '<div itemref="bar"></div>',
62
+ :ntriples => "<a> <b> <c> .",
63
+ :multi_line => '<a>\n <b>\n "literal"\n .',
64
+ :turtle => "@prefix foo: <bar> .\n foo:a foo:b <c> .",
65
+ }.each do |sym, str|
66
+ it "does not detect #{sym}" do
67
+ @format_class.detect(str).should be_false
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,542 @@
1
+ # coding: utf-8
2
+ $:.unshift "."
3
+ require 'spec_helper'
4
+
5
+ describe JSON::LD::API do
6
+ before(:each) { @debug = []}
7
+
8
+ describe ".frame" do
9
+ {
10
+ "frame with @type matches subject with @type" => {
11
+ :frame => {
12
+ "@context" => {"ex" => "http://example.org/"},
13
+ "@type" => "ex:Type1"
14
+ },
15
+ :input => [
16
+ {
17
+ "@context" => {"ex" => "http://example.org/"},
18
+ "@id" => "ex:Sub1",
19
+ "@type" => "ex:Type1"
20
+ },
21
+ {
22
+ "@context" => {"ex" => "http://example.org/"},
23
+ "@id" => "ex:Sub2",
24
+ "@type" => "ex:Type2"
25
+ },
26
+ ],
27
+ :output => {
28
+ "@context" => {"ex" => "http://example.org/"},
29
+ "@graph" => [{
30
+ "@id" => "ex:Sub1",
31
+ "@type" => "ex:Type1"
32
+ }]
33
+ }
34
+ },
35
+ "implicitly includes unframed properties" => {
36
+ :frame => {
37
+ "@context" => {"ex" => "http://example.org/"},
38
+ "@type" => "ex:Type1"
39
+ },
40
+ :input => [
41
+ {
42
+ "@context" => {"ex" => "http://example.org/"},
43
+ "@id" => "ex:Sub1",
44
+ "@type" => "ex:Type1",
45
+ "ex:prop1" => "Property 1",
46
+ "ex:prop2" => {"@id" => "ex:Obj1"}
47
+ }
48
+ ],
49
+ :output => {
50
+ "@context" => {"ex" => "http://example.org/"},
51
+ "@graph" => [{
52
+ "@id" => "ex:Sub1",
53
+ "@type" => "ex:Type1",
54
+ "ex:prop1" => "Property 1",
55
+ "ex:prop2" => {"@id" => "ex:Obj1"}
56
+ }]
57
+ }
58
+ },
59
+ "explicitly excludes unframed properties" => {
60
+ :frame => {
61
+ "@context" => {"ex" => "http://example.org/"},
62
+ "@explicit" => true,
63
+ "@type" => "ex:Type1"
64
+ },
65
+ :input => [
66
+ {
67
+ "@context" => {"ex" => "http://example.org/"},
68
+ "@id" => "ex:Sub1",
69
+ "@type" => "ex:Type1",
70
+ "ex:prop1" => "Property 1",
71
+ "ex:prop2" => {"@id" => "ex:Obj1"}
72
+ }
73
+ ],
74
+ :output => {
75
+ "@context" => {"ex" => "http://example.org/"},
76
+ "@graph" => [{
77
+ "@id" => "ex:Sub1",
78
+ "@type" => "ex:Type1"
79
+ }]
80
+ }
81
+ },
82
+ "explicitly includes unframed properties" => {
83
+ :frame => {
84
+ "@context" => {"ex" => "http://example.org/"},
85
+ "@explicit" => false,
86
+ "@type" => "ex:Type1"
87
+ },
88
+ :input => [
89
+ {
90
+ "@context" => {"ex" => "http://example.org/"},
91
+ "@id" => "ex:Sub1",
92
+ "@type" => "ex:Type1",
93
+ "ex:prop1" => "Property 1",
94
+ "ex:prop2" => {"@id" => "ex:Obj1"}
95
+ }
96
+ ],
97
+ :output => {
98
+ "@context" => {"ex" => "http://example.org/"},
99
+ "@graph" => [{
100
+ "@id" => "ex:Sub1",
101
+ "@type" => "ex:Type1",
102
+ "ex:prop1" => "Property 1",
103
+ "ex:prop2" => {"@id" => "ex:Obj1"}
104
+ }]
105
+ }
106
+ },
107
+ "frame without @type matches only subjects containing listed properties (duck typing)" => {
108
+ :frame => {
109
+ "@context" => {"ex" => "http://example.org/"},
110
+ "ex:prop1" => {},
111
+ "ex:prop2" => {}
112
+ },
113
+ :input => [
114
+ {
115
+ "@context" => {"ex" => "http://example.org/"},
116
+ "@id" => "ex:Sub1",
117
+ "ex:prop1" => "Property 1"
118
+ },
119
+ {
120
+ "@context" => {"ex" => "http://example.org/"},
121
+ "@id" => "ex:Sub2",
122
+ "ex:prop2" => "Property 2"
123
+ },
124
+ {
125
+ "@context" => {"ex" => "http://example.org/"},
126
+ "@id" => "ex:Sub3",
127
+ "ex:prop1" => "Property 1",
128
+ "ex:prop2" => "Property 2"
129
+ },
130
+ ],
131
+ :output => {
132
+ "@context" => {"ex" => "http://example.org/"},
133
+ "@graph" => [{
134
+ "@id" => "ex:Sub3",
135
+ "ex:prop1" => "Property 1",
136
+ "ex:prop2" => "Property 2"
137
+ }]
138
+ }
139
+ },
140
+ "embed matched frames" => {
141
+ :frame => {
142
+ "@context" => {"ex" => "http://example.org/"},
143
+ "@type" => "ex:Type1",
144
+ "ex:includes" => {
145
+ "@type" => "ex:Type2"
146
+ }
147
+ },
148
+ :input => [
149
+ {
150
+ "@context" => {"ex" => "http://example.org/"},
151
+ "@id" => "ex:Sub1",
152
+ "@type" => "ex:Type1",
153
+ "ex:includes" => {"@id" => "ex:Sub2"}
154
+ },
155
+ {
156
+ "@context" => {"ex" => "http://example.org/"},
157
+ "@id" => "ex:Sub2",
158
+ "@type" => "ex:Type2",
159
+ "ex:includes" => {"@id" => "ex:Sub1"}
160
+ },
161
+ ],
162
+ :output =>{
163
+ "@context" => {"ex" => "http://example.org/"},
164
+ "@graph" => [{
165
+ "@id" => "ex:Sub1",
166
+ "@type" => "ex:Type1",
167
+ "ex:includes" => {
168
+ "@id" => "ex:Sub2",
169
+ "@type" => "ex:Type2",
170
+ "ex:includes" => {"@id" => "ex:Sub1"}
171
+ }
172
+ }]
173
+ }
174
+ },
175
+ "multiple matches" => {
176
+ :frame => {
177
+ "@context" => {"ex" => "http://example.org/"},
178
+ "@type" => "ex:Type1"
179
+ },
180
+ :input => [
181
+ {
182
+ "@context" => {"ex" => "http://example.org/"},
183
+ "@id" => "ex:Sub1",
184
+ "@type" => "ex:Type1"
185
+ },
186
+ {
187
+ "@context" => {"ex" => "http://example.org/"},
188
+ "@id" => "ex:Sub2",
189
+ "@type" => "ex:Type1"
190
+ },
191
+ ],
192
+ :output => {
193
+ "@context" => {"ex" => "http://example.org/"},
194
+ "@graph" => [
195
+ {
196
+ "@id" => "ex:Sub1",
197
+ "@type" => "ex:Type1"
198
+ },
199
+ {
200
+ "@id" => "ex:Sub2",
201
+ "@type" => "ex:Type1"
202
+ }
203
+ ]
204
+ }
205
+ },
206
+ "non-existent framed properties create null property" => {
207
+ :frame => {
208
+ "@context" => {"ex" => "http://example.org/"},
209
+ "@type" => "ex:Type1",
210
+ "ex:null" => []
211
+ },
212
+ :input => [
213
+ {
214
+ "@context" => {"ex" => "http://example.org/"},
215
+ "@id" => "ex:Sub1",
216
+ "@type" => "ex:Type1",
217
+ "ex:prop1" => "Property 1",
218
+ "ex:prop2" => {"@id" => "ex:Obj1"}
219
+ }
220
+ ],
221
+ :output => {
222
+ "@context" => {"ex" => "http://example.org/"},
223
+ "@graph" => [{
224
+ "@id" => "ex:Sub1",
225
+ "@type" => "ex:Type1",
226
+ "ex:prop1" => "Property 1",
227
+ "ex:prop2" => {"@id" => "ex:Obj1"},
228
+ "ex:null" => nil
229
+ }]
230
+ }
231
+ },
232
+ "non-existent framed properties create default property" => {
233
+ :frame => {
234
+ "@context" => {"ex" => "http://example.org/", "ex:null" => {"@container" => "@set"}},
235
+ "@type" => "ex:Type1",
236
+ "ex:null" => [{"@default" => "foo"}]
237
+ },
238
+ :input => [
239
+ {
240
+ "@context" => {"ex" => "http://example.org/"},
241
+ "@id" => "ex:Sub1",
242
+ "@type" => "ex:Type1",
243
+ "ex:prop1" => "Property 1",
244
+ "ex:prop2" => {"@id" => "ex:Obj1"}
245
+ }
246
+ ],
247
+ :output => {
248
+ "@context" => {"ex" => "http://example.org/", "ex:null" => {"@container" => "@set"}},
249
+ "@graph" => [{
250
+ "@id" => "ex:Sub1",
251
+ "@type" => "ex:Type1",
252
+ "ex:prop1" => "Property 1",
253
+ "ex:prop2" => {"@id" => "ex:Obj1"},
254
+ "ex:null" => ["foo"]
255
+ }]
256
+ }
257
+ },
258
+ "mixed content" => {
259
+ :frame => {
260
+ "@context" => {"ex" => "http://example.org/"},
261
+ "ex:mixed" => {"@embed" => false}
262
+ },
263
+ :input => [
264
+ {
265
+ "@context" => {"ex" => "http://example.org/"},
266
+ "@id" => "ex:Sub1",
267
+ "ex:mixed" => [
268
+ {"@id" => "ex:Sub2"},
269
+ "literal1"
270
+ ]
271
+ }
272
+ ],
273
+ :output => {
274
+ "@context" => {"ex" => "http://example.org/"},
275
+ "@graph" => [{
276
+ "@id" => "ex:Sub1",
277
+ "ex:mixed" => [
278
+ {"@id" => "ex:Sub2"},
279
+ "literal1"
280
+ ]
281
+ }]
282
+ }
283
+ },
284
+ "no embedding" => {
285
+ :frame => {
286
+ "@context" => {"ex" => "http://example.org/"},
287
+ "ex:embed" => {"@embed" => false}
288
+ },
289
+ :input => [
290
+ {
291
+ "@context" => {"ex" => "http://example.org/"},
292
+ "@id" => "ex:Sub1",
293
+ "ex:embed" => {
294
+ "@id" => "ex:Sub2",
295
+ "ex:prop" => "property"
296
+ }
297
+ }
298
+ ],
299
+ :output => {
300
+ "@context" => {"ex" => "http://example.org/"},
301
+ "@graph" => [{
302
+ "@id" => "ex:Sub1",
303
+ "ex:embed" => {"@id" => "ex:Sub2"}
304
+ }]
305
+ }
306
+ },
307
+ "mixed list" => {
308
+ :frame => {
309
+ "@context" => {"ex" => "http://example.org/"},
310
+ "ex:mixedlist" => {}
311
+ },
312
+ :input => {
313
+ "@context" => {"ex" => "http://example.org/"},
314
+ "@id" => "ex:Sub1",
315
+ "@type" => "ex:Type1",
316
+ "ex:mixedlist" => {"@list" => [
317
+ {
318
+ "@id" => "ex:Sub2",
319
+ "@type" => "ex:Type2"
320
+ },
321
+ "literal1"
322
+ ]}
323
+ },
324
+ :output => {
325
+ "@context" => {"ex" => "http://example.org/"},
326
+ "@graph" => [{
327
+ "@id" => "ex:Sub1",
328
+ "@type" => "ex:Type1",
329
+ "ex:mixedlist" => {"@list" => [
330
+ {
331
+ "@id" => "ex:Sub2",
332
+ "@type" => "ex:Type2"
333
+ },
334
+ "literal1"
335
+ ]}
336
+ }]
337
+ }
338
+ },
339
+ "presentation example" => {
340
+ :frame => {
341
+ "@context" => {
342
+ "primaryTopic" => {"@id" => "http://xmlns.com/foaf/0.1/primaryTopic","@type" => "@id"},
343
+ "sameAs" => {"@id" => "http://www.w3.org/2002/07/owl#sameAs","@type" => "@id"},
344
+ },
345
+ "primaryTopic" => {
346
+ "@type" => "http://dbpedia.org/class/yago/Buzzwords",
347
+ "sameAs" => {}
348
+ }
349
+ },
350
+ :input => [
351
+ {
352
+ "@id" => "http://en.wikipedia.org/wiki/Linked_Data",
353
+ "http://xmlns.com/foaf/0.1/primaryTopic" => [{"@id" => "http://dbpedia.org/resource/Linked_Data"}]
354
+ },
355
+ {
356
+ "@id" => "http://www4.wiwiss.fu-berlin.de/flickrwrappr/photos/Linked_Data",
357
+ "http://www.w3.org/2002/07/owl#sameAs" => [{"@id" => "http://dbpedia.org/resource/Linked_Data"}]
358
+ },
359
+ {
360
+ "@id" => "http://dbpedia.org/resource/Linked_Data",
361
+ "@type" => ["http://dbpedia.org/class/yago/Buzzwords"],
362
+ "http://www.w3.org/2002/07/owl#sameAs" => [{"@id" => "http://rdf.freebase.com/ns/m/02r2kb1"}]
363
+ },
364
+ {
365
+ "@id" => "http://mpii.de/yago/resource/Linked_Data",
366
+ "http://www.w3.org/2002/07/owl#sameAs" => [{"@id" => "http://dbpedia.org/resource/Linked_Data"}]
367
+ }
368
+ ],
369
+ :output => {
370
+ "@context" => {
371
+ "primaryTopic" => {
372
+ "@id" => "http://xmlns.com/foaf/0.1/primaryTopic",
373
+ "@type" => "@id"
374
+ },
375
+ "sameAs" => {
376
+ "@id" => "http://www.w3.org/2002/07/owl#sameAs",
377
+ "@type" => "@id"
378
+ }
379
+ },
380
+ "@graph" => [
381
+ {
382
+ "@id" => "http://en.wikipedia.org/wiki/Linked_Data",
383
+ "primaryTopic" => {
384
+ "@id" => "http://dbpedia.org/resource/Linked_Data",
385
+ "@type" => "http://dbpedia.org/class/yago/Buzzwords",
386
+ "sameAs" => "http://rdf.freebase.com/ns/m/02r2kb1"
387
+ }
388
+ }
389
+ ]
390
+ }
391
+ }
392
+ }.each do |title, params|
393
+ it title do
394
+ @debug = []
395
+ begin
396
+ jld = JSON::LD::API.frame(params[:input], params[:frame], nil, :debug => @debug)
397
+ jld.should produce(params[:output], @debug)
398
+ rescue JSON::LD::ProcessingError, JSON::LD::InvalidContext, JSON::LD::InvalidFrame => e
399
+ fail("#{e.class}: #{e.message}\n" +
400
+ "#{@debug.join("\n")}\n" +
401
+ "Backtrace:\n#{e.backtrace.join("\n")}")
402
+ end
403
+ end
404
+ end
405
+ end
406
+
407
+ describe "#get_framing_subjects" do
408
+ {
409
+ "single object" => {
410
+ :input => {"@id" => "http://example.com", "@type" => RDF::RDFS.Resource.to_s},
411
+ :subjects => %w(http://example.com),
412
+ :output => {
413
+ "http://example.com" => {
414
+ "@id" => "http://example.com", "@type" => [RDF::RDFS.Resource.to_s]
415
+ }
416
+ }
417
+ },
418
+ "embedded object" => {
419
+ :input => {
420
+ "@context" => {"foaf" => RDF::FOAF.to_s},
421
+ "@id" => "http://greggkellogg.net/foaf",
422
+ "@type" => ["foaf:PersonalProfile"],
423
+ "foaf:primaryTopic" => [{
424
+ "@id" => "http://greggkellogg.net/foaf#me",
425
+ "@type" => ["foaf:Person"]
426
+ }]
427
+ },
428
+ :subjects => %w(http://greggkellogg.net/foaf http://greggkellogg.net/foaf#me),
429
+ :output => {
430
+ "http://greggkellogg.net/foaf" => {
431
+ "@id" => "http://greggkellogg.net/foaf",
432
+ "@type" => [RDF::FOAF.PersonalProfile.to_s],
433
+ RDF::FOAF.primaryTopic.to_s => [{"@id" => "http://greggkellogg.net/foaf#me"}]
434
+ },
435
+ "http://greggkellogg.net/foaf#me" => {
436
+ "@id" => "http://greggkellogg.net/foaf#me",
437
+ "@type" => [RDF::FOAF.Person.to_s]
438
+ }
439
+ }
440
+ },
441
+ "embedded anon" => {
442
+ :input => {
443
+ "@context" => {"foaf" => RDF::FOAF.to_s},
444
+ "@id" => "http://greggkellogg.net/foaf",
445
+ "@type" => "foaf:PersonalProfile",
446
+ "foaf:primaryTopic" => {
447
+ "@type" => "foaf:Person"
448
+ }
449
+ },
450
+ :subjects => %w(http://greggkellogg.net/foaf _:t0),
451
+ :output => {
452
+ "_:t0" => {
453
+ "@id" => "_:t0",
454
+ "@type" => [RDF::FOAF.Person.to_s]
455
+ },
456
+ "http://greggkellogg.net/foaf" => {
457
+ "@id" => "http://greggkellogg.net/foaf",
458
+ "@type" => [RDF::FOAF.PersonalProfile.to_s],
459
+ RDF::FOAF.primaryTopic.to_s => [{"@id" => "_:t0"}]
460
+ },
461
+ }
462
+ },
463
+ }.each do |title, params|
464
+ it title do
465
+ @debug = []
466
+ @subjects = Hash.ordered
467
+ jld = nil
468
+ JSON::LD::API.new(params[:input], nil, :debug => @debug) do |api|
469
+ expanded_value = api.expand(api.value, nil, api.context)
470
+ api.get_framing_subjects(@subjects, expanded_value, JSON::LD::BlankNodeNamer.new("t"))
471
+ end
472
+ @subjects.keys.should produce(params[:subjects], @debug)
473
+ @subjects.should produce(params[:output], @debug)
474
+ end
475
+ end
476
+ end
477
+
478
+ describe ".flatten" do
479
+ {
480
+ "single object" => {
481
+ :input => {"@id" => "http://example.com", "@type" => RDF::RDFS.Resource.to_s},
482
+ :output => [{"@id" => "http://example.com", "@type" => [RDF::RDFS.Resource.to_s]}]
483
+ },
484
+ "embedded object" => {
485
+ :input => {
486
+ "@context" => {
487
+ "foaf" => RDF::FOAF.to_s
488
+ },
489
+ "@id" => "http://greggkellogg.net/foaf",
490
+ "@type" => ["foaf:PersonalProfile"],
491
+ "foaf:primaryTopic" => [{
492
+ "@id" => "http://greggkellogg.net/foaf#me",
493
+ "@type" => ["foaf:Person"]
494
+ }]
495
+ },
496
+ :output => [
497
+ {
498
+ "@id" => "http://greggkellogg.net/foaf",
499
+ "@type" => [RDF::FOAF.PersonalProfile.to_s],
500
+ RDF::FOAF.primaryTopic.to_s => [{"@id" => "http://greggkellogg.net/foaf#me"}]
501
+ },
502
+ {
503
+ "@id" => "http://greggkellogg.net/foaf#me",
504
+ "@type" => [RDF::FOAF.Person.to_s]
505
+ }
506
+ ]
507
+ },
508
+ "embedded anon" => {
509
+ :input => {
510
+ "@context" => {
511
+ "foaf" => RDF::FOAF.to_s
512
+ },
513
+ "@id" => "http://greggkellogg.net/foaf",
514
+ "@type" => "foaf:PersonalProfile",
515
+ "foaf:primaryTopic" => {
516
+ "@type" => "foaf:Person"
517
+ }
518
+ },
519
+ :output => [
520
+ {
521
+ "@id" => "_:t0",
522
+ "@type" => [RDF::FOAF.Person.to_s]
523
+ },
524
+ {
525
+ "@id" => "http://greggkellogg.net/foaf",
526
+ "@type" => [RDF::FOAF.PersonalProfile.to_s],
527
+ RDF::FOAF.primaryTopic.to_s => [{"@id" => "_:t0"}]
528
+ },
529
+ ]
530
+ }
531
+ }.each do |title, params|
532
+ it title do
533
+ @debug = []
534
+ jld = nil
535
+ JSON::LD::API.new(params[:input], nil, :debug => @debug) do |api|
536
+ jld = api.flatten
537
+ end
538
+ jld.should produce(params[:output], @debug)
539
+ end
540
+ end
541
+ end
542
+ end