n3 0.4.2 → 0.5.0

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.
@@ -1,6 +1,6 @@
1
1
  var N3Parser = require('../N3').Parser;
2
- var chai = require('chai'),
3
- expect = chai.expect;
2
+ var chai = require('chai');
3
+ var expect = chai.expect;
4
4
  chai.should();
5
5
  chai.use(require('chai-things'));
6
6
 
@@ -427,6 +427,13 @@ describe('N3Parser', function () {
427
427
  ['http://ex.org/a', 'http://ex.org/b', '"c"^^http://ex.org/d'],
428
428
  ['http://ex.org/d/e', 'http://ex.org/d/f', '"g"^^http://ex.org/d/h']));
429
429
 
430
+ it('should not resolve prefixed names',
431
+ shouldParse('PREFIX ex: <http://ex.org/a/bb/ccc/../>\n' +
432
+ 'ex:a ex:b ex:c .',
433
+ ['http://ex.org/a/bb/ccc/../a',
434
+ 'http://ex.org/a/bb/ccc/../b',
435
+ 'http://ex.org/a/bb/ccc/../c']));
436
+
430
437
  it('should parse an empty default graph',
431
438
  shouldParse('{}'));
432
439
 
@@ -629,7 +636,7 @@ describe('N3Parser', function () {
629
636
  it('should not parse invalid @base statements',
630
637
  shouldNotParse('@base <http://ex.org/foo#bar>.\n' +
631
638
  '<a> <b> <c>.\n',
632
- 'Invalid base IRI at line 1.'));
639
+ 'Invalid base IRI http://ex.org/foo#bar at line 1.'));
633
640
 
