require 'support/spec_support'
require 'cheffish/rspec/chef_run_support'

describe Chef::Resource::ChefGroup do
  extend Cheffish::RSpec::ChefRunSupport

  when_the_chef_12_server 'is in multi-org mode' do
    organization 'foo'

    before :each do
      Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
    end

    context 'and is empty' do
      group 'g', {}
      user 'u', {}
      client 'c', {}

      it 'Converging chef_group "x" creates the group with no members' do
        expect_recipe {
          chef_group 'x'
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => [],
          'groups'  => [],
          'users'   => [],
          'clients' => []
        })
      end

      it 'chef_group "x" action :delete does nothing' do
        expect_recipe {
          chef_group 'x' do
            action :delete
          end
        }.to not_have_updated('chef_group[x]', :delete).and not_have_updated('chef_group[x]', :create)
        expect { get('groups/x') }.to raise_error(Net::HTTPServerException)
      end

      it 'Converging chef_group "x" creates the group with the given members' do
        expect_recipe {
          chef_group 'x' do
            groups 'g'
            users 'u'
            clients 'c'
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => %w(c u),
          'groups'  => %w(g),
          'users'   => %w(u),
          'clients' => %w(c)
        })
      end
    end

    context 'and has a group named x' do
      group 'g', {}
      group 'g2', {}
      group 'g3', {}
      group 'g4', {}
      user 'u', {}
      user 'u2', {}
      user 'u3', {}
      user 'u4', {}
      client 'c', {}
      client 'c2', {}
      client 'c3', {}
      client 'c4', {}

      group 'x', {
        'users' => %w(u u2),
        'clients' => %w(c c2),
        'groups' => %w(g g2)
      }

      it 'Converging chef_group "x" changes nothing' do
        expect_recipe {
          chef_group 'x'
        }.not_to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => %w(c c2 u u2),
          'groups'  => %w(g g2),
          'users'   => %w(u u2),
          'clients' => %w(c c2)
        })
      end

      it 'chef_group "x" action :delete deletes the group' do
        expect_recipe {
          chef_group 'x' do
            action :delete
          end
        }.to have_updated('chef_group[x]', :delete)
        expect { get('groups/x') }.to raise_error(Net::HTTPServerException)
      end

      it 'Converging chef_group "x" with existing users changes nothing' do
        expect_recipe {
          chef_group 'x' do
            users 'u'
            clients 'c'
            groups 'g'
          end
        }.not_to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => %w(c c2 u u2),
          'groups'  => %w(g g2),
          'users'   => %w(u u2),
          'clients' => %w(c c2)
        })
      end

      it 'Converging chef_group "x" adds new users' do
        expect_recipe {
          chef_group 'x' do
            users 'u3'
            clients 'c3'
            groups 'g3'
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => %w(c c2 c3 u u2 u3),
          'groups'  => %w(g g2 g3),
          'users'   => %w(u u2 u3),
          'clients' => %w(c c2 c3)
        })
      end

      it 'Converging chef_group "x" with multiple users adds new users' do
        expect_recipe {
          chef_group 'x' do
            users 'u3', 'u4'
            clients 'c3', 'c4'
            groups 'g3', 'g4'
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => %w(c c2 c3 c4 u u2 u3 u4),
          'groups'  => %w(g g2 g3 g4),
          'users'   => %w(u u2 u3 u4),
          'clients' => %w(c c2 c3 c4)
        })
      end

      it 'Converging chef_group "x" with multiple users in an array adds new users' do
        expect_recipe {
          chef_group 'x' do
            users [ 'u3', 'u4' ]
            clients [ 'c3', 'c4' ]
            groups [ 'g3', 'g4' ]
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => %w(c c2 c3 c4 u u2 u3 u4),
          'groups'  => %w(g g2 g3 g4),
          'users'   => %w(u u2 u3 u4),
          'clients' => %w(c c2 c3 c4)
        })
      end

      it 'Converging chef_group "x" with multiple users declarations adds new users' do
        expect_recipe {
          chef_group 'x' do
            users 'u3'
            users 'u4'
            clients 'c3'
            clients 'c4'
            groups 'g3'
            groups 'g4'
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => %w(c c2 c3 c4 u u2 u3 u4),
          'groups'  => %w(g g2 g3 g4),
          'users'   => %w(u u2 u3 u4),
          'clients' => %w(c c2 c3 c4)
        })
      end

      it 'Converging chef_group "x" removes desired users' do
        expect_recipe {
          chef_group 'x' do
            remove_users 'u2'
            remove_clients 'c2'
            remove_groups 'g2'
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => %w(c u),
          'groups'  => %w(g),
          'users'   => %w(u),
          'clients' => %w(c)
        })
      end

      it 'Converging chef_group "x" with multiple users removes desired users' do
        expect_recipe {
          chef_group 'x' do
            remove_users 'u', 'u2'
            remove_clients 'c', 'c2'
            remove_groups 'g', 'g2'
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => [],
          'groups'  => [],
          'users'   => [],
          'clients' => []
        })
      end

      it 'Converging chef_group "x" with multiple users in an array removes desired users' do
        expect_recipe {
          chef_group 'x' do
            remove_users [ 'u', 'u2' ]
            remove_clients [ 'c', 'c2' ]
            remove_groups [ 'g', 'g2' ]
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => [],
          'groups'  => [],
          'users'   => [],
          'clients' => []
        })
      end

      it 'Converging chef_group "x" with multiple remove_ declarations removes desired users' do
        expect_recipe {
          chef_group 'x' do
            remove_users 'u'
            remove_users 'u2'
            remove_clients 'c'
            remove_clients 'c2'
            remove_groups 'g'
            remove_groups 'g2'
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => [],
          'groups'  => [],
          'users'   => [],
          'clients' => []
        })
      end

      it 'Converging chef_group "x" adds and removes desired users' do
        expect_recipe {
          chef_group 'x' do
            users 'u3'
            clients 'c3'
            groups 'g3'
            remove_users 'u'
            remove_clients 'c'
            remove_groups 'g'
          end
        }.to have_updated('chef_group[x]', :create)
        expect(get('groups/x')).to eq({
          'name' => 'x',
          'groupname' => 'x',
          'orgname' => 'foo',
          'actors'  => %w(c2 c3 u2 u3),
          'groups'  => %w(g2 g3),
          'users'   => %w(u2 u3),
          'clients' => %w(c2 c3)
        })
      end
    end
  end
end
