flakewatch-playwright 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ export { SmartRetryReporter } from './reporter.js';
2
+ export { SmartRetryReporter as default } from './reporter.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,kBAAkB,IAAI,OAAO,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { SmartRetryReporter } from './reporter.js';
2
+ export { SmartRetryReporter as default } from './reporter.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,kBAAkB,IAAI,OAAO,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
2
+ import type { SmartRetryConfig } from 'flakewatch-core';
3
+ export interface SmartRetryReporterOptions {
4
+ configPath?: string;
5
+ /** Override any config values */
6
+ config?: Partial<SmartRetryConfig>;
7
+ /** Print progress to console */
8
+ quiet?: boolean;
9
+ }
10
+ export declare class SmartRetryReporter implements Reporter {
11
+ private failures;
12
+ private totalTests;
13
+ private config;
14
+ private options;
15
+ constructor(options?: SmartRetryReporterOptions);
16
+ onBegin(config: FullConfig, suite: Suite): Promise<void>;
17
+ onTestEnd(test: TestCase, result: TestResult): void;
18
+ onEnd(result: FullResult): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,KAAK,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACX,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAErE,MAAM,WAAW,yBAAyB;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnC,gCAAgC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,kBAAmB,YAAW,QAAQ;IACjD,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,OAAO,CAA4B;gBAE/B,OAAO,GAAE,yBAA8B;IAI7C,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB9D,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAO7C,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CA8D/C"}
@@ -0,0 +1,105 @@
1
+ import { loadConfig, triageFailures, validateConfig } from 'flakewatch-core';
2
+ export class SmartRetryReporter {
3
+ failures = [];
4
+ totalTests = 0;
5
+ config = null;
6
+ options;
7
+ constructor(options = {}) {
8
+ this.options = options;
9
+ }
10
+ async onBegin(config, suite) {
11
+ this.totalTests = countTests(suite);
12
+ this.failures = [];
13
+ try {
14
+ this.config = await loadConfig(this.options.configPath, this.options.config);
15
+ }
16
+ catch (e) {
17
+ console.error(`[flakewatch] Failed to load config: ${e.message}`);
18
+ }
19
+ }
20
+ onTestEnd(test, result) {
21
+ if (result.status === 'failed' || result.status === 'timedOut') {
22
+ const failure = extractFailure(test, result);
23
+ this.failures.push(failure);
24
+ }
25
+ }
26
+ async onEnd(result) {
27
+ if (this.failures.length === 0) {
28
+ if (!this.options.quiet) {
29
+ console.log('[flakewatch] No failures to analyze.');
30
+ }
31
+ return;
32
+ }
33
+ if (!this.config) {
34
+ console.error('[flakewatch] No config loaded, skipping analysis.');
35
+ return;
36
+ }
37
+ const errors = validateConfig(this.config);
38
+ if (errors.length > 0) {
39
+ console.error(`[flakewatch] Config validation errors:`);
40
+ for (const err of errors) {
41
+ console.error(` - ${err}`);
42
+ }
43
+ return;
44
+ }
45
+ if (!this.options.quiet) {
46
+ console.log(`[flakewatch] Analyzing ${this.failures.length} failure(s) across ${this.totalTests} total test(s)...`);
47
+ }
48
+ try {
49
+ const report = await triageFailures({
50
+ failures: this.failures,
51
+ totalTests: this.totalTests,
52
+ config: this.config,
53
+ });
54
+ if (!this.options.quiet) {
55
+ const bugCount = report.results.filter((r) => r.verdict.type === 'likely_bug').length;
56
+ const staleCount = report.results.filter((r) => r.verdict.type === 'stale_test').length;
57
+ const ambiguousCount = report.results.filter((r) => r.verdict.type === 'ambiguous_test').length;
58
+ const flakyCount = report.results.filter((r) => r.verdict.type === 'flaky').length;
59
+ console.log(`[flakewatch] Analysis complete:`);
60
+ if (bugCount > 0)
61
+ console.log(` Likely bugs: ${bugCount}`);
62
+ if (staleCount > 0)
63
+ console.log(` Stale tests: ${staleCount}`);
64
+ if (ambiguousCount > 0)
65
+ console.log(` Ambiguous tests: ${ambiguousCount}`);
66
+ if (flakyCount > 0)
67
+ console.log(` Flaky tests: ${flakyCount}`);
68
+ console.log(` Report written to: ${this.config.output.dir}`);
69
+ }
70
+ }
71
+ catch (e) {
72
+ console.error(`[flakewatch] Analysis failed: ${e.message}`);
73
+ }
74
+ }
75
+ }
76
+ function extractFailure(test, result) {
77
+ const error = result.errors[0];
78
+ // Find screenshot attachment
79
+ const screenshot = result.attachments.find((a) => a.contentType === 'image/png' && a.path);
80
+ // Find trace attachment
81
+ const trace = result.attachments.find((a) => a.name === 'trace' && a.path);
82
+ return {
83
+ testId: test.id,
84
+ testTitle: test.title,
85
+ testFile: test.location.file,
86
+ line: test.location.line,
87
+ error: {
88
+ message: error?.message ?? 'Unknown error',
89
+ stack: error?.stack,
90
+ },
91
+ duration: result.duration,
92
+ retry: result.retry,
93
+ screenshotPath: screenshot?.path,
94
+ tracePath: trace?.path,
95
+ annotations: test.annotations.map((a) => a.description ? `${a.type}: ${a.description}` : a.type),
96
+ };
97
+ }
98
+ function countTests(suite) {
99
+ let count = 0;
100
+ for (const test of suite.allTests()) {
101
+ count++;
102
+ }
103
+ return count;
104
+ }
105
+ //# sourceMappingURL=reporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "flakewatch-playwright",
3
+ "version": "0.1.0",
4
+ "description": "Playwright reporter plugin that captures test failures and triages them with AI",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "test": "vitest run",
17
+ "clean": "rm -rf dist"
18
+ },
19
+ "dependencies": {
20
+ "flakewatch-core": "^0.1.0"
21
+ },
22
+ "peerDependencies": {
23
+ "@playwright/test": ">=1.40.0"
24
+ },
25
+ "devDependencies": {
26
+ "@playwright/test": "^1.50.0",
27
+ "typescript": "^5.7.0",
28
+ "vitest": "^3.0.0",
29
+ "@types/node": "^22.0.0"
30
+ },
31
+ "files": ["dist"],
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/jlawrence6809/smart-retry",
36
+ "directory": "packages/playwright"
37
+ },
38
+ "keywords": ["playwright", "reporter", "testing", "ai", "flaky-tests"]
39
+ }