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

playwright-slack-report

Package Overview
Dependencies
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

playwright-slack-report - npm Package Compare versions

Comparing version 1.1.25 to 1.1.54

dist/cli.js

194

dist/src/index.d.ts
/// <reference types="node" />
export declare type SummaryResults = {
export type SummaryResults = {
passed: number;

@@ -30,5 +30,195 @@ failed: number;

};
export declare type failure = {
export type failure = {
test: string;
failureReason: string;
};
export interface JSONResult {
config: Config;
suites: Suite[];
errors: any[];
stats: Stats;
}
export interface Config {
configFile: string;
rootDir: string;
forbidOnly: boolean;
fullyParallel: boolean;
globalSetup: any;
globalTeardown: any;
globalTimeout: number;
grep: Grep;
grepInvert: any;
maxFailures: number;
metadata: Metadata;
preserveOutput: string;
reporter: [string, any][];
reportSlowTests: ReportSlowTests;
quiet: boolean;
projects: Project[];
shard: any;
updateSnapshots: string;
version: string;
workers: number;
webServer: any;
}
export interface Grep {
}
export interface Metadata {
actualWorkers: number;
}
export interface ReportSlowTests {
max: number;
threshold: number;
}
export interface Project {
outputDir: string;
repeatEach: number;
retries: number;
id: string;
name: string;
testDir: string;
testIgnore: any[];
testMatch: string[];
timeout: number;
}
export interface Suite {
title: string;
file: string;
column: number;
line: number;
specs: Spec[];
suites: Suites[];
}
export interface Spec {
title: string;
ok: boolean;
tags: any[];
tests: Test[];
id: string;
file: string;
line: number;
column: number;
}
export interface Test {
timeout: number;
annotations: any[];
expectedStatus: string;
projectId: string;
projectName: string;
results: Result[];
status: string;
}
export interface Result {
workerIndex: number;
status: string;
duration: number;
errors: Error[];
stdout: any[];
stderr: any[];
retry: number;
startTime: string;
attachments: Attachment[];
error?: {
message: string;
stack: string;
location: {
file: string;
column: number;
line: number;
};
snippet: string;
};
errorLocation?: ErrorLocation;
}
export interface Error {
location: Location;
message: string;
}
export interface Location {
file: string;
column: number;
line: number;
}
export interface Attachment {
name: string;
contentType: string;
path: string;
}
export interface ErrorLocation {
file: string;
column: number;
line: number;
}
export interface Suites {
title: string;
file: string;
line: number;
column: number;
specs: Specs[];
}
export interface Specs {
title: string;
ok: boolean;
tags: any[];
tests: Tests[];
id: string;
file: string;
line: number;
column: number;
}
export interface Tests {
timeout: number;
annotations: any[];
expectedStatus: string;
projectId: string;
projectName: string;
results: Results[];
status: string;
}
export interface Results {
workerIndex: number;
status: string;
duration: number;
error: {
message: string;
stack: string;
location: {
file: string;
column: number;
line: number;
};
snippet: string;
};
errors: Errors[];
stdout: any[];
stderr: any[];
retry: number;
startTime: string;
attachments: Attachments[];
errorLocation: {
file: string;
column: number;
line: number;
};
}
export interface Errors {
location: {
file: string;
column: number;
line: number;
};
message: string;
}
export interface Attachments {
name: string;
contentType: string;
path: string;
}
export interface Stats {
startTime: string;
duration: number;
expected: number;
skipped: number;
unexpected: number;
flaky: number;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=index.js.map

@@ -77,1 +77,2 @@ "use strict";

exports.generateFallbackText = generateFallbackText;
//# sourceMappingURL=LayoutGenerator.js.map
/// <reference types="node" />
import { TestCase } from '@playwright/test/reporter';
import { failure, SummaryResults } from '.';
export declare type testResult = {
import { failure, Spec, SummaryResults } from '.';
export type testResult = {
suiteName: string;

@@ -22,3 +22,3 @@ name: string;

};
export declare type testSuite = {
export type testSuite = {
testSuite: {

@@ -33,2 +33,6 @@ title: string;

constructor();
parseFromJsonFile(filePath: string): Promise<SummaryResults>;
parseTestSuite(suites: any, retries: number, suiteIndex?: number): Promise<void>;
parseTests(suiteName: any, specs: any, retries: number): Promise<testResult[]>;
getFailure(snippet: string, stack: string): string;
getParsedResults(allTests: Array<TestCase>): Promise<SummaryResults>;

@@ -40,2 +44,9 @@ getFailures(): Promise<Array<failure>>;

}): void;
addTestResultFromJson({ suiteName, spec, testCase, projectBrowserMapping, retries, }: {
suiteName: any;
spec: Spec;
testCase: any;
projectBrowserMapping: any;
retries: number;
}): void;
addTestResult(suiteName: any, testCase: any, projectBrowserMapping: any): void;

@@ -42,0 +53,0 @@ safelyDetermineFailure(result: {

@@ -8,3 +8,27 @@ "use strict";

/* eslint-disable no-param-reassign */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
class ResultsParser {

@@ -15,2 +39,75 @@ result;

}
async parseFromJsonFile(filePath) {
const data = fs.readFileSync(filePath, 'utf-8');
const parsedData = JSON.parse(data);
const { retries } = parsedData.config.projects[0];
await this.parseTestSuite(parsedData.suites, retries);
const failures = await this.getFailures();
const summary = {
passed: parsedData.stats.expected,
failed: parsedData.stats.unexpected,
flaky: parsedData.stats.flaky,
skipped: parsedData.stats.skipped,
failures,
tests: [],
};
for (const suite of this.result) {
summary.tests = summary.tests.concat(suite.testSuite.tests);
}
// console.log('🚀~ summary:', JSON.stringify(summary, null, 2));
return summary;
}
async parseTestSuite(suites, retries, suiteIndex = 0) {
let testResults = [];
if (suites[0].suites?.length > 0) {
testResults = await this.parseTests(suites[0].title, suites[0].specs, retries);
this.updateResults({
testSuite: {
title: suites[0].title,
tests: testResults,
},
});
await this.parseTestSuite(suites[suiteIndex].suites, retries, (suiteIndex += 1));
}
else {
testResults = await this.parseTests(suites[0].title, suites[0].specs, retries);
this.updateResults({
testSuite: {
title: suites[0].title,
tests: testResults,
},
});
// eslint-disable-next-line no-useless-return
return;
}
}
async parseTests(suiteName, specs, retries) {
const testResults = [];
for (const spec of specs) {
for (const test of spec.tests) {
for (const result of test.results) {
testResults.push({
suiteName,
name: spec.title,
status: result.status === 'unexpected' ? 'failed' : result.status,
browser: test.projectName,
projectName: test.projectName,
retry: result.retry,
retries,
startedAt: result.startTime,
endedAt: new Date(new Date(result.startTime).getTime() + result.duration).toISOString(),
reason: result.error
? this.getFailure(result.error.snippet, result.error.stack)
: '',
attachments: result.attachments,
});
}
}
}
return testResults;
}
getFailure(snippet, stack) {
const fullError = `${snippet}\r\n${stack || ''}`;
return this.cleanseReason(fullError);
}
async getParsedResults(allTests) {

@@ -21,3 +118,6 @@ const failures = await this.getFailures();

const stats = {
expected: 0, skipped: 0, unexpected: 0, flaky: 0,
expected: 0,
skipped: 0,
unexpected: 0,
flaky: 0,
};

@@ -72,2 +172,27 @@ // eslint-disable-next-line no-plusplus

}
addTestResultFromJson({ suiteName, spec, testCase, projectBrowserMapping, retries, }) {
const testResults = [];
const projectSettings = this.determineBrowser(projectBrowserMapping[0].projectName, projectBrowserMapping);
for (const result of testCase.results) {
testResults.push({
suiteName,
name: spec.title,
status: result.status,
browser: projectSettings.browser,
projectName: projectSettings.projectName,
retry: result.retry,
retries,
startedAt: new Date(result.startTime).toISOString(),
endedAt: new Date(new Date(result.startTime).getTime() + result.duration).toISOString(),
reason: this.safelyDetermineFailure(result),
attachments: result.attachments,
});
}
this.updateResults({
testSuite: {
title: suiteName,
tests: testResults,
},
});
}
addTestResult(suiteName, testCase, projectBrowserMapping) {

@@ -132,1 +257,2 @@ const testResults = [];

exports.default = ResultsParser;
//# sourceMappingURL=ResultsParser.js.map

2

dist/src/SlackClient.d.ts
import { WebClient, KnownBlock, Block, ChatPostMessageResponse, LogLevel } from '@slack/web-api';
import { SummaryResults } from '.';
export declare type additionalInfo = Array<{
export type additionalInfo = Array<{
key: string;

@@ -5,0 +5,0 @@ value: string;

@@ -104,1 +104,2 @@ "use strict";

exports.default = SlackClient;
//# sourceMappingURL=SlackClient.js.map
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -6,5 +9,5 @@ const web_api_1 = require("@slack/web-api");

const webhook_1 = require("@slack/webhook");
const ResultsParser_1 = require("./ResultsParser");
const SlackClient_1 = require("./SlackClient");
const SlackWebhookClient_1 = require("./SlackWebhookClient");
const ResultsParser_1 = __importDefault(require("./ResultsParser"));
const SlackClient_1 = __importDefault(require("./SlackClient"));
const SlackWebhookClient_1 = __importDefault(require("./SlackWebhookClient"));
class SlackReporter {

@@ -187,1 +190,2 @@ customLayout;

exports.default = SlackReporter;
//# sourceMappingURL=SlackReporter.js.map

@@ -43,1 +43,2 @@ "use strict";

exports.default = SlackWebhookClient;
//# sourceMappingURL=SlackWebhookClient.js.map

@@ -5,6 +5,9 @@ {

"@slack/webhook": "^7.0.1",
"https-proxy-agent": "^7.0.1"
"commander": "^11.1.0",
"https-proxy-agent": "^7.0.1",
"ts-node": "^10.9.1",
"zod": "^3.22.4"
},
"devDependencies": {
"@playwright/test": "^1.23.3",
"@playwright/test": "^1.40.0",
"@slack/types": "^2.7.0",

@@ -31,7 +34,12 @@ "@typescript-eslint/eslint-plugin": "^5.30.6",

"lint": "npx eslint . --ext .ts",
"lint-fix": "npx eslint . --ext .ts --fix"
"lint-fix": "npx eslint . --ext .ts --fix",
"cli": "yarn build && node dist/cli.js",
"cli-debug": "yarn build && npx . -c ./tests/test_data/valid_cli_config.json -j ./tests/test_data/valid_test_results.json"
},
"name": "playwright-slack-report",
"version": "1.1.25",
"main": "index.js",
"version": "1.1.54",
"bin": {
"playwright-slack-report": "dist/cli.js"
},
"main": "dist/cli.js",
"types": "dist/index.d.ts",

@@ -56,5 +64,5 @@ "repository": "git@github.com:ryanrosello-og/playwright-slack-report.git",

"exclude": [
"./src/custom_block/my_block.ts"
"./custom_block/my_block.ts"
]
}
}

@@ -14,2 +14,3 @@ # playwright-slack-report ![Builds](https://github.com/ryanrosello-og/playwright-slack-report/actions/workflows/playwright.yml/badge.svg) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ryanrosello-og/playwright-slack-report/blob/master/LICENSE) [![Coverage Status](https://coveralls.io/repos/github/ryanrosello-og/playwright-slack-report/badge.svg?branch=main)](https://coveralls.io/github/ryanrosello-og/playwright-slack-report?branch=main)

- 💌 Send results your Playwright test results to one or more Slack channels
- 🎚️ Leverage JSON results created by Playwright and seamlessly post them on Slack
- 📊 Conditionally send results to Slack channels based on test results

@@ -74,3 +75,3 @@ - 📄 Include additional meta information into your test summary e.g. Branch, BuildId etc

# Option B
# Option B - send your results via a Slack bot user
Run your tests by providing your `SLACK_BOT_USER_OAUTH_TOKEN` as an environment variable or specifying `slackOAuthToken` option in the config:

@@ -127,3 +128,50 @@

---
# Option C - send your JSON results via CLI
Playwright now provides a nice way to [merge multiple reports from multiple shards](https://playwright.dev/docs/test-sharding#merging-reports-from-multiple-shards). You can use this feature to generate a single JSON report and then send it to Slack, alleviating the need to have separate messages sent per shard:
`npx playwright merge-reports --reporter json ./all-blob-reports`
^ It is important that you set the `--reporter` to `json` otherwise the report will not be generated in the correct format.
Next, you will need to configure the cli. See example below:
*cli_config.json:*
```json
{
"sendResults": "always",
"slackLogLevel": "error",
"sendUsingBot": {
"channels": ["demo"]
},
"showInThread": true,
"meta": [
{ "key": "build", "value" : "1.0.0"},
{ "key": "branch", "value" : "master"},
{ "key": "commit", "value" : "1234567890"},
{ "key": "results", "value" : "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"}
],
"maxNumberOfFailures": 4,
"disableUnfurl": true
}
The config file also supports the follow extra options for using a proxy and sending results via a webhook:
```json
...
"proxy": "http://proxy.mycompany.com:8080",
"sendUsingWebhook": {
"webhookUrl": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
},
...
```
Once you have generated the JSON report and defined your config file, you can send it to Slack using the following command:
`SLACK_BOT_USER_OAUTH_TOKEN=[your Slack bot user OAUTH token] npx playwright-slack-report -c cli_config.json -j ./merged_tests_results.json`
# ⚙️ Configuration

@@ -130,0 +178,0 @@

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