@flakiness/playwright 1.6.0 → 1.7.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.
package/lib/playwright-test.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FlakinessReport as FK
|
|
3
|
+
} from "@flakiness/flakiness-report";
|
|
1
4
|
import {
|
|
2
5
|
CIUtils,
|
|
6
|
+
CPUUtilization,
|
|
3
7
|
GitWorktree,
|
|
8
|
+
RAMUtilization,
|
|
4
9
|
ReportUtils,
|
|
5
10
|
showReport,
|
|
6
11
|
showReportCommand,
|
|
7
|
-
CPUUtilization,
|
|
8
|
-
RAMUtilization,
|
|
9
12
|
uploadReport,
|
|
10
13
|
writeReport
|
|
11
14
|
} from "@flakiness/sdk";
|
|
@@ -36,6 +39,7 @@ class FlakinessReporter {
|
|
|
36
39
|
_config;
|
|
37
40
|
_rootSuite;
|
|
38
41
|
_results = /* @__PURE__ */ new Map();
|
|
42
|
+
_stdioEntries = /* @__PURE__ */ new Map();
|
|
39
43
|
_unattributedErrors = [];
|
|
40
44
|
_cpuUtilization = new CPUUtilization({ precision: 10 });
|
|
41
45
|
_ramUtilization = new RAMUtilization({ precision: 10 });
|
|
@@ -61,6 +65,25 @@ class FlakinessReporter {
|
|
|
61
65
|
}
|
|
62
66
|
onTestBegin(test) {
|
|
63
67
|
}
|
|
68
|
+
onStdOut(chunk, test, result) {
|
|
69
|
+
this._onStdio(chunk, "stdout", result);
|
|
70
|
+
}
|
|
71
|
+
onStdErr(chunk, test, result) {
|
|
72
|
+
this._onStdio(chunk, "stderr", result);
|
|
73
|
+
}
|
|
74
|
+
_onStdio(chunk, stream, result) {
|
|
75
|
+
if (!result) return;
|
|
76
|
+
let entries = this._stdioEntries.get(result);
|
|
77
|
+
if (!entries) {
|
|
78
|
+
entries = [];
|
|
79
|
+
this._stdioEntries.set(result, entries);
|
|
80
|
+
}
|
|
81
|
+
entries.push({
|
|
82
|
+
data: chunk,
|
|
83
|
+
stream: stream === "stderr" ? FK.STREAM_STDERR : FK.STREAM_STDOUT,
|
|
84
|
+
time: Date.now()
|
|
85
|
+
});
|
|
86
|
+
}
|
|
64
87
|
onTestEnd(test, result) {
|
|
65
88
|
const results = this._results.get(test) ?? /* @__PURE__ */ new Set();
|
|
66
89
|
results.add(result);
|
|
@@ -94,7 +117,6 @@ class FlakinessReporter {
|
|
|
94
117
|
};
|
|
95
118
|
}
|
|
96
119
|
async _toFKRunAttempt(context, pwTest, result) {
|
|
97
|
-
const attachments = [];
|
|
98
120
|
const attempt = {
|
|
99
121
|
timeout: parseDurationMS(pwTest.timeout),
|
|
100
122
|
annotations: pwTest.annotations.map((annotation) => ({
|
|
@@ -107,48 +129,74 @@ class FlakinessReporter {
|
|
|
107
129
|
parallelIndex: result.parallelIndex,
|
|
108
130
|
status: result.status,
|
|
109
131
|
errors: result.errors && result.errors.length ? result.errors.map((error) => this._toFKTestError(context, error)) : void 0,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
steps: result.steps ? result.steps.map((jsonTestStep) => this._toFKTestStep(context, jsonTestStep)) : void 0,
|
|
132
|
+
stdio: this._buildStdio(result),
|
|
133
|
+
steps: result.steps ? await Promise.all(result.steps.map((jsonTestStep) => this._toFKTestStep(context, jsonTestStep))) : void 0,
|
|
113
134
|
startTimestamp: +result.startTime,
|
|
114
135
|
duration: +result.duration,
|
|
115
|
-
attachments
|
|
136
|
+
attachments: await this._toFKAttachments(context, result.attachments)
|
|
116
137
|
};
|
|
117
|
-
await Promise.all((result.attachments ?? []).map(async (jsonAttachment) => {
|
|
118
|
-
if (jsonAttachment.path && !await existsAsync(jsonAttachment.path)) {
|
|
119
|
-
context.unaccessibleAttachmentPaths.push(jsonAttachment.path);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
let attachment;
|
|
123
|
-
if (jsonAttachment.path)
|
|
124
|
-
attachment = await ReportUtils.createFileAttachment(jsonAttachment.contentType, jsonAttachment.path);
|
|
125
|
-
else if (jsonAttachment.body)
|
|
126
|
-
attachment = await ReportUtils.createDataAttachment(jsonAttachment.contentType, jsonAttachment.body);
|
|
127
|
-
else
|
|
128
|
-
return;
|
|
129
|
-
context.attachments.set(attachment.id, attachment);
|
|
130
|
-
attachments.push({
|
|
131
|
-
id: attachment.id,
|
|
132
|
-
name: jsonAttachment.name,
|
|
133
|
-
contentType: jsonAttachment.contentType
|
|
134
|
-
});
|
|
135
|
-
}));
|
|
136
138
|
return attempt;
|
|
137
139
|
}
|
|
138
|
-
|
|
140
|
+
_buildStdio(result) {
|
|
141
|
+
const rawEntries = this._stdioEntries.get(result);
|
|
142
|
+
if (!rawEntries?.length)
|
|
143
|
+
return void 0;
|
|
144
|
+
const stdio = [];
|
|
145
|
+
let ts = +result.startTime;
|
|
146
|
+
for (const entry of rawEntries) {
|
|
147
|
+
const dts = Math.max(0, entry.time - ts);
|
|
148
|
+
ts = entry.time;
|
|
149
|
+
if (Buffer.isBuffer(entry.data))
|
|
150
|
+
stdio.push({ buffer: entry.data.toString("base64"), dts, stream: entry.stream });
|
|
151
|
+
else
|
|
152
|
+
stdio.push({ text: entry.data, dts, stream: entry.stream });
|
|
153
|
+
}
|
|
154
|
+
this._stdioEntries.delete(result);
|
|
155
|
+
return stdio;
|
|
156
|
+
}
|
|
157
|
+
async _toFKAttachments(context, pwAttachments) {
|
|
158
|
+
const all = await Promise.all(pwAttachments.map((psAttachment) => this._toFKAttachment(context, psAttachment)));
|
|
159
|
+
const filtered = all.filter((attachment) => attachment !== void 0);
|
|
160
|
+
return filtered.length ? filtered : void 0;
|
|
161
|
+
}
|
|
162
|
+
async _toFKAttachment(context, pwAttachment) {
|
|
163
|
+
let result = context.attachmentsCache.get(pwAttachment);
|
|
164
|
+
if (!result) {
|
|
165
|
+
result = (async () => {
|
|
166
|
+
if (pwAttachment.path && !await existsAsync(pwAttachment.path)) {
|
|
167
|
+
context.unaccessibleAttachmentPaths.push(pwAttachment.path);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
let attachment;
|
|
171
|
+
if (pwAttachment.path)
|
|
172
|
+
attachment = await ReportUtils.createFileAttachment(pwAttachment.contentType, pwAttachment.path);
|
|
173
|
+
else if (pwAttachment.body)
|
|
174
|
+
attachment = await ReportUtils.createDataAttachment(pwAttachment.contentType, pwAttachment.body);
|
|
175
|
+
else
|
|
176
|
+
return;
|
|
177
|
+
context.attachments.set(attachment.id, attachment);
|
|
178
|
+
return {
|
|
179
|
+
id: attachment.id,
|
|
180
|
+
name: pwAttachment.name,
|
|
181
|
+
contentType: pwAttachment.contentType
|
|
182
|
+
};
|
|
183
|
+
})();
|
|
184
|
+
context.attachmentsCache.set(pwAttachment, result);
|
|
185
|
+
}
|
|
186
|
+
return await result;
|
|
187
|
+
}
|
|
188
|
+
async _toFKTestStep(context, pwStep) {
|
|
139
189
|
const step = {
|
|
140
190
|
// NOTE: jsonStep.duration was -1 in some playwright versions
|
|
141
191
|
duration: parseDurationMS(Math.max(pwStep.duration, 0)),
|
|
142
192
|
title: pwStep.title,
|
|
143
|
-
location: pwStep.location ? this._createLocation(context, pwStep.location) : void 0
|
|
193
|
+
location: pwStep.location ? this._createLocation(context, pwStep.location) : void 0,
|
|
194
|
+
attachments: await this._toFKAttachments(context, pwStep.attachments)
|
|
144
195
|
};
|
|
145
|
-
if (pwStep.location) {
|
|
146
|
-
const resolvedPath = path.resolve(pwStep.location.file);
|
|
147
|
-
}
|
|
148
196
|
if (pwStep.error)
|
|
149
197
|
step.error = this._toFKTestError(context, pwStep.error);
|
|
150
198
|
if (pwStep.steps)
|
|
151
|
-
step.steps = pwStep.steps.map((childJSONStep) => this._toFKTestStep(context, childJSONStep));
|
|
199
|
+
step.steps = await Promise.all(pwStep.steps.map((childJSONStep) => this._toFKTestStep(context, childJSONStep)));
|
|
152
200
|
return step;
|
|
153
201
|
}
|
|
154
202
|
_createLocation(context, pwLocation) {
|
|
@@ -188,6 +236,7 @@ class FlakinessReporter {
|
|
|
188
236
|
project2environmentIdx: /* @__PURE__ */ new Map(),
|
|
189
237
|
worktree,
|
|
190
238
|
attachments: /* @__PURE__ */ new Map(),
|
|
239
|
+
attachmentsCache: /* @__PURE__ */ new Map(),
|
|
191
240
|
unaccessibleAttachmentPaths: []
|
|
192
241
|
};
|
|
193
242
|
const environmentsMap = createEnvironments(this._config.projects);
|
|
@@ -280,11 +329,6 @@ To open last Flakiness report, run:
|
|
|
280
329
|
function envBool(name) {
|
|
281
330
|
return ["1", "true"].includes(process.env[name]?.toLowerCase() ?? "");
|
|
282
331
|
}
|
|
283
|
-
function toSTDIOEntry(data) {
|
|
284
|
-
if (Buffer.isBuffer(data))
|
|
285
|
-
return { buffer: data.toString("base64") };
|
|
286
|
-
return { text: data };
|
|
287
|
-
}
|
|
288
332
|
function createEnvironments(projects) {
|
|
289
333
|
let uniqueNames = /* @__PURE__ */ new Set();
|
|
290
334
|
const result = /* @__PURE__ */ new Map();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flakiness/playwright",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"author": "Degu Labs, Inc",
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@flakiness/playwright": "^1.
|
|
31
|
+
"@flakiness/playwright": "^1.6.0",
|
|
32
32
|
"@playwright/test": "^1.57.0",
|
|
33
33
|
"@types/node": "^25.0.3",
|
|
34
34
|
"esbuild": "^0.27.2",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"typescript": "^5.9.3"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@flakiness/flakiness-report": "^0.
|
|
41
|
-
"@flakiness/sdk": "^2.
|
|
40
|
+
"@flakiness/flakiness-report": "^0.31.0",
|
|
41
|
+
"@flakiness/sdk": "^2.7.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "kubik build.mts",
|
|
@@ -5,6 +5,7 @@ export default class FlakinessReporter implements Reporter {
|
|
|
5
5
|
private _config?;
|
|
6
6
|
private _rootSuite?;
|
|
7
7
|
private _results;
|
|
8
|
+
private _stdioEntries;
|
|
8
9
|
private _unattributedErrors;
|
|
9
10
|
private _cpuUtilization;
|
|
10
11
|
private _ramUtilization;
|
|
@@ -28,10 +29,16 @@ export default class FlakinessReporter implements Reporter {
|
|
|
28
29
|
onBegin(config: FullConfig, suite: Suite): void;
|
|
29
30
|
onError(error: TestError): void;
|
|
30
31
|
onTestBegin(test: TestCase): void;
|
|
32
|
+
onStdOut(chunk: string | Buffer, test: TestCase | void, result: TestResult | void): void;
|
|
33
|
+
onStdErr(chunk: string | Buffer, test: TestCase | void, result: TestResult | void): void;
|
|
34
|
+
private _onStdio;
|
|
31
35
|
onTestEnd(test: TestCase, result: TestResult): void;
|
|
32
36
|
private _toFKSuites;
|
|
33
37
|
private _toFKTest;
|
|
34
38
|
private _toFKRunAttempt;
|
|
39
|
+
private _buildStdio;
|
|
40
|
+
private _toFKAttachments;
|
|
41
|
+
private _toFKAttachment;
|
|
35
42
|
private _toFKTestStep;
|
|
36
43
|
private _createLocation;
|
|
37
44
|
private _toFKTestError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright-test.d.ts","sourceRoot":"","sources":["../../src/playwright-test.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,UAAU,EAEV,UAAU,EAEV,QAAQ,EACR,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAEvC,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"playwright-test.d.ts","sourceRoot":"","sources":["../../src/playwright-test.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,UAAU,EAEV,UAAU,EAEV,QAAQ,EACR,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAEvC,MAAM,2BAA2B,CAAC;AAwCnC,KAAK,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;AAQlD,MAAM,CAAC,OAAO,OAAO,iBAAkB,YAAW,QAAQ;IAiB5C,OAAO,CAAC,QAAQ;IAhB5B,OAAO,CAAC,OAAO,CAAC,CAAa;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAwC;IACxD,OAAO,CAAC,aAAa,CAAuC;IAC5D,OAAO,CAAC,mBAAmB,CAAmB;IAE9C,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,aAAa,CAAS;IAE9B,OAAO,CAAC,OAAO,CAAC,CAAa;IAE7B,OAAO,CAAC,eAAe,CAAC,CAAiB;gBAErB,QAAQ,GAAE;QAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,IAAI,CAAC,EAAE,QAAQ,CAAC;QAChB,sBAAsB,CAAC,EAAE,OAAO,CAAC;QACjC,aAAa,CAAC,EAAE,OAAO,CAAC;KACpB;IAON,OAAO,CAAC,aAAa;IAMrB,aAAa,IAAI,OAAO;IAIxB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK;IAKxC,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAI/B,WAAW,CAAC,IAAI,EAAE,QAAQ;IAG1B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAIjF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAIjF,OAAO,CAAC,QAAQ;IAchB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU;YAM9B,WAAW;YAsBX,SAAS;YAWT,eAAe;IA0B7B,OAAO,CAAC,WAAW;YAkBL,gBAAgB;YAMhB,eAAe;YA4Bf,aAAa;IAgB3B,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,cAAc;IAUhB,KAAK,CAAC,MAAM,EAAE,UAAU;IAoGxB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CA4B9B"}
|