prettier-playwright-msteams-report
Version:
A modified version of the Playwright MS Teams Messager
395 lines (394 loc) • 21.1 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const processResults_1 = require("./processResults");
const MSTEAMS_WEBHOOK_URL = `https://tenant.webhook.office.com/webhookb2/12345678-1234-1234-1234-123456789abc@12345678-1234-1234-1234-123456789abc/IncomingWebhook/123456789abcdef123456789abcdef12/12345678-1234-1234-1234-123456789abc`;
const FLOW_WEBHOOK_URL = `https://prod-00.westus.logic.azure.com:443/workflows/1234567890abcdef1234567890abcdef/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=1234567890abcdef1234567890abcdef`;
const DEFAULT_OPTIONS = {
webhookUrl: undefined,
webhookType: "powerautomate",
title: "Playwright Test Results",
linkToResultsUrl: undefined,
linkToResultsText: "View test results",
notifyOnSuccess: true,
mentionOnFailure: undefined,
mentionOnFailureText: "{mentions} please validate the test results.",
quiet: false,
debug: false,
shouldRun: () => true
};
const SUITE_MOCK_PASSED = {
suites: [
{
allTests: () => [{ outcome: () => "expected" }],
},
{
allTests: () => [
{ outcome: () => "expected" },
{ outcome: () => "expected" },
],
},
],
allTests: () => [{}, {}, {}],
};
const SUITE_MOCK_FLAKY = {
suites: [
{
allTests: () => [{ outcome: () => "expected" }],
},
{
allTests: () => [
{ outcome: () => "expected" },
{ outcome: () => "expected" },
],
},
{
allTests: () => [{ outcome: () => "flaky" }],
},
],
allTests: () => [{}, {}, {}],
};
const SUITE_MOCK_FAILED = {
suites: [
{
allTests: () => [{ outcome: () => "unexpected" }],
},
{
allTests: () => [
{ outcome: () => "expected" },
{ outcome: () => "expected" },
],
},
],
allTests: () => [{}, {}, {}],
};
describe("processResults", () => {
it("should return early if no webhook URL is provided", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: undefined });
yield (0, processResults_1.processResults)(undefined, options);
expect(consoleErrorSpy).toHaveBeenCalledWith("No webhook URL provided");
consoleErrorSpy.mockReset();
}));
it("should return early if an invalid webhook URL is provided", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: "invalid-url" });
yield (0, processResults_1.processResults)(undefined, options);
expect(consoleErrorSpy).toHaveBeenCalledWith("Invalid webhook URL");
consoleErrorSpy.mockReset();
}));
it("should return early if no test suite is found", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: MSTEAMS_WEBHOOK_URL, webhookType: "msteams" });
yield (0, processResults_1.processResults)(undefined, options);
expect(consoleErrorSpy).toHaveBeenCalledWith("No test suite found");
consoleErrorSpy.mockReset();
}));
it("should skip notification if there are no failed tests and notifyOnSuccess is false", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: MSTEAMS_WEBHOOK_URL, webhookType: "msteams", notifyOnSuccess: false });
const suite = {
suites: [],
allTests: () => [],
};
yield (0, processResults_1.processResults)(suite, options);
expect(consoleLogSpy).toHaveBeenCalledWith("No failed tests, skipping notification");
consoleLogSpy.mockReset();
}));
it("should return early if shouldRun is false", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
const fetchMock = jest.fn();
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: undefined, shouldRun: () => false });
yield (0, processResults_1.processResults)(undefined, options);
expect(fetchMock).not.toHaveBeenCalled();
expect(consoleLogSpy).not.toHaveBeenCalled();
consoleLogSpy.mockReset();
}));
it("should send a message successfully", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: MSTEAMS_WEBHOOK_URL, webhookType: "msteams" });
yield (0, processResults_1.processResults)(SUITE_MOCK_PASSED, options);
expect(fetchMock).toHaveBeenCalledWith(MSTEAMS_WEBHOOK_URL, expect.any(Object));
expect(consoleLogSpy).toHaveBeenCalledWith("Message sent successfully");
consoleLogSpy.mockReset();
}));
it("should send a message successfully with API outcome", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "Some fake message" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: MSTEAMS_WEBHOOK_URL, webhookType: "msteams" });
yield (0, processResults_1.processResults)(SUITE_MOCK_PASSED, options);
expect(consoleLogSpy).toHaveBeenCalledWith("Some fake message");
consoleLogSpy.mockReset();
}));
it("should log an error if sending the message fails", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: false, text: () => "Error" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: MSTEAMS_WEBHOOK_URL, webhookType: "msteams" });
yield (0, processResults_1.processResults)(SUITE_MOCK_PASSED, options);
expect(fetchMock).toHaveBeenCalledWith(MSTEAMS_WEBHOOK_URL, expect.any(Object));
expect(consoleErrorSpy).toHaveBeenCalledWith("Failed to send message");
expect(consoleErrorSpy).toHaveBeenCalledWith("Error");
consoleErrorSpy.mockReset();
}));
it("should include a flaky row", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") && message.includes("Flaky")) {
console.log(`Flaky`);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FLAKY, options);
expect(consoleLogSpy).toHaveBeenCalledWith("Flaky");
consoleLogSpy.mockReset();
}));
it("should use version 1.4 for adaptive card", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") && message.includes("version")) {
const msgBody = JSON.parse(message);
console.log(`version: ${msgBody.attachments[0].content.version}`);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_PASSED, options);
expect(consoleLogSpy).toHaveBeenCalledWith("version: 1.4");
consoleLogSpy.mockReset();
}));
it("should include mentions", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeEmail = "fake@mail.be";
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") &&
message.includes(`<at>${fakeEmail}</at>`)) {
console.log(`<at>${fakeEmail}</at>`);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", mentionOnFailure: fakeEmail, debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(`<at>${fakeEmail}</at>`);
consoleLogSpy.mockReset();
}));
it("should include mention message", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeEmail = "fake@mail.be";
const fakeMessage = " validate the tests.";
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") &&
message.includes(`<at>${fakeEmail}</at>`) &&
message.includes(fakeMessage)) {
console.log(fakeMessage);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", mentionOnFailure: fakeEmail, mentionOnFailureText: `{mentions}${fakeMessage}`, debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(fakeMessage);
consoleLogSpy.mockReset();
}));
it("should include the link", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeLink = "https://github.com/estruyf/playwright-msteams-reporter";
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") && message.includes(fakeLink)) {
console.log(fakeLink);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", linkToResultsUrl: fakeLink, debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(fakeLink);
consoleLogSpy.mockReset();
}));
it("should include the link from the function", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeLink = "https://github.com/estruyf/playwright-msteams-reporter";
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") && message.includes(fakeLink)) {
console.log(fakeLink);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", linkToResultsUrl: () => fakeLink, debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(fakeLink);
consoleLogSpy.mockReset();
}));
it("should not include the link from the function when not a string (number)", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeLink = 123;
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") && !message.includes(fakeLink)) {
console.log(`Did not include ${fakeLink}`);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", linkToResultsUrl: () => fakeLink, debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(`Did not include ${fakeLink}`);
consoleLogSpy.mockReset();
}));
it("should not include the link from the function when not a string (undefined)", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeLink = undefined;
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") && !message.includes(fakeLink)) {
console.log(`Did not include ${fakeLink}`);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", linkToResultsUrl: () => fakeLink, debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(`Did not include ${fakeLink}`);
consoleLogSpy.mockReset();
}));
it("should include the failure link", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeFailureLink = "https://github.com/estruyf/playwright-msteams-reporter";
const fakeFailureText = "View the failed tests";
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") &&
message.includes(fakeFailureLink) &&
message.includes(fakeFailureText)) {
console.log(fakeFailureText);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", linkUrlOnFailure: fakeFailureLink, linkTextOnFailure: "View the failed tests", debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(fakeFailureText);
consoleLogSpy.mockReset();
}));
it("should include the failure link from the function", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeFailureLink = "https://github.com/estruyf/playwright-msteams-reporter";
const fakeFailureText = "View the failed tests";
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") &&
message.includes(fakeFailureLink) &&
message.includes(fakeFailureText)) {
console.log(fakeFailureText);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", linkUrlOnFailure: () => fakeFailureLink, linkTextOnFailure: "View the failed tests", debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(fakeFailureText);
consoleLogSpy.mockReset();
}));
it("should not include the failure link from the function when not a string (number)", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeFailureLink = 123;
const fakeFailureText = "View the failed tests";
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") &&
!message.includes(fakeFailureLink) &&
!message.includes(fakeFailureText)) {
console.log(`Did not include ${fakeFailureLink}`);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", linkUrlOnFailure: () => fakeFailureLink, linkTextOnFailure: "View the failed tests", debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(`Did not include ${fakeFailureLink}`);
consoleLogSpy.mockReset();
}));
it("should not include the failure link from the function when not a string (undefined)", () => __awaiter(void 0, void 0, void 0, function* () {
const fakeFailureLink = undefined;
const fakeFailureText = "View the failed tests";
const consoleLogSpy = jest
.spyOn(console, "log")
.mockImplementation((message) => {
if (message.includes("message") &&
!message.includes(fakeFailureLink) &&
!message.includes(fakeFailureText)) {
console.log(`Did not include ${fakeFailureLink}`);
}
});
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: FLOW_WEBHOOK_URL, webhookType: "powerautomate", linkUrlOnFailure: () => fakeFailureLink, linkTextOnFailure: "View the failed tests", debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_FAILED, options);
expect(consoleLogSpy).toHaveBeenCalledWith(`Did not include ${fakeFailureLink}`);
consoleLogSpy.mockReset();
}));
it("should show debug message", () => __awaiter(void 0, void 0, void 0, function* () {
const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
const fetchMock = jest
.fn()
.mockResolvedValue({ ok: true, text: () => "1" });
global.fetch = fetchMock;
const options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), { webhookUrl: MSTEAMS_WEBHOOK_URL, webhookType: "msteams", debug: true });
yield (0, processResults_1.processResults)(SUITE_MOCK_PASSED, options);
expect(consoleLogSpy).toHaveBeenCalledWith("Sending the following message:");
consoleLogSpy.mockReset();
}));
});