package se.bjurr.prnfb.listener; import static com.atlassian.bitbucket.pull.PullRequestAction.OPENED; import static com.atlassian.bitbucket.pull.PullRequestState.DECLINED; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Lists.newArrayList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; import static se.bjurr.prnfb.listener.PrnfbPullRequestAction.APPROVED; import static se.bjurr.prnfb.listener.PrnfbPullRequestAction.RESCOPED_FROM; import static se.bjurr.prnfb.listener.PrnfbPullRequestEventListener.setInvoker; import static se.bjurr.prnfb.settings.PrnfbNotificationBuilder.prnfbNotificationBuilder; import static se.bjurr.prnfb.settings.PrnfbSettingsDataBuilder.prnfbSettingsDataBuilder; import static se.bjurr.prnfb.settings.TRIGGER_IF_MERGE.ALWAYS; import static se.bjurr.prnfb.settings.TRIGGER_IF_MERGE.CONFLICTING; import static se.bjurr.prnfb.settings.TRIGGER_IF_MERGE.NOT_CONFLICTING; import java.net.URI; import java.net.URISyntaxException; import java.util.List; import java.util.concurrent.ExecutorService; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import com.atlassian.bitbucket.event.pull.PullRequestCommentAddedEvent; import com.atlassian.bitbucket.event.pull.PullRequestEvent; import com.atlassian.bitbucket.project.Project; import com.atlassian.bitbucket.pull.PullRequest; import com.atlassian.bitbucket.pull.PullRequestRef; import com.atlassian.bitbucket.pull.PullRequestService; import com.atlassian.bitbucket.repository.Repository; import com.google.common.base.Function; import se.bjurr.prnfb.http.ClientKeyStore; import se.bjurr.prnfb.http.HttpResponse; import se.bjurr.prnfb.http.Invoker; import se.bjurr.prnfb.http.UrlInvoker; import se.bjurr.prnfb.service.PrnfbRenderer; import se.bjurr.prnfb.service.PrnfbRendererFactory; import se.bjurr.prnfb.service.SettingsService; import se.bjurr.prnfb.settings.PrnfbNotification; import se.bjurr.prnfb.settings.PrnfbSettingsData; import se.bjurr.prnfb.settings.ValidationException; public class PrnfbPullRequestEventListenerTest { private final ClientKeyStore clientKeyStore = null; private final ExecutorService executorService = new FakeExecutorService(); @Mock private PullRequestRef fromRef; private final List<UrlInvoker> invokedUrls = newArrayList(); private PrnfbNotification notification1; private PrnfbNotification notification2; private PrnfbSettingsData pluginSettingsData; @Mock private PrnfbRendererFactory prnfbRendererFactory; @Mock private PullRequest pullRequest; @Mock private PullRequestEvent pullRequestOpenedEvent; @Mock private PullRequestService pullRequestService; @Mock private PrnfbRenderer renderer; @Mock private SettingsService settingsService; private Boolean shouldAcceptAnyCertificate; private PrnfbPullRequestEventListener sut; @Mock private PullRequestRef toRef; private void assertInvokedUrls(String... expectedUrls) { Iterable<String> urls = transform( invokedUrls, new Function<UrlInvoker, String>() { @Override public String apply(UrlInvoker input) { return input.getUrlParam(); } }); assertThat(urls) // .containsOnly(expectedUrls); } @Before public void before() throws ValidationException { initMocks(this); sut = new PrnfbPullRequestEventListener( prnfbRendererFactory, pullRequestService, executorService, settingsService); setInvoker( new Invoker() { @Override public HttpResponse invoke(UrlInvoker urlInvoker) { HttpResponse response = null; try { response = new HttpResponse(new URI("http://fake.com/"), 200, ""); } catch (URISyntaxException e) { e.printStackTrace(); } urlInvoker.setResponse(response); invokedUrls.add(urlInvoker); return response; } }); when(pullRequest.getFromRef()) // .thenReturn(fromRef); when(pullRequest.getFromRef().getLatestCommit()) // .thenReturn("latestCFrom"); when(pullRequest.getFromRef().getId()) // .thenReturn("IFrom"); when(pullRequest.getToRef()) // .thenReturn(toRef); when(pullRequest.getToRef().getLatestCommit()) // .thenReturn("latestCTo"); when(pullRequest.getToRef().getId()) // .thenReturn("ITo"); when(pullRequestOpenedEvent.getPullRequest()) // .thenReturn(pullRequest); when(pullRequestOpenedEvent.getPullRequest().isClosed()) // .thenReturn(false); when(pullRequestOpenedEvent.getAction()) // .thenReturn(OPENED); pluginSettingsData = prnfbSettingsDataBuilder() // .build(); when(settingsService.getPrnfbSettingsData()) // .thenReturn(pluginSettingsData); notification1 = prnfbNotificationBuilder() // .withUrl("http://not1.com/") // .withTrigger(PrnfbPullRequestAction.OPENED) // .build(); notification2 = prnfbNotificationBuilder(notification1) // .withUrl("http://not2.com/") // .build(); List<PrnfbNotification> notifications = newArrayList(notification1, notification2); when(settingsService.getNotifications()) // .thenReturn(notifications); when(prnfbRendererFactory.create(any(), any(), any(), any(), any())) // .thenReturn(renderer); when(renderer.render(any(), any(), any(), any())) // .thenAnswer( new Answer<String>() { @Override public String answer(InvocationOnMock invocation) throws Throwable { return (String) invocation.getArguments()[0]; } }); } @Test public void testThatCommentOnClosedPRIsIgnored() { when(pullRequest.isClosed()) // .thenReturn(true); PullRequestCommentAddedEvent pullRequestEvent = mock(PullRequestCommentAddedEvent.class); when(pullRequestEvent.getPullRequest()) // .thenReturn(pullRequest); sut.handleEventAsync(pullRequestEvent); assertThat(invokedUrls) // .isEmpty(); } @Test public void testThatHeaderCanContainVariables() {} @Test public void testThatNotifiationIsNotTriggeredByActionIfAFilterIsNotMatching() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .withFilterRegexp("^abc$") // .withFilterString("bc") // .build(); PrnfbPullRequestAction pullRequestAction = RESCOPED_FROM; boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isFalse(); } @Test public void testThatNotifiationIsNotTriggeredByActionIfOnlyBuildingMergingAndItIsConflicting() { assertThat(sut.ignoreBecauseOfConflicting(ALWAYS, false)) // .isFalse(); assertThat(sut.ignoreBecauseOfConflicting(CONFLICTING, false)) // .isTrue(); assertThat(sut.ignoreBecauseOfConflicting(NOT_CONFLICTING, false)) // .isFalse(); assertThat(sut.ignoreBecauseOfConflicting(ALWAYS, true)) // .isFalse(); assertThat(sut.ignoreBecauseOfConflicting(CONFLICTING, true)) // .isFalse(); assertThat(sut.ignoreBecauseOfConflicting(NOT_CONFLICTING, true)) // .isTrue(); } @Test public void testThatNotifiationIsNotTriggeredByActionIfProjectNotSame() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .withProjectKey("pk") // .build(); PrnfbPullRequestAction pullRequestAction = RESCOPED_FROM; Repository repository = mock(Repository.class); when(toRef.getRepository()) // .thenReturn(repository); Project project = mock(Project.class); when(repository.getProject()) // .thenReturn(project); when(project.getKey()) // .thenReturn("pk2"); boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isFalse(); } @Test public void testThatNotifiationIsNotTriggeredByActionIfRepositoryNotSame() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .withRepositorySlug("repositorySlug123") // .build(); PrnfbPullRequestAction pullRequestAction = RESCOPED_FROM; Repository repository = mock(Repository.class); when(toRef.getRepository()) // .thenReturn(repository); when(repository.getSlug()) // .thenReturn("asdasd"); boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isFalse(); } @Test public void testThatNotifiationIsNotTriggeredByActionIfThatActionIsATriggerButStateIgnored() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .setTriggerIgnoreState(newArrayList(DECLINED)) // .build(); PrnfbPullRequestAction pullRequestAction = RESCOPED_FROM; when(pullRequest.getState()) // .thenReturn(DECLINED); boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isFalse(); } @Test public void testThatNotifiationIsNotTriggeredByActionIfThatActionIsNotATrigger() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .build(); PrnfbPullRequestAction pullRequestAction = APPROVED; boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isFalse(); } @Test public void testThatNotifiationIsTriggeredByActionIfAFilterIsMatching() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .withFilterRegexp("^abc$") // .withFilterString("abc") // .build(); PrnfbPullRequestAction pullRequestAction = RESCOPED_FROM; boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isTrue(); } @Test public void testThatNotifiationIsTriggeredByActionIfAFilterIsMatchingWhenTrimmed() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .withFilterRegexp(" ^abc$ ") // .withFilterString(" abc ") // .build(); PrnfbPullRequestAction pullRequestAction = RESCOPED_FROM; boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isTrue(); } @Test public void testThatNotifiationIsTriggeredByActionIfProjectSame() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .withProjectKey("pk2") // .build(); PrnfbPullRequestAction pullRequestAction = RESCOPED_FROM; Repository repository = mock(Repository.class); when(toRef.getRepository()) // .thenReturn(repository); Project project = mock(Project.class); when(repository.getProject()) // .thenReturn(project); when(project.getKey()) // .thenReturn("pk2"); boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isTrue(); } @Test public void testThatNotifiationIsTriggeredByActionIfRepositorySame() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .withRepositorySlug("repositorySlug123") // .build(); PrnfbPullRequestAction pullRequestAction = RESCOPED_FROM; Repository repository = mock(Repository.class); when(toRef.getRepository()) // .thenReturn(repository); when(repository.getSlug()) // .thenReturn("repositorySlug123"); boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isTrue(); } @Test public void testThatNotifiationIsTriggeredByActionIfThatActionIsATrigger() throws ValidationException { PrnfbNotification notification = prnfbNotificationBuilder() // .withTrigger(RESCOPED_FROM) // .withUrl("http://hej.com") // .build(); PrnfbPullRequestAction pullRequestAction = RESCOPED_FROM; boolean actual = sut.isNotificationTriggeredByAction( notification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate); assertThat(actual) // .isTrue(); } @Test public void testThatPullRequestOpenedCanTriggerNotification() { sut.handleEventAsync(pullRequestOpenedEvent); assertInvokedUrls("http://not1.com/", "http://not2.com/"); } }