diff --git a/pom.xml b/pom.xml
index 1ea7917..51a7594 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
com.katalon
katalon-studio-slack-plugin
- 1.0.6
+ 1.0.7
bundle
@@ -26,15 +26,14 @@
- com.github.seratch
- jslack
- 1.1.6
-
-
- org.slf4j
- slf4j-api
-
-
+ org.apache.httpcomponents
+ httpclient
+ 4.5.7
+
+
+ com.google.code.gson
+ gson
+ 2.8.5
diff --git a/src/main/java/com/katalon/plugin/slack/SlackEventListenerInitializer.java b/src/main/java/com/katalon/plugin/slack/SlackEventListenerInitializer.java
index 7fef87a..f5b6a4f 100644
--- a/src/main/java/com/katalon/plugin/slack/SlackEventListenerInitializer.java
+++ b/src/main/java/com/katalon/plugin/slack/SlackEventListenerInitializer.java
@@ -1,14 +1,7 @@
package com.katalon.plugin.slack;
-import java.io.IOException;
-
import org.osgi.service.event.Event;
-import com.github.seratch.jslack.Slack;
-import com.github.seratch.jslack.api.methods.SlackApiException;
-import com.github.seratch.jslack.shortcut.Shortcut;
-import com.github.seratch.jslack.shortcut.model.ApiToken;
-import com.github.seratch.jslack.shortcut.model.ChannelName;
import com.katalon.platform.api.event.EventListener;
import com.katalon.platform.api.event.ExecutionEvent;
import com.katalon.platform.api.exception.ResourceException;
@@ -32,25 +25,23 @@ public void registerListener(EventListener listener) {
if (ExecutionEvent.TEST_SUITE_FINISHED_EVENT.equals(event.getTopic())) {
ExecutionEvent eventObject = (ExecutionEvent) event.getProperty("org.eclipse.e4.data");
- Slack slack = Slack.getInstance();
- ApiToken token = ApiToken.of(authToken);
- Shortcut shortcut = slack.shortcut(token);
TestSuiteExecutionContext testSuiteContext = (TestSuiteExecutionContext) eventObject
.getExecutionContext();
TestSuiteStatusSummary testSuiteSummary = TestSuiteStatusSummary.of(testSuiteContext);
System.out.println("Slack: Start sending summary message to channel: " + channel);
- shortcut.postAsBot(ChannelName.of(channel),
- "Summary execution result of test suite: " + testSuiteContext.getSourceId()
- + "\nTotal test cases: " + Integer.toString(testSuiteSummary.getTotalTestCases())
- + "\nTotal passes: " + Integer.toString(testSuiteSummary.getTotalPasses())
- + "\nTotal failures: " + Integer.toString(testSuiteSummary.getTotalFailures())
- + "\nTotal errors: " + Integer.toString(testSuiteSummary.getTotalErrors())
- + "\nTotal skipped: " + Integer.toString(testSuiteSummary.getTotalSkipped()));
+ String message = "Summary execution result of test suite: " + testSuiteContext.getSourceId()
+ + "\nTotal test cases: " + Integer.toString(testSuiteSummary.getTotalTestCases())
+ + "\nTotal passes: " + Integer.toString(testSuiteSummary.getTotalPasses())
+ + "\nTotal failures: " + Integer.toString(testSuiteSummary.getTotalFailures())
+ + "\nTotal errors: " + Integer.toString(testSuiteSummary.getTotalErrors())
+ + "\nTotal skipped: " + Integer.toString(testSuiteSummary.getTotalSkipped());
+ SlackUtil.sendMessage(authToken, channel, message);
+
System.out.println("Slack: Summary message has been successfully sent");
}
- } catch (ResourceException | IOException | SlackApiException e) {
- e.printStackTrace(System.out);
+ } catch (ResourceException | SlackException e) {
+ e.printStackTrace(System.err);
}
});
}
diff --git a/src/main/java/com/katalon/plugin/slack/SlackException.java b/src/main/java/com/katalon/plugin/slack/SlackException.java
new file mode 100644
index 0000000..c5f1645
--- /dev/null
+++ b/src/main/java/com/katalon/plugin/slack/SlackException.java
@@ -0,0 +1,18 @@
+package com.katalon.plugin.slack;
+
+public class SlackException extends Exception {
+
+ private static final long serialVersionUID = 1171601532588814667L;
+
+ public SlackException(String message) {
+ super(message, null);
+ }
+
+ public SlackException(Throwable throwable) {
+ super("", throwable);
+ }
+
+ public SlackException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+}
diff --git a/src/main/java/com/katalon/plugin/slack/SlackPreferencePage.java b/src/main/java/com/katalon/plugin/slack/SlackPreferencePage.java
index d4dfa53..0383eb6 100644
--- a/src/main/java/com/katalon/plugin/slack/SlackPreferencePage.java
+++ b/src/main/java/com/katalon/plugin/slack/SlackPreferencePage.java
@@ -1,5 +1,6 @@
package com.katalon.plugin.slack;
+import org.apache.commons.lang3.StringUtils;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
@@ -15,10 +16,6 @@
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
-import com.github.seratch.jslack.Slack;
-import com.github.seratch.jslack.shortcut.Shortcut;
-import com.github.seratch.jslack.shortcut.model.ApiToken;
-import com.github.seratch.jslack.shortcut.model.ChannelName;
import com.katalon.platform.api.exception.ResourceException;
import com.katalon.platform.api.preference.PluginPreference;
import com.katalon.platform.api.service.ApplicationManager;
@@ -100,20 +97,19 @@ private void testSlackConnection(String token, String channel) {
lblConnectionStatus.setText("Connecting...");
thread = new Thread(() -> {
try {
- Slack slack = Slack.getInstance();
- ApiToken apiToken = ApiToken.of(token);
- Shortcut shortcut = slack.shortcut(apiToken);
- shortcut.postAsBot(ChannelName.of(channel), "This is a test message from Katalon Studio using Slack Plugin");
+ SlackUtil.sendMessage(token, channel, "This is a test message from Katalon Studio using Slack Plugin");
syncExec(() -> {
lblConnectionStatus
.setForeground(lblConnectionStatus.getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN));
lblConnectionStatus.setText("Connection success");
});
} catch (Exception e) {
+ e.printStackTrace(System.err);
syncExec(() -> {
lblConnectionStatus
.setForeground(lblConnectionStatus.getDisplay().getSystemColor(SWT.COLOR_DARK_RED));
- lblConnectionStatus.setText("Connection failed");
+ lblConnectionStatus
+ .setText("Connection failed. Reason: " + StringUtils.defaultString(e.getMessage()));
});
} finally {
syncExec(() -> btnTestConnection.setEnabled(true));
diff --git a/src/main/java/com/katalon/plugin/slack/SlackUtil.java b/src/main/java/com/katalon/plugin/slack/SlackUtil.java
new file mode 100644
index 0000000..b35f391
--- /dev/null
+++ b/src/main/java/com/katalon/plugin/slack/SlackUtil.java
@@ -0,0 +1,180 @@
+package com.katalon.plugin.slack;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+
+import com.google.gson.stream.JsonReader;
+
+public class SlackUtil {
+ public static final String RES_IS_OK = "isOk";
+
+ public static final String RES_ERROR_MSG = "errorMsg";
+
+ /**
+ * Send message to Slack for Team Collaboration
+ *
+ * @param msg String message to send
+ * @throws SlackException
+ */
+ public static void sendMessage(String token, String channel, String msg) throws SlackException {
+ try {
+ Map response = getResponseFromSendingMsg(buildSlackUri(token, channel, msg));
+
+ boolean isOk = (boolean) response.get(RES_IS_OK);
+ if (!isOk) {
+ String errorMsg = (String) response.get(RES_ERROR_MSG);
+ throw new SlackException(errorMsg);
+ }
+ } catch (IOException | URISyntaxException e) {
+ throw new SlackException(e);
+ }
+ }
+
+ /**
+ * Slack URI builder which will encode user info and message into URI
+ *
+ * @param token the authentication token
+ * @param channel Channel name
+ * @param username Bot name
+ * @param asIssuedTokenUser if true, Bot name will be ignore. Otherwise, message will be sent using Bot name
+ * @param msg Message to send
+ * @return URI
+ * @throws URISyntaxException
+ * @throws Exception UnsupportedEncodingException
+ * @see UnsupportedEncodingException
+ * @see Create Slack auth token
+ */
+ public static URI buildSlackUri(String token, String channel, String msg) throws URISyntaxException {
+ // scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]
+ URIBuilder uriBuilder = new URIBuilder().setScheme("https")
+ .setHost("slack.com")
+ .setPath("/api/chat.postMessage")
+ .addParameter("token", token)
+ .addParameter("channel", channel);
+ uriBuilder.addParameter("text", msg);
+ return uriBuilder.build();
+ }
+
+ /**
+ * Get response data from sending message to Slack
+ *
+ * @param uri URI to send GET request
+ * @return A Map object with 2 keys SlackUtil.RES_IS_OK and SlackUtil.RES_ERROR_MSG
+ * @throws ClientProtocolException
+ * @throws IOException
+ */
+ public static Map getResponseFromSendingMsg(URI uri) throws ClientProtocolException, IOException {
+ boolean isOk = false;
+ String errorMsg = null;
+
+ CloseableHttpClient httpclient = HttpClients.createDefault();
+ HttpGet httpget = new HttpGet(uri);
+ CloseableHttpResponse response = httpclient.execute(httpget);
+ try {
+ HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ InputStreamReader in = new InputStreamReader(entity.getContent());
+ try {
+ JsonReader reader = new JsonReader(in);
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ if (StringUtils.equals(name, "ok")) {
+ isOk = reader.nextBoolean();
+ } else if (StringUtils.equals(name, "error")) {
+ errorMsg = reader.nextString();
+ } else {
+ reader.skipValue(); // avoid some unhandled events
+ }
+ }
+ reader.endObject();
+ reader.close();
+ } finally {
+ in.close();
+ }
+ }
+ } finally {
+ response.close();
+ }
+
+ Map res = new HashMap();
+ res.put(RES_IS_OK, isOk);
+ res.put(RES_ERROR_MSG, errorMsg);
+ return res;
+ }
+
+ /**
+ * Slack Bold format text message
+ *
+ * @param msg String text message
+ * @return String Bold format text message
+ */
+ public String fmtBold(String msg) {
+ return "*" + msg + "*";
+ }
+
+ /**
+ * Slack Italic format text message
+ *
+ * @param msg String text message
+ * @return String Italic format text message
+ */
+ public String fmtItalic(String msg) {
+ return "_" + msg + "_";
+ }
+
+ /**
+ * Slack responded message status
+ */
+ public static class SlackMsgStatus {
+ private static SlackMsgStatus _instance;
+
+ private static Map msgMap;
+
+ public static SlackMsgStatus getInstance() {
+ if (_instance == null) {
+ _instance = new SlackMsgStatus();
+ }
+ return _instance;
+ }
+
+ public SlackMsgStatus() {
+ msgMap = new HashMap();
+ msgMap.put("channel_not_found", StringConstants.SLACK_ERROR_MSG_CHANNEL_NOT_FOUND);
+ msgMap.put("not_in_channel", StringConstants.SLACK_ERROR_MSG_NOT_IN_CHANNEL);
+ msgMap.put("is_archived", StringConstants.SLACK_ERROR_MSG_IS_ARCHIVED);
+ msgMap.put("msg_too_long", StringConstants.SLACK_ERROR_MSG_MSG_TOO_LONG);
+ msgMap.put("no_text", StringConstants.SLACK_ERROR_MSG_NO_TEXT);
+ msgMap.put("rate_limited", StringConstants.SLACK_ERROR_MSG_RATE_LIMITED);
+ msgMap.put("not_authed", StringConstants.SLACK_ERROR_MSG_NOT_AUTHED);
+ msgMap.put("invalid_auth", StringConstants.SLACK_ERROR_MSG_INVALID_AUTH);
+ msgMap.put("account_inactive", StringConstants.SLACK_ERROR_MSG_ACCOUNT_INACTIVE);
+ }
+
+ public Map getMsgMap() {
+ return msgMap;
+ }
+
+ public String getMsgDescription(String msgCode) {
+ if (getMsgMap().get(msgCode) == null) {
+ // No message description found
+ return msgCode;
+ }
+ return getMsgMap().get(msgCode);
+ }
+ }
+}
diff --git a/src/main/java/com/katalon/plugin/slack/StringConstants.java b/src/main/java/com/katalon/plugin/slack/StringConstants.java
new file mode 100644
index 0000000..4493bac
--- /dev/null
+++ b/src/main/java/com/katalon/plugin/slack/StringConstants.java
@@ -0,0 +1,14 @@
+package com.katalon.plugin.slack;
+
+
+public class StringConstants {
+ public static final String SLACK_ERROR_MSG_CHANNEL_NOT_FOUND = "Invalid value passed for Channel/Group.";
+ public static final String SLACK_ERROR_MSG_NOT_IN_CHANNEL = "Unable to post user messages to a channel/group they are not in.";
+ public static final String SLACK_ERROR_MSG_IS_ARCHIVED = "Channel/Group has been archived.";
+ public static final String SLACK_ERROR_MSG_MSG_TOO_LONG = "Message text is too long.";
+ public static final String SLACK_ERROR_MSG_NO_TEXT = "No message text provided.";
+ public static final String SLACK_ERROR_MSG_RATE_LIMITED = "Application has posted too many messages.";
+ public static final String SLACK_ERROR_MSG_NOT_AUTHED = "No authentication token provided.";
+ public static final String SLACK_ERROR_MSG_INVALID_AUTH = "Invalid authentication token.";
+ public static final String SLACK_ERROR_MSG_ACCOUNT_INACTIVE = "Authentication token is for a deleted user or team.";
+}