pashage

Yet Another Opinionated Re-engineering of the Unix Password Store
git clone https://git.instinctive.eu/pashage.git
Log | Files | Refs | README | LICENSE

usage_spec.sh (64958B)


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