spec/lib/release_tools/release_managers/definitions_spec.rb (179 lines of code) (raw):
# frozen_string_literal: true
require 'spec_helper'
describe ReleaseTools::ReleaseManagers::Definitions do
subject { described_class.new(fixture) }
let(:fixture) { File.expand_path('../../../fixtures/release_managers.yml', __dir__) }
let(:clients) { stub_clients }
def stub_schedule
schedule = instance_spy(ReleaseTools::ReleaseManagers::Schedule)
users = %w[jameslopez new-team-member rspeicher].map { |username| double('user', username: username) }
allow(ReleaseTools::ReleaseManagers::Schedule)
.to receive(:new)
.and_return(schedule)
allow(schedule)
.to receive(:active_release_managers)
.and_return(users)
end
def stub_clients
%i[slack dev production ops].to_h do |instance|
client_spy = spy
allow(subject).to receive("#{instance}_client").and_return(client_spy)
[instance, client_spy]
end
end
describe 'class delegators' do
it 'delegates .allowed?' do
expect(described_class).to respond_to(:allowed?)
end
it 'delegates .sync!' do
expect(described_class).to respond_to(:sync!)
end
it 'delegates .join' do
expect(described_class).to respond_to(:join)
end
it 'delegates .leave' do
expect(described_class).to respond_to(:leave)
end
end
describe '#all' do
it 'returns an array of User objects' do
expect(subject.all)
.to all(be_a(described_class::User))
end
it 'is enumerable' do
expect(subject).to respond_to(:any?)
end
end
describe '#find_user' do
it 'finds an User by the gitlab.com username' do
user = subject.find_user('jameslopez')
expect(user).to be_a(described_class::User)
expect(user.name).to eq('James Lopez')
end
it 'returns nil for unknown users' do
expect(subject.find_user('missing-user')).to be_nil
end
it 'returns nil for nil users' do
expect(subject.find_user(nil)).to be_nil
end
it 'finds an User by the OPS username' do
user = subject.find_user('new-team-member-ops', instance: :ops)
expect(user.name).to eq('New Team Member')
end
it 'finds an User by the dev username' do
user = subject.find_user('new-team-member-dev', instance: :dev)
expect(user.name).to eq('New Team Member')
end
it 'raises ArgumentError when the instance is unknown' do
expect do
subject.find_user('new-team-member-dev', instance: :another)
end.to raise_error(ArgumentError)
end
end
describe '#allowed?' do
around do |tests|
ClimateControl.modify(CI_SERVER_URL: 'https://gitlab.com', &tests)
end
it 'allows a defined member, case-insensitively' do
expect(subject).to be_allowed('RSpeicher')
end
it 'disallows an undefined member' do
expect(subject).not_to be_allowed('invalid-member')
end
end
describe '#reload!' do
it 'raises `ArgumentError` if the config file is missing' do
expect { described_class.new('foo.yml') }
.to raise_error(ArgumentError, 'foo.yml does not exist!')
end
it 'raises `ArgumentError` if the config file is empty' do
allow(YAML).to receive(:load_file).and_return({})
expect { described_class.new('foo.yml') }
.to raise_error(ArgumentError, 'foo.yml contains no data')
end
end
describe '#sync!' do
before { stub_schedule }
it 'syncs dev usernames' do
client = clients[:dev]
subject.sync!
expect(client).to have_received(:sync_membership)
.with(%w[james new-team-member-dev rspeicher])
end
it 'syncs production usernames' do
client = clients[:production]
subject.sync!
expect(client).to have_received(:sync_membership)
.with(%w[jameslopez new-team-member rspeicher])
end
it 'syncs ops usernames' do
client = clients[:ops]
subject.sync!
expect(client).to have_received(:sync_membership)
.with(%w[jameslopez new-team-member-ops rspeicher])
end
it 'syncs slack usernames' do
client = clients[:slack]
subject.sync!
expect(client).to have_received(:sync_membership)
.with(%w[U00001 U00002 U00003])
end
it 'returns a `SyncResult`' do
stub_clients
expect(subject.sync!).to be_a(ReleaseTools::ReleaseManagers::SyncResult)
end
end
shared_examples 'a client on multiple services' do |delegated_method|
before { stub_schedule }
it 'syncs dev usernames' do
client = clients[:dev]
subject.send(delegated_method, 'new-team-member-ops')
expect(client).to have_received(delegated_method)
.with('new-team-member-dev')
end
it 'syncs production usernames' do
client = clients[:production]
subject.send(delegated_method, 'new-team-member-ops')
expect(client).to have_received(delegated_method)
.with('new-team-member')
end
it 'syncs ops usernames' do
client = clients[:ops]
subject.send(delegated_method, 'new-team-member-ops')
expect(client).to have_received(delegated_method)
.with('new-team-member-ops')
end
it 'syncs slack usernames' do
client = clients[:slack]
subject.send(delegated_method, 'new-team-member-ops')
expect(client).to have_received(delegated_method)
.with('U00002')
end
it 'returns a `SyncResult`' do
stub_clients
expect(subject.sync!).to be_a(ReleaseTools::ReleaseManagers::SyncResult)
end
it 'raises ArgumentError for unknown users' do
clients = stub_clients
expect do
subject.send(delegated_method, 'not-in-release-managers.yml')
end.to raise_error(ArgumentError, 'Unknown user not-in-release-managers.yml')
clients.each_value do |client|
expect(client).not_to have_received(delegated_method)
end
end
end
describe '#join' do
it_behaves_like 'a client on multiple services', :join
end
describe '#leave' do
it_behaves_like 'a client on multiple services', :leave
end
describe described_class::User do
describe 'initialize' do
it 'raises ArgumentError when no `gitlab.com` value is provided' do
expect { described_class.new('foo', bar: :baz) }
.to raise_error(ArgumentError, /gitlab\.com/)
end
end
end
end