json-ld 3.1.3 → 3.1.8

Sign up to get free protection for your applications and to get access to all the features.
data/spec/context_spec.rb CHANGED
@@ -56,13 +56,6 @@ describe JSON::LD::Context do
56
56
  describe "#parse" do
57
57
  context "remote" do
58
58
 
59
- it "retrieves and parses a remote context document" do
60
- JSON::LD::Context.instance_variable_set(:@cache, nil)
61
- expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
62
- ec = subject.parse("http://example.com/context")
63
- expect(ec.provided_context).to produce("http://example.com/context", logger)
64
- end
65
-
66
59
  it "fails given a missing remote @context" do
67
60
  JSON::LD::Context.instance_variable_set(:@cache, nil)
68
61
  expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_raise(IOError)
@@ -190,12 +183,6 @@ describe JSON::LD::Context do
190
183
  expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
191
184
  subject.parse(ctx)
192
185
  end
193
-
194
- it "does not use passed context as provided_context" do
195
- expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
196
- ec = subject.parse(ctx)
197
- expect(ec.provided_context).to produce(ctx, logger)
198
- end
199
186
  end
200
187
 
201
188
  context "pre-loaded remote" do
@@ -645,14 +632,6 @@ describe JSON::LD::Context do
645
632
 
646
633
  describe "#serialize" do
647
634
  before {JSON::LD::Context.instance_variable_set(:@cache, nil)}
648
- it "context document" do
649
- expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
650
- ec = subject.parse("http://example.com/context")
651
- expect(ec.serialize).to produce({
652
- "@context" => "http://example.com/context"
653
- }, logger)
654
- end
655
-
656
635
  it "context hash" do
657
636
  ctx = {"foo" => "http://example.com/"}
658
637
 
@@ -684,7 +663,7 @@ describe JSON::LD::Context do
684
663
 
685
664
  it "term mappings" do
686
665
  c = subject.
