test_natural-sort.js (24778B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const l10n = new Localization(["devtools/client/storage.ftl"], true); 7 const sessionString = l10n.formatValueSync("storage-expires-session"); 8 const { 9 naturalSortCaseSensitive, 10 naturalSortCaseInsensitive, 11 } = require("resource://devtools/shared/natural-sort.js"); 12 13 function run_test() { 14 test("different values types", function () { 15 runTest(["a", 1], [1, "a"], "number always comes first"); 16 runTest( 17 ["1", 1], 18 ["1", 1], 19 "number vs numeric string - should remain unchanged (error in chrome)" 20 ); 21 runTest( 22 ["02", 3, 2, "01"], 23 ["01", "02", 2, 3], 24 "padding numeric string vs number" 25 ); 26 }); 27 28 test("datetime", function () { 29 runTest( 30 ["10/12/2008", "10/11/2008", "10/11/2007", "10/12/2007"], 31 ["10/11/2007", "10/12/2007", "10/11/2008", "10/12/2008"], 32 "similar dates" 33 ); 34 runTest( 35 ["01/01/2008", "01/10/2008", "01/01/1992", "01/01/1991"], 36 ["01/01/1991", "01/01/1992", "01/01/2008", "01/10/2008"], 37 "similar dates" 38 ); 39 // Years should expand to 0100, 2001, 2010 40 runTest( 41 ["1/1/100", "1/1/1", "1/1/10"], 42 ["1/1/100", "1/1/1", "1/1/10"], 43 "dates with short year formatting" 44 ); 45 runTest( 46 [ 47 "Wed Jan 01 2010 00:00:00 GMT-0800 (Pacific Standard Time)", 48 "Thu Dec 31 2009 00:00:00 GMT-0800 (Pacific Standard Time)", 49 "Wed Jan 01 2010 00:00:00 GMT-0500 (Eastern Standard Time)", 50 ], 51 [ 52 "Thu Dec 31 2009 00:00:00 GMT-0800 (Pacific Standard Time)", 53 "Wed Jan 01 2010 00:00:00 GMT-0500 (Eastern Standard Time)", 54 "Wed Jan 01 2010 00:00:00 GMT-0800 (Pacific Standard Time)", 55 ], 56 "javascript toString(), different timezones" 57 ); 58 runTest( 59 [ 60 "Saturday, July 3, 2010", 61 "Monday, August 2, 2010", 62 "Monday, May 3, 2010", 63 ], 64 [ 65 "Monday, May 3, 2010", 66 "Saturday, July 3, 2010", 67 "Monday, August 2, 2010", 68 ], 69 "Date.toString(), Date.toLocaleString()" 70 ); 71 runTest( 72 [ 73 "Mon, 15 Jun 2009 20:45:30 GMT", 74 "Mon, 3 May 2010 17:45:30 GMT", 75 "Mon, 15 Jun 2009 17:45:30 GMT", 76 ], 77 [ 78 "Mon, 15 Jun 2009 17:45:30 GMT", 79 "Mon, 15 Jun 2009 20:45:30 GMT", 80 "Mon, 3 May 2010 17:45:30 GMT", 81 ], 82 "Date.toUTCString()" 83 ); 84 runTest( 85 [ 86 "Saturday, July 3, 2010 1:45 PM", 87 "Saturday, July 3, 2010 1:45 AM", 88 "Monday, August 2, 2010 1:45 PM", 89 "Monday, May 3, 2010 1:45 PM", 90 ], 91 [ 92 "Monday, May 3, 2010 1:45 PM", 93 "Saturday, July 3, 2010 1:45 AM", 94 "Saturday, July 3, 2010 1:45 PM", 95 "Monday, August 2, 2010 1:45 PM", 96 ], 97 "" 98 ); 99 runTest( 100 [ 101 "Saturday, July 3, 2010 1:45:30 PM", 102 "Saturday, July 3, 2010 1:45:29 PM", 103 "Monday, August 2, 2010 1:45:01 PM", 104 "Monday, May 3, 2010 1:45:00 PM", 105 ], 106 [ 107 "Monday, May 3, 2010 1:45:00 PM", 108 "Saturday, July 3, 2010 1:45:29 PM", 109 "Saturday, July 3, 2010 1:45:30 PM", 110 "Monday, August 2, 2010 1:45:01 PM", 111 ], 112 "" 113 ); 114 runTest( 115 ["2/15/2009 1:45 PM", "1/15/2009 1:45 PM", "2/15/2009 1:45 AM"], 116 ["1/15/2009 1:45 PM", "2/15/2009 1:45 AM", "2/15/2009 1:45 PM"], 117 "" 118 ); 119 runTest( 120 [ 121 "2010-06-15T13:45:30", 122 "2009-06-15T13:45:30", 123 "2009-06-15T01:45:30.2", 124 "2009-01-15T01:45:30", 125 ], 126 [ 127 "2009-01-15T01:45:30", 128 "2009-06-15T01:45:30.2", 129 "2009-06-15T13:45:30", 130 "2010-06-15T13:45:30", 131 ], 132 "ISO8601 Dates" 133 ); 134 runTest( 135 ["2010-06-15 13:45:30", "2009-06-15 13:45:30", "2009-01-15 01:45:30"], 136 ["2009-01-15 01:45:30", "2009-06-15 13:45:30", "2010-06-15 13:45:30"], 137 "ISO8601-ish YYYY-MM-DDThh:mm:ss - which does not parse into a Date instance" 138 ); 139 runTest( 140 [ 141 "Mon, 15 Jun 2009 20:45:30 GMT", 142 "Mon, 15 Jun 2009 20:45:30 PDT", 143 "Mon, 15 Jun 2009 20:45:30 EST", 144 ], 145 [ 146 "Mon, 15 Jun 2009 20:45:30 GMT", 147 "Mon, 15 Jun 2009 20:45:30 EST", 148 "Mon, 15 Jun 2009 20:45:30 PDT", 149 ], 150 "RFC1123 testing different timezones" 151 ); 152 runTest( 153 ["1245098730000", "14330728000", "1245098728000"], 154 ["14330728000", "1245098728000", "1245098730000"], 155 "unix epoch, Date.getTime()" 156 ); 157 runTest( 158 [ 159 new Date("2001-01-10"), 160 "2015-01-01", 161 new Date("2001-01-01"), 162 "1998-01-01", 163 ], 164 [ 165 "1998-01-01", 166 new Date("2001-01-01"), 167 new Date("2001-01-10"), 168 "2015-01-01", 169 ], 170 "mixed Date types" 171 ); 172 runTest( 173 [ 174 "Tue, 29 Jun 2021 11:31:17 GMT", 175 "Sun, 14 Jun 2009 11:11:15 GMT", 176 sessionString, 177 "Mon, 15 Jun 2009 20:45:30 GMT", 178 ], 179 [ 180 sessionString, 181 "Sun, 14 Jun 2009 11:11:15 GMT", 182 "Mon, 15 Jun 2009 20:45:30 GMT", 183 "Tue, 29 Jun 2021 11:31:17 GMT", 184 ], 185 `"${sessionString}" amongst date strings` 186 ); 187 runTest( 188 [ 189 "Wed, 04 Sep 2024 09:11:44 GMT", 190 sessionString, 191 "Tue, 06 Sep 2022 09:11:44 GMT", 192 sessionString, 193 "Mon, 05 Sep 2022 09:12:41 GMT", 194 ], 195 [ 196 sessionString, 197 sessionString, 198 "Mon, 05 Sep 2022 09:12:41 GMT", 199 "Tue, 06 Sep 2022 09:11:44 GMT", 200 "Wed, 04 Sep 2024 09:11:44 GMT", 201 ], 202 `"${sessionString}" amongst date strings (complex)` 203 ); 204 205 runTest( 206 [ 207 "Madras", 208 "Jalfrezi", 209 "Rogan Josh", 210 "Vindaloo", 211 "Tikka Masala", 212 sessionString, 213 "Masala", 214 "Korma", 215 ], 216 [ 217 "Jalfrezi", 218 "Korma", 219 "Madras", 220 "Masala", 221 "Rogan Josh", 222 sessionString, 223 "Tikka Masala", 224 "Vindaloo", 225 ], 226 `"${sessionString}" amongst strings` 227 ); 228 }); 229 230 test("version number strings", function () { 231 runTest( 232 ["1.0.2", "1.0.1", "1.0.0", "1.0.9"], 233 ["1.0.0", "1.0.1", "1.0.2", "1.0.9"], 234 "close version numbers" 235 ); 236 runTest( 237 ["1.1.100", "1.1.1", "1.1.10", "1.1.54"], 238 ["1.1.1", "1.1.10", "1.1.54", "1.1.100"], 239 "more version numbers" 240 ); 241 runTest( 242 ["1.0.03", "1.0.003", "1.0.002", "1.0.0001"], 243 ["1.0.0001", "1.0.002", "1.0.003", "1.0.03"], 244 "multi-digit branch release" 245 ); 246 runTest( 247 [ 248 "1.1beta", 249 "1.1.2alpha3", 250 "1.0.2alpha3", 251 "1.0.2alpha1", 252 "1.0.1alpha4", 253 "2.1.2", 254 "2.1.1", 255 ], 256 [ 257 "1.0.1alpha4", 258 "1.0.2alpha1", 259 "1.0.2alpha3", 260 "1.1.2alpha3", 261 "1.1beta", 262 "2.1.1", 263 "2.1.2", 264 ], 265 "close version numbers" 266 ); 267 runTest( 268 [ 269 "myrelease-1.1.3", 270 "myrelease-1.2.3", 271 "myrelease-1.1.4", 272 "myrelease-1.1.1", 273 "myrelease-1.0.5", 274 ], 275 [ 276 "myrelease-1.0.5", 277 "myrelease-1.1.1", 278 "myrelease-1.1.3", 279 "myrelease-1.1.4", 280 "myrelease-1.2.3", 281 ], 282 "string first" 283 ); 284 runTest( 285 [ 286 "1.1.3", 287 "a-release-1.1.3", 288 "b-release-1.1.3", 289 "1.2.3", 290 "a-release-1.2.3", 291 "b-release-1.2.3", 292 "1.1.4", 293 "a-release-1.1.4", 294 "b-release-1.1.4", 295 "1.1.1", 296 "a-release-1.1.1", 297 "b-release-1.1.1", 298 "1.0.5", 299 "a-release-1.0.5", 300 "b-release-1.0.5", 301 ], 302 [ 303 "1.0.5", 304 "1.1.1", 305 "1.1.3", 306 "1.1.4", 307 "1.2.3", 308 "a-release-1.0.5", 309 "a-release-1.1.1", 310 "a-release-1.1.3", 311 "a-release-1.1.4", 312 "a-release-1.2.3", 313 "b-release-1.0.5", 314 "b-release-1.1.1", 315 "b-release-1.1.3", 316 "b-release-1.1.4", 317 "b-release-1.2.3", 318 ], 319 "string first, different names" 320 ); 321 runTest( 322 ["zstring", "astring", "release-1.1.3"], 323 ["astring", "release-1.1.3", "zstring"], 324 "string first, mixed with regular strings" 325 ); 326 }); 327 328 test("numerics", function () { 329 runTest(["10", 9, 2, "1", "4"], ["1", 2, "4", 9, "10"], "string vs number"); 330 runTest( 331 ["0001", "002", "001"], 332 ["0001", "001", "002"], 333 "0 left-padded numbers" 334 ); 335 runTest( 336 [2, 1, "1", "0001", "002", "02", "001"], 337 [1, "1", "0001", "001", 2, "002", "02"], 338 "0 left-padded numbers and regular numbers" 339 ); 340 runTest( 341 ["10.0401", 10.022, 10.042, "10.021999"], 342 ["10.021999", 10.022, "10.0401", 10.042], 343 "decimal string vs decimal, different precision" 344 ); 345 runTest( 346 ["10.04", 10.02, 10.03, "10.01"], 347 ["10.01", 10.02, 10.03, "10.04"], 348 "decimal string vs decimal, same precision" 349 ); 350 runTest( 351 ["10.04f", "10.039F", "10.038d", "10.037D"], 352 ["10.037D", "10.038d", "10.039F", "10.04f"], 353 "float/decimal with 'F' or 'D' notation" 354 ); 355 runTest( 356 ["10.004Z", "10.039T", "10.038ooo", "10.037g"], 357 ["10.004Z", "10.037g", "10.038ooo", "10.039T"], 358 "not foat/decimal notation" 359 ); 360 runTest( 361 ["1.528535047e5", "1.528535047e7", "1.52e15", "1.528535047e3", "1.59e-3"], 362 ["1.59e-3", "1.528535047e3", "1.528535047e5", "1.528535047e7", "1.52e15"], 363 "scientific notation" 364 ); 365 runTest( 366 ["-1", "-2", "4", "-3", "0", "-5"], 367 ["-5", "-3", "-2", "-1", "0", "4"], 368 "negative numbers as strings" 369 ); 370 runTest( 371 [-1, "-2", 4, -3, "0", "-5"], 372 ["-5", -3, "-2", -1, "0", 4], 373 "negative numbers as strings - mixed input type, string + numeric" 374 ); 375 runTest( 376 [-2.01, -2.1, 4.144, 4.1, -2.001, -5], 377 [-5, -2.1, -2.01, -2.001, 4.1, 4.144], 378 "negative floats - all numeric" 379 ); 380 }); 381 382 test("IP addresses", function () { 383 runTest( 384 [ 385 "192.168.0.100", 386 "192.168.0.1", 387 "192.168.1.1", 388 "192.168.0.250", 389 "192.168.1.123", 390 "10.0.0.2", 391 "10.0.0.1", 392 ], 393 [ 394 "10.0.0.1", 395 "10.0.0.2", 396 "192.168.0.1", 397 "192.168.0.100", 398 "192.168.0.250", 399 "192.168.1.1", 400 "192.168.1.123", 401 ] 402 ); 403 }); 404 405 test("filenames", function () { 406 runTest( 407 ["img12.png", "img10.png", "img2.png", "img1.png"], 408 ["img1.png", "img2.png", "img10.png", "img12.png"], 409 "simple image filenames" 410 ); 411 runTest( 412 [ 413 "car.mov", 414 "01alpha.sgi", 415 "001alpha.sgi", 416 "my.string_41299.tif", 417 "organic2.0001.sgi", 418 ], 419 [ 420 "001alpha.sgi", 421 "01alpha.sgi", 422 "car.mov", 423 "my.string_41299.tif", 424 "organic2.0001.sgi", 425 ], 426 "complex filenames" 427 ); 428 runTest( 429 [ 430 "./system/kernel/js/01_ui.core.js", 431 "./system/kernel/js/00_jquery-1.3.2.js", 432 "./system/kernel/js/02_my.desktop.js", 433 ], 434 [ 435 "./system/kernel/js/00_jquery-1.3.2.js", 436 "./system/kernel/js/01_ui.core.js", 437 "./system/kernel/js/02_my.desktop.js", 438 ], 439 "unix filenames" 440 ); 441 }); 442 443 test("space(s) as first character(s)", function () { 444 runTest(["alpha", " 1", " 3", " 2", 0], [0, " 1", " 2", " 3", "alpha"]); 445 }); 446 447 test("empty strings and space character", function () { 448 runTest( 449 ["10023", "999", "", 2, 5.663, 5.6629], 450 ["", 2, 5.6629, 5.663, "999", "10023"] 451 ); 452 runTest([0, "0", ""], [0, "0", ""]); 453 }); 454 455 test("hex", function () { 456 runTest(["0xA", "0x9", "0x99"], ["0x9", "0xA", "0x99"], "real hex numbers"); 457 runTest( 458 ["0xZZ", "0xVVV", "0xVEV", "0xUU"], 459 ["0xUU", "0xVEV", "0xVVV", "0xZZ"], 460 "fake hex numbers" 461 ); 462 }); 463 464 test("unicode", function () { 465 runTest( 466 ["\u0044", "\u0055", "\u0054", "\u0043"], 467 ["\u0043", "\u0044", "\u0054", "\u0055"], 468 "basic latin" 469 ); 470 }); 471 472 test("sparse array sort", function () { 473 const sarray = [3, 2]; 474 const sarrayOutput = [1, 2, 3]; 475 476 sarray[10] = 1; 477 for (let i = 0; i < 8; i++) { 478 sarrayOutput.push(undefined); 479 } 480 runTest(sarray, sarrayOutput, "simple sparse array"); 481 }); 482 483 test("case insensitive support", function () { 484 runTest( 485 ["A", "b", "C", "d", "E", "f"], 486 ["A", "b", "C", "d", "E", "f"], 487 "case sensitive pre-sorted array", 488 true 489 ); 490 runTest( 491 ["A", "C", "E", "b", "d", "f"], 492 ["A", "b", "C", "d", "E", "f"], 493 "case sensitive un-sorted array", 494 true 495 ); 496 runTest( 497 ["A", "C", "E", "b", "d", "f"], 498 ["A", "C", "E", "b", "d", "f"], 499 "case sensitive pre-sorted array" 500 ); 501 runTest( 502 ["A", "b", "C", "d", "E", "f"], 503 ["A", "C", "E", "b", "d", "f"], 504 "case sensitive un-sorted array" 505 ); 506 }); 507 508 test("rosetta code natural sort small test set", function () { 509 runTest( 510 [ 511 "ignore leading spaces: 2-2", 512 " ignore leading spaces: 2-1", 513 " ignore leading spaces: 2+0", 514 " ignore leading spaces: 2+1", 515 ], 516 [ 517 " ignore leading spaces: 2+0", 518 " ignore leading spaces: 2+1", 519 " ignore leading spaces: 2-1", 520 "ignore leading spaces: 2-2", 521 ], 522 "Ignoring leading spaces" 523 ); 524 runTest( 525 [ 526 "ignore m.a.s spaces: 2-2", 527 "ignore m.a.s spaces: 2-1", 528 "ignore m.a.s spaces: 2+0", 529 "ignore m.a.s spaces: 2+1", 530 ], 531 [ 532 "ignore m.a.s spaces: 2+0", 533 "ignore m.a.s spaces: 2+1", 534 "ignore m.a.s spaces: 2-1", 535 "ignore m.a.s spaces: 2-2", 536 ], 537 "Ignoring multiple adjacent spaces (m.a.s)" 538 ); 539 runTest( 540 [ 541 "Equiv. spaces: 3-3", 542 "Equiv.\rspaces: 3-2", 543 "Equiv.\x0cspaces: 3-1", 544 "Equiv.\x0bspaces: 3+0", 545 "Equiv.\nspaces: 3+1", 546 "Equiv.\tspaces: 3+2", 547 ], 548 [ 549 "Equiv.\x0bspaces: 3+0", 550 "Equiv.\nspaces: 3+1", 551 "Equiv.\tspaces: 3+2", 552 "Equiv.\x0cspaces: 3-1", 553 "Equiv.\rspaces: 3-2", 554 "Equiv. spaces: 3-3", 555 ], 556 "Equivalent whitespace characters" 557 ); 558 runTest( 559 [ 560 "cASE INDEPENENT: 3-2", 561 "caSE INDEPENENT: 3-1", 562 "casE INDEPENENT: 3+0", 563 "case INDEPENENT: 3+1", 564 ], 565 [ 566 "casE INDEPENENT: 3+0", 567 "case INDEPENENT: 3+1", 568 "caSE INDEPENENT: 3-1", 569 "cASE INDEPENENT: 3-2", 570 ], 571 "Case Indepenent sort (naturalSort.insensitive = true)", 572 true 573 ); 574 runTest( 575 [ 576 "foo100bar99baz0.txt", 577 "foo100bar10baz0.txt", 578 "foo1000bar99baz10.txt", 579 "foo1000bar99baz9.txt", 580 ], 581 [ 582 "foo100bar10baz0.txt", 583 "foo100bar99baz0.txt", 584 "foo1000bar99baz9.txt", 585 "foo1000bar99baz10.txt", 586 ], 587 "Numeric fields as numerics" 588 ); 589 runTest( 590 [ 591 "The Wind in the Willows", 592 "The 40th step more", 593 "The 39 steps", 594 "Wanda", 595 ], 596 [ 597 "The 39 steps", 598 "The 40th step more", 599 "The Wind in the Willows", 600 "Wanda", 601 ], 602 "Title sorts" 603 ); 604 runTest( 605 [ 606 "Equiv. \xfd accents: 2-2", 607 "Equiv. \xdd accents: 2-1", 608 "Equiv. y accents: 2+0", 609 "Equiv. Y accents: 2+1", 610 ], 611 [ 612 "Equiv. y accents: 2+0", 613 "Equiv. Y accents: 2+1", 614 "Equiv. \xfd accents: 2-2", 615 "Equiv. \xdd accents: 2-1", 616 ], 617 "Equivalent accented characters (and case) (naturalSort.insensitive = true)", 618 true 619 ); 620 // This is not a valuable unicode ordering test 621 // runTest( 622 // ['Start with an \u0292: 2-2', 'Start with an \u017f: 2-1', 'Start with an \xdf: 2+0', 'Start with an s: 2+1'], 623 // ['Start with an s: 2+1', 'Start with an \xdf: 2+0', 'Start with an \u017f: 2-1', 'Start with an \u0292: 2-2'], 624 // 'Character replacements'); 625 }); 626 627 test("contributed tests", function () { 628 runTest( 629 [ 630 "T78", 631 "U17", 632 "U10", 633 "U12", 634 "U14", 635 "745", 636 "U7", 637 "485", 638 "S16", 639 "S2", 640 "S22", 641 "1081", 642 "S25", 643 "1055", 644 "779", 645 "776", 646 "771", 647 "44", 648 "4", 649 "87", 650 "1091", 651 "42", 652 "480", 653 "952", 654 "951", 655 "756", 656 "1000", 657 "824", 658 "770", 659 "666", 660 "633", 661 "619", 662 "1", 663 "991", 664 "77H", 665 "PIER-7", 666 "47", 667 "29", 668 "9", 669 "77L", 670 "433", 671 ], 672 [ 673 "1", 674 "4", 675 "9", 676 "29", 677 "42", 678 "44", 679 "47", 680 "77H", 681 "77L", 682 "87", 683 "433", 684 "480", 685 "485", 686 "619", 687 "633", 688 "666", 689 "745", 690 "756", 691 "770", 692 "771", 693 "776", 694 "779", 695 "824", 696 "951", 697 "952", 698 "991", 699 "1000", 700 "1055", 701 "1081", 702 "1091", 703 "PIER-7", 704 "S2", 705 "S16", 706 "S22", 707 "S25", 708 "T78", 709 "U7", 710 "U10", 711 "U12", 712 "U14", 713 "U17", 714 ], 715 "contributed by Bob Zeiner (Chrome not stable sort)" 716 ); 717 runTest( 718 [ 719 "FSI stop, Position: 5", 720 "Mail Group stop, Position: 5", 721 "Mail Group stop, Position: 5", 722 "FSI stop, Position: 6", 723 "FSI stop, Position: 6", 724 "Newsstand stop, Position: 4", 725 "Newsstand stop, Position: 4", 726 "FSI stop, Position: 5", 727 ], 728 [ 729 "FSI stop, Position: 5", 730 "FSI stop, Position: 5", 731 "FSI stop, Position: 6", 732 "FSI stop, Position: 6", 733 "Mail Group stop, Position: 5", 734 "Mail Group stop, Position: 5", 735 "Newsstand stop, Position: 4", 736 "Newsstand stop, Position: 4", 737 ], 738 "contributed by Scott" 739 ); 740 runTest( 741 [2, 10, 1, "azd", undefined, "asd"], 742 [1, 2, 10, "asd", "azd", undefined], 743 "issue #2 - undefined support - jarvinen pekka" 744 ); 745 runTest( 746 [undefined, undefined, undefined, 1, undefined], 747 [1, undefined, undefined, undefined], 748 "issue #2 - undefined support - jarvinen pekka" 749 ); 750 runTest( 751 ["-1", "-2", "4", "-3", "0", "-5"], 752 ["-5", "-3", "-2", "-1", "0", "4"], 753 "issue #3 - invalid numeric string sorting - guilermo.dev" 754 ); 755 // native sort implementations are not guaranteed to be stable (i.e. Chrome) 756 // runTest( 757 // ['9','11','22','99','A','aaaa','bbbb','Aaaa','aAaa','aa','AA','Aa','aA','BB','bB','aaA','AaA','aaa'], 758 // ['9', '11', '22', '99', 'A', 'aa', 'AA', 'Aa', 'aA', 'aaA', 'AaA', 'aaa', 'aaaa', 'Aaaa', 'aAaa', 'BB', 'bB', 'bbbb'], 759 // 'issue #5 - invalid sort order - Howie Schecter (naturalSort.insensitive = true)'m true); 760 runTest( 761 [ 762 "9", 763 "11", 764 "22", 765 "99", 766 "A", 767 "aaaa", 768 "bbbb", 769 "Aaaa", 770 "aAaa", 771 "aa", 772 "AA", 773 "Aa", 774 "aA", 775 "BB", 776 "bB", 777 "aaA", 778 "AaA", 779 "aaa", 780 ], 781 [ 782 "9", 783 "11", 784 "22", 785 "99", 786 "A", 787 "AA", 788 "Aa", 789 "AaA", 790 "Aaaa", 791 "BB", 792 "aA", 793 "aAaa", 794 "aa", 795 "aaA", 796 "aaa", 797 "aaaa", 798 "bB", 799 "bbbb", 800 ], 801 "issue #5 - invalid sort order - Howie Schecter (naturalSort.insensitive = false)" 802 ); 803 runTest( 804 [ 805 "5D", 806 "1A", 807 "2D", 808 "33A", 809 "5E", 810 "33K", 811 "33D", 812 "5S", 813 "2C", 814 "5C", 815 "5F", 816 "1D", 817 "2M", 818 ], 819 [ 820 "1A", 821 "1D", 822 "2C", 823 "2D", 824 "2M", 825 "5C", 826 "5D", 827 "5E", 828 "5F", 829 "5S", 830 "33A", 831 "33D", 832 "33K", 833 ], 834 "alphanumeric - number first" 835 ); 836 runTest( 837 ["img 99", "img199", "imga99", "imgz99"], 838 ["img 99", "img199", "imga99", "imgz99"], 839 "issue #16 - Sorting incorrect when there is a space - adrien-be" 840 ); 841 runTest( 842 ["img199", "img 99", "imga99", "imgz 99", "imgb99", "imgz199"], 843 ["img 99", "img199", "imga99", "imgb99", "imgz 99", "imgz199"], 844 "issue #16 - expanded test" 845 ); 846 runTest( 847 ["1", "02", "3"], 848 ["1", "02", "3"], 849 "issue #18 - Any zeros that precede a number messes up the sorting - menixator" 850 ); 851 // strings are coerced as floats/ints if possible and sorted accordingly - e.g. they are not chunked 852 runTest( 853 ["1.100", "1.1", "1.10", "1.54"], 854 ["1.100", "1.1", "1.10", "1.54"], 855 "issue #13 - ['1.100', '1.10', '1.1', '1.54'] etc do not sort properly... - rubenstolk" 856 ); 857 runTest( 858 ["v1.100", "v1.1", "v1.10", "v1.54"], 859 ["v1.1", "v1.10", "v1.54", "v1.100"], 860 "issue #13 - ['v1.100', 'v1.10', 'v1.1', 'v1.54'] etc do not sort properly... - rubenstolk (bypass float coercion)" 861 ); 862 runTest( 863 [ 864 "MySnmp 1234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567", 865 "MySnmp 4234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567", 866 "MySnmp 2234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567", 867 "MySnmp 3234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567", 868 ], 869 [ 870 "MySnmp 1234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567", 871 "MySnmp 2234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567", 872 "MySnmp 3234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567", 873 "MySnmp 4234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567", 874 ], 875 "issue #14 - Very large numbers make sorting very slow - Mottie" 876 ); 877 runTest( 878 ["bar.1-2", "bar.1"], 879 ["bar.1", "bar.1-2"], 880 "issue #21 - javascript error" 881 ); 882 runTest( 883 ["SomeString", "SomeString 1"], 884 ["SomeString", "SomeString 1"], 885 "PR #19 - ['SomeString', 'SomeString 1'] bombing on 'undefined is not an object' - dannycochran" 886 ); 887 runTest( 888 [ 889 "Udet", 890 "\xDCbelacker", 891 "Uell", 892 "\xDClle", 893 "Ueve", 894 "\xDCxk\xFCll", 895 "Uffenbach", 896 ], 897 [ 898 "\xDCbelacker", 899 "Udet", 900 "Uell", 901 "Ueve", 902 "Uffenbach", 903 "\xDClle", 904 "\xDCxk\xFCll", 905 ], 906 "issue #9 - Sorting umlauts characters \xC4, \xD6, \xDC - diogoalves" 907 ); 908 runTest( 909 ["2.2 sec", "1.9 sec", "1.53 sec"], 910 ["1.53 sec", "1.9 sec", "2.2 sec"], 911 "https://github.com/overset/javascript-natural-sort/issues/13 - ['2.2 sec','1.9 sec','1.53 sec'] - padded by spaces - harisb" 912 ); 913 runTest( 914 ["2.2sec", "1.9sec", "1.53sec"], 915 ["1.53sec", "1.9sec", "2.2sec"], 916 "https://github.com/overset/javascript-natural-sort/issues/13 - ['2.2sec','1.9sec','1.53sec'] - no padding - harisb" 917 ); 918 }); 919 } 920 921 function test(description, testFunc) { 922 info(description); 923 testFunc(); 924 } 925 926 function runTest(testArray, expected, description, caseInsensitive = false) { 927 let actual = null; 928 929 if (caseInsensitive) { 930 actual = testArray.sort((a, b) => 931 naturalSortCaseInsensitive(a, b, sessionString) 932 ); 933 } else { 934 actual = testArray.sort((a, b) => 935 naturalSortCaseSensitive(a, b, sessionString) 936 ); 937 } 938 939 compareOptions(actual, expected, description); 940 } 941 942 // deepEqual() doesn't work well for testing arrays containing `undefined` so 943 // we need to use a custom method. 944 function compareOptions(actual, expected, description) { 945 let match = true; 946 for (let i = 0; i < actual.length; i++) { 947 if (actual[i] + "" !== expected[i] + "") { 948 ok( 949 false, 950 `${description}\nElement ${i} does not match:\n[${i}] ${actual[i]}\n[${i}] ${expected[i]}` 951 ); 952 match = false; 953 break; 954 } 955 } 956 if (match) { 957 ok(true, description); 958 } 959 }