|
1 | 1 | const test = require('tape');
|
2 | 2 | const fn = require('../dist/regexparam');
|
3 | 3 |
|
| 4 | +const hasNamedGroups = 'groups' in /x/.exec('x'); |
| 5 | + |
4 | 6 | function run(route, url, loose) {
|
5 | 7 | let i=0, out={}, result=fn(route, !!loose);
|
6 | 8 | let matches = result.pattern.exec(url);
|
@@ -583,186 +585,171 @@ test('(RegExp) static', t => {
|
583 | 585 | t.end();
|
584 | 586 | });
|
585 | 587 |
|
586 |
| -test('(RegExp) param', t => { |
587 |
| - let rgx = /^\/(?<year>[0-9]{4})/i; |
588 |
| - let { keys, pattern } = fn(rgx); |
589 |
| - t.same(keys, false, '~> keys = false'); |
590 |
| - t.same(rgx, pattern, '~> pattern = input'); |
591 |
| - |
592 |
| - // RegExp testing (not regexparam related) |
593 |
| - t.false(pattern.test('/123'), '~> does not match 3-digit string'); |
594 |
| - t.false(pattern.test('/asdf'), '~> does not match 4 alpha characters'); |
595 |
| - t.true(pattern.test('/2019'), '~> matches definition'); |
596 |
| - t.true(pattern.test('/2019/'), '~> matches definition w/ trailing slash'); |
597 |
| - t.false(pattern.test('2019'), '~> does not match without lead slash'); |
598 |
| - t.true(pattern.test('/2019/narnia/hello'), '~> allows extra bits'); |
599 |
| - |
600 |
| - // exec results, array access |
601 |
| - let [url, value] = pattern.exec('/2019/books'); |
602 |
| - t.is(url, '/2019', '~> executing pattern on correct trimming'); |
603 |
| - t.is(value, '2019', '~> executing pattern gives correct value'); |
604 |
| - |
605 |
| - // exec results, named object |
606 |
| - t.toExec(rgx, '/2019/books', { year: '2019' }); |
607 |
| - t.toExec(rgx, '/2019/books/narnia', { year: '2019' }); |
608 |
| - |
609 |
| - t.end(); |
610 |
| -}); |
611 |
| - |
612 |
| -test('(RegExp) param :: w/ static', t => { |
613 |
| - let rgx = /^\/books\/(?<title>[a-z]+)/i; |
614 |
| - let { keys, pattern } = fn(rgx); |
615 |
| - t.same(keys, false, '~> keys = false'); |
616 |
| - t.same(rgx, pattern, '~> pattern = input'); |
617 |
| - |
618 |
| - // RegExp testing (not regexparam related) |
619 |
| - t.false(pattern.test('/books'), '~> does not match naked base'); |
620 |
| - t.false(pattern.test('/books/'), '~> does not match naked base w/ trailing slash'); |
621 |
| - t.true(pattern.test('/books/narnia'), '~> matches definition'); |
622 |
| - t.true(pattern.test('/books/narnia/'), '~> matches definition w/ trailing slash'); |
623 |
| - t.true(pattern.test('/books/narnia/hello'), '~> allows extra bits'); |
624 |
| - t.false(pattern.test('books/narnia'), '~> does not match path without lead slash'); |
625 |
| - |
626 |
| - // exec results, array access |
627 |
| - let [url, value] = pattern.exec('/books/narnia'); |
628 |
| - t.is(url, '/books/narnia', '~> executing pattern on correct trimming'); |
629 |
| - t.is(value, 'narnia', '~> executing pattern gives correct value'); |
630 |
| - |
631 |
| - // exec results, named object |
632 |
| - t.toExec(rgx, '/books/narnia', { title: 'narnia' }); |
633 |
| - t.toExec(rgx, '/books/narnia/hello', { title: 'narnia' }); |
634 |
| - |
635 |
| - t.end(); |
636 |
| -}); |
637 |
| - |
638 |
| -test('(RegExp) param :: multiple', t => { |
639 |
| - let rgx = /^\/(?<year>[0-9]{4})-(?<month>[0-9]{2})\/(?<day>[0-9]{2})/i; |
640 |
| - let { keys, pattern } = fn(rgx); |
641 |
| - t.same(keys, false, '~> keys = false'); |
642 |
| - t.same(rgx, pattern, '~> pattern = input'); |
643 |
| - |
644 |
| - // RegExp testing (not regexparam related) |
645 |
| - t.false(pattern.test('/123-1')); |
646 |
| - t.false(pattern.test('/123-10')); |
647 |
| - t.false(pattern.test('/1234-10')); |
648 |
| - t.false(pattern.test('/1234-10/1')); |
649 |
| - t.false(pattern.test('/1234-10/as')); |
650 |
| - t.true(pattern.test('/1234-10/01/')); |
651 |
| - t.true(pattern.test('/2019-10/30')); |
652 |
| - |
653 |
| - // exec results, array access |
654 |
| - let [url, year, month, day] = pattern.exec('/2019-05/30/'); |
655 |
| - t.is(url, '/2019-05/30', '~> executing pattern on correct trimming'); |
656 |
| - t.is(year, '2019', '~> executing pattern gives correct "year" value'); |
657 |
| - t.is(month, '05', '~> executing pattern gives correct "month" value'); |
658 |
| - t.is(day, '30', '~> executing pattern gives correct "day" value'); |
659 |
| - |
660 |
| - // exec results, named object |
661 |
| - t.toExec(rgx, '/2019-10/02', { year:'2019', month:'10', day:'02' }); |
662 |
| - t.toExec(rgx, '/2019-10/02/narnia', { year:'2019', month:'10', day:'02' }); |
663 |
| - |
664 |
| - t.end(); |
665 |
| -}); |
666 |
| - |
667 |
| -test('(RegExp) param :: suffix', t => { |
668 |
| - let rgx = /^\/movies[/](?<title>\w+)\.mp4/i; |
669 |
| - let { keys, pattern } = fn(rgx); |
670 |
| - t.same(keys, false, '~> keys = false'); |
671 |
| - t.same(rgx, pattern, '~> pattern = input'); |
672 |
| - |
673 |
| - // RegExp testing (not regexparam related) |
674 |
| - t.false(pattern.test('/movies')); |
675 |
| - t.false(pattern.test('/movies/')); |
676 |
| - t.false(pattern.test('/movies/foo')); |
677 |
| - t.false(pattern.test('/movies/foo.mp3')); |
678 |
| - t.true(pattern.test('/movies/foo.mp4')); |
679 |
| - t.true(pattern.test('/movies/foo.mp4/')); |
680 |
| - |
681 |
| - // exec results, array access |
682 |
| - let [url, title] = pattern.exec('/movies/narnia.mp4'); |
683 |
| - t.is(url, '/movies/narnia.mp4', '~> executing pattern on correct trimming'); |
684 |
| - t.is(title, 'narnia', '~> executing pattern gives correct "title" value'); |
685 |
| - |
686 |
| - // exec results, named object |
687 |
| - t.toExec(rgx, '/movies/narnia.mp4', { title: 'narnia' }); |
688 |
| - t.toExec(rgx, '/movies/narnia.mp4/', { title: 'narnia' }); |
689 |
| - |
690 |
| - t.end(); |
691 |
| -}); |
692 |
| - |
693 |
| -test('(RegExp) param :: suffices', t => { |
694 |
| - let rgx = /^\/movies[/](?<title>\w+)\.(mp4|mov)/i; |
695 |
| - let { keys, pattern } = fn(rgx); |
696 |
| - t.same(keys, false, '~> keys = false'); |
697 |
| - t.same(rgx, pattern, '~> pattern = input'); |
698 |
| - |
699 |
| - // RegExp testing (not regexparam related) |
700 |
| - t.false(pattern.test('/movies')); |
701 |
| - t.false(pattern.test('/movies/')); |
702 |
| - t.false(pattern.test('/movies/foo')); |
703 |
| - t.false(pattern.test('/movies/foo.mp3')); |
704 |
| - t.true(pattern.test('/movies/foo.mp4')); |
705 |
| - t.true(pattern.test('/movies/foo.mp4/')); |
706 |
| - t.true(pattern.test('/movies/foo.mov/')); |
707 |
| - |
708 |
| - // exec results, array access |
709 |
| - let [url, title] = pattern.exec('/movies/narnia.mov'); |
710 |
| - t.is(url, '/movies/narnia.mov', '~> executing pattern on correct trimming'); |
711 |
| - t.is(title, 'narnia', '~> executing pattern gives correct "title" value'); |
712 |
| - |
713 |
| - // exec results, named object |
714 |
| - t.toExec(rgx, '/movies/narnia.mov', { title: 'narnia' }); |
715 |
| - t.toExec(rgx, '/movies/narnia.mov/', { title: 'narnia' }); |
716 |
| - |
717 |
| - t.end(); |
718 |
| -}); |
719 |
| - |
720 |
| -test('(RegExp) param :: optional', t => { |
721 |
| - let rgx = /^\/books[/](?<author>[^/]+)[/]?(?<title>[^/]+)?[/]?$/ |
722 |
| - let { keys, pattern } = fn(rgx); |
723 |
| - t.same(keys, false, '~> keys = false'); |
724 |
| - t.same(rgx, pattern, '~> pattern = input'); |
725 |
| - |
726 |
| - // RegExp testing (not regexparam related) |
727 |
| - t.false(pattern.test('/books')); |
728 |
| - t.false(pattern.test('/books/')); |
729 |
| - t.true(pattern.test('/books/smith')); |
730 |
| - t.true(pattern.test('/books/smith/')); |
731 |
| - t.true(pattern.test('/books/smith/narnia')); |
732 |
| - t.true(pattern.test('/books/smith/narnia/')); |
733 |
| - t.false(pattern.test('/books/smith/narnia/reviews')); |
734 |
| - t.false(pattern.test('books/smith/narnia')); |
735 |
| - |
736 |
| - // exec results, array access |
737 |
| - let [url, author, title] = pattern.exec('/books/smith/narnia/'); |
738 |
| - t.is(url, '/books/smith/narnia/', '~> executing pattern on correct trimming'); |
739 |
| - t.is(author, 'smith', '~> executing pattern gives correct value'); |
740 |
| - t.is(title, 'narnia', '~> executing pattern gives correct value'); |
741 |
| - |
742 |
| - // exec results, named object |
743 |
| - t.toExec(rgx, '/books/smith/narnia', { author: 'smith', title: 'narnia' }); |
744 |
| - t.toExec(rgx, '/books/smith/narnia/', { author: 'smith', title: 'narnia' }); |
745 |
| - t.toExec(rgx, '/books/smith/', { author: 'smith', title: undefined }); |
746 |
| - |
747 |
| - t.end(); |
748 |
| -}); |
749 |
| - |
750 |
| -test('param :: optional', t => { |
751 |
| - let { keys, pattern } = fn('/books/:author/:title?'); |
752 |
| - t.same(keys, ['author', 'title'], '~> keys has "author" & "title" values'); |
753 |
| - t.false(pattern.test('/books'), '~> does not match naked base'); |
754 |
| - t.false(pattern.test('/books/'), '~> does not match naked base w/ trailing slash'); |
755 |
| - t.true(pattern.test('/books/smith'), '~> matches when optional parameter is missing counts'); |
756 |
| - t.true(pattern.test('/books/smith/'), '~> matches when optional paramter is missing w/ trailing slash'); |
757 |
| - t.true(pattern.test('/books/smith/narnia'), '~> matches when fully populated'); |
758 |
| - t.true(pattern.test('/books/smith/narnia/'), '~> matches when fully populated w/ trailing slash'); |
759 |
| - t.false(pattern.test('/books/smith/narnia/reviews'), '~> does not match extra bits'); |
760 |
| - t.false(pattern.test('books/smith/narnia'), '~> does not match path without lead slash'); |
761 |
| - let [_, author, title] = pattern.exec('/books/smith/narnia'); |
762 |
| - t.is(author, 'smith', '~> executing pattern gives correct value'); |
763 |
| - t.is(title, 'narnia', '~> executing pattern gives correct value'); |
764 |
| - t.end(); |
765 |
| -}); |
| 588 | +if (hasNamedGroups) { |
| 589 | + test('(RegExp) param', t => { |
| 590 | + let rgx = /^\/(?<year>[0-9]{4})/i; |
| 591 | + let { keys, pattern } = fn(rgx); |
| 592 | + t.same(keys, false, '~> keys = false'); |
| 593 | + t.same(rgx, pattern, '~> pattern = input'); |
| 594 | + |
| 595 | + // RegExp testing (not regexparam related) |
| 596 | + t.false(pattern.test('/123'), '~> does not match 3-digit string'); |
| 597 | + t.false(pattern.test('/asdf'), '~> does not match 4 alpha characters'); |
| 598 | + t.true(pattern.test('/2019'), '~> matches definition'); |
| 599 | + t.true(pattern.test('/2019/'), '~> matches definition w/ trailing slash'); |
| 600 | + t.false(pattern.test('2019'), '~> does not match without lead slash'); |
| 601 | + t.true(pattern.test('/2019/narnia/hello'), '~> allows extra bits'); |
| 602 | + |
| 603 | + // exec results, array access |
| 604 | + let [url, value] = pattern.exec('/2019/books'); |
| 605 | + t.is(url, '/2019', '~> executing pattern on correct trimming'); |
| 606 | + t.is(value, '2019', '~> executing pattern gives correct value'); |
| 607 | + |
| 608 | + // exec results, named object |
| 609 | + t.toExec(rgx, '/2019/books', { year: '2019' }); |
| 610 | + t.toExec(rgx, '/2019/books/narnia', { year: '2019' }); |
| 611 | + |
| 612 | + t.end(); |
| 613 | + }); |
| 614 | + |
| 615 | + test('(RegExp) param :: w/ static', t => { |
| 616 | + let rgx = /^\/books\/(?<title>[a-z]+)/i; |
| 617 | + let { keys, pattern } = fn(rgx); |
| 618 | + t.same(keys, false, '~> keys = false'); |
| 619 | + t.same(rgx, pattern, '~> pattern = input'); |
| 620 | + |
| 621 | + // RegExp testing (not regexparam related) |
| 622 | + t.false(pattern.test('/books'), '~> does not match naked base'); |
| 623 | + t.false(pattern.test('/books/'), '~> does not match naked base w/ trailing slash'); |
| 624 | + t.true(pattern.test('/books/narnia'), '~> matches definition'); |
| 625 | + t.true(pattern.test('/books/narnia/'), '~> matches definition w/ trailing slash'); |
| 626 | + t.true(pattern.test('/books/narnia/hello'), '~> allows extra bits'); |
| 627 | + t.false(pattern.test('books/narnia'), '~> does not match path without lead slash'); |
| 628 | + |
| 629 | + // exec results, array access |
| 630 | + let [url, value] = pattern.exec('/books/narnia'); |
| 631 | + t.is(url, '/books/narnia', '~> executing pattern on correct trimming'); |
| 632 | + t.is(value, 'narnia', '~> executing pattern gives correct value'); |
| 633 | + |
| 634 | + // exec results, named object |
| 635 | + t.toExec(rgx, '/books/narnia', { title: 'narnia' }); |
| 636 | + t.toExec(rgx, '/books/narnia/hello', { title: 'narnia' }); |
| 637 | + |
| 638 | + t.end(); |
| 639 | + }); |
| 640 | + |
| 641 | + test('(RegExp) param :: multiple', t => { |
| 642 | + let rgx = /^\/(?<year>[0-9]{4})-(?<month>[0-9]{2})\/(?<day>[0-9]{2})/i; |
| 643 | + let { keys, pattern } = fn(rgx); |
| 644 | + t.same(keys, false, '~> keys = false'); |
| 645 | + t.same(rgx, pattern, '~> pattern = input'); |
| 646 | + |
| 647 | + // RegExp testing (not regexparam related) |
| 648 | + t.false(pattern.test('/123-1')); |
| 649 | + t.false(pattern.test('/123-10')); |
| 650 | + t.false(pattern.test('/1234-10')); |
| 651 | + t.false(pattern.test('/1234-10/1')); |
| 652 | + t.false(pattern.test('/1234-10/as')); |
| 653 | + t.true(pattern.test('/1234-10/01/')); |
| 654 | + t.true(pattern.test('/2019-10/30')); |
| 655 | + |
| 656 | + // exec results, array access |
| 657 | + let [url, year, month, day] = pattern.exec('/2019-05/30/'); |
| 658 | + t.is(url, '/2019-05/30', '~> executing pattern on correct trimming'); |
| 659 | + t.is(year, '2019', '~> executing pattern gives correct "year" value'); |
| 660 | + t.is(month, '05', '~> executing pattern gives correct "month" value'); |
| 661 | + t.is(day, '30', '~> executing pattern gives correct "day" value'); |
| 662 | + |
| 663 | + // exec results, named object |
| 664 | + t.toExec(rgx, '/2019-10/02', { year:'2019', month:'10', day:'02' }); |
| 665 | + t.toExec(rgx, '/2019-10/02/narnia', { year:'2019', month:'10', day:'02' }); |
| 666 | + |
| 667 | + t.end(); |
| 668 | + }); |
| 669 | + |
| 670 | + test('(RegExp) param :: suffix', t => { |
| 671 | + let rgx = /^\/movies[/](?<title>\w+)\.mp4/i; |
| 672 | + let { keys, pattern } = fn(rgx); |
| 673 | + t.same(keys, false, '~> keys = false'); |
| 674 | + t.same(rgx, pattern, '~> pattern = input'); |
| 675 | + |
| 676 | + // RegExp testing (not regexparam related) |
| 677 | + t.false(pattern.test('/movies')); |
| 678 | + t.false(pattern.test('/movies/')); |
| 679 | + t.false(pattern.test('/movies/foo')); |
| 680 | + t.false(pattern.test('/movies/foo.mp3')); |
| 681 | + t.true(pattern.test('/movies/foo.mp4')); |
| 682 | + t.true(pattern.test('/movies/foo.mp4/')); |
| 683 | + |
| 684 | + // exec results, array access |
| 685 | + let [url, title] = pattern.exec('/movies/narnia.mp4'); |
| 686 | + t.is(url, '/movies/narnia.mp4', '~> executing pattern on correct trimming'); |
| 687 | + t.is(title, 'narnia', '~> executing pattern gives correct "title" value'); |
| 688 | + |
| 689 | + // exec results, named object |
| 690 | + t.toExec(rgx, '/movies/narnia.mp4', { title: 'narnia' }); |
| 691 | + t.toExec(rgx, '/movies/narnia.mp4/', { title: 'narnia' }); |
| 692 | + |
| 693 | + t.end(); |
| 694 | + }); |
| 695 | + |
| 696 | + test('(RegExp) param :: suffices', t => { |
| 697 | + let rgx = /^\/movies[/](?<title>\w+)\.(mp4|mov)/i; |
| 698 | + let { keys, pattern } = fn(rgx); |
| 699 | + t.same(keys, false, '~> keys = false'); |
| 700 | + t.same(rgx, pattern, '~> pattern = input'); |
| 701 | + |
| 702 | + // RegExp testing (not regexparam related) |
| 703 | + t.false(pattern.test('/movies')); |
| 704 | + t.false(pattern.test('/movies/')); |
| 705 | + t.false(pattern.test('/movies/foo')); |
| 706 | + t.false(pattern.test('/movies/foo.mp3')); |
| 707 | + t.true(pattern.test('/movies/foo.mp4')); |
| 708 | + t.true(pattern.test('/movies/foo.mp4/')); |
| 709 | + t.true(pattern.test('/movies/foo.mov/')); |
| 710 | + |
| 711 | + // exec results, array access |
| 712 | + let [url, title] = pattern.exec('/movies/narnia.mov'); |
| 713 | + t.is(url, '/movies/narnia.mov', '~> executing pattern on correct trimming'); |
| 714 | + t.is(title, 'narnia', '~> executing pattern gives correct "title" value'); |
| 715 | + |
| 716 | + // exec results, named object |
| 717 | + t.toExec(rgx, '/movies/narnia.mov', { title: 'narnia' }); |
| 718 | + t.toExec(rgx, '/movies/narnia.mov/', { title: 'narnia' }); |
| 719 | + |
| 720 | + t.end(); |
| 721 | + }); |
| 722 | + |
| 723 | + test('(RegExp) param :: optional', t => { |
| 724 | + let rgx = /^\/books[/](?<author>[^/]+)[/]?(?<title>[^/]+)?[/]?$/ |
| 725 | + let { keys, pattern } = fn(rgx); |
| 726 | + t.same(keys, false, '~> keys = false'); |
| 727 | + t.same(rgx, pattern, '~> pattern = input'); |
| 728 | + |
| 729 | + // RegExp testing (not regexparam related) |
| 730 | + t.false(pattern.test('/books')); |
| 731 | + t.false(pattern.test('/books/')); |
| 732 | + t.true(pattern.test('/books/smith')); |
| 733 | + t.true(pattern.test('/books/smith/')); |
| 734 | + t.true(pattern.test('/books/smith/narnia')); |
| 735 | + t.true(pattern.test('/books/smith/narnia/')); |
| 736 | + t.false(pattern.test('/books/smith/narnia/reviews')); |
| 737 | + t.false(pattern.test('books/smith/narnia')); |
| 738 | + |
| 739 | + // exec results, array access |
| 740 | + let [url, author, title] = pattern.exec('/books/smith/narnia/'); |
| 741 | + t.is(url, '/books/smith/narnia/', '~> executing pattern on correct trimming'); |
| 742 | + t.is(author, 'smith', '~> executing pattern gives correct value'); |
| 743 | + t.is(title, 'narnia', '~> executing pattern gives correct value'); |
| 744 | + |
| 745 | + // exec results, named object |
| 746 | + t.toExec(rgx, '/books/smith/narnia', { author: 'smith', title: 'narnia' }); |
| 747 | + t.toExec(rgx, '/books/smith/narnia/', { author: 'smith', title: 'narnia' }); |
| 748 | + t.toExec(rgx, '/books/smith/', { author: 'smith', title: undefined }); |
| 749 | + |
| 750 | + t.end(); |
| 751 | + }); |
| 752 | +} |
766 | 753 |
|
767 | 754 | test('(RegExp) nameless', t => {
|
768 | 755 | // For whatever reason~
|
|
0 commit comments