@testdino/playwright 1.0.8 → 1.0.10
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/README.md +81 -6
- package/bin/tdpw.js +2 -2
- package/dist/cli/index.mjs +51 -34
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.mts +2 -10
- package/dist/index.d.ts +2 -10
- package/dist/index.js +229 -149
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +131 -67
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +0 -935
- package/dist/cli/index.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,35 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Object.defineProperty
|
|
4
|
-
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
|
-
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
coverageFixtures: () => coverageFixtures,
|
|
34
|
+
default: () => TestdinoReporter,
|
|
35
|
+
expect: () => import_test.expect,
|
|
36
|
+
test: () => test
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(src_exports);
|
|
21
39
|
|
|
22
|
-
|
|
23
|
-
var
|
|
24
|
-
var
|
|
25
|
-
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
40
|
+
// src/reporter/index.ts
|
|
41
|
+
var import_crypto2 = require("crypto");
|
|
42
|
+
var import_fs2 = require("fs");
|
|
26
43
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}) : x)(function(x) {
|
|
30
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
31
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
32
|
-
});
|
|
44
|
+
// src/streaming/websocket.ts
|
|
45
|
+
var import_ws = __toESM(require("ws"));
|
|
33
46
|
|
|
34
47
|
// src/reporter/errors.ts
|
|
35
48
|
var TestDinoServerError = class extends Error {
|
|
@@ -101,7 +114,7 @@ var WebSocketClient = class {
|
|
|
101
114
|
* Passes sessionId from HTTP auth so the server reuses the existing session.
|
|
102
115
|
*/
|
|
103
116
|
async connect() {
|
|
104
|
-
if (this.isConnecting || this.ws?.readyState ===
|
|
117
|
+
if (this.isConnecting || this.ws?.readyState === import_ws.default.OPEN) {
|
|
105
118
|
return;
|
|
106
119
|
}
|
|
107
120
|
this.isConnecting = true;
|
|
@@ -111,7 +124,7 @@ var WebSocketClient = class {
|
|
|
111
124
|
if (this.options.sessionId) {
|
|
112
125
|
wsUrl += `&sessionId=${this.options.sessionId}`;
|
|
113
126
|
}
|
|
114
|
-
this.ws = new
|
|
127
|
+
this.ws = new import_ws.default(wsUrl);
|
|
115
128
|
let serverReady = false;
|
|
116
129
|
const handshakeTimeout = setTimeout(() => {
|
|
117
130
|
if (!serverReady) {
|
|
@@ -175,7 +188,7 @@ var WebSocketClient = class {
|
|
|
175
188
|
* Send event through WebSocket
|
|
176
189
|
*/
|
|
177
190
|
async send(event) {
|
|
178
|
-
if (!this.ws || this.ws.readyState !==
|
|
191
|
+
if (!this.ws || this.ws.readyState !== import_ws.default.OPEN) {
|
|
179
192
|
throw new Error("WebSocket is not connected");
|
|
180
193
|
}
|
|
181
194
|
return new Promise((resolve, reject) => {
|
|
@@ -193,7 +206,7 @@ var WebSocketClient = class {
|
|
|
193
206
|
* Note: Uses Promise.all intentionally - if one send fails, connection is broken
|
|
194
207
|
*/
|
|
195
208
|
async sendBatch(events) {
|
|
196
|
-
if (!this.ws || this.ws.readyState !==
|
|
209
|
+
if (!this.ws || this.ws.readyState !== import_ws.default.OPEN) {
|
|
197
210
|
throw new Error("WebSocket is not connected");
|
|
198
211
|
}
|
|
199
212
|
await Promise.all(events.map((event) => this.send(event)));
|
|
@@ -203,7 +216,7 @@ var WebSocketClient = class {
|
|
|
203
216
|
* Use this for critical events like run:end where delivery must be confirmed
|
|
204
217
|
*/
|
|
205
218
|
async sendAndWaitForAck(event, timeout = this.ackTimeout) {
|
|
206
|
-
if (!this.ws || this.ws.readyState !==
|
|
219
|
+
if (!this.ws || this.ws.readyState !== import_ws.default.OPEN) {
|
|
207
220
|
throw new Error("WebSocket is not connected");
|
|
208
221
|
}
|
|
209
222
|
const sequence = event.sequence;
|
|
@@ -232,7 +245,7 @@ var WebSocketClient = class {
|
|
|
232
245
|
* Check if WebSocket is connected
|
|
233
246
|
*/
|
|
234
247
|
isConnected() {
|
|
235
|
-
return this.ws?.readyState ===
|
|
248
|
+
return this.ws?.readyState === import_ws.default.OPEN;
|
|
236
249
|
}
|
|
237
250
|
/**
|
|
238
251
|
* Close WebSocket connection
|
|
@@ -367,7 +380,7 @@ var WebSocketClient = class {
|
|
|
367
380
|
startPing() {
|
|
368
381
|
this.stopPing();
|
|
369
382
|
this.pingInterval = setInterval(() => {
|
|
370
|
-
if (this.ws?.readyState ===
|
|
383
|
+
if (this.ws?.readyState === import_ws.default.OPEN) {
|
|
371
384
|
this.ws.ping();
|
|
372
385
|
}
|
|
373
386
|
}, 3e4);
|
|
@@ -382,9 +395,15 @@ var WebSocketClient = class {
|
|
|
382
395
|
}
|
|
383
396
|
}
|
|
384
397
|
};
|
|
398
|
+
|
|
399
|
+
// src/streaming/http.ts
|
|
400
|
+
var import_axios = __toESM(require("axios"));
|
|
401
|
+
|
|
402
|
+
// src/utils/index.ts
|
|
403
|
+
var import_path = require("path");
|
|
385
404
|
function normalizePath(filePath, rootDir) {
|
|
386
405
|
if (rootDir && filePath.startsWith(rootDir)) {
|
|
387
|
-
return
|
|
406
|
+
return (0, import_path.relative)(rootDir, filePath);
|
|
388
407
|
}
|
|
389
408
|
return filePath;
|
|
390
409
|
}
|
|
@@ -405,7 +424,7 @@ var HttpClient = class {
|
|
|
405
424
|
retryDelay: 1e3,
|
|
406
425
|
...options
|
|
407
426
|
};
|
|
408
|
-
this.client =
|
|
427
|
+
this.client = import_axios.default.create({
|
|
409
428
|
baseURL: this.options.serverUrl,
|
|
410
429
|
headers: {
|
|
411
430
|
"Content-Type": "application/json",
|
|
@@ -422,7 +441,7 @@ var HttpClient = class {
|
|
|
422
441
|
const response = await this.client.post("/auth");
|
|
423
442
|
return response.data;
|
|
424
443
|
} catch (error) {
|
|
425
|
-
if (
|
|
444
|
+
if (import_axios.default.isAxiosError(error) && error.response?.status === 402) {
|
|
426
445
|
const quotaError = error.response.data;
|
|
427
446
|
throw new QuotaExhaustedError(quotaError.message, quotaError.details);
|
|
428
447
|
}
|
|
@@ -458,7 +477,7 @@ var HttpClient = class {
|
|
|
458
477
|
* Extract error message from various error types
|
|
459
478
|
*/
|
|
460
479
|
getErrorMessage(error) {
|
|
461
|
-
if (
|
|
480
|
+
if (import_axios.default.isAxiosError(error)) {
|
|
462
481
|
return error.response?.data?.message || error.message;
|
|
463
482
|
}
|
|
464
483
|
if (error instanceof Error) {
|
|
@@ -550,6 +569,9 @@ var EventBuffer = class {
|
|
|
550
569
|
}
|
|
551
570
|
};
|
|
552
571
|
|
|
572
|
+
// src/metadata/git.ts
|
|
573
|
+
var import_promises = require("fs/promises");
|
|
574
|
+
|
|
553
575
|
// src/metadata/base.ts
|
|
554
576
|
var BaseMetadataCollector = class {
|
|
555
577
|
name;
|
|
@@ -635,6 +657,16 @@ var BaseMetadataCollector = class {
|
|
|
635
657
|
};
|
|
636
658
|
|
|
637
659
|
// src/metadata/git.ts
|
|
660
|
+
var execaPromise = null;
|
|
661
|
+
async function getExeca() {
|
|
662
|
+
if (!execaPromise) {
|
|
663
|
+
execaPromise = import("execa").then((m) => m.execa).catch((error) => {
|
|
664
|
+
console.error("Failed to import execa:", error.message);
|
|
665
|
+
throw new Error("Failed to load execa. Ensure execa is installed: npm install execa");
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
return execaPromise;
|
|
669
|
+
}
|
|
638
670
|
var GitMetadataCollector = class extends BaseMetadataCollector {
|
|
639
671
|
options;
|
|
640
672
|
constructor(options = {}) {
|
|
@@ -727,7 +759,8 @@ var GitMetadataCollector = class extends BaseMetadataCollector {
|
|
|
727
759
|
const isCI = process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true";
|
|
728
760
|
if (!isCI) return;
|
|
729
761
|
try {
|
|
730
|
-
|
|
762
|
+
const execa = await getExeca();
|
|
763
|
+
await execa("git", ["config", "--global", "--add", "safe.directory", this.options.cwd], {
|
|
731
764
|
timeout: this.options.timeout,
|
|
732
765
|
reject: true
|
|
733
766
|
});
|
|
@@ -742,7 +775,7 @@ var GitMetadataCollector = class extends BaseMetadataCollector {
|
|
|
742
775
|
if (!eventPath) return void 0;
|
|
743
776
|
try {
|
|
744
777
|
const content = await this.withTimeout(
|
|
745
|
-
|
|
778
|
+
(0, import_promises.readFile)(eventPath, "utf-8"),
|
|
746
779
|
this.options.timeout,
|
|
747
780
|
"GitHub event file read"
|
|
748
781
|
);
|
|
@@ -1026,8 +1059,9 @@ var GitMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1026
1059
|
* Execute git command with timeout
|
|
1027
1060
|
*/
|
|
1028
1061
|
async execGit(args) {
|
|
1062
|
+
const execa = await getExeca();
|
|
1029
1063
|
const { stdout } = await this.withTimeout(
|
|
1030
|
-
execa
|
|
1064
|
+
execa("git", args, {
|
|
1031
1065
|
cwd: this.options.cwd,
|
|
1032
1066
|
timeout: this.options.timeout,
|
|
1033
1067
|
reject: true
|
|
@@ -1038,6 +1072,9 @@ var GitMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1038
1072
|
return stdout.trim();
|
|
1039
1073
|
}
|
|
1040
1074
|
};
|
|
1075
|
+
|
|
1076
|
+
// src/metadata/ci.ts
|
|
1077
|
+
var import_os = require("os");
|
|
1041
1078
|
var CIMetadataCollector = class extends BaseMetadataCollector {
|
|
1042
1079
|
constructor(_options = {}) {
|
|
1043
1080
|
super("ci");
|
|
@@ -1115,9 +1152,9 @@ var CIMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1115
1152
|
collectEnvironment() {
|
|
1116
1153
|
try {
|
|
1117
1154
|
return {
|
|
1118
|
-
name:
|
|
1155
|
+
name: (0, import_os.type)(),
|
|
1119
1156
|
type: process.platform,
|
|
1120
|
-
os: `${
|
|
1157
|
+
os: `${(0, import_os.type)()} ${(0, import_os.release)()}`,
|
|
1121
1158
|
node: process.version
|
|
1122
1159
|
};
|
|
1123
1160
|
} catch {
|
|
@@ -1125,6 +1162,10 @@ var CIMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1125
1162
|
}
|
|
1126
1163
|
}
|
|
1127
1164
|
};
|
|
1165
|
+
|
|
1166
|
+
// src/metadata/system.ts
|
|
1167
|
+
var import_os2 = require("os");
|
|
1168
|
+
var import_process = require("process");
|
|
1128
1169
|
var SystemMetadataCollector = class extends BaseMetadataCollector {
|
|
1129
1170
|
constructor(_options = {}) {
|
|
1130
1171
|
super("system");
|
|
@@ -1159,11 +1200,11 @@ var SystemMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1159
1200
|
let platformName = "unknown";
|
|
1160
1201
|
let releaseVersion = "unknown";
|
|
1161
1202
|
try {
|
|
1162
|
-
platformName =
|
|
1203
|
+
platformName = (0, import_os2.platform)();
|
|
1163
1204
|
} catch {
|
|
1164
1205
|
}
|
|
1165
1206
|
try {
|
|
1166
|
-
releaseVersion =
|
|
1207
|
+
releaseVersion = (0, import_os2.release)();
|
|
1167
1208
|
} catch {
|
|
1168
1209
|
}
|
|
1169
1210
|
return `${platformName} ${releaseVersion}`;
|
|
@@ -1174,7 +1215,7 @@ var SystemMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1174
1215
|
*/
|
|
1175
1216
|
getCpuInfo() {
|
|
1176
1217
|
try {
|
|
1177
|
-
const cpuList =
|
|
1218
|
+
const cpuList = (0, import_os2.cpus)();
|
|
1178
1219
|
if (cpuList.length === 0) {
|
|
1179
1220
|
return "unknown";
|
|
1180
1221
|
}
|
|
@@ -1191,7 +1232,7 @@ var SystemMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1191
1232
|
*/
|
|
1192
1233
|
getMemoryInfo() {
|
|
1193
1234
|
try {
|
|
1194
|
-
const totalBytes =
|
|
1235
|
+
const totalBytes = (0, import_os2.totalmem)();
|
|
1195
1236
|
const totalGB = totalBytes / (1024 * 1024 * 1024);
|
|
1196
1237
|
return `${totalGB.toFixed(1)} GB`;
|
|
1197
1238
|
} catch {
|
|
@@ -1204,7 +1245,7 @@ var SystemMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1204
1245
|
*/
|
|
1205
1246
|
getNodeVersion() {
|
|
1206
1247
|
try {
|
|
1207
|
-
return
|
|
1248
|
+
return import_process.version;
|
|
1208
1249
|
} catch {
|
|
1209
1250
|
return "unknown";
|
|
1210
1251
|
}
|
|
@@ -1215,7 +1256,7 @@ var SystemMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1215
1256
|
*/
|
|
1216
1257
|
getPlatform() {
|
|
1217
1258
|
try {
|
|
1218
|
-
return
|
|
1259
|
+
return (0, import_os2.platform)();
|
|
1219
1260
|
} catch {
|
|
1220
1261
|
return "unknown";
|
|
1221
1262
|
}
|
|
@@ -1226,12 +1267,15 @@ var SystemMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1226
1267
|
*/
|
|
1227
1268
|
getHostname() {
|
|
1228
1269
|
try {
|
|
1229
|
-
return
|
|
1270
|
+
return (0, import_os2.hostname)();
|
|
1230
1271
|
} catch {
|
|
1231
1272
|
return "unknown";
|
|
1232
1273
|
}
|
|
1233
1274
|
}
|
|
1234
1275
|
};
|
|
1276
|
+
|
|
1277
|
+
// src/metadata/playwright.ts
|
|
1278
|
+
var import_promises2 = require("fs/promises");
|
|
1235
1279
|
var PlaywrightMetadataCollector = class extends BaseMetadataCollector {
|
|
1236
1280
|
options;
|
|
1237
1281
|
constructor(options = {}) {
|
|
@@ -1281,7 +1325,7 @@ var PlaywrightMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1281
1325
|
return void 0;
|
|
1282
1326
|
}
|
|
1283
1327
|
const packageJsonContent = await this.withTimeout(
|
|
1284
|
-
|
|
1328
|
+
(0, import_promises2.readFile)(packageJsonPath, "utf-8"),
|
|
1285
1329
|
this.options.timeout,
|
|
1286
1330
|
"Playwright package.json read"
|
|
1287
1331
|
);
|
|
@@ -1300,7 +1344,7 @@ var PlaywrightMetadataCollector = class extends BaseMetadataCollector {
|
|
|
1300
1344
|
*/
|
|
1301
1345
|
resolvePlaywrightPackageJson() {
|
|
1302
1346
|
try {
|
|
1303
|
-
return
|
|
1347
|
+
return require.resolve("@playwright/test/package.json");
|
|
1304
1348
|
} catch {
|
|
1305
1349
|
return void 0;
|
|
1306
1350
|
}
|
|
@@ -1704,6 +1748,9 @@ function createMetadataCollector(playwrightConfig, playwrightSuite) {
|
|
|
1704
1748
|
);
|
|
1705
1749
|
return aggregator;
|
|
1706
1750
|
}
|
|
1751
|
+
|
|
1752
|
+
// src/uploads/sas-token-client.ts
|
|
1753
|
+
var import_axios2 = __toESM(require("axios"));
|
|
1707
1754
|
var SASTokenClient = class {
|
|
1708
1755
|
client;
|
|
1709
1756
|
options;
|
|
@@ -1713,7 +1760,7 @@ var SASTokenClient = class {
|
|
|
1713
1760
|
retryDelay: 1e3,
|
|
1714
1761
|
...options
|
|
1715
1762
|
};
|
|
1716
|
-
this.client =
|
|
1763
|
+
this.client = import_axios2.default.create({
|
|
1717
1764
|
baseURL: this.options.serverUrl,
|
|
1718
1765
|
headers: {
|
|
1719
1766
|
"Content-Type": "application/json",
|
|
@@ -1755,7 +1802,7 @@ var SASTokenClient = class {
|
|
|
1755
1802
|
* Extract error message from various error types
|
|
1756
1803
|
*/
|
|
1757
1804
|
getErrorMessage(error) {
|
|
1758
|
-
if (
|
|
1805
|
+
if (import_axios2.default.isAxiosError(error)) {
|
|
1759
1806
|
if (error.response?.status === 401) {
|
|
1760
1807
|
return "Invalid API key for artifact uploads";
|
|
1761
1808
|
}
|
|
@@ -1773,6 +1820,11 @@ var SASTokenClient = class {
|
|
|
1773
1820
|
return String(error);
|
|
1774
1821
|
}
|
|
1775
1822
|
};
|
|
1823
|
+
|
|
1824
|
+
// src/uploads/artifact-uploader.ts
|
|
1825
|
+
var import_fs = require("fs");
|
|
1826
|
+
var import_path2 = require("path");
|
|
1827
|
+
var import_axios3 = __toESM(require("axios"));
|
|
1776
1828
|
var ArtifactUploader = class {
|
|
1777
1829
|
sasToken;
|
|
1778
1830
|
options;
|
|
@@ -1793,9 +1845,9 @@ var ArtifactUploader = class {
|
|
|
1793
1845
|
*/
|
|
1794
1846
|
async uploadFile(attachment, testId) {
|
|
1795
1847
|
const startTime = Date.now();
|
|
1796
|
-
const fileName =
|
|
1848
|
+
const fileName = (0, import_path2.basename)(attachment.path);
|
|
1797
1849
|
try {
|
|
1798
|
-
const stats =
|
|
1850
|
+
const stats = (0, import_fs.statSync)(attachment.path);
|
|
1799
1851
|
const fileSize = stats.size;
|
|
1800
1852
|
if (fileSize > this.sasToken.maxSize) {
|
|
1801
1853
|
return {
|
|
@@ -1806,7 +1858,7 @@ var ArtifactUploader = class {
|
|
|
1806
1858
|
duration: Date.now() - startTime
|
|
1807
1859
|
};
|
|
1808
1860
|
}
|
|
1809
|
-
const extension =
|
|
1861
|
+
const extension = (0, import_path2.extname)(fileName).slice(1).toLowerCase();
|
|
1810
1862
|
const allowedTypes = this.sasToken.allowedFileTypes;
|
|
1811
1863
|
if (allowedTypes.length > 0 && !allowedTypes.includes(extension)) {
|
|
1812
1864
|
return {
|
|
@@ -1916,9 +1968,9 @@ var ArtifactUploader = class {
|
|
|
1916
1968
|
* Perform actual file upload to Azure
|
|
1917
1969
|
*/
|
|
1918
1970
|
async doUpload(filePath, uploadUrl, contentType) {
|
|
1919
|
-
const fileStream =
|
|
1920
|
-
const stats =
|
|
1921
|
-
await
|
|
1971
|
+
const fileStream = (0, import_fs.createReadStream)(filePath);
|
|
1972
|
+
const stats = (0, import_fs.statSync)(filePath);
|
|
1973
|
+
await import_axios3.default.put(uploadUrl, fileStream, {
|
|
1922
1974
|
headers: {
|
|
1923
1975
|
"Content-Type": contentType,
|
|
1924
1976
|
"Content-Length": stats.size,
|
|
@@ -1944,6 +1996,10 @@ var ArtifactUploader = class {
|
|
|
1944
1996
|
return this.sasToken.uniqueId;
|
|
1945
1997
|
}
|
|
1946
1998
|
};
|
|
1999
|
+
|
|
2000
|
+
// src/code-coverage/merger.ts
|
|
2001
|
+
var import_istanbul_lib_coverage = __toESM(require("istanbul-lib-coverage"));
|
|
2002
|
+
var import_picomatch = __toESM(require("picomatch"));
|
|
1947
2003
|
function toIstanbulMapData(map) {
|
|
1948
2004
|
return map;
|
|
1949
2005
|
}
|
|
@@ -1951,7 +2007,7 @@ function fromIstanbulMapData(data) {
|
|
|
1951
2007
|
return data;
|
|
1952
2008
|
}
|
|
1953
2009
|
var CoverageMerger = class {
|
|
1954
|
-
coverageMap =
|
|
2010
|
+
coverageMap = import_istanbul_lib_coverage.default.createCoverageMap({});
|
|
1955
2011
|
hasData = false;
|
|
1956
2012
|
includePatterns;
|
|
1957
2013
|
excludePatterns;
|
|
@@ -1983,18 +2039,20 @@ var CoverageMerger = class {
|
|
|
1983
2039
|
}
|
|
1984
2040
|
}
|
|
1985
2041
|
/**
|
|
1986
|
-
* Filter files from a coverage map based on include/exclude patterns.
|
|
2042
|
+
* Filter files from a coverage map based on include/exclude glob patterns.
|
|
1987
2043
|
*/
|
|
1988
2044
|
filterCoverageMap(coverageMap) {
|
|
1989
2045
|
const hasInclude = this.includePatterns && this.includePatterns.length > 0;
|
|
1990
2046
|
const hasExclude = this.excludePatterns && this.excludePatterns.length > 0;
|
|
1991
2047
|
if (!hasInclude && !hasExclude) return coverageMap;
|
|
2048
|
+
const isExcluded = hasExclude ? (0, import_picomatch.default)(this.excludePatterns) : void 0;
|
|
2049
|
+
const isIncluded = hasInclude ? (0, import_picomatch.default)(this.includePatterns) : void 0;
|
|
1992
2050
|
const filtered = {};
|
|
1993
2051
|
for (const [filePath, fileCoverage] of Object.entries(coverageMap)) {
|
|
1994
|
-
if (
|
|
2052
|
+
if (isExcluded && isExcluded(filePath)) {
|
|
1995
2053
|
continue;
|
|
1996
2054
|
}
|
|
1997
|
-
if (
|
|
2055
|
+
if (isIncluded && !isIncluded(filePath)) {
|
|
1998
2056
|
continue;
|
|
1999
2057
|
}
|
|
2000
2058
|
filtered[filePath] = fileCoverage;
|
|
@@ -2058,6 +2116,9 @@ function extractMetric(metric) {
|
|
|
2058
2116
|
pct: metric.pct
|
|
2059
2117
|
};
|
|
2060
2118
|
}
|
|
2119
|
+
|
|
2120
|
+
// src/code-coverage/compact.ts
|
|
2121
|
+
var import_crypto = require("crypto");
|
|
2061
2122
|
function extractCompactCounts(coverageMapJSON, gitRoot) {
|
|
2062
2123
|
const files = {};
|
|
2063
2124
|
let fileCount = 0;
|
|
@@ -2093,14 +2154,19 @@ function computeShapeHash(fileCoverage) {
|
|
|
2093
2154
|
b: countBranchPaths(branchMap),
|
|
2094
2155
|
bp: Object.values(branchMap).map((b) => (b.locations || []).length)
|
|
2095
2156
|
};
|
|
2096
|
-
return
|
|
2157
|
+
return (0, import_crypto.createHash)("sha256").update(JSON.stringify(shape)).digest("hex").slice(0, 12);
|
|
2097
2158
|
}
|
|
2159
|
+
|
|
2160
|
+
// src/code-coverage/html-report.ts
|
|
2161
|
+
var import_istanbul_lib_report = require("istanbul-lib-report");
|
|
2162
|
+
var import_istanbul_reports = require("istanbul-reports");
|
|
2163
|
+
var import_promises3 = require("fs/promises");
|
|
2098
2164
|
async function generateIstanbulHtmlReport(coverageMerger, options) {
|
|
2099
|
-
await
|
|
2165
|
+
await (0, import_promises3.rm)(options.outputDir, { recursive: true, force: true }).catch(() => {
|
|
2100
2166
|
});
|
|
2101
|
-
await
|
|
2167
|
+
await (0, import_promises3.mkdir)(options.outputDir, { recursive: true });
|
|
2102
2168
|
const coverageMap = coverageMerger.getRawCoverageMap();
|
|
2103
|
-
const context =
|
|
2169
|
+
const context = (0, import_istanbul_lib_report.createContext)({
|
|
2104
2170
|
dir: options.outputDir,
|
|
2105
2171
|
watermarks: {
|
|
2106
2172
|
statements: [50, 80],
|
|
@@ -2110,13 +2176,16 @@ async function generateIstanbulHtmlReport(coverageMerger, options) {
|
|
|
2110
2176
|
},
|
|
2111
2177
|
coverageMap
|
|
2112
2178
|
});
|
|
2113
|
-
const reporter =
|
|
2179
|
+
const reporter = (0, import_istanbul_reports.create)("html", {
|
|
2114
2180
|
skipEmpty: false,
|
|
2115
2181
|
subdir: ""
|
|
2116
2182
|
});
|
|
2117
2183
|
reporter.execute(context);
|
|
2118
2184
|
return `${options.outputDir}/index.html`;
|
|
2119
2185
|
}
|
|
2186
|
+
|
|
2187
|
+
// src/code-coverage/fixtures.ts
|
|
2188
|
+
var import_test = require("@playwright/test");
|
|
2120
2189
|
var COVERAGE_EXTRACT_TIMEOUT_MS = 3e4;
|
|
2121
2190
|
async function extractCoverageFromPage(page, timeoutMs = COVERAGE_EXTRACT_TIMEOUT_MS) {
|
|
2122
2191
|
return Promise.race([
|
|
@@ -2145,9 +2214,30 @@ var coverageFixtures = {
|
|
|
2145
2214
|
{ auto: true }
|
|
2146
2215
|
]
|
|
2147
2216
|
};
|
|
2148
|
-
var test =
|
|
2217
|
+
var test = import_test.test.extend(
|
|
2149
2218
|
coverageFixtures
|
|
2150
2219
|
);
|
|
2220
|
+
|
|
2221
|
+
// src/reporter/log.ts
|
|
2222
|
+
var chalkPromise = null;
|
|
2223
|
+
async function getChalk() {
|
|
2224
|
+
if (!chalkPromise) {
|
|
2225
|
+
chalkPromise = import("chalk").then((m) => m.default).catch((error) => {
|
|
2226
|
+
console.warn("\u26A0\uFE0F TestDino: Failed to load chalk, using plain text output");
|
|
2227
|
+
console.debug("Chalk import error:", error.message);
|
|
2228
|
+
return {
|
|
2229
|
+
green: (s) => s,
|
|
2230
|
+
yellow: (s) => s,
|
|
2231
|
+
red: (s) => s,
|
|
2232
|
+
blue: (s) => s,
|
|
2233
|
+
cyan: (s) => s,
|
|
2234
|
+
dim: (s) => s,
|
|
2235
|
+
bold: (s) => s
|
|
2236
|
+
};
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
return chalkPromise;
|
|
2240
|
+
}
|
|
2151
2241
|
function stripAnsi(str) {
|
|
2152
2242
|
return str.replace(/\u001b\[[0-9;]*m/g, "");
|
|
2153
2243
|
}
|
|
@@ -2176,20 +2266,20 @@ function shortenPath(filePath) {
|
|
|
2176
2266
|
const parts = filePath.split("/");
|
|
2177
2267
|
return parts.length > 2 ? parts.slice(-2).join("/") : filePath;
|
|
2178
2268
|
}
|
|
2179
|
-
function colorPct(pct) {
|
|
2180
|
-
const color = pct >= 80 ?
|
|
2269
|
+
function colorPct(pct, chalk) {
|
|
2270
|
+
const color = pct >= 80 ? chalk.green : pct >= 50 ? chalk.yellow : chalk.red;
|
|
2181
2271
|
return color(pct === 100 ? "100%" : `${pct.toFixed(1)}%`);
|
|
2182
2272
|
}
|
|
2183
|
-
function
|
|
2273
|
+
function printCoverageTableWithChalk(event, chalk) {
|
|
2184
2274
|
const { summary, files } = event;
|
|
2185
|
-
const row = (content) => ` ${
|
|
2275
|
+
const row = (content) => ` ${chalk.dim("\u2502")} ${content}`;
|
|
2186
2276
|
const nameW = 30;
|
|
2187
2277
|
const colW = 10;
|
|
2188
|
-
console.log(row(`${
|
|
2278
|
+
console.log(row(`${chalk.bold("Coverage")} ${chalk.dim(`${files.length} files`)}`));
|
|
2189
2279
|
console.log(row(""));
|
|
2190
2280
|
console.log(
|
|
2191
2281
|
row(
|
|
2192
|
-
` ${
|
|
2282
|
+
` ${chalk.dim(`${pad("File", nameW)}${padStart("Stmts", colW)}${padStart("Branch", colW)}${padStart("Funcs", colW)}${padStart("Lines", colW)}`)}`
|
|
2193
2283
|
)
|
|
2194
2284
|
);
|
|
2195
2285
|
for (const file of files) {
|
|
@@ -2197,67 +2287,67 @@ function printCoverageTable(event) {
|
|
|
2197
2287
|
const short = name.length > nameW ? name.slice(0, nameW - 1) + "~" : name;
|
|
2198
2288
|
console.log(
|
|
2199
2289
|
row(
|
|
2200
|
-
` ${pad(short, nameW)}` + padStart(colorPct(file.statements.pct), colW) + padStart(colorPct(file.branches.pct), colW) + padStart(colorPct(file.functions.pct), colW) + padStart(colorPct(file.lines.pct), colW)
|
|
2290
|
+
` ${pad(short, nameW)}` + padStart(colorPct(file.statements.pct, chalk), colW) + padStart(colorPct(file.branches.pct, chalk), colW) + padStart(colorPct(file.functions.pct, chalk), colW) + padStart(colorPct(file.lines.pct, chalk), colW)
|
|
2201
2291
|
)
|
|
2202
2292
|
);
|
|
2203
2293
|
}
|
|
2204
|
-
console.log(row(` ${
|
|
2294
|
+
console.log(row(` ${chalk.dim("\u2500".repeat(nameW + colW * 4))}`));
|
|
2205
2295
|
console.log(
|
|
2206
2296
|
row(
|
|
2207
|
-
` ${
|
|
2297
|
+
` ${chalk.bold(pad("All files", nameW))}` + padStart(colorPct(summary.statements.pct, chalk), colW) + padStart(colorPct(summary.branches.pct, chalk), colW) + padStart(colorPct(summary.functions.pct, chalk), colW) + padStart(colorPct(summary.lines.pct, chalk), colW)
|
|
2208
2298
|
)
|
|
2209
2299
|
);
|
|
2210
2300
|
}
|
|
2211
|
-
function
|
|
2301
|
+
function printRunSummaryWithChalk(result, streamingSuccess, data, chalk) {
|
|
2212
2302
|
const W = 72;
|
|
2213
|
-
const topBorder = ` ${
|
|
2214
|
-
const bottomBorder = ` ${
|
|
2215
|
-
const divider = ` ${
|
|
2216
|
-
const row = (content) => ` ${
|
|
2303
|
+
const topBorder = ` ${chalk.dim(`\u250C${"\u2500".repeat(W)}\u2510`)}`;
|
|
2304
|
+
const bottomBorder = ` ${chalk.dim(`\u2514${"\u2500".repeat(W)}\u2518`)}`;
|
|
2305
|
+
const divider = ` ${chalk.dim(`\u251C${"\u2500".repeat(W)}\u2524`)}`;
|
|
2306
|
+
const row = (content) => ` ${chalk.dim("\u2502")} ${content}`;
|
|
2217
2307
|
console.log("");
|
|
2218
2308
|
console.log(topBorder);
|
|
2219
|
-
console.log(row(
|
|
2309
|
+
console.log(row(chalk.bold("TestDino Run Summary")));
|
|
2220
2310
|
console.log(divider);
|
|
2221
|
-
console.log(row(`${
|
|
2311
|
+
console.log(row(`${chalk.dim("Run")} ${data.runId}`));
|
|
2222
2312
|
const git = data.runMetadata?.git;
|
|
2223
2313
|
if (git?.branch || git?.commit?.hash) {
|
|
2224
|
-
const branch = git.branch ?
|
|
2225
|
-
const sha = git.commit?.hash ?
|
|
2226
|
-
const sep = branch && sha ? ` ${
|
|
2227
|
-
const msg = git.commit?.message ? ` ${
|
|
2228
|
-
console.log(row(`${
|
|
2314
|
+
const branch = git.branch ? chalk.cyan(git.branch) : "";
|
|
2315
|
+
const sha = git.commit?.hash ? chalk.dim(git.commit.hash.slice(0, 7)) : "";
|
|
2316
|
+
const sep = branch && sha ? ` ${chalk.dim("@")} ` : "";
|
|
2317
|
+
const msg = git.commit?.message ? ` ${chalk.dim(git.commit.message.split("\n")[0].slice(0, 50))}` : "";
|
|
2318
|
+
console.log(row(`${chalk.dim("Git")} ${branch}${sep}${sha}${msg}`));
|
|
2229
2319
|
}
|
|
2230
2320
|
console.log(divider);
|
|
2231
|
-
const statusColor = result.status === "passed" ?
|
|
2321
|
+
const statusColor = result.status === "passed" ? chalk.green : result.status === "failed" ? chalk.red : chalk.yellow;
|
|
2232
2322
|
const statusLabel = result.status === "timedout" ? "timed out" : result.status;
|
|
2233
2323
|
console.log(
|
|
2234
2324
|
row(
|
|
2235
|
-
`${
|
|
2325
|
+
`${chalk.bold("Tests")} ${statusColor(statusLabel.toUpperCase())} ${chalk.dim(formatDuration(result.duration))}`
|
|
2236
2326
|
)
|
|
2237
2327
|
);
|
|
2238
2328
|
const counts = [];
|
|
2239
|
-
if (data.testCounts.passed > 0) counts.push(
|
|
2240
|
-
if (data.testCounts.failed > 0) counts.push(
|
|
2241
|
-
if (data.testCounts.flaky > 0) counts.push(
|
|
2242
|
-
if (data.testCounts.skipped > 0) counts.push(
|
|
2243
|
-
if (data.testCounts.timedOut > 0) counts.push(
|
|
2244
|
-
if (data.testCounts.interrupted > 0) counts.push(
|
|
2245
|
-
const retriedStr = data.testCounts.retried > 0 ? ` ${
|
|
2246
|
-
console.log(row(` ${counts.join(
|
|
2329
|
+
if (data.testCounts.passed > 0) counts.push(chalk.green(`${data.testCounts.passed} passed`));
|
|
2330
|
+
if (data.testCounts.failed > 0) counts.push(chalk.red(`${data.testCounts.failed} failed`));
|
|
2331
|
+
if (data.testCounts.flaky > 0) counts.push(chalk.yellow(`${data.testCounts.flaky} flaky`));
|
|
2332
|
+
if (data.testCounts.skipped > 0) counts.push(chalk.dim(`${data.testCounts.skipped} skipped`));
|
|
2333
|
+
if (data.testCounts.timedOut > 0) counts.push(chalk.red(`${data.testCounts.timedOut} timed out`));
|
|
2334
|
+
if (data.testCounts.interrupted > 0) counts.push(chalk.yellow(`${data.testCounts.interrupted} interrupted`));
|
|
2335
|
+
const retriedStr = data.testCounts.retried > 0 ? ` ${chalk.dim(`(${data.testCounts.retried} retries)`)}` : "";
|
|
2336
|
+
console.log(row(` ${counts.join(chalk.dim(" \xB7 "))} ${chalk.dim(`of ${data.totalTests}`)}${retriedStr}`));
|
|
2247
2337
|
console.log(divider);
|
|
2248
2338
|
const shardStr = data.shardInfo ? `${data.shardInfo.current}/${data.shardInfo.total}` : "\u2014";
|
|
2249
2339
|
console.log(
|
|
2250
2340
|
row(
|
|
2251
|
-
`${pad(`${
|
|
2341
|
+
`${pad(`${chalk.dim("Workers")} ${data.workerCount > 0 ? data.workerCount : "\u2014"}`, 28)}${pad(`${chalk.dim("Shard")} ${shardStr}`, 28)}${chalk.dim("Projects")} ${data.projectNames.size > 0 ? Array.from(data.projectNames).join(", ") : "\u2014"}`
|
|
2252
2342
|
)
|
|
2253
2343
|
);
|
|
2254
2344
|
console.log(divider);
|
|
2255
2345
|
const transport = data.useHttpFallback ? "HTTP" : "WebSocket";
|
|
2256
|
-
const streamIcon = streamingSuccess ?
|
|
2257
|
-
console.log(row(`${
|
|
2346
|
+
const streamIcon = streamingSuccess ? chalk.green("sent") : chalk.red("failed");
|
|
2347
|
+
console.log(row(`${chalk.bold("Stream")} ${streamIcon} ${chalk.dim(`via ${transport}`)}`));
|
|
2258
2348
|
if (data.lastCoverageEvent) {
|
|
2259
2349
|
console.log(divider);
|
|
2260
|
-
|
|
2350
|
+
printCoverageTableWithChalk(data.lastCoverageEvent, chalk);
|
|
2261
2351
|
}
|
|
2262
2352
|
console.log(bottomBorder);
|
|
2263
2353
|
console.log("");
|
|
@@ -2272,8 +2362,14 @@ var createReporterLog = (options) => ({
|
|
|
2272
2362
|
console.log(`\u{1F50D} TestDino: ${msg}`);
|
|
2273
2363
|
}
|
|
2274
2364
|
},
|
|
2275
|
-
printRunSummary,
|
|
2276
|
-
|
|
2365
|
+
printRunSummary: async (result, streamingSuccess, data) => {
|
|
2366
|
+
const chalk = await getChalk();
|
|
2367
|
+
printRunSummaryWithChalk(result, streamingSuccess, data, chalk);
|
|
2368
|
+
},
|
|
2369
|
+
printCoverageTable: async (event) => {
|
|
2370
|
+
const chalk = await getChalk();
|
|
2371
|
+
printCoverageTableWithChalk(event, chalk);
|
|
2372
|
+
}
|
|
2277
2373
|
});
|
|
2278
2374
|
|
|
2279
2375
|
// src/reporter/index.ts
|
|
@@ -2326,7 +2422,7 @@ var TestdinoReporter = class {
|
|
|
2326
2422
|
constructor(config = {}) {
|
|
2327
2423
|
const cliConfig = this.loadCliConfig();
|
|
2328
2424
|
this.config = { ...config, ...cliConfig };
|
|
2329
|
-
this.runId =
|
|
2425
|
+
this.runId = (0, import_crypto2.randomUUID)();
|
|
2330
2426
|
this.log = createReporterLog({ debug: this.config.debug ?? false });
|
|
2331
2427
|
this.coverageEnabled = this.config.coverage?.enabled ?? false;
|
|
2332
2428
|
if (this.coverageEnabled) {
|
|
@@ -2356,10 +2452,10 @@ var TestdinoReporter = class {
|
|
|
2356
2452
|
return {};
|
|
2357
2453
|
}
|
|
2358
2454
|
try {
|
|
2359
|
-
if (!
|
|
2455
|
+
if (!(0, import_fs2.existsSync)(cliConfigPath)) {
|
|
2360
2456
|
return {};
|
|
2361
2457
|
}
|
|
2362
|
-
const configContent =
|
|
2458
|
+
const configContent = (0, import_fs2.readFileSync)(cliConfigPath, "utf-8");
|
|
2363
2459
|
const cliConfig = JSON.parse(configContent);
|
|
2364
2460
|
const mappedConfig = {};
|
|
2365
2461
|
if (cliConfig.token !== void 0 && typeof cliConfig.token === "string") {
|
|
@@ -2642,7 +2738,7 @@ var TestdinoReporter = class {
|
|
|
2642
2738
|
}
|
|
2643
2739
|
}
|
|
2644
2740
|
if (this.coverageEnabled && this.coverageMerger) {
|
|
2645
|
-
this.extractCoverageFromResult(
|
|
2741
|
+
this.extractCoverageFromResult(result, this.coverageMerger);
|
|
2646
2742
|
}
|
|
2647
2743
|
const projectName = this.getProjectName(test2);
|
|
2648
2744
|
if (projectName) {
|
|
@@ -2743,19 +2839,6 @@ var TestdinoReporter = class {
|
|
|
2743
2839
|
}
|
|
2744
2840
|
if (this.coverageEnabled && this.coverageMerger?.hasCoverage) {
|
|
2745
2841
|
try {
|
|
2746
|
-
if (this.projectNames.size > 1 && !this.config.coverage?.projects?.length) {
|
|
2747
|
-
this.log.warn(
|
|
2748
|
-
`Coverage collected from ${this.projectNames.size} projects (${Array.from(this.projectNames).join(", ")}). Set coverage.projects to a single project to avoid duplicate counts`
|
|
2749
|
-
);
|
|
2750
|
-
}
|
|
2751
|
-
if (this.config.coverage?.projects?.length) {
|
|
2752
|
-
const unmatched = this.config.coverage.projects.filter((p) => !this.projectNames.has(p));
|
|
2753
|
-
if (unmatched.length > 0) {
|
|
2754
|
-
this.log.warn(
|
|
2755
|
-
`coverage.projects contains unmatched values: ${unmatched.join(", ")}. Available projects: ${Array.from(this.projectNames).join(", ")}`
|
|
2756
|
-
);
|
|
2757
|
-
}
|
|
2758
|
-
}
|
|
2759
2842
|
const coverageEvent = this.buildCoverageEvent(this.coverageMerger);
|
|
2760
2843
|
await this.buffer.add(coverageEvent);
|
|
2761
2844
|
this.lastCoverageEvent = coverageEvent;
|
|
@@ -2763,15 +2846,21 @@ var TestdinoReporter = class {
|
|
|
2763
2846
|
if (thresholdFailures.length > 0) {
|
|
2764
2847
|
this.coverageThresholdFailed = true;
|
|
2765
2848
|
}
|
|
2766
|
-
|
|
2767
|
-
|
|
2849
|
+
} catch (error) {
|
|
2850
|
+
this.log.warn(`Failed to build coverage event: ${error instanceof Error ? error.message : String(error)}`);
|
|
2851
|
+
}
|
|
2852
|
+
if (this.coverageMerger?.hasCoverage) {
|
|
2853
|
+
try {
|
|
2854
|
+
const outputDir = "./coverage";
|
|
2768
2855
|
const reportPath = await generateIstanbulHtmlReport(this.coverageMerger, {
|
|
2769
2856
|
outputDir
|
|
2770
2857
|
});
|
|
2771
2858
|
this.log.info(`Coverage Report: ${reportPath}`);
|
|
2859
|
+
} catch (error) {
|
|
2860
|
+
this.log.warn(
|
|
2861
|
+
`Failed to generate local HTML report: ${error instanceof Error ? error.message : String(error)}`
|
|
2862
|
+
);
|
|
2772
2863
|
}
|
|
2773
|
-
} catch (error) {
|
|
2774
|
-
this.log.warn(`Failed to build coverage event: ${error instanceof Error ? error.message : String(error)}`);
|
|
2775
2864
|
}
|
|
2776
2865
|
} else if (this.coverageEnabled && !this.coverageMerger?.hasCoverage) {
|
|
2777
2866
|
this.log.warn(
|
|
@@ -2839,7 +2928,7 @@ var TestdinoReporter = class {
|
|
|
2839
2928
|
useHttpFallback: this.useHttpFallback,
|
|
2840
2929
|
lastCoverageEvent: this.lastCoverageEvent
|
|
2841
2930
|
};
|
|
2842
|
-
this.log.printRunSummary(result, delivered, summaryData);
|
|
2931
|
+
await this.log.printRunSummary(result, delivered, summaryData);
|
|
2843
2932
|
if (this.coverageThresholdFailed && this.lastCoverageEvent) {
|
|
2844
2933
|
const failures = this.checkCoverageThresholds(this.lastCoverageEvent.summary);
|
|
2845
2934
|
this.log.error("Coverage thresholds not met:");
|
|
@@ -3476,16 +3565,8 @@ var TestdinoReporter = class {
|
|
|
3476
3565
|
/**
|
|
3477
3566
|
* Extract coverage fragment from test result attachments and merge incrementally.
|
|
3478
3567
|
* The fixture attaches coverage as an in-memory JSON attachment named 'testdino-coverage'.
|
|
3479
|
-
*
|
|
3480
|
-
* Respects coverage.projects filter to avoid duplicate coverage from multiple browser projects.
|
|
3481
3568
|
*/
|
|
3482
|
-
extractCoverageFromResult(
|
|
3483
|
-
if (this.config.coverage?.projects) {
|
|
3484
|
-
const projectName = this.getProjectName(test2);
|
|
3485
|
-
if (projectName && !this.config.coverage.projects.includes(projectName)) {
|
|
3486
|
-
return;
|
|
3487
|
-
}
|
|
3488
|
-
}
|
|
3569
|
+
extractCoverageFromResult(result, merger) {
|
|
3489
3570
|
const coverageAttachment = result.attachments.find((a) => a.name === "testdino-coverage");
|
|
3490
3571
|
if (!coverageAttachment?.body) return;
|
|
3491
3572
|
try {
|
|
@@ -3509,7 +3590,9 @@ var TestdinoReporter = class {
|
|
|
3509
3590
|
const files = merger.computeFileCoverage(rootDir);
|
|
3510
3591
|
const isSharded = !!this.shardInfo;
|
|
3511
3592
|
if (files.length > COVERAGE_FILE_COUNT_WARNING) {
|
|
3512
|
-
this.log.warn(
|
|
3593
|
+
this.log.warn(
|
|
3594
|
+
`Coverage includes ${files.length} files \u2014 consider using coverage.include/exclude to reduce scope`
|
|
3595
|
+
);
|
|
3513
3596
|
}
|
|
3514
3597
|
const event = {
|
|
3515
3598
|
type: "coverage:data",
|
|
@@ -3550,13 +3633,10 @@ var TestdinoReporter = class {
|
|
|
3550
3633
|
return failures;
|
|
3551
3634
|
}
|
|
3552
3635
|
};
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3636
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3637
|
+
0 && (module.exports = {
|
|
3638
|
+
coverageFixtures,
|
|
3639
|
+
expect,
|
|
3640
|
+
test
|
|
3557
3641
|
});
|
|
3558
|
-
exports.coverageFixtures = coverageFixtures;
|
|
3559
|
-
exports.default = TestdinoReporter;
|
|
3560
|
-
exports.test = test;
|
|
3561
|
-
//# sourceMappingURL=index.js.map
|
|
3562
3642
|
//# sourceMappingURL=index.js.map
|