New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@empiricalrun/reporter

Package Overview
Dependencies
Maintainers
0
Versions
77
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@empiricalrun/reporter - npm Package Compare versions

Comparing version 0.4.1 to 0.5.0

dist/sinks/base.d.ts

6

CHANGELOG.md
# @empiricalrun/reporter
## 0.5.0
### Minor Changes
- 5fdad41: feat: add google chat reporter sink
## 0.4.1

@@ -4,0 +10,0 @@

157

dist/bin/index.js
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const google_1 = require("../sinks/google");
const slack_1 = require("../sinks/slack");
const appium_1 = require("../sources/appium");
const playwright_1 = require("../sources/playwright");
const utils_1 = require("../utils");
const color = {
warning: "dcab07",
success: "35a64f",
error: "cb2431",
};
function slackLinkForRun(repoName, runId) {
const runLink = `https://github.com/empirical-run/${repoName}-tests/actions/runs/${runId}`;
return (0, utils_1.buildSlackLink)(runLink, runId);
function buildRunLink(repoName, runId) {
return `https://github.com/empirical-run/${repoName}-tests/actions/runs/${runId}`;
}
function messageForMissingResults(repoName, runId) {
return {
text: "Tests were not run",
attachments: [
{
color: color.error,
fields: [
{
title: "Status",
short: true,
value: "Failed",
},
{
title: "Run ID",
short: true,
value: slackLinkForRun(repoName, runId),
},
],
},
],
};
}
function endMessage(repoName, runId, source) {
const results = source.resultsSummary();
const slackMessage = {
text: "Tests completed",
attachments: [
{
color: results.hasPassed ? color.success : color.error,
title: "Open test report",
title_link: source.reportLink(),
fields: [
{
title: "Status",
short: true,
value: results.hasPassed ? "Passed" : "Failed",
},
{
title: "Run ID",
short: true,
value: slackLinkForRun(repoName, runId),
},
{
title: "Tests run",
short: true,
value: `${results.totalTests} (${(0, utils_1.buildSlackLink)(source.reportLink(), "view")})`,
},
{
title: "Run duration",
short: true,
value: (0, utils_1.humanReadable)(results.runDuration),
},
],
},
],
};
if (results.flakyTests > 0) {
const reportLink = source.reportLink({ status: "flaky" });
slackMessage.attachments[0].fields.push({
title: "Flaky tests",
short: true,
value: `${results.flakyTests} (${(0, utils_1.buildSlackLink)(reportLink, "view")})`,
});
}
if (!results.hasPassed) {
const numFailed = results.failedTests;
const failures = source.failedTests(repoName, runId);
let messageStr;
const previewSizeLimit = 4;
if (numFailed <= previewSizeLimit) {
messageStr = failures.map((str) => `- ${str}`).join("\n");
}
else {
const testsStr = failures
.slice(0, previewSizeLimit)
.map((str) => `- ${str}`)
.join("\n");
// TODO: if Appium reporter does not have direct test links, we will need to show
// "view all" even if there are fewer than `previewSizeLimit` failed tests.
const reportLink = source.reportLink({ status: "failed" });
messageStr = `${testsStr}\n${(0, utils_1.buildSlackLink)(reportLink, "View all")}`;
}
slackMessage.attachments[0].fields.push({
title: `Failed tests (${numFailed})`,
short: false,
value: messageStr,
});
}
return slackMessage;
}
function startMessage(repoName, runId) {
return {
text: "Tests started",
attachments: [
{
color: color.warning,
fields: [
{
title: "Status",
short: true,
value: "In Progress",
},
{
title: "Run ID",
short: true,
value: slackLinkForRun(repoName, runId),
},
],
},
],
};
}
(async function main() {

@@ -135,2 +17,7 @@ if (process.argv.length != 6) {

const [messageType, repoName, runId, reportType] = process.argv.slice(2);
if (!runId || !repoName) {
console.error("Missing arguments: runId or repoName");
process.exit(1);
}
const runLink = buildRunLink(repoName, runId);
let reportSource = undefined;

@@ -144,15 +31,32 @@ if (reportType == "playwright") {

else {
console.log(`report type (fourth arg) must be "playwright".`);
console.error(`report type (fourth arg) must be "playwright" or "appium".`);
process.exit(1);
}
let slackMessage;
let sink;
try {
const sinkUrl = new URL(process.env.SLACK_WEBHOOK_URL);
if (sinkUrl.hostname === "hooks.slack.com") {
sink = new slack_1.SlackReportSink(sinkUrl.toString(), runLink, runId, reportSource);
}
else if (sinkUrl.hostname === "chat.googleapis.com") {
sink = new google_1.GoogleChatReportSink(sinkUrl.toString(), runLink, runId, reportSource);
}
else {
console.log("Unsupported sink URL in $SLACK_WEBHOOK_URL");
process.exit(1);
}
}
catch (e) {
console.error("Missing environment variable: SLACK_WEBHOOK_URL");
process.exit(1);
}
if (messageType === "start") {
slackMessage = startMessage(repoName, runId);
await sink.sendStartMessage();
}
else if (messageType === "end") {
if (!reportSource.reportExists()) {
slackMessage = messageForMissingResults(repoName, runId);
await sink.sendMessageForError();
}
else {
slackMessage = endMessage(repoName, runId, reportSource);
await sink.sendEndMessage();
}

@@ -164,4 +68,3 @@ }

}
await (0, slack_1.sendToSlack)(slackMessage);
return;
})();

@@ -1,3 +0,16 @@

import { IncomingWebhookSendArguments } from "@slack/webhook";
export declare function sendToSlack(message: IncomingWebhookSendArguments): Promise<void>;
import { BaseReportSource } from "../sources/base";
import { BaseReportSink } from "./base";
export declare class SlackReportSink implements BaseReportSink {
private url;
private runLink;
private runId;
private reportSource;
constructor(url: string, runLink: string, runId: string, // TODO: remove this once we remove it from message contents
reportSource: BaseReportSource);
sendStartMessage(): Promise<void>;
sendMessageForError(): Promise<void>;
sendEndMessage(): Promise<void>;
private send;
private formatLink;
}
//# sourceMappingURL=slack.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendToSlack = void 0;
exports.SlackReportSink = void 0;
const webhook_1 = require("@slack/webhook");
async function sendToSlack(message) {
// eslint-disable-next-line turbo/no-undeclared-env-vars
const url = process.env.SLACK_WEBHOOK_URL;
if (!url) {
console.error("Missing environment variable: SLACK_WEBHOOK_URL");
process.exit(1);
const utils_1 = require("../utils");
const color = {
warning: "dcab07",
success: "35a64f",
error: "cb2431",
};
class SlackReportSink {
url;
runLink;
runId;
reportSource;
constructor(url, runLink, runId, // TODO: remove this once we remove it from message contents
reportSource) {
this.url = url;
this.runLink = runLink;
this.runId = runId;
this.reportSource = reportSource;
}
const webhook = new webhook_1.IncomingWebhook(url);
await webhook.send(message);
async sendStartMessage() {
const message = {
text: "Tests started",
attachments: [
{
color: color.warning,
fields: [
{
title: "Status",
short: true,
value: "In Progress",
},
{
title: "Run ID",
short: true,
value: this.formatLink(this.runLink, this.runId),
},
],
},
],
};
await this.send(message);
}
async sendMessageForError() {
const message = {
text: "Tests were not run",
attachments: [
{
color: color.error,
fields: [
{
title: "Status",
short: true,
value: "Failed",
},
{
title: "Run ID",
short: true,
value: this.formatLink(this.runLink, this.runId),
},
],
},
],
};
await this.send(message);
}
async sendEndMessage() {
const results = this.reportSource.resultsSummary();
const message = {
text: "Tests completed",
attachments: [
{
color: results.hasPassed ? color.success : color.error,
title: "Open test report",
title_link: this.reportSource.reportLink(),
fields: [
{
title: "Status",
short: true,
value: results.hasPassed ? "Passed" : "Failed",
},
{
title: "Run ID",
short: true,
value: this.formatLink(this.runLink, this.runId),
},
{
title: "Tests run",
short: true,
value: `${results.totalTests} (${this.formatLink(this.reportSource.reportLink(), "view")})`,
},
{
title: "Run duration",
short: true,
value: (0, utils_1.humanReadable)(results.runDuration),
},
],
},
],
};
if (results.flakyTests > 0) {
const reportLink = this.reportSource.reportLink({ status: "flaky" });
//@ts-ignore
message.attachments[0].fields.push({
title: "Flaky tests",
short: true,
value: `${results.flakyTests} (${this.formatLink(reportLink, "view")})`,
});
}
if (!results.hasPassed) {
const numFailed = results.failedTests;
const failedTestsWithLinks = this.reportSource.failedTests();
const failures = failedTestsWithLinks.map((f) => {
return `${f.name} (${this.formatLink(f.link, "view")})`;
});
let messageStr;
const previewSizeLimit = 4;
if (numFailed <= previewSizeLimit) {
messageStr = failures.map((str) => `- ${str}`).join("\n");
}
else {
const testsStr = failures
.slice(0, previewSizeLimit)
.map((str) => `- ${str}`)
.join("\n");
// TODO: if Appium reporter does not have direct test links, we will need to show
// "view all" even if there are fewer than `previewSizeLimit` failed tests.
const reportLink = this.reportSource.reportLink({ status: "failed" });
messageStr = `${testsStr}\n${this.formatLink(reportLink, "View all")}`;
}
//@ts-ignore
message.attachments[0].fields.push({
title: `Failed tests (${numFailed})`,
short: false,
value: messageStr,
});
}
await this.send(message);
}
async send(message) {
const webhook = new webhook_1.IncomingWebhook(this.url);
try {
await webhook.send(message);
}
catch (e) {
console.error(`Error sending message to Slack: ${e.code}`);
console.error(e.message);
}
}
formatLink(href, text) {
return `<${href}|${text}>`;
}
}
exports.sendToSlack = sendToSlack;
exports.SlackReportSink = SlackReportSink;

@@ -15,7 +15,9 @@ import { BaseReportSource, ReportFilter } from "./base";

};
failedTests(): string[];
failedTests(): {
name: string;
link: string;
}[];
reportLink(filter?: ReportFilter): string;
private buildReportLink;
private testDirectLink;
}
//# sourceMappingURL=appium.d.ts.map

@@ -36,3 +36,3 @@ "use strict";

return failedSpecs.map(({ name }) => {
return `${name} (${this.testDirectLink("view", name)})`;
return { name, link: this.buildReportLink({ testName: name }) };
});

@@ -58,7 +58,3 @@ }

}
testDirectLink(previewText, testName) {
const link = this.buildReportLink({ testName });
return (0, utils_1.buildSlackLink)(link, previewText);
}
}
exports.AppiumReportSource = AppiumReportSource;

