2021-01-12 16:27:25 -05:00
# frozen_string_literal: true
require " completions "
2024-02-18 15:11:11 -08:00
RSpec . describe Homebrew :: Completions do
2021-01-18 03:09:57 -05:00
let ( :completions_dir ) { HOMEBREW_REPOSITORY / " completions " }
2021-01-12 16:27:25 -05:00
let ( :internal_path ) { HOMEBREW_REPOSITORY / " Library/Taps/homebrew/homebrew-bar " }
let ( :external_path ) { HOMEBREW_REPOSITORY / " Library/Taps/foo/homebrew-bar " }
before do
HOMEBREW_REPOSITORY . cd do
system " git " , " init "
end
2021-01-18 03:09:57 -05:00
described_class :: SHELLS . each do | shell |
( completions_dir / shell ) . mkpath
end
2021-01-12 16:27:25 -05:00
internal_path . mkpath
external_path . mkpath
end
after do
2021-01-18 03:09:57 -05:00
FileUtils . rm_rf completions_dir
2021-01-12 16:27:25 -05:00
FileUtils . rm_rf internal_path
FileUtils . rm_rf external_path . dirname
end
2021-01-18 03:09:57 -05:00
context " when linking or unlinking completions " do
def setup_completions ( external : )
2021-05-03 13:24:32 +01:00
internal_bash_completion = internal_path / " completions/bash "
external_bash_completion = external_path / " completions/bash "
internal_bash_completion . mkpath
( internal_bash_completion / " foo_internal " ) . write " # foo completions "
2021-01-18 03:09:57 -05:00
if external
2021-05-03 13:24:32 +01:00
external_bash_completion . mkpath
( external_bash_completion / " foo_external " ) . write " # foo completions "
elsif ( external_bash_completion / " foo_external " ) . exist?
( external_bash_completion / " foo_external " ) . delete
2021-01-18 03:09:57 -05:00
end
end
def setup_completions_setting ( state , setting : " linkcompletions " )
HOMEBREW_REPOSITORY . cd do
system " git " , " config " , " --replace-all " , " homebrew. #{ setting } " , state . to_s
end
end
def read_completions_setting ( setting : " linkcompletions " )
HOMEBREW_REPOSITORY . cd do
Utils . popen_read ( " git " , " config " , " --get " , " homebrew. #{ setting } " ) . chomp . presence
end
end
def delete_completions_setting ( setting : " linkcompletions " )
HOMEBREW_REPOSITORY . cd do
system " git " , " config " , " --unset-all " , " homebrew. #{ setting } "
end
end
describe " .link! " do
it " sets homebrew.linkcompletions to true " do
setup_completions_setting false
expect { described_class . link! } . not_to raise_error
expect ( read_completions_setting ) . to eq " true "
end
it " sets homebrew.linkcompletions to true if unset " do
delete_completions_setting
expect { described_class . link! } . not_to raise_error
expect ( read_completions_setting ) . to eq " true "
end
it " keeps homebrew.linkcompletions set to true " do
setup_completions_setting true
expect { described_class . link! } . not_to raise_error
expect ( read_completions_setting ) . to eq " true "
end
end
describe " .unlink! " do
it " sets homebrew.linkcompletions to false " do
setup_completions_setting true
expect { described_class . unlink! } . not_to raise_error
expect ( read_completions_setting ) . to eq " false "
end
it " sets homebrew.linkcompletions to false if unset " do
delete_completions_setting
expect { described_class . unlink! } . not_to raise_error
expect ( read_completions_setting ) . to eq " false "
end
it " keeps homebrew.linkcompletions set to false " do
setup_completions_setting false
expect { described_class . unlink! } . not_to raise_error
expect ( read_completions_setting ) . to eq " false "
end
end
describe " .link_completions? " do
it " returns true if homebrew.linkcompletions is true " do
setup_completions_setting true
expect ( described_class . link_completions? ) . to be true
end
it " returns false if homebrew.linkcompletions is false " do
setup_completions_setting false
expect ( described_class . link_completions? ) . to be false
end
it " returns false if homebrew.linkcompletions is not set " do
expect ( described_class . link_completions? ) . to be false
end
end
describe " .completions_to_link? " do
it " returns false if only internal taps have completions " do
setup_completions external : false
expect ( described_class . completions_to_link? ) . to be false
end
it " returns true if external taps have completions " do
setup_completions external : true
expect ( described_class . completions_to_link? ) . to be true
end
end
describe " .show_completions_message_if_needed " do
it " doesn't show the message if there are no completions to link " do
setup_completions external : false
delete_completions_setting setting : :completionsmessageshown
expect { described_class . show_completions_message_if_needed } . not_to output . to_stdout
end
it " doesn't show the message if there are completions to link but the message has already been shown " do
setup_completions external : true
setup_completions_setting true , setting : :completionsmessageshown
expect { described_class . show_completions_message_if_needed } . not_to output . to_stdout
end
2021-01-12 16:27:25 -05:00
2021-01-18 03:09:57 -05:00
it " shows the message if there are completions to link and the message hasn't already been shown " do
setup_completions external : true
delete_completions_setting setting : :completionsmessageshown
message = / Homebrew completions for external commands are unlinked by default! /
expect { described_class . show_completions_message_if_needed }
. to output ( message ) . to_stdout
end
2021-01-12 16:27:25 -05:00
end
end
2021-01-18 03:09:57 -05:00
context " when generating completions " do
2024-07-14 08:49:39 -04:00
# TODO: re-enable this test if it can be made to take ~ 1 second or there's
# an actual regression.
# describe ".update_shell_completions!" do
# it "generates shell completions" do
# described_class.update_shell_completions!
# expect(completions_dir/"bash/brew").to be_a_file
# end
# end
2021-01-18 03:09:57 -05:00
2021-01-24 03:12:52 -05:00
describe " .format_description " do
2021-01-24 16:42:28 -05:00
it " escapes single quotes " do
2021-01-24 03:12:52 -05:00
expect ( described_class . format_description ( " Homebrew's " ) ) . to eq " Homebrew' \\ ''s "
end
2021-01-26 10:47:56 -05:00
it " escapes single quotes for fish " do
expect ( described_class . format_description ( " Homebrew's " , fish : true ) ) . to eq " Homebrew \\ 's "
end
2021-01-24 03:12:52 -05:00
it " removes angle brackets " do
expect ( described_class . format_description ( " <formula> " ) ) . to eq " formula "
end
it " replaces newlines with spaces " do
expect ( described_class . format_description ( " Homebrew \n command " ) ) . to eq " Homebrew command "
end
it " removes trailing period " do
expect ( described_class . format_description ( " Homebrew. " ) ) . to eq " Homebrew "
end
end
2021-01-18 03:09:57 -05:00
describe " .command_options " do
it " returns an array of options for a ruby command " do
2021-01-24 03:12:52 -05:00
expected_options = {
2021-01-24 16:42:28 -05:00
" --debug " = > " Display any debugging information. " ,
" --help " = > " Show this message. " ,
" --hide " = > " Act as if none of the specified <hidden> are installed. <hidden> should be " \
" a comma-separated list of formulae. " ,
" --quiet " = > " Make some output more quiet. " ,
" --verbose " = > " Make some output more verbose. " ,
2021-01-24 03:12:52 -05:00
}
2021-01-18 03:09:57 -05:00
expect ( described_class . command_options ( " missing " ) ) . to eq expected_options
end
it " returns an array of options for a shell command " do
2021-01-24 03:12:52 -05:00
expected_options = {
2022-05-19 11:04:20 -04:00
" --auto-update " = > " Run on auto-updates (e.g. before `brew install`). Skips some slower steps. " ,
" --debug " = > " Display a trace of all shell commands as they are executed. " ,
" --force " = > " Always do a slower, full update check (even if unnecessary). " ,
" --help " = > " Show this message. " ,
" --merge " = > " Use `git merge` to apply updates (rather than `git rebase`). " ,
2023-02-10 23:15:40 -05:00
" --quiet " = > " Make some output more quiet. " ,
2022-05-19 11:04:20 -04:00
" --verbose " = > " Print the directories checked and `git` operations performed. " ,
2021-01-24 03:12:52 -05:00
}
2021-01-18 03:09:57 -05:00
expect ( described_class . command_options ( " update " ) ) . to eq expected_options
end
it " handles --[no]- options correctly " do
options = described_class . command_options ( " audit " )
2023-03-29 20:49:29 +02:00
expect ( options . key? ( " --signing " ) ) . to be true
expect ( options . key? ( " --no-signing " ) ) . to be true
expect ( options [ " --signing " ] == options [ " --no-signing " ] ) . to be true
2021-01-18 03:09:57 -05:00
end
it " return an empty array if command is not found " do
2021-01-24 03:12:52 -05:00
expect ( described_class . command_options ( " foobar " ) ) . to eq ( { } )
2021-01-18 03:09:57 -05:00
end
it " return an empty array for a command with no options " do
2021-01-24 03:12:52 -05:00
expect ( described_class . command_options ( " help " ) ) . to eq ( { } )
2021-01-18 03:09:57 -05:00
end
2024-01-06 09:54:29 -08:00
it " overrides global options with local descriptions " do
2021-01-24 03:12:52 -05:00
options = described_class . command_options ( " upgrade " )
2023-09-08 14:46:15 -04:00
expect ( options [ " --verbose " ] ) . to eq " Print the verification and post-install steps. "
2021-01-18 03:09:57 -05:00
end
end
describe " .command_gets_completions? " do
it " returns true for a non-cask command with options " do
2022-03-01 00:02:36 +00:00
expect ( described_class . command_gets_completions? ( " install " ) ) . to be true
2021-01-18 03:09:57 -05:00
end
it " returns false for a non-cask command with no options " do
2022-03-01 00:02:36 +00:00
expect ( described_class . command_gets_completions? ( " help " ) ) . to be false
2021-01-18 03:09:57 -05:00
end
it " returns false for a cask command " do
2022-03-01 00:02:36 +00:00
expect ( described_class . command_gets_completions? ( " cask install " ) ) . to be false
2021-01-18 03:09:57 -05:00
end
end
describe " .generate_bash_subcommand_completion " do
it " returns nil if completions aren't needed " do
expect ( described_class . generate_bash_subcommand_completion ( " help " ) ) . to be_nil
end
it " returns appropriate completion for a ruby command " do
completion = described_class . generate_bash_subcommand_completion ( " missing " )
2021-01-24 03:12:52 -05:00
expect ( completion ) . to eq << ~ COMPLETION
_brew_missing ( ) {
local cur = " ${COMP_WORDS[COMP_CWORD]} "
2021-05-02 14:26:12 +05:30
case " ${cur} " in
2021-01-24 03:12:52 -05:00
- * )
__brewcomp "
- - debug
- - help
- - hide
- - quiet
- - verbose
"
return
; ;
2023-02-23 18:50:19 -07:00
* ) ; ;
2021-01-24 03:12:52 -05:00
esac
__brew_complete_formulae
}
COMPLETION
2021-01-18 03:09:57 -05:00
end
it " returns appropriate completion for a shell command " do
completion = described_class . generate_bash_subcommand_completion ( " update " )
2021-01-24 03:12:52 -05:00
expect ( completion ) . to eq << ~ COMPLETION
_brew_update ( ) {
local cur = " ${COMP_WORDS[COMP_CWORD]} "
2021-05-02 14:26:12 +05:30
case " ${cur} " in
2021-01-24 03:12:52 -05:00
- * )
__brewcomp "
2022-05-19 11:04:20 -04:00
- - auto - update
2021-01-24 03:12:52 -05:00
- - debug
- - force
- - help
- - merge
2022-05-04 10:38:24 -05:00
- - quiet
2021-01-24 03:12:52 -05:00
- - verbose
"
return
; ;
2023-02-23 18:50:19 -07:00
* ) ; ;
2021-01-24 03:12:52 -05:00
esac
}
COMPLETION
2021-01-18 03:09:57 -05:00
end
it " returns appropriate completion for a command with multiple named arg types " do
completion = described_class . generate_bash_subcommand_completion ( " upgrade " )
2024-01-24 12:23:18 -05:00
expect ( completion ) . to match ( / __brew_complete_installed_formulae \ n __brew_complete_installed_casks \ n}$ / )
2021-01-18 03:09:57 -05:00
end
end
describe " .generate_bash_completion_file " do
it " returns the correct completion file " do
file = described_class . generate_bash_completion_file ( %w[ install missing update ] )
expect ( file ) . to match ( / ^__brewcomp \ ( \ ) {$ / )
expect ( file ) . to match ( / ^_brew_install \ ( \ ) {$ / )
expect ( file ) . to match ( / ^_brew_missing \ ( \ ) {$ / )
expect ( file ) . to match ( / ^_brew_update \ ( \ ) {$ / )
expect ( file ) . to match ( / ^_brew \ ( \ ) {$ / )
expect ( file ) . to match ( / ^ {4}install \ ) _brew_install ;; / )
expect ( file ) . to match ( / ^ {4}missing \ ) _brew_missing ;; / )
expect ( file ) . to match ( / ^ {4}update \ ) _brew_update ;; / )
expect ( file ) . to match ( / ^complete -o bashdefault -o default -F _brew brew$ / )
end
2021-01-12 16:27:25 -05:00
end
2021-01-24 03:12:52 -05:00
describe " .generate_zsh_subcommand_completion " do
it " returns nil if completions aren't needed " do
expect ( described_class . generate_zsh_subcommand_completion ( " help " ) ) . to be_nil
end
it " returns appropriate completion for a ruby command " do
completion = described_class . generate_zsh_subcommand_completion ( " missing " )
expect ( completion ) . to eq << ~ COMPLETION
# brew missing
_brew_missing ( ) {
_arguments \ \
'--debug[Display any debugging information]' \ \
'--help[Show this message]' \ \
'--hide[Act as if none of the specified hidden are installed. hidden should be a comma-separated list of formulae]' \ \
'--quiet[Make some output more quiet]' \ \
'--verbose[Make some output more verbose]' \ \
2021-03-14 01:39:14 +05:30
- formula \ \
'*::formula:__brew_formulae'
2021-01-24 03:12:52 -05:00
}
COMPLETION
end
it " returns appropriate completion for a shell command " do
completion = described_class . generate_zsh_subcommand_completion ( " update " )
expect ( completion ) . to eq << ~ COMPLETION
# brew update
_brew_update ( ) {
_arguments \ \
2022-05-19 11:04:20 -04:00
'--auto-update[Run on auto-updates (e.g. before `brew install`). Skips some slower steps]' \ \
2021-01-24 03:12:52 -05:00
'--debug[Display a trace of all shell commands as they are executed]' \ \
'--force[Always do a slower, full update check (even if unnecessary)]' \ \
'--help[Show this message]' \ \
'--merge[Use `git merge` to apply updates (rather than `git rebase`)]' \ \
2022-05-04 10:38:24 -05:00
'--quiet[Make some output more quiet]' \ \
2021-01-24 03:12:52 -05:00
'--verbose[Print the directories checked and `git` operations performed]'
}
COMPLETION
end
it " returns appropriate completion for a command with multiple named arg types " do
2021-03-14 01:39:14 +05:30
completion = described_class . generate_zsh_subcommand_completion ( " livecheck " )
2021-01-24 03:12:52 -05:00
expect ( completion ) . to match (
2021-03-14 01:39:14 +05:30
/ '*::formula:__brew_formulae' / ,
)
expect ( completion ) . to match (
/ '*::cask:__brew_casks' \ n}$ / ,
2021-01-24 03:12:52 -05:00
)
end
end
describe " .generate_zsh_completion_file " do
it " returns the correct completion file " do
file = described_class . generate_zsh_completion_file ( %w[ install missing update ] )
expect ( file ) . to match ( / ^__brew_list_aliases \ ( \ ) {$ / )
expect ( file ) . to match ( / ^ up update$ / )
expect ( file ) . to match ( / ^__brew_internal_commands \ ( \ ) {$ / )
expect ( file ) . to match ( / ^ 'install:Install a formula or cask'$ / )
expect ( file ) . to match ( / ^ 'missing:Check the given formula kegs for missing dependencies'$ / )
expect ( file ) . to match ( / ^ 'update:Fetch the newest version of Homebrew and all formulae from GitHub .*'$ / )
expect ( file ) . to match ( / ^_brew_install \ ( \ ) {$ / )
expect ( file ) . to match ( / ^_brew_missing \ ( \ ) {$ / )
expect ( file ) . to match ( / ^_brew_update \ ( \ ) {$ / )
expect ( file ) . to match ( / ^_brew " \ $@"$ / )
end
end
2021-01-26 10:47:56 -05:00
describe " .generate_fish_subcommand_completion " do
it " returns nil if completions aren't needed " do
expect ( described_class . generate_fish_subcommand_completion ( " help " ) ) . to be_nil
end
it " returns appropriate completion for a ruby command " do
completion = described_class . generate_fish_subcommand_completion ( " missing " )
expect ( completion ) . to eq << ~ COMPLETION
__fish_brew_complete_cmd 'missing' 'Check the given formula kegs for missing dependencies'
__fish_brew_complete_arg 'missing' - l debug - d 'Display any debugging information'
__fish_brew_complete_arg 'missing' - l help - d 'Show this message'
__fish_brew_complete_arg 'missing' - l hide - d 'Act as if none of the specified hidden are installed. hidden should be a comma-separated list of formulae'
__fish_brew_complete_arg 'missing' - l quiet - d 'Make some output more quiet'
__fish_brew_complete_arg 'missing' - l verbose - d 'Make some output more verbose'
__fish_brew_complete_arg 'missing' - a '(__fish_brew_suggest_formulae_all)'
COMPLETION
end
it " returns appropriate completion for a shell command " do
completion = described_class . generate_fish_subcommand_completion ( " update " )
expect ( completion ) . to eq << ~ COMPLETION
__fish_brew_complete_cmd 'update' 'Fetch the newest version of Homebrew and all formulae from GitHub using `git`(1) and perform any necessary migrations'
2022-05-19 11:04:20 -04:00
__fish_brew_complete_arg 'update' - l auto - update - d 'Run on auto-updates (e.g. before `brew install`). Skips some slower steps'
2021-01-26 10:47:56 -05:00
__fish_brew_complete_arg 'update' - l debug - d 'Display a trace of all shell commands as they are executed'
__fish_brew_complete_arg 'update' - l force - d 'Always do a slower, full update check (even if unnecessary)'
__fish_brew_complete_arg 'update' - l help - d 'Show this message'
__fish_brew_complete_arg 'update' - l merge - d 'Use `git merge` to apply updates (rather than `git rebase`)'
2022-05-04 10:38:24 -05:00
__fish_brew_complete_arg 'update' - l quiet - d 'Make some output more quiet'
2021-01-26 10:47:56 -05:00
__fish_brew_complete_arg 'update' - l verbose - d 'Print the directories checked and `git` operations performed'
COMPLETION
end
it " returns appropriate completion for a command with multiple named arg types " do
completion = described_class . generate_fish_subcommand_completion ( " upgrade " )
2021-04-27 20:30:23 -04:00
expected_line_start = " __fish_brew_complete_arg 'upgrade; and not __fish_seen_argument "
2021-01-26 10:47:56 -05:00
expect ( completion ) . to match (
2024-01-24 12:23:18 -05:00
/ #{ expected_line_start } -l cask -l casks' -a ' \ (__fish_brew_suggest_formulae_installed \ )' / ,
2021-04-27 20:30:23 -04:00
)
expect ( completion ) . to match (
2024-01-24 12:23:18 -05:00
/ #{ expected_line_start } -l formula -l formulae' -a ' \ (__fish_brew_suggest_casks_installed \ )' / ,
2021-01-26 10:47:56 -05:00
)
end
end
describe " .generate_fish_completion_file " do
it " returns the correct completion file " do
file = described_class . generate_fish_completion_file ( %w[ install missing update ] )
expect ( file ) . to match ( / ^function __fish_brew_complete_cmd / )
expect ( file ) . to match ( / ^__fish_brew_complete_cmd 'install' 'Install a formula or cask'$ / )
expect ( file ) . to match ( / ^__fish_brew_complete_cmd 'missing' 'Check the given formula kegs for .*'$ / )
expect ( file ) . to match ( / ^__fish_brew_complete_cmd 'update' 'Fetch the newest version of Homebrew .*'$ / )
end
end
2021-01-12 16:27:25 -05:00
end
end