require 'spec_helper'

module CavalerieWeb

  describe VagrantManager do
    let(:container_name) { "apache-server" }
    let(:containers_names) {["mysql-server", "apache-server"]}

    describe "#get_container_status" do
      context "when container is not created" do
        before { allow(VagrantHelper).to receive(:status).with(container_name).and_return "Current machine states: apache not created (docker)" }
        it { expect(VagrantManager.get_container_status container_name).to eq "not created" }
      end

      context "when container is running" do
        before { allow(VagrantHelper).to receive(:status).with(container_name).and_return "Current machine states: apache running (docker) The container is created and running." }
        it { expect(VagrantManager.get_container_status container_name).to eq "running" }
      end

      context "when container is saved" do
        before { allow(VagrantHelper).to receive(:status).with(container_name).and_return "Current machine states: apache saved (docker)" }
        it { expect(VagrantManager.get_container_status container_name).to eq "saved" }
      end

      context "when container is preparing" do
        before { allow(VagrantHelper).to receive(:status).with(container_name).and_return "Current machine states: apache preparing (docker)" }
        it { expect(VagrantManager.get_container_status container_name).to eq "preparing" }
      end

      context "when container is powered off" do
        before { allow(VagrantHelper).to receive(:status).with(container_name).and_return "Current machine states: apache poweroff (docker)" }
        it { expect(VagrantManager.get_container_status container_name).to eq "poweroff" }
      end

      context "when container is stopped" do
        before { allow(VagrantHelper).to receive(:status).with(container_name).and_return "Current machine states: apache stopped (docker)" }
        it { expect(VagrantManager.get_container_status container_name).to eq "stopped" }
      end

      context "when container is host state unknown" do
        before { allow(VagrantHelper).to receive(:status).with(container_name).and_return "Current machine states: apache host state unknown (docker)" }
        it { expect(VagrantManager.get_container_status container_name).to eq "host state unknown" }
      end

      context "when container has another status" do
        let(:status) { "Current machine states" }
        before { allow(VagrantHelper).to receive(:status).with(container_name).and_return status }
        it { expect{ VagrantManager.get_container_status container_name }.to raise_error SystemExit, /#{status}/ }
      end
    end

    describe "#ensure_containers_are_running" do
      before do
        allow(Config).to receive(:get_containers_names).and_return containers_names
        allow(VagrantManager).to receive(:get_container_status).and_return "running"
      end

      context "whe one container is preparing" do
        before { allow(VagrantManager).to receive :sleep }

        context "and finally run in time" do
          before { allow(VagrantManager).to receive(:get_container_status).and_return "preparing", "preparing", "preparing", "running" }
          it { expect{ VagrantManager.ensure_containers_are_running }.not_to raise_error }
        end

        context "and didn't run in time" do
          before { allow(VagrantManager).to receive(:get_container_status).and_return "preparing" }
          it { expect{ VagrantManager.ensure_containers_are_running }.to raise_error SystemExit, /isn't running/ }
        end
      end

      context "when one container isn't running" do
        before { allow(VagrantManager).to receive(:get_container_status).and_return "not created", "running" }
        it { expect{ VagrantManager.ensure_containers_are_running }.to raise_error SystemExit, /isn't running/ }
      end

      context "when containers are running" do
        it { expect{ VagrantManager.ensure_containers_are_running }.not_to raise_error }
      end
    end

    describe "#start_or_restart_containers" do
      before do
        allow(VagrantManager).to receive :destroy_containers
        allow(VagrantManager).to receive :start_containers
        VagrantManager.start_or_restart_containers
      end
      it { expect(VagrantManager).to have_received :destroy_containers }
      it { expect(VagrantManager).to have_received :start_containers }
    end

    describe "#start_containers" do
      before do
        allow(Config).to receive(:get_containers_names).and_return containers_names
        allow(VagrantHelper).to receive :start_container
        VagrantManager.start_containers
      end
      it { expect(VagrantHelper).to have_received(:start_container).with containers_names[0] }
    end

    describe "#destroy_containers" do
      before do
        allow(Config).to receive(:get_containers_names).and_return containers_names
        allow(VagrantHelper).to receive :destroy_container
      end

      context "when a container isn't created" do
        before do
          allow(VagrantManager).to receive(:get_container_status).and_return "not created"
          VagrantManager.destroy_containers
        end
        it { expect(VagrantHelper).not_to have_received :destroy_container }
      end

      context "when a container is created" do
        before do
          allow(VagrantManager).to receive(:get_container_status).and_return "running", "preparing"
          VagrantManager.destroy_containers
        end
        it { expect(VagrantHelper).to have_received(:destroy_container).with containers_names[0] }
        it { expect(VagrantHelper).to have_received(:destroy_container).with containers_names[1] }
      end
    end

    describe "#restart_container" do
      before do
        allow(VagrantHelper).to receive :destroy_container
        allow(VagrantHelper).to receive :start_container
        VagrantManager.restart_container container_name
      end
      it { expect(VagrantHelper).to have_received(:destroy_container).with container_name }
      it { expect(VagrantHelper).to have_received(:start_container).with container_name }
    end

    describe "#get_containers_names" do
      let(:docker_configs) {{ "containers_names"=>["mysql-server", "apache-server"] }}
      before do
        allow(Config).to receive(:get_docker_configs).and_return docker_configs
        VagrantManager.get_containers_names
      end
      it { expect(Config).to have_received :get_docker_configs }
      it { expect(VagrantManager.get_containers_names).to be_a Array }
    end

    describe "#get_all_containers_info" do
      let(:docker_configs) {{ "containers_names"=>["mysql-server", "apache-server"] }}
      before do
        allow(Config).to receive(:get_docker_configs).and_return docker_configs
        allow(VagrantManager).to receive :get_container_info
        VagrantManager.get_all_containers_info
      end
      it { expect(Config).to have_received :get_docker_configs }
      it { expect(VagrantManager).to have_received(:get_container_info).twice }
      it { expect(VagrantManager.get_all_containers_info).to be_a Hash }
    end

    describe "#get_container_info" do
      before do
        allow(Config).to receive(:get_docker_configs).and_return $docker_configs_parsed
        allow(VagrantManager).to receive(:get_container_status).and_return "running"
      end

      context "when container hasn't any other info" do
        before do
          allow(VagrantManager).to receive(:get_container_other_info).and_return ""
          @result = VagrantManager.get_container_info container_name
        end
        it { expect(Config).to have_received :get_docker_configs }
        it { expect(VagrantManager).to have_received(:get_container_status).with container_name }
        it { expect(VagrantManager).to have_received(:get_container_other_info).with container_name }
        it { expect(@result).to include status: "running" }
        it { expect(@result[:others]).to be_empty }
      end

      context "when container has other info" do
        let(:other_info) {{ "mysql-server_user"=>"dev", "mysql-server_user_password"=>"devpass", "mysql-server_root_password"=>"cavalerie" }}
        before do
          allow(VagrantManager).to receive(:get_container_other_info).and_return other_info
          @result = VagrantManager.get_container_info container_name
        end
        it { expect(@result[:others]).not_to be_empty }
      end
    end

    describe "#get_container_other_info" do
      before { allow(Config).to receive(:get_docker_configs).and_return $docker_configs_parsed }

      context "when container hasn't any other info" do
        let(:container_name) { "apache-server" }
        it { expect(VagrantManager.get_container_other_info container_name).to be_empty }
      end

      context "when container has other info" do
        let(:container_name) { "mysql-server" }
        it { expect(VagrantManager.get_container_other_info container_name).not_to be_empty }
      end
    end

  end

end