@@ -11,8 +11,12 @@ export type Results = {

};
export type FailedTestWithLink = {
name: string;
link: string;
};
export interface BaseReportSource {
reportExists(): boolean;
resultsSummary(): Results;
failedTests(repoName: string, runId: string): string[];
failedTests(): FailedTestWithLink[];
reportLink(filter?: ReportFilter): string;
}
//# sourceMappingURL=base.d.ts.map

@@ -1,2 +0,7 @@

import { BaseReportSource, ReportFilter } from "./base";
import { BaseReportSource, FailedTestWithLink } from "./base";
type PlaywrightReportFilter = {
status: string;
} | {
testId: string;
};
export declare class PlaywrightReportSource implements BaseReportSource {

@@ -15,8 +20,7 @@ private repoName;

};
failedTests(): string[];
reportLink(filter?: ReportFilter): string;
failedTests(): FailedTestWithLink[];
reportLink(filter?: PlaywrightReportFilter): string;
private failedTestsFromSuite;
private buildReportLink;
private testDirectLink;
}
export {};
//# sourceMappingURL=playwright.d.ts.map

@@ -46,8 +46,16 @@ "use strict";

return failedSpecs.map(({ title, id }) => {
return `${title} (${this.testDirectLink("view", id)})`;
return { name: title, link: this.reportLink({ testId: id }) };
});
}
reportLink(filter) {
const link = filter ? this.buildReportLink(filter) : this.buildReportLink();
return link;
const base = `https://reports.empirical.run/${this.repoName}/${this.runId}/index.html`;
if (filter && "status" in filter) {
return `${base}#?q=s:${filter.status}`;
}
else if (filter && "testId" in filter) {
return `${base}#?testId=${filter.testId}`;
}
else {
return base;
}
}