634
641
  it('should not parse improperly nested parentheses and brackets',
635
642
  shouldNotParse('<a> <b> [<c> (<d>]).',
@@ -720,25 +727,68 @@ describe('N3Parser', function () {
720
727
  });
721
728
 
722
729
  describe('An N3Parser instance with a document IRI', function () {
723
- var parser = new N3Parser({ documentIRI: 'http://ex.org/doc/f.ttl' });
730
+ var parser = new N3Parser({ documentIRI: 'http://ex.org/x/yy/zzz/f.ttl' });
724
731
 
725
732
  it('should resolve IRIs against the document IRI',
726
733
  shouldParse(parser,
727
734
  '@prefix : <#>.\n' +
728
735
  '<a> <b> <c> <g>.\n' +
729
736
  ':d :e :f :g.',
730
- ['http://ex.org/doc/a', 'http://ex.org/doc/b', 'http://ex.org/doc/c', 'http://ex.org/doc/g'],
731
- ['http://ex.org/doc/f.ttl#d', 'http://ex.org/doc/f.ttl#e', 'http://ex.org/doc/f.ttl#f', 'http://ex.org/doc/f.ttl#g']));
737
+ ['http://ex.org/x/yy/zzz/a', 'http://ex.org/x/yy/zzz/b', 'http://ex.org/x/yy/zzz/c', 'http://ex.org/x/yy/zzz/g'],
738
+ ['http://ex.org/x/yy/zzz/f.ttl#d', 'http://ex.org/x/yy/zzz/f.ttl#e', 'http://ex.org/x/yy/zzz/f.ttl#f', 'http://ex.org/x/yy/zzz/f.ttl#g']));
732
739
 
733
- it('should resolve IRIs with a trailing slashes against the document IRI',
740
+ it('should resolve IRIs with a trailing slash against the document IRI',
734
741
  shouldParse(parser,
735
742
  '</a> </a/b> </a/b/c>.\n',
736
743
  ['http://ex.org/a', 'http://ex.org/a/b', 'http://ex.org/a/b/c']));
737
744
 
745
+ it('should resolve IRIs starting with ./ against the document IRI',
746
+ shouldParse(parser,
747
+ '<./a> <./a/b> <./a/b/c>.\n',
748
+ ['http://ex.org/x/yy/zzz/a', 'http://ex.org/x/yy/zzz/a/b', 'http://ex.org/x/yy/zzz/a/b/c']));
749
+
750
+ it('should resolve IRIs starting with multiple ./ sequences against the document IRI',
751
+ shouldParse(parser,
752
+ '<./././a> <./././././a/b> <././././././a/b/c>.\n',
753
+ ['http://ex.org/x/yy/zzz/a', 'http://ex.org/x/yy/zzz/a/b', 'http://ex.org/x/yy/zzz/a/b/c']));
754
+
755
+ it('should resolve IRIs starting with ../ against the document IRI',
756
+ shouldParse(parser,
757
+ '<../a> <../a/b> <../a/b/c>.\n',
758
+ ['http://ex.org/x/yy/a', 'http://ex.org/x/yy/a/b', 'http://ex.org/x/yy/a/b/c']));
759
+
760
+ it('should resolve IRIs starting multiple ../ sequences against the document IRI',
761
+ shouldParse(parser,
762
+ '<../../a> <../../../a/b> <../../../../../../../../a/b/c>.\n',
763
+ ['http://ex.org/x/a', 'http://ex.org/a/b', 'http://ex.org/a/b/c']));
764
+
765
+ it('should resolve IRIs starting with mixes of ./ and ../ sequences against the document IRI',
766
+ shouldParse(parser,
767
+ '<.././a> <./.././a/b> <./.././.././a/b/c>.\n',
768
+ ['http://ex.org/x/yy/a', 'http://ex.org/x/yy/a/b', 'http://ex.org/x/a/b/c']));
769
+
770
+ it('should resolve IRIs starting with .x, ..x, or .../ against the document IRI',
771
+ shouldParse(parser,
772
+ '<.x/a> <..x/a/b> <.../a/b/c>.\n',
773
+ ['http://ex.org/x/yy/zzz/.x/a', 'http://ex.org/x/yy/zzz/..x/a/b', 'http://ex.org/x/yy/zzz/.../a/b/c']));
774
+
738
775
  it('should resolve datatype IRIs against the document IRI',
739
776
  shouldParse(parser,
740
777
  '<a> <b> "c"^^<d>.',
741
- ['http://ex.org/doc/a', 'http://ex.org/doc/b', '"c"^^http://ex.org/doc/d']));
778
+ ['http://ex.org/x/yy/zzz/a', 'http://ex.org/x/yy/zzz/b', '"c"^^http://ex.org/x/yy/zzz/d']));
779
+
780
+ it('should resolve IRIs in lists against the document IRI',
781
+ shouldParse(parser,
782
+ '(<a> <b>) <p> (<c> <d>).',
783
+ ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first', 'http://ex.org/x/yy/zzz/a'],
784
+ ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest', '_:b1'],
785
+ ['_:b1', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first', 'http://ex.org/x/yy/zzz/b'],
786
+ ['_:b1', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'],
787
+ ['_:b0', 'http://ex.org/x/yy/zzz/p', '_:b2'],
788
+ ['_:b2', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first', 'http://ex.org/x/yy/zzz/c'],
789
+ ['_:b2', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest', '_:b3'],
790
+ ['_:b3', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first', 'http://ex.org/x/yy/zzz/d'],
791
+ ['_:b3', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil']));
742
792
 
743
793
  it('should respect @base statements',
744
794
  shouldParse(parser,
@@ -749,19 +799,37 @@ describe('N3Parser', function () {
749
799
  '<h> <i> <j>.\n' +
750
800
  '@base </e/>.\n' +
751
801
  '<k> <l> <m>.',
752
- ['http://ex.org/doc/a', 'http://ex.org/doc/b', 'http://ex.org/doc/c'],
802
+ ['http://ex.org/x/yy/zzz/a', 'http://ex.org/x/yy/zzz/b', 'http://ex.org/x/yy/zzz/c'],
753
803
  ['http://ex.org/x/e', 'http://ex.org/x/f', 'http://ex.org/x/g'],
754
804
  ['http://ex.org/x/d/h', 'http://ex.org/x/d/i', 'http://ex.org/x/d/j'],
755
805
  ['http://ex.org/e/k', 'http://ex.org/e/l', 'http://ex.org/e/m']));
756
806
  });
757
807
 
808
+ describe('An N3Parser instance with a blank node prefix', function () {
809
+ var parser = new N3Parser({ blankNodePrefix: '_:blank' });
810
+
811
+ it('should use the given prefix for blank nodes',
812
+ shouldParse(parser,
813
+ '_:a <b> _:c.\n',
814
+ ['_:blanka', 'b', '_:blankc']));
815
+ });
816
+
817
+ describe('An N3Parser instance with an empty blank node prefix', function () {
818
+ var parser = new N3Parser({ blankNodePrefix: '' });
819
+
820
+ it('should not use a prefix for blank nodes',
821
+ shouldParse(parser,
822
+ '_:a <b> _:c.\n',
823
+ ['_:a', 'b', '_:c']));
824
+ });
825
+
758
826
  describe('An N3Parser instance with an invalid document IRI', function () {
759
827
  it('cannot be created', function (done) {
760
828
  try {
761
- new N3Parser({ documentIRI: 'http://ex.org/doc/f#' });
829
+ var parser = new N3Parser({ documentIRI: 'http://ex.org/x/yy/zzz/f#' });
762
830
  }
763
831
  catch (error) {
764
- error.message.should.equal('Invalid document IRI');
832
+ error.message.should.equal('Invalid base IRI http://ex.org/x/yy/zzz/f#');
765
833
  done();
766
834
  }
767
835
  });
@@ -850,6 +918,386 @@ describe('N3Parser', function () {
850
918
  it('should not parse a prefix declaration',
851
919
  shouldNotParse(parser, '@prefix : <p#>.', 'Syntax error: unexpected "@prefix" on line 1.'));
852
920
  });
921
+
922
+ describe('IRI resolution', function () {
923
+ describe('RFC3986 normal examples', function () {
924
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g:h', 'g:h');
925
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g', 'http://a/bb/ccc/g');
926
+ itShouldResolve('http://a/bb/ccc/d;p?q', './g', 'http://a/bb/ccc/g');
927
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g/', 'http://a/bb/ccc/g/');
928
+ itShouldResolve('http://a/bb/ccc/d;p?q', '/g', 'http://a/g');
929
+ itShouldResolve('http://a/bb/ccc/d;p?q', '//g', 'http://g');
930
+ itShouldResolve('http://a/bb/ccc/d;p?q', '?y', 'http://a/bb/ccc/d;p?y');
931
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g?y', 'http://a/bb/ccc/g?y');
932
+ itShouldResolve('http://a/bb/ccc/d;p?q', '#s', 'http://a/bb/ccc/d;p?q#s');
933
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g#s', 'http://a/bb/ccc/g#s');
934
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g?y#s', 'http://a/bb/ccc/g?y#s');
935
+ itShouldResolve('http://a/bb/ccc/d;p?q', ';x', 'http://a/bb/ccc/;x');
936
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g;x', 'http://a/bb/ccc/g;x');
937
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g;x?y#s', 'http://a/bb/ccc/g;x?y#s');
938
+ itShouldResolve('http://a/bb/ccc/d;p?q', '', 'http://a/bb/ccc/d;p?q');
939
+ itShouldResolve('http://a/bb/ccc/d;p?q', '.', 'http://a/bb/ccc/');
940
+ itShouldResolve('http://a/bb/ccc/d;p?q', './', 'http://a/bb/ccc/');
941
+ itShouldResolve('http://a/bb/ccc/d;p?q', '..', 'http://a/bb/');
942
+ itShouldResolve('http://a/bb/ccc/d;p?q', '../', 'http://a/bb/');
943
+ itShouldResolve('http://a/bb/ccc/d;p?q', '../g', 'http://a/bb/g');
944
+ itShouldResolve('http://a/bb/ccc/d;p?q', '../..', 'http://a/');
945
+ itShouldResolve('http://a/bb/ccc/d;p?q', '../../', 'http://a/');
946
+ itShouldResolve('http://a/bb/ccc/d;p?q', '../../g', 'http://a/g');
947
+ });
948
+
949
+ describe('RFC3986 abnormal examples', function () {
950
+ itShouldResolve('http://a/bb/ccc/d;p?q', '../../../g', 'http://a/g');
951
+ itShouldResolve('http://a/bb/ccc/d;p?q', '../../../../g', 'http://a/g');
952
+ itShouldResolve('http://a/bb/ccc/d;p?q', '/./g', 'http://a/g');
953
+ itShouldResolve('http://a/bb/ccc/d;p?q', '/../g', 'http://a/g');
954
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g.', 'http://a/bb/ccc/g.');
955
+ itShouldResolve('http://a/bb/ccc/d;p?q', '.g', 'http://a/bb/ccc/.g');
956
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g..', 'http://a/bb/ccc/g..');
957
+ itShouldResolve('http://a/bb/ccc/d;p?q', '..g', 'http://a/bb/ccc/..g');
958
+ itShouldResolve('http://a/bb/ccc/d;p?q', './../g', 'http://a/bb/g');
959
+ itShouldResolve('http://a/bb/ccc/d;p?q', './g/.', 'http://a/bb/ccc/g/');
960
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g/./h', 'http://a/bb/ccc/g/h');
961
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g/../h', 'http://a/bb/ccc/h');
962
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g;x=1/./y', 'http://a/bb/ccc/g;x=1/y');
963
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g;x=1/../y', 'http://a/bb/ccc/y');
964
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g?y/./x', 'http://a/bb/ccc/g?y/./x');
965
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g?y/../x', 'http://a/bb/ccc/g?y/../x');
966
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g#s/./x', 'http://a/bb/ccc/g#s/./x');
967
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'g#s/../x', 'http://a/bb/ccc/g#s/../x');
968
+ itShouldResolve('http://a/bb/ccc/d;p?q', 'http:g', 'http:g');
969
+ });
970
+
971
+ describe('RFC3986 normal examples with trailing slash in base IRI', function () {
972
+ itShouldResolve('http://a/bb/ccc/d/', 'g:h', 'g:h');
973
+ itShouldResolve('http://a/bb/ccc/d/', 'g', 'http://a/bb/ccc/d/g');
974
+ itShouldResolve('http://a/bb/ccc/d/', './g', 'http://a/bb/ccc/d/g');
975
+ itShouldResolve('http://a/bb/ccc/d/', 'g/', 'http://a/bb/ccc/d/g/');
976
+ itShouldResolve('http://a/bb/ccc/d/', '/g', 'http://a/g');
977
+ itShouldResolve('http://a/bb/ccc/d/', '//g', 'http://g');
978
+ itShouldResolve('http://a/bb/ccc/d/', '?y', 'http://a/bb/ccc/d/?y');
979
+ itShouldResolve('http://a/bb/ccc/d/', 'g?y', 'http://a/bb/ccc/d/g?y');
980
+ itShouldResolve('http://a/bb/ccc/d/', '#s', 'http://a/bb/ccc/d/#s');
981
+ itShouldResolve('http://a/bb/ccc/d/', 'g#s', 'http://a/bb/ccc/d/g#s');
982
+ itShouldResolve('http://a/bb/ccc/d/', 'g?y#s', 'http://a/bb/ccc/d/g?y#s');
983
+ itShouldResolve('http://a/bb/ccc/d/', ';x', 'http://a/bb/ccc/d/;x');
984
+ itShouldResolve('http://a/bb/ccc/d/', 'g;x', 'http://a/bb/ccc/d/g;x');
985
+ itShouldResolve('http://a/bb/ccc/d/', 'g;x?y#s', 'http://a/bb/ccc/d/g;x?y#s');
986
+ itShouldResolve('http://a/bb/ccc/d/', '', 'http://a/bb/ccc/d/');
987
+ itShouldResolve('http://a/bb/ccc/d/', '.', 'http://a/bb/ccc/d/');
988
+ itShouldResolve('http://a/bb/ccc/d/', './', 'http://a/bb/ccc/d/');
989
+ itShouldResolve('http://a/bb/ccc/d/', '..', 'http://a/bb/ccc/');
990
+ itShouldResolve('http://a/bb/ccc/d/', '../', 'http://a/bb/ccc/');
991
+ itShouldResolve('http://a/bb/ccc/d/', '../g', 'http://a/bb/ccc/g');
992
+ itShouldResolve('http://a/bb/ccc/d/', '../..', 'http://a/bb/');
993
+ itShouldResolve('http://a/bb/ccc/d/', '../../', 'http://a/bb/');
994
+ itShouldResolve('http://a/bb/ccc/d/', '../../g', 'http://a/bb/g');
995
+ });
996
+
997
+ describe('RFC3986 abnormal examples with trailing slash in base IRI', function () {
998
+ itShouldResolve('http://a/bb/ccc/d/', '../../../g', 'http://a/g');
999
+ itShouldResolve('http://a/bb/ccc/d/', '../../../../g', 'http://a/g');
1000
+ itShouldResolve('http://a/bb/ccc/d/', '/./g', 'http://a/g');
1001
+ itShouldResolve('http://a/bb/ccc/d/', '/../g', 'http://a/g');
1002
+ itShouldResolve('http://a/bb/ccc/d/', 'g.', 'http://a/bb/ccc/d/g.');
1003
+ itShouldResolve('http://a/bb/ccc/d/', '.g', 'http://a/bb/ccc/d/.g');
1004
+ itShouldResolve('http://a/bb/ccc/d/', 'g..', 'http://a/bb/ccc/d/g..');
1005
+ itShouldResolve('http://a/bb/ccc/d/', '..g', 'http://a/bb/ccc/d/..g');
1006
+ itShouldResolve('http://a/bb/ccc/d/', './../g', 'http://a/bb/ccc/g');
1007
+ itShouldResolve('http://a/bb/ccc/d/', './g/.', 'http://a/bb/ccc/d/g/');
1008
+ itShouldResolve('http://a/bb/ccc/d/', 'g/./h', 'http://a/bb/ccc/d/g/h');
1009
+ itShouldResolve('http://a/bb/ccc/d/', 'g/../h', 'http://a/bb/ccc/d/h');
1010
+ itShouldResolve('http://a/bb/ccc/d/', 'g;x=1/./y', 'http://a/bb/ccc/d/g;x=1/y');
1011
+ itShouldResolve('http://a/bb/ccc/d/', 'g;x=1/../y', 'http://a/bb/ccc/d/y');
1012
+ itShouldResolve('http://a/bb/ccc/d/', 'g?y/./x', 'http://a/bb/ccc/d/g?y/./x');
1013
+ itShouldResolve('http://a/bb/ccc/d/', 'g?y/../x', 'http://a/bb/ccc/d/g?y/../x');
1014
+ itShouldResolve('http://a/bb/ccc/d/', 'g#s/./x', 'http://a/bb/ccc/d/g#s/./x');
1015
+ itShouldResolve('http://a/bb/ccc/d/', 'g#s/../x', 'http://a/bb/ccc/d/g#s/../x');
1016
+ itShouldResolve('http://a/bb/ccc/d/', 'http:g', 'http:g');
1017
+ });
1018
+
1019
+ describe('RFC3986 normal examples with /. in the base IRI', function () {
1020
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g:h', 'g:h');
1021
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g', 'http://a/bb/ccc/g');
1022
+ itShouldResolve('http://a/bb/ccc/./d;p?q', './g', 'http://a/bb/ccc/g');
1023
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g/', 'http://a/bb/ccc/g/');
1024
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '/g', 'http://a/g');
1025
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '//g', 'http://g');
1026
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '?y', 'http://a/bb/ccc/./d;p?y');
1027
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g?y', 'http://a/bb/ccc/g?y');
1028
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '#s', 'http://a/bb/ccc/./d;p?q#s');
1029
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g#s', 'http://a/bb/ccc/g#s');
1030
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g?y#s', 'http://a/bb/ccc/g?y#s');
1031
+ itShouldResolve('http://a/bb/ccc/./d;p?q', ';x', 'http://a/bb/ccc/;x');
1032
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g;x', 'http://a/bb/ccc/g;x');
1033
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g;x?y#s', 'http://a/bb/ccc/g;x?y#s');
1034
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '', 'http://a/bb/ccc/./d;p?q');
1035
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '.', 'http://a/bb/ccc/');
1036
+ itShouldResolve('http://a/bb/ccc/./d;p?q', './', 'http://a/bb/ccc/');
1037
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '..', 'http://a/bb/');
1038
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '../', 'http://a/bb/');
1039
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '../g', 'http://a/bb/g');
1040
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '../..', 'http://a/');
1041
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '../../', 'http://a/');
1042
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '../../g', 'http://a/g');
1043
+ });
1044
+
1045
+ describe('RFC3986 abnormal examples with /. in the base IRI', function () {
1046
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '../../../g', 'http://a/g');
1047
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '../../../../g', 'http://a/g');
1048
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '/./g', 'http://a/g');
1049
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '/../g', 'http://a/g');
1050
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g.', 'http://a/bb/ccc/g.');
1051
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '.g', 'http://a/bb/ccc/.g');
1052
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g..', 'http://a/bb/ccc/g..');
1053
+ itShouldResolve('http://a/bb/ccc/./d;p?q', '..g', 'http://a/bb/ccc/..g');
1054
+ itShouldResolve('http://a/bb/ccc/./d;p?q', './../g', 'http://a/bb/g');
1055
+ itShouldResolve('http://a/bb/ccc/./d;p?q', './g/.', 'http://a/bb/ccc/g/');
1056
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g/./h', 'http://a/bb/ccc/g/h');
1057
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g/../h', 'http://a/bb/ccc/h');
1058
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g;x=1/./y', 'http://a/bb/ccc/g;x=1/y');
1059
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g;x=1/../y', 'http://a/bb/ccc/y');
1060
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g?y/./x', 'http://a/bb/ccc/g?y/./x');
1061
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g?y/../x', 'http://a/bb/ccc/g?y/../x');
1062
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g#s/./x', 'http://a/bb/ccc/g#s/./x');
1063
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'g#s/../x', 'http://a/bb/ccc/g#s/../x');
1064
+ itShouldResolve('http://a/bb/ccc/./d;p?q', 'http:g', 'http:g');
1065
+ });
1066
+
1067
+ describe('RFC3986 normal examples with /.. in the base IRI', function () {
1068
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g:h', 'g:h');
1069
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g', 'http://a/bb/g');
1070
+ itShouldResolve('http://a/bb/ccc/../d;p?q', './g', 'http://a/bb/g');
1071
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g/', 'http://a/bb/g/');
1072
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '/g', 'http://a/g');
1073
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '//g', 'http://g');
1074
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '?y', 'http://a/bb/ccc/../d;p?y');
1075
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g?y', 'http://a/bb/g?y');
1076
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '#s', 'http://a/bb/ccc/../d;p?q#s');
1077
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g#s', 'http://a/bb/g#s');
1078
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g?y#s', 'http://a/bb/g?y#s');
1079
+ itShouldResolve('http://a/bb/ccc/../d;p?q', ';x', 'http://a/bb/;x');
1080
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g;x', 'http://a/bb/g;x');
1081
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g;x?y#s', 'http://a/bb/g;x?y#s');
1082
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '', 'http://a/bb/ccc/../d;p?q');
1083
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '.', 'http://a/bb/');
1084
+ itShouldResolve('http://a/bb/ccc/../d;p?q', './', 'http://a/bb/');
1085
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '..', 'http://a/');
1086
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '../', 'http://a/');
1087
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '../g', 'http://a/g');
1088
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '../..', 'http://a/');
1089
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '../../', 'http://a/');
1090
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '../../g', 'http://a/g');
1091
+ });
1092
+
1093
+ describe('RFC3986 abnormal examples with /.. in the base IRI', function () {
1094
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '../../../g', 'http://a/g');
1095
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '../../../../g', 'http://a/g');
1096
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '/./g', 'http://a/g');
1097
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '/../g', 'http://a/g');
1098
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g.', 'http://a/bb/g.');
1099
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '.g', 'http://a/bb/.g');
1100
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g..', 'http://a/bb/g..');
1101
+ itShouldResolve('http://a/bb/ccc/../d;p?q', '..g', 'http://a/bb/..g');
1102
+ itShouldResolve('http://a/bb/ccc/../d;p?q', './../g', 'http://a/g');
1103
+ itShouldResolve('http://a/bb/ccc/../d;p?q', './g/.', 'http://a/bb/g/');
1104
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g/./h', 'http://a/bb/g/h');
1105
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g/../h', 'http://a/bb/h');
1106
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g;x=1/./y', 'http://a/bb/g;x=1/y');
1107
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g;x=1/../y', 'http://a/bb/y');
1108
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g?y/./x', 'http://a/bb/g?y/./x');
1109
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g?y/../x', 'http://a/bb/g?y/../x');
1110
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g#s/./x', 'http://a/bb/g#s/./x');
1111
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'g#s/../x', 'http://a/bb/g#s/../x');
1112
+ itShouldResolve('http://a/bb/ccc/../d;p?q', 'http:g', 'http:g');
1113
+ });
1114
+
1115
+ describe('RFC3986 normal examples with trailing /. in the base IRI', function () {
1116
+ itShouldResolve('http://a/bb/ccc/.', 'g:h', 'g:h');
1117
+ itShouldResolve('http://a/bb/ccc/.', 'g', 'http://a/bb/ccc/g');
1118
+ itShouldResolve('http://a/bb/ccc/.', './g', 'http://a/bb/ccc/g');
1119
+ itShouldResolve('http://a/bb/ccc/.', 'g/', 'http://a/bb/ccc/g/');
1120
+ itShouldResolve('http://a/bb/ccc/.', '/g', 'http://a/g');
1121
+ itShouldResolve('http://a/bb/ccc/.', '//g', 'http://g');
1122
+ itShouldResolve('http://a/bb/ccc/.', '?y', 'http://a/bb/ccc/.?y');
1123
+ itShouldResolve('http://a/bb/ccc/.', 'g?y', 'http://a/bb/ccc/g?y');
1124
+ itShouldResolve('http://a/bb/ccc/.', '#s', 'http://a/bb/ccc/.#s');
1125
+ itShouldResolve('http://a/bb/ccc/.', 'g#s', 'http://a/bb/ccc/g#s');
1126
+ itShouldResolve('http://a/bb/ccc/.', 'g?y#s', 'http://a/bb/ccc/g?y#s');
1127
+ itShouldResolve('http://a/bb/ccc/.', ';x', 'http://a/bb/ccc/;x');
1128
+ itShouldResolve('http://a/bb/ccc/.', 'g;x', 'http://a/bb/ccc/g;x');
1129
+ itShouldResolve('http://a/bb/ccc/.', 'g;x?y#s', 'http://a/bb/ccc/g;x?y#s');
1130
+ itShouldResolve('http://a/bb/ccc/.', '', 'http://a/bb/ccc/.');
1131
+ itShouldResolve('http://a/bb/ccc/.', '.', 'http://a/bb/ccc/');
1132
+ itShouldResolve('http://a/bb/ccc/.', './', 'http://a/bb/ccc/');
1133
+ itShouldResolve('http://a/bb/ccc/.', '..', 'http://a/bb/');
1134
+ itShouldResolve('http://a/bb/ccc/.', '../', 'http://a/bb/');
1135
+ itShouldResolve('http://a/bb/ccc/.', '../g', 'http://a/bb/g');
1136
+ itShouldResolve('http://a/bb/ccc/.', '../..', 'http://a/');
1137
+ itShouldResolve('http://a/bb/ccc/.', '../../', 'http://a/');
1138
+ itShouldResolve('http://a/bb/ccc/.', '../../g', 'http://a/g');
1139
+ });
1140
+
1141
+ describe('RFC3986 abnormal examples with trailing /. in the base IRI', function () {
1142
+ itShouldResolve('http://a/bb/ccc/.', '../../../g', 'http://a/g');
1143
+ itShouldResolve('http://a/bb/ccc/.', '../../../../g', 'http://a/g');
1144
+ itShouldResolve('http://a/bb/ccc/.', '/./g', 'http://a/g');
1145
+ itShouldResolve('http://a/bb/ccc/.', '/../g', 'http://a/g');
1146
+ itShouldResolve('http://a/bb/ccc/.', 'g.', 'http://a/bb/ccc/g.');
1147
+ itShouldResolve('http://a/bb/ccc/.', '.g', 'http://a/bb/ccc/.g');
1148
+ itShouldResolve('http://a/bb/ccc/.', 'g..', 'http://a/bb/ccc/g..');
1149
+ itShouldResolve('http://a/bb/ccc/.', '..g', 'http://a/bb/ccc/..g');
1150
+ itShouldResolve('http://a/bb/ccc/.', './../g', 'http://a/bb/g');
1151
+ itShouldResolve('http://a/bb/ccc/.', './g/.', 'http://a/bb/ccc/g/');
1152
+ itShouldResolve('http://a/bb/ccc/.', 'g/./h', 'http://a/bb/ccc/g/h');
1153
+ itShouldResolve('http://a/bb/ccc/.', 'g/../h', 'http://a/bb/ccc/h');
1154
+ itShouldResolve('http://a/bb/ccc/.', 'g;x=1/./y', 'http://a/bb/ccc/g;x=1/y');
1155
+ itShouldResolve('http://a/bb/ccc/.', 'g;x=1/../y', 'http://a/bb/ccc/y');
1156
+ itShouldResolve('http://a/bb/ccc/.', 'g?y/./x', 'http://a/bb/ccc/g?y/./x');
1157
+ itShouldResolve('http://a/bb/ccc/.', 'g?y/../x', 'http://a/bb/ccc/g?y/../x');
1158
+ itShouldResolve('http://a/bb/ccc/.', 'g#s/./x', 'http://a/bb/ccc/g#s/./x');
1159
+ itShouldResolve('http://a/bb/ccc/.', 'g#s/../x', 'http://a/bb/ccc/g#s/../x');
1160
+ itShouldResolve('http://a/bb/ccc/.', 'http:g', 'http:g');
1161
+ });
1162
+
1163
+ describe('RFC3986 normal examples with trailing /.. in the base IRI', function () {
1164
+ itShouldResolve('http://a/bb/ccc/..', 'g:h', 'g:h');
1165
+ itShouldResolve('http://a/bb/ccc/..', 'g', 'http://a/bb/ccc/g');
1166
+ itShouldResolve('http://a/bb/ccc/..', './g', 'http://a/bb/ccc/g');
1167
+ itShouldResolve('http://a/bb/ccc/..', 'g/', 'http://a/bb/ccc/g/');
1168
+ itShouldResolve('http://a/bb/ccc/..', '/g', 'http://a/g');
1169
+ itShouldResolve('http://a/bb/ccc/..', '//g', 'http://g');
1170
+ itShouldResolve('http://a/bb/ccc/..', '?y', 'http://a/bb/ccc/..?y');
1171
+ itShouldResolve('http://a/bb/ccc/..', 'g?y', 'http://a/bb/ccc/g?y');
1172
+ itShouldResolve('http://a/bb/ccc/..', '#s', 'http://a/bb/ccc/..#s');
1173
+ itShouldResolve('http://a/bb/ccc/..', 'g#s', 'http://a/bb/ccc/g#s');
1174
+ itShouldResolve('http://a/bb/ccc/..', 'g?y#s', 'http://a/bb/ccc/g?y#s');
1175
+ itShouldResolve('http://a/bb/ccc/..', ';x', 'http://a/bb/ccc/;x');
1176
+ itShouldResolve('http://a/bb/ccc/..', 'g;x', 'http://a/bb/ccc/g;x');
1177
+ itShouldResolve('http://a/bb/ccc/..', 'g;x?y#s', 'http://a/bb/ccc/g;x?y#s');
1178
+ itShouldResolve('http://a/bb/ccc/..', '', 'http://a/bb/ccc/..');
1179
+ itShouldResolve('http://a/bb/ccc/..', '.', 'http://a/bb/ccc/');
1180
+ itShouldResolve('http://a/bb/ccc/..', './', 'http://a/bb/ccc/');
1181
+ itShouldResolve('http://a/bb/ccc/..', '..', 'http://a/bb/');
1182
+ itShouldResolve('http://a/bb/ccc/..', '../', 'http://a/bb/');
1183
+ itShouldResolve('http://a/bb/ccc/..', '../g', 'http://a/bb/g');
1184
+ itShouldResolve('http://a/bb/ccc/..', '../..', 'http://a/');
1185
+ itShouldResolve('http://a/bb/ccc/..', '../../', 'http://a/');
1186
+ itShouldResolve('http://a/bb/ccc/..', '../../g', 'http://a/g');
1187
+ });
1188
+
1189
+ describe('RFC3986 abnormal examples with trailing /.. in the base IRI', function () {
1190
+ itShouldResolve('http://a/bb/ccc/..', '../../../g', 'http://a/g');
1191
+ itShouldResolve('http://a/bb/ccc/..', '../../../../g', 'http://a/g');
1192
+ itShouldResolve('http://a/bb/ccc/..', '/./g', 'http://a/g');
1193
+ itShouldResolve('http://a/bb/ccc/..', '/../g', 'http://a/g');
1194
+ itShouldResolve('http://a/bb/ccc/..', 'g.', 'http://a/bb/ccc/g.');
1195
+ itShouldResolve('http://a/bb/ccc/..', '.g', 'http://a/bb/ccc/.g');
1196
+ itShouldResolve('http://a/bb/ccc/..', 'g..', 'http://a/bb/ccc/g..');
1197
+ itShouldResolve('http://a/bb/ccc/..', '..g', 'http://a/bb/ccc/..g');
1198
+ itShouldResolve('http://a/bb/ccc/..', './../g', 'http://a/bb/g');
1199
+ itShouldResolve('http://a/bb/ccc/..', './g/.', 'http://a/bb/ccc/g/');
1200
+ itShouldResolve('http://a/bb/ccc/..', 'g/./h', 'http://a/bb/ccc/g/h');
1201
+ itShouldResolve('http://a/bb/ccc/..', 'g/../h', 'http://a/bb/ccc/h');
1202
+ itShouldResolve('http://a/bb/ccc/..', 'g;x=1/./y', 'http://a/bb/ccc/g;x=1/y');
1203
+ itShouldResolve('http://a/bb/ccc/..', 'g;x=1/../y', 'http://a/bb/ccc/y');
1204
+ itShouldResolve('http://a/bb/ccc/..', 'g?y/./x', 'http://a/bb/ccc/g?y/./x');
1205
+ itShouldResolve('http://a/bb/ccc/..', 'g?y/../x', 'http://a/bb/ccc/g?y/../x');
1206
+ itShouldResolve('http://a/bb/ccc/..', 'g#s/./x', 'http://a/bb/ccc/g#s/./x');
1207
+ itShouldResolve('http://a/bb/ccc/..', 'g#s/../x', 'http://a/bb/ccc/g#s/../x');
1208
+ itShouldResolve('http://a/bb/ccc/..', 'http:g', 'http:g');
1209
+ });
1210
+
1211
+ describe('RFC3986 normal examples with file path', function () {
1212
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g:h', 'g:h');
1213
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g', 'file:///a/bb/ccc/g');
1214
+ itShouldResolve('file:///a/bb/ccc/d;p?q', './g', 'file:///a/bb/ccc/g');
1215
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g/', 'file:///a/bb/ccc/g/');
1216
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '/g', 'file:///g');
1217
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '//g', 'file://g');
1218
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '?y', 'file:///a/bb/ccc/d;p?y');
1219
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g?y', 'file:///a/bb/ccc/g?y');
1220
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '#s', 'file:///a/bb/ccc/d;p?q#s');
1221
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g#s', 'file:///a/bb/ccc/g#s');
1222
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g?y#s', 'file:///a/bb/ccc/g?y#s');
1223
+ itShouldResolve('file:///a/bb/ccc/d;p?q', ';x', 'file:///a/bb/ccc/;x');
1224
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g;x', 'file:///a/bb/ccc/g;x');
1225
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g;x?y#s', 'file:///a/bb/ccc/g;x?y#s');
1226
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '', 'file:///a/bb/ccc/d;p?q');
1227
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '.', 'file:///a/bb/ccc/');
1228
+ itShouldResolve('file:///a/bb/ccc/d;p?q', './', 'file:///a/bb/ccc/');
1229
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '..', 'file:///a/bb/');
1230
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '../', 'file:///a/bb/');
1231
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '../g', 'file:///a/bb/g');
1232
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '../..', 'file:///a/');
1233
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '../../', 'file:///a/');
1234
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '../../g', 'file:///a/g');
1235
+ });
1236
+
1237
+ describe('RFC3986 abnormal examples with file path', function () {
1238
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '../../../g', 'file:///g');
1239
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '../../../../g', 'file:///g');
1240
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '/./g', 'file:///g');
1241
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '/../g', 'file:///g');
1242
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g.', 'file:///a/bb/ccc/g.');
1243
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '.g', 'file:///a/bb/ccc/.g');
1244
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g..', 'file:///a/bb/ccc/g..');
1245
+ itShouldResolve('file:///a/bb/ccc/d;p?q', '..g', 'file:///a/bb/ccc/..g');
1246
+ itShouldResolve('file:///a/bb/ccc/d;p?q', './../g', 'file:///a/bb/g');
1247
+ itShouldResolve('file:///a/bb/ccc/d;p?q', './g/.', 'file:///a/bb/ccc/g/');
1248
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g/./h', 'file:///a/bb/ccc/g/h');
1249
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g/../h', 'file:///a/bb/ccc/h');
1250
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g;x=1/./y', 'file:///a/bb/ccc/g;x=1/y');
1251
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g;x=1/../y', 'file:///a/bb/ccc/y');
1252
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g?y/./x', 'file:///a/bb/ccc/g?y/./x');
1253
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g?y/../x', 'file:///a/bb/ccc/g?y/../x');
1254
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g#s/./x', 'file:///a/bb/ccc/g#s/./x');
1255
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'g#s/../x', 'file:///a/bb/ccc/g#s/../x');
1256
+ itShouldResolve('file:///a/bb/ccc/d;p?q', 'http:g', 'http:g');
1257
+ });
1258
+
1259
+ describe('additional cases', function () {
1260
+ // relative paths ending with '.'
1261
+ itShouldResolve('http://abc/', '.', 'http://abc/');
1262
+ itShouldResolve('http://abc/def/ghi', '.', 'http://abc/def/');
1263
+ itShouldResolve('http://abc/def/ghi', '.?a=b', 'http://abc/def/?a=b');
1264
+ itShouldResolve('http://abc/def/ghi', '.#a=b', 'http://abc/def/#a=b');
1265
+
1266
+ // relative paths ending with '..'
1267
+ itShouldResolve('http://abc/', '..', 'http://abc/');
1268
+ itShouldResolve('http://abc/def/ghi', '..', 'http://abc/');
1269
+ itShouldResolve('http://abc/def/ghi', '..?a=b', 'http://abc/?a=b');
1270
+ itShouldResolve('http://abc/def/ghi', '..#a=b', 'http://abc/#a=b');
1271
+
1272
+ // base path with empty subpaths (double slashes)
1273
+ itShouldResolve('http://ab//de//ghi', 'xyz', 'http://ab//de//xyz');
1274
+ itShouldResolve('http://ab//de//ghi', './xyz', 'http://ab//de//xyz');
1275
+ itShouldResolve('http://ab//de//ghi', '../xyz', 'http://ab//de/xyz');
1276
+
1277
+ // base path with colon (possible confusion with scheme)
1278
+ itShouldResolve('http://abc/d:f/ghi', 'xyz', 'http://abc/d:f/xyz');
1279
+ itShouldResolve('http://abc/d:f/ghi', './xyz', 'http://abc/d:f/xyz');
1280
+ itShouldResolve('http://abc/d:f/ghi', '../xyz', 'http://abc/xyz');
1281
+
1282
+ // base path consisting of '..' and/or '../' sequences
1283
+ itShouldResolve('./', 'abc', '/abc');
1284
+ itShouldResolve('../', 'abc', '/abc');
1285
+ itShouldResolve('./././', '././abc', '/abc');
1286
+ itShouldResolve('../../../', '../../abc', '/abc');
1287
+ itShouldResolve('.../././', '././abc', '.../abc');
1288
+
1289
+ // base path without authority
1290
+ itShouldResolve('a:b:c/', 'def/../', 'a:b:c/');
1291
+ itShouldResolve('a:b:c', '/def', 'a:/def');
1292
+ itShouldResolve('a:b/c', '/def', 'a:/def');
1293
+ itShouldResolve('a:', '/.', 'a:/');
1294
+ itShouldResolve('a:', '/..', 'a:/');
1295
+
1296
+ // base path with slashes in query string
1297
+ itShouldResolve('http://abc/def/ghi?q=xx/yyy/z', 'jjj', 'http://abc/def/jjj');
1298
+ itShouldResolve('http://abc/def/ghi?q=xx/y?y/z', 'jjj', 'http://abc/def/jjj');
1299
+ });
1300
+ });
853
1301
  });
854
1302
 
855
1303
  function shouldParse(parser, input) {
@@ -893,7 +1341,27 @@ function shouldNotParse(parser, input, expectedError) {
893
1341
  done();
894
1342
  }
895
1343
  else if (!triple)
896
- throw new Error("Expected error " + expectedError);
1344
+ throw new Error('Expected error ' + expectedError);
897
1345
  });
898
1346
  };
899
1347
  }
1348
+
1349
+ function itShouldResolve(baseIri, relativeIri, expected) {
1350
+ var result;
1351
+ describe('resolving <' + relativeIri + '> against <' + baseIri + '>', function () {
1352
+ before(function (done) {
1353
+ try {
1354
+ var doc = '<urn:ex:s> <urn:ex:p> <' + relativeIri + '>.';
1355
+ new N3Parser({ documentIRI: baseIri }).parse(doc, function (error, triple) {
1356
+ if (done)
1357
+ result = triple, done(error);
1358
+ done = null;
1359
+ });
1360
+ }
1361
+ catch (error) { done(error); }
1362
+ });
1363
+ it('should result in ' + expected, function () {
1364
+ expect(result.object).to.equal(expected);
1365
+ });
1366
+ });
1367
+ }