spec/lib/release_tools/release_managers/slack_client_spec.rb (157 lines of code) (raw):

# frozen_string_literal: true require 'spec_helper' describe ReleaseTools::ReleaseManagers::SlackClient do let(:slack_url) { described_class::SLACK_URL } let(:slack_token) { 'my-secret-token' } subject(:client) do ClimateControl.modify(SLACK_APP_ADMIN_TOKEN: slack_token) do described_class.new end end describe 'initialize' do context 'when SLACK_APP_ADMIN_TOKEN is not set' do let(:slack_token) { nil } it 'raises an error' do expect { client }.to raise_error('Missing environment variable `SLACK_APP_ADMIN_TOKEN`') end end it { expect { client }.not_to raise_error } end describe '#sync_membership' do let(:url) { "https://slack.com/api/usergroups.users.update" } it 'sends a POST request with IDS and the provided token' do user_ids = %w[UID1 UID2 UID3] request = stub_request(:post, url) .with( headers: { Authorization: "Bearer #{slack_token}", 'Content-Type': 'application/x-www-form-urlencoded' }, body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS, users: user_ids.join(',')) ).to_return(body: { ok: true }.to_json) client.sync_membership(user_ids) expect(request).to have_been_requested end context 'when the request is unauthorized' do it 'keeps track of the error' do request = stub_request(:post, url) .with( headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS, users: 'UID1') ).to_return(status: 401) client.sync_membership(%w[UID1]) expect(request).to have_been_requested expect(subject.sync_errors).to contain_exactly(an_instance_of(ReleaseTools::ReleaseManagers::Client::UnauthorizedError)) end end context 'when the request is forbidden' do it 'keeps track of the error' do request = stub_request(:post, url) .with(body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS, users: 'UID1')) .to_return(status: 403) client.sync_membership(%w[UID1]) expect(request).to have_been_requested expect(subject.sync_errors).to contain_exactly(an_instance_of(ReleaseTools::ReleaseManagers::Client::UnauthorizedError)) end end context "with a Bad request (or any other failure)" do it 'keeps track of the error' do request = stub_request(:post, url) .with(body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS, users: 'UID1')) .to_return(status: 400) client.sync_membership(%w[UID1]) expect(request).to have_been_requested expect(subject.sync_errors).to contain_exactly(an_instance_of(ReleaseTools::ReleaseManagers::Client::SyncError)) end end context 'when slack returns a failure' do it 'keeps track of the error' do user_ids = %w[NOTEXISTING] request = stub_request(:post, url) .with( headers: { Authorization: "Bearer #{slack_token}" }, body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS, users: 'NOTEXISTING') ).to_return(status: 200, body: { ok: false, error: 'invalid_users' }.to_json) client.sync_membership(user_ids) expect(request).to have_been_requested expect(subject.sync_errors).to contain_exactly(an_instance_of(ReleaseTools::ReleaseManagers::Client::SyncError)) expect(subject.sync_errors.first.message).to eq('invalid_users') end end end describe '#members' do let(:url) { "#{slack_url}/usergroups.users.list" } it 'sends a GET request with the provided token' do user_ids = %w[UID1 UID2 UID3] request = stub_request(:post, url) .with(headers: { Authorization: "Bearer #{slack_token}" }, body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS)) .to_return(body: { ok: true, users: user_ids }.to_json) expect(client.members).to eq(user_ids) expect(request).to have_been_requested end context 'when the request is unauthorized' do it 'keeps track of the error' do request = stub_request(:post, url) .with(body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS)) .to_return(status: 401) expect { client.members }.to raise_error(ReleaseTools::ReleaseManagers::Client::UnauthorizedError) expect(request).to have_been_requested end end context 'when the request is forbidden' do it 'keeps track of the error' do request = stub_request(:post, url) .with(body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS)) .to_return(status: 403) expect { client.members }.to raise_error(ReleaseTools::ReleaseManagers::Client::UnauthorizedError, 'Invalid token') expect(request).to have_been_requested end end context "with a Bad request (or any other failure)" do it 'keeps track of the error' do request = stub_request(:post, url).to_return(status: 400) expect { client.members }.to raise_error(ReleaseTools::ReleaseManagers::Client::SyncError, 'Bad Request') expect(request).to have_been_requested end end end describe '#join' do let(:user_ids) { %w[UID1 UID2 UID3] } let!(:members_request) do stub_request(:post, "#{slack_url}/usergroups.users.list") .with(body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS)) .to_return(body: { ok: true, users: user_ids }.to_json) end it 'adds a new user to the group' do new_user = 'UID4' expect(subject).to receive(:sync_membership).with(user_ids + [new_user]) client.join(new_user) expect(members_request).to have_been_requested end it 'does not add users already belonging to the group' do new_user = user_ids[0] expect(subject).not_to receive(:sync_membership) client.join(new_user) expect(members_request).to have_been_requested end end describe '#leave' do let(:user_ids) { %w[UID1 UID2 UID3] } let!(:members_request) do stub_request(:post, "#{slack_url}/usergroups.users.list") .with(body: hash_including(usergroup: ReleaseTools::Slack::RELEASE_MANAGERS)) .to_return(body: { ok: true, users: user_ids }.to_json) end it 'removes a user from the group' do new_user = user_ids[0] expect(subject).to receive(:sync_membership).with(user_ids - [new_user]) client.leave(new_user) expect(members_request).to have_been_requested end it 'does not remove users not belonging to the group' do new_user = 'UID4' expect(subject).not_to receive(:sync_membership) client.leave(new_user) expect(members_request).to have_been_requested end end end