@@ -69,19 +77,3 @@ failedTestsFromSuite(rootSuite) {

}
buildReportLink(filter) {
const base = `https://reports.empirical.run/${this.repoName}/${this.runId}/index.html`;
if (filter && "status" in filter) {
return `${base}#?q=s:${filter.status}`;
}
else if (filter && "testId" in filter) {
return `${base}#?testId=${filter.testId}`;
}
else {
return base;
}
}
testDirectLink(previewText, testId) {
const link = this.buildReportLink({ testId });
return (0, utils_1.buildSlackLink)(link, previewText);
}
}
exports.PlaywrightReportSource = PlaywrightReportSource;
export declare function humanReadable(duration: number): string;
export declare function buildSlackLink(href: string, text: string): string;
export declare function parseJsonReport<T>(srcFile: string): T;
//# sourceMappingURL=utils.d.ts.map

@@ -6,3 +6,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.parseJsonReport = exports.buildSlackLink = exports.humanReadable = void 0;
exports.parseJsonReport = exports.humanReadable = void 0;
const fs_1 = __importDefault(require("fs"));

@@ -16,6 +16,2 @@ function humanReadable(duration) {

exports.humanReadable = humanReadable;
function buildSlackLink(href, text) {
return `<${href}|${text}>`;
}
exports.buildSlackLink = buildSlackLink;
function parseJsonReport(srcFile) {

@@ -22,0 +18,0 @@ return JSON.parse(fs_1.default.readFileSync(srcFile, { encoding: "utf-8" }));

{
"name": "@empiricalrun/reporter",
"version": "0.4.1",
"version": "0.5.0",
"publishConfig": {

@@ -5,0 +5,0 @@ "registry": "https://registry.npmjs.org/",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc