diff --git a/src/main/java/com/devadmin/vicky/event/EventModelWrapper.java b/src/main/java/com/devadmin/vicky/event/EventModelWrapper.java
index 650381e..fb690c6 100644
--- a/src/main/java/com/devadmin/vicky/event/EventModelWrapper.java
+++ b/src/main/java/com/devadmin/vicky/event/EventModelWrapper.java
@@ -5,7 +5,7 @@
/**
* An event wrapper holding a model which describes the event.
*
- *
This allows listeners to not care about the implementation of the event model.
+ *
This allows listener to not care about the implementation of the event model.
*/
abstract class EventModelWrapper extends ApplicationEvent {
private T eventModel;
diff --git a/src/main/java/com/devadmin/vicky/format/SimpleTaskEventFormatter.java b/src/main/java/com/devadmin/vicky/format/SimpleTaskEventFormatter.java
index f02a838..fcecd90 100644
--- a/src/main/java/com/devadmin/vicky/format/SimpleTaskEventFormatter.java
+++ b/src/main/java/com/devadmin/vicky/format/SimpleTaskEventFormatter.java
@@ -28,7 +28,8 @@ public class SimpleTaskEventFormatter implements TaskEventFormatter {
private Properties issueTypeIdToIconsMapping;
private static final int COMMENT_CUT_LENGTH = 256; // all comments are cut off at this length for display
- private static final String DEFAULT_ICON_KEY = "default";
+ public static final String DEFAULT_ICON_KEY = "default";
+ static final String EMPTY_COMMENT = "This task does not contain comment";
/**
* composes basic part of message (without comment)
@@ -88,7 +89,7 @@ protected String getShortDescription(TaskEvent event) {
*/
private String getIcon(@NotNull Task task) {
String icon = issueTypeIdToIconsMapping.getProperty(task.getTypeId());
- if(icon == null){
+ if (icon == null) {
icon = issueTypeIdToIconsMapping.getProperty(DEFAULT_ICON_KEY);
}
return icon != null ? icon : "";
@@ -125,7 +126,7 @@ protected String getLastComment(TaskEvent event) {
Comment comment = task.getLastComment();
if (comment == null || comment.getBody() == null) {
- lastComment = "This task does not contain comment";
+ lastComment = EMPTY_COMMENT;
} else {
String truncatedComment = truncateComment(comment.getBody());
lastComment = truncatedComment.replace("[~", "@").replace("]", "");
diff --git a/src/main/java/com/devadmin/vicky/format/SummaryTaskEventFormatter.java b/src/main/java/com/devadmin/vicky/format/SummaryTaskEventFormatter.java
index 87a118f..cbe3d6d 100644
--- a/src/main/java/com/devadmin/vicky/format/SummaryTaskEventFormatter.java
+++ b/src/main/java/com/devadmin/vicky/format/SummaryTaskEventFormatter.java
@@ -19,7 +19,7 @@ public class SummaryTaskEventFormatter extends SimpleTaskEventFormatter {
@Override
public String format(TaskEvent event) {
final String lastComment = super.getLastComment(event);
- if (StringUtils.isNotBlank(lastComment)) {
+ if (StringUtils.isNotBlank(lastComment) && !lastComment.equals(EMPTY_COMMENT)) {
return String.format(
"%s %s %s ➠ %s",
super.formatBase(event),
diff --git a/src/main/java/com/devadmin/vicky/listener/AtReferenceListener.java b/src/main/java/com/devadmin/vicky/listener/AtReferenceListener.java
index f50785b..c33d358 100644
--- a/src/main/java/com/devadmin/vicky/listener/AtReferenceListener.java
+++ b/src/main/java/com/devadmin/vicky/listener/AtReferenceListener.java
@@ -36,6 +36,8 @@ public void onApplicationEvent(TaskEventModelWrapper eventWrapper) {
if (commentNotEmpty(event)) {
sendMessageToReferencedPersons(event);
+ } else{
+ log.warn("Ignore empty comment");
}
}
diff --git a/src/main/java/com/devadmin/vicky/listener/LabeledTaskListener.java b/src/main/java/com/devadmin/vicky/listener/LabeledTaskListener.java
index 3a2817d..277114d 100644
--- a/src/main/java/com/devadmin/vicky/listener/LabeledTaskListener.java
+++ b/src/main/java/com/devadmin/vicky/listener/LabeledTaskListener.java
@@ -51,7 +51,7 @@ private boolean shouldListenerReactOnEvent(TaskEvent event, TaskEventModelWrappe
private void sendMessage(TaskEvent event) {
for (String label : event.getTask().getLabels()) {
- log.info("Trying to send channel message about labeled task");
+ log.info("Trying to send channel message about labeled task {}", label);
messageService.sendChannelMessage(label, formatter.format(event));
}
}
diff --git a/src/main/java/com/devadmin/vicky/listener/ResolvedTaskListener.java b/src/main/java/com/devadmin/vicky/listener/ResolvedTaskListener.java
index 480f4d3..fe1b395 100644
--- a/src/main/java/com/devadmin/vicky/listener/ResolvedTaskListener.java
+++ b/src/main/java/com/devadmin/vicky/listener/ResolvedTaskListener.java
@@ -50,6 +50,8 @@ public void onApplicationEvent(TaskEventModelWrapper eventWrapper) {
* What we want is just to send notification on resolved task , also we check if eventWrapper contain all the data or we should skip it
*/
private boolean shouldListenerReactOnEvent(TaskEvent event, Task task, TaskEventModelWrapper eventWrapper) {
- return task.isResolved() && event.getType() != null && event.getType().equals(TaskEventType.UPDATED) && !this.shouldSkip(eventWrapper);
+ return task.isResolved() && event.getType() != null
+ && event.getType() == TaskEventType.UPDATED
+ && !this.shouldSkip(eventWrapper);
}
}
diff --git a/src/main/java/com/devadmin/vicky/model/jira/status/StatusModel.java b/src/main/java/com/devadmin/vicky/model/jira/status/StatusModel.java
index ff69f98..ad316ef 100644
--- a/src/main/java/com/devadmin/vicky/model/jira/status/StatusModel.java
+++ b/src/main/java/com/devadmin/vicky/model/jira/status/StatusModel.java
@@ -11,6 +11,8 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public class StatusModel {
+ public static final String RESOLVED = "Resolved 解決済";
+
@JsonProperty("self")
private String self;
diff --git a/src/main/java/com/devadmin/vicky/model/jira/task/IssueModel.java b/src/main/java/com/devadmin/vicky/model/jira/task/IssueModel.java
index 875c580..e55326c 100644
--- a/src/main/java/com/devadmin/vicky/model/jira/task/IssueModel.java
+++ b/src/main/java/com/devadmin/vicky/model/jira/task/IssueModel.java
@@ -1,7 +1,8 @@
package com.devadmin.vicky.model.jira.task;
-import com.devadmin.vicky.model.jira.comment.CommentModel;
import com.devadmin.vicky.model.jira.FieldModel;
+import com.devadmin.vicky.model.jira.comment.CommentModel;
+import com.devadmin.vicky.model.jira.status.StatusModel;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.beans.factory.annotation.Value;
@@ -96,7 +97,7 @@ public List getLabels() {
*/
@Override
public Boolean isResolved() {
- return "Resolved 解決済".equals(this.fields.getStatus().getName());
+ return StatusModel.RESOLVED.equals(this.fields.getStatus().getName());
}
@Override
diff --git a/src/main/java/com/devadmin/vicky/service/jira/JiraTaskServiceImpl.java b/src/main/java/com/devadmin/vicky/service/jira/JiraTaskServiceImpl.java
index 0ce087c..0e16d51 100644
--- a/src/main/java/com/devadmin/vicky/service/jira/JiraTaskServiceImpl.java
+++ b/src/main/java/com/devadmin/vicky/service/jira/JiraTaskServiceImpl.java
@@ -23,6 +23,32 @@ public class JiraTaskServiceImpl implements TaskService {
private final JiraClient jiraClient;
+ @Override
+ public List getBlockerTasks() {
+ try {
+ Issue.SearchResult searchResult = jiraClient.searchIssues(BLOCKER_TASKS_JQL);
+ return searchResult.issues.stream()
+ .map(JiraTaskServiceImpl::convertIssueToIssueModel)
+ .collect(Collectors.toList());
+ } catch (JiraException e) {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public Comment getLastCommentByTaskId(String taskId) {
+ Comment lastComment = null;
+ try {
+ List comments = jiraClient.getIssue(taskId).getComments();
+ if (!comments.isEmpty()) {
+ lastComment = comments.get(comments.size() - 1);
+ }
+ } catch (JiraException e) {
+ log.error("There was a problem getting issue from jira", e.getMessage());
+ }
+ return lastComment;
+ }
+
/**
* @param issue Issue
* @return issueModel which was converted from issue
@@ -114,30 +140,4 @@ private static UserModel getAssignee(Issue issue) {
return userModel;
}
-
- @Override
- public List getBlockerTasks() {
- try {
- Issue.SearchResult searchResult = jiraClient.searchIssues(BLOCKER_TASKS_JQL);
- return searchResult.issues.stream()
- .map(JiraTaskServiceImpl::convertIssueToIssueModel)
- .collect(Collectors.toList());
- } catch (JiraException e) {
- return Collections.emptyList();
- }
- }
-
- @Override
- public Comment getLastCommentByTaskId(String taskId) {
- Comment lastComment = null;
- try {
- List comments = jiraClient.getIssue(taskId).getComments();
- if (!comments.isEmpty()) {
- lastComment = comments.get(comments.size() - 1);
- }
- } catch (JiraException e) {
- log.error("There was a problem getting issue from jira", e.getMessage());
- }
- return lastComment;
- }
}
diff --git a/src/main/java/com/devadmin/vicky/service/slack/MessageService.java b/src/main/java/com/devadmin/vicky/service/slack/MessageService.java
index a0e9d6c..e0519ef 100644
--- a/src/main/java/com/devadmin/vicky/service/slack/MessageService.java
+++ b/src/main/java/com/devadmin/vicky/service/slack/MessageService.java
@@ -5,8 +5,6 @@
*/
package com.devadmin.vicky.service.slack;
-import com.devadmin.vicky.MessageServiceException;
-
/**
* A generic messaging service. Allows writing string messages to a named channel or privately to a
* person.
diff --git a/src/main/java/com/devadmin/vicky/service/slack/SlackMessageServiceImpl.java b/src/main/java/com/devadmin/vicky/service/slack/SlackMessageServiceImpl.java
index 4ead087..2c8127a 100644
--- a/src/main/java/com/devadmin/vicky/service/slack/SlackMessageServiceImpl.java
+++ b/src/main/java/com/devadmin/vicky/service/slack/SlackMessageServiceImpl.java
@@ -27,13 +27,18 @@ public class SlackMessageServiceImpl implements MessageService {
private final SlackProperties properties;
private final SlackApiEndpoints slackApiEndpoints;
private final RestTemplate restTemplate;
- @Value("${debug.message-service.additional-information:}")
- private String additionalMessageInformation;
+ private final String additionalMessageInformation;
- public SlackMessageServiceImpl(SlackProperties properties, SlackApiEndpoints slackApiEndpoints, RestTemplate restTemplate) {
+ public SlackMessageServiceImpl(
+ SlackProperties properties,
+ SlackApiEndpoints slackApiEndpoints,
+ RestTemplate restTemplate,
+ @Value("${debug.message-service.additional-information:}") final String additionalMessageInformation
+ ) {
this.properties = properties;
this.slackApiEndpoints = slackApiEndpoints;
this.restTemplate = restTemplate;
+ this.additionalMessageInformation = additionalMessageInformation;
}
/**
diff --git a/src/test/java/com/devadmin/vicky/test/TestTasks.java b/src/test/java/com/devadmin/vicky/test/TestTasks.java
new file mode 100644
index 0000000..a906b80
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/TestTasks.java
@@ -0,0 +1,80 @@
+package com.devadmin.vicky.test;
+
+import com.devadmin.vicky.model.jira.*;
+import com.devadmin.vicky.model.jira.changelog.ChangeLogModel;
+import com.devadmin.vicky.model.jira.changelog.JiraChangeLogItemModel;
+import com.devadmin.vicky.model.jira.comment.CommentModel;
+import com.devadmin.vicky.model.jira.status.StatusModel;
+import com.devadmin.vicky.model.jira.task.IssueModel;
+import com.devadmin.vicky.model.jira.task.IssueTypeModel;
+import com.devadmin.vicky.model.jira.task.TaskEventType;
+
+import java.util.Collections;
+
+/**
+ * Create test tasks.
+ */
+public final class TestTasks {
+
+ public static final String PROJECT = "vicky";
+
+ public static final String TEST_ID = "13";
+
+ public static JiraEventModel taskModel(final String creator, final String assignee, final String body) {
+ final AuthorModel authorModel = new AuthorModel();
+ authorModel.setName(creator);
+ authorModel.setDisplayName(creator);
+ authorModel.setEmailAddress(creator);
+
+ final CommentModel comment = new CommentModel();
+ comment.setBody(body);
+ comment.setAuthor(authorModel);
+
+
+ final IssueTypeModel issueTypeModel = new IssueTypeModel();
+ issueTypeModel.setId(TEST_ID);
+
+ final StatusModel statusModel = new StatusModel();
+ statusModel.setName(StatusModel.RESOLVED);
+ statusModel.setDescription("Bla bla");
+
+ final UserModel userModel = new UserModel();
+ userModel.setName(assignee);
+ userModel.setDisplayName(assignee);
+ userModel.setEmailAddress(assignee);
+
+ final ProjectModel projectModel = new ProjectModel();
+ projectModel.setName(PROJECT);
+
+ final FieldModel fieldModel = new FieldModel();
+ fieldModel.setIssueType(issueTypeModel);
+ fieldModel.setStatus(statusModel);
+ fieldModel.setAssignee(userModel);
+ fieldModel.setSummary("Everything is ok");
+ fieldModel.setProject(projectModel);
+
+ final IssueModel issueModel = new IssueModel();
+ issueModel.setId(TEST_ID);
+ issueModel.setKey("test key");
+ issueModel.setFields(fieldModel);
+
+
+ final JiraChangeLogItemModel logItemModel = new JiraChangeLogItemModel();
+ logItemModel.setField("assignee");
+ logItemModel.setTo(assignee);
+
+ final ChangeLogModel changeLogModel = new ChangeLogModel();
+ changeLogModel.setId(TEST_ID);
+ changeLogModel.setItems(Collections.singletonList(logItemModel));
+
+ final JiraEventModel testEventModel = new JiraEventModel();
+ testEventModel.setComment(comment);
+ testEventModel.setUser(userModel);
+ testEventModel.setIssue(issueModel);
+ testEventModel.setTimeStamp(System.currentTimeMillis());
+ testEventModel.setChangeLog(changeLogModel);
+ testEventModel.setType(TaskEventType.UPDATED);
+
+ return testEventModel;
+ }
+}
diff --git a/src/test/java/com/devadmin/vicky/test/format/AssignTaskEventFormatterTest.java b/src/test/java/com/devadmin/vicky/test/format/AssignTaskEventFormatterTest.java
new file mode 100644
index 0000000..cfa68e9
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/format/AssignTaskEventFormatterTest.java
@@ -0,0 +1,85 @@
+package com.devadmin.vicky.test.format;
+
+import com.devadmin.vicky.config.FormatConfig;
+import com.devadmin.vicky.format.AssignTaskEventFormatter;
+import com.devadmin.vicky.format.TaskEventFormatter;
+import com.devadmin.vicky.model.jira.JiraEventModel;
+import com.devadmin.vicky.test.TestTasks;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Properties;
+
+/**
+ * Test class for {@link AssignTaskEventFormatter}
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ classes = {
+ FormatConfig.class,
+ AssignTaskEventFormatter.class,
+ }
+)
+public class AssignTaskEventFormatterTest {
+
+ /**
+ * Formatter to use.
+ */
+ @Autowired
+ @Qualifier("AssignFormatter")
+ private TaskEventFormatter taskEventFormatter;
+
+ /**
+ * Mock properties.
+ */
+ @MockBean(name = "issueTypeIdToIconsMapping")
+ private Properties properties;
+
+
+ /**
+ * Init.
+ */
+ @Before
+ public void init() {
+ Mockito.when(this.properties.getProperty(TestTasks.TEST_ID))
+ .thenReturn("test icon");
+ }
+
+ /**
+ * Test correct format.
+ */
+ @Test
+ public void testFormat() {
+ final JiraEventModel jiraEventModel = TestTasks.taskModel("lollipop", "fin", "Hello world!");
+ Assert.assertThat(
+ this.taskEventFormatter.format(jiraEventModel),
+ CoreMatchers.is(
+ String.join(
+ "",
+ "fin assigned to you: test icon Resolved 解決済: Everything is ok @fin\n",
+ " lollipop ➠ Hello world!"
+ )
+ )
+ );
+ }
+
+ /**
+ * Test that format will fail without user.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testFailsWithoutUser() {
+ final JiraEventModel jiraEventModel = TestTasks.taskModel("lollipop", "fin", "Hello world!");
+ jiraEventModel.setUser(null);
+ this.taskEventFormatter.format(jiraEventModel);
+ }
+}
diff --git a/src/test/java/com/devadmin/vicky/test/SimpleTaskEventFormatterTest.java b/src/test/java/com/devadmin/vicky/test/format/SimpleTaskEventFormatterTest.java
similarity index 77%
rename from src/test/java/com/devadmin/vicky/test/SimpleTaskEventFormatterTest.java
rename to src/test/java/com/devadmin/vicky/test/format/SimpleTaskEventFormatterTest.java
index 81f82e9..03a31d1 100644
--- a/src/test/java/com/devadmin/vicky/test/SimpleTaskEventFormatterTest.java
+++ b/src/test/java/com/devadmin/vicky/test/format/SimpleTaskEventFormatterTest.java
@@ -1,21 +1,23 @@
-package com.devadmin.vicky.test;
+package com.devadmin.vicky.test.format;
import com.devadmin.vicky.config.FormatConfig;
import com.devadmin.vicky.format.SimpleTaskEventFormatter;
+import com.devadmin.vicky.format.TaskEventFormatter;
import com.devadmin.vicky.model.jira.task.Task;
import com.devadmin.vicky.model.jira.task.TaskEvent;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockReset;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Properties;
+import static com.devadmin.vicky.format.SimpleTaskEventFormatter.DEFAULT_ICON_KEY;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
@@ -23,14 +25,19 @@
@SpringBootTest(classes = {SimpleTaskEventFormatter.class, FormatConfig.class})
public class SimpleTaskEventFormatterTest {
+ /**
+ * Formatter to test.
+ * Use qualifier to avoid IDE warning
+ */
@Autowired
- private SimpleTaskEventFormatter simpleTaskEventFormatter;
+ @Qualifier("SimpleFormatter")
+ private TaskEventFormatter simpleTaskEventFormatter;
@SpyBean(name = "issueTypeIdToIconsMapping")
private Properties properties;
@Test
- public void testFormattedEventHasRightIcon(){
+ public void testFormattedEventHasRightIcon() {
//Arrange
Task task = mock(Task.class, RETURNS_DEEP_STUBS);
TaskEvent taskEvent = mock(TaskEvent.class);
@@ -42,26 +49,25 @@ public void testFormattedEventHasRightIcon(){
}
@Test
- public void testFormattedEventHasDefaultIcon(){
+ public void testFormattedEventHasDefaultIcon() {
//Arrange
Task task = mock(Task.class, RETURNS_DEEP_STUBS);
TaskEvent taskEvent = mock(TaskEvent.class);
when(task.getTypeId()).thenReturn("177");
when(taskEvent.getTask()).thenReturn(task);
-
//Act + Assert
assertThat(simpleTaskEventFormatter.format(taskEvent)).isEqualTo(":rocket: null: null @null\n null ➠ This task does not contain comment");
}
@Test
@DirtiesContext
- public void testFormattedEventHasEmptyIcon(){
+ public void testFormattedEventHasEmptyIcon() {
//Arrange
Task task = mock(Task.class, RETURNS_DEEP_STUBS);
TaskEvent taskEvent = mock(TaskEvent.class);
when(task.getTypeId()).thenReturn("177");
when(taskEvent.getTask()).thenReturn(task);
- when(properties.getProperty("default")).thenReturn(null);
+ when(properties.getProperty(DEFAULT_ICON_KEY)).thenReturn(null);
//Act + Assert
assertThat(simpleTaskEventFormatter.format(taskEvent)).isEqualTo(" null: null @null\n null ➠ This task does not contain comment");
diff --git a/src/test/java/com/devadmin/vicky/test/format/SummaryTaskEventFormatterTest.java b/src/test/java/com/devadmin/vicky/test/format/SummaryTaskEventFormatterTest.java
new file mode 100644
index 0000000..d5944ad
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/format/SummaryTaskEventFormatterTest.java
@@ -0,0 +1,93 @@
+package com.devadmin.vicky.test.format;
+
+import com.devadmin.vicky.config.FormatConfig;
+import com.devadmin.vicky.format.SummaryTaskEventFormatter;
+import com.devadmin.vicky.format.TaskEventFormatter;
+import com.devadmin.vicky.model.jira.JiraEventModel;
+import com.devadmin.vicky.test.TestTasks;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Properties;
+
+/**
+ * Test class for {@link com.devadmin.vicky.format.SummaryTaskEventFormatter}
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ classes = {
+ FormatConfig.class,
+ SummaryTaskEventFormatter.class,
+ }
+)
+public class SummaryTaskEventFormatterTest {
+
+ /**
+ * Formatter to use.
+ */
+ @Autowired
+ @Qualifier("SummaryFormatter")
+ private TaskEventFormatter taskEventFormatter;
+
+ /**
+ * Mock properties.
+ */
+ @MockBean(name = "issueTypeIdToIconsMapping")
+ private Properties properties;
+
+
+ /**
+ * Init.
+ */
+ @Before
+ public void init() {
+ Mockito.when(this.properties.getProperty(TestTasks.TEST_ID))
+ .thenReturn("test icon");
+ }
+
+ /**
+ * Test correct format.
+ */
+ @Test
+ public void testFormat() {
+ final JiraEventModel jiraEventModel = TestTasks.taskModel("lollipop", "fin", "Hello world!");
+ Assert.assertThat(
+ this.taskEventFormatter.format(jiraEventModel),
+ CoreMatchers.is(
+ String.join(
+ "",
+ "test icon Resolved 解決済: ",
+ "Everything is ok @fin Bla bla lollipop ➠ Hello world!"
+ )
+ )
+ );
+ }
+
+ /**
+ * Test correct format.
+ */
+ @Test
+ public void testFormatWithoutComment() {
+ final JiraEventModel jiraEventModel = TestTasks.taskModel("lollipop", "fin", "Hello world!");
+ jiraEventModel.setComment(null);
+ Assert.assertThat(
+ this.taskEventFormatter.format(jiraEventModel),
+ CoreMatchers.is(
+ String.join(
+ "",
+ "test icon Resolved 解決済: Everything is ok @fin Bla bla "
+ )
+ )
+ );
+ }
+}
diff --git a/src/test/java/com/devadmin/vicky/test/listener/AtReferenceListenerTest.java b/src/test/java/com/devadmin/vicky/test/listener/AtReferenceListenerTest.java
new file mode 100644
index 0000000..e45c716
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/listener/AtReferenceListenerTest.java
@@ -0,0 +1,178 @@
+package com.devadmin.vicky.test.listener;
+
+import com.devadmin.vicky.config.FormatConfig;
+import com.devadmin.vicky.event.TaskEventModelWrapper;
+import com.devadmin.vicky.format.SimpleTaskEventFormatter;
+import com.devadmin.vicky.format.TaskEventFormatter;
+import com.devadmin.vicky.listener.AtReferenceListener;
+import com.devadmin.vicky.model.jira.AuthorModel;
+import com.devadmin.vicky.model.jira.FieldModel;
+import com.devadmin.vicky.model.jira.JiraEventModel;
+import com.devadmin.vicky.model.jira.comment.CommentModel;
+import com.devadmin.vicky.model.jira.status.StatusModel;
+import com.devadmin.vicky.model.jira.task.IssueModel;
+import com.devadmin.vicky.model.jira.task.IssueTypeModel;
+import com.devadmin.vicky.service.slack.MessageService;
+import com.devadmin.vicky.service.slack.SlackMessageServiceImpl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * Test class for {@link AtReferenceListener}
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ classes = {
+ FormatConfig.class,
+ AtReferenceListener.class,
+ SimpleTaskEventFormatter.class,
+ SlackMessageServiceImpl.class,
+ ApplicationEventPublisher.class,
+ }
+)
+public class AtReferenceListenerTest {
+
+ /**
+ * Event publisher.
+ */
+ @Autowired
+ private ApplicationEventPublisher applicationEventPublisher;
+
+ /**
+ * Event formatter to test.
+ * Add qualifier to avoid warning from IDEA
+ */
+ @Autowired
+ @Qualifier("SimpleFormatter")
+ private TaskEventFormatter eventFormatter;
+
+ /**
+ * Mocked slack message sender.
+ */
+ @MockBean
+ private MessageService messageService;
+
+ /**
+ * Nobody will get message because reference format is incorrect.
+ */
+ @Test
+ public void testMessageWithInvalidReference() {
+ final JiraEventModel testEventModel = taskModel("Wrong reference format Lollipop");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendPrivateMessage(
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Nobody will get message because comment is null.
+ */
+ @Test
+ public void testSkipEmptyComment() {
+ final JiraEventModel testEventModel = taskModel("[~lollipop]");
+ testEventModel.setComment(null);
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendPrivateMessage(
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Test that if reference and author are the same, then don't send notification.
+ */
+ @Test
+ public void testTheSameReferenceAndAuthor() {
+ final JiraEventModel testEventModel = taskModel("serpento");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendPrivateMessage(
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Test that multiple users will receive private messages.
+ */
+ @Test
+ public void testMultipleReferences() {
+ final JiraEventModel testEventModel = taskModel("[~lollipop] and [~vvorski]");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, atLeastOnce())
+ .sendPrivateMessage(
+ "lollipop",
+ this.eventFormatter.format(testEventModel)
+ );
+ Mockito.verify(
+ this.messageService, atLeastOnce())
+ .sendPrivateMessage(
+ "vvorski",
+ this.eventFormatter.format(testEventModel)
+ );
+ }
+
+
+ /**
+ * Test that one user will receive private message.
+ */
+ @Test
+ public void shouldSendPrivateMessage() {
+ final JiraEventModel testEventModel = taskModel("[~Lollipop]");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, times(1))
+ .sendPrivateMessage(
+ "Lollipop",
+ this.eventFormatter.format(testEventModel)
+ );
+ }
+
+ /**
+ * Create task model with given body.
+ *
+ * @param body Body to use
+ * @return Test task
+ */
+ private static JiraEventModel taskModel(final String body) {
+ final AuthorModel authorModel = new AuthorModel();
+ authorModel.setName("serpento");
+
+ final CommentModel comment = new CommentModel();
+ comment.setBody(body);
+ comment.setAuthor(authorModel);
+
+ final IssueTypeModel issueTypeModel = new IssueTypeModel();
+ issueTypeModel.setId("13");
+
+ final StatusModel statusModel = new StatusModel();
+ statusModel.setName("test");
+ final FieldModel fieldModel = new FieldModel();
+ fieldModel.setIssueType(issueTypeModel);
+ fieldModel.setStatus(statusModel);
+ final IssueModel issueModel = new IssueModel();
+ issueModel.setId("13");
+ issueModel.setFields(fieldModel);
+ JiraEventModel testEventModel = new JiraEventModel();
+ testEventModel.setComment(comment);
+ testEventModel.setIssue(issueModel);
+
+ return testEventModel;
+ }
+}
diff --git a/src/test/java/com/devadmin/vicky/test/listener/CommentedTaskListenerTest.java b/src/test/java/com/devadmin/vicky/test/listener/CommentedTaskListenerTest.java
new file mode 100644
index 0000000..428060e
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/listener/CommentedTaskListenerTest.java
@@ -0,0 +1,103 @@
+package com.devadmin.vicky.test.listener;
+
+import com.devadmin.vicky.config.FormatConfig;
+import com.devadmin.vicky.event.TaskEventModelWrapper;
+import com.devadmin.vicky.format.SimpleTaskEventFormatter;
+import com.devadmin.vicky.format.TaskEventFormatter;
+import com.devadmin.vicky.listener.CommentedTaskListener;
+import com.devadmin.vicky.model.jira.JiraEventModel;
+import com.devadmin.vicky.service.slack.MessageService;
+import com.devadmin.vicky.service.slack.SlackMessageServiceImpl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static com.devadmin.vicky.test.TestTasks.taskModel;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ classes = {
+ FormatConfig.class,
+ CommentedTaskListener.class,
+ SimpleTaskEventFormatter.class,
+ SlackMessageServiceImpl.class,
+ ApplicationEventPublisher.class
+ }
+)
+public class CommentedTaskListenerTest {
+
+ /**
+ * Event publisher.
+ */
+ @Autowired
+ private ApplicationEventPublisher applicationEventPublisher;
+
+ /**
+ * Event formatter to test.
+ * Add qualifier to avoid warning from IDEA
+ */
+ @Autowired
+ @Qualifier("SimpleFormatter")
+ private TaskEventFormatter eventFormatter;
+
+ /**
+ * Mocked slack message sender.
+ */
+ @MockBean
+ private MessageService messageService;
+
+ /**
+ * test that listener sends notification.
+ */
+ @Test
+ public void testSendNotificationOnCreatedEvent() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "This is a simple comment");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, atLeastOnce())
+ .sendPrivateMessage(
+ "serpento",
+ this.eventFormatter.format(testEventModel)
+ );
+ }
+
+ /*
+ * Test that message service is not called if assignee and author are equal.
+ */
+ @Test
+ public void testWhenCommenterAndAssigneeAreSameUsers() {
+ final JiraEventModel testEventModel = taskModel("testUser", "testUser", "This is a simple comment");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendPrivateMessage(
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Skip message because comment is null.
+ */
+ @Test
+ public void testCommentIsNull() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "This is a simple comment");
+ testEventModel.setComment(null);
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendPrivateMessage(
+ any(),
+ any()
+ );
+ }
+}
diff --git a/src/test/java/com/devadmin/vicky/test/listener/CreatedTaskListenerTest.java b/src/test/java/com/devadmin/vicky/test/listener/CreatedTaskListenerTest.java
new file mode 100644
index 0000000..07eb671
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/listener/CreatedTaskListenerTest.java
@@ -0,0 +1,112 @@
+package com.devadmin.vicky.test.listener;
+
+import com.devadmin.vicky.config.FormatConfig;
+import com.devadmin.vicky.event.TaskEventModelWrapper;
+import com.devadmin.vicky.format.SummaryTaskEventFormatter;
+import com.devadmin.vicky.format.TaskEventFormatter;
+import com.devadmin.vicky.listener.CreatedTaskListener;
+import com.devadmin.vicky.model.jira.JiraEventModel;
+import com.devadmin.vicky.model.jira.task.TaskEventType;
+import com.devadmin.vicky.service.slack.MessageService;
+import com.devadmin.vicky.service.slack.SlackMessageServiceImpl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static com.devadmin.vicky.test.TestTasks.PROJECT;
+import static com.devadmin.vicky.test.TestTasks.taskModel;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+
+/**
+ * Test class for {@link CreatedTaskListener}
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ classes = {
+ FormatConfig.class,
+ CreatedTaskListener.class,
+ SummaryTaskEventFormatter.class,
+ SlackMessageServiceImpl.class,
+ ApplicationEventPublisher.class
+ }
+)
+@ActiveProfiles("test") // to load yml
+public class CreatedTaskListenerTest {
+
+ /**
+ * Event publisher.
+ */
+ @Autowired
+ private ApplicationEventPublisher applicationEventPublisher;
+
+ /**
+ * Event formatter to test.
+ * Add qualifier to avoid warning from IDEA
+ */
+ @Autowired
+ @Qualifier("SummaryFormatter")
+ private TaskEventFormatter eventFormatter;
+
+ /**
+ * Mocked slack message sender.
+ */
+ @MockBean
+ private MessageService messageService;
+
+ /**
+ * Test that channel will send notification.
+ */
+ @Test
+ public void testSendNotificationOnCreatedEvent() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ testEventModel.setType(TaskEventType.CREATED);
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, atLeastOnce())
+ .sendChannelMessage(
+ PROJECT,
+ this.eventFormatter.format(testEventModel)
+ );
+ }
+
+ /**
+ * Test that UPDATED type will be skipped.
+ */
+ @Test
+ public void testWrongEventType() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ testEventModel.setType(TaskEventType.UPDATED);
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendChannelMessage(
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Test that unsupported issue ids ae skipped
+ */
+ @Test
+ public void testSkipIssueId() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ testEventModel.getIssue().getFields().getIssueType().setId("228");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendChannelMessage(
+ any(),
+ any()
+ );
+ }
+}
diff --git a/src/test/java/com/devadmin/vicky/test/listener/LabeledTaskListenerTest.java b/src/test/java/com/devadmin/vicky/test/listener/LabeledTaskListenerTest.java
new file mode 100644
index 0000000..d510dd2
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/listener/LabeledTaskListenerTest.java
@@ -0,0 +1,117 @@
+package com.devadmin.vicky.test.listener;
+
+import com.devadmin.vicky.config.FormatConfig;
+import com.devadmin.vicky.event.TaskEventModelWrapper;
+import com.devadmin.vicky.format.SimpleTaskEventFormatter;
+import com.devadmin.vicky.format.TaskEventFormatter;
+import com.devadmin.vicky.listener.LabeledTaskListener;
+import com.devadmin.vicky.model.jira.JiraEventModel;
+import com.devadmin.vicky.model.jira.task.TaskEventType;
+import com.devadmin.vicky.service.slack.MessageService;
+import com.devadmin.vicky.service.slack.SlackMessageServiceImpl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.devadmin.vicky.test.TestTasks.taskModel;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+
+/**
+ * Test class for {@link LabeledTaskListener}
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ classes = {
+ FormatConfig.class,
+ LabeledTaskListener.class,
+ SimpleTaskEventFormatter.class,
+ SlackMessageServiceImpl.class,
+ ApplicationEventPublisher.class
+ }
+)
+public class LabeledTaskListenerTest {
+
+ /**
+ * Event publisher.
+ */
+ @Autowired
+ private ApplicationEventPublisher applicationEventPublisher;
+
+ /**
+ * Event formatter to test.
+ * Add qualifier to avoid warning from IDEA
+ */
+ @Autowired
+ @Qualifier("SimpleFormatter")
+ private TaskEventFormatter eventFormatter;
+
+ /**
+ * Mocked slack message sender.
+ */
+ @MockBean
+ private MessageService messageService;
+
+ /**
+ * Sip event if it doesn't have labels.
+ */
+ @Test
+ public void eventShouldNotBeHandledWithoutLabelsTest() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ testEventModel.getTask().getFields().setLabels(new String[0]);
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendChannelMessage(
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Test that channel skip updated type.
+ */
+ @Test
+ public void testSendNotificationOnCreatedEvent() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ testEventModel.setType(TaskEventType.UPDATED);
+ testEventModel.getTask().getFields().setLabels(new String[]{"first", "second"});
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendChannelMessage(
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Tests that the message was sent two times.
+ */
+ @Test
+ public void testMuptypleLabels() {
+ final List labels = Arrays.asList("first", "second");
+ final JiraEventModel testTaskEventModel = taskModel("serpento", "testUser", "Test task");
+ testTaskEventModel.getTask().getFields().setLabels(labels.toArray(new String[0]));
+ testTaskEventModel.setType(TaskEventType.CREATED);
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testTaskEventModel));
+ for (final String label : labels) {
+ Mockito.verify(
+ this.messageService, atLeastOnce())
+ .sendChannelMessage(
+ label,
+ this.eventFormatter.format(testTaskEventModel)
+ );
+ }
+ }
+}
diff --git a/src/test/java/com/devadmin/vicky/test/listener/PMOnAssignListenerTest.java b/src/test/java/com/devadmin/vicky/test/listener/PMOnAssignListenerTest.java
new file mode 100644
index 0000000..f7ac847
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/listener/PMOnAssignListenerTest.java
@@ -0,0 +1,131 @@
+package com.devadmin.vicky.test.listener;
+
+import com.devadmin.vicky.config.FormatConfig;
+import com.devadmin.vicky.event.TaskEventModelWrapper;
+import com.devadmin.vicky.format.AssignTaskEventFormatter;
+import com.devadmin.vicky.format.TaskEventFormatter;
+import com.devadmin.vicky.listener.PMOnAssignListener;
+import com.devadmin.vicky.model.jira.JiraEventModel;
+import com.devadmin.vicky.model.jira.changelog.JiraChangeLogItemModel;
+import com.devadmin.vicky.service.slack.MessageService;
+import com.devadmin.vicky.service.slack.SlackMessageServiceImpl;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.devadmin.vicky.test.TestTasks.taskModel;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+
+/**
+ * Test fpr {@link com.devadmin.vicky.listener.PMOnAssignListener}
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ classes = {
+ FormatConfig.class,
+ PMOnAssignListener.class,
+ AssignTaskEventFormatter.class,
+ SlackMessageServiceImpl.class,
+ ApplicationEventPublisher.class
+ }
+)
+public class PMOnAssignListenerTest {
+
+ /**
+ * Event publisher.
+ */
+ @Autowired
+ private ApplicationEventPublisher applicationEventPublisher;
+
+ /**
+ * Event formatter to test.
+ * Add qualifier to avoid warning from IDEA
+ */
+ @Autowired
+ @Qualifier("AssignFormatter")
+ private TaskEventFormatter eventFormatter;
+
+ /**
+ * Mocked slack message sender.
+ */
+ @MockBean
+ private MessageService messageService;
+
+ /**
+ * Test that sends notification.
+ */
+ @Test
+ public void testSendNotificationOnCreatedEvent() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, atLeastOnce())
+ .sendPrivateMessage(
+ "testUser",
+ this.eventFormatter.format(testEventModel)
+ );
+ }
+
+ /**
+ * Test that not assignee field is skipped.
+ */
+ @Test
+ public void testNotAssigneeEvent() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ ((JiraChangeLogItemModel) testEventModel.getChangeLog().getItems().get(0)).setField("not assignee");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendPrivateMessage(
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Test multiple change logs.
+ */
+ @Test
+ public void testMultipleChangeLogs() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ final List itemModels = this.multipleItems();
+
+ Assert.assertThat(itemModels.size(), CoreMatchers.is(2));
+
+ testEventModel.getChangeLog().setItems(itemModels);
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, times(2))
+ .sendPrivateMessage(
+ any(),
+ any()
+ );
+ }
+
+ private List multipleItems() {
+ final JiraChangeLogItemModel logItemModel = new JiraChangeLogItemModel();
+ logItemModel.setField("assignee");
+ logItemModel.setTo("testUser2");
+
+ final JiraChangeLogItemModel logItemModel2 = new JiraChangeLogItemModel();
+ logItemModel2.setField("assignee");
+ logItemModel2.setTo("testUser3");
+
+ return Arrays.asList(logItemModel, logItemModel2);
+ }
+
+}
diff --git a/src/test/java/com/devadmin/vicky/test/listener/ResolvedTestListenerTest.java b/src/test/java/com/devadmin/vicky/test/listener/ResolvedTestListenerTest.java
new file mode 100644
index 0000000..2758f2f
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/listener/ResolvedTestListenerTest.java
@@ -0,0 +1,111 @@
+package com.devadmin.vicky.test.listener;
+
+import com.devadmin.vicky.config.FormatConfig;
+import com.devadmin.vicky.event.TaskEventModelWrapper;
+import com.devadmin.vicky.format.SimpleTaskEventFormatter;
+import com.devadmin.vicky.format.TaskEventFormatter;
+import com.devadmin.vicky.listener.ResolvedTaskListener;
+import com.devadmin.vicky.model.jira.JiraEventModel;
+import com.devadmin.vicky.model.jira.task.TaskEventType;
+import com.devadmin.vicky.service.slack.MessageService;
+import com.devadmin.vicky.service.slack.SlackMessageServiceImpl;
+import com.devadmin.vicky.test.TestTasks;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static com.devadmin.vicky.test.TestTasks.taskModel;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+
+/**
+ * Test fpr {@link com.devadmin.vicky.listener.ResolvedTaskListener}
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ classes = {
+ FormatConfig.class,
+ ResolvedTaskListener.class,
+ SimpleTaskEventFormatter.class,
+ SlackMessageServiceImpl.class,
+ ApplicationEventPublisher.class
+ }
+)
+@ActiveProfiles("test")// to load yml
+public class ResolvedTestListenerTest {
+
+ /**
+ * Event publisher.
+ */
+ @Autowired
+ private ApplicationEventPublisher applicationEventPublisher;
+
+ /**
+ * Event formatter to test.
+ * Add qualifier to avoid warning from IDEA
+ */
+ @Autowired
+ @Qualifier("SimpleFormatter")
+ private TaskEventFormatter eventFormatter;
+
+ /**
+ * Mocked slack message sender.
+ */
+ @MockBean
+ private MessageService messageService;
+
+ /**
+ * Test that sends notification.
+ */
+ @Test
+ public void testSendNotificationOnCreatedEvent() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, atLeastOnce())
+ .sendChannelMessage(
+ TestTasks.PROJECT,
+ this.eventFormatter.format(testEventModel)
+ );
+ }
+
+ /**
+ * Test that listener skip non updated status.
+ */
+ @Test
+ public void testSkipByStatus() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ testEventModel.setType(TaskEventType.COMMENT);
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendChannelMessage(
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Test that listener skip non updated status.
+ */
+ @Test
+ public void testSkipUnsupportedId() {
+ final JiraEventModel testEventModel = taskModel("serpento", "testUser", "Test task");
+ testEventModel.getIssue().getFields().getIssueType().setId("228");
+ this.applicationEventPublisher.publishEvent(new TaskEventModelWrapper(testEventModel));
+ Mockito.verify(
+ this.messageService, never())
+ .sendChannelMessage(
+ any(),
+ any()
+ );
+ }
+}
diff --git a/src/test/java/com/devadmin/vicky/test/service/JiraServiceTest.java b/src/test/java/com/devadmin/vicky/test/service/JiraServiceTest.java
new file mode 100644
index 0000000..21ef603
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/service/JiraServiceTest.java
@@ -0,0 +1,162 @@
+package com.devadmin.vicky.test.service;
+
+import com.devadmin.vicky.model.jira.FieldModel;
+import com.devadmin.vicky.model.jira.task.Task;
+import com.devadmin.vicky.service.jira.JiraTaskServiceImpl;
+import com.devadmin.vicky.service.jira.TaskService;
+import net.rcarz.jiraclient.*;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * Test {@link JiraTaskServiceImpl}.
+ */
+public final class JiraServiceTest {
+
+ /**
+ * Id of empty comment.
+ */
+ private static final String EMPTY_COMMENT = "empty";
+
+ /**
+ * Id of existing comment.
+ */
+ private static final String EXISTING_COMMENT = "exist";
+
+ /**
+ * Id of comment that throws exception.
+ */
+ private static final String EXCEPTIONAL_COMMENT = "exception";
+
+ /**
+ * Jira service.
+ */
+ private TaskService taskService;
+
+ /**
+ * Init jira service.
+ *
+ * @throws JiraException if failed
+ */
+ @Before
+ public void init() throws JiraException {
+ this.taskService = new JiraTaskServiceImpl(this.prepareClient());
+ }
+
+ /**
+ * Test that service returns blocker tasks.
+ */
+ @Test
+ public void testBlockerTasks() {
+ final List blockerTasks = this.taskService.getBlockerTasks();
+ Assert.assertThat(
+ blockerTasks.size(),
+ CoreMatchers.is(1)
+ );
+ final FieldModel fields = blockerTasks.get(0).getFields();
+ Assert.assertNotNull(fields);
+ Assert.assertNotNull(fields.getAssignee());
+ Assert.assertNotNull(fields.getStatus());
+ Assert.assertNotNull(fields.getPriority());
+ }
+
+ /**
+ * Test that service returns comments.
+ */
+ @Test
+ public void testComments() {
+ Assert.assertNotNull(this.taskService.getLastCommentByTaskId(EXISTING_COMMENT));
+ Assert.assertNull(this.taskService.getLastCommentByTaskId(EMPTY_COMMENT));
+ Assert.assertNull(this.taskService.getLastCommentByTaskId(EXCEPTIONAL_COMMENT));
+ }
+
+ /**
+ * Prepare mocked jira client.
+ *
+ * @return Mocked jira client
+ * @throws JiraException if failed
+ */
+ private JiraClient prepareClient() throws JiraException {
+ final Issue.SearchResult searchResult = Mockito.mock(Issue.SearchResult.class);
+ final Issue issue = Mockito.mock(Issue.class);
+ this.prepareIssue(issue);
+ searchResult.issues = Collections.singletonList(issue);
+ final JiraClient jiraClient = Mockito.mock(JiraClient.class, RETURNS_DEEP_STUBS);
+ when(jiraClient.searchIssues(any())).thenReturn(searchResult);
+ when(jiraClient.getIssue(EMPTY_COMMENT).getComments()).thenReturn(Collections.emptyList());
+ when(jiraClient.getIssue(EXISTING_COMMENT).getComments()).thenReturn(Collections.singletonList(Mockito.mock(Comment.class)));
+ when(jiraClient.getIssue(EXCEPTIONAL_COMMENT)).thenThrow(new JiraException("Comment doesn't exist"));
+ return jiraClient;
+ }
+
+ /**
+ * Prepare mocked jira issue
+ *
+ * @param issue Mocked issue
+ */
+ private void prepareIssue(final Issue issue) {
+ final User user = Mockito.mock(User.class);
+ this.prepareUserMock(user);
+
+ final Status status = Mockito.mock(Status.class);
+ this.prepareStatus(status);
+
+ final Priority priority = Mockito.mock(Priority.class);
+ this.preparePriority(priority);
+
+ when(issue.getCreatedDate()).thenReturn(new Date());
+ when(issue.getUpdatedDate()).thenReturn(new Date());
+ when(issue.getLabels()).thenReturn(Arrays.asList("1", "2", "3"));
+ when(issue.getAssignee()).thenReturn(user);
+ when(issue.getPriority()).thenReturn(priority);
+ when(issue.getStatus()).thenReturn(status);
+ }
+
+ /**
+ * Prepare mocked jira priority.
+ *
+ * @param priority Mocked priority
+ */
+ private void preparePriority(final Priority priority) {
+ when(priority.getId()).thenReturn("1");
+ when(priority.getIconUrl()).thenReturn("example.com");
+ when(priority.getName()).thenReturn("Test");
+ when(priority.getSelf()).thenReturn("example.com");
+ }
+
+ /**
+ * Prepare mocked jira status.
+ *
+ * @param status Mocked status
+ */
+ private void prepareStatus(final Status status) {
+ when(status.getId()).thenReturn("1");
+ when(status.getDescription()).thenReturn("Test");
+ when(status.getIconUrl()).thenReturn("example.com");
+ when(status.getName()).thenReturn("Test");
+ when(status.getSelf()).thenReturn("example.com");
+ }
+
+ /**
+ * Prepare mocked jira user.
+ *
+ * @param user Mocked user
+ */
+ private void prepareUserMock(final User user) {
+ when(user.getId()).thenReturn("1");
+ when(user.getSelf()).thenReturn("example.com");
+ when(user.getName()).thenReturn("almas");
+ when(user.getEmail()).thenReturn("Lollipop@devadmin.com");
+ when(user.getDisplayName()).thenReturn("Lollipop");
+ }
+}
diff --git a/src/test/java/com/devadmin/vicky/test/service/SlackServiceTest.java b/src/test/java/com/devadmin/vicky/test/service/SlackServiceTest.java
new file mode 100644
index 0000000..20892ae
--- /dev/null
+++ b/src/test/java/com/devadmin/vicky/test/service/SlackServiceTest.java
@@ -0,0 +1,193 @@
+package com.devadmin.vicky.test.service;
+
+import com.devadmin.vicky.config.slack.SlackApiEndpoints;
+import com.devadmin.vicky.config.slack.SlackProperties;
+import com.devadmin.vicky.model.slack.Event;
+import com.devadmin.vicky.service.slack.MessageService;
+import com.devadmin.vicky.service.slack.SlackMessageServiceImpl;
+import me.ramswaroop.jbot.core.slack.models.User;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.*;
+
+/**
+ * Test {@link SlackMessageServiceImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public final class SlackServiceTest {
+
+ /**
+ * Email to test.
+ */
+ private static final String TEST_EMAIL = "Lollipop@devadmin.com";
+
+ /**
+ * User id to test.
+ */
+ private static final String TEST_ID = "1";
+
+ /**
+ * MessageService to test.
+ */
+ private MessageService messageService;
+
+ /**
+ * Slack properties with fake data.
+ */
+ private SlackProperties properties;
+
+ /**
+ * Mocked rest template.
+ */
+ @Mock
+ private RestTemplate restTemplate;
+
+ /**
+ * Mocked slack endpoints.
+ */
+ @Mock
+ private SlackApiEndpoints endpoints;
+
+ /**
+ * Init objects.
+ */
+ @Before
+ public void init() {
+ this.prepareProperties();
+ this.prepareEndpoints();
+ this.prepareRestTemplate();
+
+ this.messageService = new SlackMessageServiceImpl(
+ this.properties,
+ this.endpoints,
+ this.restTemplate,
+ ""
+ );
+ }
+
+ /**
+ * Test that service sends channel message using rest template.
+ */
+ @Test
+ public void testChannelMessage() {
+ this.messageService.sendChannelMessage("dev", "Good morning");
+ verify(this.restTemplate, atLeastOnce())
+ .postForEntity(
+ eq(this.endpoints.getChatPostMessageApi()),
+ isNull(),
+ eq(String.class),
+ eq(this.properties.getToken().getBot()),
+ any(),
+ any()
+ );
+ }
+
+ /**
+ * Test private message.
+ * Firstly gets list of users using rest template
+ * Then sends message to user with TEST_EMAIL using rest template
+ */
+ @Test
+ public void testPrivateMessage() {
+ this.messageService.sendPrivateMessage(TEST_EMAIL, "Good morning");
+ verify(this.restTemplate, atLeastOnce())
+ .postForEntity(
+ eq(this.endpoints.getUserListApi()),
+ isNull(),
+ eq(Event.class),
+ eq(this.properties.getToken().getBot())
+ );
+ verify(this.restTemplate, atLeastOnce())
+ .postForEntity(
+ eq(this.endpoints.getChatPostMessageApi()),
+ isNull(),
+ eq(String.class),
+ eq(this.properties.getToken().getBot()),
+ eq(TEST_ID),
+ any()
+ );
+ }
+
+ /**
+ * Prepare mocked rest template.
+ */
+ private void prepareRestTemplate() {
+ final Event event = this.prepareEvent();
+ //send Channel message
+ when(
+ this.restTemplate.postForEntity(
+ eq(this.endpoints.getChatPostMessageApi()),
+ isNull(),
+ eq(String.class),
+ eq(this.properties.getToken().getBot()),
+ any(),
+ any()
+ )
+ ).thenReturn(ResponseEntity.ok("Success"));
+ //send private message to get users
+ when(
+ this.restTemplate
+ .postForEntity(
+ eq(this.endpoints.getUserListApi()),
+ isNull(),
+ eq(Event.class),
+ eq(this.properties.getToken().getBot())
+ )
+ ).thenReturn(ResponseEntity.ok(event));
+ //send private message to one user from list
+ when(
+ this.restTemplate
+ .postForEntity(
+ eq(this.endpoints.getChatPostMessageApi()),
+ isNull(),
+ eq(String.class),
+ eq(this.properties.getToken().getBot()),
+ eq(TEST_ID),
+ any()
+ )
+ ).thenReturn(ResponseEntity.ok("Success"));
+ }
+
+ /**
+ * Prepare mocked event.
+ *
+ * @return Mocked event
+ */
+ private Event prepareEvent() {
+ final User user = Mockito.mock(User.class, RETURNS_DEEP_STUBS);
+ when(user.getProfile().getEmail()).thenReturn(TEST_EMAIL);
+ when(user.getId()).thenReturn(TEST_ID);
+ final Event event = Mockito.mock(Event.class, RETURNS_DEEP_STUBS);
+ when(event.getMembers()).thenReturn(new User[]{user});
+ return event;
+ }
+
+ /**
+ * Prepare mocked endpoints.
+ */
+ private void prepareEndpoints() {
+ when(this.endpoints.getChatPostMessageApi()).thenReturn("www.example.com");
+ when(this.endpoints.getUserListApi()).thenReturn("www.example.com");
+ }
+
+ /**
+ * Prepare properties with fake data.
+ */
+ private void prepareProperties() {
+ this.properties = new SlackProperties();
+ this.properties.setApiUrl("example.com");
+ final SlackProperties.Token token = new SlackProperties.Token();
+ token.setBot("bot");
+ this.properties.setToken(token);
+ }
+}
diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml
new file mode 100644
index 0000000..e258602
--- /dev/null
+++ b/src/test/resources/application-test.yml
@@ -0,0 +1,5 @@
+slack:
+ notification:
+ task-types:
+ createdTask: 13
+ resolvedTask: 13
\ No newline at end of file