require 'spec_helper'
require 'silver_lining'

describe SilverLining::Command::CommandNsupdate do

  context "dns action" do

    let(:command) do
      SilverLining::Command::CommandNsupdate.new("an org name", "vapp name")
    end

    let(:valid_configuration) do
      configuration = SilverLining::Config.new
      configuration.url = "http://domain/api"
      configuration.username = "username"
      configuration.set_password("password")
      configuration.organization = "organization"
      configuration.dns_server = "1.2.3.4"
      configuration.dns_suffix = "wiget.com"
      configuration.vapp_name = "vapp_name"
      configuration.detail = "true"
      configuration.xml = "false"
      configuration
    end

    let(:vdc) do
      Vcloud::Item::Vdc.new
    end

    let(:organization) do
      Vcloud::Item::Organization.new.tap do |organization|
        organization.link_vdcs << Vcloud::Item::Link.new(:name => "vdcname")
      end
    end

    context "that interact with server" do

      before do
        vapp = Vcloud::Item::Vapp.new
        vapp.vms << Vcloud::Item::Vm.new(:name => "machine1", :status => "4",
                                         :network_connection => Vcloud::Item::NetworkConnection.new(:ip_address => "1.1.1.1", :external_ip_address => "2.2.2.2"))
        vapp.vms << Vcloud::Item::Vm.new(:name => "machine2", :status => "8",
                                         :network_connection => Vcloud::Item::NetworkConnection.new(:ip_address => "1.1.1.2", :external_ip_address => "2.2.2.3"))
        vapp.vms << Vcloud::Item::Vm.new(:name => "machine3", :status => "3",
                                         :network_connection => Vcloud::Item::NetworkConnection.new(:ip_address => "1.1.1.3", :external_ip_address => ""))

        client = double(Vcloud::Api::Client)
        expect( client ).to receive(:organization).and_return(organization)
        expect( client ).to receive(:vapp).and_return(vapp)

        session = double("session")
        expect( session ).to receive(:client).and_return(client)
        expect( SilverLining::Session ).to receive(:instance).and_return(session)

        expect( SilverLining::Config ).to receive(:configuration).and_return(valid_configuration)

        allow_any_instance_of( Dnsruby::Resolver ).to receive(:send_message)
      end

      context "sending add" do
        it "when argument is add" do
          output = StringIO.new
          command.output = output

          command.run("add")

          expect( output.string ).to include("machine1.vapp-name.wiget.com\t2.2.2.2 in dns server 1.2.3.4\n")
          expect( output.string ).to include("machine2.vapp-name.wiget.com\t2.2.2.3 in dns server 1.2.3.4\n")
          expect( output.string ).to include("machine3.vapp-name.wiget.com\thas no external ip address so was not added\n")
        end

        it "when no argument" do
          output = StringIO.new
          command.output = output

          command.run

          expect( output.string ).to include("machine1.vapp-name.wiget.com\t2.2.2.2 in dns server 1.2.3.4\n")
          expect( output.string ).to include("machine2.vapp-name.wiget.com\t2.2.2.3 in dns server 1.2.3.4\n")
          expect( output.string ).to include("machine3.vapp-name.wiget.com\thas no external ip address so was not added\n")
        end
      end

      context "sending delete" do
        it "when argument is delete" do
          output = StringIO.new
          command.output = output

          command.run("delete")

          expect( output.string ).to include("machine1.vapp-name.wiget.com deleted from dns server 1.2.3.4\n")
          expect( output.string ).to include("machine2.vapp-name.wiget.com deleted from dns server 1.2.3.4\n")
          expect( output.string ).to include("machine3.vapp-name.wiget.com deleted from dns server 1.2.3.4\n")
        end
      end
    end

    context "with invalid" do
      it "argument" do
        output = StringIO.new
        command.output = output

        command.run("INVALID")

        expect( output.string ).to include("nsupdate doesn't support the 'INVALID' option, try 'add' or 'delete'\n")
      end
    end
  end

  context "validation" do

    [
      ["machine-name", "machine-name"],
      ["machine_name", "machine-name"],
      ["machine name", "machine-name"],
      ["MACHINE name", "machine-name"],
      ["machine.name", "machine-name"],
      ["a1!b2@c3#d4$e5%f6^g7&h8*i9(j0)", "a1-b2-c3-d4-e5-f6-g7-h8-i9-j0"],
      ["ending-in-dash-", "ending-in-dash"],
      ["-beginning-in-dash", "beginning-in-dash"],
      ["-beginning-and-ending-in-dash-", "beginning-and-ending-in-dash"],
      ["--containing--multiple--dashes--", "containing-multiple-dashes"],
      ["", ""],
      [nil, ""],
    ].each do |*args|

      machine_name, expected_machine_name = args[0]

      it "formats machine name ${machome_name}" do
        command = SilverLining::Command::CommandNsupdate.new("org1", "vapp1") 

        expect( command.send(:machine_to_dns, machine_name) ).to eq(expected_machine_name)
      end
    end

    [
      ["vapp-name", "vapp-name"],
      ["vapp_name", "vapp-name"],
      ["vapp name", "vapp-name"],
      ["VAPP name", "vapp-name"],
      ["vapp.name", "vapp-name"],
      ["a1!b2@c3#d4$e5%f6^g7&h8*i9(j0)", "a1-b2-c3-d4-e5-f6-g7-h8-i9-j0"],
      ["ending-in-dash-", "ending-in-dash"],
      ["-beginning-in-dash", "beginning-in-dash"],
      ["-beginning-and-ending-in-dash-", "beginning-and-ending-in-dash"],
      ["--containing--multiple--dashes--", "containing-multiple-dashes"],
      ["", ""],
      [nil, ""],
    ].each do |*args|

      vapp_name, expected_dns_name = args[0]

      it "formats vapp name #{vapp_name}" do
        command = SilverLining::Command::CommandNsupdate.new("org1", "vapp1") 

        expect( command.send(:vapp_to_dns, vapp_name) ).to eq(expected_dns_name)
      end
    end
  end
end
