PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/test/java/com/atlassian/bitbucket/plugin/hooks/protectbranch/ProtectUnmergedBranchHookTest.java

https://bitbucket.org/atlassian/stash-protect-unmerged-branch-hook
Java | 150 lines | 116 code | 30 blank | 4 comment | 0 complexity | 7246d1110e66c3f5a05331f2f9e1707f MD5 | raw file
Possible License(s): Apache-2.0
  1. package com.atlassian.bitbucket.plugin.hooks.protectbranch;
  2. import com.atlassian.bitbucket.hook.repository.RepositoryHookContext;
  3. import com.atlassian.bitbucket.i18n.I18nService;
  4. import com.atlassian.bitbucket.i18n.SimpleI18nService;
  5. import com.atlassian.bitbucket.nav.NavBuilder;
  6. import com.atlassian.bitbucket.plugin.hooks.protectbranch.project.TestProjectBuilder;
  7. import com.atlassian.bitbucket.plugin.hooks.protectbranch.pull.TestPullRequestBuilder;
  8. import com.atlassian.bitbucket.plugin.hooks.protectbranch.util.TestPageUtils;
  9. import com.atlassian.bitbucket.project.Project;
  10. import com.atlassian.bitbucket.pull.*;
  11. import com.atlassian.bitbucket.repository.RefChange;
  12. import com.atlassian.bitbucket.repository.RefChangeType;
  13. import com.atlassian.bitbucket.repository.Repository;
  14. import com.atlassian.bitbucket.plugin.hooks.protectbranch.pull.TestPullRequestRefBuilder;
  15. import com.atlassian.bitbucket.plugin.hooks.protectbranch.repository.TestRefChangeBuilder;
  16. import com.atlassian.bitbucket.plugin.hooks.protectbranch.repository.TestRepositoryBuilder;
  17. import com.atlassian.bitbucket.setting.Settings;
  18. import com.atlassian.bitbucket.util.PageRequest;
  19. import com.atlassian.bitbucket.util.PageUtils;
  20. import org.junit.AfterClass;
  21. import org.junit.Before;
  22. import org.junit.Test;
  23. import java.util.Arrays;
  24. import static org.hamcrest.CoreMatchers.*;
  25. import static org.junit.Assert.assertFalse;
  26. import static org.junit.Assert.assertTrue;
  27. import static org.mockito.BDDMockito.*;
  28. import static org.mockito.Matchers.any;
  29. import static org.mockito.Mockito.mock;
  30. import static org.mockito.Mockito.verifyNoMoreInteractions;
  31. public class ProtectUnmergedBranchHookTest {
  32. public static final String TARGET_BRANCH = "target_branch";
  33. public static final String SOURCE_BRANCH = "feature/source_branch";
  34. public static final String RANDOM_BRANCH = "random_branch";
  35. public static final RefChange ADD_RANDOM_BRANCH = new TestRefChangeBuilder().refId(RANDOM_BRANCH).type(RefChangeType.ADD).build();
  36. public static final RefChange UPDATE_TARGET_BRANCH = new TestRefChangeBuilder().refId(TARGET_BRANCH).type(RefChangeType.UPDATE).build();
  37. public static final RefChange UPDATE_RANDOM_BRANCH = new TestRefChangeBuilder().refId(RANDOM_BRANCH).type(RefChangeType.UPDATE).build();
  38. public static final RefChange DELETE_TARGET_BRANCH = new TestRefChangeBuilder().refId(TARGET_BRANCH).type(RefChangeType.DELETE).build();
  39. public static final RefChange DELETE_SOURCE_BRANCH = new TestRefChangeBuilder().refId(SOURCE_BRANCH).type(RefChangeType.DELETE).build();
  40. public static final RefChange DELETE_RANDOM_BRANCH = new TestRefChangeBuilder().refId(RANDOM_BRANCH).type(RefChangeType.DELETE).build();
  41. private static final Project PROJECT = new TestProjectBuilder().key("PROJECT").build();
  42. private static final Repository REPOSITORY = new TestRepositoryBuilder().slug("REPO").project(PROJECT).build();
  43. private static final PullRequest TARGET_PULL_REQUEST = new TestPullRequestBuilder().id(1).state(PullRequestState.OPEN).toRef(new TestPullRequestRefBuilder().repository(REPOSITORY).build()).build();
  44. private static final PullRequest SOURCE_PULL_REQUEST = new TestPullRequestBuilder().id(2).state(PullRequestState.OPEN).toRef(new TestPullRequestRefBuilder().repository(REPOSITORY).build()).build();
  45. private static final Settings SETTINGS = mock(Settings.class);
  46. private static final RepositoryHookContext CONTEXT = new RepositoryHookContext(REPOSITORY, SETTINGS);
  47. private final PullRequestService pullRequestService = mock(PullRequestService.class);
  48. private final NavBuilder navBuilder = mock(NavBuilder.class, RETURNS_DEEP_STUBS);
  49. private final I18nService i18nService = new SimpleI18nService(SimpleI18nService.Mode.FORMAT_MESSAGES);
  50. private final StubHookResponse hookResponse = new StubHookResponse();
  51. private final ProtectUnmergedBranchHook hook = new ProtectUnmergedBranchHook(pullRequestService, i18nService, navBuilder);
  52. @AfterClass
  53. public static void verifyNoInteractionsWithSettings() {
  54. verifyNoMoreInteractions(SETTINGS);
  55. }
  56. @Before
  57. public void setup() {
  58. // Return an empty page for any find in direction call - we'll override this if needed
  59. given(pullRequestService.search(any(PullRequestSearchRequest.class), any(PageRequest.class)))
  60. .willReturn(PageUtils.<PullRequest>createEmptyPage(PageUtils.newRequest(0, 10)));
  61. // target branch is involved in PR1
  62. given(pullRequestService.search(refEq(new PullRequestSearchRequest.Builder()
  63. .repositoryAndBranch(PullRequestDirection.INCOMING, REPOSITORY.getId(), "refs/heads/" + TARGET_BRANCH)
  64. .state(PullRequestState.OPEN).build()), any(PageRequest.class)))
  65. .willReturn(TestPageUtils.pageContaining(TARGET_PULL_REQUEST));
  66. // source branch is involved in PR2
  67. given(pullRequestService.search(refEq(new PullRequestSearchRequest.Builder()
  68. .repositoryAndBranch(PullRequestDirection.OUTGOING, REPOSITORY.getId(), "refs/heads/" + SOURCE_BRANCH)
  69. .state(PullRequestState.OPEN).build()), any(PageRequest.class)))
  70. .willReturn(TestPageUtils.pageContaining(SOURCE_PULL_REQUEST));
  71. }
  72. @Test
  73. public void shouldRejectDeletionOfActivePullRequestTargetBranch() throws Exception {
  74. boolean receiveAllowed = hook.onReceive(CONTEXT, Arrays.asList(DELETE_TARGET_BRANCH), hookResponse);
  75. assertFalse("Attempt to delete active pull request target branch should not be allowed", receiveAllowed);
  76. }
  77. @Test
  78. public void shouldRejectDeletionOfActivePullRequestSourceBranch() throws Exception {
  79. boolean receiveAllowed = hook.onReceive(CONTEXT, Arrays.asList(DELETE_SOURCE_BRANCH), hookResponse);
  80. assertFalse("Attempt to delete active pull request source branch should not be allowed", receiveAllowed);
  81. }
  82. @Test
  83. public void shouldRejectDeletionOfActivePullRequestSourceAndTargetBranches() throws Exception {
  84. boolean receiveAllowed = hook.onReceive(CONTEXT, Arrays.asList(DELETE_TARGET_BRANCH, DELETE_SOURCE_BRANCH), hookResponse);
  85. assertFalse("Attempt to delete active pull request source and target branch should not be allowed", receiveAllowed);
  86. }
  87. @Test
  88. public void shouldAllowDeletionOfUnrelatedBranch() throws Exception {
  89. boolean receiveAllowed = hook.onReceive(CONTEXT, Arrays.asList(DELETE_RANDOM_BRANCH), hookResponse);
  90. assertTrue("Deleting branches is allowed if they are not connected to active pull requests", receiveAllowed);
  91. }
  92. @Test
  93. public void shouldRejectAnActiveBranchDeleteInterspersedWithOtherChanges() throws Exception {
  94. boolean receiveAllowed = hook.onReceive(CONTEXT, Arrays.asList(ADD_RANDOM_BRANCH, UPDATE_TARGET_BRANCH, DELETE_TARGET_BRANCH, UPDATE_RANDOM_BRANCH, DELETE_RANDOM_BRANCH), hookResponse);
  95. assertFalse("Attempt to delete active pull request target branch should not be allowed even if other, uninteresting changes are included", receiveAllowed);
  96. }
  97. @Test
  98. public void shouldAllowChangesToActiveBranch() throws Exception {
  99. boolean receiveAllowed = hook.onReceive(CONTEXT, Arrays.asList(UPDATE_TARGET_BRANCH), hookResponse);
  100. assertTrue("Changes to branches with active pull requests are allowed", receiveAllowed);
  101. }
  102. @Test
  103. public void shouldListAllBranchesAndActivePullRequestsOnErr() throws Exception {
  104. given(navBuilder.repo(REPOSITORY).pullRequest(1).buildAbsolute()).willReturn("http://url.to/project/repo/1");
  105. given(navBuilder.repo(REPOSITORY).pullRequest(2).buildAbsolute()).willReturn("http://url.to/project/repo/2");
  106. hook.onReceive(CONTEXT, Arrays.asList(DELETE_TARGET_BRANCH, DELETE_SOURCE_BRANCH), hookResponse);
  107. // also tests that we strip refs/heads if it exists (on source branch) but don't freak out if it doesn't (on target branch)
  108. hookResponse.assertStdErr(allOf(containsString("'target_branch'"),
  109. containsString("http://url.to/project/repo/1"),
  110. containsString("'feature/source_branch'"),
  111. containsString("http://url.to/project/repo/2")));
  112. hookResponse.assertStdOut(is(""));
  113. }
  114. @Test
  115. public void shouldNotSendAnyOutputForAllowedChanges() throws Exception {
  116. hook.onReceive(CONTEXT, Arrays.asList(ADD_RANDOM_BRANCH, UPDATE_TARGET_BRANCH, UPDATE_RANDOM_BRANCH, DELETE_RANDOM_BRANCH), hookResponse);
  117. hookResponse.assertStdOut(is(""));
  118. hookResponse.assertStdErr(is(""));
  119. }
  120. }