@moroo/wdio-slack-reporter
Version:
Reporter from WebdriverIO using Incoming webhook and Web API to send results to Slack.
948 lines • 34.2 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var reporter_exports = {};
__export(reporter_exports, {
default: () => reporter_default
});
module.exports = __toCommonJS(reporter_exports);
var import_node_path = __toESM(require("node:path"), 1);
var import_node_util = __toESM(require("node:util"), 1);
var import_reporter = __toESM(require("@wdio/reporter"), 1);
var import_client = require("./client.js");
var import_constants = require("./constants.js");
var import_utils = require("./utils.js");
class SlackReporter extends import_reporter.default {
static resultsUrl;
_slackRequestQueue = [];
_thread;
_pendingSlackRequestCount = 0;
_stateCounts = {
passed: 0,
failed: 0,
skipped: 0
};
_useScenarioBasedStateCounts = false;
_webClient;
_webhookClient;
_channel;
_symbols;
_isCucumberFramework = false;
_title;
_notifyTestStartMessage = true;
_notifyFailedCase = true;
_uploadScreenshotOfFailedCase = true;
_notifyTestFinishMessage = true;
_notifyDetailResultThread = true;
_filterForDetailResults = [
"passed",
"failed",
"pending",
"skipped"
];
_isSynchronizing = false;
_interval;
_hasRunnerEnd = false;
_lastScreenshotBuffer = void 0;
_suiteUids = /* @__PURE__ */ new Set();
_orderedSuites = [];
_cucumberOrderedTests = [];
_indents = 0;
_suiteIndents = {};
_currentSuite;
constructor(options) {
super(Object.assign({ stdout: true }, options));
if (!options.slackOptions) {
import_utils.logger.error(import_constants.ERROR_MESSAGES.UNDEFINED_SLACK_OPTION);
import_utils.logger.debug(options.slackOptions);
throw new Error(import_constants.ERROR_MESSAGES.UNDEFINED_SLACK_OPTION);
}
if (options.slackOptions.type === "web-api") {
if (options.slackOptions.slackBotToken) {
import_utils.logger.warn(
'"slackBotToken" property is deprecated. Please use the inherited "token" property instead. Will be removed in the next major version.'
);
options.slackOptions.token = options.slackOptions.slackBotToken;
}
this._webClient = new import_client.SlackWebClient(options.slackOptions);
import_utils.logger.info("Created Slack Web API Client Instance.");
import_utils.logger.debug("Slack Web API Client", {
token: options.slackOptions.slackBotToken,
channel: options.slackOptions.channel
});
this._channel = options.slackOptions.channel;
if (options.slackOptions.notifyDetailResultThread !== void 0) {
if (options.notifyTestFinishMessage === false) {
import_utils.logger.warn(
"Notify is not possible. because the notifyResultMessage option is off."
);
}
this._notifyDetailResultThread = options.slackOptions.notifyDetailResultThread;
}
if (options.slackOptions.filterForDetailResults !== void 0) {
if (options.slackOptions.notifyDetailResultThread === false) {
import_utils.logger.warn(
"Detail result filters does not work. because the notifyDetailResultThread option is off."
);
}
if (options.slackOptions.filterForDetailResults.length === 0) {
import_utils.logger.info(
"If there are no filters (array is empty), all filters are applied."
);
} else {
this._filterForDetailResults = [
...options.slackOptions.filterForDetailResults
];
}
}
if (options.slackOptions.uploadScreenshotOfFailedCase !== void 0) {
this._uploadScreenshotOfFailedCase = options.slackOptions.uploadScreenshotOfFailedCase;
}
if (options.slackOptions.uploadScreenshotOfFailedCase !== void 0) {
this._uploadScreenshotOfFailedCase = options.slackOptions.uploadScreenshotOfFailedCase;
}
if (options.slackOptions.createScreenshotPayload) {
this.createScreenshotPayload = options.slackOptions.createScreenshotPayload.bind(this);
import_utils.logger.info(
"The [createScreenshotPayload] function has been overridden."
);
import_utils.logger.debug("RESULT", this.createScreenshotPayload.toString());
}
if (options.slackOptions.createResultDetailPayload) {
this.createResultDetailPayload = options.slackOptions.createResultDetailPayload.bind(this);
import_utils.logger.info(
"The [createResultDetailPayload] function has been overridden."
);
import_utils.logger.debug("RESULT", this.createResultDetailPayload.toString());
}
} else {
if (options.slackOptions.slackName) {
import_utils.logger.warn(
'"slackName" property is deprecated. Please use the inherited "username" property instead. Will be removed in the next major version.'
);
options.slackOptions.username = options.slackOptions.slackName;
}
if (options.slackOptions.slackIconUrl) {
import_utils.logger.warn(
'"slackIconUrl" property is deprecated. Please use the inherited "icon_url" property instead. Will be removed in the next major version.'
);
options.slackOptions.icon_url = options.slackOptions.slackIconUrl;
}
this._webhookClient = new import_client.SlackWebhookClient({
username: options.slackOptions.username ?? import_constants.SLACK_NAME,
icon_url: !options.slackOptions.icon_url && !options.slackOptions.icon_emoji ? import_constants.SLACK_ICON_URL : void 0,
...options.slackOptions
});
import_utils.logger.info("Created Slack Webhook Instance.");
import_utils.logger.debug("IncomingWebhook", {
username: options.slackOptions.username ?? import_constants.SLACK_NAME,
icon_url: !options.slackOptions.icon_url && !options.slackOptions.icon_emoji ? import_constants.SLACK_ICON_URL : void 0,
...options.slackOptions
});
}
this._symbols = {
passed: options.emojiSymbols?.passed || import_constants.EMOJI_SYMBOLS.PASSED,
skipped: options.emojiSymbols?.skipped || import_constants.EMOJI_SYMBOLS.SKIPPED,
failed: options.emojiSymbols?.failed || import_constants.EMOJI_SYMBOLS.FAILED,
pending: options.emojiSymbols?.pending || import_constants.EMOJI_SYMBOLS.PENDING,
start: options.emojiSymbols?.start || import_constants.EMOJI_SYMBOLS.ROCKET,
finished: options.emojiSymbols?.finished || import_constants.EMOJI_SYMBOLS.CHECKERED_FLAG,
watch: options.emojiSymbols?.watch || import_constants.EMOJI_SYMBOLS.STOPWATCH
};
this._title = options.title;
if (options.resultsUrl !== void 0) {
SlackReporter.setResultsUrl(options.resultsUrl);
}
if (options.notifyTestStartMessage !== void 0) {
this._notifyTestStartMessage = options.notifyTestStartMessage;
}
if (options.notifyFailedCase !== void 0) {
this._notifyFailedCase = options.notifyFailedCase;
}
if (options.notifyTestFinishMessage !== void 0) {
this._notifyTestFinishMessage = options.notifyTestFinishMessage;
}
if (options.useScenarioBasedStateCounts !== void 0) {
this._useScenarioBasedStateCounts = options.useScenarioBasedStateCounts;
}
this._interval = global.setInterval(this.sync.bind(this), 100);
if (options.createStartPayload) {
this.createStartPayload = options.createStartPayload.bind(this);
import_utils.logger.info("The [createStartPayload] function has been overridden.");
import_utils.logger.debug("RESULT", this.createStartPayload.toString());
}
if (options.createFailedTestPayload) {
this.createFailedTestPayload = options.createFailedTestPayload.bind(this);
import_utils.logger.info(
"The [createFailedTestPayload] function has been overridden."
);
import_utils.logger.debug("RESULT", this.createFailedTestPayload.toString());
}
if (options.createResultPayload) {
this.createResultPayload = options.createResultPayload.bind(this);
import_utils.logger.info("The [createResultPayload] function has been overridden.");
import_utils.logger.debug("RESULT", this.createResultPayload.toString());
}
process.on(import_constants.EVENTS.POST_MESSAGE, this.postMessage.bind(this));
process.on(import_constants.EVENTS.UPLOAD, this.upload.bind(this));
process.on(import_constants.EVENTS.SEND, this.send.bind(this));
process.on(import_constants.EVENTS.SCREENSHOT, this.uploadFailedTestScreenshot.bind(this));
}
static getResultsUrl() {
return SlackReporter.resultsUrl;
}
static setResultsUrl(url) {
SlackReporter.resultsUrl = url;
}
/**
* Upload failed test screenshot
* @param {string | Buffer} data Screenshot buffer
*/
static uploadFailedTestScreenshot(data) {
let buffer;
if (typeof data === "string") {
buffer = Buffer.from(data, "base64");
} else {
buffer = data;
}
process.emit(import_constants.EVENTS.SCREENSHOT, {
buffer
});
}
/**
* Post message from Slack web-api
* @param {ChatPostMessageArguments} payload Parameters used by Slack web-api
* @return {Promise<WebAPICallResult>}
*/
static postMessage(payload) {
return new Promise((resolve, reject) => {
process.emit(import_constants.EVENTS.POST_MESSAGE, payload);
process.once(import_constants.EVENTS.RESULT, ({ result, error }) => {
if (result) {
resolve(result);
}
reject(error);
});
});
}
/**
* Upload from Slack web-api
* @param {FilesUploadArguments} payload Parameters used by Slack web-api
* @return {WebAPICallResult}
*/
static async upload(payload, options = {
waitForUpload: true,
timeout: 30,
interval: 1e3
}) {
return new Promise((resolve, reject) => {
void process.emit(import_constants.EVENTS.UPLOAD, { payload, options });
process.once(import_constants.EVENTS.RESULT, ({ result, error }) => {
if (result) {
resolve(
result
);
}
reject(error);
});
});
}
/**
* Send from Slack webhook
* @param {IncomingWebhookSendArguments} payload Parameters used by Slack webhook
* @return {IncomingWebhookResult}
*/
static async send(payload) {
return new Promise((resolve, reject) => {
process.emit(import_constants.EVENTS.SEND, payload);
process.once(import_constants.EVENTS.RESULT, ({ result, error }) => {
if (result) {
resolve(result);
}
reject(error);
});
});
}
uploadFailedTestScreenshot(buffer) {
if (this._webClient) {
if (this._notifyFailedCase && this._uploadScreenshotOfFailedCase) {
this._lastScreenshotBuffer = buffer;
return;
} else {
import_utils.logger.warn(import_constants.ERROR_MESSAGES.DISABLED_OPTIONS);
}
} else {
import_utils.logger.warn(import_constants.ERROR_MESSAGES.NOT_USING_WEB_API);
}
}
async postMessage(payload) {
if (this._webClient) {
try {
import_utils.logger.debug("COMMAND", `postMessage(${payload})`);
this._pendingSlackRequestCount++;
const result = await this._webClient.postMessage(payload);
import_utils.logger.debug("RESULT", import_node_util.default.inspect(result));
process.emit(import_constants.EVENTS.RESULT, { result, error: void 0 });
return result;
} catch (error) {
import_utils.logger.error(error);
process.emit(import_constants.EVENTS.RESULT, { result: void 0, error });
throw error;
} finally {
this._pendingSlackRequestCount--;
}
}
import_utils.logger.error(import_constants.ERROR_MESSAGES.NOT_USING_WEB_API);
throw new Error(import_constants.ERROR_MESSAGES.NOT_USING_WEB_API);
}
async upload(payload, options) {
if (this._webClient) {
try {
import_utils.logger.debug("COMMAND", `upload(${payload})`);
this._pendingSlackRequestCount++;
const result = await this._webClient.uploadV2(payload, options);
import_utils.logger.debug("RESULT", import_node_util.default.inspect(result));
process.emit(import_constants.EVENTS.RESULT, { result, error: void 0 });
return result;
} catch (error) {
import_utils.logger.error(error);
process.emit(import_constants.EVENTS.RESULT, { result: void 0, error });
throw error;
} finally {
this._pendingSlackRequestCount--;
}
}
import_utils.logger.error(import_constants.ERROR_MESSAGES.NOT_USING_WEB_API);
throw new Error(import_constants.ERROR_MESSAGES.NOT_USING_WEB_API);
}
async send(payload) {
if (this._webhookClient) {
try {
import_utils.logger.debug("COMMAND", `send(${payload})`);
this._pendingSlackRequestCount++;
const result = await this._webhookClient.send(payload);
import_utils.logger.debug("RESULT", import_node_util.default.inspect(result));
process.emit(import_constants.EVENTS.RESULT, { result, error: void 0 });
return result;
} catch (error) {
import_utils.logger.error(error);
process.emit(import_constants.EVENTS.RESULT, { result: void 0, error });
throw error;
} finally {
this._pendingSlackRequestCount--;
}
}
import_utils.logger.error(import_constants.ERROR_MESSAGES.NOT_USING_WEBHOOK);
throw new Error(import_constants.ERROR_MESSAGES.NOT_USING_WEBHOOK);
}
get isSynchronised() {
return this._pendingSlackRequestCount === 0 && !this._isSynchronizing;
}
async sync() {
if (this._hasRunnerEnd && this._slackRequestQueue.length === 0 && this._pendingSlackRequestCount === 0) {
clearInterval(this._interval);
}
if (this._isSynchronizing || this._slackRequestQueue.length === 0 || this._pendingSlackRequestCount > 0) {
return;
}
try {
this._isSynchronizing = true;
import_utils.logger.info("Start Synchronisation");
await this.next();
} catch (error) {
import_utils.logger.error(error);
throw error;
} finally {
this._isSynchronizing = false;
import_utils.logger.info("End Synchronisation");
}
}
async next() {
const request = this._slackRequestQueue.shift();
let result;
import_utils.logger.info("POST", `Slack Request ${request?.type}`);
import_utils.logger.debug("DATA", import_node_util.default.inspect(request?.payload));
if (request) {
try {
this._pendingSlackRequestCount++;
switch (request.type) {
case import_constants.SLACK_REQUEST_TYPE.WEB_API_POST_MESSAGE: {
if (this._webClient) {
const payload = request.payload;
if (this._thread) {
payload.thread_ts = this._thread;
}
result = await this._webClient.postMessage({
...payload
});
this._thread = result.ts;
import_utils.logger.debug("RESULT", import_node_util.default.inspect(result));
}
break;
}
case import_constants.SLACK_REQUEST_TYPE.WEB_API_UPLOAD: {
if (this._webClient) {
const payload = request.payload;
if ("file" in payload && payload.file.type === "Buffer") {
payload.file = Buffer.from(
payload.file.data
);
}
if ("file" in payload && "buffer" in payload.file) {
payload.file = payload.file.buffer;
}
if (this._thread) {
payload.thread_ts = this._thread;
}
result = await this._webClient.uploadV2(
{
...payload
},
{ ...request.options || {} }
);
import_utils.logger.debug("RESULT", import_node_util.default.inspect(result));
}
break;
}
case import_constants.SLACK_REQUEST_TYPE.WEBHOOK_SEND: {
if (this._webhookClient) {
result = await this._webhookClient.send(request.payload);
import_utils.logger.debug("RESULT", import_node_util.default.inspect(result));
}
break;
}
}
} catch (error) {
import_utils.logger.error(error);
} finally {
this._pendingSlackRequestCount--;
}
if (this._slackRequestQueue.length > 0) {
await this.next();
}
}
}
/**
* Convert error stack to string
* @param {string} stack Error stack
* @return {string} Converted error stack
*/
convertErrorStack(stack) {
return stack.replace(
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
""
);
}
/**
* Get information about the environment
* @description
* Referenced from [Spec Reporter](https://github.com/webdriverio/webdriverio/blob/c6cf43f67aa46a294a4df158ddd194d79f11ac90/packages/wdio-spec-reporter/src/index.ts#L653)
* @param {Capabilities.ResolvedTestrunnerCapabilities} capability Capabilities
* @param {boolean} isMultiremote Is multiremote
* @return {string} Environment string
*/
getEnvironmentCombo(capability, isMultiremote = false) {
let output = "";
const capabilities = "alwaysMatch" in capability ? capability.alwaysMatch : capability;
const drivers = [];
if (isMultiremote) {
output += "*MultiRemote*: \n";
Object.keys(capabilities).forEach((key) => {
drivers.push({
driverName: key,
capability: capabilities[key]
});
});
} else {
drivers.push({
capability: capabilities
});
}
drivers.forEach(({ driverName, capability: capability2 }, index, array) => {
const isLastIndex = array.length - 1 === index;
let env = "";
const caps = "alwaysMatch" in capability2 ? capability2.alwaysMatch : capability2;
const device = caps["appium:deviceName"];
const app = (capability2["appium:app"] || capability2.app || "").replace("sauce-storage:", "");
const appName = caps["appium:bundleId"] || caps["appium:appPackage"] || caps["appium:appActivity"] || (import_node_path.default.isAbsolute(app) ? import_node_path.default.basename(app) : app);
const browser = capability2.browserName || capability2.browser || appName;
const version = caps.browserVersion || caps.version || caps["appium:platformVersion"] || caps.browser_version;
const platform = caps.platformName || caps.platform || (caps.os ? caps.os + (caps.os_version ? ` ${caps.os_version}` : "") : "(unknown)");
if (device) {
const program = appName || caps.browserName;
const executing = program ? `executing ${program}` : "";
env = `${device} on ${platform} ${version} ${executing}`.trim();
} else {
env = browser + (version ? ` (v${version})` : "") + ` on ${platform}`;
}
output += isMultiremote ? `- *${driverName}*: ` : "*Driver*: ";
output += env;
output += isLastIndex ? "" : "\n";
});
return output;
}
/**
* Indent a suite based on where how it's nested
* @param {String} uid Unique suite key
* @return {String} Spaces for indentation
*/
indent(uid) {
const indents = this._suiteIndents[uid];
return indents === 0 ? "" : Array(indents).join(import_constants.DEFAULT_INDENT);
}
/**
* Indent a suite based on where how it's nested
* @param {StateCount} stateCounts Stat count
* @return {String} String to the stat count to be displayed in Slack
*/
getCounts(stateCounts) {
return `*${this._symbols.passed} Passed: ${stateCounts.passed} | ${this._symbols.failed} Failed: ${stateCounts.failed} | ${this._symbols.skipped} Skipped: ${stateCounts.skipped}*`;
}
createStartPayload(runnerStats) {
const text = `${this._title ? "*Title*: `" + this._title + "`\n" : ""}${this.getEnvironmentCombo(
runnerStats.capabilities,
runnerStats.isMultiremote
)}`;
const payload = {
channel: this._channel,
text: `${this._symbols.start} Start testing${this._title ? "for " + this._title : ""}`,
blocks: [
{
type: "header",
text: {
type: "plain_text",
text: `${this._symbols.start} Start testing`,
emoji: true
}
}
],
attachments: [
{
color: import_constants.DEFAULT_COLOR,
text,
ts: Date.now().toString()
}
]
};
return payload;
}
createFailedTestPayload(hookAndTest) {
const stack = hookAndTest.error?.stack ? "```" + this.convertErrorStack(hookAndTest.error.stack) + "```" : "";
const payload = {
channel: this._channel,
text: `${this._symbols.failed} Test failure`,
blocks: [
{
type: "header",
text: {
type: "plain_text",
text: `${this._symbols.failed} Test failure`,
emoji: true
}
}
],
attachments: [
{
color: import_constants.FAILED_COLOR,
title: `${this._currentSuite ? this._currentSuite.title : hookAndTest.parent}`,
text: `* \xBB ${hookAndTest.title}*
${stack}`
}
]
};
return payload;
}
createScreenshotPayload(testStats, screenshotBuffer) {
if (this._channel && this._thread) {
const payload = {
channel_id: this._channel,
thread_ts: this._thread,
initial_comment: `Screenshot for Fail to ${testStats.title}`,
filename: `${testStats.uid}.png`,
file: screenshotBuffer
};
return payload;
} else {
const payload = {
channel_id: this._channel,
initial_comment: `Screenshot for Fail to ${testStats.title}`,
filename: `${testStats.uid}.png`,
file: screenshotBuffer
};
return payload;
}
}
createResultPayload(runnerStats, stateCounts) {
const resultsUrl = SlackReporter.getResultsUrl();
const counts = this.getCounts(stateCounts);
const payload = {
channel: this._channel,
text: `${this._symbols.finished} End of test${this._title ? " - " + this._title : ""}
${counts}`,
blocks: [
{
type: "header",
text: {
type: "plain_text",
text: `${this._symbols.finished} End of test - ${this._symbols.watch} ${runnerStats.duration / 1e3}s`,
emoji: true
}
}
],
attachments: [
{
color: import_constants.FINISHED_COLOR,
text: `${this._title ? `*Title*: \`${this._title}\`
` : ""}${resultsUrl ? `*Results*: <${resultsUrl}>
` : ""}${counts}`,
ts: Date.now().toString()
}
]
};
return payload;
}
createResultDetailPayload(runnerStats, stateCounts) {
const counts = this.getCounts(stateCounts);
const payload = {
channel: this._channel,
text: `${this._title ? this._title + "\n" : ""}${counts}`,
blocks: [
{
type: "header",
text: {
type: "plain_text",
text: "Result Details",
emoji: true
}
},
...this.getResultDetailPayloads(),
{
type: "section",
text: {
type: "mrkdwn",
text: `${counts}
${this._symbols.watch} ${runnerStats.duration / 1e3}s`
}
},
{
type: "context",
elements: [
{
type: "mrkdwn",
text: `*Filter*: ${this._filterForDetailResults.map((filter) => "`" + filter + "`").join(", ")}`
}
]
}
]
};
return payload;
}
getResultDetailPayloads() {
const output = [];
let suites = this._isCucumberFramework ? this.getOrderedCucumberTests() : this.getOrderedSuites();
const blocks = [];
if (this._isCucumberFramework && this._notifyDetailResultThread) {
suites = suites.filter(
({ state }) => this._filterForDetailResults.includes(state)
);
}
for (const suite of suites) {
if (suite.tests.length === 0 && suite.suites.length === 0 && suite.hooks.length === 0) {
continue;
}
let eventsToReport = this.getEventsToReport(suite);
if (!this._isCucumberFramework && this._notifyDetailResultThread) {
eventsToReport = eventsToReport.filter(
({ state }) => state && this._filterForDetailResults.includes(state)
);
}
if (eventsToReport.length === 0) {
continue;
}
const suiteIndent = this.indent(suite.uid);
if (suite.type) {
output.push(`*${suiteIndent}${suite.title}*`);
}
if (suite.description) {
output.push(
...suite.description.trim().split("\n").map((l) => `${suiteIndent}${l.trim()}`)
);
}
for (const test of eventsToReport) {
const testTitle = test.title;
const testState = test.state;
const testIndent = `${import_constants.DEFAULT_INDENT}${suiteIndent}`;
output.push(
`*${testIndent}${testState ? `${this._symbols[testState]} ` : ""}${testTitle}*`
);
}
if (eventsToReport.length) {
const block = {
type: "section",
text: {
type: "mrkdwn",
text: output.join("\n")
}
};
output.length = 0;
blocks.push(block);
}
}
if (blocks.length === 0) {
const block = {
type: "section",
text: {
type: "mrkdwn",
text: "*`No filter Results.`*"
}
};
blocks.push(block);
}
return blocks;
}
getOrderedSuites() {
if (this._orderedSuites.length) {
return this._orderedSuites;
}
this._orderedSuites = [];
for (const uid of this._suiteUids) {
for (const [suiteUid, suite] of Object.entries(this.suites)) {
if (suiteUid !== uid) {
continue;
}
this._orderedSuites.push(suite);
}
}
return this._orderedSuites;
}
getOrderedCucumberTests() {
if (this._cucumberOrderedTests.length) {
return this._cucumberOrderedTests;
}
this._cucumberOrderedTests = [];
for (const uid of this._suiteUids) {
for (const [suiteUid, suite] of Object.entries(this.suites)) {
if (suiteUid !== uid) {
continue;
}
if (suite.type === "scenario") {
let testState = "passed";
if (suite.tests.some((test) => test.state === "failed")) {
testState = "failed";
} else if (suite.tests.every((test) => test.state === "skipped")) {
testState = "skipped";
}
this._cucumberOrderedTests.push(
Object.assign(suite, { state: testState })
);
}
}
}
return this._cucumberOrderedTests;
}
getCucumberTestsCounts() {
if (this._isCucumberFramework) {
const suitesData = this.getOrderedCucumberTests();
const suiteStats = {
passed: suitesData.filter(({ state }) => state === "passed").length,
failed: suitesData.filter(({ state }) => state === "failed").length,
skipped: suitesData.filter(({ state }) => state === "skipped").length
};
return suiteStats;
} else {
import_utils.logger.warn(
"Since the Cucumber Framework is not being used, the state is counted based on the tests(steps)."
);
return this._stateCounts;
}
}
/**
* returns everything worth reporting from a suite
* @param {Object} suite test suite containing tests and hooks
* @return {Object[]} list of events to report
*/
getEventsToReport(suite) {
return [
/**
* report all tests and only hooks that failed
*/
...suite.hooksAndTests.filter((item) => {
return item.type === "test" || Boolean(item.error);
})
];
}
onRunnerStart(runnerStats) {
import_utils.logger.info("INFO", `Test Framework: ${runnerStats.config.framework}`);
if (runnerStats.config.framework === "cucumber") {
this._isCucumberFramework = true;
}
if (this._notifyTestStartMessage) {
try {
if (this._webClient) {
import_utils.logger.info("INFO", `ON RUNNER START: POST MESSAGE`);
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEB_API_POST_MESSAGE,
payload: this.createStartPayload(
runnerStats
)
});
} else if (this._webhookClient) {
import_utils.logger.info("INFO", `ON RUNNER START: SEND`);
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEBHOOK_SEND,
payload: this.createStartPayload(
runnerStats
)
});
}
} catch (error) {
import_utils.logger.error(error);
throw error;
}
}
}
// onBeforeCommand(commandArgs: BeforeCommandArgs): void {}
// onAfterCommand(commandArgs: AfterCommandArgs): void {}
onSuiteStart(suiteStats) {
this._currentSuite = suiteStats;
this._suiteUids.add(suiteStats.uid);
if (this._isCucumberFramework) {
if (suiteStats.type === "feature") {
this._indents = 0;
this._suiteIndents[suiteStats.uid] = this._indents;
}
} else {
this._suiteIndents[suiteStats.uid] = ++this._indents;
}
}
// onHookStart(hookStat: HookStats): void {}
onHookEnd(hookStats) {
if (hookStats.error) {
this._stateCounts.failed++;
if (this._notifyFailedCase) {
if (this._webClient) {
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEB_API_POST_MESSAGE,
payload: this.createFailedTestPayload(
hookStats
)
});
} else {
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEBHOOK_SEND,
payload: this.createFailedTestPayload(
hookStats
)
});
}
}
}
}
// onTestStart(testStats: TestStats): void {}
onTestPass(testStats) {
this._stateCounts.passed++;
}
onTestFail(testStats) {
this._stateCounts.failed++;
if (this._notifyFailedCase) {
if (this._webClient) {
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEB_API_POST_MESSAGE,
payload: this.createFailedTestPayload(
testStats
)
});
if (this._uploadScreenshotOfFailedCase && this._lastScreenshotBuffer) {
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEB_API_UPLOAD,
payload: this.createScreenshotPayload(
testStats,
this._lastScreenshotBuffer
)
});
this._lastScreenshotBuffer = void 0;
}
} else {
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEBHOOK_SEND,
payload: this.createFailedTestPayload(
testStats
)
});
}
}
}
// onTestRetry(testStats: TestStats): void {}
onTestSkip(testStats) {
this._stateCounts.skipped++;
}
// onTestEnd(testStats: TestStats): void {}
onSuiteEnd(suiteStats) {
this._indents--;
}
onRunnerEnd(runnerStats) {
if (this._notifyTestFinishMessage) {
const stateCount = this._useScenarioBasedStateCounts ? this.getCucumberTestsCounts() : this._stateCounts;
try {
if (this._webClient) {
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEB_API_POST_MESSAGE,
payload: this.createResultPayload(
runnerStats,
stateCount
)
});
if (this._notifyDetailResultThread) {
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEB_API_POST_MESSAGE,
payload: this.createResultDetailPayload(
runnerStats,
stateCount
),
isDetailResult: true
});
}
} else {
this._slackRequestQueue.push({
type: import_constants.SLACK_REQUEST_TYPE.WEBHOOK_SEND,
payload: this.createResultPayload(
runnerStats,
stateCount
)
});
}
} catch (error) {
import_utils.logger.error(error);
throw error;
}
}
this._hasRunnerEnd = true;
}
}
var reporter_default = SlackReporter;
//# sourceMappingURL=reporter.cjs.map