[READ-ONLY] Mirror of https://github.com/bombshell-dev/clack. Effortlessly build beautiful command-line apps bomb.sh/docs/clack/basics/getting-started/
cli command-line command-line-app node prompt prompts
5

Configure Feed

Select the types of activity you want to include in your feed.

fix: revert placeholder-on-return change (#324)

authored by

James Garbutt and committed by
GitHub
(May 21, 2025, 1:25 PM +0100) 07ca32dc 5de191fc

+6 -4763
+6
.changeset/afraid-ladybugs-drive.md
··· 1 + --- 2 + "@clack/prompts": minor 3 + "@clack/core": minor 4 + --- 5 + 6 + Reverted a change where placeholders were being set as values on return.
-5
packages/core/src/prompts/prompt.ts
··· 205 205 } 206 206 207 207 if (key?.name === 'return') { 208 - if (!this.value && this.opts.placeholder) { 209 - this.rl?.write(this.opts.placeholder); 210 - this.emit('value', this.opts.placeholder); 211 - } 212 - 213 208 if (this.opts.validate) { 214 209 const problem = this.opts.validate(this.value); 215 210 if (problem) {
-3550
packages/prompts/src/__snapshots__/index.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`prompts (isCI = false) > confirm > can cancel 1`] = ` 4 - [ 5 - "[?25l", 6 - "│ 7 - ◆ foo 8 - │ ● Yes / ○ No 9 - └ 10 - ", 11 - "", 12 - "", 13 - "", 14 - "■ foo 15 - │ No 16 - │", 17 - " 18 - ", 19 - "[?25h", 20 - ] 21 - `; 22 - 23 - exports[`prompts (isCI = false) > confirm > can set initialValue 1`] = ` 24 - [ 25 - "[?25l", 26 - "│ 27 - ◆ foo 28 - │ ○ Yes / ● No 29 - └ 30 - ", 31 - "", 32 - "", 33 - "", 34 - "◇ foo 35 - │ No", 36 - " 37 - ", 38 - "[?25h", 39 - ] 40 - `; 41 - 42 - exports[`prompts (isCI = false) > confirm > left arrow moves to previous choice 1`] = ` 43 - [ 44 - "[?25l", 45 - "│ 46 - ◆ foo 47 - │ ● Yes / ○ No 48 - └ 49 - ", 50 - "", 51 - "", 52 - "", 53 - "│ ○ Yes / ● No", 54 - "", 55 - "", 56 - "", 57 - "", 58 - "│ ● Yes / ○ No", 59 - "", 60 - "", 61 - "", 62 - "", 63 - "◇ foo 64 - │ Yes", 65 - " 66 - ", 67 - "[?25h", 68 - ] 69 - `; 70 - 71 - exports[`prompts (isCI = false) > confirm > renders custom active choice 1`] = ` 72 - [ 73 - "[?25l", 74 - "│ 75 - ◆ foo 76 - │ ● bleep / ○ No 77 - └ 78 - ", 79 - "", 80 - "", 81 - "", 82 - "◇ foo 83 - │ bleep", 84 - " 85 - ", 86 - "[?25h", 87 - ] 88 - `; 89 - 90 - exports[`prompts (isCI = false) > confirm > renders custom inactive choice 1`] = ` 91 - [ 92 - "[?25l", 93 - "│ 94 - ◆ foo 95 - │ ● Yes / ○ bleep 96 - └ 97 - ", 98 - "", 99 - "", 100 - "", 101 - "◇ foo 102 - │ Yes", 103 - " 104 - ", 105 - "[?25h", 106 - ] 107 - `; 108 - 109 - exports[`prompts (isCI = false) > confirm > renders message with choices 1`] = ` 110 - [ 111 - "[?25l", 112 - "│ 113 - ◆ foo 114 - │ ● Yes / ○ No 115 - └ 116 - ", 117 - "", 118 - "", 119 - "", 120 - "◇ foo 121 - │ Yes", 122 - " 123 - ", 124 - "[?25h", 125 - ] 126 - `; 127 - 128 - exports[`prompts (isCI = false) > confirm > right arrow moves to next choice 1`] = ` 129 - [ 130 - "[?25l", 131 - "│ 132 - ◆ foo 133 - │ ● Yes / ○ No 134 - └ 135 - ", 136 - "", 137 - "", 138 - "", 139 - "│ ○ Yes / ● No", 140 - "", 141 - "", 142 - "", 143 - "", 144 - "◇ foo 145 - │ No", 146 - " 147 - ", 148 - "[?25h", 149 - ] 150 - `; 151 - 152 - exports[`prompts (isCI = false) > groupMultiselect > can deselect an option 1`] = ` 153 - [ 154 - "[?25l", 155 - "│ 156 - ◆ foo 157 - │ ◻ group1 158 - │ │ ◻ group1value0 159 - │ └ ◻ group1value1 160 - └ 161 - ", 162 - "", 163 - "", 164 - "", 165 - "│ ◻ group1 166 - │ │ ◻ group1value0 167 - │ └ ◻ group1value1 168 - └ 169 - ", 170 - "", 171 - "", 172 - "", 173 - "│ │ ◼ group1value0", 174 - "", 175 - "", 176 - "", 177 - "", 178 - "│ │ ◼ group1value0 179 - │ └ ◻ group1value1 180 - └ 181 - ", 182 - "", 183 - "", 184 - "", 185 - "│ ◼ group1 186 - │ │ ◼ group1value0 187 - │ └ ◼ group1value1 188 - └ 189 - ", 190 - "", 191 - "", 192 - "", 193 - "│ ◻ group1 194 - │ │ ◼ group1value0 195 - │ └ ◻ group1value1 196 - └ 197 - ", 198 - "", 199 - "", 200 - "", 201 - "◇ foo 202 - │ group1value0", 203 - " 204 - ", 205 - "[?25h", 206 - ] 207 - `; 208 - 209 - exports[`prompts (isCI = false) > groupMultiselect > can select a group 1`] = ` 210 - [ 211 - "[?25l", 212 - "│ 213 - ◆ foo 214 - │ ◻ group1 215 - │ │ ◻ group1value0 216 - │ └ ◻ group1value1 217 - └ 218 - ", 219 - "", 220 - "", 221 - "", 222 - "│ ◼ group1 223 - │ │ ◼ group1value0 224 - │ └ ◼ group1value1 225 - └ 226 - ", 227 - "", 228 - "", 229 - "", 230 - "◇ foo 231 - │ group1value0, group1value1", 232 - " 233 - ", 234 - "[?25h", 235 - ] 236 - `; 237 - 238 - exports[`prompts (isCI = false) > groupMultiselect > can select a group by selecting all members 1`] = ` 239 - [ 240 - "[?25l", 241 - "│ 242 - ◆ foo 243 - │ ◻ group1 244 - │ │ ◻ group1value0 245 - │ └ ◻ group1value1 246 - └ 247 - ", 248 - "", 249 - "", 250 - "", 251 - "│ ◻ group1 252 - │ │ ◻ group1value0 253 - │ └ ◻ group1value1 254 - └ 255 - ", 256 - "", 257 - "", 258 - "", 259 - "│ │ ◼ group1value0", 260 - "", 261 - "", 262 - "", 263 - "", 264 - "│ │ ◼ group1value0 265 - │ └ ◻ group1value1 266 - └ 267 - ", 268 - "", 269 - "", 270 - "", 271 - "│ ◼ group1 272 - │ │ ◼ group1value0 273 - │ └ ◼ group1value1 274 - └ 275 - ", 276 - "", 277 - "", 278 - "", 279 - "◇ foo 280 - │ group1value0, group1value1", 281 - " 282 - ", 283 - "[?25h", 284 - ] 285 - `; 286 - 287 - exports[`prompts (isCI = false) > groupMultiselect > can select multiple options 1`] = ` 288 - [ 289 - "[?25l", 290 - "│ 291 - ◆ foo 292 - │ ◻ group1 293 - │ │ ◻ group1value0 294 - │ │ ◻ group1value1 295 - │ └ ◻ group1value2 296 - └ 297 - ", 298 - "", 299 - "", 300 - "", 301 - "│ ◻ group1 302 - │ │ ◻ group1value0 303 - │ │ ◻ group1value1 304 - │ └ ◻ group1value2 305 - └ 306 - ", 307 - "", 308 - "", 309 - "", 310 - "│ │ ◼ group1value0", 311 - "", 312 - "", 313 - "", 314 - "", 315 - "│ │ ◼ group1value0 316 - │ │ ◻ group1value1 317 - │ └ ◻ group1value2 318 - └ 319 - ", 320 - "", 321 - "", 322 - "", 323 - "│ │ ◼ group1value1", 324 - "", 325 - "", 326 - "", 327 - "", 328 - "◇ foo 329 - │ group1value0, group1value1", 330 - " 331 - ", 332 - "[?25h", 333 - ] 334 - `; 335 - 336 - exports[`prompts (isCI = false) > groupMultiselect > can submit empty selection when require = false 1`] = ` 337 - [ 338 - "[?25l", 339 - "│ 340 - ◆ foo 341 - │ ◻ group1 342 - │ │ ◻ group1value0 343 - │ └ ◻ group1value1 344 - └ 345 - ", 346 - "", 347 - "", 348 - "", 349 - "◇ foo 350 - │", 351 - " 352 - ", 353 - "[?25h", 354 - ] 355 - `; 356 - 357 - exports[`prompts (isCI = false) > groupMultiselect > cursorAt sets initial selection 1`] = ` 358 - [ 359 - "[?25l", 360 - "│ 361 - ◆ foo 362 - │ ◻ group1 363 - │ │ ◻ group1value0 364 - │ └ ◻ group1value1 365 - └ 366 - ", 367 - "", 368 - "", 369 - "", 370 - "│ └ ◼ group1value1", 371 - "", 372 - "", 373 - "", 374 - "", 375 - "◇ foo 376 - │ group1value1", 377 - " 378 - ", 379 - "[?25h", 380 - ] 381 - `; 382 - 383 - exports[`prompts (isCI = false) > groupMultiselect > initial values can be set 1`] = ` 384 - [ 385 - "[?25l", 386 - "│ 387 - ◆ foo 388 - │ ◻ group1 389 - │ │ ◻ group1value0 390 - │ └ ◼ group1value1 391 - └ 392 - ", 393 - "", 394 - "", 395 - "", 396 - "◇ foo 397 - │ group1value1", 398 - " 399 - ", 400 - "[?25h", 401 - ] 402 - `; 403 - 404 - exports[`prompts (isCI = false) > groupMultiselect > renders error when nothing selected 1`] = ` 405 - [ 406 - "[?25l", 407 - "│ 408 - ◆ foo 409 - │ ◻ group1 410 - │ │ ◻ group1value0 411 - │ └ ◻ group1value1 412 - └ 413 - ", 414 - "", 415 - "", 416 - "", 417 - "▲ foo 418 - │ ◻ group1 419 - │ │ ◻ group1value0 420 - │ └ ◻ group1value1 421 - └ Please select at least one option. 422 - Press  space  to select,  enter  to submit 423 - ", 424 - "", 425 - "", 426 - "", 427 - "◆ foo 428 - │ ◻ group1 429 - │ │ ◻ group1value0 430 - │ └ ◻ group1value1 431 - └ 432 - ", 433 - "", 434 - "", 435 - "", 436 - "│ │ ◼ group1value0", 437 - "", 438 - "", 439 - "", 440 - "", 441 - "◇ foo 442 - │ group1value0", 443 - " 444 - ", 445 - "[?25h", 446 - ] 447 - `; 448 - 449 - exports[`prompts (isCI = false) > groupMultiselect > renders message with options 1`] = ` 450 - [ 451 - "[?25l", 452 - "│ 453 - ◆ foo 454 - │ ◻ group1 455 - │ │ ◻ group1value0 456 - │ └ ◻ group1value1 457 - │ ◻ group2 458 - │ └ ◻ group2value0 459 - └ 460 - ", 461 - "", 462 - "", 463 - "", 464 - "│ ◻ group1 465 - │ │ ◻ group1value0 466 - │ └ ◻ group1value1 467 - │ ◻ group2 468 - │ └ ◻ group2value0 469 - └ 470 - ", 471 - "", 472 - "", 473 - "", 474 - "│ │ ◼ group1value0", 475 - "", 476 - "", 477 - "", 478 - "", 479 - "◇ foo 480 - │ group1value0", 481 - " 482 - ", 483 - "[?25h", 484 - ] 485 - `; 486 - 487 - exports[`prompts (isCI = false) > groupMultiselect > selectableGroups = false > cannot select groups 1`] = ` 488 - [ 489 - "[?25l", 490 - "│ 491 - ◆ foo 492 - │  group1 493 - │  ◻ group1value0 494 - │  ◻ group1value1 495 - └ 496 - ", 497 - "", 498 - "", 499 - "", 500 - "│  ◼ group1value0", 501 - "", 502 - "", 503 - "", 504 - "", 505 - "◇ foo 506 - │ group1value0", 507 - " 508 - ", 509 - "[?25h", 510 - ] 511 - `; 512 - 513 - exports[`prompts (isCI = false) > groupMultiselect > selectableGroups = false > selecting all members of group does not select group 1`] = ` 514 - [ 515 - "[?25l", 516 - "│ 517 - ◆ foo 518 - │  group1 519 - │  ◻ group1value0 520 - │  ◻ group1value1 521 - └ 522 - ", 523 - "", 524 - "", 525 - "", 526 - "│  ◼ group1value0", 527 - "", 528 - "", 529 - "", 530 - "", 531 - "│  ◼ group1value0 532 - │  ◻ group1value1 533 - └ 534 - ", 535 - "", 536 - "", 537 - "", 538 - "│  ◼ group1value1", 539 - "", 540 - "", 541 - "", 542 - "", 543 - "◇ foo 544 - │ group1value0, group1value1", 545 - " 546 - ", 547 - "[?25h", 548 - ] 549 - `; 550 - 551 - exports[`prompts (isCI = false) > groupMultiselect > values can be non-primitive 1`] = ` 552 - [ 553 - "[?25l", 554 - "│ 555 - ◆ foo 556 - │ ◻ group1 557 - │ │ ◻ value0 558 - │ └ ◻ value1 559 - └ 560 - ", 561 - "", 562 - "", 563 - "", 564 - "│ ◻ group1 565 - │ │ ◻ value0 566 - │ └ ◻ value1 567 - └ 568 - ", 569 - "", 570 - "", 571 - "", 572 - "│ │ ◼ value0", 573 - "", 574 - "", 575 - "", 576 - "", 577 - "◇ foo 578 - │ value0", 579 - " 580 - ", 581 - "[?25h", 582 - ] 583 - `; 584 - 585 - exports[`prompts (isCI = false) > multiselect > can cancel 1`] = ` 586 - [ 587 - "[?25l", 588 - "│ 589 - ◆ foo 590 - │ ◻ opt0 591 - │ ◻ opt1 592 - └ 593 - ", 594 - "", 595 - "", 596 - "", 597 - "■ foo 598 - │", 599 - " 600 - ", 601 - "[?25h", 602 - ] 603 - `; 604 - 605 - exports[`prompts (isCI = false) > multiselect > can render option hints 1`] = ` 606 - [ 607 - "[?25l", 608 - "│ 609 - ◆ foo 610 - │ ◻ opt0 (Hint 0) 611 - │ ◻ opt1 612 - └ 613 - ", 614 - "", 615 - "", 616 - "", 617 - "│ ◼ opt0 (Hint 0)", 618 - "", 619 - "", 620 - "", 621 - "", 622 - "◇ foo 623 - │ opt0", 624 - " 625 - ", 626 - "[?25h", 627 - ] 628 - `; 629 - 630 - exports[`prompts (isCI = false) > multiselect > can set cursorAt to preselect an option 1`] = ` 631 - [ 632 - "[?25l", 633 - "│ 634 - ◆ foo 635 - │ ◻ opt0 636 - │ ◻ opt1 637 - └ 638 - ", 639 - "", 640 - "", 641 - "", 642 - "│ ◼ opt1", 643 - "", 644 - "", 645 - "", 646 - "", 647 - "◇ foo 648 - │ opt1", 649 - " 650 - ", 651 - "[?25h", 652 - ] 653 - `; 654 - 655 - exports[`prompts (isCI = false) > multiselect > can set custom labels 1`] = ` 656 - [ 657 - "[?25l", 658 - "│ 659 - ◆ foo 660 - │ ◻ Option 0 661 - │ ◻ Option 1 662 - └ 663 - ", 664 - "", 665 - "", 666 - "", 667 - "│ ◼ Option 0", 668 - "", 669 - "", 670 - "", 671 - "", 672 - "◇ foo 673 - │ Option 0", 674 - " 675 - ", 676 - "[?25h", 677 - ] 678 - `; 679 - 680 - exports[`prompts (isCI = false) > multiselect > can set initial values 1`] = ` 681 - [ 682 - "[?25l", 683 - "│ 684 - ◆ foo 685 - │ ◻ opt0 686 - │ ◼ opt1 687 - └ 688 - ", 689 - "", 690 - "", 691 - "", 692 - "◇ foo 693 - │ opt1", 694 - " 695 - ", 696 - "[?25h", 697 - ] 698 - `; 699 - 700 - exports[`prompts (isCI = false) > multiselect > can submit without selection when required = false 1`] = ` 701 - [ 702 - "[?25l", 703 - "│ 704 - ◆ foo 705 - │ ◻ opt0 706 - │ ◻ opt1 707 - └ 708 - ", 709 - "", 710 - "", 711 - "", 712 - "◇ foo 713 - │ none", 714 - " 715 - ", 716 - "[?25h", 717 - ] 718 - `; 719 - 720 - exports[`prompts (isCI = false) > multiselect > maxItems renders a sliding window 1`] = ` 721 - [ 722 - "[?25l", 723 - "│ 724 - ◆ foo 725 - │ ◻ opt0 726 - │ ◻ opt1 727 - │ ◻ opt2 728 - │ ◻ opt3 729 - │ ◻ opt4 730 - │ ... 731 - └ 732 - ", 733 - "", 734 - "", 735 - "", 736 - "│ ◻ opt0 737 - │ ◻ opt1 738 - │ ◻ opt2 739 - │ ◻ opt3 740 - │ ◻ opt4 741 - │ ... 742 - └ 743 - ", 744 - "", 745 - "", 746 - "", 747 - "│ ◻ opt1 748 - │ ◻ opt2 749 - │ ◻ opt3 750 - │ ◻ opt4 751 - │ ... 752 - └ 753 - ", 754 - "", 755 - "", 756 - "", 757 - "│ ◻ opt2 758 - │ ◻ opt3 759 - │ ◻ opt4 760 - │ ... 761 - └ 762 - ", 763 - "", 764 - "", 765 - "", 766 - "│ ... 767 - │ ◻ opt2 768 - │ ◻ opt3 769 - │ ◻ opt4 770 - │ ◻ opt5 771 - │ ... 772 - └ 773 - ", 774 - "", 775 - "", 776 - "", 777 - "│ ◻ opt3 778 - │ ◻ opt4 779 - │ ◻ opt5 780 - │ ◻ opt6 781 - │ ... 782 - └ 783 - ", 784 - "", 785 - "", 786 - "", 787 - "│ ◻ opt4 788 - │ ◻ opt5 789 - │ ◻ opt6 790 - │ ◻ opt7 791 - │ ... 792 - └ 793 - ", 794 - "", 795 - "", 796 - "", 797 - "│ ◼ opt6", 798 - "", 799 - "", 800 - "", 801 - "", 802 - "◇ foo 803 - │ opt6", 804 - " 805 - ", 806 - "[?25h", 807 - ] 808 - `; 809 - 810 - exports[`prompts (isCI = false) > multiselect > renders message 1`] = ` 811 - [ 812 - "[?25l", 813 - "│ 814 - ◆ foo 815 - │ ◻ opt0 816 - │ ◻ opt1 817 - └ 818 - ", 819 - "", 820 - "", 821 - "", 822 - "│ ◼ opt0", 823 - "", 824 - "", 825 - "", 826 - "", 827 - "◇ foo 828 - │ opt0", 829 - " 830 - ", 831 - "[?25h", 832 - ] 833 - `; 834 - 835 - exports[`prompts (isCI = false) > multiselect > renders multiple cancelled values 1`] = ` 836 - [ 837 - "[?25l", 838 - "│ 839 - ◆ foo 840 - │ ◻ opt0 841 - │ ◻ opt1 842 - │ ◻ opt2 843 - └ 844 - ", 845 - "", 846 - "", 847 - "", 848 - "│ ◼ opt0", 849 - "", 850 - "", 851 - "", 852 - "", 853 - "│ ◼ opt0 854 - │ ◻ opt1 855 - │ ◻ opt2 856 - └ 857 - ", 858 - "", 859 - "", 860 - "", 861 - "│ ◼ opt1", 862 - "", 863 - "", 864 - "", 865 - "", 866 - "■ foo 867 - │ opt0, opt1 868 - │", 869 - " 870 - ", 871 - "[?25h", 872 - ] 873 - `; 874 - 875 - exports[`prompts (isCI = false) > multiselect > renders multiple selected options 1`] = ` 876 - [ 877 - "[?25l", 878 - "│ 879 - ◆ foo 880 - │ ◻ opt0 881 - │ ◻ opt1 882 - │ ◻ opt2 883 - └ 884 - ", 885 - "", 886 - "", 887 - "", 888 - "│ ◼ opt0", 889 - "", 890 - "", 891 - "", 892 - "", 893 - "│ ◼ opt0 894 - │ ◻ opt1 895 - │ ◻ opt2 896 - └ 897 - ", 898 - "", 899 - "", 900 - "", 901 - "│ ◼ opt1", 902 - "", 903 - "", 904 - "", 905 - "", 906 - "│ ◼ opt1 907 - │ ◻ opt2 908 - └ 909 - ", 910 - "", 911 - "", 912 - "", 913 - "◇ foo 914 - │ opt0, opt1", 915 - " 916 - ", 917 - "[?25h", 918 - ] 919 - `; 920 - 921 - exports[`prompts (isCI = false) > multiselect > renders validation errors 1`] = ` 922 - [ 923 - "[?25l", 924 - "│ 925 - ◆ foo 926 - │ ◻ opt0 927 - │ ◻ opt1 928 - └ 929 - ", 930 - "", 931 - "", 932 - "", 933 - "▲ foo 934 - │ ◻ opt0 935 - │ ◻ opt1 936 - └ Please select at least one option. 937 - Press  space  to select,  enter  to submit 938 - ", 939 - "", 940 - "", 941 - "", 942 - "◆ foo 943 - │ ◼ opt0 944 - │ ◻ opt1 945 - └ 946 - ", 947 - "", 948 - "", 949 - "", 950 - "◇ foo 951 - │ opt0", 952 - " 953 - ", 954 - "[?25h", 955 - ] 956 - `; 957 - 958 - exports[`prompts (isCI = false) > multiselect > shows hints for all selected options 1`] = ` 959 - [ 960 - "[?25l", 961 - "│ 962 - ◆ foo 963 - │ ◼ opt0 (Hint 0) 964 - │ ◼ opt1 (Hint 1) 965 - │ ◻ opt2 966 - └ 967 - ", 968 - "", 969 - "", 970 - "", 971 - "│ ◼ opt0 (Hint 0) 972 - │ ◼ opt1 (Hint 1) 973 - │ ◻ opt2 974 - └ 975 - ", 976 - "", 977 - "", 978 - "", 979 - "│ ◼ opt1 (Hint 1) 980 - │ ◻ opt2 (Hint 2) 981 - └ 982 - ", 983 - "", 984 - "", 985 - "", 986 - "◇ foo 987 - │ opt0, opt1", 988 - " 989 - ", 990 - "[?25h", 991 - ] 992 - `; 993 - 994 - exports[`prompts (isCI = false) > multiselect > sliding window loops downwards 1`] = ` 995 - [ 996 - "[?25l", 997 - "│ 998 - ◆ foo 999 - │ ◻ opt0 1000 - │ ◻ opt1 1001 - │ ◻ opt2 1002 - │ ◻ opt3 1003 - │ ◻ opt4 1004 - │ ... 1005 - └ 1006 - ", 1007 - "", 1008 - "", 1009 - "", 1010 - "│ ◻ opt0 1011 - │ ◻ opt1 1012 - │ ◻ opt2 1013 - │ ◻ opt3 1014 - │ ◻ opt4 1015 - │ ... 1016 - └ 1017 - ", 1018 - "", 1019 - "", 1020 - "", 1021 - "│ ◻ opt1 1022 - │ ◻ opt2 1023 - │ ◻ opt3 1024 - │ ◻ opt4 1025 - │ ... 1026 - └ 1027 - ", 1028 - "", 1029 - "", 1030 - "", 1031 - "│ ◻ opt2 1032 - │ ◻ opt3 1033 - │ ◻ opt4 1034 - │ ... 1035 - └ 1036 - ", 1037 - "", 1038 - "", 1039 - "", 1040 - "│ ... 1041 - │ ◻ opt2 1042 - │ ◻ opt3 1043 - │ ◻ opt4 1044 - │ ◻ opt5 1045 - │ ... 1046 - └ 1047 - ", 1048 - "", 1049 - "", 1050 - "", 1051 - "│ ◻ opt3 1052 - │ ◻ opt4 1053 - │ ◻ opt5 1054 - │ ◻ opt6 1055 - │ ... 1056 - └ 1057 - ", 1058 - "", 1059 - "", 1060 - "", 1061 - "│ ◻ opt4 1062 - │ ◻ opt5 1063 - │ ◻ opt6 1064 - │ ◻ opt7 1065 - │ ... 1066 - └ 1067 - ", 1068 - "", 1069 - "", 1070 - "", 1071 - "│ ◻ opt5 1072 - │ ◻ opt6 1073 - │ ◻ opt7 1074 - │ ◻ opt8 1075 - │ ... 1076 - └ 1077 - ", 1078 - "", 1079 - "", 1080 - "", 1081 - "│ ◻ opt6 1082 - │ ◻ opt7 1083 - │ ◻ opt8 1084 - │ ◻ opt9 1085 - │ ... 1086 - └ 1087 - ", 1088 - "", 1089 - "", 1090 - "", 1091 - "│ ◻ opt7 1092 - │ ◻ opt8 1093 - │ ◻ opt9 1094 - │ ◻ opt10 1095 - │ ◻ opt11 1096 - └ 1097 - ", 1098 - "", 1099 - "", 1100 - "", 1101 - "│ ◻ opt9 1102 - │ ◻ opt10 1103 - │ ◻ opt11 1104 - └ 1105 - ", 1106 - "", 1107 - "", 1108 - "", 1109 - "│ ◻ opt10 1110 - │ ◻ opt11 1111 - └ 1112 - ", 1113 - "", 1114 - "", 1115 - "", 1116 - "│ ◻ opt0 1117 - │ ◻ opt1 1118 - │ ◻ opt2 1119 - │ ◻ opt3 1120 - │ ◻ opt4 1121 - │ ... 1122 - └ 1123 - ", 1124 - "", 1125 - "", 1126 - "", 1127 - "│ ◼ opt0", 1128 - "", 1129 - "", 1130 - "", 1131 - "", 1132 - "◇ foo 1133 - │ opt0", 1134 - " 1135 - ", 1136 - "[?25h", 1137 - ] 1138 - `; 1139 - 1140 - exports[`prompts (isCI = false) > multiselect > sliding window loops upwards 1`] = ` 1141 - [ 1142 - "[?25l", 1143 - "│ 1144 - ◆ foo 1145 - │ ◻ opt0 1146 - │ ◻ opt1 1147 - │ ◻ opt2 1148 - │ ◻ opt3 1149 - │ ◻ opt4 1150 - │ ... 1151 - └ 1152 - ", 1153 - "", 1154 - "", 1155 - "", 1156 - "│ ... 1157 - │ ◻ opt7 1158 - │ ◻ opt8 1159 - │ ◻ opt9 1160 - │ ◻ opt10 1161 - │ ◻ opt11 1162 - └ 1163 - ", 1164 - "", 1165 - "", 1166 - "", 1167 - "│ ◼ opt11", 1168 - "", 1169 - "", 1170 - "", 1171 - "", 1172 - "◇ foo 1173 - │ opt11", 1174 - " 1175 - ", 1176 - "[?25h", 1177 - ] 1178 - `; 1179 - 1180 - exports[`prompts (isCI = false) > password > renders and clears validation errors 1`] = ` 1181 - [ 1182 - "[?25l", 1183 - "│ 1184 - ◆ foo 1185 - │ _ 1186 - └ 1187 - ", 1188 - "", 1189 - "", 1190 - "", 1191 - "│ ▪_", 1192 - "", 1193 - "", 1194 - "", 1195 - "", 1196 - "▲ foo 1197 - │ ▪ 1198 - └ Password must be at least 2 characters 1199 - ", 1200 - "", 1201 - "", 1202 - "", 1203 - "◆ foo 1204 - │ ▪▪_ 1205 - └ 1206 - ", 1207 - "", 1208 - "", 1209 - "", 1210 - "◇ foo 1211 - │ ▪▪", 1212 - " 1213 - ", 1214 - "[?25h", 1215 - ] 1216 - `; 1217 - 1218 - exports[`prompts (isCI = false) > password > renders cancelled value 1`] = ` 1219 - [ 1220 - "[?25l", 1221 - "│ 1222 - ◆ foo 1223 - │ _ 1224 - └ 1225 - ", 1226 - "", 1227 - "", 1228 - "", 1229 - "│ ▪_", 1230 - "", 1231 - "", 1232 - "", 1233 - "", 1234 - "■ foo 1235 - │ ▪ 1236 - │", 1237 - " 1238 - ", 1239 - "[?25h", 1240 - ] 1241 - `; 1242 - 1243 - exports[`prompts (isCI = false) > password > renders custom mask 1`] = ` 1244 - [ 1245 - "[?25l", 1246 - "│ 1247 - ◆ foo 1248 - │ _ 1249 - └ 1250 - ", 1251 - "", 1252 - "", 1253 - "", 1254 - "│ *_", 1255 - "", 1256 - "", 1257 - "", 1258 - "", 1259 - "│ **_", 1260 - "", 1261 - "", 1262 - "", 1263 - "", 1264 - "◇ foo 1265 - │ **", 1266 - " 1267 - ", 1268 - "[?25h", 1269 - ] 1270 - `; 1271 - 1272 - exports[`prompts (isCI = false) > password > renders masked value 1`] = ` 1273 - [ 1274 - "[?25l", 1275 - "│ 1276 - ◆ foo 1277 - │ _ 1278 - └ 1279 - ", 1280 - "", 1281 - "", 1282 - "", 1283 - "│ ▪_", 1284 - "", 1285 - "", 1286 - "", 1287 - "", 1288 - "│ ▪▪_", 1289 - "", 1290 - "", 1291 - "", 1292 - "", 1293 - "◇ foo 1294 - │ ▪▪", 1295 - " 1296 - ", 1297 - "[?25h", 1298 - ] 1299 - `; 1300 - 1301 - exports[`prompts (isCI = false) > password > renders message 1`] = ` 1302 - [ 1303 - "[?25l", 1304 - "│ 1305 - ◆ foo 1306 - │ _ 1307 - └ 1308 - ", 1309 - "", 1310 - "", 1311 - "", 1312 - "◇ foo 1313 - │", 1314 - " 1315 - ", 1316 - "[?25h", 1317 - ] 1318 - `; 1319 - 1320 - exports[`prompts (isCI = false) > select > can cancel 1`] = ` 1321 - [ 1322 - "[?25l", 1323 - "│ 1324 - ◆ foo 1325 - │ ● opt0 1326 - │ ○ opt1 1327 - └ 1328 - ", 1329 - "", 1330 - "", 1331 - "", 1332 - "■ foo 1333 - │ opt0 1334 - │", 1335 - " 1336 - ", 1337 - "[?25h", 1338 - ] 1339 - `; 1340 - 1341 - exports[`prompts (isCI = false) > select > down arrow selects next option 1`] = ` 1342 - [ 1343 - "[?25l", 1344 - "│ 1345 - ◆ foo 1346 - │ ● opt0 1347 - │ ○ opt1 1348 - └ 1349 - ", 1350 - "", 1351 - "", 1352 - "", 1353 - "│ ○ opt0 1354 - │ ● opt1 1355 - └ 1356 - ", 1357 - "", 1358 - "", 1359 - "", 1360 - "◇ foo 1361 - │ opt1", 1362 - " 1363 - ", 1364 - "[?25h", 1365 - ] 1366 - `; 1367 - 1368 - exports[`prompts (isCI = false) > select > renders option hints 1`] = ` 1369 - [ 1370 - "[?25l", 1371 - "│ 1372 - ◆ foo 1373 - │ ● opt0 (Hint 0) 1374 - │ ○ opt1 1375 - └ 1376 - ", 1377 - "", 1378 - "", 1379 - "", 1380 - "◇ foo 1381 - │ opt0", 1382 - " 1383 - ", 1384 - "[?25h", 1385 - ] 1386 - `; 1387 - 1388 - exports[`prompts (isCI = false) > select > renders option labels 1`] = ` 1389 - [ 1390 - "[?25l", 1391 - "│ 1392 - ◆ foo 1393 - │ ● Option 0 1394 - │ ○ Option 1 1395 - └ 1396 - ", 1397 - "", 1398 - "", 1399 - "", 1400 - "◇ foo 1401 - │ Option 0", 1402 - " 1403 - ", 1404 - "[?25h", 1405 - ] 1406 - `; 1407 - 1408 - exports[`prompts (isCI = false) > select > renders options and message 1`] = ` 1409 - [ 1410 - "[?25l", 1411 - "│ 1412 - ◆ foo 1413 - │ ● opt0 1414 - │ ○ opt1 1415 - └ 1416 - ", 1417 - "", 1418 - "", 1419 - "", 1420 - "◇ foo 1421 - │ opt0", 1422 - " 1423 - ", 1424 - "[?25h", 1425 - ] 1426 - `; 1427 - 1428 - exports[`prompts (isCI = false) > select > up arrow selects previous option 1`] = ` 1429 - [ 1430 - "[?25l", 1431 - "│ 1432 - ◆ foo 1433 - │ ● opt0 1434 - │ ○ opt1 1435 - └ 1436 - ", 1437 - "", 1438 - "", 1439 - "", 1440 - "│ ○ opt0 1441 - │ ● opt1 1442 - └ 1443 - ", 1444 - "", 1445 - "", 1446 - "", 1447 - "│ ● opt0 1448 - │ ○ opt1 1449 - └ 1450 - ", 1451 - "", 1452 - "", 1453 - "", 1454 - "◇ foo 1455 - │ opt0", 1456 - " 1457 - ", 1458 - "[?25h", 1459 - ] 1460 - `; 1461 - 1462 - exports[`prompts (isCI = false) > spinner > message > sets message for next frame 1`] = ` 1463 - [ 1464 - "[?25l", 1465 - "│ 1466 - ", 1467 - "◒ ", 1468 - "", 1469 - "", 1470 - "◐ foo", 1471 - ] 1472 - `; 1473 - 1474 - exports[`prompts (isCI = false) > spinner > start > renders frames at interval 1`] = ` 1475 - [ 1476 - "[?25l", 1477 - "│ 1478 - ", 1479 - "◒ ", 1480 - "", 1481 - "", 1482 - "◐ ", 1483 - "", 1484 - "", 1485 - "◓ ", 1486 - "", 1487 - "", 1488 - "◑ ", 1489 - ] 1490 - `; 1491 - 1492 - exports[`prompts (isCI = false) > spinner > start > renders message 1`] = ` 1493 - [ 1494 - "[?25l", 1495 - "│ 1496 - ", 1497 - "◒ foo", 1498 - ] 1499 - `; 1500 - 1501 - exports[`prompts (isCI = false) > spinner > start > renders timer when indicator is "timer" 1`] = ` 1502 - [ 1503 - "[?25l", 1504 - "│ 1505 - ", 1506 - "◒ [0s]", 1507 - ] 1508 - `; 1509 - 1510 - exports[`prompts (isCI = false) > spinner > stop > renders cancel symbol if code = 1 1`] = ` 1511 - [ 1512 - "[?25l", 1513 - "│ 1514 - ", 1515 - "◒ ", 1516 - "", 1517 - "", 1518 - "■ 1519 - ", 1520 - "[?25h", 1521 - ] 1522 - `; 1523 - 1524 - exports[`prompts (isCI = false) > spinner > stop > renders error symbol if code > 1 1`] = ` 1525 - [ 1526 - "[?25l", 1527 - "│ 1528 - ", 1529 - "◒ ", 1530 - "", 1531 - "", 1532 - "▲ 1533 - ", 1534 - "[?25h", 1535 - ] 1536 - `; 1537 - 1538 - exports[`prompts (isCI = false) > spinner > stop > renders message 1`] = ` 1539 - [ 1540 - "[?25l", 1541 - "│ 1542 - ", 1543 - "◒ ", 1544 - "", 1545 - "", 1546 - "◇ foo 1547 - ", 1548 - "[?25h", 1549 - ] 1550 - `; 1551 - 1552 - exports[`prompts (isCI = false) > spinner > stop > renders submit symbol and stops spinner 1`] = ` 1553 - [ 1554 - "[?25l", 1555 - "│ 1556 - ", 1557 - "◒ ", 1558 - "", 1559 - "", 1560 - "◇ 1561 - ", 1562 - "[?25h", 1563 - ] 1564 - `; 1565 - 1566 - exports[`prompts (isCI = false) > text > can cancel 1`] = ` 1567 - [ 1568 - "[?25l", 1569 - "│ 1570 - ◆ foo 1571 - │ _ 1572 - └ 1573 - ", 1574 - "", 1575 - "", 1576 - "", 1577 - "■ foo 1578 - │", 1579 - " 1580 - ", 1581 - "[?25h", 1582 - ] 1583 - `; 1584 - 1585 - exports[`prompts (isCI = false) > text > defaultValue sets the value but does not render 1`] = ` 1586 - [ 1587 - "[?25l", 1588 - "│ 1589 - ◆ foo 1590 - │ _ 1591 - └ 1592 - ", 1593 - "", 1594 - "", 1595 - "", 1596 - "◇ foo 1597 - │ bar", 1598 - " 1599 - ", 1600 - "[?25h", 1601 - ] 1602 - `; 1603 - 1604 - exports[`prompts (isCI = false) > text > renders cancelled value if one set 1`] = ` 1605 - [ 1606 - "[?25l", 1607 - "│ 1608 - ◆ foo 1609 - │ _ 1610 - └ 1611 - ", 1612 - "", 1613 - "", 1614 - "", 1615 - "│ x█", 1616 - "", 1617 - "", 1618 - "", 1619 - "", 1620 - "│ xy█", 1621 - "", 1622 - "", 1623 - "", 1624 - "", 1625 - "■ foo 1626 - │ xy 1627 - │", 1628 - " 1629 - ", 1630 - "[?25h", 1631 - ] 1632 - `; 1633 - 1634 - exports[`prompts (isCI = false) > text > renders message 1`] = ` 1635 - [ 1636 - "[?25l", 1637 - "│ 1638 - ◆ foo 1639 - │ _ 1640 - └ 1641 - ", 1642 - "", 1643 - "", 1644 - "", 1645 - "◇ foo 1646 - │ undefined", 1647 - " 1648 - ", 1649 - "[?25h", 1650 - ] 1651 - `; 1652 - 1653 - exports[`prompts (isCI = false) > text > renders placeholder if set 1`] = ` 1654 - [ 1655 - "[?25l", 1656 - "│ 1657 - ◆ foo 1658 - │ bar 1659 - └ 1660 - ", 1661 - "", 1662 - "", 1663 - "", 1664 - "◇ foo 1665 - │ bar", 1666 - " 1667 - ", 1668 - "[?25h", 1669 - ] 1670 - `; 1671 - 1672 - exports[`prompts (isCI = false) > text > renders submitted value 1`] = ` 1673 - [ 1674 - "[?25l", 1675 - "│ 1676 - ◆ foo 1677 - │ _ 1678 - └ 1679 - ", 1680 - "", 1681 - "", 1682 - "", 1683 - "│ x█", 1684 - "", 1685 - "", 1686 - "", 1687 - "", 1688 - "│ xy█", 1689 - "", 1690 - "", 1691 - "", 1692 - "", 1693 - "◇ foo 1694 - │ xy", 1695 - " 1696 - ", 1697 - "[?25h", 1698 - ] 1699 - `; 1700 - 1701 - exports[`prompts (isCI = false) > text > validation errors render and clear (using Error) 1`] = ` 1702 - [ 1703 - "[?25l", 1704 - "│ 1705 - ◆ foo 1706 - │ _ 1707 - └ 1708 - ", 1709 - "", 1710 - "", 1711 - "", 1712 - "│ x█", 1713 - "", 1714 - "", 1715 - "", 1716 - "", 1717 - "▲ foo 1718 - │ x█ 1719 - └ should be xy 1720 - ", 1721 - "", 1722 - "", 1723 - "", 1724 - "◆ foo 1725 - │ xy█ 1726 - └ 1727 - ", 1728 - "", 1729 - "", 1730 - "", 1731 - "◇ foo 1732 - │ xy", 1733 - " 1734 - ", 1735 - "[?25h", 1736 - ] 1737 - `; 1738 - 1739 - exports[`prompts (isCI = false) > text > validation errors render and clear 1`] = ` 1740 - [ 1741 - "[?25l", 1742 - "│ 1743 - ◆ foo 1744 - │ _ 1745 - └ 1746 - ", 1747 - "", 1748 - "", 1749 - "", 1750 - "│ x█", 1751 - "", 1752 - "", 1753 - "", 1754 - "", 1755 - "▲ foo 1756 - │ x█ 1757 - └ should be xy 1758 - ", 1759 - "", 1760 - "", 1761 - "", 1762 - "◆ foo 1763 - │ xy█ 1764 - └ 1765 - ", 1766 - "", 1767 - "", 1768 - "", 1769 - "◇ foo 1770 - │ xy", 1771 - " 1772 - ", 1773 - "[?25h", 1774 - ] 1775 - `; 1776 - 1777 - exports[`prompts (isCI = true) > confirm > can cancel 1`] = ` 1778 - [ 1779 - "[?25l", 1780 - "│ 1781 - ◆ foo 1782 - │ ● Yes / ○ No 1783 - └ 1784 - ", 1785 - "", 1786 - "", 1787 - "", 1788 - "■ foo 1789 - │ No 1790 - │", 1791 - " 1792 - ", 1793 - "[?25h", 1794 - ] 1795 - `; 1796 - 1797 - exports[`prompts (isCI = true) > confirm > can set initialValue 1`] = ` 1798 - [ 1799 - "[?25l", 1800 - "│ 1801 - ◆ foo 1802 - │ ○ Yes / ● No 1803 - └ 1804 - ", 1805 - "", 1806 - "", 1807 - "", 1808 - "◇ foo 1809 - │ No", 1810 - " 1811 - ", 1812 - "[?25h", 1813 - ] 1814 - `; 1815 - 1816 - exports[`prompts (isCI = true) > confirm > left arrow moves to previous choice 1`] = ` 1817 - [ 1818 - "[?25l", 1819 - "│ 1820 - ◆ foo 1821 - │ ● Yes / ○ No 1822 - └ 1823 - ", 1824 - "", 1825 - "", 1826 - "", 1827 - "│ ○ Yes / ● No", 1828 - "", 1829 - "", 1830 - "", 1831 - "", 1832 - "│ ● Yes / ○ No", 1833 - "", 1834 - "", 1835 - "", 1836 - "", 1837 - "◇ foo 1838 - │ Yes", 1839 - " 1840 - ", 1841 - "[?25h", 1842 - ] 1843 - `; 1844 - 1845 - exports[`prompts (isCI = true) > confirm > renders custom active choice 1`] = ` 1846 - [ 1847 - "[?25l", 1848 - "│ 1849 - ◆ foo 1850 - │ ● bleep / ○ No 1851 - └ 1852 - ", 1853 - "", 1854 - "", 1855 - "", 1856 - "◇ foo 1857 - │ bleep", 1858 - " 1859 - ", 1860 - "[?25h", 1861 - ] 1862 - `; 1863 - 1864 - exports[`prompts (isCI = true) > confirm > renders custom inactive choice 1`] = ` 1865 - [ 1866 - "[?25l", 1867 - "│ 1868 - ◆ foo 1869 - │ ● Yes / ○ bleep 1870 - └ 1871 - ", 1872 - "", 1873 - "", 1874 - "", 1875 - "◇ foo 1876 - │ Yes", 1877 - " 1878 - ", 1879 - "[?25h", 1880 - ] 1881 - `; 1882 - 1883 - exports[`prompts (isCI = true) > confirm > renders message with choices 1`] = ` 1884 - [ 1885 - "[?25l", 1886 - "│ 1887 - ◆ foo 1888 - │ ● Yes / ○ No 1889 - └ 1890 - ", 1891 - "", 1892 - "", 1893 - "", 1894 - "◇ foo 1895 - │ Yes", 1896 - " 1897 - ", 1898 - "[?25h", 1899 - ] 1900 - `; 1901 - 1902 - exports[`prompts (isCI = true) > confirm > right arrow moves to next choice 1`] = ` 1903 - [ 1904 - "[?25l", 1905 - "│ 1906 - ◆ foo 1907 - │ ● Yes / ○ No 1908 - └ 1909 - ", 1910 - "", 1911 - "", 1912 - "", 1913 - "│ ○ Yes / ● No", 1914 - "", 1915 - "", 1916 - "", 1917 - "", 1918 - "◇ foo 1919 - │ No", 1920 - " 1921 - ", 1922 - "[?25h", 1923 - ] 1924 - `; 1925 - 1926 - exports[`prompts (isCI = true) > groupMultiselect > can deselect an option 1`] = ` 1927 - [ 1928 - "[?25l", 1929 - "│ 1930 - ◆ foo 1931 - │ ◻ group1 1932 - │ │ ◻ group1value0 1933 - │ └ ◻ group1value1 1934 - └ 1935 - ", 1936 - "", 1937 - "", 1938 - "", 1939 - "│ ◻ group1 1940 - │ │ ◻ group1value0 1941 - │ └ ◻ group1value1 1942 - └ 1943 - ", 1944 - "", 1945 - "", 1946 - "", 1947 - "│ │ ◼ group1value0", 1948 - "", 1949 - "", 1950 - "", 1951 - "", 1952 - "│ │ ◼ group1value0 1953 - │ └ ◻ group1value1 1954 - └ 1955 - ", 1956 - "", 1957 - "", 1958 - "", 1959 - "│ ◼ group1 1960 - │ │ ◼ group1value0 1961 - │ └ ◼ group1value1 1962 - └ 1963 - ", 1964 - "", 1965 - "", 1966 - "", 1967 - "│ ◻ group1 1968 - │ │ ◼ group1value0 1969 - │ └ ◻ group1value1 1970 - └ 1971 - ", 1972 - "", 1973 - "", 1974 - "", 1975 - "◇ foo 1976 - │ group1value0", 1977 - " 1978 - ", 1979 - "[?25h", 1980 - ] 1981 - `; 1982 - 1983 - exports[`prompts (isCI = true) > groupMultiselect > can select a group 1`] = ` 1984 - [ 1985 - "[?25l", 1986 - "│ 1987 - ◆ foo 1988 - │ ◻ group1 1989 - │ │ ◻ group1value0 1990 - │ └ ◻ group1value1 1991 - └ 1992 - ", 1993 - "", 1994 - "", 1995 - "", 1996 - "│ ◼ group1 1997 - │ │ ◼ group1value0 1998 - │ └ ◼ group1value1 1999 - └ 2000 - ", 2001 - "", 2002 - "", 2003 - "", 2004 - "◇ foo 2005 - │ group1value0, group1value1", 2006 - " 2007 - ", 2008 - "[?25h", 2009 - ] 2010 - `; 2011 - 2012 - exports[`prompts (isCI = true) > groupMultiselect > can select a group by selecting all members 1`] = ` 2013 - [ 2014 - "[?25l", 2015 - "│ 2016 - ◆ foo 2017 - │ ◻ group1 2018 - │ │ ◻ group1value0 2019 - │ └ ◻ group1value1 2020 - └ 2021 - ", 2022 - "", 2023 - "", 2024 - "", 2025 - "│ ◻ group1 2026 - │ │ ◻ group1value0 2027 - │ └ ◻ group1value1 2028 - └ 2029 - ", 2030 - "", 2031 - "", 2032 - "", 2033 - "│ │ ◼ group1value0", 2034 - "", 2035 - "", 2036 - "", 2037 - "", 2038 - "│ │ ◼ group1value0 2039 - │ └ ◻ group1value1 2040 - └ 2041 - ", 2042 - "", 2043 - "", 2044 - "", 2045 - "│ ◼ group1 2046 - │ │ ◼ group1value0 2047 - │ └ ◼ group1value1 2048 - └ 2049 - ", 2050 - "", 2051 - "", 2052 - "", 2053 - "◇ foo 2054 - │ group1value0, group1value1", 2055 - " 2056 - ", 2057 - "[?25h", 2058 - ] 2059 - `; 2060 - 2061 - exports[`prompts (isCI = true) > groupMultiselect > can select multiple options 1`] = ` 2062 - [ 2063 - "[?25l", 2064 - "│ 2065 - ◆ foo 2066 - │ ◻ group1 2067 - │ │ ◻ group1value0 2068 - │ │ ◻ group1value1 2069 - │ └ ◻ group1value2 2070 - └ 2071 - ", 2072 - "", 2073 - "", 2074 - "", 2075 - "│ ◻ group1 2076 - │ │ ◻ group1value0 2077 - │ │ ◻ group1value1 2078 - │ └ ◻ group1value2 2079 - └ 2080 - ", 2081 - "", 2082 - "", 2083 - "", 2084 - "│ │ ◼ group1value0", 2085 - "", 2086 - "", 2087 - "", 2088 - "", 2089 - "│ │ ◼ group1value0 2090 - │ │ ◻ group1value1 2091 - │ └ ◻ group1value2 2092 - └ 2093 - ", 2094 - "", 2095 - "", 2096 - "", 2097 - "│ │ ◼ group1value1", 2098 - "", 2099 - "", 2100 - "", 2101 - "", 2102 - "◇ foo 2103 - │ group1value0, group1value1", 2104 - " 2105 - ", 2106 - "[?25h", 2107 - ] 2108 - `; 2109 - 2110 - exports[`prompts (isCI = true) > groupMultiselect > can submit empty selection when require = false 1`] = ` 2111 - [ 2112 - "[?25l", 2113 - "│ 2114 - ◆ foo 2115 - │ ◻ group1 2116 - │ │ ◻ group1value0 2117 - │ └ ◻ group1value1 2118 - └ 2119 - ", 2120 - "", 2121 - "", 2122 - "", 2123 - "◇ foo 2124 - │", 2125 - " 2126 - ", 2127 - "[?25h", 2128 - ] 2129 - `; 2130 - 2131 - exports[`prompts (isCI = true) > groupMultiselect > cursorAt sets initial selection 1`] = ` 2132 - [ 2133 - "[?25l", 2134 - "│ 2135 - ◆ foo 2136 - │ ◻ group1 2137 - │ │ ◻ group1value0 2138 - │ └ ◻ group1value1 2139 - └ 2140 - ", 2141 - "", 2142 - "", 2143 - "", 2144 - "│ └ ◼ group1value1", 2145 - "", 2146 - "", 2147 - "", 2148 - "", 2149 - "◇ foo 2150 - │ group1value1", 2151 - " 2152 - ", 2153 - "[?25h", 2154 - ] 2155 - `; 2156 - 2157 - exports[`prompts (isCI = true) > groupMultiselect > initial values can be set 1`] = ` 2158 - [ 2159 - "[?25l", 2160 - "│ 2161 - ◆ foo 2162 - │ ◻ group1 2163 - │ │ ◻ group1value0 2164 - │ └ ◼ group1value1 2165 - └ 2166 - ", 2167 - "", 2168 - "", 2169 - "", 2170 - "◇ foo 2171 - │ group1value1", 2172 - " 2173 - ", 2174 - "[?25h", 2175 - ] 2176 - `; 2177 - 2178 - exports[`prompts (isCI = true) > groupMultiselect > renders error when nothing selected 1`] = ` 2179 - [ 2180 - "[?25l", 2181 - "│ 2182 - ◆ foo 2183 - │ ◻ group1 2184 - │ │ ◻ group1value0 2185 - │ └ ◻ group1value1 2186 - └ 2187 - ", 2188 - "", 2189 - "", 2190 - "", 2191 - "▲ foo 2192 - │ ◻ group1 2193 - │ │ ◻ group1value0 2194 - │ └ ◻ group1value1 2195 - └ Please select at least one option. 2196 - Press  space  to select,  enter  to submit 2197 - ", 2198 - "", 2199 - "", 2200 - "", 2201 - "◆ foo 2202 - │ ◻ group1 2203 - │ │ ◻ group1value0 2204 - │ └ ◻ group1value1 2205 - └ 2206 - ", 2207 - "", 2208 - "", 2209 - "", 2210 - "│ │ ◼ group1value0", 2211 - "", 2212 - "", 2213 - "", 2214 - "", 2215 - "◇ foo 2216 - │ group1value0", 2217 - " 2218 - ", 2219 - "[?25h", 2220 - ] 2221 - `; 2222 - 2223 - exports[`prompts (isCI = true) > groupMultiselect > renders message with options 1`] = ` 2224 - [ 2225 - "[?25l", 2226 - "│ 2227 - ◆ foo 2228 - │ ◻ group1 2229 - │ │ ◻ group1value0 2230 - │ └ ◻ group1value1 2231 - │ ◻ group2 2232 - │ └ ◻ group2value0 2233 - └ 2234 - ", 2235 - "", 2236 - "", 2237 - "", 2238 - "│ ◻ group1 2239 - │ │ ◻ group1value0 2240 - │ └ ◻ group1value1 2241 - │ ◻ group2 2242 - │ └ ◻ group2value0 2243 - └ 2244 - ", 2245 - "", 2246 - "", 2247 - "", 2248 - "│ │ ◼ group1value0", 2249 - "", 2250 - "", 2251 - "", 2252 - "", 2253 - "◇ foo 2254 - │ group1value0", 2255 - " 2256 - ", 2257 - "[?25h", 2258 - ] 2259 - `; 2260 - 2261 - exports[`prompts (isCI = true) > groupMultiselect > selectableGroups = false > cannot select groups 1`] = ` 2262 - [ 2263 - "[?25l", 2264 - "│ 2265 - ◆ foo 2266 - │  group1 2267 - │  ◻ group1value0 2268 - │  ◻ group1value1 2269 - └ 2270 - ", 2271 - "", 2272 - "", 2273 - "", 2274 - "│  ◼ group1value0", 2275 - "", 2276 - "", 2277 - "", 2278 - "", 2279 - "◇ foo 2280 - │ group1value0", 2281 - " 2282 - ", 2283 - "[?25h", 2284 - ] 2285 - `; 2286 - 2287 - exports[`prompts (isCI = true) > groupMultiselect > selectableGroups = false > selecting all members of group does not select group 1`] = ` 2288 - [ 2289 - "[?25l", 2290 - "│ 2291 - ◆ foo 2292 - │  group1 2293 - │  ◻ group1value0 2294 - │  ◻ group1value1 2295 - └ 2296 - ", 2297 - "", 2298 - "", 2299 - "", 2300 - "│  ◼ group1value0", 2301 - "", 2302 - "", 2303 - "", 2304 - "", 2305 - "│  ◼ group1value0 2306 - │  ◻ group1value1 2307 - └ 2308 - ", 2309 - "", 2310 - "", 2311 - "", 2312 - "│  ◼ group1value1", 2313 - "", 2314 - "", 2315 - "", 2316 - "", 2317 - "◇ foo 2318 - │ group1value0, group1value1", 2319 - " 2320 - ", 2321 - "[?25h", 2322 - ] 2323 - `; 2324 - 2325 - exports[`prompts (isCI = true) > groupMultiselect > values can be non-primitive 1`] = ` 2326 - [ 2327 - "[?25l", 2328 - "│ 2329 - ◆ foo 2330 - │ ◻ group1 2331 - │ │ ◻ value0 2332 - │ └ ◻ value1 2333 - └ 2334 - ", 2335 - "", 2336 - "", 2337 - "", 2338 - "│ ◻ group1 2339 - │ │ ◻ value0 2340 - │ └ ◻ value1 2341 - └ 2342 - ", 2343 - "", 2344 - "", 2345 - "", 2346 - "│ │ ◼ value0", 2347 - "", 2348 - "", 2349 - "", 2350 - "", 2351 - "◇ foo 2352 - │ value0", 2353 - " 2354 - ", 2355 - "[?25h", 2356 - ] 2357 - `; 2358 - 2359 - exports[`prompts (isCI = true) > multiselect > can cancel 1`] = ` 2360 - [ 2361 - "[?25l", 2362 - "│ 2363 - ◆ foo 2364 - │ ◻ opt0 2365 - │ ◻ opt1 2366 - └ 2367 - ", 2368 - "", 2369 - "", 2370 - "", 2371 - "■ foo 2372 - │", 2373 - " 2374 - ", 2375 - "[?25h", 2376 - ] 2377 - `; 2378 - 2379 - exports[`prompts (isCI = true) > multiselect > can render option hints 1`] = ` 2380 - [ 2381 - "[?25l", 2382 - "│ 2383 - ◆ foo 2384 - │ ◻ opt0 (Hint 0) 2385 - │ ◻ opt1 2386 - └ 2387 - ", 2388 - "", 2389 - "", 2390 - "", 2391 - "│ ◼ opt0 (Hint 0)", 2392 - "", 2393 - "", 2394 - "", 2395 - "", 2396 - "◇ foo 2397 - │ opt0", 2398 - " 2399 - ", 2400 - "[?25h", 2401 - ] 2402 - `; 2403 - 2404 - exports[`prompts (isCI = true) > multiselect > can set cursorAt to preselect an option 1`] = ` 2405 - [ 2406 - "[?25l", 2407 - "│ 2408 - ◆ foo 2409 - │ ◻ opt0 2410 - │ ◻ opt1 2411 - └ 2412 - ", 2413 - "", 2414 - "", 2415 - "", 2416 - "│ ◼ opt1", 2417 - "", 2418 - "", 2419 - "", 2420 - "", 2421 - "◇ foo 2422 - │ opt1", 2423 - " 2424 - ", 2425 - "[?25h", 2426 - ] 2427 - `; 2428 - 2429 - exports[`prompts (isCI = true) > multiselect > can set custom labels 1`] = ` 2430 - [ 2431 - "[?25l", 2432 - "│ 2433 - ◆ foo 2434 - │ ◻ Option 0 2435 - │ ◻ Option 1 2436 - └ 2437 - ", 2438 - "", 2439 - "", 2440 - "", 2441 - "│ ◼ Option 0", 2442 - "", 2443 - "", 2444 - "", 2445 - "", 2446 - "◇ foo 2447 - │ Option 0", 2448 - " 2449 - ", 2450 - "[?25h", 2451 - ] 2452 - `; 2453 - 2454 - exports[`prompts (isCI = true) > multiselect > can set initial values 1`] = ` 2455 - [ 2456 - "[?25l", 2457 - "│ 2458 - ◆ foo 2459 - │ ◻ opt0 2460 - │ ◼ opt1 2461 - └ 2462 - ", 2463 - "", 2464 - "", 2465 - "", 2466 - "◇ foo 2467 - │ opt1", 2468 - " 2469 - ", 2470 - "[?25h", 2471 - ] 2472 - `; 2473 - 2474 - exports[`prompts (isCI = true) > multiselect > can submit without selection when required = false 1`] = ` 2475 - [ 2476 - "[?25l", 2477 - "│ 2478 - ◆ foo 2479 - │ ◻ opt0 2480 - │ ◻ opt1 2481 - └ 2482 - ", 2483 - "", 2484 - "", 2485 - "", 2486 - "◇ foo 2487 - │ none", 2488 - " 2489 - ", 2490 - "[?25h", 2491 - ] 2492 - `; 2493 - 2494 - exports[`prompts (isCI = true) > multiselect > maxItems renders a sliding window 1`] = ` 2495 - [ 2496 - "[?25l", 2497 - "│ 2498 - ◆ foo 2499 - │ ◻ opt0 2500 - │ ◻ opt1 2501 - │ ◻ opt2 2502 - │ ◻ opt3 2503 - │ ◻ opt4 2504 - │ ... 2505 - └ 2506 - ", 2507 - "", 2508 - "", 2509 - "", 2510 - "│ ◻ opt0 2511 - │ ◻ opt1 2512 - │ ◻ opt2 2513 - │ ◻ opt3 2514 - │ ◻ opt4 2515 - │ ... 2516 - └ 2517 - ", 2518 - "", 2519 - "", 2520 - "", 2521 - "│ ◻ opt1 2522 - │ ◻ opt2 2523 - │ ◻ opt3 2524 - │ ◻ opt4 2525 - │ ... 2526 - └ 2527 - ", 2528 - "", 2529 - "", 2530 - "", 2531 - "│ ◻ opt2 2532 - │ ◻ opt3 2533 - │ ◻ opt4 2534 - │ ... 2535 - └ 2536 - ", 2537 - "", 2538 - "", 2539 - "", 2540 - "│ ... 2541 - │ ◻ opt2 2542 - │ ◻ opt3 2543 - │ ◻ opt4 2544 - │ ◻ opt5 2545 - │ ... 2546 - └ 2547 - ", 2548 - "", 2549 - "", 2550 - "", 2551 - "│ ◻ opt3 2552 - │ ◻ opt4 2553 - │ ◻ opt5 2554 - │ ◻ opt6 2555 - │ ... 2556 - └ 2557 - ", 2558 - "", 2559 - "", 2560 - "", 2561 - "│ ◻ opt4 2562 - │ ◻ opt5 2563 - │ ◻ opt6 2564 - │ ◻ opt7 2565 - │ ... 2566 - └ 2567 - ", 2568 - "", 2569 - "", 2570 - "", 2571 - "│ ◼ opt6", 2572 - "", 2573 - "", 2574 - "", 2575 - "", 2576 - "◇ foo 2577 - │ opt6", 2578 - " 2579 - ", 2580 - "[?25h", 2581 - ] 2582 - `; 2583 - 2584 - exports[`prompts (isCI = true) > multiselect > renders message 1`] = ` 2585 - [ 2586 - "[?25l", 2587 - "│ 2588 - ◆ foo 2589 - │ ◻ opt0 2590 - │ ◻ opt1 2591 - └ 2592 - ", 2593 - "", 2594 - "", 2595 - "", 2596 - "│ ◼ opt0", 2597 - "", 2598 - "", 2599 - "", 2600 - "", 2601 - "◇ foo 2602 - │ opt0", 2603 - " 2604 - ", 2605 - "[?25h", 2606 - ] 2607 - `; 2608 - 2609 - exports[`prompts (isCI = true) > multiselect > renders multiple cancelled values 1`] = ` 2610 - [ 2611 - "[?25l", 2612 - "│ 2613 - ◆ foo 2614 - │ ◻ opt0 2615 - │ ◻ opt1 2616 - │ ◻ opt2 2617 - └ 2618 - ", 2619 - "", 2620 - "", 2621 - "", 2622 - "│ ◼ opt0", 2623 - "", 2624 - "", 2625 - "", 2626 - "", 2627 - "│ ◼ opt0 2628 - │ ◻ opt1 2629 - │ ◻ opt2 2630 - └ 2631 - ", 2632 - "", 2633 - "", 2634 - "", 2635 - "│ ◼ opt1", 2636 - "", 2637 - "", 2638 - "", 2639 - "", 2640 - "■ foo 2641 - │ opt0, opt1 2642 - │", 2643 - " 2644 - ", 2645 - "[?25h", 2646 - ] 2647 - `; 2648 - 2649 - exports[`prompts (isCI = true) > multiselect > renders multiple selected options 1`] = ` 2650 - [ 2651 - "[?25l", 2652 - "│ 2653 - ◆ foo 2654 - │ ◻ opt0 2655 - │ ◻ opt1 2656 - │ ◻ opt2 2657 - └ 2658 - ", 2659 - "", 2660 - "", 2661 - "", 2662 - "│ ◼ opt0", 2663 - "", 2664 - "", 2665 - "", 2666 - "", 2667 - "│ ◼ opt0 2668 - │ ◻ opt1 2669 - │ ◻ opt2 2670 - └ 2671 - ", 2672 - "", 2673 - "", 2674 - "", 2675 - "│ ◼ opt1", 2676 - "", 2677 - "", 2678 - "", 2679 - "", 2680 - "│ ◼ opt1 2681 - │ ◻ opt2 2682 - └ 2683 - ", 2684 - "", 2685 - "", 2686 - "", 2687 - "◇ foo 2688 - │ opt0, opt1", 2689 - " 2690 - ", 2691 - "[?25h", 2692 - ] 2693 - `; 2694 - 2695 - exports[`prompts (isCI = true) > multiselect > renders validation errors 1`] = ` 2696 - [ 2697 - "[?25l", 2698 - "│ 2699 - ◆ foo 2700 - │ ◻ opt0 2701 - │ ◻ opt1 2702 - └ 2703 - ", 2704 - "", 2705 - "", 2706 - "", 2707 - "▲ foo 2708 - │ ◻ opt0 2709 - │ ◻ opt1 2710 - └ Please select at least one option. 2711 - Press  space  to select,  enter  to submit 2712 - ", 2713 - "", 2714 - "", 2715 - "", 2716 - "◆ foo 2717 - │ ◼ opt0 2718 - │ ◻ opt1 2719 - └ 2720 - ", 2721 - "", 2722 - "", 2723 - "", 2724 - "◇ foo 2725 - │ opt0", 2726 - " 2727 - ", 2728 - "[?25h", 2729 - ] 2730 - `; 2731 - 2732 - exports[`prompts (isCI = true) > multiselect > shows hints for all selected options 1`] = ` 2733 - [ 2734 - "[?25l", 2735 - "│ 2736 - ◆ foo 2737 - │ ◼ opt0 (Hint 0) 2738 - │ ◼ opt1 (Hint 1) 2739 - │ ◻ opt2 2740 - └ 2741 - ", 2742 - "", 2743 - "", 2744 - "", 2745 - "│ ◼ opt0 (Hint 0) 2746 - │ ◼ opt1 (Hint 1) 2747 - │ ◻ opt2 2748 - └ 2749 - ", 2750 - "", 2751 - "", 2752 - "", 2753 - "│ ◼ opt1 (Hint 1) 2754 - │ ◻ opt2 (Hint 2) 2755 - └ 2756 - ", 2757 - "", 2758 - "", 2759 - "", 2760 - "◇ foo 2761 - │ opt0, opt1", 2762 - " 2763 - ", 2764 - "[?25h", 2765 - ] 2766 - `; 2767 - 2768 - exports[`prompts (isCI = true) > multiselect > sliding window loops downwards 1`] = ` 2769 - [ 2770 - "[?25l", 2771 - "│ 2772 - ◆ foo 2773 - │ ◻ opt0 2774 - │ ◻ opt1 2775 - │ ◻ opt2 2776 - │ ◻ opt3 2777 - │ ◻ opt4 2778 - │ ... 2779 - └ 2780 - ", 2781 - "", 2782 - "", 2783 - "", 2784 - "│ ◻ opt0 2785 - │ ◻ opt1 2786 - │ ◻ opt2 2787 - │ ◻ opt3 2788 - │ ◻ opt4 2789 - │ ... 2790 - └ 2791 - ", 2792 - "", 2793 - "", 2794 - "", 2795 - "│ ◻ opt1 2796 - │ ◻ opt2 2797 - │ ◻ opt3 2798 - │ ◻ opt4 2799 - │ ... 2800 - └ 2801 - ", 2802 - "", 2803 - "", 2804 - "", 2805 - "│ ◻ opt2 2806 - │ ◻ opt3 2807 - │ ◻ opt4 2808 - │ ... 2809 - └ 2810 - ", 2811 - "", 2812 - "", 2813 - "", 2814 - "│ ... 2815 - │ ◻ opt2 2816 - │ ◻ opt3 2817 - │ ◻ opt4 2818 - │ ◻ opt5 2819 - │ ... 2820 - └ 2821 - ", 2822 - "", 2823 - "", 2824 - "", 2825 - "│ ◻ opt3 2826 - │ ◻ opt4 2827 - │ ◻ opt5 2828 - │ ◻ opt6 2829 - │ ... 2830 - └ 2831 - ", 2832 - "", 2833 - "", 2834 - "", 2835 - "│ ◻ opt4 2836 - │ ◻ opt5 2837 - │ ◻ opt6 2838 - │ ◻ opt7 2839 - │ ... 2840 - └ 2841 - ", 2842 - "", 2843 - "", 2844 - "", 2845 - "│ ◻ opt5 2846 - │ ◻ opt6 2847 - │ ◻ opt7 2848 - │ ◻ opt8 2849 - │ ... 2850 - └ 2851 - ", 2852 - "", 2853 - "", 2854 - "", 2855 - "│ ◻ opt6 2856 - │ ◻ opt7 2857 - │ ◻ opt8 2858 - │ ◻ opt9 2859 - │ ... 2860 - └ 2861 - ", 2862 - "", 2863 - "", 2864 - "", 2865 - "│ ◻ opt7 2866 - │ ◻ opt8 2867 - │ ◻ opt9 2868 - │ ◻ opt10 2869 - │ ◻ opt11 2870 - └ 2871 - ", 2872 - "", 2873 - "", 2874 - "", 2875 - "│ ◻ opt9 2876 - │ ◻ opt10 2877 - │ ◻ opt11 2878 - └ 2879 - ", 2880 - "", 2881 - "", 2882 - "", 2883 - "│ ◻ opt10 2884 - │ ◻ opt11 2885 - └ 2886 - ", 2887 - "", 2888 - "", 2889 - "", 2890 - "│ ◻ opt0 2891 - │ ◻ opt1 2892 - │ ◻ opt2 2893 - │ ◻ opt3 2894 - │ ◻ opt4 2895 - │ ... 2896 - └ 2897 - ", 2898 - "", 2899 - "", 2900 - "", 2901 - "│ ◼ opt0", 2902 - "", 2903 - "", 2904 - "", 2905 - "", 2906 - "◇ foo 2907 - │ opt0", 2908 - " 2909 - ", 2910 - "[?25h", 2911 - ] 2912 - `; 2913 - 2914 - exports[`prompts (isCI = true) > multiselect > sliding window loops upwards 1`] = ` 2915 - [ 2916 - "[?25l", 2917 - "│ 2918 - ◆ foo 2919 - │ ◻ opt0 2920 - │ ◻ opt1 2921 - │ ◻ opt2 2922 - │ ◻ opt3 2923 - │ ◻ opt4 2924 - │ ... 2925 - └ 2926 - ", 2927 - "", 2928 - "", 2929 - "", 2930 - "│ ... 2931 - │ ◻ opt7 2932 - │ ◻ opt8 2933 - │ ◻ opt9 2934 - │ ◻ opt10 2935 - │ ◻ opt11 2936 - └ 2937 - ", 2938 - "", 2939 - "", 2940 - "", 2941 - "│ ◼ opt11", 2942 - "", 2943 - "", 2944 - "", 2945 - "", 2946 - "◇ foo 2947 - │ opt11", 2948 - " 2949 - ", 2950 - "[?25h", 2951 - ] 2952 - `; 2953 - 2954 - exports[`prompts (isCI = true) > password > renders and clears validation errors 1`] = ` 2955 - [ 2956 - "[?25l", 2957 - "│ 2958 - ◆ foo 2959 - │ _ 2960 - └ 2961 - ", 2962 - "", 2963 - "", 2964 - "", 2965 - "│ ▪_", 2966 - "", 2967 - "", 2968 - "", 2969 - "", 2970 - "▲ foo 2971 - │ ▪ 2972 - └ Password must be at least 2 characters 2973 - ", 2974 - "", 2975 - "", 2976 - "", 2977 - "◆ foo 2978 - │ ▪▪_ 2979 - └ 2980 - ", 2981 - "", 2982 - "", 2983 - "", 2984 - "◇ foo 2985 - │ ▪▪", 2986 - " 2987 - ", 2988 - "[?25h", 2989 - ] 2990 - `; 2991 - 2992 - exports[`prompts (isCI = true) > password > renders cancelled value 1`] = ` 2993 - [ 2994 - "[?25l", 2995 - "│ 2996 - ◆ foo 2997 - │ _ 2998 - └ 2999 - ", 3000 - "", 3001 - "", 3002 - "", 3003 - "│ ▪_", 3004 - "", 3005 - "", 3006 - "", 3007 - "", 3008 - "■ foo 3009 - │ ▪ 3010 - │", 3011 - " 3012 - ", 3013 - "[?25h", 3014 - ] 3015 - `; 3016 - 3017 - exports[`prompts (isCI = true) > password > renders custom mask 1`] = ` 3018 - [ 3019 - "[?25l", 3020 - "│ 3021 - ◆ foo 3022 - │ _ 3023 - └ 3024 - ", 3025 - "", 3026 - "", 3027 - "", 3028 - "│ *_", 3029 - "", 3030 - "", 3031 - "", 3032 - "", 3033 - "│ **_", 3034 - "", 3035 - "", 3036 - "", 3037 - "", 3038 - "◇ foo 3039 - │ **", 3040 - " 3041 - ", 3042 - "[?25h", 3043 - ] 3044 - `; 3045 - 3046 - exports[`prompts (isCI = true) > password > renders masked value 1`] = ` 3047 - [ 3048 - "[?25l", 3049 - "│ 3050 - ◆ foo 3051 - │ _ 3052 - └ 3053 - ", 3054 - "", 3055 - "", 3056 - "", 3057 - "│ ▪_", 3058 - "", 3059 - "", 3060 - "", 3061 - "", 3062 - "│ ▪▪_", 3063 - "", 3064 - "", 3065 - "", 3066 - "", 3067 - "◇ foo 3068 - │ ▪▪", 3069 - " 3070 - ", 3071 - "[?25h", 3072 - ] 3073 - `; 3074 - 3075 - exports[`prompts (isCI = true) > password > renders message 1`] = ` 3076 - [ 3077 - "[?25l", 3078 - "│ 3079 - ◆ foo 3080 - │ _ 3081 - └ 3082 - ", 3083 - "", 3084 - "", 3085 - "", 3086 - "◇ foo 3087 - │", 3088 - " 3089 - ", 3090 - "[?25h", 3091 - ] 3092 - `; 3093 - 3094 - exports[`prompts (isCI = true) > select > can cancel 1`] = ` 3095 - [ 3096 - "[?25l", 3097 - "│ 3098 - ◆ foo 3099 - │ ● opt0 3100 - │ ○ opt1 3101 - └ 3102 - ", 3103 - "", 3104 - "", 3105 - "", 3106 - "■ foo 3107 - │ opt0 3108 - │", 3109 - " 3110 - ", 3111 - "[?25h", 3112 - ] 3113 - `; 3114 - 3115 - exports[`prompts (isCI = true) > select > down arrow selects next option 1`] = ` 3116 - [ 3117 - "[?25l", 3118 - "│ 3119 - ◆ foo 3120 - │ ● opt0 3121 - │ ○ opt1 3122 - └ 3123 - ", 3124 - "", 3125 - "", 3126 - "", 3127 - "│ ○ opt0 3128 - │ ● opt1 3129 - └ 3130 - ", 3131 - "", 3132 - "", 3133 - "", 3134 - "◇ foo 3135 - │ opt1", 3136 - " 3137 - ", 3138 - "[?25h", 3139 - ] 3140 - `; 3141 - 3142 - exports[`prompts (isCI = true) > select > renders option hints 1`] = ` 3143 - [ 3144 - "[?25l", 3145 - "│ 3146 - ◆ foo 3147 - │ ● opt0 (Hint 0) 3148 - │ ○ opt1 3149 - └ 3150 - ", 3151 - "", 3152 - "", 3153 - "", 3154 - "◇ foo 3155 - │ opt0", 3156 - " 3157 - ", 3158 - "[?25h", 3159 - ] 3160 - `; 3161 - 3162 - exports[`prompts (isCI = true) > select > renders option labels 1`] = ` 3163 - [ 3164 - "[?25l", 3165 - "│ 3166 - ◆ foo 3167 - │ ● Option 0 3168 - │ ○ Option 1 3169 - └ 3170 - ", 3171 - "", 3172 - "", 3173 - "", 3174 - "◇ foo 3175 - │ Option 0", 3176 - " 3177 - ", 3178 - "[?25h", 3179 - ] 3180 - `; 3181 - 3182 - exports[`prompts (isCI = true) > select > renders options and message 1`] = ` 3183 - [ 3184 - "[?25l", 3185 - "│ 3186 - ◆ foo 3187 - │ ● opt0 3188 - │ ○ opt1 3189 - └ 3190 - ", 3191 - "", 3192 - "", 3193 - "", 3194 - "◇ foo 3195 - │ opt0", 3196 - " 3197 - ", 3198 - "[?25h", 3199 - ] 3200 - `; 3201 - 3202 - exports[`prompts (isCI = true) > select > up arrow selects previous option 1`] = ` 3203 - [ 3204 - "[?25l", 3205 - "│ 3206 - ◆ foo 3207 - │ ● opt0 3208 - │ ○ opt1 3209 - └ 3210 - ", 3211 - "", 3212 - "", 3213 - "", 3214 - "│ ○ opt0 3215 - │ ● opt1 3216 - └ 3217 - ", 3218 - "", 3219 - "", 3220 - "", 3221 - "│ ● opt0 3222 - │ ○ opt1 3223 - └ 3224 - ", 3225 - "", 3226 - "", 3227 - "", 3228 - "◇ foo 3229 - │ opt0", 3230 - " 3231 - ", 3232 - "[?25h", 3233 - ] 3234 - `; 3235 - 3236 - exports[`prompts (isCI = true) > spinner > message > sets message for next frame 1`] = ` 3237 - [ 3238 - "[?25l", 3239 - "│ 3240 - ", 3241 - "◒ ...", 3242 - " 3243 - ", 3244 - "", 3245 - "", 3246 - "◐ foo...", 3247 - ] 3248 - `; 3249 - 3250 - exports[`prompts (isCI = true) > spinner > start > renders frames at interval 1`] = ` 3251 - [ 3252 - "[?25l", 3253 - "│ 3254 - ", 3255 - "◒ ...", 3256 - ] 3257 - `; 3258 - 3259 - exports[`prompts (isCI = true) > spinner > start > renders message 1`] = ` 3260 - [ 3261 - "[?25l", 3262 - "│ 3263 - ", 3264 - "◒ foo...", 3265 - ] 3266 - `; 3267 - 3268 - exports[`prompts (isCI = true) > spinner > start > renders timer when indicator is "timer" 1`] = ` 3269 - [ 3270 - "[?25l", 3271 - "│ 3272 - ", 3273 - "◒ ...", 3274 - ] 3275 - `; 3276 - 3277 - exports[`prompts (isCI = true) > spinner > stop > renders cancel symbol if code = 1 1`] = ` 3278 - [ 3279 - "[?25l", 3280 - "│ 3281 - ", 3282 - "◒ ...", 3283 - " 3284 - ", 3285 - "", 3286 - "", 3287 - "■ 3288 - ", 3289 - "[?25h", 3290 - ] 3291 - `; 3292 - 3293 - exports[`prompts (isCI = true) > spinner > stop > renders error symbol if code > 1 1`] = ` 3294 - [ 3295 - "[?25l", 3296 - "│ 3297 - ", 3298 - "◒ ...", 3299 - " 3300 - ", 3301 - "", 3302 - "", 3303 - "▲ 3304 - ", 3305 - "[?25h", 3306 - ] 3307 - `; 3308 - 3309 - exports[`prompts (isCI = true) > spinner > stop > renders message 1`] = ` 3310 - [ 3311 - "[?25l", 3312 - "│ 3313 - ", 3314 - "◒ ...", 3315 - " 3316 - ", 3317 - "", 3318 - "", 3319 - "◇ foo 3320 - ", 3321 - "[?25h", 3322 - ] 3323 - `; 3324 - 3325 - exports[`prompts (isCI = true) > spinner > stop > renders submit symbol and stops spinner 1`] = ` 3326 - [ 3327 - "[?25l", 3328 - "│ 3329 - ", 3330 - "◒ ...", 3331 - " 3332 - ", 3333 - "", 3334 - "", 3335 - "◇ 3336 - ", 3337 - "[?25h", 3338 - ] 3339 - `; 3340 - 3341 - exports[`prompts (isCI = true) > text > can cancel 1`] = ` 3342 - [ 3343 - "[?25l", 3344 - "│ 3345 - ◆ foo 3346 - │ _ 3347 - └ 3348 - ", 3349 - "", 3350 - "", 3351 - "", 3352 - "■ foo 3353 - │", 3354 - " 3355 - ", 3356 - "[?25h", 3357 - ] 3358 - `; 3359 - 3360 - exports[`prompts (isCI = true) > text > defaultValue sets the value but does not render 1`] = ` 3361 - [ 3362 - "[?25l", 3363 - "│ 3364 - ◆ foo 3365 - │ _ 3366 - └ 3367 - ", 3368 - "", 3369 - "", 3370 - "", 3371 - "◇ foo 3372 - │ bar", 3373 - " 3374 - ", 3375 - "[?25h", 3376 - ] 3377 - `; 3378 - 3379 - exports[`prompts (isCI = true) > text > renders cancelled value if one set 1`] = ` 3380 - [ 3381 - "[?25l", 3382 - "│ 3383 - ◆ foo 3384 - │ _ 3385 - └ 3386 - ", 3387 - "", 3388 - "", 3389 - "", 3390 - "│ x█", 3391 - "", 3392 - "", 3393 - "", 3394 - "", 3395 - "│ xy█", 3396 - "", 3397 - "", 3398 - "", 3399 - "", 3400 - "■ foo 3401 - │ xy 3402 - │", 3403 - " 3404 - ", 3405 - "[?25h", 3406 - ] 3407 - `; 3408 - 3409 - exports[`prompts (isCI = true) > text > renders message 1`] = ` 3410 - [ 3411 - "[?25l", 3412 - "│ 3413 - ◆ foo 3414 - │ _ 3415 - └ 3416 - ", 3417 - "", 3418 - "", 3419 - "", 3420 - "◇ foo 3421 - │ undefined", 3422 - " 3423 - ", 3424 - "[?25h", 3425 - ] 3426 - `; 3427 - 3428 - exports[`prompts (isCI = true) > text > renders placeholder if set 1`] = ` 3429 - [ 3430 - "[?25l", 3431 - "│ 3432 - ◆ foo 3433 - │ bar 3434 - └ 3435 - ", 3436 - "", 3437 - "", 3438 - "", 3439 - "◇ foo 3440 - │ bar", 3441 - " 3442 - ", 3443 - "[?25h", 3444 - ] 3445 - `; 3446 - 3447 - exports[`prompts (isCI = true) > text > renders submitted value 1`] = ` 3448 - [ 3449 - "[?25l", 3450 - "│ 3451 - ◆ foo 3452 - │ _ 3453 - └ 3454 - ", 3455 - "", 3456 - "", 3457 - "", 3458 - "│ x█", 3459 - "", 3460 - "", 3461 - "", 3462 - "", 3463 - "│ xy█", 3464 - "", 3465 - "", 3466 - "", 3467 - "", 3468 - "◇ foo 3469 - │ xy", 3470 - " 3471 - ", 3472 - "[?25h", 3473 - ] 3474 - `; 3475 - 3476 - exports[`prompts (isCI = true) > text > validation errors render and clear (using Error) 1`] = ` 3477 - [ 3478 - "[?25l", 3479 - "│ 3480 - ◆ foo 3481 - │ _ 3482 - └ 3483 - ", 3484 - "", 3485 - "", 3486 - "", 3487 - "│ x█", 3488 - "", 3489 - "", 3490 - "", 3491 - "", 3492 - "▲ foo 3493 - │ x█ 3494 - └ should be xy 3495 - ", 3496 - "", 3497 - "", 3498 - "", 3499 - "◆ foo 3500 - │ xy█ 3501 - └ 3502 - ", 3503 - "", 3504 - "", 3505 - "", 3506 - "◇ foo 3507 - │ xy", 3508 - " 3509 - ", 3510 - "[?25h", 3511 - ] 3512 - `; 3513 - 3514 - exports[`prompts (isCI = true) > text > validation errors render and clear 1`] = ` 3515 - [ 3516 - "[?25l", 3517 - "│ 3518 - ◆ foo 3519 - │ _ 3520 - └ 3521 - ", 3522 - "", 3523 - "", 3524 - "", 3525 - "│ x█", 3526 - "", 3527 - "", 3528 - "", 3529 - "", 3530 - "▲ foo 3531 - │ x█ 3532 - └ should be xy 3533 - ", 3534 - "", 3535 - "", 3536 - "", 3537 - "◆ foo 3538 - │ xy█ 3539 - └ 3540 - ", 3541 - "", 3542 - "", 3543 - "", 3544 - "◇ foo 3545 - │ xy", 3546 - " 3547 - ", 3548 - "[?25h", 3549 - ] 3550 - `;
-1208
packages/prompts/src/index.test.ts
··· 1 - import { Readable, Writable } from 'node:stream'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from './index.js'; 4 - 5 - // TODO (43081j): move this into a util? 6 - class MockWritable extends Writable { 7 - public buffer: string[] = []; 8 - 9 - _write( 10 - chunk: any, 11 - _encoding: BufferEncoding, 12 - callback: (error?: Error | null | undefined) => void 13 - ): void { 14 - this.buffer.push(chunk.toString()); 15 - callback(); 16 - } 17 - } 18 - 19 - class MockReadable extends Readable { 20 - protected _buffer: unknown[] | null = []; 21 - 22 - _read() { 23 - if (this._buffer === null) { 24 - this.push(null); 25 - return; 26 - } 27 - 28 - for (const val of this._buffer) { 29 - this.push(val); 30 - } 31 - 32 - this._buffer = []; 33 - } 34 - 35 - pushValue(val: unknown): void { 36 - this._buffer?.push(val); 37 - } 38 - 39 - close(): void { 40 - this._buffer = null; 41 - } 42 - } 43 - 44 - describe.each(['true', 'false'])('prompts (isCI = %s)', (isCI) => { 45 - let originalCI: string | undefined; 46 - let output: MockWritable; 47 - let input: MockReadable; 48 - 49 - beforeAll(() => { 50 - originalCI = process.env.CI; 51 - process.env.CI = isCI; 52 - }); 53 - 54 - afterAll(() => { 55 - process.env.CI = originalCI; 56 - }); 57 - 58 - beforeEach(() => { 59 - output = new MockWritable(); 60 - input = new MockReadable(); 61 - }); 62 - 63 - afterEach(() => { 64 - vi.restoreAllMocks(); 65 - }); 66 - 67 - describe('spinner', () => { 68 - beforeEach(() => { 69 - vi.useFakeTimers(); 70 - }); 71 - 72 - afterEach(() => { 73 - vi.useRealTimers(); 74 - }); 75 - 76 - test('returns spinner API', () => { 77 - const api = prompts.spinner({ output }); 78 - 79 - expect(api.stop).toBeTypeOf('function'); 80 - expect(api.start).toBeTypeOf('function'); 81 - expect(api.message).toBeTypeOf('function'); 82 - }); 83 - 84 - describe('start', () => { 85 - test('renders frames at interval', () => { 86 - const result = prompts.spinner({ output }); 87 - 88 - result.start(); 89 - 90 - // there are 4 frames 91 - for (let i = 0; i < 4; i++) { 92 - vi.advanceTimersByTime(80); 93 - } 94 - 95 - expect(output.buffer).toMatchSnapshot(); 96 - }); 97 - 98 - test('renders message', () => { 99 - const result = prompts.spinner({ output }); 100 - 101 - result.start('foo'); 102 - 103 - vi.advanceTimersByTime(80); 104 - 105 - expect(output.buffer).toMatchSnapshot(); 106 - }); 107 - 108 - test('renders timer when indicator is "timer"', () => { 109 - const result = prompts.spinner({ output, indicator: 'timer' }); 110 - 111 - result.start(); 112 - 113 - vi.advanceTimersByTime(80); 114 - 115 - expect(output.buffer).toMatchSnapshot(); 116 - }); 117 - }); 118 - 119 - describe('stop', () => { 120 - test('renders submit symbol and stops spinner', () => { 121 - const result = prompts.spinner({ output }); 122 - 123 - result.start(); 124 - 125 - vi.advanceTimersByTime(80); 126 - 127 - result.stop(); 128 - 129 - vi.advanceTimersByTime(80); 130 - 131 - expect(output.buffer).toMatchSnapshot(); 132 - }); 133 - 134 - test('renders cancel symbol if code = 1', () => { 135 - const result = prompts.spinner({ output }); 136 - 137 - result.start(); 138 - 139 - vi.advanceTimersByTime(80); 140 - 141 - result.stop('', 1); 142 - 143 - expect(output.buffer).toMatchSnapshot(); 144 - }); 145 - 146 - test('renders error symbol if code > 1', () => { 147 - const result = prompts.spinner({ output }); 148 - 149 - result.start(); 150 - 151 - vi.advanceTimersByTime(80); 152 - 153 - result.stop('', 2); 154 - 155 - expect(output.buffer).toMatchSnapshot(); 156 - }); 157 - 158 - test('renders message', () => { 159 - const result = prompts.spinner({ output }); 160 - 161 - result.start(); 162 - 163 - vi.advanceTimersByTime(80); 164 - 165 - result.stop('foo'); 166 - 167 - expect(output.buffer).toMatchSnapshot(); 168 - }); 169 - }); 170 - 171 - describe('message', () => { 172 - test('sets message for next frame', () => { 173 - const result = prompts.spinner({ output }); 174 - 175 - result.start(); 176 - 177 - vi.advanceTimersByTime(80); 178 - 179 - result.message('foo'); 180 - 181 - vi.advanceTimersByTime(80); 182 - 183 - expect(output.buffer).toMatchSnapshot(); 184 - }); 185 - }); 186 - }); 187 - 188 - describe('text', () => { 189 - test('renders message', async () => { 190 - const result = prompts.text({ 191 - message: 'foo', 192 - input, 193 - output, 194 - }); 195 - 196 - input.emit('keypress', '', { name: 'return' }); 197 - 198 - await result; 199 - 200 - expect(output.buffer).toMatchSnapshot(); 201 - }); 202 - 203 - test('renders placeholder if set', async () => { 204 - const result = prompts.text({ 205 - message: 'foo', 206 - placeholder: 'bar', 207 - input, 208 - output, 209 - }); 210 - 211 - input.emit('keypress', '', { name: 'return' }); 212 - 213 - const value = await result; 214 - 215 - expect(output.buffer).toMatchSnapshot(); 216 - 217 - expect(value).toBe('bar'); 218 - }); 219 - 220 - test('<tab> applies placeholder', async () => { 221 - const result = prompts.text({ 222 - message: 'foo', 223 - placeholder: 'bar', 224 - input, 225 - output, 226 - }); 227 - 228 - input.emit('keypress', '\t', { name: 'tab' }); 229 - input.emit('keypress', '', { name: 'return' }); 230 - 231 - const value = await result; 232 - 233 - expect(value).toBe('bar'); 234 - }); 235 - 236 - test('can cancel', async () => { 237 - const result = prompts.text({ 238 - message: 'foo', 239 - input, 240 - output, 241 - }); 242 - 243 - input.emit('keypress', 'escape', { name: 'escape' }); 244 - 245 - const value = await result; 246 - 247 - expect(prompts.isCancel(value)).toBe(true); 248 - expect(output.buffer).toMatchSnapshot(); 249 - }); 250 - 251 - test('renders cancelled value if one set', async () => { 252 - const result = prompts.text({ 253 - message: 'foo', 254 - input, 255 - output, 256 - }); 257 - 258 - input.emit('keypress', 'x', { name: 'x' }); 259 - input.emit('keypress', 'y', { name: 'y' }); 260 - input.emit('keypress', '', { name: 'escape' }); 261 - 262 - const value = await result; 263 - 264 - expect(prompts.isCancel(value)).toBe(true); 265 - expect(output.buffer).toMatchSnapshot(); 266 - }); 267 - 268 - test('renders submitted value', async () => { 269 - const result = prompts.text({ 270 - message: 'foo', 271 - input, 272 - output, 273 - }); 274 - 275 - input.emit('keypress', 'x', { name: 'x' }); 276 - input.emit('keypress', 'y', { name: 'y' }); 277 - input.emit('keypress', '', { name: 'return' }); 278 - 279 - const value = await result; 280 - 281 - expect(value).toBe('xy'); 282 - expect(output.buffer).toMatchSnapshot(); 283 - }); 284 - 285 - test('defaultValue sets the value but does not render', async () => { 286 - const result = prompts.text({ 287 - message: 'foo', 288 - defaultValue: 'bar', 289 - input, 290 - output, 291 - }); 292 - 293 - input.emit('keypress', '', { name: 'return' }); 294 - 295 - const value = await result; 296 - 297 - expect(value).toBe('bar'); 298 - expect(output.buffer).toMatchSnapshot(); 299 - }); 300 - 301 - test('validation errors render and clear', async () => { 302 - const result = prompts.text({ 303 - message: 'foo', 304 - validate: (val) => (val !== 'xy' ? 'should be xy' : undefined), 305 - input, 306 - output, 307 - }); 308 - 309 - input.emit('keypress', 'x', { name: 'x' }); 310 - input.emit('keypress', '', { name: 'return' }); 311 - input.emit('keypress', 'y', { name: 'y' }); 312 - input.emit('keypress', '', { name: 'return' }); 313 - 314 - const value = await result; 315 - 316 - expect(value).toBe('xy'); 317 - expect(output.buffer).toMatchSnapshot(); 318 - }); 319 - 320 - test('validation errors render and clear (using Error)', async () => { 321 - const result = prompts.text({ 322 - message: 'foo', 323 - validate: (val) => (val !== 'xy' ? new Error('should be xy') : undefined), 324 - input, 325 - output, 326 - }); 327 - 328 - input.emit('keypress', 'x', { name: 'x' }); 329 - input.emit('keypress', '', { name: 'return' }); 330 - input.emit('keypress', 'y', { name: 'y' }); 331 - input.emit('keypress', '', { name: 'return' }); 332 - 333 - const value = await result; 334 - 335 - expect(value).toBe('xy'); 336 - expect(output.buffer).toMatchSnapshot(); 337 - }); 338 - }); 339 - 340 - describe('confirm', () => { 341 - test('renders message with choices', async () => { 342 - const result = prompts.confirm({ 343 - message: 'foo', 344 - input, 345 - output, 346 - }); 347 - 348 - input.emit('keypress', '', { name: 'return' }); 349 - 350 - const value = await result; 351 - 352 - expect(value).toBe(true); 353 - expect(output.buffer).toMatchSnapshot(); 354 - }); 355 - 356 - test('renders custom active choice', async () => { 357 - const result = prompts.confirm({ 358 - message: 'foo', 359 - active: 'bleep', 360 - input, 361 - output, 362 - }); 363 - 364 - input.emit('keypress', '', { name: 'return' }); 365 - 366 - const value = await result; 367 - 368 - expect(value).toBe(true); 369 - expect(output.buffer).toMatchSnapshot(); 370 - }); 371 - 372 - test('renders custom inactive choice', async () => { 373 - const result = prompts.confirm({ 374 - message: 'foo', 375 - inactive: 'bleep', 376 - input, 377 - output, 378 - }); 379 - 380 - input.emit('keypress', '', { name: 'return' }); 381 - 382 - const value = await result; 383 - 384 - expect(value).toBe(true); 385 - expect(output.buffer).toMatchSnapshot(); 386 - }); 387 - 388 - test('right arrow moves to next choice', async () => { 389 - const result = prompts.confirm({ 390 - message: 'foo', 391 - input, 392 - output, 393 - }); 394 - 395 - input.emit('keypress', 'right', { name: 'right' }); 396 - input.emit('keypress', '', { name: 'return' }); 397 - 398 - const value = await result; 399 - 400 - expect(value).toBe(false); 401 - expect(output.buffer).toMatchSnapshot(); 402 - }); 403 - 404 - test('left arrow moves to previous choice', async () => { 405 - const result = prompts.confirm({ 406 - message: 'foo', 407 - input, 408 - output, 409 - }); 410 - 411 - input.emit('keypress', 'right', { name: 'right' }); 412 - input.emit('keypress', 'left', { name: 'left' }); 413 - input.emit('keypress', '', { name: 'return' }); 414 - 415 - const value = await result; 416 - 417 - expect(value).toBe(true); 418 - expect(output.buffer).toMatchSnapshot(); 419 - }); 420 - 421 - test('can cancel', async () => { 422 - const result = prompts.confirm({ 423 - message: 'foo', 424 - input, 425 - output, 426 - }); 427 - 428 - input.emit('keypress', 'escape', { name: 'escape' }); 429 - 430 - const value = await result; 431 - 432 - expect(prompts.isCancel(value)).toBe(true); 433 - expect(output.buffer).toMatchSnapshot(); 434 - }); 435 - 436 - test('can set initialValue', async () => { 437 - const result = prompts.confirm({ 438 - message: 'foo', 439 - initialValue: false, 440 - input, 441 - output, 442 - }); 443 - 444 - input.emit('keypress', '', { name: 'return' }); 445 - 446 - const value = await result; 447 - 448 - expect(value).toBe(false); 449 - expect(output.buffer).toMatchSnapshot(); 450 - }); 451 - }); 452 - 453 - describe('select', () => { 454 - test('renders options and message', async () => { 455 - const result = prompts.select({ 456 - message: 'foo', 457 - options: [{ value: 'opt0' }, { value: 'opt1' }], 458 - input, 459 - output, 460 - }); 461 - 462 - input.emit('keypress', '', { name: 'return' }); 463 - 464 - const value = await result; 465 - 466 - expect(value).toBe('opt0'); 467 - expect(output.buffer).toMatchSnapshot(); 468 - }); 469 - 470 - test('down arrow selects next option', async () => { 471 - const result = prompts.select({ 472 - message: 'foo', 473 - options: [{ value: 'opt0' }, { value: 'opt1' }], 474 - input, 475 - output, 476 - }); 477 - 478 - input.emit('keypress', '', { name: 'down' }); 479 - input.emit('keypress', '', { name: 'return' }); 480 - 481 - const value = await result; 482 - 483 - expect(value).toBe('opt1'); 484 - expect(output.buffer).toMatchSnapshot(); 485 - }); 486 - 487 - test('up arrow selects previous option', async () => { 488 - const result = prompts.select({ 489 - message: 'foo', 490 - options: [{ value: 'opt0' }, { value: 'opt1' }], 491 - input, 492 - output, 493 - }); 494 - 495 - input.emit('keypress', '', { name: 'down' }); 496 - input.emit('keypress', '', { name: 'up' }); 497 - input.emit('keypress', '', { name: 'return' }); 498 - 499 - const value = await result; 500 - 501 - expect(value).toBe('opt0'); 502 - expect(output.buffer).toMatchSnapshot(); 503 - }); 504 - 505 - test('can cancel', async () => { 506 - const result = prompts.select({ 507 - message: 'foo', 508 - options: [{ value: 'opt0' }, { value: 'opt1' }], 509 - input, 510 - output, 511 - }); 512 - 513 - input.emit('keypress', 'escape', { name: 'escape' }); 514 - 515 - const value = await result; 516 - 517 - expect(prompts.isCancel(value)).toBe(true); 518 - expect(output.buffer).toMatchSnapshot(); 519 - }); 520 - 521 - test('renders option labels', async () => { 522 - const result = prompts.select({ 523 - message: 'foo', 524 - options: [ 525 - { value: 'opt0', label: 'Option 0' }, 526 - { value: 'opt1', label: 'Option 1' }, 527 - ], 528 - input, 529 - output, 530 - }); 531 - 532 - input.emit('keypress', '', { name: 'return' }); 533 - 534 - const value = await result; 535 - 536 - expect(value).toBe('opt0'); 537 - expect(output.buffer).toMatchSnapshot(); 538 - }); 539 - 540 - test('renders option hints', async () => { 541 - const result = prompts.select({ 542 - message: 'foo', 543 - options: [ 544 - { value: 'opt0', hint: 'Hint 0' }, 545 - { value: 'opt1', hint: 'Hint 1' }, 546 - ], 547 - input, 548 - output, 549 - }); 550 - 551 - input.emit('keypress', '', { name: 'return' }); 552 - 553 - const value = await result; 554 - 555 - expect(value).toBe('opt0'); 556 - expect(output.buffer).toMatchSnapshot(); 557 - }); 558 - }); 559 - 560 - describe('multiselect', () => { 561 - test('renders message', async () => { 562 - const result = prompts.multiselect({ 563 - message: 'foo', 564 - options: [{ value: 'opt0' }, { value: 'opt1' }], 565 - input, 566 - output, 567 - }); 568 - 569 - input.emit('keypress', '', { name: 'space' }); 570 - input.emit('keypress', '', { name: 'return' }); 571 - 572 - const value = await result; 573 - 574 - expect(value).toEqual(['opt0']); 575 - expect(output.buffer).toMatchSnapshot(); 576 - }); 577 - 578 - test('renders multiple selected options', async () => { 579 - const result = prompts.multiselect({ 580 - message: 'foo', 581 - options: [{ value: 'opt0' }, { value: 'opt1' }, { value: 'opt2' }], 582 - input, 583 - output, 584 - }); 585 - 586 - input.emit('keypress', '', { name: 'space' }); 587 - input.emit('keypress', '', { name: 'down' }); 588 - input.emit('keypress', '', { name: 'space' }); 589 - input.emit('keypress', '', { name: 'down' }); 590 - input.emit('keypress', '', { name: 'return' }); 591 - 592 - const value = await result; 593 - 594 - expect(value).toEqual(['opt0', 'opt1']); 595 - expect(output.buffer).toMatchSnapshot(); 596 - }); 597 - 598 - test('can cancel', async () => { 599 - const result = prompts.multiselect({ 600 - message: 'foo', 601 - options: [{ value: 'opt0' }, { value: 'opt1' }], 602 - input, 603 - output, 604 - }); 605 - 606 - input.emit('keypress', 'escape', { name: 'escape' }); 607 - 608 - const value = await result; 609 - 610 - expect(prompts.isCancel(value)).toBe(true); 611 - expect(output.buffer).toMatchSnapshot(); 612 - }); 613 - 614 - test('renders validation errors', async () => { 615 - const result = prompts.multiselect({ 616 - message: 'foo', 617 - options: [{ value: 'opt0' }, { value: 'opt1' }], 618 - input, 619 - output, 620 - }); 621 - 622 - // try submit with nothing selected 623 - input.emit('keypress', '', { name: 'return' }); 624 - // select and submit 625 - input.emit('keypress', '', { name: 'space' }); 626 - input.emit('keypress', '', { name: 'return' }); 627 - 628 - const value = await result; 629 - 630 - expect(value).toEqual(['opt0']); 631 - expect(output.buffer).toMatchSnapshot(); 632 - }); 633 - 634 - test('can submit without selection when required = false', async () => { 635 - const result = prompts.multiselect({ 636 - message: 'foo', 637 - options: [{ value: 'opt0' }, { value: 'opt1' }], 638 - required: false, 639 - input, 640 - output, 641 - }); 642 - 643 - input.emit('keypress', '', { name: 'return' }); 644 - 645 - const value = await result; 646 - 647 - expect(value).toEqual([]); 648 - expect(output.buffer).toMatchSnapshot(); 649 - }); 650 - 651 - test('can set cursorAt to preselect an option', async () => { 652 - const result = prompts.multiselect({ 653 - message: 'foo', 654 - options: [{ value: 'opt0' }, { value: 'opt1' }], 655 - cursorAt: 'opt1', 656 - input, 657 - output, 658 - }); 659 - 660 - input.emit('keypress', '', { name: 'space' }); 661 - input.emit('keypress', '', { name: 'return' }); 662 - 663 - const value = await result; 664 - 665 - expect(value).toEqual(['opt1']); 666 - expect(output.buffer).toMatchSnapshot(); 667 - }); 668 - 669 - test('can set initial values', async () => { 670 - const result = prompts.multiselect({ 671 - message: 'foo', 672 - options: [{ value: 'opt0' }, { value: 'opt1' }], 673 - initialValues: ['opt1'], 674 - input, 675 - output, 676 - }); 677 - 678 - input.emit('keypress', '', { name: 'return' }); 679 - 680 - const value = await result; 681 - 682 - expect(value).toEqual(['opt1']); 683 - expect(output.buffer).toMatchSnapshot(); 684 - }); 685 - 686 - test('maxItems renders a sliding window', async () => { 687 - const result = prompts.multiselect({ 688 - message: 'foo', 689 - options: [...Array(12).keys()].map((k) => ({ 690 - value: `opt${k}`, 691 - })), 692 - maxItems: 6, 693 - input, 694 - output, 695 - }); 696 - 697 - for (let i = 0; i < 6; i++) { 698 - input.emit('keypress', '', { name: 'down' }); 699 - } 700 - input.emit('keypress', '', { name: 'space' }); 701 - input.emit('keypress', '', { name: 'return' }); 702 - 703 - const value = await result; 704 - 705 - expect(value).toEqual(['opt6']); 706 - expect(output.buffer).toMatchSnapshot(); 707 - }); 708 - 709 - test('sliding window loops upwards', async () => { 710 - const result = prompts.multiselect({ 711 - message: 'foo', 712 - options: [...Array(12).keys()].map((k) => ({ 713 - value: `opt${k}`, 714 - })), 715 - maxItems: 6, 716 - input, 717 - output, 718 - }); 719 - 720 - input.emit('keypress', '', { name: 'up' }); 721 - input.emit('keypress', '', { name: 'space' }); 722 - input.emit('keypress', '', { name: 'return' }); 723 - 724 - const value = await result; 725 - 726 - expect(value).toEqual(['opt11']); 727 - expect(output.buffer).toMatchSnapshot(); 728 - }); 729 - 730 - test('sliding window loops downwards', async () => { 731 - const result = prompts.multiselect({ 732 - message: 'foo', 733 - options: [...Array(12).keys()].map((k) => ({ 734 - value: `opt${k}`, 735 - })), 736 - maxItems: 6, 737 - input, 738 - output, 739 - }); 740 - 741 - for (let i = 0; i < 12; i++) { 742 - input.emit('keypress', '', { name: 'down' }); 743 - } 744 - input.emit('keypress', '', { name: 'space' }); 745 - input.emit('keypress', '', { name: 'return' }); 746 - 747 - const value = await result; 748 - 749 - expect(value).toEqual(['opt0']); 750 - expect(output.buffer).toMatchSnapshot(); 751 - }); 752 - 753 - test('can set custom labels', async () => { 754 - const result = prompts.multiselect({ 755 - message: 'foo', 756 - options: [ 757 - { value: 'opt0', label: 'Option 0' }, 758 - { value: 'opt1', label: 'Option 1' }, 759 - ], 760 - input, 761 - output, 762 - }); 763 - 764 - input.emit('keypress', '', { name: 'space' }); 765 - input.emit('keypress', '', { name: 'return' }); 766 - 767 - const value = await result; 768 - 769 - expect(value).toEqual(['opt0']); 770 - expect(output.buffer).toMatchSnapshot(); 771 - }); 772 - 773 - test('can render option hints', async () => { 774 - const result = prompts.multiselect({ 775 - message: 'foo', 776 - options: [ 777 - { value: 'opt0', hint: 'Hint 0' }, 778 - { value: 'opt1', hint: 'Hint 1' }, 779 - ], 780 - input, 781 - output, 782 - }); 783 - 784 - input.emit('keypress', '', { name: 'space' }); 785 - input.emit('keypress', '', { name: 'return' }); 786 - 787 - const value = await result; 788 - 789 - expect(value).toEqual(['opt0']); 790 - expect(output.buffer).toMatchSnapshot(); 791 - }); 792 - 793 - test('shows hints for all selected options', async () => { 794 - const result = prompts.multiselect({ 795 - message: 'foo', 796 - options: [ 797 - { value: 'opt0', hint: 'Hint 0' }, 798 - { value: 'opt1', hint: 'Hint 1' }, 799 - { value: 'opt2', hint: 'Hint 2' }, 800 - ], 801 - initialValues: ['opt0', 'opt1'], 802 - input, 803 - output, 804 - }); 805 - 806 - // Check that both selected options show their hints 807 - input.emit('keypress', '', { name: 'down' }); 808 - input.emit('keypress', '', { name: 'down' }); 809 - input.emit('keypress', '', { name: 'return' }); 810 - 811 - const value = await result; 812 - 813 - expect(value).toEqual(['opt0', 'opt1']); 814 - expect(output.buffer).toMatchSnapshot(); 815 - }); 816 - 817 - test('renders multiple cancelled values', async () => { 818 - const result = prompts.multiselect({ 819 - message: 'foo', 820 - options: [{ value: 'opt0' }, { value: 'opt1' }, { value: 'opt2' }], 821 - input, 822 - output, 823 - }); 824 - 825 - input.emit('keypress', '', { name: 'space' }); 826 - input.emit('keypress', '', { name: 'down' }); 827 - input.emit('keypress', '', { name: 'space' }); 828 - input.emit('keypress', '', { name: 'escape' }); 829 - 830 - const value = await result; 831 - 832 - expect(prompts.isCancel(value)).toBe(true); 833 - expect(output.buffer).toMatchSnapshot(); 834 - }); 835 - }); 836 - 837 - describe('password', () => { 838 - test('renders message', async () => { 839 - const result = prompts.password({ 840 - message: 'foo', 841 - input, 842 - output, 843 - }); 844 - 845 - input.emit('keypress', '', { name: 'return' }); 846 - 847 - await result; 848 - 849 - expect(output.buffer).toMatchSnapshot(); 850 - }); 851 - 852 - test('renders masked value', async () => { 853 - const result = prompts.password({ 854 - message: 'foo', 855 - input, 856 - output, 857 - }); 858 - 859 - input.emit('keypress', 'x', { name: 'x' }); 860 - input.emit('keypress', 'y', { name: 'y' }); 861 - input.emit('keypress', '', { name: 'return' }); 862 - 863 - const value = await result; 864 - 865 - expect(value).toBe('xy'); 866 - expect(output.buffer).toMatchSnapshot(); 867 - }); 868 - 869 - test('renders custom mask', async () => { 870 - const result = prompts.password({ 871 - message: 'foo', 872 - mask: '*', 873 - input, 874 - output, 875 - }); 876 - 877 - input.emit('keypress', 'x', { name: 'x' }); 878 - input.emit('keypress', 'y', { name: 'y' }); 879 - input.emit('keypress', '', { name: 'return' }); 880 - 881 - await result; 882 - 883 - expect(output.buffer).toMatchSnapshot(); 884 - }); 885 - 886 - test('renders and clears validation errors', async () => { 887 - const result = prompts.password({ 888 - message: 'foo', 889 - validate: (value) => { 890 - if (value.length < 2) { 891 - return 'Password must be at least 2 characters'; 892 - } 893 - 894 - return undefined; 895 - }, 896 - input, 897 - output, 898 - }); 899 - 900 - input.emit('keypress', 'x', { name: 'x' }); 901 - input.emit('keypress', '', { name: 'return' }); 902 - input.emit('keypress', 'y', { name: 'y' }); 903 - input.emit('keypress', '', { name: 'return' }); 904 - 905 - await result; 906 - 907 - expect(output.buffer).toMatchSnapshot(); 908 - }); 909 - 910 - test('renders cancelled value', async () => { 911 - const result = prompts.password({ 912 - message: 'foo', 913 - input, 914 - output, 915 - }); 916 - 917 - input.emit('keypress', 'x', { name: 'x' }); 918 - input.emit('keypress', '', { name: 'escape' }); 919 - 920 - const value = await result; 921 - 922 - expect(prompts.isCancel(value)).toBe(true); 923 - expect(output.buffer).toMatchSnapshot(); 924 - }); 925 - }); 926 - 927 - describe('groupMultiselect', () => { 928 - test('renders message with options', async () => { 929 - const result = prompts.groupMultiselect({ 930 - message: 'foo', 931 - input, 932 - output, 933 - options: { 934 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 935 - group2: [{ value: 'group2value0' }], 936 - }, 937 - }); 938 - 939 - // Select the first non-group option 940 - input.emit('keypress', '', { name: 'down' }); 941 - input.emit('keypress', '', { name: 'space' }); 942 - 943 - // submit 944 - input.emit('keypress', '', { name: 'return' }); 945 - 946 - const value = await result; 947 - 948 - expect(value).toEqual(['group1value0']); 949 - expect(output.buffer).toMatchSnapshot(); 950 - }); 951 - 952 - test('can select multiple options', async () => { 953 - const result = prompts.groupMultiselect({ 954 - message: 'foo', 955 - input, 956 - output, 957 - options: { 958 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }, { value: 'group1value2' }], 959 - }, 960 - }); 961 - 962 - // Select the first non-group option 963 - input.emit('keypress', '', { name: 'down' }); 964 - input.emit('keypress', '', { name: 'space' }); 965 - // Select the second non-group option 966 - input.emit('keypress', '', { name: 'down' }); 967 - input.emit('keypress', '', { name: 'space' }); 968 - 969 - // submit 970 - input.emit('keypress', '', { name: 'return' }); 971 - 972 - const value = await result; 973 - 974 - expect(value).toEqual(['group1value0', 'group1value1']); 975 - expect(output.buffer).toMatchSnapshot(); 976 - }); 977 - 978 - test('can select a group', async () => { 979 - const result = prompts.groupMultiselect({ 980 - message: 'foo', 981 - input, 982 - output, 983 - options: { 984 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 985 - }, 986 - }); 987 - 988 - // Select the group as a whole 989 - input.emit('keypress', '', { name: 'space' }); 990 - 991 - // submit 992 - input.emit('keypress', '', { name: 'return' }); 993 - 994 - const value = await result; 995 - 996 - expect(value).toEqual(['group1value0', 'group1value1']); 997 - expect(output.buffer).toMatchSnapshot(); 998 - }); 999 - 1000 - test('can select a group by selecting all members', async () => { 1001 - const result = prompts.groupMultiselect({ 1002 - message: 'foo', 1003 - input, 1004 - output, 1005 - options: { 1006 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1007 - }, 1008 - }); 1009 - 1010 - // Select the first group option 1011 - input.emit('keypress', '', { name: 'down' }); 1012 - input.emit('keypress', '', { name: 'space' }); 1013 - // Select the second group option 1014 - input.emit('keypress', '', { name: 'down' }); 1015 - input.emit('keypress', '', { name: 'space' }); 1016 - 1017 - // submit 1018 - input.emit('keypress', '', { name: 'return' }); 1019 - 1020 - const value = await result; 1021 - 1022 - expect(value).toEqual(['group1value0', 'group1value1']); 1023 - expect(output.buffer).toMatchSnapshot(); 1024 - }); 1025 - 1026 - test('can deselect an option', async () => { 1027 - const result = prompts.groupMultiselect({ 1028 - message: 'foo', 1029 - input, 1030 - output, 1031 - options: { 1032 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1033 - }, 1034 - }); 1035 - 1036 - // Select the first group option 1037 - input.emit('keypress', '', { name: 'down' }); 1038 - input.emit('keypress', '', { name: 'space' }); 1039 - // Select the second group option 1040 - input.emit('keypress', '', { name: 'down' }); 1041 - input.emit('keypress', '', { name: 'space' }); 1042 - // Deselect it 1043 - input.emit('keypress', '', { name: 'space' }); 1044 - 1045 - // submit 1046 - input.emit('keypress', '', { name: 'return' }); 1047 - 1048 - const value = await result; 1049 - 1050 - expect(value).toEqual(['group1value0']); 1051 - expect(output.buffer).toMatchSnapshot(); 1052 - }); 1053 - 1054 - test('renders error when nothing selected', async () => { 1055 - const result = prompts.groupMultiselect({ 1056 - message: 'foo', 1057 - input, 1058 - output, 1059 - options: { 1060 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1061 - }, 1062 - }); 1063 - 1064 - // try submit 1065 - input.emit('keypress', '', { name: 'return' }); 1066 - // now select something and submit 1067 - input.emit('keypress', '', { name: 'down' }); 1068 - input.emit('keypress', '', { name: 'space' }); 1069 - input.emit('keypress', '', { name: 'return' }); 1070 - 1071 - const value = await result; 1072 - 1073 - expect(value).toEqual(['group1value0']); 1074 - expect(output.buffer).toMatchSnapshot(); 1075 - }); 1076 - 1077 - describe('selectableGroups = false', () => { 1078 - test('cannot select groups', async () => { 1079 - const result = prompts.groupMultiselect({ 1080 - message: 'foo', 1081 - input, 1082 - output, 1083 - options: { 1084 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1085 - }, 1086 - selectableGroups: false, 1087 - }); 1088 - 1089 - // first selectable item should be group's child 1090 - input.emit('keypress', '', { name: 'space' }); 1091 - input.emit('keypress', '', { name: 'return' }); 1092 - 1093 - const value = await result; 1094 - 1095 - expect(value).toEqual(['group1value0']); 1096 - expect(output.buffer).toMatchSnapshot(); 1097 - }); 1098 - 1099 - test('selecting all members of group does not select group', async () => { 1100 - const result = prompts.groupMultiselect({ 1101 - message: 'foo', 1102 - input, 1103 - output, 1104 - options: { 1105 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1106 - }, 1107 - selectableGroups: false, 1108 - }); 1109 - 1110 - // first selectable item should be group's child 1111 - input.emit('keypress', '', { name: 'space' }); 1112 - // select second item 1113 - input.emit('keypress', '', { name: 'down' }); 1114 - input.emit('keypress', '', { name: 'space' }); 1115 - // submit 1116 - input.emit('keypress', '', { name: 'return' }); 1117 - 1118 - const value = await result; 1119 - 1120 - expect(value).toEqual(['group1value0', 'group1value1']); 1121 - expect(output.buffer).toMatchSnapshot(); 1122 - }); 1123 - }); 1124 - 1125 - test('can submit empty selection when require = false', async () => { 1126 - const result = prompts.groupMultiselect({ 1127 - message: 'foo', 1128 - input, 1129 - output, 1130 - options: { 1131 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1132 - }, 1133 - required: false, 1134 - }); 1135 - 1136 - input.emit('keypress', '', { name: 'return' }); 1137 - 1138 - const value = await result; 1139 - 1140 - expect(value).toEqual([]); 1141 - expect(output.buffer).toMatchSnapshot(); 1142 - }); 1143 - 1144 - test('cursorAt sets initial selection', async () => { 1145 - const result = prompts.groupMultiselect({ 1146 - message: 'foo', 1147 - input, 1148 - output, 1149 - options: { 1150 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1151 - }, 1152 - cursorAt: 'group1value1', 1153 - }); 1154 - 1155 - input.emit('keypress', '', { name: 'space' }); 1156 - input.emit('keypress', '', { name: 'return' }); 1157 - 1158 - const value = await result; 1159 - 1160 - expect(value).toEqual(['group1value1']); 1161 - expect(output.buffer).toMatchSnapshot(); 1162 - }); 1163 - 1164 - test('initial values can be set', async () => { 1165 - const result = prompts.groupMultiselect({ 1166 - message: 'foo', 1167 - input, 1168 - output, 1169 - options: { 1170 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 1171 - }, 1172 - initialValues: ['group1value1'], 1173 - }); 1174 - 1175 - input.emit('keypress', '', { name: 'return' }); 1176 - 1177 - const value = await result; 1178 - 1179 - expect(value).toEqual(['group1value1']); 1180 - expect(output.buffer).toMatchSnapshot(); 1181 - }); 1182 - 1183 - test('values can be non-primitive', async () => { 1184 - const value0 = Symbol(); 1185 - const value1 = Symbol(); 1186 - const result = prompts.groupMultiselect({ 1187 - message: 'foo', 1188 - input, 1189 - output, 1190 - options: { 1191 - group1: [ 1192 - { value: value0, label: 'value0' }, 1193 - { value: value1, label: 'value1' }, 1194 - ], 1195 - }, 1196 - }); 1197 - 1198 - input.emit('keypress', '', { name: 'down' }); 1199 - input.emit('keypress', '', { name: 'space' }); 1200 - input.emit('keypress', '', { name: 'return' }); 1201 - 1202 - const value = await result; 1203 - 1204 - expect(value).toEqual([value0]); 1205 - expect(output.buffer).toMatchSnapshot(); 1206 - }); 1207 - }); 1208 - });