diff options
Diffstat (limited to 'Library/Homebrew/test/cask/cli')
18 files changed, 1525 insertions, 0 deletions
diff --git a/Library/Homebrew/test/cask/cli/audit_spec.rb b/Library/Homebrew/test/cask/cli/audit_spec.rb new file mode 100644 index 000000000..2736e60c1 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/audit_spec.rb @@ -0,0 +1,59 @@ +describe Hbc::CLI::Audit, :cask do + let(:auditor) { double } + let(:cask) { double } + + describe "selection of Casks to audit" do + it "audits all Casks if no tokens are given" do + allow(Hbc).to receive(:all).and_return([cask, cask]) + + expect(auditor).to receive(:audit).twice + + run_audit([], auditor) + end + + it "audits specified Casks if tokens are given" do + cask_token = "nice-app" + expect(Hbc).to receive(:load).with(cask_token).and_return(cask) + + expect(auditor).to receive(:audit).with(cask, audit_download: false, check_token_conflicts: false) + + run_audit([cask_token], auditor) + end + end + + describe "rules for downloading a Cask" do + it "does not download the Cask per default" do + allow(Hbc).to receive(:load).and_return(cask) + expect(auditor).to receive(:audit).with(cask, audit_download: false, check_token_conflicts: false) + + run_audit(["casktoken"], auditor) + end + + it "download a Cask if --download flag is set" do + allow(Hbc).to receive(:load).and_return(cask) + expect(auditor).to receive(:audit).with(cask, audit_download: true, check_token_conflicts: false) + + run_audit(["casktoken", "--download"], auditor) + end + end + + describe "rules for checking token conflicts" do + it "does not check for token conflicts per default" do + allow(Hbc).to receive(:load).and_return(cask) + expect(auditor).to receive(:audit).with(cask, audit_download: false, check_token_conflicts: false) + + run_audit(["casktoken"], auditor) + end + + it "checks for token conflicts if --token-conflicts flag is set" do + allow(Hbc).to receive(:load).and_return(cask) + expect(auditor).to receive(:audit).with(cask, audit_download: false, check_token_conflicts: true) + + run_audit(["casktoken", "--token-conflicts"], auditor) + end + end + + def run_audit(args, auditor) + Hbc::CLI::Audit.new(args, auditor).run + end +end diff --git a/Library/Homebrew/test/cask/cli/cat_spec.rb b/Library/Homebrew/test/cask/cli/cat_spec.rb new file mode 100644 index 000000000..daf6fb960 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/cat_spec.rb @@ -0,0 +1,57 @@ +describe Hbc::CLI::Cat, :cask do + describe "given a basic Cask" do + let(:expected_output) { + <<-EOS.undent + cask 'basic-cask' do + version '1.2.3' + sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' + + url 'http://example.com/TestCask.dmg' + homepage 'http://example.com/' + + app 'TestCask.app' + end + EOS + } + + it "displays the Cask file content about the specified Cask" do + expect { + Hbc::CLI::Cat.run("basic-cask") + }.to output(expected_output).to_stdout + end + + it "throws away additional Cask arguments and uses the first" do + expect { + Hbc::CLI::Cat.run("basic-cask", "local-caffeine") + }.to output(expected_output).to_stdout + end + + it "throws away stray options" do + expect { + Hbc::CLI::Cat.run("--notavalidoption", "basic-cask") + }.to output(expected_output).to_stdout + end + end + + it "raises an exception when the Cask does not exist" do + expect { + Hbc::CLI::Cat.run("notacask") + }.to raise_error(Hbc::CaskUnavailableError) + end + + describe "when no Cask is specified" do + it "raises an exception" do + expect { + Hbc::CLI::Cat.run + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end + + describe "when no Cask is specified, but an invalid option" do + it "raises an exception" do + expect { + Hbc::CLI::Cat.run("--notavalidoption") + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end +end diff --git a/Library/Homebrew/test/cask/cli/cleanup_spec.rb b/Library/Homebrew/test/cask/cli/cleanup_spec.rb new file mode 100644 index 000000000..f8578e80d --- /dev/null +++ b/Library/Homebrew/test/cask/cli/cleanup_spec.rb @@ -0,0 +1,93 @@ +describe Hbc::CLI::Cleanup, :cask do + let(:cache_location) { Pathname.new(Dir.mktmpdir).realpath } + let(:cleanup_outdated) { false } + + subject { described_class.new(cache_location, cleanup_outdated) } + + after do + cache_location.rmtree + end + + describe "cleanup" do + it "removes cached downloads of given casks" do + cleaned_up_cached_download = "caffeine" + + cached_downloads = [ + cache_location.join("#{cleaned_up_cached_download}--latest.zip"), + cache_location.join("transmission--2.61.dmg"), + ] + + cached_downloads.each(&FileUtils.method(:touch)) + + cleanup_size = Hbc::Utils.size_in_bytes(cached_downloads[0]) + + expect { + subject.cleanup(cleaned_up_cached_download) + }.to output(<<-EOS.undent).to_stdout + ==> Removing cached downloads for #{cleaned_up_cached_download} + #{cached_downloads[0]} + ==> This operation has freed approximately #{disk_usage_readable(cleanup_size)} of disk space. + EOS + + expect(cached_downloads[0].exist?).to eq(false) + expect(cached_downloads[1].exist?).to eq(true) + end + end + + describe "cleanup!" do + it "removes cached downloads" do + cached_download = cache_location.join("SomeDownload.dmg") + FileUtils.touch(cached_download) + cleanup_size = subject.disk_cleanup_size + + expect { + subject.cleanup! + }.to output(<<-EOS.undent).to_stdout + ==> Removing cached downloads + #{cached_download} + ==> This operation has freed approximately #{disk_usage_readable(cleanup_size)} of disk space. + EOS + + expect(cached_download.exist?).to eq(false) + end + + # TODO: uncomment when unflaky. + # it "does not removed locked files" do + # cached_download = cache_location.join("SomeDownload.dmg") + # FileUtils.touch(cached_download) + # cleanup_size = subject.disk_cleanup_size + # + # File.new(cached_download).flock(File::LOCK_EX) + # + # expect(Hbc::Utils).to be_file_locked(cached_download) + # + # expect { + # subject.cleanup! + # }.to output(<<-EOS.undent).to_stdout + # ==> Removing cached downloads + # skipping: #{cached_download} is locked + # ==> This operation has freed approximately #{disk_usage_readable(cleanup_size)} of disk space. + # EOS + # + # expect(cached_download.exist?).to eq(true) + # end + + context "when cleanup_outdated is specified" do + let(:cleanup_outdated) { true } + + it "does not remove cache files newer than 10 days old" do + cached_download = cache_location.join("SomeNewDownload.dmg") + FileUtils.touch(cached_download) + + expect { + subject.cleanup! + }.to output(<<-EOS.undent).to_stdout + ==> Removing cached downloads older than 10 days old + Nothing to do + EOS + + expect(cached_download.exist?).to eq(true) + end + end + end +end diff --git a/Library/Homebrew/test/cask/cli/create_spec.rb b/Library/Homebrew/test/cask/cli/create_spec.rb new file mode 100644 index 000000000..21eaeb656 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/create_spec.rb @@ -0,0 +1,98 @@ +# monkeypatch for testing +module Hbc + class CLI + class Create + def self.exec_editor(*command) + editor_commands << command + end + + def self.reset! + @editor_commands = [] + end + + def self.editor_commands + @editor_commands ||= [] + end + end + end +end + +describe Hbc::CLI::Create, :cask do + before(:each) do + Hbc::CLI::Create.reset! + end + + after(:each) do + %w[new-cask additional-cask another-cask yet-another-cask local-caff].each do |cask| + path = Hbc.path(cask) + path.delete if path.exist? + end + end + + it "opens the editor for the specified Cask" do + Hbc::CLI::Create.run("new-cask") + expect(Hbc::CLI::Create.editor_commands).to eq [ + [Hbc.path("new-cask")], + ] + end + + it "drops a template down for the specified Cask" do + Hbc::CLI::Create.run("new-cask") + template = File.read(Hbc.path("new-cask")) + expect(template).to eq <<-EOS.undent + cask 'new-cask' do + version '' + sha256 '' + + url 'https://' + name '' + homepage '' + + app '' + end + EOS + end + + it "throws away additional Cask arguments and uses the first" do + Hbc::CLI::Create.run("additional-cask", "another-cask") + expect(Hbc::CLI::Create.editor_commands).to eq [ + [Hbc.path("additional-cask")], + ] + end + + it "throws away stray options" do + Hbc::CLI::Create.run("--notavalidoption", "yet-another-cask") + expect(Hbc::CLI::Create.editor_commands).to eq [ + [Hbc.path("yet-another-cask")], + ] + end + + it "raises an exception when the Cask already exists" do + expect { + Hbc::CLI::Create.run("basic-cask") + }.to raise_error(Hbc::CaskAlreadyCreatedError) + end + + it "allows creating Casks that are substrings of existing Casks" do + Hbc::CLI::Create.run("local-caff") + expect(Hbc::CLI::Create.editor_commands).to eq [ + [Hbc.path("local-caff")], + ] + end + + describe "when no Cask is specified" do + it "raises an exception" do + expect { + Hbc::CLI::Create.run + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end + + describe "when no Cask is specified, but an invalid option" do + it "raises an exception" do + expect { + Hbc::CLI::Create.run("--notavalidoption") + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end +end diff --git a/Library/Homebrew/test/cask/cli/doctor_spec.rb b/Library/Homebrew/test/cask/cli/doctor_spec.rb new file mode 100644 index 000000000..ff1cf5706 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/doctor_spec.rb @@ -0,0 +1,15 @@ +require "hbc/version" + +describe Hbc::CLI::Doctor do + it "displays some nice info about the environment" do + expect { + Hbc::CLI::Doctor.run + }.to output(/\A==> Homebrew-Cask Version/).to_stdout + end + + it "raises an exception when arguments are given" do + expect { + Hbc::CLI::Doctor.run("argument") + }.to raise_error(ArgumentError) + end +end diff --git a/Library/Homebrew/test/cask/cli/edit_spec.rb b/Library/Homebrew/test/cask/cli/edit_spec.rb new file mode 100644 index 000000000..61970290b --- /dev/null +++ b/Library/Homebrew/test/cask/cli/edit_spec.rb @@ -0,0 +1,60 @@ +# monkeypatch for testing +module Hbc + class CLI + class Edit + def self.exec_editor(*command) + editor_commands << command + end + + def self.reset! + @editor_commands = [] + end + + def self.editor_commands + @editor_commands ||= [] + end + end + end +end + +describe Hbc::CLI::Edit, :cask do + before(:each) do + Hbc::CLI::Edit.reset! + end + + it "opens the editor for the specified Cask" do + Hbc::CLI::Edit.run("local-caffeine") + expect(Hbc::CLI::Edit.editor_commands).to eq [ + [Hbc.path("local-caffeine")], + ] + end + + it "throws away additional arguments and uses the first" do + Hbc::CLI::Edit.run("local-caffeine", "local-transmission") + expect(Hbc::CLI::Edit.editor_commands).to eq [ + [Hbc.path("local-caffeine")], + ] + end + + it "raises an exception when the Cask doesnt exist" do + expect { + Hbc::CLI::Edit.run("notacask") + }.to raise_error(Hbc::CaskUnavailableError) + end + + describe "when no Cask is specified" do + it "raises an exception" do + expect { + Hbc::CLI::Edit.run + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end + + describe "when no Cask is specified, but an invalid option" do + it "raises an exception" do + expect { + Hbc::CLI::Edit.run("--notavalidoption") + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end +end diff --git a/Library/Homebrew/test/cask/cli/fetch_spec.rb b/Library/Homebrew/test/cask/cli/fetch_spec.rb new file mode 100644 index 000000000..1571c2a70 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/fetch_spec.rb @@ -0,0 +1,75 @@ +describe Hbc::CLI::Fetch, :cask do + let(:local_transmission) { + Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") + } + + let(:local_caffeine) { + Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + } + + it "allows download the installer of a Cask" do + shutup do + Hbc::CLI::Fetch.run("local-transmission", "local-caffeine") + end + expect(Hbc::CurlDownloadStrategy.new(local_transmission).cached_location).to exist + expect(Hbc::CurlDownloadStrategy.new(local_caffeine).cached_location).to exist + end + + it "prevents double fetch (without nuking existing installation)" do + download_stategy = Hbc::CurlDownloadStrategy.new(local_transmission) + + shutup do + Hbc::Download.new(local_transmission).perform + end + old_ctime = File.stat(download_stategy.cached_location).ctime + + shutup do + Hbc::CLI::Fetch.run("local-transmission") + end + new_ctime = File.stat(download_stategy.cached_location).ctime + + expect(old_ctime.to_i).to eq(new_ctime.to_i) + end + + it "allows double fetch with --force" do + shutup do + Hbc::Download.new(local_transmission).perform + end + + download_stategy = Hbc::CurlDownloadStrategy.new(local_transmission) + old_ctime = File.stat(download_stategy.cached_location).ctime + sleep(1) + + shutup do + Hbc::CLI::Fetch.run("local-transmission", "--force") + end + download_stategy = Hbc::CurlDownloadStrategy.new(local_transmission) + new_ctime = File.stat(download_stategy.cached_location).ctime + + expect(new_ctime.to_i).to be > old_ctime.to_i + end + + it "properly handles Casks that are not present" do + expect { + shutup do + Hbc::CLI::Fetch.run("notacask") + end + }.to raise_error(Hbc::CaskUnavailableError) + end + + describe "when no Cask is specified" do + it "raises an exception" do + expect { + Hbc::CLI::Fetch.run + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end + + describe "when no Cask is specified, but an invalid option" do + it "raises an exception" do + expect { + Hbc::CLI::Fetch.run("--notavalidoption") + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end +end diff --git a/Library/Homebrew/test/cask/cli/home_spec.rb b/Library/Homebrew/test/cask/cli/home_spec.rb new file mode 100644 index 000000000..a5359f24f --- /dev/null +++ b/Library/Homebrew/test/cask/cli/home_spec.rb @@ -0,0 +1,46 @@ +# monkeypatch for testing +module Hbc + class CLI + class Home + def self.system(*command) + system_commands << command + end + + def self.reset! + @system_commands = [] + end + + def self.system_commands + @system_commands ||= [] + end + end + end +end + +describe Hbc::CLI::Home, :cask do + before do + Hbc::CLI::Home.reset! + end + + it "opens the homepage for the specified Cask" do + Hbc::CLI::Home.run("local-caffeine") + expect(Hbc::CLI::Home.system_commands).to eq [ + ["/usr/bin/open", "--", "http://example.com/local-caffeine"], + ] + end + + it "works for multiple Casks" do + Hbc::CLI::Home.run("local-caffeine", "local-transmission") + expect(Hbc::CLI::Home.system_commands).to eq [ + ["/usr/bin/open", "--", "http://example.com/local-caffeine"], + ["/usr/bin/open", "--", "http://example.com/local-transmission"], + ] + end + + it "opens the project page when no Cask is specified" do + Hbc::CLI::Home.run + expect(Hbc::CLI::Home.system_commands).to eq [ + ["/usr/bin/open", "--", "http://caskroom.io/"], + ] + end +end diff --git a/Library/Homebrew/test/cask/cli/info_spec.rb b/Library/Homebrew/test/cask/cli/info_spec.rb new file mode 100644 index 000000000..2f70a0b96 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/info_spec.rb @@ -0,0 +1,108 @@ +describe Hbc::CLI::Info, :cask do + it "displays some nice info about the specified Cask" do + expect { + Hbc::CLI::Info.run("local-caffeine") + }.to output(<<-EOS.undent).to_stdout + local-caffeine: 1.2.3 + http://example.com/local-caffeine + Not installed + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/local-caffeine.rb + ==> Name + None + ==> Artifacts + Caffeine.app (app) + EOS + end + + describe "given multiple Casks" do + let(:expected_output) { + <<-EOS.undent + local-caffeine: 1.2.3 + http://example.com/local-caffeine + Not installed + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/local-caffeine.rb + ==> Name + None + ==> Artifacts + Caffeine.app (app) + local-transmission: 2.61 + http://example.com/local-transmission + Not installed + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/local-transmission.rb + ==> Name + None + ==> Artifacts + Transmission.app (app) + EOS + } + + it "displays the info" do + expect { + Hbc::CLI::Info.run("local-caffeine", "local-transmission") + }.to output(expected_output).to_stdout + end + + it "throws away stray options" do + expect { + Hbc::CLI::Info.run("--notavalidoption", "local-caffeine", "local-transmission") + }.to output(expected_output).to_stdout + end + end + + it "should print caveats if the Cask provided one" do + expect { + Hbc::CLI::Info.run("with-caveats") + }.to output(<<-EOS.undent).to_stdout + with-caveats: 1.2.3 + http://example.com/local-caffeine + Not installed + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/with-caveats.rb + ==> Name + None + ==> Artifacts + Caffeine.app (app) + ==> Caveats + Here are some things you might want to know. + + Cask token: with-caveats + + Custom text via puts followed by DSL-generated text: + To use with-caveats, you may need to add the /custom/path/bin directory + to your PATH environment variable, eg (for bash shell): + + export PATH=/custom/path/bin:"$PATH" + + EOS + end + + it 'should not print "Caveats" section divider if the caveats block has no output' do + expect { + Hbc::CLI::Info.run("with-conditional-caveats") + }.to output(<<-EOS.undent).to_stdout + with-conditional-caveats: 1.2.3 + http://example.com/local-caffeine + Not installed + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/with-conditional-caveats.rb + ==> Name + None + ==> Artifacts + Caffeine.app (app) + EOS + end + + describe "when no Cask is specified" do + it "raises an exception" do + expect { + Hbc::CLI::Info.run + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end + + describe "when no Cask is specified, but an invalid option" do + it "raises an exception" do + expect { + Hbc::CLI::Info.run("--notavalidoption") + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end +end diff --git a/Library/Homebrew/test/cask/cli/install_spec.rb b/Library/Homebrew/test/cask/cli/install_spec.rb new file mode 100644 index 000000000..5a40017e8 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/install_spec.rb @@ -0,0 +1,107 @@ +describe Hbc::CLI::Install, :cask do + it "allows staging and activation of multiple Casks at once" do + shutup do + Hbc::CLI::Install.run("local-transmission", "local-caffeine") + end + + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed + expect(Hbc.appdir.join("Transmission.app")).to be_a_directory + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")).to be_installed + expect(Hbc.appdir.join("Caffeine.app")).to be_a_directory + end + + it "skips double install (without nuking existing installation)" do + shutup do + Hbc::CLI::Install.run("local-transmission") + end + shutup do + Hbc::CLI::Install.run("local-transmission") + end + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed + end + + it "prints a warning message on double install" do + shutup do + Hbc::CLI::Install.run("local-transmission") + end + + expect { + Hbc::CLI::Install.run("local-transmission", "") + }.to output(/Warning: A Cask for local-transmission is already installed./).to_stderr + end + + it "allows double install with --force" do + shutup do + Hbc::CLI::Install.run("local-transmission") + end + + expect { + expect { + Hbc::CLI::Install.run("local-transmission", "--force") + }.to output(/It seems there is already an App at.*overwriting\./).to_stderr + }.to output(/local-transmission was successfully installed!/).to_stdout + end + + it "skips dependencies with --skip-cask-deps" do + shutup do + Hbc::CLI::Install.run("with-depends-on-cask-multiple", "--skip-cask-deps") + end + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-cask-multiple.rb")).to be_installed + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")).not_to be_installed + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).not_to be_installed + end + + it "properly handles Casks that are not present" do + expect { + shutup do + Hbc::CLI::Install.run("notacask") + end + }.to raise_error(Hbc::CaskError) + end + + it "returns a suggestion for a misspelled Cask" do + expect { + begin + Hbc::CLI::Install.run("localcaffeine") + rescue Hbc::CaskError + nil + end + }.to output(/No available Cask for localcaffeine\. Did you mean:\nlocal-caffeine/).to_stderr + end + + it "returns multiple suggestions for a Cask fragment" do + expect { + begin + Hbc::CLI::Install.run("local-caf") + rescue Hbc::CaskError + nil + end + }.to output(/No available Cask for local-caf\. Did you mean one of:\nlocal-caffeine/).to_stderr + end + + describe "when no Cask is specified" do + with_options = lambda do |options| + it "raises an exception" do + expect { + Hbc::CLI::Install.run(*options) + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end + + describe "without options" do + with_options.call([]) + end + + describe "with --force" do + with_options.call(["--force"]) + end + + describe "with --skip-cask-deps" do + with_options.call(["--skip-cask-deps"]) + end + + describe "with an invalid option" do + with_options.call(["--notavalidoption"]) + end + end +end diff --git a/Library/Homebrew/test/cask/cli/list_spec.rb b/Library/Homebrew/test/cask/cli/list_spec.rb new file mode 100644 index 000000000..e367e9588 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/list_spec.rb @@ -0,0 +1,82 @@ +describe Hbc::CLI::List, :cask do + it "lists the installed Casks in a pretty fashion" do + casks = %w[local-caffeine local-transmission].map { |c| Hbc.load(c) } + + casks.each do |c| + InstallHelper.install_with_caskfile(c) + end + + expect { + Hbc::CLI::List.run + }.to output(<<-EOS.undent).to_stdout + local-caffeine + local-transmission + EOS + end + + describe "lists versions" do + let(:casks) { ["local-caffeine", "local-transmission"] } + let(:expected_output) { + <<-EOS.undent + local-caffeine 1.2.3 + local-transmission 2.61 + EOS + } + + before(:each) do + casks.map(&Hbc.method(:load)).each(&InstallHelper.method(:install_with_caskfile)) + end + + it "of all installed Casks" do + expect { + Hbc::CLI::List.run("--versions") + }.to output(expected_output).to_stdout + end + + it "of given Casks" do + expect { + Hbc::CLI::List.run("--versions", "local-caffeine", "local-transmission") + }.to output(expected_output).to_stdout + end + end + + describe "when Casks have been renamed" do + let(:caskroom_path) { Hbc.caskroom.join("ive-been-renamed") } + let(:staged_path) { caskroom_path.join("latest") } + + before do + staged_path.mkpath + end + + it "lists installed Casks without backing ruby files (due to renames or otherwise)" do + expect { + Hbc::CLI::List.run + }.to output(<<-EOS.undent).to_stdout + ive-been-renamed (!) + EOS + end + end + + describe "given a set of installed Casks" do + let(:caffeine) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") } + let(:transmission) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") } + let(:casks) { [caffeine, transmission] } + + it "lists the installed files for those Casks" do + casks.each(&InstallHelper.method(:install_without_artifacts_with_caskfile)) + + shutup do + Hbc::Artifact::App.new(transmission).install_phase + end + + expect { + Hbc::CLI::List.run("local-transmission", "local-caffeine") + }.to output(<<-EOS.undent).to_stdout + ==> Apps + #{Hbc.appdir.join("Transmission.app")} (#{Hbc.appdir.join("Transmission.app").abv}) + ==> Apps + Missing App: #{Hbc.appdir.join("Caffeine.app")} + EOS + end + end +end diff --git a/Library/Homebrew/test/cask/cli/options_spec.rb b/Library/Homebrew/test/cask/cli/options_spec.rb new file mode 100644 index 000000000..86933e27e --- /dev/null +++ b/Library/Homebrew/test/cask/cli/options_spec.rb @@ -0,0 +1,138 @@ +describe Hbc::CLI, :cask do + it "supports setting the appdir" do + Hbc::CLI.process_options %w[help --appdir=/some/path/foo] + + expect(Hbc.appdir).to eq(Pathname.new("/some/path/foo")) + end + + it "supports setting the appdir from ENV" do + ENV["HOMEBREW_CASK_OPTS"] = "--appdir=/some/path/bar" + + Hbc::CLI.process_options %w[help] + + expect(Hbc.appdir).to eq(Pathname.new("/some/path/bar")) + end + + it "supports setting the prefpanedir" do + Hbc::CLI.process_options %w[help --prefpanedir=/some/path/foo] + + expect(Hbc.prefpanedir).to eq(Pathname.new("/some/path/foo")) + end + + it "supports setting the prefpanedir from ENV" do + ENV["HOMEBREW_CASK_OPTS"] = "--prefpanedir=/some/path/bar" + + Hbc::CLI.process_options %w[help] + + expect(Hbc.prefpanedir).to eq(Pathname.new("/some/path/bar")) + end + + it "supports setting the qlplugindir" do + Hbc::CLI.process_options %w[help --qlplugindir=/some/path/foo] + + expect(Hbc.qlplugindir).to eq(Pathname.new("/some/path/foo")) + end + + it "supports setting the qlplugindir from ENV" do + ENV["HOMEBREW_CASK_OPTS"] = "--qlplugindir=/some/path/bar" + + Hbc::CLI.process_options %w[help] + + expect(Hbc.qlplugindir).to eq(Pathname.new("/some/path/bar")) + end + + it "supports setting the colorpickerdir" do + Hbc::CLI.process_options %w[help --colorpickerdir=/some/path/foo] + + expect(Hbc.colorpickerdir).to eq(Pathname.new("/some/path/foo")) + end + + it "supports setting the colorpickerdir from ENV" do + ENV["HOMEBREW_CASK_OPTS"] = "--colorpickerdir=/some/path/bar" + + Hbc::CLI.process_options %w[help] + + expect(Hbc.colorpickerdir).to eq(Pathname.new("/some/path/bar")) + end + + it "supports setting the dictionarydir" do + Hbc::CLI.process_options %w[help --dictionarydir=/some/path/foo] + + expect(Hbc.dictionarydir).to eq(Pathname.new("/some/path/foo")) + end + + it "supports setting the dictionarydir from ENV" do + ENV["HOMEBREW_CASK_OPTS"] = "--dictionarydir=/some/path/bar" + + Hbc::CLI.process_options %w[help] + + expect(Hbc.dictionarydir).to eq(Pathname.new("/some/path/bar")) + end + + it "supports setting the fontdir" do + Hbc::CLI.process_options %w[help --fontdir=/some/path/foo] + + expect(Hbc.fontdir).to eq(Pathname.new("/some/path/foo")) + end + + it "supports setting the fontdir from ENV" do + ENV["HOMEBREW_CASK_OPTS"] = "--fontdir=/some/path/bar" + + Hbc::CLI.process_options %w[help] + + expect(Hbc.fontdir).to eq(Pathname.new("/some/path/bar")) + end + + it "supports setting the servicedir" do + Hbc::CLI.process_options %w[help --servicedir=/some/path/foo] + + expect(Hbc.servicedir).to eq(Pathname.new("/some/path/foo")) + end + + it "supports setting the servicedir from ENV" do + ENV["HOMEBREW_CASK_OPTS"] = "--servicedir=/some/path/bar" + + Hbc::CLI.process_options %w[help] + + expect(Hbc.servicedir).to eq(Pathname.new("/some/path/bar")) + end + + it "allows additional options to be passed through" do + rest = Hbc::CLI.process_options %w[edit foo --create --appdir=/some/path/qux] + + expect(Hbc.appdir).to eq(Pathname.new("/some/path/qux")) + expect(rest).to eq(%w[edit foo --create]) + end + + describe "when a mandatory argument is missing" do + it "shows a user-friendly error message" do + expect { + Hbc::CLI.process_options %w[install -f] + }.to raise_error(Hbc::CaskError) + end + end + + describe "given an ambiguous option" do + it "shows a user-friendly error message" do + expect { + Hbc::CLI.process_options %w[edit -c] + }.to raise_error(Hbc::CaskError) + end + end + + describe "--debug" do + it "sets the Cask debug method to true" do + Hbc::CLI.process_options %w[help --debug] + expect(Hbc.debug).to be true + Hbc.debug = false + end + end + + describe "--help" do + it "sets the Cask help method to true" do + Hbc::CLI.process_options %w[foo --help] + expect(Hbc.help).to be true + Hbc.help = false + end + end +end diff --git a/Library/Homebrew/test/cask/cli/reinstall_spec.rb b/Library/Homebrew/test/cask/cli/reinstall_spec.rb new file mode 100644 index 000000000..e573a3470 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/reinstall_spec.rb @@ -0,0 +1,22 @@ +describe Hbc::CLI::Reinstall, :cask do + it "allows reinstalling a Cask" do + shutup do + Hbc::CLI::Install.run("local-transmission") + end + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed + + shutup do + Hbc::CLI::Reinstall.run("local-transmission") + end + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed + end + + it "allows reinstalling a non installed Cask" do + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).not_to be_installed + + shutup do + Hbc::CLI::Reinstall.run("local-transmission") + end + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed + end +end diff --git a/Library/Homebrew/test/cask/cli/search_spec.rb b/Library/Homebrew/test/cask/cli/search_spec.rb new file mode 100644 index 000000000..0bcff809a --- /dev/null +++ b/Library/Homebrew/test/cask/cli/search_spec.rb @@ -0,0 +1,59 @@ +describe Hbc::CLI::Search, :cask do + it "lists the available Casks that match the search term" do + expect { + Hbc::CLI::Search.run("local") + }.to output(<<-EOS.undent).to_stdout + ==> Partial matches + local-caffeine + local-transmission + EOS + end + + it "shows that there are no Casks matching a search term that did not result in anything" do + expect { + Hbc::CLI::Search.run("foo-bar-baz") + }.to output("No Cask found for \"foo-bar-baz\".\n").to_stdout + end + + it "lists all available Casks with no search term" do + expect { + Hbc::CLI::Search.run + }.to output(/local-caffeine/).to_stdout + end + + it "ignores hyphens in search terms" do + expect { + Hbc::CLI::Search.run("lo-cal-caffeine") + }.to output(/local-caffeine/).to_stdout + end + + it "ignores hyphens in Cask tokens" do + expect { + Hbc::CLI::Search.run("localcaffeine") + }.to output(/local-caffeine/).to_stdout + end + + it "accepts multiple arguments" do + expect { + Hbc::CLI::Search.run("local caffeine") + }.to output(/local-caffeine/).to_stdout + end + + it "accepts a regexp argument" do + expect { + Hbc::CLI::Search.run("/^local-c[a-z]ffeine$/") + }.to output("==> Regexp matches\nlocal-caffeine\n").to_stdout + end + + it "Returns both exact and partial matches" do + expect { + Hbc::CLI::Search.run("test-opera") + }.to output(/^==> Exact match\ntest-opera\n==> Partial matches\ntest-opera-mail/).to_stdout + end + + it "does not search the Tap name" do + expect { + Hbc::CLI::Search.run("caskroom") + }.to output(/^No Cask found for "caskroom"\.\n/).to_stdout + end +end diff --git a/Library/Homebrew/test/cask/cli/style_spec.rb b/Library/Homebrew/test/cask/cli/style_spec.rb new file mode 100644 index 000000000..106bfbb44 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/style_spec.rb @@ -0,0 +1,235 @@ +require "English" +require "open3" +require "rubygems" + +describe Hbc::CLI::Style do + let(:args) { [] } + let(:cli) { described_class.new(args) } + + around do |example| + shutup { example.run } + end + + describe ".run" do + subject { described_class.run(args) } + + before do + allow(described_class).to receive(:new).and_return(cli) + allow(cli).to receive(:run).and_return(retval) + end + + context "when rubocop succeeds" do + let(:retval) { true } + + it "exits successfully" do + subject + end + end + + context "when rubocop fails" do + let(:retval) { false } + + it "raises an exception" do + expect { subject }.to raise_error(Hbc::CaskError) + end + end + end + + describe "#run" do + subject { cli.run } + + before do + allow(cli).to receive_messages(install_rubocop: nil, + system: nil, + rubocop_args: nil, + cask_paths: nil) + allow($CHILD_STATUS).to receive(:success?).and_return(success) + end + + context "when rubocop succeeds" do + let(:success) { true } + it { is_expected.to be_truthy } + end + + context "when rubocop fails" do + let(:success) { false } + it { is_expected.to be_falsey } + end + end + + describe "#install_rubocop" do + subject { cli.install_rubocop } + + context "when installation succeeds" do + before do + allow(Homebrew).to receive(:install_gem_setup_path!) + end + + it "exits successfully" do + expect { subject }.not_to raise_error + end + end + + context "when installation fails" do + before do + allow(Homebrew).to receive(:install_gem_setup_path!).and_raise(SystemExit) + end + + it "raises an error" do + expect { subject }.to raise_error(Hbc::CaskError) + end + end + + context "version" do + it "matches `HOMEBREW_RUBOCOP_VERSION`" do + stdout, status = Open3.capture2("gem", "dependency", "rubocop-cask", "--version", HOMEBREW_RUBOCOP_CASK_VERSION, "--pipe", "--remote") + + expect(status).to be_a_success + + requirement = Gem::Requirement.new(stdout.scan(/rubocop --version '(.*)'/).flatten.first) + version = Gem::Version.new(HOMEBREW_RUBOCOP_VERSION) + + expect(requirement).not_to be_none + expect(requirement).to be_satisfied_by(version) + end + end + end + + describe "#cask_paths" do + subject { cli.cask_paths } + + before do + allow(cli).to receive(:cask_tokens).and_return(tokens) + end + + context "when no cask tokens are given" do + let(:tokens) { [] } + + before do + allow(Hbc).to receive(:all_tapped_cask_dirs).and_return(%w[Casks MoreCasks]) + end + + it { is_expected.to eq(%w[Casks MoreCasks]) } + end + + context "when at least one cask token is a path that exists" do + let(:tokens) { ["adium", "Casks/dropbox.rb"] } + before do + allow(File).to receive(:exist?).and_return(false, true) + end + + it "treats all tokens as paths" do + expect(subject).to eq(tokens) + end + end + + context "when no cask tokens are paths that exist" do + let(:tokens) { %w[adium dropbox] } + before do + allow(File).to receive(:exist?).and_return(false) + end + + it "tries to find paths for all tokens" do + expect(Hbc).to receive(:path).twice + subject + end + end + end + + describe "#cask_tokens" do + subject { cli.cask_tokens } + + context "when no args are given" do + let(:args) { [] } + it { is_expected.to be_empty } + end + + context "when only flags are given" do + let(:args) { ["--fix"] } + it { is_expected.to be_empty } + end + + context "when only empty args are given" do + let(:args) { ["", ""] } + it { is_expected.to be_empty } + end + + context "when a cask token is given" do + let(:args) { ["adium"] } + it { is_expected.to eq(["adium"]) } + end + + context "when multiple cask tokens are given" do + let(:args) { %w[adium dropbox] } + it { is_expected.to eq(%w[adium dropbox]) } + end + + context "when cask tokens are given with flags" do + let(:args) { ["adium", "dropbox", "--fix"] } + it { is_expected.to eq(%w[adium dropbox]) } + end + end + + describe "#rubocop_args" do + subject { cli.rubocop_args } + + before do + allow(cli).to receive(:fix?).and_return(fix) + end + + context "when fix? is true" do + let(:fix) { true } + it { is_expected.to include("--auto-correct") } + end + + context "when fix? is false" do + let(:fix) { false } + it { is_expected.not_to include("--auto-correct") } + end + end + + describe "#default_args" do + subject { cli.default_args } + + it { is_expected.to include("--require", "rubocop-cask", "--format", "simple", "--force-exclusion") } + end + + describe "#autocorrect_args" do + subject { cli.autocorrect_args } + let(:default_args) { ["--format", "simple"] } + + it "should add --auto-correct to default args" do + allow(cli).to receive(:default_args).and_return(default_args) + expect(subject).to include("--auto-correct", *default_args) + end + end + + describe "#fix?" do + subject { cli.fix? } + + context "when --fix is passed as an argument" do + let(:args) { ["adium", "--fix"] } + it { is_expected.to be_truthy } + end + + context "when --correct is passed as an argument" do + let(:args) { ["adium", "--correct"] } + it { is_expected.to be_truthy } + end + + context "when --auto-correct is passed as an argument" do + let(:args) { ["adium", "--auto-correct"] } + it { is_expected.to be_truthy } + end + + context "when --auto-correct is misspelled as --autocorrect" do + let(:args) { ["adium", "--autocorrect"] } + it { is_expected.to be_truthy } + end + + context "when no flag equivalent to --fix is passed as an argument" do + let(:args) { ["adium"] } + it { is_expected.to be_falsey } + end + end +end diff --git a/Library/Homebrew/test/cask/cli/uninstall_spec.rb b/Library/Homebrew/test/cask/cli/uninstall_spec.rb new file mode 100644 index 000000000..cbfb3e237 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/uninstall_spec.rb @@ -0,0 +1,189 @@ +describe Hbc::CLI::Uninstall, :cask do + it "shows an error when a bad Cask is provided" do + expect { + Hbc::CLI::Uninstall.run("notacask") + }.to raise_error(Hbc::CaskUnavailableError) + end + + it "shows an error when a Cask is provided that's not installed" do + expect { + Hbc::CLI::Uninstall.run("local-caffeine") + }.to raise_error(Hbc::CaskNotInstalledError) + end + + it "tries anyway on a non-present Cask when --force is given" do + expect { + Hbc::CLI::Uninstall.run("local-caffeine", "--force") + }.not_to raise_error + end + + it "can uninstall and unlink multiple Casks at once" do + caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") + + shutup do + Hbc::Installer.new(caffeine).install + Hbc::Installer.new(transmission).install + end + + expect(caffeine).to be_installed + expect(transmission).to be_installed + + shutup do + Hbc::CLI::Uninstall.run("local-caffeine", "local-transmission") + end + + expect(caffeine).not_to be_installed + expect(Hbc.appdir.join("Transmission.app")).not_to exist + expect(transmission).not_to be_installed + expect(Hbc.appdir.join("Caffeine.app")).not_to exist + end + + it "calls `uninstall` before removing artifacts" do + cask = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-script-app.rb") + + shutup do + Hbc::Installer.new(cask).install + end + + expect(cask).to be_installed + + expect { + shutup do + Hbc::CLI::Uninstall.run("with-uninstall-script-app") + end + }.not_to raise_error + + expect(cask).not_to be_installed + expect(Hbc.appdir.join("MyFancyApp.app")).not_to exist + end + + it "can uninstall Casks when the uninstall script is missing, but only when using `--force`" do + cask = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-script-app.rb") + + shutup do + Hbc::Installer.new(cask).install + end + + expect(cask).to be_installed + + Hbc.appdir.join("MyFancyApp.app").rmtree + + expect { + shutup do + Hbc::CLI::Uninstall.run("with-uninstall-script-app") + end + }.to raise_error(Hbc::CaskError, /does not exist/) + + expect(cask).to be_installed + + expect { + shutup do + Hbc::CLI::Uninstall.run("with-uninstall-script-app", "--force") + end + }.not_to raise_error + + expect(cask).not_to be_installed + end + + describe "when multiple versions of a cask are installed" do + let(:token) { "versioned-cask" } + let(:first_installed_version) { "1.2.3" } + let(:last_installed_version) { "4.5.6" } + let(:timestamped_versions) { + [ + [first_installed_version, "123000"], + [last_installed_version, "456000"], + ] + } + let(:caskroom_path) { Hbc.caskroom.join(token).tap(&:mkpath) } + + before(:each) do + timestamped_versions.each do |timestamped_version| + caskroom_path.join(".metadata", *timestamped_version, "Casks").tap(&:mkpath) + .join("#{token}.rb").open("w") do |caskfile| + caskfile.puts <<-EOS.undent + cask '#{token}' do + version '#{timestamped_version[0]}' + end + EOS + end + caskroom_path.join(timestamped_version[0]).mkpath + end + end + + it "uninstalls one version at a time" do + shutup do + Hbc::CLI::Uninstall.run("versioned-cask") + end + + expect(caskroom_path.join(first_installed_version)).to exist + expect(caskroom_path.join(last_installed_version)).not_to exist + expect(caskroom_path).to exist + + shutup do + Hbc::CLI::Uninstall.run("versioned-cask") + end + + expect(caskroom_path.join(first_installed_version)).not_to exist + expect(caskroom_path).not_to exist + end + + it "displays a message when versions remain installed" do + expect { + expect { + Hbc::CLI::Uninstall.run("versioned-cask") + }.not_to output.to_stderr + }.to output(/#{token} #{first_installed_version} is still installed./).to_stdout + end + end + + describe "when Casks in Taps have been renamed or removed" do + let(:app) { Hbc.appdir.join("ive-been-renamed.app") } + let(:caskroom_path) { Hbc.caskroom.join("ive-been-renamed").tap(&:mkpath) } + let(:saved_caskfile) { caskroom_path.join(".metadata", "latest", "timestamp", "Casks").join("ive-been-renamed.rb") } + + before do + app.tap(&:mkpath) + .join("Contents").tap(&:mkpath) + .join("Info.plist").tap(&FileUtils.method(:touch)) + + caskroom_path.mkpath + + saved_caskfile.dirname.mkpath + + IO.write saved_caskfile, <<-EOS.undent + cask 'ive-been-renamed' do + version :latest + + app 'ive-been-renamed.app' + end + EOS + end + + it "can still uninstall those Casks" do + shutup do + Hbc::CLI::Uninstall.run("ive-been-renamed") + end + + expect(app).not_to exist + expect(caskroom_path).not_to exist + end + end + + describe "when no Cask is specified" do + it "raises an exception" do + expect { + Hbc::CLI::Uninstall.run + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end + + describe "when no Cask is specified, but an invalid option" do + it "raises an exception" do + expect { + Hbc::CLI::Uninstall.run("--notavalidoption") + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end +end diff --git a/Library/Homebrew/test/cask/cli/version_spec.rb b/Library/Homebrew/test/cask/cli/version_spec.rb new file mode 100644 index 000000000..2091496fc --- /dev/null +++ b/Library/Homebrew/test/cask/cli/version_spec.rb @@ -0,0 +1,9 @@ +describe "brew cask --version", :cask do + it "respects the --version argument" do + expect { + expect { + Hbc::CLI::NullCommand.new("--version").run + }.not_to output.to_stderr + }.to output(Hbc.full_version).to_stdout + end +end diff --git a/Library/Homebrew/test/cask/cli/zap_spec.rb b/Library/Homebrew/test/cask/cli/zap_spec.rb new file mode 100644 index 000000000..0f3d024b5 --- /dev/null +++ b/Library/Homebrew/test/cask/cli/zap_spec.rb @@ -0,0 +1,73 @@ +describe Hbc::CLI::Zap, :cask do + it "shows an error when a bad Cask is provided" do + expect { + Hbc::CLI::Zap.run("notacask") + }.to raise_error(Hbc::CaskUnavailableError) + end + + it "can zap and unlink multiple Casks at once" do + caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") + + shutup do + Hbc::Installer.new(caffeine).install + Hbc::Installer.new(transmission).install + end + + expect(caffeine).to be_installed + expect(transmission).to be_installed + + shutup do + Hbc::CLI::Zap.run("--notavalidoption", + "local-caffeine", "local-transmission") + end + + expect(caffeine).not_to be_installed + expect(Hbc.appdir.join("Caffeine.app")).not_to be_a_symlink + expect(transmission).not_to be_installed + expect(Hbc.appdir.join("Transmission.app")).not_to be_a_symlink + end + + # TODO: Explicit test that both zap and uninstall directives get dispatched. + # The above tests that implicitly. + # + # it "dispatches both uninstall and zap stanzas" do + # with_zap = Hbc.load('with-zap') + # + # shutup do + # Hbc::Installer.new(with_zap).install + # end + # + # with_zap.must_be :installed? + # + # Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app"'], '1') + # Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app" to quit']) + # Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app.from.uninstall"'], '1') + # Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app.from.uninstall" to quit']) + # + # Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', with_zap.staged_path.join('MyFancyPkg','FancyUninstaller.tool'), '--please']) + # Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-rf', '--', + # Pathname.new('~/Library/Preferences/my.fancy.app.plist').expand_path]) + # + # shutup do + # Hbc::CLI::Zap.run('with-zap') + # end + # with_zap.wont_be :installed? + # end + + describe "when no Cask is specified" do + it "raises an exception" do + expect { + Hbc::CLI::Zap.run + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end + + describe "when no Cask is specified, but an invalid option" do + it "raises an exception" do + expect { + Hbc::CLI::Zap.run("--notavalidoption") + }.to raise_error(Hbc::CaskUnspecifiedError) + end + end +end |
