<commit_before># typed: false
# frozen_string_literal: true

describe Cask::Cmd::Uninstall, :cask do
  it "displays the uninstallation progress" do
    caffeine = Cask::CaskLoader.load(cask_path("local-caffeine"))

    Cask::Installer.new(caffeine).install

    output = Regexp.new <<~EOS
      ==> Uninstalling Cask local-caffeine
      ==> Backing App 'Caffeine.app' up to '.*Caffeine.app'
      ==> Removing App '.*Caffeine.app'
      ==> Purging files for version 1.2.3 of Cask local-caffeine
    EOS

    expect {
      described_class.run("local-caffeine")
    }.to output(output).to_stdout
  end

  it "shows an error when a bad Cask is provided" do
    expect { described_class.run("notacask") }
      .to raise_error(Cask::CaskUnavailableError, /is unavailable/)
  end

  it "shows an error when a Cask is provided that's not installed" do
    expect { described_class.run("local-caffeine") }
    .to raise_error(Cask::CaskNotInstalledError, /is not installed/)
  end

  it "tries anyway on a non-present Cask when --force is given" do
    expect {
      described_class.run("local-caffeine", "--force")
    }.not_to raise_error
  end

  it "can uninstall and unlink multiple Casks at once" do
    caffeine = Cask::CaskLoader.load(cask_path("local-caffeine"))
    transmission = Cask::CaskLoader.load(cask_path("local-transmission"))

    Cask::Installer.new(caffeine).install
    Cask::Installer.new(transmission).install

    expect(caffeine).to be_installed
    expect(transmission).to be_installed

    described_class.run("local-caffeine", "local-transmission")

    expect(caffeine).not_to be_installed
    expect(caffeine.config.appdir.join("Transmission.app")).not_to exist
    expect(transmission).not_to be_installed
    expect(transmission.config.appdir.join("Caffeine.app")).not_to exist
  end

  it "calls `uninstall` before removing artifacts" do
    cask = Cask::CaskLoader.load(cask_path("with-uninstall-script-app"))

    Cask::Installer.new(cask).install

    expect(cask).to be_installed
    expect(cask.config.appdir.join("MyFancyApp.app")).to exist

    expect {
      described_class.run("with-uninstall-script-app")
    }.not_to raise_error

    expect(cask).not_to be_installed
    expect(cask.config.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 = Cask::CaskLoader.load(cask_path("with-uninstall-script-app"))

    Cask::Installer.new(cask).install

    expect(cask).to be_installed

    cask.config.appdir.join("MyFancyApp.app").rmtree

    expect { described_class.run("with-uninstall-script-app") }
    .to raise_error(Cask::CaskError, /uninstall script .* does not exist/)

    expect(cask).to be_installed

    expect {
      described_class.run("with-uninstall-script-app", "--force")
    }.not_to raise_error

    expect(cask).not_to be_installed
  end

  context "when Casks use script path with `~` as `HOME`" do
    let(:home_dir) { mktmpdir }
    let(:app) { Pathname.new("#{home_dir}/MyFancyApp.app") }
    let(:cask) { Cask::CaskLoader.load(cask_path("with-uninstall-script-user-relative")) }

    before do
      ENV["HOME"] = home_dir
    end

    it "can still uninstall them" do
      Cask::Installer.new(cask).install

      expect(cask).to be_installed
      expect(app).to exist

      expect {
        described_class.run("with-uninstall-script-user-relative")
      }.not_to raise_error

      expect(cask).not_to be_installed
      expect(app).not_to exist
    end
  end

  describe "when multiple versions of a cask are installed" do
    let(:token) { "<PASSWORD>" }
    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) { Cask::Caskroom.path.join(token).tap(&:mkpath) }

    before 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 <<~RUBY
                         cask '#{token}' do
                           version '#{timestamped_version[0]}'
                         end<commit_msg>cask/cmd/uninstall_spec: delete more flaky tests.<commit_after># typed: false
# frozen_string_literal: true

describe Cask::Cmd::Uninstall, :cask do
  it "displays the uninstallation progress" do
    caffeine = Cask::CaskLoader.load(cask_path("local-caffeine"))

    Cask::Installer.new(caffeine).install

    output = Regexp.new <<~EOS
      ==> Uninstalling Cask local-caffeine
      ==> Backing App 'Caffeine.app' up to '.*Caffeine.app'
      ==> Removing App '.*Caffeine.app'
      ==> Purging files for version 1.2.3 of Cask local-caffeine
    EOS

    expect {
      described_class.run("local-caffeine")
    }.to output(output).to_stdout
  end

  it "shows an error when a bad Cask is provided" do
    expect { described_class.run("notacask") }
      .to raise_error(Cask::CaskUnavailableError, /is unavailable/)
  end

  it "shows an error when a Cask is provided that's not installed" do
    expect { described_class.run("local-caffeine") }
    .to raise_error(Cask::CaskNotInstalledError, /is not installed/)
  end

  it "tries anyway on a non-present Cask when --force is given" do
    expect {
      described_class.run("local-caffeine", "--force")
    }.not_to raise_error
  end

  it "can uninstall and unlink multiple Casks at once" do
    caffeine = Cask::CaskLoader.load(cask_path("local-caffeine"))
    transmission = Cask::CaskLoader.load(cask_path("local-transmission"))

    Cask::Installer.new(caffeine).install
    Cask::Installer.new(transmission).install

    expect(caffeine).to be_installed
    expect(transmission).to be_installed

    described_class.run("local-caffeine", "local-transmission")

    expect(caffeine).not_to be_installed
    expect(caffeine.config.appdir.join("Transmission.app")).not_to exist
    expect(transmission).not_to be_installed
    expect(transmission.config.appdir.join("Caffeine.app")).not_to exist
  end

  it "can uninstall Casks when the uninstall script is missing, but only when using `--force`" do
    cask = Cask::CaskLoader.load(cask_path("with-uninstall-script-app"))

    Cask::Installer.new(cask).install

    expect(cask).to be_installed

    cask.config.appdir.join("MyFancyApp.app").rmtree

    expect { described_class.run("with-uninstall-script-app") }
    .to raise_error(Cask::CaskError, /uninstall script .* does not exist/)

    expect(cask).to be_installed

    expect {
      described_class.run("with-uninstall-script-app", "--force")
    }.not_to raise_error

    expect(cask).not_to be_installed
  end

  describe "when multiple versions of a cask are installed" do
    let(:token) { "<PASSWORD>" }
    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) { Cask::Caskroom.path.join(token).tap(&:mkpath) }

    before 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 <<~RUBY
                         cask '#{token}' do
                           version '#{timestamped_version[0]}'
                         end
{'fraction_non_alphanumeric': 0.12589787122894083, 'fraction_numerical': 0.005746375865221366, 'mean_word_length': 3.230939226519337, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5621316', 'n_tokens_mistral': 2639, 'n_tokens_neox': 2511, 'n_words': 504}