687
- parse({'foo' => "http://example.com/"}).send(:clear_provided_context)
666
+ parse({'foo' => "http://example.com/"})
688
667
  expect(c.serialize).to produce({
689
668
  "@context" => {
690
669
  "foo" => "http://example.com/"
@@ -696,7 +675,7 @@ describe JSON::LD::Context do
696
675
  it "@context" do
697
676
  expect(subject.parse({
698
677
  "foo" => {"@id" => "http://example.com/", "@context" => {"bar" => "http://example.com/baz"}}
699
- }).send(:clear_provided_context).
678
+ }).
700
679
  serialize).to produce({
701
680
  "@context" => {
702
681
  "foo" => {
@@ -712,7 +691,6 @@ describe JSON::LD::Context do
712
691
  'xsd' => "http://www.w3.org/2001/XMLSchema#",
713
692
  'homepage' => {'@id' => RDF::Vocab::FOAF.homepage.to_s, '@type' => '@id'}
714
693
  }).
715
- send(:clear_provided_context).
716
694
  serialize).to produce({
717
695
  "@context" => {
718
696
  "xsd" => RDF::XSD.to_uri.to_s,
@@ -725,7 +703,6 @@ describe JSON::LD::Context do
725
703
  expect(subject.parse({
726
704
  'knows' => {'@id' => RDF::Vocab::FOAF.knows.to_s, '@container' => '@list'}
727
705
  }).
728
- send(:clear_provided_context).
729
706
  serialize).to produce({
730
707
  "@context" => {
731
708
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@list"}
@@ -737,7 +714,6 @@ describe JSON::LD::Context do
737
714
  expect(subject.parse({
738
715
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@set"}
739
716
  }).
740
- send(:clear_provided_context).
741
717
  serialize).to produce({
742
718
  "@context" => {
743
719
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@set"}
@@ -749,7 +725,6 @@ describe JSON::LD::Context do
749
725
  expect(subject.parse({
750
726
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => "en"}
751
727
  }).
752
- send(:clear_provided_context).
753
728
  serialize).to produce({
754
729
  "@context" => {
755
730
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => "en"}
@@ -762,7 +737,6 @@ describe JSON::LD::Context do
762
737
  "@language" => 'en',
763
738
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => 'en'}
764
739
  }).
765
- send(:clear_provided_context).
766
740
  serialize).to produce({
767
741
  "@context" => {
768
742
  "@language" => 'en',
@@ -776,7 +750,6 @@ describe JSON::LD::Context do
776
750
  "@language" => 'en',
777
751
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => "de"}
778
752
  }).
779
- send(:clear_provided_context).
780
753
  serialize).to produce({
781
754
  "@context" => {
782
755
  "@language" => 'en',
@@ -790,7 +763,6 @@ describe JSON::LD::Context do
790
763
  "@language" => 'en',
791
764
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => nil}
792
765
  }).
793
- send(:clear_provided_context).
794
766
  serialize).to produce({
795
767
  "@context" => {
796
768
  "@language" => 'en',
@@ -803,7 +775,6 @@ describe JSON::LD::Context do
803
775
  expect(subject.parse({
804
776
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@id", "@container" => "@list"}
805
777
  }).
806
- send(:clear_provided_context).
807
778
  serialize).to produce({
808
779
  "@context" => {
809
780
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@id", "@container" => "@list"}
@@ -815,7 +786,6 @@ describe JSON::LD::Context do
815
786
  expect(subject.parse({
816
787
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@id", "@container" => "@set"}
817
788
  }).
818
- send(:clear_provided_context).
819
789
  serialize).to produce({
820
790
  "@context" => {
821
791
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@id", "@container" => "@set"}
@@ -827,7 +797,6 @@ describe JSON::LD::Context do
827
797
  expect(subject.parse({
828
798
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@json"}
829
799
  }).
830
- send(:clear_provided_context).
831
800
  serialize).to produce({
832
801
  "@context" => {
833
802
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@json"}
@@ -842,7 +811,6 @@ describe JSON::LD::Context do
842
811
  "@container" => "@list"
843
812
  }
844
813
  }).
845
- send(:clear_provided_context).
846
814
  serialize).to produce({
847
815
  "@context" => {
848
816
  "foaf" => RDF::Vocab::FOAF.to_uri.to_s,
@@ -858,7 +826,6 @@ describe JSON::LD::Context do
858
826
  "id" => "@id",
859
827
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@list"}
860
828
  }).
861
- send(:clear_provided_context).
862
829
  serialize).to produce({
863
830
  "@context" => {
864
831
  "id" => "@id",
@@ -875,7 +842,6 @@ describe JSON::LD::Context do
875
842
  "@type" => "@id"
876
843
  }
877
844
  }).
878
- send(:clear_provided_context).
879
845
  serialize).to produce({
880
846
  "@context" => {
881
847
  "foaf" => RDF::Vocab::FOAF.to_uri.to_s,
@@ -893,7 +859,6 @@ describe JSON::LD::Context do
893
859
  "type" => "@type",
894
860
  "foaf:homepage" => {"@type" => "@id"}
895
861
  }).
896
- send(:clear_provided_context).
897
862
  serialize).to produce({
898
863
  "@context" => {
899
864
  "foaf" => RDF::Vocab::FOAF.to_uri.to_s,
@@ -908,7 +873,6 @@ describe JSON::LD::Context do
908
873
  "container" => "@container",
909
874
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@list"}
910
875
  }).
911
- send(:clear_provided_context).
912
876
  serialize).to produce({
913
877
  "@context" => {
914
878
  "container" => "@container",
@@ -922,7 +886,6 @@ describe JSON::LD::Context do
922
886
  "ex" => 'http://example.org/',
923
887
  "term" => {"@id" => "ex:term", "@type" => "ex:datatype"}
924
888
  }).
925
- send(:clear_provided_context).
926
889
  serialize).to produce({
927
890
  "@context" => {
928
891
  "ex" => 'http://example.org/',
@@ -936,7 +899,6 @@ describe JSON::LD::Context do
936
899
  "@vocab" => 'http://example.org/',
937
900
  "term" => {"@id" => "http://example.org/term", "@type" => "datatype"}
938
901
  }).
939
- send(:clear_provided_context).
940
902
  serialize).to produce({
941
903
  "@context" => {
942
904
  "@vocab" => 'http://example.org/',
@@ -1245,7 +1207,7 @@ describe JSON::LD::Context do
1245
1207
  it "does not use @vocab if it would collide with a term" do
1246
1208
  subject.set_mapping("name", "http://xmlns.com/foaf/0.1/name")
1247
1209
  subject.set_mapping("ex", nil)
1248
- expect(subject.compact_iri("http://example.org/name", position: :predicate)).
1210
+ expect(subject.compact_iri("http://example.org/name", vocab: true)).
1249
1211
  not_to produce("name", logger)
1250
1212
  end
1251
1213
 
@@ -1528,7 +1490,7 @@ describe JSON::LD::Context do
1528
1490
  })
1529
1491
  end
1530
1492
  it "Compact @id that is a property IRI when @container is @list" do
1531
- expect(ctx.compact_iri("http://example.org/ns#property", position: :subject)).
1493
+ expect(ctx.compact_iri("http://example.org/ns#property", vocab: false)).
1532
1494
  to produce("ex:property", logger)
1533
1495
  end
1534
1496
  end
data/spec/expand_spec.rb CHANGED
@@ -3371,9 +3371,640 @@ describe JSON::LD::API do
3371
3371
  }),
3372
3372
  exception: JSON::LD::JsonLdError::InvalidReversePropertyMap,
3373
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*" 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
+ },
3374
3458
  }.each do |title, params|
3375
3459
  it(title) {run_expand params}
3376
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
3377
4008
  end
3378
4009
 
3379
4010
  begin