spec/reviewlette_spec.rb in reviewlette-0.0.9 vs spec/reviewlette_spec.rb in reviewlette-1.0.0

- old
+ new

@@ -1,85 +1,183 @@ require 'spec_helper' describe Reviewlette do - subject { Reviewlette } + let(:instance) { described_class.new members: [member1, member2] } + subject { instance } - let(:reviewlette) { subject.new } + let(:member1) { double(name: 'test1', github_handle: 'pinky', trello_handle: 'trellotest1') } + let(:member2) { double(name: 'test2', github_handle: 'brain', trello_handle: 'trellotest2') } - let(:members_config) { { 'members' => [member1, member2] } } - let(:member1) { { 'name' => 'test1', 'suse_username' => 'test1', 'trello_username' => 'trellotest1' } } - let(:member2) { { 'name' => 'test2', 'suse_username' => 'test2', 'trello_username' => 'trellotest2' } } - let(:github_config) { { token: token, repos: [repo, repo2] } } let(:token) { '1234' } let(:repo) { 'SUSE/test' } let(:repo2) { 'SUSE/foo' } before do - allow(TrelloConnection).to receive(:new).and_return TrelloConnection - allow(GithubConnection).to receive(:new).with(repo, token).and_return GithubConnection + allow(described_class::TrelloConnection).to receive(:new).and_return described_class::TrelloConnection + allow(described_class::GithubConnection).to receive(:new).with(repo, token).and_return described_class::GithubConnection allow(YAML).to receive(:load_file).with(/github\.yml/).and_return github_config - allow(YAML).to receive(:load_file).with(/members\.yml/).and_return members_config end describe '.new' do it 'sets trello connections' do - expect(TrelloConnection).to receive(:new) - subject.new + expect(described_class::TrelloConnection).to receive(:new) + subject end end describe '.run' do it 'iterates over all open repositories and looks for unassigned pull requests' do github_config[:repos].each do |r| - expect(reviewlette).to receive(:check_repo).with(r, token) - reviewlette.check_repo(r, token) + expect(subject).to receive(:check_repo).with(r, token) + subject.check_repo(r, token) end end end describe '.check_repo' do + context 'invalid repo' do + it 'skips the repo' do + expect(described_class::GithubConnection).to receive(:repo_exists?).and_return false + expect { subject.check_repo(repo, token) }.to output(/does not exist/).to_stdout + end + end + it 'iterates over all open pull requests and extracts trello ids from name' do - expect(GithubConnection).to receive(:repo_exists?).and_return true - expect(GithubConnection).to receive(:unassigned_pull_requests).and_return([{number: 11, title: 'test_issue_12'}]) - expect(TrelloConnection).to receive(:find_card_by_id).with(12) + expect(described_class::GithubConnection).to receive(:repo_exists?).and_return true + expect(described_class::GithubConnection).to receive(:pull_requests).and_return([{number: 11, title: 'test_issue_12'}]) + expect(described_class::GithubConnection).to receive(:labels).and_return([]) + expect(described_class::TrelloConnection).to receive(:find_card_by_id).with(12) - reviewlette.check_repo(repo, token) + subject.check_repo(repo, token) end - it 'adds assignee and reviewer comment on github, adds comment on trello and moves card' do - card = Trello::Card.new + it 'iterates over all pull requests and skips those with no card id' do + expect(described_class::GithubConnection).to receive(:repo_exists?).and_return true + expect(described_class::GithubConnection).to receive(:pull_requests).and_return([{ number: 11, title: 'no card id' }]) + expect(described_class::GithubConnection).to receive(:labels).and_return([]) - expect(GithubConnection).to receive(:repo_exists?).and_return true - expect(GithubConnection).to receive(:unassigned_pull_requests).and_return([{number: 11, title: 'test_issue_12'}]) - expect(TrelloConnection).to receive(:find_card_by_id).with(12).and_return(card) - expect(reviewlette).to receive(:select_reviewer).and_return({'suse_username' => 'test', 'github_username' => 'testgit'}) + expect { subject.check_repo(repo, token) }.to output(/Pull request not assigned to a trello card/).to_stdout + end - expect(GithubConnection).to receive(:add_assignee).with(11, 'testgit') - expect(GithubConnection).to receive(:reviewer_comment).with(11, 'testgit', card) + it 'adds assignees and reviewers comment on github, adds comment on trello and moves card' do + card = Trello::Card.new + user = double(github_handle: 'testgit', trello_handle: 'testtrello') + pullrequest = { number: 11, title: 'test_issue_12', assignees: [] } - expect(TrelloConnection).to receive(:comment_on_card).with("@ will review https://github.com/SUSE/test/issues/11", card) - expect(TrelloConnection).to receive(:move_card_to_list).with(card, 'In review') + expect(described_class::GithubConnection).to receive(:repo_exists?).and_return true + expect(described_class::GithubConnection).to receive(:pull_requests).and_return([pullrequest]) + expect(described_class::GithubConnection).to receive(:labels).and_return([]) + expect(described_class::TrelloConnection).to receive(:find_card_by_id).with(12).and_return(card) + expect(subject).to receive(:select_reviewers).and_return([user]) - reviewlette.check_repo(repo, token) + expect(described_class::GithubConnection).to receive(:add_assignees).with(11, ['testgit']) + expect(described_class::GithubConnection).to receive(:comment_reviewers).with(11, [user], card) + + expect(described_class::TrelloConnection).to receive(:comment_reviewers).with(card, 'SUSE/test', 11, [user]) + expect(described_class::TrelloConnection).to receive(:move_card_to_list).with(card, 'In review') + + subject.check_repo(repo, token) end - end + context 'pull request with one reviewer but two wanted' do + it 'selects a second reviewer' do + card = Trello::Card.new + pullrequest = { number: 11, title: 'pr title 42', assignees: [OpenStruct.new({login: 'pinky'})] } + expect(described_class::GithubConnection).to receive(:repo_exists?).and_return true + expect(described_class::GithubConnection).to receive(:pull_requests).and_return([pullrequest]) + expect(described_class::GithubConnection).to receive(:labels).and_return(['2 reviewers']) + expect(described_class::TrelloConnection).to receive(:find_card_by_id).with(42).and_return(card) - describe '.select_reviewer' do - it 'excludes members on vacation' do - card = Trello::Card.new + expect(described_class::GithubConnection).to receive(:add_assignees).with(11, ['pinky', 'brain']) + expect(described_class::GithubConnection).to receive(:comment_reviewers).with(11, [member1, member2], card) + expect(described_class::TrelloConnection).to receive(:comment_reviewers).with(card, repo, 11, [member1, member2]) + expect(described_class::TrelloConnection).to receive(:move_card_to_list).with(card, 'In review') + expect(subject).to receive(:select_reviewers).with(card, 2, [member1]).and_return([member1, member2]) + subject.check_repo(repo, token) + end + end - allow(card).to receive(:members).and_return([]) - expect(Vacations).to receive(:members_on_vacation).and_return([member1['suse_username']]) - expect(reviewlette.select_reviewer(nil, card)).to eq(member2) + context 'pull request with two reviewers but no "2 reviewers" label' do + it 'keeps both reviewers' do + card = Trello::Card.new + pullrequest = { number: 11, title: 'pr title 42', assignees: [ OpenStruct.new({login: 'pinky'}), OpenStruct.new({login: 'brain'})] } + expect(described_class::GithubConnection).to receive(:repo_exists?).and_return true + expect(described_class::GithubConnection).to receive(:pull_requests).and_return([pullrequest]) + expect(described_class::GithubConnection).to receive(:labels).and_return([]) + expect(described_class::TrelloConnection).to receive(:find_card_by_id).with(42).and_return(card) + + expect(described_class::GithubConnection).not_to receive(:add_assignees) + expect(described_class::TrelloConnection).not_to receive(:move_card_to_list).with(card, 'In review') + subject.check_repo(repo, token) + end end + context 'pull request with already correct number of reviewers' do + it 'does not assign nor comment in GitHub or Trello' do + card = Trello::Card.new + pullrequest = { number: 11, title: 'pr title 42', assignees: [ OpenStruct.new({login: 'pinky'}), OpenStruct.new({login: 'pinky'})] } + expect(described_class::GithubConnection).to receive(:repo_exists?).and_return true + expect(described_class::GithubConnection).to receive(:pull_requests).and_return([pullrequest]) + expect(described_class::GithubConnection).to receive(:labels).and_return(['2 reviewers']) + expect(described_class::TrelloConnection).to receive(:find_card_by_id).with(42).and_return(card) + + expect(described_class::GithubConnection).not_to receive(:add_assignees) + expect(described_class::GithubConnection).not_to receive(:comment_reviewers) + expect(described_class::TrelloConnection).not_to receive(:comment_reviewers) + expect(described_class::TrelloConnection).not_to receive(:move_card_to_list).with(card, 'In review') + subject.check_repo(repo, token) + end + end + + it 'does not find a reviewer' do + card = Trello::Card.new + + expect(described_class::GithubConnection).to receive(:repo_exists?).and_return true + expect(described_class::GithubConnection).to receive(:pull_requests).and_return([{ number: 11, title: 'test_issue_12', assignees: [] }]) + expect(described_class::GithubConnection).to receive(:labels).and_return([]) + expect(described_class::TrelloConnection).to receive(:find_card_by_id).with(12).and_return(card) + expect(subject).to receive(:select_reviewers).and_return [] + + expect { subject.check_repo(repo, token) }.to output(/Could not find a reviewer/).to_stdout + end + + end + + describe '.select_reviewers' do it 'excludes the owner of the trello card' do card = Trello::Card.new + reviewers = [member1, member2] - allow(card).to receive_message_chain(:members, :map).and_return(['trellotest1']) - expect(Vacations).to receive(:members_on_vacation).and_return([]) - expect(reviewlette.select_reviewer(nil, card)).to eq(members_config['members'].last) + allow(card).to receive_message_chain(:members, :map).and_return(reviewers) + expect(subject.select_reviewers(card).size).to eq(1) + end + + it 'selects n reviewers' do + card = Trello::Card.new + + allow(card).to receive_message_chain(:members, :map).and_return([member1]) + expect(subject.select_reviewers(card, 2)).to match_array([member1, member2]) + end + + it 'selects only one reviewer if no second is available' do + card = Trello::Card.new + + allow(card).to receive_message_chain(:members, :map).and_return([member2.trello_handle]) + expect(subject.select_reviewers(card, 2)).to eq([member1]) + end + end + + describe '.how_many_should_review' do + subject { instance.how_many_should_review(labels) } + + context 'with "2 reviewers" label' do + let(:labels) { ['foo', '2 reviewers', 'bar'] } + it { is_expected.to eq(2) } + end + + context 'with no "2 reviewers" label' do + let(:labels) { ['foo', 'bar'] } + it { is_expected.to eq(1) } end end end