usage_spec.sh (67393B)
1 # pashage - age-backed POSIX password manager 2 # Copyright (C) 2024-2025 Natasha Kerensikova 3 # 4 # This program is free software; you can redistribute it and/or 5 # modify it under the terms of the GNU General Public License 6 # as published by the Free Software Foundation; either version 2 7 # of the License, or (at your option) any later version. 8 # 9 # This program is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with this program; if not, write to the Free Software 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 18 # This test file fully covers all command functions in isolation, 19 # using mocks for all action and helper functions. 20 # It mostly tests command-line parsing and environment transmission to actions. 21 22 Describe 'Command-Line Parsing' 23 Include src/pashage.sh 24 if [ "${SHELLSPEC_SHELL_TYPE}" = sh ]; then 25 Set 'errexit:on' 'nounset:on' 26 else 27 Set 'errexit:on' 'nounset:on' 'pipefail:on' 28 fi 29 30 PREFIX=/prefix 31 PROGRAM=prg 32 33 CHARACTER_SET='[:punct:][:alnum:]' 34 CHARACTER_SET_NO_SYMBOLS='[:alnum:]' 35 36 # mocks 37 platform_tmpdir() { 38 SECURE_TMPDIR=/tmp/secure 39 } 40 41 check_sneaky_path() { mocklog check_sneaky_path "$@"; } 42 git() { mocklog git "$@"; } 43 scm_add() { mocklog scm_add "$@"; } 44 scm_begin() { mocklog scm_begin "$@"; } 45 scm_commit() { mocklog scm_commit "$@"; } 46 47 do_copy_move() { 48 mocklog do_copy_move "$@" 49 %text:expand >&2 50 #|ACTION=${ACTION} 51 #|DECISION=${DECISION} 52 #|OVERWRITE=${OVERWRITE} 53 #|SCM_ACTION=${SCM_ACTION} 54 } 55 do_decrypt() { 56 mocklog do_decrypt "$@" 57 } 58 do_decrypt_gpg() { 59 mocklog do_decrypt_gpg "$@" 60 } 61 do_deinit() { 62 mocklog do_deinit "$@" 63 %text:expand >&2 64 #|DECISION=${DECISION} 65 } 66 do_delete() { 67 mocklog do_delete "$@" 68 %text:expand >&2 69 #|DECISION=${DECISION} 70 #|RECURSIVE=${RECURSIVE} 71 } 72 do_edit() { 73 mocklog do_edit "$@" 74 %text:expand >&2 75 #|EDITOR=${EDITOR} 76 #|SECURE_TMPDIR=${SECURE_TMPDIR} 77 #|TERM=${TERM} 78 #|VISUAL=${VISUAL} 79 } 80 do_encrypt() { 81 mocklog do_encrypt "$@" 82 %text:expand >&2 83 #|IDENTITIES_FILE=${IDENTITIES_FILE} 84 #|LOCAL_RECIPIENT_FILE=${LOCAL_RECIPIENT_FILE} 85 #|PASHAGE_RECIPIENTS=${PASHAGE_RECIPIENTS} 86 #|PASHAGE_RECIPIENTS_FILE=${PASHAGE_RECIPIENTS_FILE} 87 #|PASSAGE_RECIPIENTS=${PASSAGE_RECIPIENTS} 88 #|PASSAGE_RECIPIENTS_FILE=${PASSAGE_RECIPIENTS_FILE} 89 } 90 do_generate() { 91 mocklog do_generate "$@" 92 %text:expand >&2 93 #|DECISION=${DECISION} 94 #|MULTILINE=${MULTILINE} 95 #|OVERWRITE=${OVERWRITE} 96 #|SELECTED_LINE=${SELECTED_LINE} 97 #|SHOW=${SHOW} 98 } 99 do_grep() { 100 mocklog do_grep "$@" 101 } 102 do_init() { 103 mocklog do_init "$@" 104 %text:expand >&2 105 #|DECISION=${DECISION} 106 #|OVERWRITE=${OVERWRITE} 107 } 108 do_insert() { 109 mocklog do_insert "$@" 110 %text:expand >&2 111 #|ECHO=${ECHO} 112 #|MULTILINE=${MULTILINE} 113 #|OVERWRITE=${OVERWRITE} 114 } 115 do_list() { 116 mocklog do_list "$@" 117 } 118 do_list_or_show() { 119 mocklog do_list_or_show "$@" 120 %text:expand >&2 121 #|LIST_VIEW=${LIST_VIEW} 122 #|SELECTED_LINE=${SELECTED_LINE} 123 #|SHOW=${SHOW} 124 } 125 do_reencrypt() { 126 mocklog do_reencrypt "$@" 127 %text:expand >&2 128 #|DECISION=${DECISION} 129 #|RECURSIVE=${RECURSIVE} 130 } 131 do_reencrypt_dir() { 132 mocklog do_reencrypt_dir "$@" 133 %text:expand >&2 134 #|DECISION=${DECISION} 135 } 136 do_reencrypt_file() { 137 mocklog do_reencrypt_file "$@" 138 %text:expand >&2 139 #|DECISION=${DECISION} 140 } 141 do_show() { 142 mocklog do_show "$@" 143 %text:expand >&2 144 #|SELECTED_LINE=${SELECTED_LINE} 145 #|SHOW=${SHOW} 146 } 147 do_tree() { 148 mocklog do_tree "$@" 149 } 150 151 Describe 'cmd_copy' 152 COMMAND=copy 153 154 It 'copies multiple files' 155 result() { 156 %text 157 #|$ check_sneaky_path src1 158 #|$ check_sneaky_path src2 159 #|$ check_sneaky_path src3 160 #|$ check_sneaky_path dest 161 #|$ do_copy_move src1 dest/ 162 #|ACTION=Copy 163 #|DECISION=default 164 #|OVERWRITE=no 165 #|SCM_ACTION=scm_cp 166 #|$ do_copy_move src2 dest/ 167 #|ACTION=Copy 168 #|DECISION=default 169 #|OVERWRITE=no 170 #|SCM_ACTION=scm_cp 171 #|$ do_copy_move src3 dest/ 172 #|ACTION=Copy 173 #|DECISION=default 174 #|OVERWRITE=no 175 #|SCM_ACTION=scm_cp 176 } 177 When call cmd_copy src1 src2 src3 dest 178 The status should be success 179 The output should be blank 180 The error should equal "$(result)" 181 End 182 183 It 'copies forcefully with a long option' 184 result() { 185 %text 186 #|$ check_sneaky_path src 187 #|$ check_sneaky_path dest 188 #|$ do_copy_move src dest 189 #|ACTION=Copy 190 #|DECISION=default 191 #|OVERWRITE=yes 192 #|SCM_ACTION=scm_cp 193 } 194 When call cmd_copy --force src dest 195 The status should be success 196 The output should be blank 197 The error should equal "$(result)" 198 End 199 200 It 'copies forcefully with a short option' 201 result() { 202 %text 203 #|$ check_sneaky_path src 204 #|$ check_sneaky_path dest 205 #|$ do_copy_move src dest 206 #|ACTION=Copy 207 #|DECISION=default 208 #|OVERWRITE=yes 209 #|SCM_ACTION=scm_cp 210 } 211 When call cmd_copy -f src dest 212 The status should be success 213 The output should be blank 214 The error should equal "$(result)" 215 End 216 217 It 'always reencrypts with a long option' 218 result() { 219 %text 220 #|$ check_sneaky_path src 221 #|$ check_sneaky_path dest 222 #|$ do_copy_move src dest 223 #|ACTION=Copy 224 #|DECISION=force 225 #|OVERWRITE=no 226 #|SCM_ACTION=scm_cp 227 } 228 When call cmd_copy --reencrypt src dest 229 The status should be success 230 The output should be blank 231 The error should equal "$(result)" 232 End 233 234 It 'always reencrypts with a short option' 235 result() { 236 %text 237 #|$ check_sneaky_path src 238 #|$ check_sneaky_path dest 239 #|$ do_copy_move src dest 240 #|ACTION=Copy 241 #|DECISION=force 242 #|OVERWRITE=no 243 #|SCM_ACTION=scm_cp 244 } 245 When call cmd_copy -e src dest 246 The status should be success 247 The output should be blank 248 The error should equal "$(result)" 249 End 250 251 It 'interactively reencrypts with a long option' 252 result() { 253 %text 254 #|$ check_sneaky_path src 255 #|$ check_sneaky_path dest 256 #|$ do_copy_move src dest 257 #|ACTION=Copy 258 #|DECISION=interactive 259 #|OVERWRITE=no 260 #|SCM_ACTION=scm_cp 261 } 262 When call cmd_copy --interactive src dest 263 The status should be success 264 The output should be blank 265 The error should equal "$(result)" 266 End 267 268 It 'interactively reencrypts with a short option' 269 result() { 270 %text 271 #|$ check_sneaky_path src 272 #|$ check_sneaky_path dest 273 #|$ do_copy_move src dest 274 #|ACTION=Copy 275 #|DECISION=interactive 276 #|OVERWRITE=no 277 #|SCM_ACTION=scm_cp 278 } 279 When call cmd_copy -i src dest 280 The status should be success 281 The output should be blank 282 The error should equal "$(result)" 283 End 284 285 It 'never reencrypts with a long option' 286 result() { 287 %text 288 #|$ check_sneaky_path src 289 #|$ check_sneaky_path dest 290 #|$ do_copy_move src dest 291 #|ACTION=Copy 292 #|DECISION=keep 293 #|OVERWRITE=no 294 #|SCM_ACTION=scm_cp 295 } 296 When call cmd_copy --keep src dest 297 The status should be success 298 The output should be blank 299 The error should equal "$(result)" 300 End 301 302 It 'never reencrypts with a short option' 303 result() { 304 %text 305 #|$ check_sneaky_path src 306 #|$ check_sneaky_path dest 307 #|$ do_copy_move src dest 308 #|ACTION=Copy 309 #|DECISION=keep 310 #|OVERWRITE=no 311 #|SCM_ACTION=scm_cp 312 } 313 When call cmd_copy -k src dest 314 The status should be success 315 The output should be blank 316 The error should equal "$(result)" 317 End 318 319 It 'copies a file named like a flag' 320 result() { 321 %text 322 #|$ check_sneaky_path -s 323 #|$ check_sneaky_path dest 324 #|$ do_copy_move -s dest 325 #|ACTION=Copy 326 #|DECISION=default 327 #|OVERWRITE=no 328 #|SCM_ACTION=scm_cp 329 } 330 When call cmd_copy -- -s dest 331 The status should be success 332 The output should be blank 333 The error should equal "$(result)" 334 End 335 336 usage_text() { %text 337 #|Usage: prg copy [--reencrypt,-e | --interactive,-i | --keep,-k ] 338 #| [--force,-f] old-path new-path 339 } 340 341 It 'reports a bad option' 342 cat() { @cat; } 343 When run cmd_copy -s arg 344 The output should be blank 345 The error should equal "$(usage_text)" 346 The status should equal 1 347 End 348 349 It 'reports incompatible re-encryption options (-e and -i)' 350 cat() { @cat; } 351 When run cmd_copy -ei src dest 352 The output should be blank 353 The error should equal "$(usage_text)" 354 The status should equal 1 355 End 356 357 It 'reports incompatible re-encryption options (-i and -k)' 358 cat() { @cat; } 359 When run cmd_copy -ik src dest 360 The output should be blank 361 The error should equal "$(usage_text)" 362 The status should equal 1 363 End 364 365 It 'reports incompatible re-encryption options (-k and -e)' 366 cat() { @cat; } 367 When run cmd_copy -ke src dest 368 The output should be blank 369 The error should equal "$(usage_text)" 370 The status should equal 1 371 End 372 373 It 'reports a lack of argument' 374 cat() { @cat; } 375 When run cmd_copy src 376 The output should be blank 377 The error should equal "$(usage_text)" 378 The status should equal 1 379 End 380 End 381 382 Describe 'cmd_copy_move' 383 COMMAND=wrong 384 385 It 'reports both commands when confused' 386 cat() { @cat; } 387 result() { %text 388 #|Usage: prg copy [--reencrypt,-e | --interactive,-i | --keep,-k ] 389 #| [--force,-f] old-path new-path 390 #| prg move [--reencrypt,-e | --interactive,-i | --keep,-k ] 391 #| [--force,-f] old-path new-path 392 } 393 When run cmd_copy src 394 The output should be blank 395 The error should equal "$(result)" 396 The status should equal 1 397 End 398 End 399 400 Describe 'cmd_delete' 401 COMMAND=delete 402 403 It 'removes a file forcefully with a long option' 404 result() { 405 %text 406 #|$ check_sneaky_path arg1 407 #|$ do_delete arg1 408 #|DECISION=force 409 #|RECURSIVE=no 410 } 411 When call cmd_delete --force arg1 412 The status should be success 413 The output should be blank 414 The error should equal "$(result)" 415 End 416 417 It 'removes a file forcefully with a short option' 418 result() { 419 %text 420 #|$ check_sneaky_path arg1 421 #|$ do_delete arg1 422 #|DECISION=force 423 #|RECURSIVE=no 424 } 425 When call cmd_delete -f arg1 426 The status should be success 427 The output should be blank 428 The error should equal "$(result)" 429 End 430 431 It 'removes a directory recursively with a long option' 432 result() { 433 %text 434 #|$ check_sneaky_path arg1 435 #|$ do_delete arg1 436 #|DECISION=default 437 #|RECURSIVE=yes 438 } 439 When call cmd_delete --recursive arg1 440 The status should be success 441 The output should be blank 442 The error should equal "$(result)" 443 End 444 445 It 'removes a directory recursively with a short option' 446 result() { 447 %text 448 #|$ check_sneaky_path arg1 449 #|$ do_delete arg1 450 #|DECISION=default 451 #|RECURSIVE=yes 452 } 453 When call cmd_delete -r arg1 454 The status should be success 455 The output should be blank 456 The error should equal "$(result)" 457 End 458 459 It 'removes a directory recursively and forcefully with long options' 460 result() { 461 %text 462 #|$ check_sneaky_path arg1 463 #|$ do_delete arg1 464 #|DECISION=force 465 #|RECURSIVE=yes 466 } 467 When call cmd_delete --recursive --force arg1 468 The status should be success 469 The output should be blank 470 The error should equal "$(result)" 471 End 472 473 It 'removes a directory recursively and forcefully with short options' 474 result() { 475 %text 476 #|$ check_sneaky_path arg1 477 #|$ do_delete arg1 478 #|DECISION=force 479 #|RECURSIVE=yes 480 } 481 When call cmd_delete -rf arg1 482 The status should be success 483 The output should be blank 484 The error should equal "$(result)" 485 End 486 487 It 'removes a directory forcefully and recursively with short options' 488 result() { 489 %text 490 #|$ check_sneaky_path arg1 491 #|$ do_delete arg1 492 #|DECISION=force 493 #|RECURSIVE=yes 494 } 495 When call cmd_delete -fr arg1 496 The status should be success 497 The output should be blank 498 The error should equal "$(result)" 499 End 500 501 It 'removes multiple files' 502 result() { 503 %text 504 #|$ check_sneaky_path arg1 505 #|$ check_sneaky_path arg2 506 #|$ check_sneaky_path arg3 507 #|$ do_delete arg1 508 #|DECISION=default 509 #|RECURSIVE=no 510 #|$ do_delete arg2 511 #|DECISION=default 512 #|RECURSIVE=no 513 #|$ do_delete arg3 514 #|DECISION=default 515 #|RECURSIVE=no 516 } 517 When call cmd_delete arg1 arg2 arg3 518 The status should be success 519 The output should be blank 520 The error should equal "$(result)" 521 End 522 523 It 'removes a file named like a flag' 524 result() { 525 %text 526 #|$ check_sneaky_path -f 527 #|$ check_sneaky_path arg2 528 #|$ do_delete -f 529 #|DECISION=default 530 #|RECURSIVE=no 531 #|$ do_delete arg2 532 #|DECISION=default 533 #|RECURSIVE=no 534 } 535 When call cmd_delete -- -f arg2 536 The status should be success 537 The output should be blank 538 The error should equal "$(result)" 539 End 540 541 It 'reports a bad option' 542 cat() { @cat; } 543 When run cmd_delete -u arg 544 The output should be blank 545 The error should equal \ 546 'Usage: prg delete [--recursive,-r] [--force,-f] pass-name' 547 The status should equal 1 548 End 549 550 It 'reports a lack of argument' 551 cat() { @cat; } 552 When run cmd_delete 553 The output should be blank 554 The error should equal \ 555 'Usage: prg delete [--recursive,-r] [--force,-f] pass-name' 556 The status should equal 1 557 End 558 End 559 560 Describe 'cmd_edit' 561 COMMAND=edit 562 EDITOR=ed 563 TERM=dumb 564 VISUAL=vi 565 566 It 'edits multiple files succesively' 567 result() { 568 %text 569 #|$ check_sneaky_path arg1 570 #|$ check_sneaky_path arg2 571 #|$ check_sneaky_path arg3 572 #|$ do_edit arg1 573 #|EDITOR=ed 574 #|SECURE_TMPDIR=/tmp/secure 575 #|TERM=dumb 576 #|VISUAL=vi 577 #|$ do_edit arg2 578 #|EDITOR=ed 579 #|SECURE_TMPDIR=/tmp/secure 580 #|TERM=dumb 581 #|VISUAL=vi 582 #|$ do_edit arg3 583 #|EDITOR=ed 584 #|SECURE_TMPDIR=/tmp/secure 585 #|TERM=dumb 586 #|VISUAL=vi 587 } 588 When call cmd_edit arg1 arg2 arg3 589 The status should be success 590 The output should be blank 591 The error should equal "$(result)" 592 End 593 594 It 'reports a lack of argument' 595 cat() { @cat; } 596 When run cmd_edit 597 The output should be blank 598 The error should equal 'Usage: prg edit pass-name' 599 The status should equal 1 600 End 601 End 602 603 Describe 'cmd_find' 604 COMMAND=find 605 606 It 'uses the argument list directly' 607 When call cmd_find -i pattern 608 The status should be success 609 The output should equal 'Search pattern: -i pattern' 610 The error should equal '$ do_tree -i pattern' 611 End 612 613 It 'interprets the raw list flag' 614 When call cmd_find -r pattern 615 The status should be success 616 The output should be blank 617 The error should equal '$ do_list pattern' 618 End 619 620 It 'reports a lack of argument' 621 cat() { @cat; } 622 When run cmd_find 623 The output should be blank 624 The error should equal 'Usage: prg find [--raw,-r] [GREP_OPTIONS] regex' 625 The status should equal 1 626 End 627 628 It 'reports a lack of argument for grep' 629 cat() { @cat; } 630 When run cmd_find -r 631 The output should be blank 632 The error should equal 'Usage: prg find [--raw,-r] [GREP_OPTIONS] regex' 633 The status should equal 1 634 End 635 End 636 637 Describe 'cmd_generate' 638 COMMAND=generate 639 GENERATED_LENGTH=25 640 641 usage_text() { %text 642 #|Usage: prg generate [--no-symbols,-n] [--clip,-c | --qrcode,-q] 643 #| [--in-place,-i | --force,-f] [--multiline,-m] 644 #| [--try,-t] pass-name [pass-length [character-set]] 645 } 646 647 It 'generates a new entry with default length' 648 result() { 649 %text 650 #|$ check_sneaky_path secret 651 #|$ do_generate secret 25 [:punct:][:alnum:] 652 #|DECISION=default 653 #|MULTILINE=no 654 #|OVERWRITE=no 655 #|SELECTED_LINE=1 656 #|SHOW=text 657 } 658 When call cmd_generate secret 659 The status should be success 660 The output should be blank 661 The error should equal "$(result)" 662 End 663 664 It 'generates a new entry with explicit length' 665 result() { 666 %text 667 #|$ check_sneaky_path secret 668 #|$ do_generate secret 12 [:punct:][:alnum:] 669 #|DECISION=default 670 #|MULTILINE=no 671 #|OVERWRITE=no 672 #|SELECTED_LINE=1 673 #|SHOW=text 674 } 675 When call cmd_generate secret 12 676 The status should be success 677 The output should be blank 678 The error should equal "$(result)" 679 End 680 681 It 'generates a new entry with explicit length and character set' 682 result() { 683 %text 684 #|$ check_sneaky_path secret 685 #|$ do_generate secret 12 [A-Z] 686 #|DECISION=default 687 #|MULTILINE=no 688 #|OVERWRITE=no 689 #|SELECTED_LINE=1 690 #|SHOW=text 691 } 692 When call cmd_generate secret 12 '[A-Z]' 693 The status should be success 694 The output should be blank 695 The error should equal "$(result)" 696 End 697 698 It 'generates a new flag-like entry' 699 result() { 700 %text 701 #|$ check_sneaky_path -f 702 #|$ do_generate -f 25 [:punct:][:alnum:] 703 #|DECISION=default 704 #|MULTILINE=no 705 #|OVERWRITE=no 706 #|SELECTED_LINE=1 707 #|SHOW=text 708 } 709 When call cmd_generate -- -f 710 The status should be success 711 The output should be blank 712 The error should equal "$(result)" 713 End 714 715 It 'generates a new entry and copies it into the clipboard (long)' 716 result() { 717 %text 718 #|$ check_sneaky_path secret 719 #|$ do_generate secret 25 [:punct:][:alnum:] 720 #|DECISION=default 721 #|MULTILINE=no 722 #|OVERWRITE=no 723 #|SELECTED_LINE=1 724 #|SHOW=clip 725 } 726 When call cmd_generate --clip secret 727 The status should be success 728 The output should be blank 729 The error should equal "$(result)" 730 End 731 732 It 'generates a new entry and copies it into the clipboard (short)' 733 result() { 734 %text 735 #|$ check_sneaky_path secret 736 #|$ do_generate secret 25 [:punct:][:alnum:] 737 #|DECISION=default 738 #|MULTILINE=no 739 #|OVERWRITE=no 740 #|SELECTED_LINE=1 741 #|SHOW=clip 742 } 743 When call cmd_generate -c secret 744 The status should be success 745 The output should be blank 746 The error should equal "$(result)" 747 End 748 749 It 'generates a new entry and shows it as a QR-code (long)' 750 result() { 751 %text 752 #|$ check_sneaky_path secret 753 #|$ do_generate secret 25 [:punct:][:alnum:] 754 #|DECISION=default 755 #|MULTILINE=no 756 #|OVERWRITE=no 757 #|SELECTED_LINE=1 758 #|SHOW=qrcode 759 } 760 When call cmd_generate --qrcode secret 761 The status should be success 762 The output should be blank 763 The error should equal "$(result)" 764 End 765 766 It 'generates a new entry and shows it as a QR-code (short)' 767 result() { 768 %text 769 #|$ check_sneaky_path secret 770 #|$ do_generate secret 25 [:punct:][:alnum:] 771 #|DECISION=default 772 #|MULTILINE=no 773 #|OVERWRITE=no 774 #|SELECTED_LINE=1 775 #|SHOW=qrcode 776 } 777 When call cmd_generate -q secret 778 The status should be success 779 The output should be blank 780 The error should equal "$(result)" 781 End 782 783 It 'generates a new alphanumeric entry and copies it into the clipboard (long)' 784 result() { 785 %text 786 #|$ check_sneaky_path secret 787 #|$ do_generate secret 25 [:alnum:] 788 #|DECISION=default 789 #|MULTILINE=no 790 #|OVERWRITE=no 791 #|SELECTED_LINE=1 792 #|SHOW=clip 793 } 794 When call cmd_generate --clip --no-symbols secret 795 The status should be success 796 The output should be blank 797 The error should equal "$(result)" 798 End 799 800 It 'generates a new alphanumeric entry and copies it into the clipboard (short)' 801 result() { 802 %text 803 #|$ check_sneaky_path secret 804 #|$ do_generate secret 25 [:alnum:] 805 #|DECISION=default 806 #|MULTILINE=no 807 #|OVERWRITE=no 808 #|SELECTED_LINE=1 809 #|SHOW=clip 810 } 811 When call cmd_generate -cn secret 812 The status should be success 813 The output should be blank 814 The error should equal "$(result)" 815 End 816 817 It 'generates a new alphanumeric entry and shows it as a QR-code (long)' 818 result() { 819 %text 820 #|$ check_sneaky_path secret 821 #|$ do_generate secret 25 [:alnum:] 822 #|DECISION=default 823 #|MULTILINE=no 824 #|OVERWRITE=no 825 #|SELECTED_LINE=1 826 #|SHOW=qrcode 827 } 828 When call cmd_generate --no-symbols --qrcode secret 829 The status should be success 830 The output should be blank 831 The error should equal "$(result)" 832 End 833 834 It 'generates a new alphanumeric entry and shows it as a QR-code (short)' 835 result() { 836 %text 837 #|$ check_sneaky_path secret 838 #|$ do_generate secret 25 [:alnum:] 839 #|DECISION=default 840 #|MULTILINE=no 841 #|OVERWRITE=no 842 #|SELECTED_LINE=1 843 #|SHOW=qrcode 844 } 845 When call cmd_generate -nq secret 846 The status should be success 847 The output should be blank 848 The error should equal "$(result)" 849 End 850 851 It 'generates a new entry in place (long)' 852 result() { 853 %text 854 #|$ check_sneaky_path secret 855 #|$ do_generate secret 25 [:punct:][:alnum:] 856 #|DECISION=default 857 #|MULTILINE=no 858 #|OVERWRITE=reuse 859 #|SELECTED_LINE=1 860 #|SHOW=text 861 } 862 When call cmd_generate --in-place secret 863 The status should be success 864 The output should be blank 865 The error should equal "$(result)" 866 End 867 868 It 'generates a new entry in place (short)' 869 result() { 870 %text 871 #|$ check_sneaky_path secret 872 #|$ do_generate secret 25 [:punct:][:alnum:] 873 #|DECISION=default 874 #|MULTILINE=no 875 #|OVERWRITE=reuse 876 #|SELECTED_LINE=1 877 #|SHOW=text 878 } 879 When call cmd_generate -i secret 880 The status should be success 881 The output should be blank 882 The error should equal "$(result)" 883 End 884 885 It 'overwrites an existing entry (long)' 886 result() { 887 %text 888 #|$ check_sneaky_path secret 889 #|$ do_generate secret 25 [:punct:][:alnum:] 890 #|DECISION=default 891 #|MULTILINE=no 892 #|OVERWRITE=yes 893 #|SELECTED_LINE=1 894 #|SHOW=text 895 } 896 When call cmd_generate --force secret 897 The status should be success 898 The output should be blank 899 The error should equal "$(result)" 900 End 901 902 It 'overwrites an existing entry (short)' 903 result() { 904 %text 905 #|$ check_sneaky_path secret 906 #|$ do_generate secret 25 [:punct:][:alnum:] 907 #|DECISION=default 908 #|MULTILINE=no 909 #|OVERWRITE=yes 910 #|SELECTED_LINE=1 911 #|SHOW=text 912 } 913 When call cmd_generate -f secret 914 The status should be success 915 The output should be blank 916 The error should equal "$(result)" 917 End 918 919 It 'asks for confirmation before saving the generated password (long)' 920 result() { 921 %text 922 #|$ check_sneaky_path secret 923 #|$ do_generate secret 25 [:punct:][:alnum:] 924 #|DECISION=interactive 925 #|MULTILINE=no 926 #|OVERWRITE=no 927 #|SELECTED_LINE=1 928 #|SHOW=text 929 } 930 When call cmd_generate --try secret 931 The status should be success 932 The output should be blank 933 The error should equal "$(result)" 934 End 935 936 It 'asks for confirmation before saving the generated password (short)' 937 result() { 938 %text 939 #|$ check_sneaky_path secret 940 #|$ do_generate secret 25 [:punct:][:alnum:] 941 #|DECISION=interactive 942 #|MULTILINE=no 943 #|OVERWRITE=no 944 #|SELECTED_LINE=1 945 #|SHOW=text 946 } 947 When call cmd_generate -t secret 948 The status should be success 949 The output should be blank 950 The error should equal "$(result)" 951 End 952 953 It 'accepts extra lines after the generated secret (long)' 954 result() { 955 %text 956 #|$ check_sneaky_path secret 957 #|$ do_generate secret 25 [:punct:][:alnum:] 958 #|DECISION=default 959 #|MULTILINE=yes 960 #|OVERWRITE=no 961 #|SELECTED_LINE=1 962 #|SHOW=text 963 } 964 When call cmd_generate --multiline secret 965 The status should be success 966 The output should be blank 967 The error should equal "$(result)" 968 End 969 970 It 'accepts extra lines after the generated secret (short)' 971 result() { 972 %text 973 #|$ check_sneaky_path secret 974 #|$ do_generate secret 25 [:punct:][:alnum:] 975 #|DECISION=default 976 #|MULTILINE=yes 977 #|OVERWRITE=no 978 #|SELECTED_LINE=1 979 #|SHOW=text 980 } 981 When call cmd_generate -m secret 982 The status should be success 983 The output should be blank 984 The error should equal "$(result)" 985 End 986 987 It 'reports incompatible generation long options' 988 cat() { @cat; } 989 When run cmd_generate --in-place --force secret 990 The output should be blank 991 The error should equal "$(usage_text)" 992 The status should equal 1 993 End 994 995 It 'reports incompatible generation short options' 996 cat() { @cat; } 997 When run cmd_generate -fi secret 998 The output should be blank 999 The error should equal "$(usage_text)" 1000 The status should equal 1 1001 End 1002 1003 It 'reports incompatible show long options' 1004 cat() { @cat; } 1005 When run cmd_generate --qrcode --clip secret 1006 The output should be blank 1007 The error should equal "$(usage_text)" 1008 The status should equal 1 1009 End 1010 1011 It 'reports incompatible show short options' 1012 cat() { @cat; } 1013 When run cmd_generate -cq secret 1014 The output should be blank 1015 The error should equal "$(usage_text)" 1016 The status should equal 1 1017 End 1018 1019 It 'reports a bad option' 1020 cat() { @cat; } 1021 When run cmd_generate --bad secret 1022 The output should be blank 1023 The error should equal "$(usage_text)" 1024 The status should equal 1 1025 End 1026 1027 It 'reports a lack of argument' 1028 cat() { @cat; } 1029 When run cmd_generate 1030 The output should be blank 1031 The error should equal "$(usage_text)" 1032 The status should equal 1 1033 End 1034 End 1035 1036 Describe 'cmd_git' 1037 COMMAND=git 1038 1039 cmd_gitconfig() { mocklog cmd_gitconfig "$@"; } 1040 mkdir() { mocklog mkdir "$@"; @mkdir "$@"; } 1041 1042 setup() { 1043 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/.git" 1044 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/sub" 1045 } 1046 1047 cleanup() { 1048 @rm -rf "${SHELLSPEC_WORKDIR}/repo" 1049 } 1050 1051 BeforeEach setup 1052 AfterEach cleanup 1053 1054 It 'initializes a new repository' 1055 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub" 1056 result() { 1057 %text:expand 1058 #|$ mkdir -p -- ${PREFIX} 1059 #|$ git -C ${PREFIX} init 1060 #|$ scm_add . 1061 #|$ scm_commit Add current contents of password store. 1062 #|$ cmd_gitconfig 1063 } 1064 When call cmd_git init 1065 The status should be success 1066 The output should be blank 1067 The error should equal "$(result)" 1068 End 1069 1070 It 'clones a new repository' 1071 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub" 1072 result() { 1073 %text:expand 1074 #|$ git clone origin ${PREFIX} 1075 #|$ cmd_gitconfig 1076 } 1077 When call cmd_git clone origin 1078 The status should be success 1079 The output should be blank 1080 The error should equal "$(result)" 1081 End 1082 1083 It 'runs the git command into the store' 1084 PREFIX="${SHELLSPEC_WORKDIR}/repo" 1085 When call cmd_git log --oneline 1086 The status should be success 1087 The output should be blank 1088 The error should equal "$ git -C ${PREFIX} log --oneline" 1089 End 1090 1091 It 'transmits an empty argument list to git' 1092 PREFIX="${SHELLSPEC_WORKDIR}/repo" 1093 When run cmd_git 1094 The status should be success 1095 The output should be blank 1096 The error should equal "$ git -C ${PREFIX}" 1097 End 1098 1099 It 'aborts without a git repository' 1100 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub" 1101 When run cmd_git log 1102 The output should be blank 1103 The error should equal 'Error: the password store is not a git repository. Try "prg git init".' 1104 The status should equal 1 1105 End 1106 End 1107 1108 Describe 'cmd_gitconfig' 1109 COMMAND=gitconfig 1110 AGE=age 1111 IDENTITIES_FILE=id 1112 1113 grep() { @grep "$@"; } 1114 1115 setup() { 1116 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/.git" 1117 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/sub-1/.git" 1118 %putsn data >"${SHELLSPEC_WORKDIR}/repo/sub-1/.gitattributes" 1119 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/sub-2/.git" 1120 %putsn '*.age diff=age' >"${SHELLSPEC_WORKDIR}/repo/sub-2/.gitattributes" 1121 } 1122 1123 cleanup() { 1124 @rm -rf "${SHELLSPEC_WORKDIR}/repo" 1125 } 1126 1127 BeforeEach setup 1128 AfterEach cleanup 1129 1130 It 'configures a new repository' 1131 PREFIX="${SHELLSPEC_WORKDIR}/repo" 1132 result() { 1133 %text:expand 1134 #|$ scm_begin 1135 #|$ scm_add .gitattributes 1136 #|$ scm_commit Configure git repository for age file diff. 1137 #|$ git -C ${PREFIX} config --local diff.age.binary true 1138 #|$ git -C ${PREFIX} config --local diff.age.textconv age -d -i id 1139 } 1140 When call cmd_gitconfig 1141 The status should be success 1142 The output should be blank 1143 The error should equal "$(result)" 1144 The contents of file "${PREFIX}/.gitattributes" should equal '*.age diff=age' 1145 End 1146 1147 It 'expands an existing .gitattributes' 1148 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub-1" 1149 result() { 1150 %text:expand 1151 #|$ scm_begin 1152 #|$ scm_add .gitattributes 1153 #|$ scm_commit Configure git repository for age file diff. 1154 #|$ git -C ${PREFIX} config --local diff.age.binary true 1155 #|$ git -C ${PREFIX} config --local diff.age.textconv age -d -i id 1156 } 1157 attrs() { 1158 %text 1159 #|data 1160 #|*.age diff=age 1161 } 1162 When call cmd_gitconfig 1163 The status should be success 1164 The output should be blank 1165 The error should equal "$(result)" 1166 The contents of file "${PREFIX}/.gitattributes" should equal "$(attrs)" 1167 End 1168 1169 It 'configures a repository with a valid .gitattributes' 1170 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub-2" 1171 result() { 1172 %text:expand 1173 #|$ git -C ${PREFIX} config --local diff.age.binary true 1174 #|$ git -C ${PREFIX} config --local diff.age.textconv age -d -i id 1175 } 1176 When call cmd_gitconfig 1177 The status should be success 1178 The output should be blank 1179 The error should equal "$(result)" 1180 The contents of file "${PREFIX}/.gitattributes" should equal '*.age diff=age' 1181 End 1182 1183 It 'aborts without a git repository' 1184 PREFIX="${SHELLSPEC_WORKDIR}/repo/prefix" 1185 When run cmd_gitconfig 1186 The output should be blank 1187 The error should equal 'The store is not a git repository.' 1188 The status should equal 1 1189 End 1190 End 1191 1192 Describe 'cmd_grep' 1193 COMMAND=grep 1194 PREFIX="${SHELLSPEC_WORKDIR}" 1195 1196 It 'uses the argument list directly' 1197 When call cmd_grep -i pattern 1198 The status should be success 1199 The output should be blank 1200 The error should equal "$ do_grep ${PREFIX} -i pattern" 1201 End 1202 1203 It 'reports a lack of argument' 1204 cat() { @cat; } 1205 When run cmd_grep 1206 The output should be blank 1207 The error should equal 'Usage: prg grep [GREP_OPTIONS] search-regex' 1208 The status should equal 1 1209 End 1210 End 1211 1212 Describe 'cmd_help' 1213 COMMAND=help 1214 1215 It 'displays version and usage without arguments' 1216 cmd_usage() { mocklog cmd_usage "$@"; } 1217 cmd_version() { mocklog cmd_version "$@"; } 1218 expected_output() { %text 1219 #| 1220 #|Usage: 1221 } 1222 result() { 1223 %text | @sed 's/\$$//' 1224 #|$ cmd_version 1225 #|$ cmd_usage yes $ 1226 } 1227 When call cmd_help 1228 The status should be success 1229 The output should equal "$(expected_output)" 1230 The error should equal "$(result)" 1231 End 1232 1233 It 'displays only usage with arguments' 1234 cmd_usage() { mocklog cmd_usage "$@"; } 1235 cmd_version() { mocklog cmd_version "$@"; } 1236 When call cmd_help foo bar 1237 The status should be success 1238 The output should be blank 1239 The error should equal '$ cmd_usage yes foo bar' 1240 End 1241 End 1242 1243 Describe 'cmd_init' 1244 COMMAND=init 1245 1246 It 'initializes the whole store' 1247 result() { 1248 %text | @sed 's/\$$//' 1249 #|$ check_sneaky_path $ 1250 #|$ do_init recipient-1 recipient-2 1251 #|DECISION=default 1252 #|OVERWRITE=yes 1253 } 1254 When call cmd_init recipient-1 recipient-2 1255 The status should be success 1256 The output should be blank 1257 The error should equal "$(result)" 1258 End 1259 1260 It 'initializes the whole store conservatively with a long option' 1261 result() { 1262 %text | @sed 's/\$$//' 1263 #|$ check_sneaky_path $ 1264 #|$ do_init recipient-1 recipient-2 1265 #|DECISION=keep 1266 #|OVERWRITE=yes 1267 } 1268 When call cmd_init --keep recipient-1 recipient-2 1269 The status should be success 1270 The output should be blank 1271 The error should equal "$(result)" 1272 End 1273 1274 It 'initializes the whole store conservatively with a short option' 1275 result() { 1276 %text | @sed 's/\$$//' 1277 #|$ check_sneaky_path $ 1278 #|$ do_init recipient-1 recipient-2 1279 #|DECISION=keep 1280 #|OVERWRITE=yes 1281 } 1282 When call cmd_init -k recipient-1 recipient-2 1283 The status should be success 1284 The output should be blank 1285 The error should equal "$(result)" 1286 End 1287 1288 It 'initializes the whole store interactively with a long option' 1289 result() { 1290 %text | @sed 's/\$$//' 1291 #|$ check_sneaky_path $ 1292 #|$ do_init recipient-1 recipient-2 1293 #|DECISION=interactive 1294 #|OVERWRITE=yes 1295 } 1296 When call cmd_init --interactive recipient-1 recipient-2 1297 The status should be success 1298 The output should be blank 1299 The error should equal "$(result)" 1300 End 1301 1302 It 'initializes the whole store interactively with a short option' 1303 result() { 1304 %text | @sed 's/\$$//' 1305 #|$ check_sneaky_path $ 1306 #|$ do_init recipient-1 recipient-2 1307 #|DECISION=interactive 1308 #|OVERWRITE=yes 1309 } 1310 When call cmd_init -i recipient-1 recipient-2 1311 The status should be success 1312 The output should be blank 1313 The error should equal "$(result)" 1314 End 1315 1316 It 'initializes a subdirectory with a collapsed long option' 1317 result() { 1318 %text 1319 #|$ check_sneaky_path sub 1320 #|$ do_init sub recipient 1321 #|DECISION=default 1322 #|OVERWRITE=yes 1323 } 1324 When call cmd_init --path=sub recipient 1325 The status should be success 1326 The output should be blank 1327 The error should equal "$(result)" 1328 End 1329 1330 It 'initializes a subdirectory with an expanded long option' 1331 result() { 1332 %text 1333 #|$ check_sneaky_path sub 1334 #|$ do_init sub recipient 1335 #|DECISION=default 1336 #|OVERWRITE=yes 1337 } 1338 When call cmd_init --path sub recipient 1339 The status should be success 1340 The output should be blank 1341 The error should equal "$(result)" 1342 End 1343 1344 It 'initializes a subdirectory with a collapsed short option' 1345 result() { 1346 %text 1347 #|$ check_sneaky_path sub 1348 #|$ do_init sub recipient 1349 #|DECISION=default 1350 #|OVERWRITE=yes 1351 } 1352 When call cmd_init -psub recipient 1353 The status should be success 1354 The output should be blank 1355 The error should equal "$(result)" 1356 End 1357 1358 It 'initializes a subdirectory with an expanded short option' 1359 result() { 1360 %text 1361 #|$ check_sneaky_path sub 1362 #|$ do_init sub recipient 1363 #|DECISION=default 1364 #|OVERWRITE=yes 1365 } 1366 When call cmd_init -p sub recipient 1367 The status should be success 1368 The output should be blank 1369 The error should equal "$(result)" 1370 End 1371 1372 It 'interactively initializes a directory with collapsed short options' 1373 result() { 1374 %text 1375 #|$ check_sneaky_path sub 1376 #|$ do_init sub recipient 1377 #|DECISION=interactive 1378 #|OVERWRITE=yes 1379 } 1380 When call cmd_init -ipsub recipient 1381 The status should be success 1382 The output should be blank 1383 The error should equal "$(result)" 1384 End 1385 1386 It 'conservatively initializes a directory with long options' 1387 result() { 1388 %text 1389 #|$ check_sneaky_path sub 1390 #|$ do_init sub recipient 1391 #|DECISION=keep 1392 #|OVERWRITE=yes 1393 } 1394 When call cmd_init --path sub --keep recipient 1395 The status should be success 1396 The output should be blank 1397 The error should equal "$(result)" 1398 End 1399 1400 It 'de-initializes a subdirectory' 1401 result() { 1402 %text 1403 #|$ check_sneaky_path sub 1404 #|$ do_deinit sub 1405 #|DECISION=default 1406 } 1407 When call cmd_init -p sub '' 1408 The status should be success 1409 The output should be blank 1410 The error should equal "$(result)" 1411 End 1412 1413 It 'supports recipients starting with dash' 1414 result() { 1415 %text | @sed 's/\$$//' 1416 #|$ check_sneaky_path $ 1417 #|$ do_init -recipient 1418 #|DECISION=default 1419 #|OVERWRITE=yes 1420 } 1421 When call cmd_init -- -recipient 1422 The status should be success 1423 The output should be blank 1424 The error should equal "$(result)" 1425 End 1426 1427 usage_text() { %text 1428 #|Usage: prg init [--interactive,-i | --keep,-k ] 1429 #| [--path=subfolder,-p subfolder] age-recipient ... 1430 } 1431 1432 It 'reports a bad option' 1433 cat() { @cat; } 1434 When run cmd_init -q arg 1435 The output should be blank 1436 The error should equal "$(usage_text)" 1437 The status should equal 1 1438 End 1439 1440 It 'reports conflicting options (`-i` then `-k`)' 1441 cat() { @cat; } 1442 When run cmd_init -ik arg 1443 The output should be blank 1444 The error should equal "$(usage_text)" 1445 The status should equal 1 1446 End 1447 1448 It 'reports conflicting options (`-k` then `-i`)' 1449 cat() { @cat; } 1450 When run cmd_init --keep --interactive arg 1451 The output should be blank 1452 The error should equal "$(usage_text)" 1453 The status should equal 1 1454 End 1455 1456 It 'reports a missing recipient' 1457 cat() { @cat; } 1458 When run cmd_init -p sub 1459 The output should be blank 1460 The error should equal "$(usage_text)" 1461 The status should equal 1 1462 End 1463 1464 It 'reports a missing path' 1465 cat() { @cat; } 1466 When run cmd_init -p 1467 The output should be blank 1468 The error should equal "$(usage_text)" 1469 The status should equal 1 1470 End 1471 1472 It 'reports a lack of argument' 1473 cat() { @cat; } 1474 When run cmd_init 1475 The output should be blank 1476 The error should equal "$(usage_text)" 1477 The status should equal 1 1478 End 1479 End 1480 1481 Describe 'cmd_insert' 1482 COMMAND=insert 1483 1484 It 'inserts a few new entries' 1485 result() { 1486 %text 1487 #|$ check_sneaky_path secret1 1488 #|$ check_sneaky_path secret2 1489 #|$ do_insert secret1 1490 #|ECHO=no 1491 #|MULTILINE=no 1492 #|OVERWRITE=no 1493 #|$ do_insert secret2 1494 #|ECHO=no 1495 #|MULTILINE=no 1496 #|OVERWRITE=no 1497 } 1498 When call cmd_insert secret1 secret2 1499 The status should be success 1500 The output should be blank 1501 The error should equal "$(result)" 1502 End 1503 1504 It 'inserts a new flag-like entry' 1505 result() { 1506 %text 1507 #|$ check_sneaky_path -c 1508 #|$ do_insert -c 1509 #|ECHO=no 1510 #|MULTILINE=no 1511 #|OVERWRITE=no 1512 } 1513 When call cmd_insert -- -c 1514 The status should be success 1515 The output should be blank 1516 The error should equal "$(result)" 1517 End 1518 1519 It 'inserts a new entry with echo (short option)' 1520 result() { 1521 %text 1522 #|$ check_sneaky_path secret 1523 #|$ do_insert secret 1524 #|ECHO=yes 1525 #|MULTILINE=no 1526 #|OVERWRITE=no 1527 } 1528 When call cmd_insert -e secret 1529 The status should be success 1530 The output should be blank 1531 The error should equal "$(result)" 1532 End 1533 1534 It 'inserts a new entry with echo (long option)' 1535 result() { 1536 %text 1537 #|$ check_sneaky_path secret 1538 #|$ do_insert secret 1539 #|ECHO=yes 1540 #|MULTILINE=no 1541 #|OVERWRITE=no 1542 } 1543 When call cmd_insert --echo secret 1544 The status should be success 1545 The output should be blank 1546 The error should equal "$(result)" 1547 End 1548 1549 It 'forcefully inserts a new entry with echo (short option)' 1550 result() { 1551 %text 1552 #|$ check_sneaky_path secret 1553 #|$ do_insert secret 1554 #|ECHO=yes 1555 #|MULTILINE=no 1556 #|OVERWRITE=yes 1557 } 1558 When call cmd_insert -fe secret 1559 The status should be success 1560 The output should be blank 1561 The error should equal "$(result)" 1562 End 1563 1564 It 'forcefully inserts a new entry with echo (short options)' 1565 result() { 1566 %text 1567 #|$ check_sneaky_path secret 1568 #|$ do_insert secret 1569 #|ECHO=yes 1570 #|MULTILINE=no 1571 #|OVERWRITE=yes 1572 } 1573 When call cmd_insert -e -f secret 1574 The status should be success 1575 The output should be blank 1576 The error should equal "$(result)" 1577 End 1578 1579 It 'forcefully inserts a new entry with echo (long option)' 1580 result() { 1581 %text 1582 #|$ check_sneaky_path secret 1583 #|$ do_insert secret 1584 #|ECHO=yes 1585 #|MULTILINE=no 1586 #|OVERWRITE=yes 1587 } 1588 When call cmd_insert --force --echo secret 1589 The status should be success 1590 The output should be blank 1591 The error should equal "$(result)" 1592 End 1593 1594 It 'inserts a new multiline entry (short option)' 1595 result() { 1596 %text 1597 #|$ check_sneaky_path secret 1598 #|$ do_insert secret 1599 #|ECHO=no 1600 #|MULTILINE=yes 1601 #|OVERWRITE=no 1602 } 1603 When call cmd_insert -m secret 1604 The status should be success 1605 The output should be blank 1606 The error should equal "$(result)" 1607 End 1608 1609 It 'inserts a new multiline entry (long option)' 1610 result() { 1611 %text 1612 #|$ check_sneaky_path secret 1613 #|$ do_insert secret 1614 #|ECHO=no 1615 #|MULTILINE=yes 1616 #|OVERWRITE=no 1617 } 1618 When call cmd_insert --multiline secret 1619 The status should be success 1620 The output should be blank 1621 The error should equal "$(result)" 1622 End 1623 1624 It 'forcefully inserts a new multiline entry (short option)' 1625 result() { 1626 %text 1627 #|$ check_sneaky_path secret 1628 #|$ do_insert secret 1629 #|ECHO=no 1630 #|MULTILINE=yes 1631 #|OVERWRITE=yes 1632 } 1633 When call cmd_insert -mf secret 1634 The status should be success 1635 The output should be blank 1636 The error should equal "$(result)" 1637 End 1638 1639 It 'forcefully inserts a new multiline entry (short options)' 1640 result() { 1641 %text 1642 #|$ check_sneaky_path secret 1643 #|$ do_insert secret 1644 #|ECHO=no 1645 #|MULTILINE=yes 1646 #|OVERWRITE=yes 1647 } 1648 When call cmd_insert -m -f secret 1649 The status should be success 1650 The output should be blank 1651 The error should equal "$(result)" 1652 End 1653 1654 It 'forcefully inserts a new multiline entry (long option)' 1655 result() { 1656 %text 1657 #|$ check_sneaky_path secret 1658 #|$ do_insert secret 1659 #|ECHO=no 1660 #|MULTILINE=yes 1661 #|OVERWRITE=yes 1662 } 1663 When call cmd_insert --force --multiline secret 1664 The status should be success 1665 The output should be blank 1666 The error should equal "$(result)" 1667 End 1668 1669 It 'reports a bad option' 1670 cat() { @cat; } 1671 When run cmd_insert -u secret 1672 The output should be blank 1673 The error should equal \ 1674 'Usage: prg insert [--echo,-e | --multiline,-m] [--force,-f] pass-name' 1675 The status should equal 1 1676 End 1677 1678 It 'reports incompatible long options' 1679 cat() { @cat; } 1680 When run cmd_insert --multiline --echo secret 1681 The output should be blank 1682 The error should equal \ 1683 'Usage: prg insert [--echo,-e | --multiline,-m] [--force,-f] pass-name' 1684 The status should equal 1 1685 End 1686 1687 It 'reports incompatible short options' 1688 cat() { @cat; } 1689 When run cmd_insert -em secret 1690 The output should be blank 1691 The error should equal \ 1692 'Usage: prg insert [--echo,-e | --multiline,-m] [--force,-f] pass-name' 1693 The status should equal 1 1694 End 1695 1696 It 'reports a lack of argument' 1697 cat() { @cat; } 1698 When run cmd_insert 1699 The output should be blank 1700 The error should equal \ 1701 'Usage: prg insert [--echo,-e | --multiline,-m] [--force,-f] pass-name' 1702 The status should equal 1 1703 End 1704 End 1705 1706 Describe 'cmd_list_or_show' 1707 COMMAND= 1708 1709 It 'lists the whole store as a list' 1710 result() { 1711 %text | @sed 's/\$$//' 1712 #|$ do_list_or_show $ 1713 #|LIST_VIEW=yes 1714 #|SELECTED_LINE=1 1715 #|SHOW=text 1716 } 1717 When call cmd_list_or_show -r 1718 The status should be success 1719 The output should be blank 1720 The error should equal "$(result)" 1721 End 1722 1723 It 'lists the whole store as a tree' 1724 result() { 1725 %text | @sed 's/\$$//' 1726 #|$ do_list_or_show $ 1727 #|LIST_VIEW=no 1728 #|SELECTED_LINE=1 1729 #|SHOW=text 1730 } 1731 When call cmd_list_or_show 1732 The status should be success 1733 The output should be blank 1734 The error should equal "$(result)" 1735 End 1736 1737 It 'shows multiple entries' 1738 result() { 1739 %text 1740 #|$ check_sneaky_path arg1 1741 #|$ check_sneaky_path arg2 1742 #|$ check_sneaky_path arg3 1743 #|$ do_list_or_show arg1 1744 #|LIST_VIEW=no 1745 #|SELECTED_LINE=1 1746 #|SHOW=text 1747 #|$ do_list_or_show arg2 1748 #|LIST_VIEW=no 1749 #|SELECTED_LINE=1 1750 #|SHOW=text 1751 #|$ do_list_or_show arg3 1752 #|LIST_VIEW=no 1753 #|SELECTED_LINE=1 1754 #|SHOW=text 1755 } 1756 When call cmd_list_or_show arg1 arg2 arg3 1757 The status should be success 1758 The output should be blank 1759 The error should equal "$(result)" 1760 End 1761 1762 It 'shows a flag-like entry' 1763 result() { 1764 %text 1765 #|$ check_sneaky_path -c 1766 #|$ do_list_or_show -c 1767 #|LIST_VIEW=no 1768 #|SELECTED_LINE=1 1769 #|SHOW=text 1770 } 1771 When call cmd_list_or_show -- -c 1772 The status should be success 1773 The output should be blank 1774 The error should equal "$(result)" 1775 End 1776 1777 It 'copies an entry into the clipboard (short option)' 1778 result() { 1779 %text 1780 #|$ check_sneaky_path arg 1781 #|$ do_list_or_show arg 1782 #|LIST_VIEW=no 1783 #|SELECTED_LINE=1 1784 #|SHOW=clip 1785 } 1786 When call cmd_list_or_show -c arg 1787 The status should be success 1788 The output should be blank 1789 The error should equal "$(result)" 1790 End 1791 1792 It 'copies an entry into the clipboard (long option)' 1793 result() { 1794 %text 1795 #|$ check_sneaky_path arg 1796 #|$ do_list_or_show arg 1797 #|LIST_VIEW=no 1798 #|SELECTED_LINE=1 1799 #|SHOW=clip 1800 } 1801 When call cmd_list_or_show --clip arg 1802 The status should be success 1803 The output should be blank 1804 The error should equal "$(result)" 1805 End 1806 1807 It 'copies a line of an entry into the clipboard (short option)' 1808 result() { 1809 %text 1810 #|$ check_sneaky_path arg 1811 #|$ do_list_or_show arg 1812 #|LIST_VIEW=no 1813 #|SELECTED_LINE=2 1814 #|SHOW=clip 1815 } 1816 When call cmd_list_or_show -c2 arg 1817 The status should be success 1818 The output should be blank 1819 The error should equal "$(result)" 1820 End 1821 1822 It 'copies a line of an entry into the clipboard (short option)' 1823 result() { 1824 %text 1825 #|$ check_sneaky_path arg 1826 #|$ do_list_or_show arg 1827 #|LIST_VIEW=no 1828 #|SELECTED_LINE=2 1829 #|SHOW=clip 1830 } 1831 When call cmd_list_or_show --clip=2 arg 1832 The status should be success 1833 The output should be blank 1834 The error should equal "$(result)" 1835 End 1836 1837 It 'shows an entry as a QR-code (short option)' 1838 result() { 1839 %text 1840 #|$ check_sneaky_path arg 1841 #|$ do_list_or_show arg 1842 #|LIST_VIEW=no 1843 #|SELECTED_LINE=1 1844 #|SHOW=qrcode 1845 } 1846 When call cmd_list_or_show -q arg 1847 The status should be success 1848 The output should be blank 1849 The error should equal "$(result)" 1850 End 1851 1852 It 'shows an entry as a QR-code (long option)' 1853 result() { 1854 %text 1855 #|$ check_sneaky_path arg 1856 #|$ do_list_or_show arg 1857 #|LIST_VIEW=no 1858 #|SELECTED_LINE=1 1859 #|SHOW=qrcode 1860 } 1861 When call cmd_list_or_show --qrcode arg 1862 The status should be success 1863 The output should be blank 1864 The error should equal "$(result)" 1865 End 1866 1867 It 'shows the line of an entry as a QR-code (short option)' 1868 result() { 1869 %text 1870 #|$ check_sneaky_path arg 1871 #|$ do_list_or_show arg 1872 #|LIST_VIEW=no 1873 #|SELECTED_LINE=3 1874 #|SHOW=qrcode 1875 } 1876 When call cmd_list_or_show -q3 arg 1877 The status should be success 1878 The output should be blank 1879 The error should equal "$(result)" 1880 End 1881 1882 It 'shows the line of an entry as a QR-code (long option)' 1883 result() { 1884 %text 1885 #|$ check_sneaky_path arg 1886 #|$ do_list_or_show arg 1887 #|LIST_VIEW=no 1888 #|SELECTED_LINE=3 1889 #|SHOW=qrcode 1890 } 1891 When call cmd_list_or_show --qrcode=3 arg 1892 The status should be success 1893 The output should be blank 1894 The error should equal "$(result)" 1895 End 1896 1897 It 'shows an entry as a raw list (shot option)' 1898 result() { 1899 %text 1900 #|$ check_sneaky_path arg 1901 #|$ do_list_or_show arg 1902 #|LIST_VIEW=yes 1903 #|SELECTED_LINE=1 1904 #|SHOW=text 1905 } 1906 When call cmd_list_or_show -r arg 1907 The status should be success 1908 The output should be blank 1909 The error should equal "$(result)" 1910 End 1911 1912 It 'shows an entry as a raw list (long option)' 1913 result() { 1914 %text 1915 #|$ check_sneaky_path arg 1916 #|$ do_list_or_show arg 1917 #|LIST_VIEW=yes 1918 #|SELECTED_LINE=1 1919 #|SHOW=text 1920 } 1921 When call cmd_list_or_show --raw arg 1922 The status should be success 1923 The output should be blank 1924 The error should equal "$(result)" 1925 End 1926 1927 It 'reports incompatible show options' 1928 cat() { @cat; } 1929 result() { %text 1930 #|Usage: prg [list] [--raw,-r] [subfolder] 1931 #| prg [show] [--clip[=line-number],-c[line-number] | 1932 #| --qrcode[=line-number],-q[line-number]] pass-name 1933 } 1934 When run cmd_list_or_show -q -c arg 1935 The output should be blank 1936 The error should equal "$(result)" 1937 The status should equal 1 1938 End 1939 1940 It 'reports a bad option for both commands' 1941 cat() { @cat; } 1942 result() { %text 1943 #|Usage: prg [list] [--raw,-r] [subfolder] 1944 #| prg [show] [--clip[=line-number],-c[line-number] | 1945 #| --qrcode[=line-number],-q[line-number]] pass-name 1946 } 1947 When run cmd_list_or_show -f arg 1948 The output should be blank 1949 The error should equal "$(result)" 1950 The status should equal 1 1951 End 1952 1953 It 'reports a bad option for list command' 1954 COMMAND=list 1955 cat() { @cat; } 1956 result() { %text 1957 #|Usage: prg [list] [--raw,-r] [subfolder] 1958 } 1959 When run cmd_list_or_show -f arg 1960 The output should be blank 1961 The error should equal "$(result)" 1962 The status should equal 1 1963 End 1964 1965 It 'reports a bad option for show command' 1966 COMMAND=show 1967 cat() { @cat; } 1968 result() { %text 1969 #|Usage: prg [show] [--clip[=line-number],-c[line-number] | 1970 #| --qrcode[=line-number],-q[line-number]] pass-name 1971 } 1972 When run cmd_list_or_show -f arg 1973 The output should be blank 1974 The error should equal "$(result)" 1975 The status should equal 1 1976 End 1977 End 1978 1979 Describe 'cmd_move' 1980 COMMAND=move 1981 1982 It 'moves multiple files' 1983 result() { 1984 %text 1985 #|$ check_sneaky_path src1 1986 #|$ check_sneaky_path src2 1987 #|$ check_sneaky_path src3 1988 #|$ check_sneaky_path dest 1989 #|$ do_copy_move src1 dest/ 1990 #|ACTION=Move 1991 #|DECISION=default 1992 #|OVERWRITE=no 1993 #|SCM_ACTION=scm_mv 1994 #|$ do_copy_move src2 dest/ 1995 #|ACTION=Move 1996 #|DECISION=default 1997 #|OVERWRITE=no 1998 #|SCM_ACTION=scm_mv 1999 #|$ do_copy_move src3 dest/ 2000 #|ACTION=Move 2001 #|DECISION=default 2002 #|OVERWRITE=no 2003 #|SCM_ACTION=scm_mv 2004 } 2005 When call cmd_move src1 src2 src3 dest 2006 The status should be success 2007 The output should be blank 2008 The error should equal "$(result)" 2009 End 2010 2011 It 'moves forcefully with a long option' 2012 result() { 2013 %text 2014 #|$ check_sneaky_path src 2015 #|$ check_sneaky_path dest 2016 #|$ do_copy_move src dest 2017 #|ACTION=Move 2018 #|DECISION=default 2019 #|OVERWRITE=yes 2020 #|SCM_ACTION=scm_mv 2021 } 2022 When call cmd_move --force src dest 2023 The status should be success 2024 The output should be blank 2025 The error should equal "$(result)" 2026 End 2027 2028 It 'moves forcefully with a short option' 2029 result() { 2030 %text 2031 #|$ check_sneaky_path src 2032 #|$ check_sneaky_path dest 2033 #|$ do_copy_move src dest 2034 #|ACTION=Move 2035 #|DECISION=default 2036 #|OVERWRITE=yes 2037 #|SCM_ACTION=scm_mv 2038 } 2039 When call cmd_move -f src dest 2040 The status should be success 2041 The output should be blank 2042 The error should equal "$(result)" 2043 End 2044 2045 It 'always reencrypts with a long option' 2046 result() { 2047 %text 2048 #|$ check_sneaky_path src 2049 #|$ check_sneaky_path dest 2050 #|$ do_copy_move src dest 2051 #|ACTION=Move 2052 #|DECISION=force 2053 #|OVERWRITE=no 2054 #|SCM_ACTION=scm_mv 2055 } 2056 When call cmd_move --reencrypt src dest 2057 The status should be success 2058 The output should be blank 2059 The error should equal "$(result)" 2060 End 2061 2062 It 'always reencrypts with a short option' 2063 result() { 2064 %text 2065 #|$ check_sneaky_path src 2066 #|$ check_sneaky_path dest 2067 #|$ do_copy_move src dest 2068 #|ACTION=Move 2069 #|DECISION=force 2070 #|OVERWRITE=no 2071 #|SCM_ACTION=scm_mv 2072 } 2073 When call cmd_move -e src dest 2074 The status should be success 2075 The output should be blank 2076 The error should equal "$(result)" 2077 End 2078 2079 It 'interactively reencrypts with a long option' 2080 result() { 2081 %text 2082 #|$ check_sneaky_path src 2083 #|$ check_sneaky_path dest 2084 #|$ do_copy_move src dest 2085 #|ACTION=Move 2086 #|DECISION=interactive 2087 #|OVERWRITE=no 2088 #|SCM_ACTION=scm_mv 2089 } 2090 When call cmd_move --interactive src dest 2091 The status should be success 2092 The output should be blank 2093 The error should equal "$(result)" 2094 End 2095 2096 It 'interactively reencrypts with a short option' 2097 result() { 2098 %text 2099 #|$ check_sneaky_path src 2100 #|$ check_sneaky_path dest 2101 #|$ do_copy_move src dest 2102 #|ACTION=Move 2103 #|DECISION=interactive 2104 #|OVERWRITE=no 2105 #|SCM_ACTION=scm_mv 2106 } 2107 When call cmd_move -i src dest 2108 The status should be success 2109 The output should be blank 2110 The error should equal "$(result)" 2111 End 2112 2113 It 'never reencrypts with a long option' 2114 result() { 2115 %text 2116 #|$ check_sneaky_path src 2117 #|$ check_sneaky_path dest 2118 #|$ do_copy_move src dest 2119 #|ACTION=Move 2120 #|DECISION=keep 2121 #|OVERWRITE=no 2122 #|SCM_ACTION=scm_mv 2123 } 2124 When call cmd_move --keep src dest 2125 The status should be success 2126 The output should be blank 2127 The error should equal "$(result)" 2128 End 2129 2130 It 'never reencrypts with a short option' 2131 result() { 2132 %text 2133 #|$ check_sneaky_path src 2134 #|$ check_sneaky_path dest 2135 #|$ do_copy_move src dest 2136 #|ACTION=Move 2137 #|DECISION=keep 2138 #|OVERWRITE=no 2139 #|SCM_ACTION=scm_mv 2140 } 2141 When call cmd_move -k src dest 2142 The status should be success 2143 The output should be blank 2144 The error should equal "$(result)" 2145 End 2146 2147 It 'moves a file named like a flag' 2148 result() { 2149 %text 2150 #|$ check_sneaky_path -s 2151 #|$ check_sneaky_path dest 2152 #|$ do_copy_move -s dest 2153 #|ACTION=Move 2154 #|DECISION=default 2155 #|OVERWRITE=no 2156 #|SCM_ACTION=scm_mv 2157 } 2158 When call cmd_move -- -s dest 2159 The status should be success 2160 The output should be blank 2161 The error should equal "$(result)" 2162 End 2163 2164 usage_text() { %text 2165 #|Usage: prg move [--reencrypt,-e | --interactive,-i | --keep,-k ] 2166 #| [--force,-f] old-path new-path 2167 } 2168 2169 It 'reports a bad option' 2170 cat() { @cat; } 2171 When run cmd_move -s arg 2172 The output should be blank 2173 The error should equal "$(usage_text)" 2174 The status should equal 1 2175 End 2176 2177 It 'reports incompatible re-encryption options (-e and -i)' 2178 cat() { @cat; } 2179 When run cmd_move -ei src dest 2180 The output should be blank 2181 The error should equal "$(usage_text)" 2182 The status should equal 1 2183 End 2184 2185 It 'reports incompatible re-encryption options (-i and -k)' 2186 cat() { @cat; } 2187 When run cmd_move -ik src dest 2188 The output should be blank 2189 The error should equal "$(usage_text)" 2190 The status should equal 1 2191 End 2192 2193 It 'reports incompatible re-encryption options (-k and -e)' 2194 cat() { @cat; } 2195 When run cmd_move -ke src dest 2196 The output should be blank 2197 The error should equal "$(usage_text)" 2198 The status should equal 1 2199 End 2200 2201 It 'reports a lack of argument' 2202 cat() { @cat; } 2203 When run cmd_move src 2204 The output should be blank 2205 The error should equal "$(usage_text)" 2206 The status should equal 1 2207 End 2208 End 2209 2210 Describe 'cmd_random' 2211 COMMAND=generate 2212 GENERATED_LENGTH=25 2213 2214 random_chars() { mocklog random_chars "$@"; } 2215 2216 It 'generates random characters with default parameters' 2217 When run cmd_random 2218 The status should be success 2219 The error should equal \ 2220 "$ random_chars ${GENERATED_LENGTH} ${CHARACTER_SET}" 2221 End 2222 2223 It 'generates random characters with default character set' 2224 When run cmd_random 8 2225 The status should be success 2226 The error should equal "$ random_chars 8 ${CHARACTER_SET}" 2227 End 2228 2229 It 'generates random characters with the given arguments' 2230 When run cmd_random 8 a-z 2231 The status should be success 2232 The error should equal "$ random_chars 8 a-z" 2233 End 2234 2235 It 'reports too many arguments' 2236 cat() { @cat; } 2237 When run cmd_random 1 2 3 2238 The output should be blank 2239 The error should equal 'Usage: prg random [pass-length [character-set]]' 2240 The status should equal 1 2241 End 2242 End 2243 2244 Describe 'cmd_reencrypt' 2245 COMMAND=reencrypt 2246 2247 It 're-encrypts multiple files and directories' 2248 result() { 2249 %text 2250 #|$ check_sneaky_path file-1 2251 #|$ check_sneaky_path dir/ 2252 #|$ check_sneaky_path sub/file-2 2253 #|$ do_reencrypt file-1 2254 #|DECISION=default 2255 #|RECURSIVE=no 2256 #|$ do_reencrypt dir/ 2257 #|DECISION=default 2258 #|RECURSIVE=no 2259 #|$ do_reencrypt sub/file-2 2260 #|DECISION=default 2261 #|RECURSIVE=no 2262 } 2263 When call cmd_reencrypt file-1 dir/ sub/file-2 2264 The status should be success 2265 The output should be blank 2266 The error should equal "$(result)" 2267 End 2268 2269 It 'deeply re-encrypts with a long option' 2270 result() { 2271 %text 2272 #|$ check_sneaky_path arg 2273 #|$ do_reencrypt arg 2274 #|DECISION=default 2275 #|RECURSIVE=yes 2276 } 2277 When call cmd_reencrypt --deep arg 2278 The status should be success 2279 The output should be blank 2280 The error should equal "$(result)" 2281 End 2282 2283 It 'deeply re-encrypts with a short option' 2284 result() { 2285 %text 2286 #|$ check_sneaky_path arg 2287 #|$ do_reencrypt arg 2288 #|DECISION=default 2289 #|RECURSIVE=yes 2290 } 2291 When call cmd_reencrypt -d arg 2292 The status should be success 2293 The output should be blank 2294 The error should equal "$(result)" 2295 End 2296 2297 It 'deeply and interactively re-encrypts with short options' 2298 result() { 2299 %text 2300 #|$ check_sneaky_path arg 2301 #|$ do_reencrypt arg 2302 #|DECISION=interactive 2303 #|RECURSIVE=yes 2304 } 2305 When call cmd_reencrypt -di arg 2306 The status should be success 2307 The output should be blank 2308 The error should equal "$(result)" 2309 End 2310 2311 It 'interactively re-encrypts with a long option' 2312 result() { 2313 %text 2314 #|$ check_sneaky_path arg 2315 #|$ do_reencrypt arg 2316 #|DECISION=interactive 2317 #|RECURSIVE=no 2318 } 2319 When call cmd_reencrypt --interactive arg 2320 The status should be success 2321 The output should be blank 2322 The error should equal "$(result)" 2323 End 2324 2325 It 'interactively re-encrypts with a short option' 2326 result() { 2327 %text 2328 #|$ check_sneaky_path arg 2329 #|$ do_reencrypt arg 2330 #|DECISION=interactive 2331 #|RECURSIVE=no 2332 } 2333 When call cmd_reencrypt -i arg 2334 The status should be success 2335 The output should be blank 2336 The error should equal "$(result)" 2337 End 2338 2339 It 'interactively and deeply re-encrypts with short options' 2340 result() { 2341 %text 2342 #|$ check_sneaky_path arg 2343 #|$ do_reencrypt arg 2344 #|DECISION=interactive 2345 #|RECURSIVE=yes 2346 } 2347 When call cmd_reencrypt -id arg 2348 The status should be success 2349 The output should be blank 2350 The error should equal "$(result)" 2351 End 2352 2353 It 're-encrypts a file named like a flag' 2354 result() { 2355 %text 2356 #|$ check_sneaky_path -s 2357 #|$ do_reencrypt -s 2358 #|DECISION=default 2359 #|RECURSIVE=no 2360 } 2361 When call cmd_reencrypt -- -s 2362 The status should be success 2363 The output should be blank 2364 The error should equal "$(result)" 2365 End 2366 2367 usage_text() { %text 2368 #|Usage: prg reencrypt [--deep,-d] [--interactive,-i] pass-name|subfolder ... 2369 } 2370 2371 It 'reports a bad option' 2372 cat() { @cat; } 2373 When run cmd_reencrypt -s arg 2374 The status should equal 1 2375 The output should be blank 2376 The error should equal "$(usage_text)" 2377 End 2378 2379 It 'reports a lack of argument' 2380 cat() { @cat; } 2381 When run cmd_reencrypt 2382 The status should equal 1 2383 The output should be blank 2384 The error should equal "$(usage_text)" 2385 End 2386 End 2387 2388 Describe 'cmd_usage' 2389 COMMAND=usage 2390 CLIP_TIME='$CLIP_TIME' 2391 GENERATED_LENGTH='$GENERATED_LENGTH' 2392 cat() { @cat; } 2393 2394 It 'includes help about all commands' 2395 When call cmd_usage 2396 The status should be success 2397 The output should include 'prg copy' 2398 The output should include 'prg delete' 2399 The output should include 'prg edit' 2400 The output should include 'prg find' 2401 The output should include 'prg generate' 2402 The output should include 'prg git' 2403 The output should include 'prg gitconfig' 2404 The output should include 'prg grep' 2405 The output should include 'prg help' 2406 The output should include 'prg init' 2407 The output should include 'prg insert' 2408 The output should include 'prg [list]' 2409 The output should include 'prg move' 2410 The output should include 'prg random' 2411 The output should include 'prg reencrypt' 2412 The output should include 'prg [show]' 2413 The output should include 'prg version' 2414 End 2415 2416 It 'displays terse help about the given commands' 2417 When call cmd_usage no '> ' version edit version 2418 The status should be success 2419 The output should match pattern '*prg version*prg edit*prg version*' 2420 The lines of output should equal 3 2421 End 2422 2423 It 'displays verbose help about the given commands' 2424 When call cmd_usage yes '> ' version edit version 2425 The status should be success 2426 The output should match pattern \ 2427 '*prg version*Show*prg edit*Insert*prg version*Show*' 2428 The lines of output should equal 6 2429 End 2430 2431 It 'rejects unknown commands' 2432 When run cmd_usage no '> ' foo 2433 The output should be blank 2434 The error should equal 'cmd_usage: unknown command "foo"' 2435 The status should equal 1 2436 End 2437 End 2438 2439 Describe 'cmd_version' 2440 COMMAND=version 2441 2442 It 'shows the version box' 2443 cat() { @cat; } 2444 result() { 2445 %text 2446 #|============================================== 2447 #|= pashage: age-backed POSIX password manager = 2448 #|= = 2449 #|= v* 2450 #|= = 2451 #|= Natasha Kerensikova = 2452 #|= = 2453 #|= Based on: = 2454 #|= password-store by Jason A. Donenfeld = 2455 #|= passage by Filippo Valsorda = 2456 #|= pash by Dylan Araps = 2457 #|============================================== 2458 } 2459 When call cmd_version 2460 The status should be success 2461 The output should match pattern "$(result)" 2462 End 2463 End 2464 End