require 'spec_helper'
require 'r10k/source'
require 'json'
require 'yaml'

describe R10K::Source::Exec do

  let(:environments_hash) do
    {
      'production' => {
        'remote'  => 'https://git.example.com/puppet/control-repo.git',
        'ref'     => 'release-141',
        'modules' => {
          'puppetlabs-stdlib' => '6.1.0',
          'puppetlabs-ntp' => '8.1.0',
          'example-myapp1' => {
            'git' => 'https://git.example.com/puppet/example-myapp1.git',
            'ref' => 'v1.3.0'
          }
        }
      },
      'development' => {
        'remote'  => 'https://git.example.com/puppet/control-repo.git',
        'ref'     => 'master',
        'modules' => {
          'puppetlabs-stdlib' => '6.1.0',
          'puppetlabs-ntp' => '8.1.0',
          'example-myapp1' => {
            'git' => 'https://git.example.com/puppet/example-myapp1.git',
            'ref' => 'v1.3.1'
          }
        }
      }
    }
  end

  describe 'initialize' do
    context 'with a valid command' do
      context 'that produces valid output' do
        it 'accepts json' do
          allow_any_instance_of(R10K::Util::Subprocess)
            .to receive(:execute)
            .and_return(double('result', stdout: environments_hash.to_json))

          source = described_class.new('execsource', '/some/nonexistent/dir', command: '/path/to/command')
          expect(source.environments.map(&:name)).to contain_exactly('production', 'development')
        end

        it 'accepts yaml' do
          allow_any_instance_of(R10K::Util::Subprocess)
            .to receive(:execute)
            .and_return(double('result', stdout: environments_hash.to_yaml))

          source = described_class.new('execsource', '/some/nonexistent/dir', command: '/path/to/command')
          expect(source.environments.map(&:name)).to contain_exactly('production', 'development')
        end

      end

      context 'that produces invalid output' do
        it 'raises an error for non-json, non-yaml data' do
          allow_any_instance_of(R10K::Util::Subprocess)
            .to receive(:execute)
            .and_return(double('result', stdout: "one:\ntwo\n"))

          source = described_class.new('execsource', '/some/nonexistent/dir', command: '/path/to/command')
          expect { source.environments }.to raise_error(/Error parsing command output/)
        end

        it 'raises an error for yaml data that is not a hash' do
          allow_any_instance_of(R10K::Util::Subprocess)
            .to receive(:execute)
            .and_return(double('result', stdout: "[one, two]"))

          source = described_class.new('execsource', '/some/nonexistent/dir', command: '/path/to/command')
          expect { source.environments }.to raise_error(R10K::Error, /Environment source execsource.*did not return valid environment data.*one.*two.*/m)
        end
      end
    end
  end
end
