json-ld 3.1.3 → 3.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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