11const fs = require("fs");
2+ const { App } = require("@slack/bolt");
23const { JSDOM } = require("jsdom");
34const dotenv = require("dotenv");
5+ const path = require("path");
46
57dotenv.config();
68
@@ -9,40 +11,38 @@ const user2 = process.env.USER2;
911const user3 = process.env.USER3;
1012const user4 = process.env.USER4;
1113
12- const tapHtmlContent = fs.readFileSync("./tap-html.html", "utf8");
13- const dom = new JSDOM(tapHtmlContent);
14- const $ = require("jquery")(dom.window);
15-
16- const totalCount = $(".nav a:nth-child(2)")
17- .text()
18- .trim()
19- .replace("Total Count", "");
20- const totalPass = $(".nav a:nth-child(3)")
21- .text()
22- .trim()
23- .replace("Total Pass", "");
24- const totalFail = $(".nav a:nth-child(4)")
25- .text()
26- .trim()
27- .replace("Total Fail", "");
28-
29- const totalTime = $(".nav a:nth-child(1)")
30- .text()
31- .trim()
32- .replace("Total Time", "");
33-
34- const milliseconds = parseInt(totalTime.replace(/\D/g, ''), 10);
35- const totalSeconds = Math.floor(milliseconds / 1000);
36- const durationInMinutes = Math.floor(totalSeconds / 60);
37- const durationInSeconds = totalSeconds % 60;
38-
39- const passedTests = parseInt(totalPass, 10);
40- const totalTests = parseInt(totalCount, 10);
14+ const data = fs.readFileSync(path.join(__dirname, "tap-html.html"), "utf8");
15+ const dom = new JSDOM(data);
16+ const textarea = dom.window.document.querySelector(
17+ "#jest-html-reports-result-data"
18+ );
19+ const testResults = JSON.parse(textarea.textContent.trim());
20+
21+ const startTime = testResults.startTime;
22+ const endTime = Math.max(
23+ ...testResults.testResults.map((t) => t.perfStats.end)
24+ );
25+ const totalSeconds = (endTime - startTime) / 1000;
26+ const minutes = Math.floor(totalSeconds / 60);
27+ const seconds = (totalSeconds % 60).toFixed(2);
28+ const duration = `${minutes}m ${seconds}s`;
29+
30+ const summary = {
31+ totalSuites: testResults.numTotalTestSuites,
32+ passedSuites: testResults.numPassedTestSuites,
33+ failedSuites: testResults.numFailedTestSuites,
34+ totalTests: testResults.numTotalTests,
35+ passedTests: testResults.numPassedTests,
36+ failedTests: testResults.numFailedTests,
37+ skippedTests: testResults.numPendingTests + testResults.numTodoTests,
38+ pendingTests: testResults.numPendingTests,
39+ duration: duration,
40+ };
4141
4242const resultMessage =
43- passedTests === totalTests
44- ? `:white_check_mark: Success (${passedTests} / ${totalTests} Passed)`
45- : `:x: Failure (${passedTests} / ${totalTests} Passed)`;
43+ summary. passedTests === summary. totalTests
44+ ? `:white_check_mark: Success (${summary. passedTests} / ${summary. totalTests} Passed)`
45+ : `:x: Failure (${summary. passedTests} / ${summary. totalTests} Passed)`;
4646
4747const pipelineName = process.env.GO_PIPELINE_NAME;
4848const pipelineCounter = process.env.GO_PIPELINE_COUNTER;
@@ -51,42 +51,65 @@ const goCdServer = process.env.GOCD_SERVER;
5151const reportUrl = `http://${goCdServer}/go/files/${pipelineName}/${pipelineCounter}/sanity/1/sanity/test-results/tap-html.html`;
5252
5353let tagUsers = ``;
54- if (totalFail > 0) {
54+ if (summary.failedTests > 0) {
5555 tagUsers = `<@${user1}> <@${user2}> <@${user3}> <@${user4}>`;
5656}
5757
5858const slackMessage = {
5959 text: `Dev11, SDK-CDA Sanity
60- *Result:* ${resultMessage}. ${durationInMinutes}m ${durationInSeconds }s
61- *Failed Tests:* ${totalFail }
60+ *Result:* ${resultMessage}. ${summary.duration }s
61+ *Failed Tests:* ${summary.failedTests + summary.skippedTests }
6262<${reportUrl}|View Report>
6363${tagUsers}`,
6464};
6565
66- const slackWebhookUrl = process.env.SLACK_WEBHOOK_URL;
67-
68- const sendSlackMessage = async (message) => {
69- const payload = {
70- text: message,
71- };
66+ const app = new App({
67+ token: process.env.SLACK_BOT_TOKEN,
68+ signingSecret: process.env.SLACK_SIGNING_SECRET,
69+ });
7270
71+ const sendSlackMessage = async () => {
7372 try {
74- const response = await fetch(slackWebhookUrl, {
75- method: "POST",
76- headers: {
77- "Content-Type": "application/json",
78- },
79- body: JSON.stringify(payload),
73+ const result = await app.client.chat.postMessage({
74+ token: process.env.SLACK_BOT_TOKEN,
75+ channel: process.env.SLACK_CHANNEL2,
76+ text: slackMessage.text, // Ensure this is the full object
8077 });
8178
82- if (!response.ok ) {
83- throw new Error(`Error sending message to Slack: ${response.statusText}`);
79+ if (summary.failedTests > 0 ) {
80+ await sendFailureDetails(result.ts); // Pass the correct thread timestamp
8481 }
85-
86- console.log("Message sent to Slack successfully");
8782 } catch (error) {
88- console.error("Error:", error);
83+ console.error("Error sending Slack message:", error);
84+ }
85+ };
86+
87+ const sendFailureDetails = async (threadTs) => {
88+ const failedTestSuites = testResults.testResults.filter(
89+ (suite) => suite.numFailingTests > 0
90+ );
91+ if (failedTestSuites.length > 0) {
92+ let failureDetails = "*Failed Test Modules:*\n";
93+ for (const suite of failedTestSuites) {
94+ let modulePath = suite.testFilePath;
95+ let formattedModuleName = path
96+ .relative(__dirname, modulePath)
97+ .replace(/^test\//, "")
98+ .replace(/\.js$/, "")
99+ .replace(/\//g, " ");
100+ failureDetails += ` - ${formattedModuleName}: ${suite.numFailingTests} failed\n`;
101+ }
102+ try {
103+ await app.client.chat.postMessage({
104+ token: process.env.SLACK_BOT_TOKEN,
105+ channel: process.env.SLACK_CHANNEL2,
106+ text: failureDetails,
107+ thread_ts: threadTs,
108+ });
109+ } catch (error) {
110+ console.error("Error sending failure details:", error);
111+ }
89112 }
90113};
91114
92- sendSlackMessage(slackMessage.text);
115+ sendSlackMessage(slackMessage.text);
0 commit comments