1import { Selector, SelectorType, AttributeAction, IgnoreCaseMode } from ".."; 2 3export const tests: [ 4 selector: string, 5 expected: Selector[][], 6 message: string 7][] = [ 8 // Tag names 9 [ 10 "div", 11 [ 12 [ 13 { 14 type: SelectorType.Tag, 15 namespace: null, 16 name: "div", 17 }, 18 ], 19 ], 20 "simple tag", 21 ], 22 [ 23 "*", 24 [ 25 [ 26 { 27 type: SelectorType.Universal, 28 namespace: null, 29 }, 30 ], 31 ], 32 "universal", 33 ], 34 35 // Traversal 36 [ 37 "div div", 38 [ 39 [ 40 { 41 type: SelectorType.Tag, 42 namespace: null, 43 name: "div", 44 }, 45 { 46 type: SelectorType.Descendant, 47 }, 48 { 49 type: SelectorType.Tag, 50 namespace: null, 51 name: "div", 52 }, 53 ], 54 ], 55 "descendant", 56 ], 57 [ 58 "div\t \n \tdiv", 59 [ 60 [ 61 { 62 type: SelectorType.Tag, 63 namespace: null, 64 name: "div", 65 }, 66 { 67 type: SelectorType.Descendant, 68 }, 69 { 70 type: SelectorType.Tag, 71 namespace: null, 72 name: "div", 73 }, 74 ], 75 ], 76 "descendant /w whitespace", 77 ], 78 [ 79 "div + div", 80 [ 81 [ 82 { 83 type: SelectorType.Tag, 84 namespace: null, 85 name: "div", 86 }, 87 { 88 type: SelectorType.Adjacent, 89 }, 90 { 91 type: SelectorType.Tag, 92 namespace: null, 93 name: "div", 94 }, 95 ], 96 ], 97 "adjacent", 98 ], 99 [ 100 "div ~ div", 101 [ 102 [ 103 { 104 type: SelectorType.Tag, 105 namespace: null, 106 name: "div", 107 }, 108 { 109 type: SelectorType.Sibling, 110 }, 111 { 112 type: SelectorType.Tag, 113 namespace: null, 114 name: "div", 115 }, 116 ], 117 ], 118 "sibling", 119 ], 120 [ 121 "p < div", 122 [ 123 [ 124 { 125 type: SelectorType.Tag, 126 namespace: null, 127 name: "p", 128 }, 129 { 130 type: SelectorType.Parent, 131 }, 132 { 133 type: SelectorType.Tag, 134 namespace: null, 135 name: "div", 136 }, 137 ], 138 ], 139 "parent", 140 ], 141 142 // Escaped whitespace 143 [ 144 "#\\ > a ", 145 [ 146 [ 147 { 148 type: SelectorType.Attribute, 149 namespace: null, 150 action: AttributeAction.Equals, 151 name: "id", 152 ignoreCase: IgnoreCaseMode.QuirksMode, 153 value: " ", 154 }, 155 { 156 type: SelectorType.Child, 157 }, 158 { 159 type: SelectorType.Tag, 160 namespace: null, 161 name: "a", 162 }, 163 ], 164 ], 165 "Space between escaped space and combinator", 166 ], 167 [ 168 ".\\ ", 169 [ 170 [ 171 { 172 type: SelectorType.Attribute, 173 namespace: null, 174 name: "class", 175 action: AttributeAction.Element, 176 ignoreCase: IgnoreCaseMode.QuirksMode, 177 value: " ", 178 }, 179 ], 180 ], 181 "Space after escaped space", 182 ], 183 [ 184 ".m™²³", 185 [ 186 [ 187 { 188 type: SelectorType.Attribute, 189 namespace: null, 190 name: "class", 191 action: AttributeAction.Element, 192 ignoreCase: IgnoreCaseMode.QuirksMode, 193 value: "m™²³", 194 }, 195 ], 196 ], 197 "Special charecters in selector", 198 ], 199 [ 200 "\\61 ", 201 [ 202 [ 203 { 204 type: SelectorType.Tag, 205 namespace: null, 206 name: "a", 207 }, 208 ], 209 ], 210 "Numeric escape with space (BMP)", 211 ], 212 [ 213 "\\1d306\\01d306", 214 [ 215 [ 216 { 217 type: SelectorType.Tag, 218 namespace: null, 219 name: "\uD834\uDF06\uD834\uDF06", 220 }, 221 ], 222 ], 223 "Numeric escape (outside BMP)", 224 ], 225 [ 226 "#\\26 B", 227 [ 228 [ 229 { 230 type: SelectorType.Attribute, 231 namespace: null, 232 action: AttributeAction.Equals, 233 name: "id", 234 ignoreCase: IgnoreCaseMode.QuirksMode, 235 value: "&B", 236 }, 237 ], 238 ], 239 "id selector with escape sequence", 240 ], 241 242 // Attributes 243 [ 244 '[name^="foo["]', 245 [ 246 [ 247 { 248 type: SelectorType.Attribute, 249 namespace: null, 250 name: "name", 251 ignoreCase: IgnoreCaseMode.Unknown, 252 action: AttributeAction.Start, 253 value: "foo[", 254 }, 255 ], 256 ], 257 "quoted attribute", 258 ], 259 [ 260 '[name^="foo[bar]"]', 261 [ 262 [ 263 { 264 type: SelectorType.Attribute, 265 namespace: null, 266 name: "name", 267 ignoreCase: IgnoreCaseMode.Unknown, 268 action: AttributeAction.Start, 269 value: "foo[bar]", 270 }, 271 ], 272 ], 273 "quoted attribute", 274 ], 275 [ 276 '[name$="[bar]"]', 277 [ 278 [ 279 { 280 type: SelectorType.Attribute, 281 namespace: null, 282 name: "name", 283 ignoreCase: IgnoreCaseMode.Unknown, 284 action: AttributeAction.End, 285 value: "[bar]", 286 }, 287 ], 288 ], 289 "quoted attribute", 290 ], 291 [ 292 '[href *= "google"]', 293 [ 294 [ 295 { 296 type: SelectorType.Attribute, 297 namespace: null, 298 name: "href", 299 ignoreCase: IgnoreCaseMode.Unknown, 300 action: AttributeAction.Any, 301 value: "google", 302 }, 303 ], 304 ], 305 "quoted attribute with spaces", 306 ], 307 [ 308 '[value="\nsome text\n"]', 309 [ 310 [ 311 { 312 type: SelectorType.Attribute, 313 namespace: null, 314 name: "value", 315 ignoreCase: IgnoreCaseMode.Unknown, 316 action: AttributeAction.Equals, 317 value: "\nsome text\n", 318 }, 319 ], 320 ], 321 "quoted attribute with internal newline", 322 ], 323 [ 324 "[name=foo\\.baz]", 325 [ 326 [ 327 { 328 type: SelectorType.Attribute, 329 namespace: null, 330 name: "name", 331 ignoreCase: IgnoreCaseMode.Unknown, 332 action: AttributeAction.Equals, 333 value: "foo.baz", 334 }, 335 ], 336 ], 337 "attribute with escaped dot", 338 ], 339 [ 340 "[name=foo\\[bar\\]]", 341 [ 342 [ 343 { 344 type: SelectorType.Attribute, 345 namespace: null, 346 name: "name", 347 ignoreCase: IgnoreCaseMode.Unknown, 348 action: AttributeAction.Equals, 349 value: "foo[bar]", 350 }, 351 ], 352 ], 353 "attribute with escaped square brackets", 354 ], 355 [ 356 "[xml\\:test]", 357 [ 358 [ 359 { 360 type: SelectorType.Attribute, 361 namespace: null, 362 name: "xml:test", 363 action: AttributeAction.Exists, 364 value: "", 365 ignoreCase: IgnoreCaseMode.Unknown, 366 }, 367 ], 368 ], 369 "escaped attribute", 370 ], 371 [ 372 "[name='foo ~ < > , bar' i]", 373 [ 374 [ 375 { 376 type: SelectorType.Attribute, 377 namespace: null, 378 name: "name", 379 action: AttributeAction.Equals, 380 value: "foo ~ < > , bar", 381 ignoreCase: IgnoreCaseMode.IgnoreCase, 382 }, 383 ], 384 ], 385 "attribute with previously normalized characters", 386 ], 387 388 // ID starting with a dot 389 [ 390 "#.identifier", 391 [ 392 [ 393 { 394 type: SelectorType.Attribute, 395 namespace: null, 396 action: AttributeAction.Equals, 397 name: "id", 398 ignoreCase: IgnoreCaseMode.QuirksMode, 399 value: ".identifier", 400 }, 401 ], 402 ], 403 "ID starting with a dot", 404 ], 405 406 // Pseudo elements 407 [ 408 "::foo", 409 [ 410 [ 411 { 412 type: SelectorType.PseudoElement, 413 name: "foo", 414 data: null, 415 }, 416 ], 417 ], 418 "pseudo-element", 419 ], 420 [ 421 "::foo()", 422 [ 423 [ 424 { 425 type: SelectorType.PseudoElement, 426 name: "foo", 427 data: "", 428 }, 429 ], 430 ], 431 "pseudo-element", 432 ], 433 [ 434 "::foo(bar())", 435 [ 436 [ 437 { 438 type: SelectorType.PseudoElement, 439 name: "foo", 440 data: "bar()", 441 }, 442 ], 443 ], 444 "pseudo-element", 445 ], 446 447 // Pseudo selectors 448 [ 449 ":foo", 450 [ 451 [ 452 { 453 type: SelectorType.Pseudo, 454 name: "foo", 455 data: null, 456 }, 457 ], 458 ], 459 "pseudo selector without any data", 460 ], 461 [ 462 ":bar(baz)", 463 [ 464 [ 465 { 466 type: SelectorType.Pseudo, 467 name: "bar", 468 data: "baz", 469 }, 470 ], 471 ], 472 "pseudo selector with data", 473 ], 474 [ 475 ':contains("(foo)")', 476 [ 477 [ 478 { 479 type: SelectorType.Pseudo, 480 name: "contains", 481 data: "(foo)", 482 }, 483 ], 484 ], 485 "pseudo selector with data", 486 ], 487 [ 488 ":where(a)", 489 [ 490 [ 491 { 492 type: SelectorType.Pseudo, 493 name: "where", 494 data: [ 495 [ 496 { 497 type: SelectorType.Tag, 498 namespace: null, 499 name: "a", 500 }, 501 ], 502 ], 503 }, 504 ], 505 ], 506 "pseudo selector with data", 507 ], 508 [ 509 ':contains("(a((foo\\\\\\))))")', 510 [ 511 [ 512 { 513 type: SelectorType.Pseudo, 514 name: "contains", 515 data: "(a((foo))))", 516 }, 517 ], 518 ], 519 "pseudo selector with escaped data", 520 ], 521 [ 522 ":icontains('')", 523 [ 524 [ 525 { 526 type: SelectorType.Pseudo, 527 name: "icontains", 528 data: "", 529 }, 530 ], 531 ], 532 "pseudo selector with quote-stripped data", 533 ], 534 [ 535 ':contains("(foo)")', 536 [ 537 [ 538 { 539 type: SelectorType.Pseudo, 540 name: "contains", 541 data: "(foo)", 542 }, 543 ], 544 ], 545 "pseudo selector with data", 546 ], 547 548 // Multiple selectors 549 [ 550 "a , b", 551 [ 552 [ 553 { 554 type: SelectorType.Tag, 555 namespace: null, 556 name: "a", 557 }, 558 ], 559 [ 560 { 561 type: SelectorType.Tag, 562 namespace: null, 563 name: "b", 564 }, 565 ], 566 ], 567 "multiple selectors", 568 ], 569 570 [ 571 ":host(h1, p)", 572 [ 573 [ 574 { 575 type: SelectorType.Pseudo, 576 name: "host", 577 data: [ 578 [ 579 { 580 type: SelectorType.Tag, 581 namespace: null, 582 name: "h1", 583 }, 584 ], 585 [ 586 { 587 type: SelectorType.Tag, 588 namespace: null, 589 name: "p", 590 }, 591 ], 592 ], 593 }, 594 ], 595 ], 596 "pseudo selector with data", 597 ], 598 599 /* 600 * Bad attributes (taken from Sizzle) 601 * https://github.com/jquery/sizzle/blob/af163873d7cdfc57f18b16c04b1915209533f0b1/test/unit/selector.js#L602-L651 602 */ 603 [ 604 "[id=types_all]", 605 [ 606 [ 607 { 608 type: SelectorType.Attribute, 609 namespace: null, 610 action: AttributeAction.Equals, 611 name: "id", 612 ignoreCase: IgnoreCaseMode.Unknown, 613 value: "types_all", 614 }, 615 ], 616 ], 617 "Underscores don't need escaping", 618 ], 619 [ 620 "[name=foo\\ bar]", 621 [ 622 [ 623 { 624 type: SelectorType.Attribute, 625 namespace: null, 626 action: AttributeAction.Equals, 627 name: "name", 628 value: "foo bar", 629 ignoreCase: IgnoreCaseMode.Unknown, 630 }, 631 ], 632 ], 633 "Escaped space", 634 ], 635 [ 636 "[name=foo\\.baz]", 637 [ 638 [ 639 { 640 type: SelectorType.Attribute, 641 namespace: null, 642 action: AttributeAction.Equals, 643 name: "name", 644 value: "foo.baz", 645 ignoreCase: IgnoreCaseMode.Unknown, 646 }, 647 ], 648 ], 649 "Escaped dot", 650 ], 651 [ 652 "[name=foo\\[baz\\]]", 653 [ 654 [ 655 { 656 type: SelectorType.Attribute, 657 namespace: null, 658 action: AttributeAction.Equals, 659 name: "name", 660 value: "foo[baz]", 661 ignoreCase: IgnoreCaseMode.Unknown, 662 }, 663 ], 664 ], 665 "Escaped brackets", 666 ], 667 [ 668 "[data-attr='foo_baz\\']']", 669 [ 670 [ 671 { 672 type: SelectorType.Attribute, 673 namespace: null, 674 action: AttributeAction.Equals, 675 name: "data-attr", 676 value: "foo_baz']", 677 ignoreCase: IgnoreCaseMode.Unknown, 678 }, 679 ], 680 ], 681 "Escaped quote + right bracket", 682 ], 683 [ 684 "[data-attr='\\'']", 685 [ 686 [ 687 { 688 type: SelectorType.Attribute, 689 namespace: null, 690 action: AttributeAction.Equals, 691 name: "data-attr", 692 value: "'", 693 ignoreCase: IgnoreCaseMode.Unknown, 694 }, 695 ], 696 ], 697 "Quoted quote", 698 ], 699 [ 700 "[data-attr='\\\\']", 701 [ 702 [ 703 { 704 type: SelectorType.Attribute, 705 namespace: null, 706 action: AttributeAction.Equals, 707 name: "data-attr", 708 value: "\\", 709 ignoreCase: IgnoreCaseMode.Unknown, 710 }, 711 ], 712 ], 713 "Quoted backslash", 714 ], 715 [ 716 "[data-attr='\\\\\\'']", 717 [ 718 [ 719 { 720 type: SelectorType.Attribute, 721 namespace: null, 722 action: AttributeAction.Equals, 723 name: "data-attr", 724 value: "\\'", 725 ignoreCase: IgnoreCaseMode.Unknown, 726 }, 727 ], 728 ], 729 "Quoted backslash quote", 730 ], 731 [ 732 "[data-attr='\\\\\\\\']", 733 [ 734 [ 735 { 736 type: SelectorType.Attribute, 737 namespace: null, 738 action: AttributeAction.Equals, 739 name: "data-attr", 740 value: "\\\\", 741 ignoreCase: IgnoreCaseMode.Unknown, 742 }, 743 ], 744 ], 745 "Quoted backslash backslash", 746 ], 747 [ 748 "[data-attr='\\5C\\\\']", 749 [ 750 [ 751 { 752 type: SelectorType.Attribute, 753 namespace: null, 754 action: AttributeAction.Equals, 755 name: "data-attr", 756 value: "\\\\", 757 ignoreCase: IgnoreCaseMode.Unknown, 758 }, 759 ], 760 ], 761 "Quoted backslash backslash (numeric escape)", 762 ], 763 [ 764 "[data-attr='\\5C \\\\']", 765 [ 766 [ 767 { 768 type: SelectorType.Attribute, 769 namespace: null, 770 action: AttributeAction.Equals, 771 name: "data-attr", 772 value: "\\\\", 773 ignoreCase: IgnoreCaseMode.Unknown, 774 }, 775 ], 776 ], 777 "Quoted backslash backslash (numeric escape with trailing space)", 778 ], 779 [ 780 "[data-attr='\\5C\t\\\\']", 781 [ 782 [ 783 { 784 type: SelectorType.Attribute, 785 namespace: null, 786 action: AttributeAction.Equals, 787 name: "data-attr", 788 value: "\\\\", 789 ignoreCase: IgnoreCaseMode.Unknown, 790 }, 791 ], 792 ], 793 "Quoted backslash backslash (numeric escape with trailing tab)", 794 ], 795 [ 796 "[data-attr='\\04e00']", 797 [ 798 [ 799 { 800 type: SelectorType.Attribute, 801 namespace: null, 802 action: AttributeAction.Equals, 803 name: "data-attr", 804 value: "\u4e00", 805 ignoreCase: IgnoreCaseMode.Unknown, 806 }, 807 ], 808 ], 809 "Long numeric escape (BMP)", 810 ], 811 [ 812 "[data-attr='\\01D306A']", 813 [ 814 [ 815 { 816 type: SelectorType.Attribute, 817 namespace: null, 818 action: AttributeAction.Equals, 819 name: "data-attr", 820 value: "\uD834\uDF06A", 821 ignoreCase: IgnoreCaseMode.Unknown, 822 }, 823 ], 824 ], 825 "Long numeric escape (non-BMP)", 826 ], 827 [ 828 "fOo[baR]", 829 [ 830 [ 831 { 832 name: "fOo", 833 type: SelectorType.Tag, 834 namespace: null, 835 }, 836 { 837 action: AttributeAction.Exists, 838 name: "baR", 839 type: SelectorType.Attribute, 840 namespace: null, 841 value: "", 842 ignoreCase: IgnoreCaseMode.Unknown, 843 }, 844 ], 845 ], 846 "Mixed case tag and attribute name", 847 ], 848 849 // Namespaces 850 [ 851 "foo|bar", 852 [ 853 [ 854 { 855 name: "bar", 856 type: SelectorType.Tag, 857 namespace: "foo", 858 }, 859 ], 860 ], 861 "basic tag namespace", 862 ], 863 [ 864 "*|bar", 865 [ 866 [ 867 { 868 name: "bar", 869 type: SelectorType.Tag, 870 namespace: "*", 871 }, 872 ], 873 ], 874 "star tag namespace", 875 ], 876 [ 877 "|bar", 878 [ 879 [ 880 { 881 name: "bar", 882 type: SelectorType.Tag, 883 namespace: "", 884 }, 885 ], 886 ], 887 "without namespace", 888 ], 889 [ 890 "*|*", 891 [ 892 [ 893 { 894 type: SelectorType.Universal, 895 namespace: "*", 896 }, 897 ], 898 ], 899 "universal with namespace", 900 ], 901 [ 902 "[foo|bar]", 903 [ 904 [ 905 { 906 action: AttributeAction.Exists, 907 name: "bar", 908 type: SelectorType.Attribute, 909 namespace: "foo", 910 value: "", 911 ignoreCase: IgnoreCaseMode.Unknown, 912 }, 913 ], 914 ], 915 "basic attribute namespace, existential", 916 ], 917 [ 918 "[|bar]", 919 [ 920 [ 921 { 922 action: AttributeAction.Exists, 923 name: "bar", 924 type: SelectorType.Attribute, 925 namespace: null, 926 value: "", 927 ignoreCase: IgnoreCaseMode.Unknown, 928 }, 929 ], 930 ], 931 "without namespace, existential", 932 ], 933 [ 934 "[foo|bar='baz' i]", 935 [ 936 [ 937 { 938 action: AttributeAction.Equals, 939 ignoreCase: IgnoreCaseMode.IgnoreCase, 940 name: "bar", 941 type: SelectorType.Attribute, 942 namespace: "foo", 943 value: "baz", 944 }, 945 ], 946 ], 947 "basic attribute namespace, equality", 948 ], 949 [ 950 "[*|bar='baz' i]", 951 [ 952 [ 953 { 954 action: AttributeAction.Equals, 955 ignoreCase: IgnoreCaseMode.IgnoreCase, 956 name: "bar", 957 type: SelectorType.Attribute, 958 namespace: "*", 959 value: "baz", 960 }, 961 ], 962 ], 963 "star attribute namespace", 964 ], 965 [ 966 "[type='a' S]", 967 [ 968 [ 969 { 970 action: AttributeAction.Equals, 971 ignoreCase: IgnoreCaseMode.CaseSensitive, 972 name: "type", 973 type: SelectorType.Attribute, 974 value: "a", 975 namespace: null, 976 }, 977 ], 978 ], 979 "case-sensitive attribute selector", 980 ], 981 [ 982 "foo || bar", 983 [ 984 [ 985 { 986 name: "foo", 987 namespace: null, 988 type: SelectorType.Tag, 989 }, 990 { 991 type: SelectorType.ColumnCombinator, 992 }, 993 { 994 name: "bar", 995 namespace: null, 996 type: SelectorType.Tag, 997 }, 998 ], 999 ], 1000 "column combinator", 1001 ], 1002 [ 1003 "foo||bar", 1004 [ 1005 [ 1006 { 1007 name: "foo", 1008 namespace: null, 1009 type: SelectorType.Tag, 1010 }, 1011 { 1012 type: SelectorType.ColumnCombinator, 1013 }, 1014 { 1015 name: "bar", 1016 namespace: null, 1017 type: SelectorType.Tag, 1018 }, 1019 ], 1020 ], 1021 "column combinator without whitespace", 1022 ], 1023]; 1024