require "spec_helper" require "octopolo/pull_request_merger" module Octopolo module Scripts describe PullRequestMerger do let(:cli) { stub(:CLI) } let(:config) { stub(:Config, github_repo: "tstmedia/foo") } let(:pull_request_id) { 42 } let(:pull_request) { stub(:PullRequest, branch: "cool-feature", url: "http://example.com/") } let(:branch_type) { Git::DEPLOYABLE_PREFIX } let(:git) { stub(:git, deployable_branch: "deployable") } let(:options) { { :user_notifications => ['NickLaMuro', 'anfleene'] } } subject { PullRequestMerger.new(Git::DEPLOYABLE_PREFIX, 42, options) } before do subject.git = git subject.config = config subject.cli = cli end context "#pull_request" do before do subject.pull_request_id = pull_request_id end it "finds the PullRequest for the given ID" do GitHub::PullRequest.should_receive(:new).with(config.github_repo, pull_request_id) { pull_request } subject.pull_request.should == pull_request end it "caches the PullRequest" do GitHub::PullRequest.should_receive(:new).once { pull_request } subject.pull_request subject.pull_request end end context "#perform" do before do subject.pull_request_id = pull_request_id subject.pull_request = pull_request end it "checks out branch, merges the pull request's branch, and writes a comment" do git.stub(:if_clean).and_yield # do not yield, index is dirty subject.should_receive(:check_out_branch) subject.should_receive(:merge_pull_request) subject.should_receive(:comment_about_merge) subject.perform end it "does nothing if the index is dirty" do git.stub(:if_clean) # do not yield, index is dirty subject.should_not_receive(:check_out_branch) subject.should_not_receive(:merge_pull_request) subject.should_not_receive(:comment_about_merge) subject.perform end it "properly handles an invalid pull request ID" do git.should_receive(:if_clean).and_raise(GitHub::PullRequest::NotFound) cli.should_receive(:say).with("Unable to find pull request #{pull_request_id}. Please retry with a valid ID.") expect { subject.perform }.to raise_error end it "properly handles a failed merge" do git.should_receive(:if_clean).and_raise(Git::MergeFailed) cli.should_receive(:say).with("Merge failed. Please identify the source of this merge conflict resolve this conflict in your pull request's branch. NOTE: Merge conflicts resolved in the deployable branch are NOT used when deploying.") expect { subject.perform }.to raise_error end it "properly handles a failed checkout of branch" do git.should_receive(:if_clean).and_raise(Git::CheckoutFailed) git.should_receive(:latest_branch_for).with("deployable").and_return("deployable") cli.should_receive(:say).with("Checkout of #{git.deployable_branch} failed. Please contact Infrastructure to determine the cause.") expect { subject.perform }.to raise_error end it "properly handles a failed comment" do git.should_receive(:if_clean).and_raise(GitHub::PullRequest::CommentFailed) git.should_receive(:latest_branch_for).with("deployable").and_return("deployable") cli.should_receive(:say).with("Unable to write comment. Please navigate to #{pull_request.url} and add the comment, '#{subject.comment_body}'") expect { subject.perform }.to raise_error end end context "#check_out_branch" do let(:creator) { stub(:dated_branch_creator, branch_name: "new-deployable") } it "checks out the project's deployable branch" do git.should_receive(:check_out).with(git.deployable_branch) git.should_receive(:latest_branch_for).with("deployable").and_return("deployable") subject.check_out_branch end it "creates a new deployable branch if none exists, and checks it out" do git.should_receive(:latest_branch_for).with(Git::DEPLOYABLE_PREFIX).and_raise(Git::NoBranchOfType) DatedBranchCreator.should_receive(:perform).with(Git::DEPLOYABLE_PREFIX) { creator } git.should_receive(:check_out).with(creator.branch_name) cli.should_receive(:say).with("No deployable branch available. Creating one now.") subject.check_out_branch end end context "#merge_pull_request" do before do subject.pull_request = pull_request end it "merges the pull request into the checked-out branch" do git.should_receive(:merge).with(pull_request.branch) subject.merge_pull_request end end context "#comment_about_merge" do before do subject.pull_request = pull_request end it "submits a comment that the pull request was merged into the branch" do git.should_receive(:latest_branch_for).with("deployable").and_return("deployable") pull_request.should_receive(:write_comment).with(subject.comment_body) subject.comment_about_merge end end context "#comment_body" do it "contains the default comment body" do git.should_receive(:latest_branch_for).with("deployable").and_return("deployable") subject.comment_body.should == "Merged into #{git.deployable_branch}. /cc @NickLaMuro @anfleene" end end end end end