diff --git a/src/main/java/jenkins/plugins/slack/ActiveNotifier.java b/src/main/java/jenkins/plugins/slack/ActiveNotifier.java index 03ab2ecd..ba77a8f6 100755 --- a/src/main/java/jenkins/plugins/slack/ActiveNotifier.java +++ b/src/main/java/jenkins/plugins/slack/ActiveNotifier.java @@ -19,11 +19,15 @@ import org.apache.commons.lang.StringUtils; import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static java.util.logging.Level.INFO; import static java.util.logging.Level.SEVERE; @@ -216,6 +220,8 @@ String getBuildStatusMessage(AbstractBuild r, boolean includeTestSummary, boolea public static class MessageBuilder { + private static final Pattern aTag = Pattern.compile("(?i)]+)>(.+?)"); + private static final Pattern href = Pattern.compile("\\s*(?i)href\\s*=\\s*(\"([^\"]*\")|'[^']*'|([^'\">\\s]+))"); private static final String STARTING_STATUS_MESSAGE = "Starting...", BACK_TO_NORMAL_STATUS_MESSAGE = "Back to normal", STILL_FAILING_STATUS_MESSAGE = "Still Failing", @@ -383,7 +389,7 @@ private String createBackToNormalDurationString(){ return Util.getTimeSpanString(backToNormalDuration); } - public String escape(String string) { + private String escapeCharacters(String string) { string = string.replace("&", "&"); string = string.replace("<", "<"); string = string.replace(">", ">"); @@ -391,6 +397,26 @@ public String escape(String string) { return string; } + private String[] extractReplaceLinks(Matcher aTag, StringBuffer sb) { + int size = 0; + List links = new ArrayList(); + while (aTag.find()) { + Matcher url = href.matcher(aTag.group(1)); + if (url.find()) { + aTag.appendReplacement(sb,String.format("{%s}", size++)); + links.add(String.format("<%s|%s>", url.group(1).replaceAll("\"", ""), aTag.group(2))); + } + } + aTag.appendTail(sb); + return links.toArray(new String[size]); + } + + public String escape(String string) { + StringBuffer pattern = new StringBuffer(); + String[] links = extractReplaceLinks(aTag.matcher(string), pattern); + return MessageFormat.format(escapeCharacters(pattern.toString()), links); + } + public String toString() { return message.toString(); } diff --git a/src/test/java/jenkins/plugins/slack/workflow/MessageBuilderTest.java b/src/test/java/jenkins/plugins/slack/workflow/MessageBuilderTest.java new file mode 100644 index 00000000..1fa93cd7 --- /dev/null +++ b/src/test/java/jenkins/plugins/slack/workflow/MessageBuilderTest.java @@ -0,0 +1,66 @@ +package jenkins.plugins.slack.workflow; + +import hudson.model.FreeStyleBuild; +import hudson.model.FreeStyleProject; +import hudson.model.ItemGroup; +import jenkins.plugins.slack.ActiveNotifier; +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.Mockito; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.ExecutionException; + +@RunWith(Parameterized.class) +public class MessageBuilderTest extends TestCase { + + private ActiveNotifier.MessageBuilder messageBuilder; + private String expectedResult; + private FreeStyleBuild build; + + + @Before + @Override + public void setUp() throws IOException, ExecutionException, InterruptedException { + messageBuilder = new ActiveNotifier.MessageBuilder(null, build); + } + + public MessageBuilderTest(String projectDisplayName, String buildDisplayName, String expectedResult) { + this.build = Mockito.mock(FreeStyleBuild.class); + FreeStyleProject project = Mockito.mock(FreeStyleProject.class); + + Mockito.when(build.getProject()).thenReturn(project); + Mockito.when(build.getDisplayName()).thenReturn(buildDisplayName); + + ItemGroup ig = Mockito.mock(ItemGroup.class); + Mockito.when(ig.getFullDisplayName()).thenReturn(""); + Mockito.when(project.getParent()).thenReturn(ig); + Mockito.when(project.getDisplayName()).thenReturn(projectDisplayName); + + this.expectedResult = expectedResult; + + } + + @Parameterized.Parameters + public static Collection businessTypeKeys() { + return Arrays.asList(new Object[][]{ + {"", "", " - "}, + {"project", "#43 Started by changes from Bob", "project - #43 Started by changes from Bob "}, + {"project", "#541 #125 Bug", + "project - #541 "}, + {"project", "#541 Bold Project", "project - #541 <b>Bold Project</b> "}, + {"project", "#541 bob", "project - #541 <a no-url>bob</a> "} + }); + } + + @Test + public void testStartMessage() { + assertEquals(expectedResult, messageBuilder.toString()); + } + +}