@checkly/playwright-reporter 0.1.10 → 1.2.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/CHANGELOG.md +134 -0
- package/README.md +266 -0
- package/dist/index.d.ts +49 -289
- package/dist/index.js +1799 -812
- package/package.json +18 -15
package/dist/index.js
CHANGED
|
@@ -1,6 +1,57 @@
|
|
|
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);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
MissingCredentialsError: () => MissingCredentialsError,
|
|
34
|
+
createChecklyReporter: () => createChecklyReporter,
|
|
35
|
+
default: () => index_default
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
|
|
39
|
+
// src/extensions/checkly-upload.ts
|
|
40
|
+
var fs5 = __toESM(require("fs"));
|
|
41
|
+
var path4 = __toESM(require("path"));
|
|
42
|
+
|
|
43
|
+
// ../utils/src/ansi.ts
|
|
44
|
+
var ansiRegex = new RegExp(
|
|
45
|
+
[
|
|
46
|
+
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
|
|
47
|
+
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"
|
|
48
|
+
].join("|"),
|
|
49
|
+
"g"
|
|
50
|
+
);
|
|
51
|
+
|
|
1
52
|
// ../utils/src/asset-collector.ts
|
|
2
|
-
|
|
3
|
-
|
|
53
|
+
var fs = __toESM(require("fs"), 1);
|
|
54
|
+
var path = __toESM(require("path"), 1);
|
|
4
55
|
var AssetCollector = class {
|
|
5
56
|
constructor(testResultsDir) {
|
|
6
57
|
this.testResultsDir = testResultsDir;
|
|
@@ -234,8 +285,37 @@ var AssetCollector = class {
|
|
|
234
285
|
}
|
|
235
286
|
};
|
|
236
287
|
|
|
288
|
+
// ../utils/src/ci-detector.ts
|
|
289
|
+
function detectCI() {
|
|
290
|
+
if (process.env.GITHUB_ACTIONS === "true") {
|
|
291
|
+
return { environment: "ci", ciProvider: "github-actions", repositoryId: process.env.GITHUB_REPOSITORY };
|
|
292
|
+
}
|
|
293
|
+
if (process.env.GITLAB_CI === "true") {
|
|
294
|
+
return { environment: "ci", ciProvider: "gitlab-ci", repositoryId: process.env.CI_PROJECT_PATH };
|
|
295
|
+
}
|
|
296
|
+
if (process.env.JENKINS_URL) {
|
|
297
|
+
return { environment: "ci", ciProvider: "jenkins", repositoryId: process.env.JOB_NAME };
|
|
298
|
+
}
|
|
299
|
+
if (process.env.CIRCLECI === "true") {
|
|
300
|
+
return { environment: "ci", ciProvider: "circleci", repositoryId: process.env.CIRCLE_PROJECT_REPONAME };
|
|
301
|
+
}
|
|
302
|
+
if (process.env.TRAVIS === "true") {
|
|
303
|
+
return { environment: "ci", ciProvider: "travis-ci", repositoryId: process.env.TRAVIS_REPO_SLUG };
|
|
304
|
+
}
|
|
305
|
+
if (process.env.TF_BUILD === "True") {
|
|
306
|
+
return { environment: "ci", ciProvider: "azure-devops", repositoryId: process.env.BUILD_REPOSITORY_NAME };
|
|
307
|
+
}
|
|
308
|
+
if (process.env.BITBUCKET_PIPELINE_UUID) {
|
|
309
|
+
return { environment: "ci", ciProvider: "bitbucket-pipelines", repositoryId: process.env.BITBUCKET_REPO_SLUG };
|
|
310
|
+
}
|
|
311
|
+
if (process.env.CI === "true" || process.env.CI === "1") {
|
|
312
|
+
return { environment: "ci", ciProvider: "unknown-ci" };
|
|
313
|
+
}
|
|
314
|
+
return { environment: "local", ciProvider: "local" };
|
|
315
|
+
}
|
|
316
|
+
|
|
237
317
|
// ../utils/src/console-adapter.ts
|
|
238
|
-
|
|
318
|
+
var import_node_crypto = require("crypto");
|
|
239
319
|
function normalizeType(messageType) {
|
|
240
320
|
switch (messageType.toLowerCase()) {
|
|
241
321
|
case "debug":
|
|
@@ -252,7 +332,7 @@ function normalizeType(messageType) {
|
|
|
252
332
|
}
|
|
253
333
|
}
|
|
254
334
|
function generateId(time, messageType, text, url) {
|
|
255
|
-
return createHash("sha256").update(`${time}-${messageType}-${text}-${url}`).digest("hex").substring(0, 16);
|
|
335
|
+
return (0, import_node_crypto.createHash)("sha256").update(`${time}-${messageType}-${text}-${url}`).digest("hex").substring(0, 16);
|
|
256
336
|
}
|
|
257
337
|
function toConsoleMessage(event) {
|
|
258
338
|
const url = event.location?.url || "";
|
|
@@ -269,10 +349,29 @@ function toConsoleMessage(event) {
|
|
|
269
349
|
};
|
|
270
350
|
}
|
|
271
351
|
|
|
352
|
+
// ../utils/src/git-info.ts
|
|
353
|
+
function getGitHubRepoInfo() {
|
|
354
|
+
const repository = process.env.GITHUB_REPOSITORY;
|
|
355
|
+
if (!repository) return void 0;
|
|
356
|
+
return {
|
|
357
|
+
repoUrl: `https://github.com/${repository}`,
|
|
358
|
+
commitId: process.env.GITHUB_SHA,
|
|
359
|
+
branchName: process.env.GITHUB_REF_NAME,
|
|
360
|
+
commitOwner: process.env.GITHUB_ACTOR,
|
|
361
|
+
commitMessage: process.env.GITHUB_EVENT_NAME
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// ../utils/src/machine-id.ts
|
|
366
|
+
var import_node_crypto2 = require("crypto");
|
|
367
|
+
var fs2 = __toESM(require("fs"), 1);
|
|
368
|
+
var os = __toESM(require("os"), 1);
|
|
369
|
+
var path2 = __toESM(require("path"), 1);
|
|
370
|
+
|
|
272
371
|
// ../utils/src/network-adapter.ts
|
|
273
|
-
|
|
372
|
+
var import_node_crypto3 = require("crypto");
|
|
274
373
|
function generateId2(url, method, startedAt) {
|
|
275
|
-
return
|
|
374
|
+
return (0, import_node_crypto3.createHash)("sha256").update(`${url}-${method}-${startedAt}`).digest("hex").substring(0, 16);
|
|
276
375
|
}
|
|
277
376
|
function extractDomain(url) {
|
|
278
377
|
try {
|
|
@@ -330,13 +429,13 @@ function toNetworkRequest(event) {
|
|
|
330
429
|
}
|
|
331
430
|
|
|
332
431
|
// ../utils/src/trace-reader.ts
|
|
333
|
-
|
|
432
|
+
var fs3 = __toESM(require("fs"), 1);
|
|
334
433
|
|
|
335
434
|
// ../utils/src/zip-reader.ts
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
var gunzip2 = promisify(zlib.gunzip);
|
|
339
|
-
var inflateRaw2 = promisify(zlib.inflateRaw);
|
|
435
|
+
var import_node_util = require("util");
|
|
436
|
+
var zlib = __toESM(require("zlib"), 1);
|
|
437
|
+
var gunzip2 = (0, import_node_util.promisify)(zlib.gunzip);
|
|
438
|
+
var inflateRaw2 = (0, import_node_util.promisify)(zlib.inflateRaw);
|
|
340
439
|
function parseZipEntries(zipBuffer) {
|
|
341
440
|
const EOCD_SIG = 101010256;
|
|
342
441
|
let eocdOffset = -1;
|
|
@@ -407,11 +506,11 @@ var TraceReader = class {
|
|
|
407
506
|
zipBuffer = null;
|
|
408
507
|
traceEntries = [];
|
|
409
508
|
async open() {
|
|
410
|
-
if (!
|
|
509
|
+
if (!fs3.existsSync(this.tracePath)) {
|
|
411
510
|
return false;
|
|
412
511
|
}
|
|
413
512
|
try {
|
|
414
|
-
this.zipBuffer =
|
|
513
|
+
this.zipBuffer = fs3.readFileSync(this.tracePath);
|
|
415
514
|
const entries = parseZipEntries(this.zipBuffer);
|
|
416
515
|
this.traceEntries = entries.filter(
|
|
417
516
|
(e) => (/^\d+-trace\.trace$/.test(e.fileName) || /^\d+-trace\.network$/.test(e.fileName)) && !e.fileName.includes("/")
|
|
@@ -488,14 +587,732 @@ var TraceReader = class {
|
|
|
488
587
|
};
|
|
489
588
|
|
|
490
589
|
// ../utils/src/zipper.ts
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
590
|
+
var fs4 = __toESM(require("fs"), 1);
|
|
591
|
+
var os2 = __toESM(require("os"), 1);
|
|
592
|
+
var path3 = __toESM(require("path"), 1);
|
|
593
|
+
|
|
594
|
+
// ../../node_modules/.pnpm/fflate@0.8.2/node_modules/fflate/esm/index.mjs
|
|
595
|
+
var import_module = require("module");
|
|
596
|
+
var require2 = (0, import_module.createRequire)("/");
|
|
597
|
+
var Worker;
|
|
598
|
+
try {
|
|
599
|
+
Worker = require2("worker_threads").Worker;
|
|
600
|
+
} catch (e) {
|
|
601
|
+
}
|
|
602
|
+
var u8 = Uint8Array;
|
|
603
|
+
var u16 = Uint16Array;
|
|
604
|
+
var i32 = Int32Array;
|
|
605
|
+
var fleb = new u8([
|
|
606
|
+
0,
|
|
607
|
+
0,
|
|
608
|
+
0,
|
|
609
|
+
0,
|
|
610
|
+
0,
|
|
611
|
+
0,
|
|
612
|
+
0,
|
|
613
|
+
0,
|
|
614
|
+
1,
|
|
615
|
+
1,
|
|
616
|
+
1,
|
|
617
|
+
1,
|
|
618
|
+
2,
|
|
619
|
+
2,
|
|
620
|
+
2,
|
|
621
|
+
2,
|
|
622
|
+
3,
|
|
623
|
+
3,
|
|
624
|
+
3,
|
|
625
|
+
3,
|
|
626
|
+
4,
|
|
627
|
+
4,
|
|
628
|
+
4,
|
|
629
|
+
4,
|
|
630
|
+
5,
|
|
631
|
+
5,
|
|
632
|
+
5,
|
|
633
|
+
5,
|
|
634
|
+
0,
|
|
635
|
+
/* unused */
|
|
636
|
+
0,
|
|
637
|
+
0,
|
|
638
|
+
/* impossible */
|
|
639
|
+
0
|
|
640
|
+
]);
|
|
641
|
+
var fdeb = new u8([
|
|
642
|
+
0,
|
|
643
|
+
0,
|
|
644
|
+
0,
|
|
645
|
+
0,
|
|
646
|
+
1,
|
|
647
|
+
1,
|
|
648
|
+
2,
|
|
649
|
+
2,
|
|
650
|
+
3,
|
|
651
|
+
3,
|
|
652
|
+
4,
|
|
653
|
+
4,
|
|
654
|
+
5,
|
|
655
|
+
5,
|
|
656
|
+
6,
|
|
657
|
+
6,
|
|
658
|
+
7,
|
|
659
|
+
7,
|
|
660
|
+
8,
|
|
661
|
+
8,
|
|
662
|
+
9,
|
|
663
|
+
9,
|
|
664
|
+
10,
|
|
665
|
+
10,
|
|
666
|
+
11,
|
|
667
|
+
11,
|
|
668
|
+
12,
|
|
669
|
+
12,
|
|
670
|
+
13,
|
|
671
|
+
13,
|
|
672
|
+
/* unused */
|
|
673
|
+
0,
|
|
674
|
+
0
|
|
675
|
+
]);
|
|
676
|
+
var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
|
|
677
|
+
var freb = function(eb, start) {
|
|
678
|
+
var b = new u16(31);
|
|
679
|
+
for (var i = 0; i < 31; ++i) {
|
|
680
|
+
b[i] = start += 1 << eb[i - 1];
|
|
681
|
+
}
|
|
682
|
+
var r = new i32(b[30]);
|
|
683
|
+
for (var i = 1; i < 30; ++i) {
|
|
684
|
+
for (var j = b[i]; j < b[i + 1]; ++j) {
|
|
685
|
+
r[j] = j - b[i] << 5 | i;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return { b, r };
|
|
689
|
+
};
|
|
690
|
+
var _a = freb(fleb, 2);
|
|
691
|
+
var fl = _a.b;
|
|
692
|
+
var revfl = _a.r;
|
|
693
|
+
fl[28] = 258, revfl[258] = 28;
|
|
694
|
+
var _b = freb(fdeb, 0);
|
|
695
|
+
var fd = _b.b;
|
|
696
|
+
var revfd = _b.r;
|
|
697
|
+
var rev = new u16(32768);
|
|
698
|
+
for (i = 0; i < 32768; ++i) {
|
|
699
|
+
x = (i & 43690) >> 1 | (i & 21845) << 1;
|
|
700
|
+
x = (x & 52428) >> 2 | (x & 13107) << 2;
|
|
701
|
+
x = (x & 61680) >> 4 | (x & 3855) << 4;
|
|
702
|
+
rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;
|
|
703
|
+
}
|
|
704
|
+
var x;
|
|
705
|
+
var i;
|
|
706
|
+
var hMap = (function(cd, mb, r) {
|
|
707
|
+
var s = cd.length;
|
|
708
|
+
var i = 0;
|
|
709
|
+
var l = new u16(mb);
|
|
710
|
+
for (; i < s; ++i) {
|
|
711
|
+
if (cd[i])
|
|
712
|
+
++l[cd[i] - 1];
|
|
713
|
+
}
|
|
714
|
+
var le = new u16(mb);
|
|
715
|
+
for (i = 1; i < mb; ++i) {
|
|
716
|
+
le[i] = le[i - 1] + l[i - 1] << 1;
|
|
717
|
+
}
|
|
718
|
+
var co;
|
|
719
|
+
if (r) {
|
|
720
|
+
co = new u16(1 << mb);
|
|
721
|
+
var rvb = 15 - mb;
|
|
722
|
+
for (i = 0; i < s; ++i) {
|
|
723
|
+
if (cd[i]) {
|
|
724
|
+
var sv = i << 4 | cd[i];
|
|
725
|
+
var r_1 = mb - cd[i];
|
|
726
|
+
var v = le[cd[i] - 1]++ << r_1;
|
|
727
|
+
for (var m = v | (1 << r_1) - 1; v <= m; ++v) {
|
|
728
|
+
co[rev[v] >> rvb] = sv;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
} else {
|
|
733
|
+
co = new u16(s);
|
|
734
|
+
for (i = 0; i < s; ++i) {
|
|
735
|
+
if (cd[i]) {
|
|
736
|
+
co[i] = rev[le[cd[i] - 1]++] >> 15 - cd[i];
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return co;
|
|
741
|
+
});
|
|
742
|
+
var flt = new u8(288);
|
|
743
|
+
for (i = 0; i < 144; ++i)
|
|
744
|
+
flt[i] = 8;
|
|
745
|
+
var i;
|
|
746
|
+
for (i = 144; i < 256; ++i)
|
|
747
|
+
flt[i] = 9;
|
|
748
|
+
var i;
|
|
749
|
+
for (i = 256; i < 280; ++i)
|
|
750
|
+
flt[i] = 7;
|
|
751
|
+
var i;
|
|
752
|
+
for (i = 280; i < 288; ++i)
|
|
753
|
+
flt[i] = 8;
|
|
754
|
+
var i;
|
|
755
|
+
var fdt = new u8(32);
|
|
756
|
+
for (i = 0; i < 32; ++i)
|
|
757
|
+
fdt[i] = 5;
|
|
758
|
+
var i;
|
|
759
|
+
var flm = /* @__PURE__ */ hMap(flt, 9, 0);
|
|
760
|
+
var fdm = /* @__PURE__ */ hMap(fdt, 5, 0);
|
|
761
|
+
var shft = function(p) {
|
|
762
|
+
return (p + 7) / 8 | 0;
|
|
763
|
+
};
|
|
764
|
+
var slc = function(v, s, e) {
|
|
765
|
+
if (s == null || s < 0)
|
|
766
|
+
s = 0;
|
|
767
|
+
if (e == null || e > v.length)
|
|
768
|
+
e = v.length;
|
|
769
|
+
return new u8(v.subarray(s, e));
|
|
770
|
+
};
|
|
771
|
+
var ec = [
|
|
772
|
+
"unexpected EOF",
|
|
773
|
+
"invalid block type",
|
|
774
|
+
"invalid length/literal",
|
|
775
|
+
"invalid distance",
|
|
776
|
+
"stream finished",
|
|
777
|
+
"no stream handler",
|
|
778
|
+
,
|
|
779
|
+
"no callback",
|
|
780
|
+
"invalid UTF-8 data",
|
|
781
|
+
"extra field too long",
|
|
782
|
+
"date not in range 1980-2099",
|
|
783
|
+
"filename too long",
|
|
784
|
+
"stream finishing",
|
|
785
|
+
"invalid zip data"
|
|
786
|
+
// determined by unknown compression method
|
|
787
|
+
];
|
|
788
|
+
var err = function(ind, msg, nt) {
|
|
789
|
+
var e = new Error(msg || ec[ind]);
|
|
790
|
+
e.code = ind;
|
|
791
|
+
if (Error.captureStackTrace)
|
|
792
|
+
Error.captureStackTrace(e, err);
|
|
793
|
+
if (!nt)
|
|
794
|
+
throw e;
|
|
795
|
+
return e;
|
|
796
|
+
};
|
|
797
|
+
var wbits = function(d, p, v) {
|
|
798
|
+
v <<= p & 7;
|
|
799
|
+
var o = p / 8 | 0;
|
|
800
|
+
d[o] |= v;
|
|
801
|
+
d[o + 1] |= v >> 8;
|
|
802
|
+
};
|
|
803
|
+
var wbits16 = function(d, p, v) {
|
|
804
|
+
v <<= p & 7;
|
|
805
|
+
var o = p / 8 | 0;
|
|
806
|
+
d[o] |= v;
|
|
807
|
+
d[o + 1] |= v >> 8;
|
|
808
|
+
d[o + 2] |= v >> 16;
|
|
809
|
+
};
|
|
810
|
+
var hTree = function(d, mb) {
|
|
811
|
+
var t = [];
|
|
812
|
+
for (var i = 0; i < d.length; ++i) {
|
|
813
|
+
if (d[i])
|
|
814
|
+
t.push({ s: i, f: d[i] });
|
|
815
|
+
}
|
|
816
|
+
var s = t.length;
|
|
817
|
+
var t2 = t.slice();
|
|
818
|
+
if (!s)
|
|
819
|
+
return { t: et, l: 0 };
|
|
820
|
+
if (s == 1) {
|
|
821
|
+
var v = new u8(t[0].s + 1);
|
|
822
|
+
v[t[0].s] = 1;
|
|
823
|
+
return { t: v, l: 1 };
|
|
824
|
+
}
|
|
825
|
+
t.sort(function(a, b) {
|
|
826
|
+
return a.f - b.f;
|
|
827
|
+
});
|
|
828
|
+
t.push({ s: -1, f: 25001 });
|
|
829
|
+
var l = t[0], r = t[1], i0 = 0, i1 = 1, i2 = 2;
|
|
830
|
+
t[0] = { s: -1, f: l.f + r.f, l, r };
|
|
831
|
+
while (i1 != s - 1) {
|
|
832
|
+
l = t[t[i0].f < t[i2].f ? i0++ : i2++];
|
|
833
|
+
r = t[i0 != i1 && t[i0].f < t[i2].f ? i0++ : i2++];
|
|
834
|
+
t[i1++] = { s: -1, f: l.f + r.f, l, r };
|
|
835
|
+
}
|
|
836
|
+
var maxSym = t2[0].s;
|
|
837
|
+
for (var i = 1; i < s; ++i) {
|
|
838
|
+
if (t2[i].s > maxSym)
|
|
839
|
+
maxSym = t2[i].s;
|
|
840
|
+
}
|
|
841
|
+
var tr = new u16(maxSym + 1);
|
|
842
|
+
var mbt = ln(t[i1 - 1], tr, 0);
|
|
843
|
+
if (mbt > mb) {
|
|
844
|
+
var i = 0, dt = 0;
|
|
845
|
+
var lft = mbt - mb, cst = 1 << lft;
|
|
846
|
+
t2.sort(function(a, b) {
|
|
847
|
+
return tr[b.s] - tr[a.s] || a.f - b.f;
|
|
848
|
+
});
|
|
849
|
+
for (; i < s; ++i) {
|
|
850
|
+
var i2_1 = t2[i].s;
|
|
851
|
+
if (tr[i2_1] > mb) {
|
|
852
|
+
dt += cst - (1 << mbt - tr[i2_1]);
|
|
853
|
+
tr[i2_1] = mb;
|
|
854
|
+
} else
|
|
855
|
+
break;
|
|
856
|
+
}
|
|
857
|
+
dt >>= lft;
|
|
858
|
+
while (dt > 0) {
|
|
859
|
+
var i2_2 = t2[i].s;
|
|
860
|
+
if (tr[i2_2] < mb)
|
|
861
|
+
dt -= 1 << mb - tr[i2_2]++ - 1;
|
|
862
|
+
else
|
|
863
|
+
++i;
|
|
864
|
+
}
|
|
865
|
+
for (; i >= 0 && dt; --i) {
|
|
866
|
+
var i2_3 = t2[i].s;
|
|
867
|
+
if (tr[i2_3] == mb) {
|
|
868
|
+
--tr[i2_3];
|
|
869
|
+
++dt;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
mbt = mb;
|
|
873
|
+
}
|
|
874
|
+
return { t: new u8(tr), l: mbt };
|
|
875
|
+
};
|
|
876
|
+
var ln = function(n, l, d) {
|
|
877
|
+
return n.s == -1 ? Math.max(ln(n.l, l, d + 1), ln(n.r, l, d + 1)) : l[n.s] = d;
|
|
878
|
+
};
|
|
879
|
+
var lc = function(c) {
|
|
880
|
+
var s = c.length;
|
|
881
|
+
while (s && !c[--s])
|
|
882
|
+
;
|
|
883
|
+
var cl = new u16(++s);
|
|
884
|
+
var cli = 0, cln = c[0], cls = 1;
|
|
885
|
+
var w = function(v) {
|
|
886
|
+
cl[cli++] = v;
|
|
887
|
+
};
|
|
888
|
+
for (var i = 1; i <= s; ++i) {
|
|
889
|
+
if (c[i] == cln && i != s)
|
|
890
|
+
++cls;
|
|
891
|
+
else {
|
|
892
|
+
if (!cln && cls > 2) {
|
|
893
|
+
for (; cls > 138; cls -= 138)
|
|
894
|
+
w(32754);
|
|
895
|
+
if (cls > 2) {
|
|
896
|
+
w(cls > 10 ? cls - 11 << 5 | 28690 : cls - 3 << 5 | 12305);
|
|
897
|
+
cls = 0;
|
|
898
|
+
}
|
|
899
|
+
} else if (cls > 3) {
|
|
900
|
+
w(cln), --cls;
|
|
901
|
+
for (; cls > 6; cls -= 6)
|
|
902
|
+
w(8304);
|
|
903
|
+
if (cls > 2)
|
|
904
|
+
w(cls - 3 << 5 | 8208), cls = 0;
|
|
905
|
+
}
|
|
906
|
+
while (cls--)
|
|
907
|
+
w(cln);
|
|
908
|
+
cls = 1;
|
|
909
|
+
cln = c[i];
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
return { c: cl.subarray(0, cli), n: s };
|
|
913
|
+
};
|
|
914
|
+
var clen = function(cf, cl) {
|
|
915
|
+
var l = 0;
|
|
916
|
+
for (var i = 0; i < cl.length; ++i)
|
|
917
|
+
l += cf[i] * cl[i];
|
|
918
|
+
return l;
|
|
919
|
+
};
|
|
920
|
+
var wfblk = function(out, pos, dat) {
|
|
921
|
+
var s = dat.length;
|
|
922
|
+
var o = shft(pos + 2);
|
|
923
|
+
out[o] = s & 255;
|
|
924
|
+
out[o + 1] = s >> 8;
|
|
925
|
+
out[o + 2] = out[o] ^ 255;
|
|
926
|
+
out[o + 3] = out[o + 1] ^ 255;
|
|
927
|
+
for (var i = 0; i < s; ++i)
|
|
928
|
+
out[o + i + 4] = dat[i];
|
|
929
|
+
return (o + 4 + s) * 8;
|
|
930
|
+
};
|
|
931
|
+
var wblk = function(dat, out, final, syms, lf, df, eb, li, bs, bl, p) {
|
|
932
|
+
wbits(out, p++, final);
|
|
933
|
+
++lf[256];
|
|
934
|
+
var _a2 = hTree(lf, 15), dlt = _a2.t, mlb = _a2.l;
|
|
935
|
+
var _b2 = hTree(df, 15), ddt = _b2.t, mdb = _b2.l;
|
|
936
|
+
var _c = lc(dlt), lclt = _c.c, nlc = _c.n;
|
|
937
|
+
var _d = lc(ddt), lcdt = _d.c, ndc = _d.n;
|
|
938
|
+
var lcfreq = new u16(19);
|
|
939
|
+
for (var i = 0; i < lclt.length; ++i)
|
|
940
|
+
++lcfreq[lclt[i] & 31];
|
|
941
|
+
for (var i = 0; i < lcdt.length; ++i)
|
|
942
|
+
++lcfreq[lcdt[i] & 31];
|
|
943
|
+
var _e = hTree(lcfreq, 7), lct = _e.t, mlcb = _e.l;
|
|
944
|
+
var nlcc = 19;
|
|
945
|
+
for (; nlcc > 4 && !lct[clim[nlcc - 1]]; --nlcc)
|
|
946
|
+
;
|
|
947
|
+
var flen = bl + 5 << 3;
|
|
948
|
+
var ftlen = clen(lf, flt) + clen(df, fdt) + eb;
|
|
949
|
+
var dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + 2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18];
|
|
950
|
+
if (bs >= 0 && flen <= ftlen && flen <= dtlen)
|
|
951
|
+
return wfblk(out, p, dat.subarray(bs, bs + bl));
|
|
952
|
+
var lm, ll, dm, dl;
|
|
953
|
+
wbits(out, p, 1 + (dtlen < ftlen)), p += 2;
|
|
954
|
+
if (dtlen < ftlen) {
|
|
955
|
+
lm = hMap(dlt, mlb, 0), ll = dlt, dm = hMap(ddt, mdb, 0), dl = ddt;
|
|
956
|
+
var llm = hMap(lct, mlcb, 0);
|
|
957
|
+
wbits(out, p, nlc - 257);
|
|
958
|
+
wbits(out, p + 5, ndc - 1);
|
|
959
|
+
wbits(out, p + 10, nlcc - 4);
|
|
960
|
+
p += 14;
|
|
961
|
+
for (var i = 0; i < nlcc; ++i)
|
|
962
|
+
wbits(out, p + 3 * i, lct[clim[i]]);
|
|
963
|
+
p += 3 * nlcc;
|
|
964
|
+
var lcts = [lclt, lcdt];
|
|
965
|
+
for (var it = 0; it < 2; ++it) {
|
|
966
|
+
var clct = lcts[it];
|
|
967
|
+
for (var i = 0; i < clct.length; ++i) {
|
|
968
|
+
var len = clct[i] & 31;
|
|
969
|
+
wbits(out, p, llm[len]), p += lct[len];
|
|
970
|
+
if (len > 15)
|
|
971
|
+
wbits(out, p, clct[i] >> 5 & 127), p += clct[i] >> 12;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
} else {
|
|
975
|
+
lm = flm, ll = flt, dm = fdm, dl = fdt;
|
|
976
|
+
}
|
|
977
|
+
for (var i = 0; i < li; ++i) {
|
|
978
|
+
var sym = syms[i];
|
|
979
|
+
if (sym > 255) {
|
|
980
|
+
var len = sym >> 18 & 31;
|
|
981
|
+
wbits16(out, p, lm[len + 257]), p += ll[len + 257];
|
|
982
|
+
if (len > 7)
|
|
983
|
+
wbits(out, p, sym >> 23 & 31), p += fleb[len];
|
|
984
|
+
var dst = sym & 31;
|
|
985
|
+
wbits16(out, p, dm[dst]), p += dl[dst];
|
|
986
|
+
if (dst > 3)
|
|
987
|
+
wbits16(out, p, sym >> 5 & 8191), p += fdeb[dst];
|
|
988
|
+
} else {
|
|
989
|
+
wbits16(out, p, lm[sym]), p += ll[sym];
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
wbits16(out, p, lm[256]);
|
|
993
|
+
return p + ll[256];
|
|
994
|
+
};
|
|
995
|
+
var deo = /* @__PURE__ */ new i32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]);
|
|
996
|
+
var et = /* @__PURE__ */ new u8(0);
|
|
997
|
+
var dflt = function(dat, lvl, plvl, pre, post, st) {
|
|
998
|
+
var s = st.z || dat.length;
|
|
999
|
+
var o = new u8(pre + s + 5 * (1 + Math.ceil(s / 7e3)) + post);
|
|
1000
|
+
var w = o.subarray(pre, o.length - post);
|
|
1001
|
+
var lst = st.l;
|
|
1002
|
+
var pos = (st.r || 0) & 7;
|
|
1003
|
+
if (lvl) {
|
|
1004
|
+
if (pos)
|
|
1005
|
+
w[0] = st.r >> 3;
|
|
1006
|
+
var opt = deo[lvl - 1];
|
|
1007
|
+
var n = opt >> 13, c = opt & 8191;
|
|
1008
|
+
var msk_1 = (1 << plvl) - 1;
|
|
1009
|
+
var prev = st.p || new u16(32768), head = st.h || new u16(msk_1 + 1);
|
|
1010
|
+
var bs1_1 = Math.ceil(plvl / 3), bs2_1 = 2 * bs1_1;
|
|
1011
|
+
var hsh = function(i2) {
|
|
1012
|
+
return (dat[i2] ^ dat[i2 + 1] << bs1_1 ^ dat[i2 + 2] << bs2_1) & msk_1;
|
|
1013
|
+
};
|
|
1014
|
+
var syms = new i32(25e3);
|
|
1015
|
+
var lf = new u16(288), df = new u16(32);
|
|
1016
|
+
var lc_1 = 0, eb = 0, i = st.i || 0, li = 0, wi = st.w || 0, bs = 0;
|
|
1017
|
+
for (; i + 2 < s; ++i) {
|
|
1018
|
+
var hv = hsh(i);
|
|
1019
|
+
var imod = i & 32767, pimod = head[hv];
|
|
1020
|
+
prev[imod] = pimod;
|
|
1021
|
+
head[hv] = imod;
|
|
1022
|
+
if (wi <= i) {
|
|
1023
|
+
var rem = s - i;
|
|
1024
|
+
if ((lc_1 > 7e3 || li > 24576) && (rem > 423 || !lst)) {
|
|
1025
|
+
pos = wblk(dat, w, 0, syms, lf, df, eb, li, bs, i - bs, pos);
|
|
1026
|
+
li = lc_1 = eb = 0, bs = i;
|
|
1027
|
+
for (var j = 0; j < 286; ++j)
|
|
1028
|
+
lf[j] = 0;
|
|
1029
|
+
for (var j = 0; j < 30; ++j)
|
|
1030
|
+
df[j] = 0;
|
|
1031
|
+
}
|
|
1032
|
+
var l = 2, d = 0, ch_1 = c, dif = imod - pimod & 32767;
|
|
1033
|
+
if (rem > 2 && hv == hsh(i - dif)) {
|
|
1034
|
+
var maxn = Math.min(n, rem) - 1;
|
|
1035
|
+
var maxd = Math.min(32767, i);
|
|
1036
|
+
var ml = Math.min(258, rem);
|
|
1037
|
+
while (dif <= maxd && --ch_1 && imod != pimod) {
|
|
1038
|
+
if (dat[i + l] == dat[i + l - dif]) {
|
|
1039
|
+
var nl = 0;
|
|
1040
|
+
for (; nl < ml && dat[i + nl] == dat[i + nl - dif]; ++nl)
|
|
1041
|
+
;
|
|
1042
|
+
if (nl > l) {
|
|
1043
|
+
l = nl, d = dif;
|
|
1044
|
+
if (nl > maxn)
|
|
1045
|
+
break;
|
|
1046
|
+
var mmd = Math.min(dif, nl - 2);
|
|
1047
|
+
var md = 0;
|
|
1048
|
+
for (var j = 0; j < mmd; ++j) {
|
|
1049
|
+
var ti = i - dif + j & 32767;
|
|
1050
|
+
var pti = prev[ti];
|
|
1051
|
+
var cd = ti - pti & 32767;
|
|
1052
|
+
if (cd > md)
|
|
1053
|
+
md = cd, pimod = ti;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
imod = pimod, pimod = prev[imod];
|
|
1058
|
+
dif += imod - pimod & 32767;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
if (d) {
|
|
1062
|
+
syms[li++] = 268435456 | revfl[l] << 18 | revfd[d];
|
|
1063
|
+
var lin = revfl[l] & 31, din = revfd[d] & 31;
|
|
1064
|
+
eb += fleb[lin] + fdeb[din];
|
|
1065
|
+
++lf[257 + lin];
|
|
1066
|
+
++df[din];
|
|
1067
|
+
wi = i + l;
|
|
1068
|
+
++lc_1;
|
|
1069
|
+
} else {
|
|
1070
|
+
syms[li++] = dat[i];
|
|
1071
|
+
++lf[dat[i]];
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
for (i = Math.max(i, wi); i < s; ++i) {
|
|
1076
|
+
syms[li++] = dat[i];
|
|
1077
|
+
++lf[dat[i]];
|
|
1078
|
+
}
|
|
1079
|
+
pos = wblk(dat, w, lst, syms, lf, df, eb, li, bs, i - bs, pos);
|
|
1080
|
+
if (!lst) {
|
|
1081
|
+
st.r = pos & 7 | w[pos / 8 | 0] << 3;
|
|
1082
|
+
pos -= 7;
|
|
1083
|
+
st.h = head, st.p = prev, st.i = i, st.w = wi;
|
|
1084
|
+
}
|
|
1085
|
+
} else {
|
|
1086
|
+
for (var i = st.w || 0; i < s + lst; i += 65535) {
|
|
1087
|
+
var e = i + 65535;
|
|
1088
|
+
if (e >= s) {
|
|
1089
|
+
w[pos / 8 | 0] = lst;
|
|
1090
|
+
e = s;
|
|
1091
|
+
}
|
|
1092
|
+
pos = wfblk(w, pos + 1, dat.subarray(i, e));
|
|
1093
|
+
}
|
|
1094
|
+
st.i = s;
|
|
1095
|
+
}
|
|
1096
|
+
return slc(o, 0, pre + shft(pos) + post);
|
|
1097
|
+
};
|
|
1098
|
+
var crct = /* @__PURE__ */ (function() {
|
|
1099
|
+
var t = new Int32Array(256);
|
|
1100
|
+
for (var i = 0; i < 256; ++i) {
|
|
1101
|
+
var c = i, k = 9;
|
|
1102
|
+
while (--k)
|
|
1103
|
+
c = (c & 1 && -306674912) ^ c >>> 1;
|
|
1104
|
+
t[i] = c;
|
|
1105
|
+
}
|
|
1106
|
+
return t;
|
|
1107
|
+
})();
|
|
1108
|
+
var crc = function() {
|
|
1109
|
+
var c = -1;
|
|
1110
|
+
return {
|
|
1111
|
+
p: function(d) {
|
|
1112
|
+
var cr = c;
|
|
1113
|
+
for (var i = 0; i < d.length; ++i)
|
|
1114
|
+
cr = crct[cr & 255 ^ d[i]] ^ cr >>> 8;
|
|
1115
|
+
c = cr;
|
|
1116
|
+
},
|
|
1117
|
+
d: function() {
|
|
1118
|
+
return ~c;
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
};
|
|
1122
|
+
var dopt = function(dat, opt, pre, post, st) {
|
|
1123
|
+
if (!st) {
|
|
1124
|
+
st = { l: 1 };
|
|
1125
|
+
if (opt.dictionary) {
|
|
1126
|
+
var dict = opt.dictionary.subarray(-32768);
|
|
1127
|
+
var newDat = new u8(dict.length + dat.length);
|
|
1128
|
+
newDat.set(dict);
|
|
1129
|
+
newDat.set(dat, dict.length);
|
|
1130
|
+
dat = newDat;
|
|
1131
|
+
st.w = dict.length;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
return dflt(dat, opt.level == null ? 6 : opt.level, opt.mem == null ? st.l ? Math.ceil(Math.max(8, Math.min(13, Math.log(dat.length))) * 1.5) : 20 : 12 + opt.mem, pre, post, st);
|
|
1135
|
+
};
|
|
1136
|
+
var mrg = function(a, b) {
|
|
1137
|
+
var o = {};
|
|
1138
|
+
for (var k in a)
|
|
1139
|
+
o[k] = a[k];
|
|
1140
|
+
for (var k in b)
|
|
1141
|
+
o[k] = b[k];
|
|
1142
|
+
return o;
|
|
1143
|
+
};
|
|
1144
|
+
var wbytes = function(d, b, v) {
|
|
1145
|
+
for (; v; ++b)
|
|
1146
|
+
d[b] = v, v >>>= 8;
|
|
1147
|
+
};
|
|
1148
|
+
function deflateSync(data, opts) {
|
|
1149
|
+
return dopt(data, opts || {}, 0, 0);
|
|
1150
|
+
}
|
|
1151
|
+
var fltn = function(d, p, t, o) {
|
|
1152
|
+
for (var k in d) {
|
|
1153
|
+
var val = d[k], n = p + k, op = o;
|
|
1154
|
+
if (Array.isArray(val))
|
|
1155
|
+
op = mrg(o, val[1]), val = val[0];
|
|
1156
|
+
if (val instanceof u8)
|
|
1157
|
+
t[n] = [val, op];
|
|
1158
|
+
else {
|
|
1159
|
+
t[n += "/"] = [new u8(0), op];
|
|
1160
|
+
fltn(val, n, t, o);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
var te = typeof TextEncoder != "undefined" && /* @__PURE__ */ new TextEncoder();
|
|
1165
|
+
var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder();
|
|
1166
|
+
var tds = 0;
|
|
1167
|
+
try {
|
|
1168
|
+
td.decode(et, { stream: true });
|
|
1169
|
+
tds = 1;
|
|
1170
|
+
} catch (e) {
|
|
1171
|
+
}
|
|
1172
|
+
function strToU8(str, latin1) {
|
|
1173
|
+
if (latin1) {
|
|
1174
|
+
var ar_1 = new u8(str.length);
|
|
1175
|
+
for (var i = 0; i < str.length; ++i)
|
|
1176
|
+
ar_1[i] = str.charCodeAt(i);
|
|
1177
|
+
return ar_1;
|
|
1178
|
+
}
|
|
1179
|
+
if (te)
|
|
1180
|
+
return te.encode(str);
|
|
1181
|
+
var l = str.length;
|
|
1182
|
+
var ar = new u8(str.length + (str.length >> 1));
|
|
1183
|
+
var ai = 0;
|
|
1184
|
+
var w = function(v) {
|
|
1185
|
+
ar[ai++] = v;
|
|
1186
|
+
};
|
|
1187
|
+
for (var i = 0; i < l; ++i) {
|
|
1188
|
+
if (ai + 5 > ar.length) {
|
|
1189
|
+
var n = new u8(ai + 8 + (l - i << 1));
|
|
1190
|
+
n.set(ar);
|
|
1191
|
+
ar = n;
|
|
1192
|
+
}
|
|
1193
|
+
var c = str.charCodeAt(i);
|
|
1194
|
+
if (c < 128 || latin1)
|
|
1195
|
+
w(c);
|
|
1196
|
+
else if (c < 2048)
|
|
1197
|
+
w(192 | c >> 6), w(128 | c & 63);
|
|
1198
|
+
else if (c > 55295 && c < 57344)
|
|
1199
|
+
c = 65536 + (c & 1023 << 10) | str.charCodeAt(++i) & 1023, w(240 | c >> 18), w(128 | c >> 12 & 63), w(128 | c >> 6 & 63), w(128 | c & 63);
|
|
1200
|
+
else
|
|
1201
|
+
w(224 | c >> 12), w(128 | c >> 6 & 63), w(128 | c & 63);
|
|
1202
|
+
}
|
|
1203
|
+
return slc(ar, 0, ai);
|
|
1204
|
+
}
|
|
1205
|
+
var exfl = function(ex) {
|
|
1206
|
+
var le = 0;
|
|
1207
|
+
if (ex) {
|
|
1208
|
+
for (var k in ex) {
|
|
1209
|
+
var l = ex[k].length;
|
|
1210
|
+
if (l > 65535)
|
|
1211
|
+
err(9);
|
|
1212
|
+
le += l + 4;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
return le;
|
|
1216
|
+
};
|
|
1217
|
+
var wzh = function(d, b, f, fn, u, c, ce, co) {
|
|
1218
|
+
var fl2 = fn.length, ex = f.extra, col = co && co.length;
|
|
1219
|
+
var exl = exfl(ex);
|
|
1220
|
+
wbytes(d, b, ce != null ? 33639248 : 67324752), b += 4;
|
|
1221
|
+
if (ce != null)
|
|
1222
|
+
d[b++] = 20, d[b++] = f.os;
|
|
1223
|
+
d[b] = 20, b += 2;
|
|
1224
|
+
d[b++] = f.flag << 1 | (c < 0 && 8), d[b++] = u && 8;
|
|
1225
|
+
d[b++] = f.compression & 255, d[b++] = f.compression >> 8;
|
|
1226
|
+
var dt = new Date(f.mtime == null ? Date.now() : f.mtime), y = dt.getFullYear() - 1980;
|
|
1227
|
+
if (y < 0 || y > 119)
|
|
1228
|
+
err(10);
|
|
1229
|
+
wbytes(d, b, y << 25 | dt.getMonth() + 1 << 21 | dt.getDate() << 16 | dt.getHours() << 11 | dt.getMinutes() << 5 | dt.getSeconds() >> 1), b += 4;
|
|
1230
|
+
if (c != -1) {
|
|
1231
|
+
wbytes(d, b, f.crc);
|
|
1232
|
+
wbytes(d, b + 4, c < 0 ? -c - 2 : c);
|
|
1233
|
+
wbytes(d, b + 8, f.size);
|
|
1234
|
+
}
|
|
1235
|
+
wbytes(d, b + 12, fl2);
|
|
1236
|
+
wbytes(d, b + 14, exl), b += 16;
|
|
1237
|
+
if (ce != null) {
|
|
1238
|
+
wbytes(d, b, col);
|
|
1239
|
+
wbytes(d, b + 6, f.attrs);
|
|
1240
|
+
wbytes(d, b + 10, ce), b += 14;
|
|
1241
|
+
}
|
|
1242
|
+
d.set(fn, b);
|
|
1243
|
+
b += fl2;
|
|
1244
|
+
if (exl) {
|
|
1245
|
+
for (var k in ex) {
|
|
1246
|
+
var exf = ex[k], l = exf.length;
|
|
1247
|
+
wbytes(d, b, +k);
|
|
1248
|
+
wbytes(d, b + 2, l);
|
|
1249
|
+
d.set(exf, b + 4), b += 4 + l;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
if (col)
|
|
1253
|
+
d.set(co, b), b += col;
|
|
1254
|
+
return b;
|
|
1255
|
+
};
|
|
1256
|
+
var wzf = function(o, b, c, d, e) {
|
|
1257
|
+
wbytes(o, b, 101010256);
|
|
1258
|
+
wbytes(o, b + 8, c);
|
|
1259
|
+
wbytes(o, b + 10, c);
|
|
1260
|
+
wbytes(o, b + 12, d);
|
|
1261
|
+
wbytes(o, b + 16, e);
|
|
1262
|
+
};
|
|
1263
|
+
function zipSync(data, opts) {
|
|
1264
|
+
if (!opts)
|
|
1265
|
+
opts = {};
|
|
1266
|
+
var r = {};
|
|
1267
|
+
var files = [];
|
|
1268
|
+
fltn(data, "", r, opts);
|
|
1269
|
+
var o = 0;
|
|
1270
|
+
var tot = 0;
|
|
1271
|
+
for (var fn in r) {
|
|
1272
|
+
var _a2 = r[fn], file = _a2[0], p = _a2[1];
|
|
1273
|
+
var compression = p.level == 0 ? 0 : 8;
|
|
1274
|
+
var f = strToU8(fn), s = f.length;
|
|
1275
|
+
var com = p.comment, m = com && strToU8(com), ms = m && m.length;
|
|
1276
|
+
var exl = exfl(p.extra);
|
|
1277
|
+
if (s > 65535)
|
|
1278
|
+
err(11);
|
|
1279
|
+
var d = compression ? deflateSync(file, p) : file, l = d.length;
|
|
1280
|
+
var c = crc();
|
|
1281
|
+
c.p(file);
|
|
1282
|
+
files.push(mrg(p, {
|
|
1283
|
+
size: file.length,
|
|
1284
|
+
crc: c.d(),
|
|
1285
|
+
c: d,
|
|
1286
|
+
f,
|
|
1287
|
+
m,
|
|
1288
|
+
u: s != fn.length || m && com.length != ms,
|
|
1289
|
+
o,
|
|
1290
|
+
compression
|
|
1291
|
+
}));
|
|
1292
|
+
o += 30 + s + exl + l;
|
|
1293
|
+
tot += 76 + 2 * (s + exl) + (ms || 0) + l;
|
|
1294
|
+
}
|
|
1295
|
+
var out = new u8(tot + 22), oe = o, cdl = tot - o;
|
|
1296
|
+
for (var i = 0; i < files.length; ++i) {
|
|
1297
|
+
var f = files[i];
|
|
1298
|
+
wzh(out, f.o, f, f.f, f.u, f.c.length);
|
|
1299
|
+
var badd = 30 + f.f.length + exfl(f.extra);
|
|
1300
|
+
out.set(f.c, f.o + badd);
|
|
1301
|
+
wzh(out, o, f, f.f, f.u, f.c.length, f.o, f.m), o += 16 + badd + (f.m ? f.m.length : 0);
|
|
1302
|
+
}
|
|
1303
|
+
wzf(out, o, files.length, cdl, oe);
|
|
1304
|
+
return out;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
// ../utils/src/zipper.ts
|
|
495
1308
|
var Zipper = class {
|
|
496
1309
|
outputPath;
|
|
1310
|
+
compressionLevel;
|
|
1311
|
+
onProgress;
|
|
497
1312
|
constructor(options) {
|
|
498
1313
|
this.outputPath = options.outputPath;
|
|
1314
|
+
this.compressionLevel = options.compressionLevel ?? 0;
|
|
1315
|
+
this.onProgress = options.onProgress;
|
|
499
1316
|
}
|
|
500
1317
|
/**
|
|
501
1318
|
* Creates a ZIP archive containing the JSON report and assets
|
|
@@ -504,76 +1321,105 @@ var Zipper = class {
|
|
|
504
1321
|
* @returns ZIP creation result with metadata
|
|
505
1322
|
*/
|
|
506
1323
|
async createZip(reportPath, assets) {
|
|
1324
|
+
if (!fs4.existsSync(reportPath)) {
|
|
1325
|
+
throw new Error(`Report file not found: ${reportPath}`);
|
|
1326
|
+
}
|
|
1327
|
+
const transformedReportPath = this.transformJsonReport(reportPath);
|
|
1328
|
+
const files = {};
|
|
1329
|
+
const totalEntries = assets.length + 1;
|
|
1330
|
+
let processedEntries = 0;
|
|
1331
|
+
const reportContent = fs4.readFileSync(transformedReportPath);
|
|
1332
|
+
files["output/playwright-test-report.json"] = new Uint8Array(reportContent);
|
|
1333
|
+
processedEntries++;
|
|
1334
|
+
this.onProgress?.({ processedEntries, totalEntries, currentFile: "output/playwright-test-report.json" });
|
|
1335
|
+
for (const asset of assets) {
|
|
1336
|
+
if (!fs4.existsSync(asset.sourcePath)) {
|
|
1337
|
+
console.warn(`[Checkly Reporter] Skipping missing asset: ${asset.sourcePath}`);
|
|
1338
|
+
continue;
|
|
1339
|
+
}
|
|
1340
|
+
const content = fs4.readFileSync(asset.sourcePath);
|
|
1341
|
+
files[asset.archivePath] = new Uint8Array(content);
|
|
1342
|
+
processedEntries++;
|
|
1343
|
+
this.onProgress?.({ processedEntries, totalEntries, currentFile: asset.archivePath });
|
|
1344
|
+
}
|
|
1345
|
+
const zipData = zipSync(files, { level: this.compressionLevel });
|
|
1346
|
+
fs4.writeFileSync(this.outputPath, zipData);
|
|
1347
|
+
try {
|
|
1348
|
+
fs4.unlinkSync(transformedReportPath);
|
|
1349
|
+
} catch {
|
|
1350
|
+
}
|
|
1351
|
+
const entries = this.extractEntryOffsets(zipData);
|
|
1352
|
+
return {
|
|
1353
|
+
zipPath: this.outputPath,
|
|
1354
|
+
size: zipData.length,
|
|
1355
|
+
entryCount: entries.length,
|
|
1356
|
+
entries
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Extracts byte offsets for each entry from the ZIP data
|
|
1361
|
+
* Parses the central directory to get accurate offset information
|
|
1362
|
+
*/
|
|
1363
|
+
extractEntryOffsets(zipData) {
|
|
507
1364
|
const entries = [];
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
size: zipSize,
|
|
529
|
-
entryCount: entries.length,
|
|
530
|
-
entries
|
|
531
|
-
});
|
|
532
|
-
});
|
|
533
|
-
archive.on("error", (err) => {
|
|
534
|
-
reject(err);
|
|
535
|
-
});
|
|
536
|
-
output.on("error", (err) => {
|
|
537
|
-
reject(err);
|
|
538
|
-
});
|
|
539
|
-
archive.pipe(output);
|
|
540
|
-
if (!fs3.existsSync(reportPath)) {
|
|
541
|
-
reject(new Error(`Report file not found: ${reportPath}`));
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
const transformedReportPath = this.transformJsonReport(reportPath);
|
|
545
|
-
archive.file(transformedReportPath, { name: "output/playwright-test-report.json" });
|
|
546
|
-
for (const asset of assets) {
|
|
547
|
-
if (!fs3.existsSync(asset.sourcePath)) {
|
|
548
|
-
console.warn(`[Checkly Reporter] Skipping missing asset: ${asset.sourcePath}`);
|
|
549
|
-
continue;
|
|
550
|
-
}
|
|
551
|
-
archive.file(asset.sourcePath, { name: asset.archivePath });
|
|
1365
|
+
const view = new DataView(zipData.buffer, zipData.byteOffset, zipData.byteLength);
|
|
1366
|
+
let eocdOffset = -1;
|
|
1367
|
+
for (let i = zipData.length - 22; i >= 0; i--) {
|
|
1368
|
+
if (view.getUint32(i, true) === 101010256) {
|
|
1369
|
+
eocdOffset = i;
|
|
1370
|
+
break;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
if (eocdOffset === -1) {
|
|
1374
|
+
console.warn("[Checkly Reporter] Could not find ZIP end of central directory");
|
|
1375
|
+
return entries;
|
|
1376
|
+
}
|
|
1377
|
+
let cdOffset = view.getUint32(eocdOffset + 16, true);
|
|
1378
|
+
const cdSize = view.getUint32(eocdOffset + 12, true);
|
|
1379
|
+
if (cdOffset === 4294967295 && eocdOffset >= 20) {
|
|
1380
|
+
const zip64LocatorOffset = eocdOffset - 20;
|
|
1381
|
+
if (view.getUint32(zip64LocatorOffset, true) === 117853008) {
|
|
1382
|
+
const zip64EocdOffset = Number(view.getBigUint64(zip64LocatorOffset + 8, true));
|
|
1383
|
+
if (view.getUint32(zip64EocdOffset, true) === 101075792) {
|
|
1384
|
+
cdOffset = Number(view.getBigUint64(zip64EocdOffset + 48, true));
|
|
552
1385
|
}
|
|
553
|
-
archive.finalize();
|
|
554
|
-
} catch (error) {
|
|
555
|
-
reject(error);
|
|
556
1386
|
}
|
|
557
|
-
}
|
|
1387
|
+
}
|
|
1388
|
+
let offset = cdOffset;
|
|
1389
|
+
const cdEnd = cdOffset + cdSize;
|
|
1390
|
+
while (offset < cdEnd && view.getUint32(offset, true) === 33639248) {
|
|
1391
|
+
const compressedSize = view.getUint32(offset + 20, true);
|
|
1392
|
+
const filenameLength = view.getUint16(offset + 28, true);
|
|
1393
|
+
const extraLength = view.getUint16(offset + 30, true);
|
|
1394
|
+
const commentLength = view.getUint16(offset + 32, true);
|
|
1395
|
+
const localHeaderOffset = view.getUint32(offset + 42, true);
|
|
1396
|
+
const filenameBytes = zipData.slice(offset + 46, offset + 46 + filenameLength);
|
|
1397
|
+
const filename = new TextDecoder().decode(filenameBytes);
|
|
1398
|
+
const localExtraLength = view.getUint16(localHeaderOffset + 28, true);
|
|
1399
|
+
const dataStart = localHeaderOffset + 30 + filenameLength + localExtraLength;
|
|
1400
|
+
const dataEnd = dataStart + compressedSize - 1;
|
|
1401
|
+
entries.push({
|
|
1402
|
+
name: filename.replace(/\\/g, "/"),
|
|
1403
|
+
start: dataStart,
|
|
1404
|
+
end: dataEnd >= dataStart ? dataEnd : dataStart
|
|
1405
|
+
});
|
|
1406
|
+
offset += 46 + filenameLength + extraLength + commentLength;
|
|
1407
|
+
}
|
|
1408
|
+
return entries;
|
|
558
1409
|
}
|
|
559
1410
|
/**
|
|
560
1411
|
* Transforms the JSON report to use relative paths for attachments
|
|
561
|
-
* This ensures the UI can map attachment paths to ZIP entries
|
|
562
|
-
* @param reportPath - Path to the original JSON report
|
|
563
|
-
* @returns Path to the transformed JSON report (in temp directory)
|
|
564
1412
|
*/
|
|
565
1413
|
transformJsonReport(reportPath) {
|
|
566
|
-
const reportContent =
|
|
1414
|
+
const reportContent = fs4.readFileSync(reportPath, "utf-8");
|
|
567
1415
|
const report = JSON.parse(reportContent);
|
|
568
1416
|
this.transformAttachmentPaths(report);
|
|
569
|
-
const tempReportPath =
|
|
570
|
-
|
|
1417
|
+
const tempReportPath = path3.join(os2.tmpdir(), `playwright-test-report-${Date.now()}.json`);
|
|
1418
|
+
fs4.writeFileSync(tempReportPath, JSON.stringify(report, null, 2));
|
|
571
1419
|
return tempReportPath;
|
|
572
1420
|
}
|
|
573
1421
|
/**
|
|
574
1422
|
* Recursively transforms attachment paths in the report structure
|
|
575
|
-
* Converts absolute paths to relative paths matching ZIP structure
|
|
576
|
-
* @param obj - Object to transform (mutated in place)
|
|
577
1423
|
*/
|
|
578
1424
|
transformAttachmentPaths(obj) {
|
|
579
1425
|
if (typeof obj !== "object" || obj === null) {
|
|
@@ -593,21 +1439,7 @@ var Zipper = class {
|
|
|
593
1439
|
Object.values(obj).forEach((value) => this.transformAttachmentPaths(value));
|
|
594
1440
|
}
|
|
595
1441
|
/**
|
|
596
|
-
* Normalizes attachment paths by extracting the relevant snapshot directory portion
|
|
597
|
-
* Supports Playwright's default and common custom snapshot directory patterns,
|
|
598
|
-
* as well as blob merge resource paths.
|
|
599
|
-
*
|
|
600
|
-
* Priority order (first match wins):
|
|
601
|
-
* 1. test-results/ (highest priority, existing behavior)
|
|
602
|
-
* 2. blob-reports/resources/ (blob merge extraction paths)
|
|
603
|
-
* 3. snapshots directories (Playwright default pattern)
|
|
604
|
-
* 4. __screenshots__/ (common custom pattern)
|
|
605
|
-
* 5. __snapshots__/ (common custom pattern)
|
|
606
|
-
* 6. screenshots/ (simple custom pattern)
|
|
607
|
-
* 7. snapshots/ (simple custom pattern)
|
|
608
|
-
*
|
|
609
|
-
* @param attachmentPath - Absolute or relative path to attachment
|
|
610
|
-
* @returns Normalized path starting from the matched directory, or original path if no match
|
|
1442
|
+
* Normalizes attachment paths by extracting the relevant snapshot directory portion
|
|
611
1443
|
*/
|
|
612
1444
|
normalizeAttachmentPath(attachmentPath) {
|
|
613
1445
|
const normalizedPath = attachmentPath.replace(/\\/g, "/");
|
|
@@ -644,17 +1476,11 @@ var Zipper = class {
|
|
|
644
1476
|
}
|
|
645
1477
|
};
|
|
646
1478
|
|
|
647
|
-
// src/
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
import * as path3 from "path";
|
|
651
|
-
import { dirname, join as join3 } from "path";
|
|
652
|
-
import { fileURLToPath } from "url";
|
|
653
|
-
|
|
654
|
-
// ../clients/src/checkly-client.ts
|
|
655
|
-
import axios from "axios";
|
|
1479
|
+
// src/api/client.ts
|
|
1480
|
+
var import_axios = __toESM(require("axios"));
|
|
1481
|
+
var import_form_data = __toESM(require("form-data"));
|
|
656
1482
|
|
|
657
|
-
//
|
|
1483
|
+
// src/api/errors.ts
|
|
658
1484
|
var ApiError = class extends Error {
|
|
659
1485
|
data;
|
|
660
1486
|
constructor(data, options) {
|
|
@@ -664,44 +1490,20 @@ var ApiError = class extends Error {
|
|
|
664
1490
|
}
|
|
665
1491
|
};
|
|
666
1492
|
var ValidationError = class extends ApiError {
|
|
667
|
-
constructor(data, options) {
|
|
668
|
-
super(data, options);
|
|
669
|
-
}
|
|
670
1493
|
};
|
|
671
1494
|
var UnauthorizedError = class extends ApiError {
|
|
672
|
-
constructor(data, options) {
|
|
673
|
-
super(data, options);
|
|
674
|
-
}
|
|
675
1495
|
};
|
|
676
1496
|
var ForbiddenError = class extends ApiError {
|
|
677
|
-
constructor(data, options) {
|
|
678
|
-
super(data, options);
|
|
679
|
-
}
|
|
680
1497
|
};
|
|
681
1498
|
var NotFoundError = class extends ApiError {
|
|
682
|
-
constructor(data, options) {
|
|
683
|
-
super(data, options);
|
|
684
|
-
}
|
|
685
1499
|
};
|
|
686
1500
|
var RequestTimeoutError = class extends ApiError {
|
|
687
|
-
constructor(data, options) {
|
|
688
|
-
super(data, options);
|
|
689
|
-
}
|
|
690
1501
|
};
|
|
691
1502
|
var ConflictError = class extends ApiError {
|
|
692
|
-
constructor(data, options) {
|
|
693
|
-
super(data, options);
|
|
694
|
-
}
|
|
695
1503
|
};
|
|
696
1504
|
var ServerError = class extends ApiError {
|
|
697
|
-
constructor(data, options) {
|
|
698
|
-
super(data, options);
|
|
699
|
-
}
|
|
700
1505
|
};
|
|
701
1506
|
var MiscellaneousError = class extends ApiError {
|
|
702
|
-
constructor(data, options) {
|
|
703
|
-
super(data, options);
|
|
704
|
-
}
|
|
705
1507
|
};
|
|
706
1508
|
var MissingResponseError = class extends Error {
|
|
707
1509
|
constructor(message, options) {
|
|
@@ -709,63 +1511,58 @@ var MissingResponseError = class extends Error {
|
|
|
709
1511
|
this.name = "MissingResponseError";
|
|
710
1512
|
}
|
|
711
1513
|
};
|
|
712
|
-
function parseErrorData(data,
|
|
713
|
-
if (!data)
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1514
|
+
function parseErrorData(data, statusCode) {
|
|
1515
|
+
if (!data) return void 0;
|
|
1516
|
+
if (typeof data === "object" && data !== null) {
|
|
1517
|
+
const obj = data;
|
|
1518
|
+
if (obj.statusCode && obj.error && obj.message) {
|
|
1519
|
+
return {
|
|
1520
|
+
statusCode: obj.statusCode,
|
|
1521
|
+
error: obj.error,
|
|
1522
|
+
message: obj.message,
|
|
1523
|
+
errorCode: obj.errorCode
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
if (obj.error && obj.message) {
|
|
1527
|
+
return {
|
|
1528
|
+
statusCode,
|
|
1529
|
+
error: obj.error,
|
|
1530
|
+
message: obj.message,
|
|
1531
|
+
errorCode: obj.errorCode
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
if (obj.error) {
|
|
1535
|
+
return {
|
|
1536
|
+
statusCode,
|
|
1537
|
+
error: obj.error,
|
|
1538
|
+
message: obj.error
|
|
1539
|
+
};
|
|
1540
|
+
}
|
|
1541
|
+
if (obj.message) {
|
|
1542
|
+
return {
|
|
1543
|
+
statusCode,
|
|
1544
|
+
error: obj.message,
|
|
1545
|
+
message: obj.message,
|
|
1546
|
+
errorCode: obj.errorCode
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
746
1549
|
}
|
|
747
1550
|
if (typeof data === "string") {
|
|
748
|
-
return {
|
|
749
|
-
statusCode: options.statusCode,
|
|
750
|
-
error: data,
|
|
751
|
-
message: data
|
|
752
|
-
};
|
|
1551
|
+
return { statusCode, error: data, message: data };
|
|
753
1552
|
}
|
|
754
1553
|
return void 0;
|
|
755
1554
|
}
|
|
756
|
-
function handleErrorResponse(
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
const
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
});
|
|
768
|
-
}
|
|
1555
|
+
function handleErrorResponse(err2) {
|
|
1556
|
+
const axiosError = err2;
|
|
1557
|
+
if (!axiosError.response) {
|
|
1558
|
+
throw new MissingResponseError(axiosError.message || "Network error");
|
|
1559
|
+
}
|
|
1560
|
+
const { status, data } = axiosError.response;
|
|
1561
|
+
const errorData = parseErrorData(data, status) ?? {
|
|
1562
|
+
statusCode: status,
|
|
1563
|
+
error: "Unknown error",
|
|
1564
|
+
message: axiosError.message || "An error occurred"
|
|
1565
|
+
};
|
|
769
1566
|
switch (status) {
|
|
770
1567
|
case 400:
|
|
771
1568
|
throw new ValidationError(errorData);
|
|
@@ -787,715 +1584,905 @@ function handleErrorResponse(err) {
|
|
|
787
1584
|
}
|
|
788
1585
|
}
|
|
789
1586
|
|
|
790
|
-
//
|
|
791
|
-
function
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
1587
|
+
// src/api/client.ts
|
|
1588
|
+
function createClient(options) {
|
|
1589
|
+
const http = import_axios.default.create({
|
|
1590
|
+
baseURL: options.baseUrl,
|
|
1591
|
+
timeout: 12e4,
|
|
1592
|
+
maxContentLength: Number.POSITIVE_INFINITY,
|
|
1593
|
+
maxBodyLength: Number.POSITIVE_INFINITY
|
|
1594
|
+
});
|
|
1595
|
+
http.interceptors.request.use((config) => {
|
|
796
1596
|
if (config.headers) {
|
|
797
|
-
config.headers.Authorization = `Bearer ${apiKey}`;
|
|
798
|
-
config.headers["x-checkly-account"] = accountId;
|
|
799
|
-
config.headers["
|
|
1597
|
+
config.headers.Authorization = `Bearer ${options.apiKey}`;
|
|
1598
|
+
config.headers["x-checkly-account"] = options.accountId;
|
|
1599
|
+
config.headers["x-checkly-reporter-version"] = options.telemetry.reporterVersion;
|
|
1600
|
+
config.headers["x-checkly-playwright-version"] = options.telemetry.playwrightVersion;
|
|
1601
|
+
config.headers["x-checkly-ci-provider"] = options.telemetry.ciProvider;
|
|
1602
|
+
config.headers["x-checkly-ci-environment"] = options.telemetry.ciEnvironment;
|
|
1603
|
+
config.headers["x-checkly-node-version"] = options.telemetry.nodeVersion;
|
|
800
1604
|
}
|
|
801
1605
|
return config;
|
|
1606
|
+
});
|
|
1607
|
+
http.interceptors.response.use(
|
|
1608
|
+
(response) => response,
|
|
1609
|
+
(error) => handleErrorResponse(error)
|
|
1610
|
+
);
|
|
1611
|
+
return {
|
|
1612
|
+
testSessions: {
|
|
1613
|
+
async create(request) {
|
|
1614
|
+
const response = await http.post("/next/test-sessions/create", request);
|
|
1615
|
+
return response.data;
|
|
1616
|
+
},
|
|
1617
|
+
async uploadAsset(testSessionId, testResultId, assets) {
|
|
1618
|
+
const form = new import_form_data.default();
|
|
1619
|
+
form.append("assets", assets, { filename: "assets.zip", contentType: "application/zip" });
|
|
1620
|
+
const response = await http.post(
|
|
1621
|
+
`/next/test-sessions/${testSessionId}/results/${testResultId}/assets`,
|
|
1622
|
+
form,
|
|
1623
|
+
{ headers: form.getHeaders() }
|
|
1624
|
+
);
|
|
1625
|
+
return response.data;
|
|
1626
|
+
},
|
|
1627
|
+
async updateResult(testSessionId, testResultId, request) {
|
|
1628
|
+
const response = await http.post(
|
|
1629
|
+
`/next/test-sessions/${testSessionId}/results/${testResultId}`,
|
|
1630
|
+
request
|
|
1631
|
+
);
|
|
1632
|
+
return response.data;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
802
1635
|
};
|
|
803
1636
|
}
|
|
804
|
-
function createResponseErrorInterceptor() {
|
|
805
|
-
return (error) => {
|
|
806
|
-
handleErrorResponse(error);
|
|
807
|
-
};
|
|
808
|
-
}
|
|
809
|
-
var ChecklyClient = class {
|
|
810
|
-
apiKey;
|
|
811
|
-
baseUrl;
|
|
812
|
-
accountId;
|
|
813
|
-
api;
|
|
814
|
-
constructor(options) {
|
|
815
|
-
this.accountId = options.accountId;
|
|
816
|
-
this.apiKey = options.apiKey;
|
|
817
|
-
this.baseUrl = options.baseUrl;
|
|
818
|
-
this.api = axios.create({
|
|
819
|
-
baseURL: this.baseUrl,
|
|
820
|
-
timeout: 12e4,
|
|
821
|
-
// 120 second timeout for large uploads
|
|
822
|
-
maxContentLength: Number.POSITIVE_INFINITY,
|
|
823
|
-
// Allow large payloads
|
|
824
|
-
maxBodyLength: Number.POSITIVE_INFINITY
|
|
825
|
-
// Allow large request bodies
|
|
826
|
-
});
|
|
827
|
-
this.api.interceptors.request.use(createRequestInterceptor(this.apiKey, this.accountId));
|
|
828
|
-
this.api.interceptors.response.use((response) => response, createResponseErrorInterceptor());
|
|
829
|
-
}
|
|
830
|
-
/**
|
|
831
|
-
* Gets the underlying axios instance
|
|
832
|
-
* Useful for creating resource-specific clients (e.g., TestResults)
|
|
833
|
-
*/
|
|
834
|
-
getAxiosInstance() {
|
|
835
|
-
return this.api;
|
|
836
|
-
}
|
|
837
|
-
};
|
|
838
1637
|
|
|
839
|
-
//
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
* @param request Test session creation request
|
|
849
|
-
* @returns Test session response with session ID and test result IDs
|
|
850
|
-
* @throws {ValidationError} If request data is invalid
|
|
851
|
-
* @throws {UnauthorizedError} If authentication fails
|
|
852
|
-
* @throws {ServerError} If server error occurs
|
|
853
|
-
*/
|
|
854
|
-
async createTestSession(request) {
|
|
855
|
-
const response = await this.api.post("/next/test-sessions/create", request);
|
|
856
|
-
return response.data;
|
|
857
|
-
}
|
|
858
|
-
/**
|
|
859
|
-
* Step 1: Upload test result assets to S3
|
|
860
|
-
* Streams a ZIP file containing test assets (traces, videos, screenshots)
|
|
861
|
-
*
|
|
862
|
-
* @param testSessionId ID of the test session
|
|
863
|
-
* @param testResultId ID of the test result
|
|
864
|
-
* @param assets Buffer or ReadableStream of the ZIP file
|
|
865
|
-
* @returns Upload response with assetId, region, key, and url
|
|
866
|
-
* @throws {ValidationError} If assets are invalid
|
|
867
|
-
* @throws {UnauthorizedError} If authentication fails
|
|
868
|
-
* @throws {NotFoundError} If test session or result not found
|
|
869
|
-
* @throws {PayloadTooLargeError} If assets exceed 500MB
|
|
870
|
-
* @throws {ServerError} If S3 upload fails
|
|
871
|
-
*/
|
|
872
|
-
async uploadTestResultAsset(testSessionId, testResultId, assets) {
|
|
873
|
-
const form = new FormData();
|
|
874
|
-
form.append("assets", assets, {
|
|
875
|
-
filename: "assets.zip",
|
|
876
|
-
contentType: "application/zip"
|
|
877
|
-
});
|
|
878
|
-
const response = await this.api.post(
|
|
879
|
-
`/next/test-sessions/${testSessionId}/results/${testResultId}/assets`,
|
|
880
|
-
form,
|
|
881
|
-
{
|
|
882
|
-
headers: {
|
|
883
|
-
...form.getHeaders()
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
);
|
|
887
|
-
return response.data;
|
|
888
|
-
}
|
|
889
|
-
/**
|
|
890
|
-
* Step 2: Update test result with status and optional asset reference
|
|
891
|
-
* Uses JSON payload for clean, easy-to-validate updates
|
|
892
|
-
*
|
|
893
|
-
* @param testSessionId ID of the test session
|
|
894
|
-
* @param testResultId ID of the test result to update
|
|
895
|
-
* @param request Test result update request (JSON)
|
|
896
|
-
* @returns Test result update response
|
|
897
|
-
* @throws {ValidationError} If request data is invalid
|
|
898
|
-
* @throws {UnauthorizedError} If authentication fails
|
|
899
|
-
* @throws {NotFoundError} If test session or result not found
|
|
900
|
-
* @throws {ServerError} If server error occurs
|
|
901
|
-
*/
|
|
902
|
-
async updateTestResult(testSessionId, testResultId, request) {
|
|
903
|
-
const response = await this.api.post(
|
|
904
|
-
`/next/test-sessions/${testSessionId}/results/${testResultId}`,
|
|
905
|
-
request
|
|
1638
|
+
// src/extensions/checkly-upload.ts
|
|
1639
|
+
var MissingCredentialsError = class extends Error {
|
|
1640
|
+
constructor(missing) {
|
|
1641
|
+
const missingList = missing.map((m) => m === "CHECKLY_API_KEY" ? "apiKey / CHECKLY_API_KEY" : "accountId / CHECKLY_ACCOUNT_ID").join(", ");
|
|
1642
|
+
super(
|
|
1643
|
+
`Missing required Checkly credentials: ${missingList}.
|
|
1644
|
+
Provide them via reporter options or environment variables.
|
|
1645
|
+
Get your API key at: https://app.checklyhq.com/settings/user/api-keys
|
|
1646
|
+
Or use dryRun: true for local report generation.`
|
|
906
1647
|
);
|
|
907
|
-
|
|
1648
|
+
this.name = "MissingCredentialsError";
|
|
908
1649
|
}
|
|
909
1650
|
};
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
zero: "Project",
|
|
919
|
-
one: "Project",
|
|
920
|
-
two: "Projects",
|
|
921
|
-
few: "Projects",
|
|
922
|
-
many: "Projects",
|
|
923
|
-
other: "Projects"
|
|
924
|
-
};
|
|
1651
|
+
function getPackageVersion() {
|
|
1652
|
+
try {
|
|
1653
|
+
const packageJson = JSON.parse(fs5.readFileSync(path4.join(__dirname, "..", "package.json"), "utf-8"));
|
|
1654
|
+
return packageJson.version;
|
|
1655
|
+
} catch {
|
|
1656
|
+
return "unknown";
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
925
1659
|
function getApiUrl(environment) {
|
|
926
|
-
const
|
|
1660
|
+
const urls = {
|
|
927
1661
|
local: "http://127.0.0.1:3000",
|
|
928
1662
|
development: "https://api-dev.checklyhq.com",
|
|
929
1663
|
staging: "https://api-test.checklyhq.com",
|
|
930
1664
|
production: "https://api.checklyhq.com"
|
|
931
1665
|
};
|
|
932
|
-
return
|
|
1666
|
+
return urls[environment];
|
|
933
1667
|
}
|
|
934
|
-
function getEnvironment(
|
|
935
|
-
const
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
if (!validEnvironments.includes(env)) {
|
|
940
|
-
console.warn(`[Checkly Reporter] Invalid environment "${env}", using "production"`);
|
|
1668
|
+
function getEnvironment() {
|
|
1669
|
+
const env = process.env.CHECKLY_ENV || "production";
|
|
1670
|
+
const valid = ["local", "development", "staging", "production"];
|
|
1671
|
+
if (!valid.includes(env)) {
|
|
1672
|
+
console.warn(`[Checkly] Invalid environment "${env}", using "production"`);
|
|
941
1673
|
return "production";
|
|
942
1674
|
}
|
|
943
1675
|
return env;
|
|
944
1676
|
}
|
|
945
|
-
function convertStepToJSON(step) {
|
|
946
|
-
return {
|
|
947
|
-
title: step.title,
|
|
948
|
-
duration: step.duration,
|
|
949
|
-
error: step.error,
|
|
950
|
-
steps: step.steps.length > 0 ? step.steps.map(convertStepToJSON) : void 0
|
|
951
|
-
};
|
|
952
|
-
}
|
|
953
1677
|
function getDirectoryName() {
|
|
954
1678
|
const cwd = process.cwd();
|
|
955
|
-
let
|
|
956
|
-
if (!
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
if (dirName.length > 255) {
|
|
961
|
-
dirName = dirName.substring(0, 255);
|
|
962
|
-
}
|
|
963
|
-
return dirName;
|
|
1679
|
+
let name = path4.basename(cwd);
|
|
1680
|
+
if (!name || name === "/" || name === ".") name = "playwright-tests";
|
|
1681
|
+
name = name.replace(/[<>:"|?*]/g, "-");
|
|
1682
|
+
if (name.length > 255) name = name.substring(0, 255);
|
|
1683
|
+
return name;
|
|
964
1684
|
}
|
|
965
|
-
|
|
966
|
-
options;
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
tracePathsMap = /* @__PURE__ */ new Map();
|
|
983
|
-
|
|
984
|
-
consoleMessagesMap = /* @__PURE__ */ new Map();
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
if (
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
accountId,
|
|
1007
|
-
apiKey,
|
|
1008
|
-
outputPath: options.outputPath ?? "checkly-report.zip",
|
|
1009
|
-
jsonReportPath: options.jsonReportPath ?? "test-results/playwright-test-report.json",
|
|
1010
|
-
testResultsDir: options.testResultsDir ?? "test-results",
|
|
1011
|
-
dryRun: options.dryRun ?? false,
|
|
1012
|
-
sessionName: options.sessionName,
|
|
1013
|
-
verbose
|
|
1014
|
-
};
|
|
1015
|
-
this.assetCollector = new AssetCollector(this.options.testResultsDir);
|
|
1016
|
-
this.zipper = new Zipper({
|
|
1017
|
-
outputPath: this.options.outputPath
|
|
1018
|
-
});
|
|
1019
|
-
if (!this.options.dryRun && this.options.apiKey && this.options.accountId) {
|
|
1020
|
-
const client = new ChecklyClient({
|
|
1021
|
-
apiKey: this.options.apiKey,
|
|
1022
|
-
accountId: this.options.accountId,
|
|
1023
|
-
baseUrl
|
|
1024
|
-
});
|
|
1025
|
-
this.testResults = new TestResults(client.getAxiosInstance());
|
|
1026
|
-
}
|
|
1027
|
-
if (verbose) {
|
|
1028
|
-
console.log(`[Checkly Reporter DEBUG] Initialized with options:`, {
|
|
1029
|
-
environment,
|
|
1030
|
-
baseUrl,
|
|
1031
|
-
hasApiKey: !!apiKey,
|
|
1032
|
-
hasAccountId: !!accountId,
|
|
1033
|
-
outputPath: this.options.outputPath,
|
|
1034
|
-
jsonReportPath: this.options.jsonReportPath,
|
|
1035
|
-
testResultsDir: this.options.testResultsDir,
|
|
1036
|
-
dryRun: this.options.dryRun,
|
|
1037
|
-
verbose: this.options.verbose,
|
|
1038
|
-
hasTestResults: !!this.testResults
|
|
1685
|
+
function checklyUpload(options = {}) {
|
|
1686
|
+
const apiKey = process.env.CHECKLY_API_KEY || options.apiKey;
|
|
1687
|
+
const accountId = process.env.CHECKLY_ACCOUNT_ID || options.accountId;
|
|
1688
|
+
const environment = getEnvironment();
|
|
1689
|
+
const baseUrl = getApiUrl(environment);
|
|
1690
|
+
const dryRun = options.dryRun ?? false;
|
|
1691
|
+
const ciInfo = detectCI();
|
|
1692
|
+
const reporterVersion = getPackageVersion();
|
|
1693
|
+
const canUpload = !dryRun && apiKey && accountId;
|
|
1694
|
+
let api;
|
|
1695
|
+
let testSession;
|
|
1696
|
+
let sessionCreationPromise;
|
|
1697
|
+
let startTime;
|
|
1698
|
+
let resolvedOutputDir;
|
|
1699
|
+
let assetCollector;
|
|
1700
|
+
let zipper;
|
|
1701
|
+
const testCounts = { passed: 0, failed: 0, flaky: 0 };
|
|
1702
|
+
const tracePathsMap = /* @__PURE__ */ new Map();
|
|
1703
|
+
const warningsMap = /* @__PURE__ */ new Map();
|
|
1704
|
+
const consoleMessagesMap = /* @__PURE__ */ new Map();
|
|
1705
|
+
const networkRequestsMap = /* @__PURE__ */ new Map();
|
|
1706
|
+
function resolveSessionName(ctx) {
|
|
1707
|
+
const { sessionName } = options;
|
|
1708
|
+
if (typeof sessionName === "function") return sessionName(ctx);
|
|
1709
|
+
if (typeof sessionName === "string") return sessionName;
|
|
1710
|
+
return `Playwright Test Session: ${ctx.directoryName}`;
|
|
1711
|
+
}
|
|
1712
|
+
async function createSession(config, suite, log) {
|
|
1713
|
+
if (!api) return;
|
|
1714
|
+
try {
|
|
1715
|
+
const directoryName = getDirectoryName();
|
|
1716
|
+
const sessionName = resolveSessionName({ directoryName, config, suite });
|
|
1717
|
+
const repoInfo = getGitHubRepoInfo();
|
|
1718
|
+
log("\u{1F517} Creating test session", { name: sessionName, environment });
|
|
1719
|
+
testSession = await api.testSessions.create({
|
|
1720
|
+
name: sessionName,
|
|
1721
|
+
environment: process.env.NODE_ENV || "test",
|
|
1722
|
+
repoInfo,
|
|
1723
|
+
startedAt: startTime.getTime(),
|
|
1724
|
+
testResults: [{ name: directoryName }],
|
|
1725
|
+
provider: "PW_REPORTER"
|
|
1039
1726
|
});
|
|
1727
|
+
log("\u2705 Session created", { id: testSession.testSessionId });
|
|
1728
|
+
} catch (err2) {
|
|
1729
|
+
if (err2 instanceof UnauthorizedError) {
|
|
1730
|
+
console.error(
|
|
1731
|
+
"[Checkly] Authentication failed: Invalid API key.\n Please verify your apiKey option or CHECKLY_API_KEY environment variable is correct.\n Get your API key at: https://app.checklyhq.com/settings/user/api-keys"
|
|
1732
|
+
);
|
|
1733
|
+
api = void 0;
|
|
1734
|
+
return;
|
|
1735
|
+
}
|
|
1736
|
+
if (err2 instanceof ForbiddenError) {
|
|
1737
|
+
console.error(
|
|
1738
|
+
"[Checkly] Access denied: You do not have access to this account.\n Please verify your accountId option or CHECKLY_ACCOUNT_ID environment variable is correct.\n Get your API key at: https://app.checklyhq.com/settings/user/api-keys"
|
|
1739
|
+
);
|
|
1740
|
+
api = void 0;
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
console.error("[Checkly] Failed to create test session:", err2);
|
|
1040
1744
|
}
|
|
1041
1745
|
}
|
|
1042
|
-
|
|
1043
|
-
* Resolves the session name from options
|
|
1044
|
-
* Supports string, callback function, or falls back to default
|
|
1045
|
-
*/
|
|
1046
|
-
resolveSessionName(context) {
|
|
1047
|
-
const { sessionName } = this.options;
|
|
1048
|
-
if (typeof sessionName === "function") {
|
|
1049
|
-
return sessionName(context);
|
|
1050
|
-
}
|
|
1051
|
-
if (typeof sessionName === "string") {
|
|
1052
|
-
return sessionName;
|
|
1053
|
-
}
|
|
1054
|
-
return `Playwright Test Session: ${context.directoryName}`;
|
|
1055
|
-
}
|
|
1056
|
-
/**
|
|
1057
|
-
* Checks if test result has a trace attachment and adds context-aware warning if missing
|
|
1058
|
-
* Also captures trace file path for later console message extraction
|
|
1059
|
-
* The warning type depends on the trace configuration and test result state
|
|
1060
|
-
*/
|
|
1061
|
-
checkTraceAttachment(test, result) {
|
|
1746
|
+
function checkTraceAttachment(test, result) {
|
|
1062
1747
|
const key = `${test.id}:${result.retry}`;
|
|
1063
|
-
const traceAttachment = result.attachments?.find(
|
|
1064
|
-
(attachment) => attachment.name === "trace" || attachment.contentType === "application/zip"
|
|
1065
|
-
);
|
|
1748
|
+
const traceAttachment = result.attachments?.find((a) => a.name === "trace" || a.contentType === "application/zip");
|
|
1066
1749
|
if (traceAttachment?.path) {
|
|
1067
|
-
|
|
1750
|
+
tracePathsMap.set(key, traceAttachment.path);
|
|
1068
1751
|
return;
|
|
1069
1752
|
}
|
|
1070
1753
|
const traceConfig = test.parent?.project()?.use?.trace;
|
|
1071
1754
|
const traceMode = typeof traceConfig === "object" ? traceConfig.mode : traceConfig;
|
|
1072
|
-
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
} else {
|
|
1121
|
-
warningType = "trace-missing";
|
|
1122
|
-
message = 'Trace should exist but was not found. The test failed on first run with trace: "retain-on-first-failure".';
|
|
1755
|
+
if (!traceMode || traceMode === "off") return;
|
|
1756
|
+
const warnings = warningsMap.get(key) || [];
|
|
1757
|
+
warnings.push({ type: "trace-missing", message: `No trace found for trace mode "${traceMode}"` });
|
|
1758
|
+
warningsMap.set(key, warnings);
|
|
1759
|
+
}
|
|
1760
|
+
async function extractTraceData(key, tracePath) {
|
|
1761
|
+
const reader = new TraceReader(tracePath);
|
|
1762
|
+
if (!await reader.open()) return;
|
|
1763
|
+
const messages = await reader.extractEvents('"type":"console"', toConsoleMessage);
|
|
1764
|
+
if (messages.length > 0) consoleMessagesMap.set(key, messages);
|
|
1765
|
+
const requests = await reader.extractEvents('"type":"resource-snapshot"', toNetworkRequest);
|
|
1766
|
+
if (requests.length > 0) networkRequestsMap.set(key, requests);
|
|
1767
|
+
}
|
|
1768
|
+
async function extractDataFromTraces(log) {
|
|
1769
|
+
if (tracePathsMap.size === 0) return;
|
|
1770
|
+
log("\u{1F4E6} Extracting trace data", { traces: tracePathsMap.size });
|
|
1771
|
+
const extractions = Array.from(tracePathsMap.entries()).map(
|
|
1772
|
+
([key, tracePath]) => extractTraceData(key, tracePath).catch((err2) => {
|
|
1773
|
+
console.error(`[Checkly] Failed to extract trace data: ${err2}`);
|
|
1774
|
+
})
|
|
1775
|
+
);
|
|
1776
|
+
await Promise.all(extractions);
|
|
1777
|
+
}
|
|
1778
|
+
function buildChecklyExtensionData(key) {
|
|
1779
|
+
const warnings = warningsMap.get(key);
|
|
1780
|
+
const consoleMessages = consoleMessagesMap.get(key);
|
|
1781
|
+
const network = networkRequestsMap.get(key);
|
|
1782
|
+
if (!warnings?.length && !consoleMessages?.length && !network?.length) {
|
|
1783
|
+
return null;
|
|
1784
|
+
}
|
|
1785
|
+
return {
|
|
1786
|
+
...warnings?.length ? { warnings } : {},
|
|
1787
|
+
...consoleMessages?.length ? { console: consoleMessages } : {},
|
|
1788
|
+
...network?.length ? { network } : {}
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
function injectDataIntoReport(report) {
|
|
1792
|
+
function processSuite(suite) {
|
|
1793
|
+
for (const spec of suite.specs) {
|
|
1794
|
+
for (const test of spec.tests) {
|
|
1795
|
+
for (const result of test.results) {
|
|
1796
|
+
const key = `${spec.id}:${result.retry}`;
|
|
1797
|
+
const checklyData = buildChecklyExtensionData(key);
|
|
1798
|
+
if (checklyData) {
|
|
1799
|
+
;
|
|
1800
|
+
result._checkly = checklyData;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1123
1803
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
warningType = "trace-missing";
|
|
1127
|
-
message = 'Trace should exist but was not found. Trace mode is "on" which should always record traces.';
|
|
1128
|
-
break;
|
|
1129
|
-
default:
|
|
1130
|
-
warningType = "trace-missing";
|
|
1131
|
-
message = `No trace found. Trace mode "${traceMode}" may not be generating traces for this result.`;
|
|
1804
|
+
}
|
|
1805
|
+
suite.suites?.forEach(processSuite);
|
|
1132
1806
|
}
|
|
1133
|
-
|
|
1134
|
-
warnings.push({ type: warningType, message });
|
|
1135
|
-
this.warningsMap.set(key, warnings);
|
|
1807
|
+
report.suites.forEach(processSuite);
|
|
1136
1808
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1809
|
+
function calculateTiming(report) {
|
|
1810
|
+
const stats = report.stats;
|
|
1811
|
+
if (stats?.startTime && stats?.duration !== void 0) {
|
|
1812
|
+
const start = new Date(stats.startTime);
|
|
1813
|
+
const responseTime = Math.round(stats.duration);
|
|
1814
|
+
return {
|
|
1815
|
+
startedAt: start.toISOString(),
|
|
1816
|
+
stoppedAt: new Date(start.getTime() + responseTime).toISOString(),
|
|
1817
|
+
responseTime
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
const now = Date.now();
|
|
1821
|
+
return {
|
|
1822
|
+
startedAt: startTime?.toISOString() ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1823
|
+
stoppedAt: new Date(now).toISOString(),
|
|
1824
|
+
responseTime: startTime ? Math.round(now - startTime.getTime()) : 0
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
async function uploadAssets(log, zipPath, zipSizeBytes) {
|
|
1828
|
+
if (!api || !testSession || zipSizeBytes === 0) return void 0;
|
|
1829
|
+
const firstResult = testSession.testResults[0];
|
|
1830
|
+
if (!firstResult) return void 0;
|
|
1831
|
+
log("\u{1F4E4} Uploading assets", { size: `${(zipSizeBytes / 1024).toFixed(1)}KB` });
|
|
1832
|
+
try {
|
|
1833
|
+
const assets = fs5.createReadStream(zipPath);
|
|
1834
|
+
const uploadResponse = await api.testSessions.uploadAsset(
|
|
1835
|
+
testSession.testSessionId,
|
|
1836
|
+
firstResult.testResultId,
|
|
1837
|
+
assets
|
|
1838
|
+
);
|
|
1839
|
+
log("\u2705 Assets uploaded", { assetId: uploadResponse.assetId });
|
|
1840
|
+
return uploadResponse.assetId;
|
|
1841
|
+
} catch (err2) {
|
|
1842
|
+
console.error("[Checkly] Asset upload failed:", err2);
|
|
1843
|
+
return void 0;
|
|
1145
1844
|
}
|
|
1845
|
+
}
|
|
1846
|
+
async function uploadResults(log, report, zipPath, entries) {
|
|
1847
|
+
if (!api || !testSession || testSession.testResults.length === 0) return;
|
|
1146
1848
|
try {
|
|
1147
|
-
const
|
|
1148
|
-
const
|
|
1149
|
-
const
|
|
1150
|
-
const
|
|
1151
|
-
const
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
repoInfo,
|
|
1162
|
-
startedAt: this.startTime.getTime(),
|
|
1163
|
-
// Required timestamp in milliseconds
|
|
1164
|
-
testResults,
|
|
1165
|
-
provider: "PW_REPORTER"
|
|
1166
|
-
}).then((response) => {
|
|
1167
|
-
this.testSession = response;
|
|
1168
|
-
}).catch((error) => {
|
|
1169
|
-
console.error("[Checkly Reporter] Failed to create test session:", error.message);
|
|
1849
|
+
const { failed, flaky } = testCounts;
|
|
1850
|
+
const overallStatus = failed > 0 ? "FAILED" : "PASSED";
|
|
1851
|
+
const isDegraded = failed === 0 && flaky > 0;
|
|
1852
|
+
const timing = calculateTiming(report);
|
|
1853
|
+
const zipSizeBytes = (await fs5.promises.stat(zipPath)).size;
|
|
1854
|
+
const assetId = await uploadAssets(log, zipPath, zipSizeBytes);
|
|
1855
|
+
const firstResult = testSession.testResults[0];
|
|
1856
|
+
log("\u{1F4DD} Updating test result", { status: overallStatus, isDegraded });
|
|
1857
|
+
await api.testSessions.updateResult(testSession.testSessionId, firstResult.testResultId, {
|
|
1858
|
+
status: overallStatus,
|
|
1859
|
+
assetEntries: assetId ? entries : void 0,
|
|
1860
|
+
isDegraded,
|
|
1861
|
+
...timing,
|
|
1862
|
+
metadata: { usageData: { s3PostTotalBytes: zipSizeBytes } }
|
|
1170
1863
|
});
|
|
1171
|
-
} catch (
|
|
1172
|
-
console.error("[Checkly
|
|
1864
|
+
} catch (err2) {
|
|
1865
|
+
console.error("[Checkly] Failed to upload results:", err2);
|
|
1173
1866
|
}
|
|
1174
1867
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
if (
|
|
1184
|
-
|
|
1868
|
+
return {
|
|
1869
|
+
name: "checkly-upload",
|
|
1870
|
+
onBegin: ({ config, suite, log }) => {
|
|
1871
|
+
startTime = /* @__PURE__ */ new Date();
|
|
1872
|
+
resolvedOutputDir = options.outputDir ?? config.projects[0]?.outputDir ?? "test-results";
|
|
1873
|
+
const zipPath = path4.join(resolvedOutputDir, "checkly-report.zip");
|
|
1874
|
+
assetCollector = new AssetCollector(resolvedOutputDir);
|
|
1875
|
+
zipper = new Zipper({ outputPath: zipPath });
|
|
1876
|
+
if (!canUpload) {
|
|
1877
|
+
if (dryRun) {
|
|
1878
|
+
console.warn("[Checkly] Dry run mode - report will be generated locally");
|
|
1879
|
+
return;
|
|
1880
|
+
}
|
|
1881
|
+
const missing = [];
|
|
1882
|
+
if (!apiKey) missing.push("CHECKLY_API_KEY");
|
|
1883
|
+
if (!accountId) missing.push("CHECKLY_ACCOUNT_ID");
|
|
1884
|
+
throw new MissingCredentialsError(missing);
|
|
1185
1885
|
}
|
|
1886
|
+
api = createClient({
|
|
1887
|
+
apiKey,
|
|
1888
|
+
accountId,
|
|
1889
|
+
baseUrl,
|
|
1890
|
+
telemetry: {
|
|
1891
|
+
reporterVersion,
|
|
1892
|
+
playwrightVersion: config.version,
|
|
1893
|
+
ciProvider: ciInfo.ciProvider,
|
|
1894
|
+
ciEnvironment: ciInfo.environment,
|
|
1895
|
+
nodeVersion: process.version
|
|
1896
|
+
}
|
|
1897
|
+
});
|
|
1898
|
+
sessionCreationPromise = createSession(config, suite, log);
|
|
1899
|
+
},
|
|
1900
|
+
onTestEnd: ({ test, result }) => {
|
|
1901
|
+
checkTraceAttachment(test, result);
|
|
1186
1902
|
const outcome = test.outcome();
|
|
1187
1903
|
const testIsComplete = result.retry === test.retries || outcome !== "unexpected";
|
|
1188
|
-
if (!testIsComplete)
|
|
1189
|
-
|
|
1904
|
+
if (!testIsComplete) return;
|
|
1905
|
+
if (outcome === "flaky") {
|
|
1906
|
+
testCounts.flaky++;
|
|
1907
|
+
testCounts.passed++;
|
|
1908
|
+
} else if (result.status === "passed") {
|
|
1909
|
+
testCounts.passed++;
|
|
1910
|
+
} else if (result.status === "failed" || result.status === "timedOut") {
|
|
1911
|
+
testCounts.failed++;
|
|
1190
1912
|
}
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
if (result.status === "passed") {
|
|
1197
|
-
this.testCounts.passed++;
|
|
1198
|
-
} else if (result.status === "failed" || result.status === "timedOut") {
|
|
1199
|
-
this.testCounts.failed++;
|
|
1913
|
+
},
|
|
1914
|
+
onEnd: async ({ report, log, addSummaryLine }) => {
|
|
1915
|
+
try {
|
|
1916
|
+
if (sessionCreationPromise) {
|
|
1917
|
+
await sessionCreationPromise;
|
|
1200
1918
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
const jsonReportPath = this.options.jsonReportPath;
|
|
1220
|
-
if (!fs4.existsSync(jsonReportPath)) {
|
|
1221
|
-
console.error(`[Checkly Reporter] ERROR: JSON report not found at: ${jsonReportPath}`);
|
|
1222
|
-
console.error("[Checkly Reporter] Make sure to configure the json reporter before the checkly reporter:");
|
|
1223
|
-
console.error(
|
|
1224
|
-
" reporter: [\n ['json', { outputFile: 'test-results/playwright-test-report.json' }],\n ['@checkly/playwright-reporter']\n ]"
|
|
1225
|
-
);
|
|
1226
|
-
return;
|
|
1227
|
-
}
|
|
1228
|
-
this.log("Reading JSON report", { path: jsonReportPath });
|
|
1229
|
-
const reportContent = fs4.readFileSync(jsonReportPath, "utf-8");
|
|
1230
|
-
const report = JSON.parse(reportContent);
|
|
1231
|
-
this.log("JSON report parsed", {
|
|
1232
|
-
configVersion: report.config?.version,
|
|
1233
|
-
projectsCount: report.config?.projects?.length ?? 0,
|
|
1234
|
-
suitesCount: report.suites?.length ?? 0,
|
|
1235
|
-
rootDir: report.config?.rootDir
|
|
1236
|
-
});
|
|
1237
|
-
await this.extractDataFromTraces();
|
|
1238
|
-
this.injectDataIntoReport(report);
|
|
1239
|
-
this.log("Data injected into report", {
|
|
1240
|
-
projectsCountAfterReconstruction: report.config?.projects?.length ?? 0
|
|
1241
|
-
});
|
|
1242
|
-
fs4.writeFileSync(jsonReportPath, JSON.stringify(report, null, 2), "utf-8");
|
|
1243
|
-
this.log("Enriched report written to disk");
|
|
1244
|
-
this.log("Collecting assets", { testResultsDir: this.options.testResultsDir });
|
|
1245
|
-
const assets = await this.assetCollector.collectAssets(report);
|
|
1246
|
-
this.log("Assets collected", {
|
|
1247
|
-
count: assets.length,
|
|
1248
|
-
assets: assets.map((a) => ({ source: a.sourcePath, archive: a.archivePath, type: a.type }))
|
|
1249
|
-
});
|
|
1250
|
-
this.log("Creating ZIP archive", { outputPath: this.options.outputPath });
|
|
1251
|
-
const result = await this.zipper.createZip(jsonReportPath, assets);
|
|
1252
|
-
this.log("ZIP created", {
|
|
1253
|
-
zipPath: result.zipPath,
|
|
1254
|
-
zipSize: result.size,
|
|
1255
|
-
entriesCount: result.entries.length,
|
|
1256
|
-
entries: result.entries.map((e) => ({ name: e.name, start: e.start, end: e.end }))
|
|
1257
|
-
});
|
|
1258
|
-
if (this.testResults && this.testSession) {
|
|
1259
|
-
this.log("Uploading results", { testSessionId: this.testSession.testSessionId });
|
|
1260
|
-
await this.uploadResults(report, result.zipPath, result.entries);
|
|
1261
|
-
if (!this.options.dryRun) {
|
|
1262
|
-
try {
|
|
1263
|
-
fs4.unlinkSync(result.zipPath);
|
|
1264
|
-
} catch (cleanupError) {
|
|
1265
|
-
console.warn(`[Checkly Reporter] Warning: Could not delete ZIP file: ${cleanupError}`);
|
|
1919
|
+
await extractDataFromTraces(log);
|
|
1920
|
+
injectDataIntoReport(report);
|
|
1921
|
+
fs5.mkdirSync(resolvedOutputDir, { recursive: true });
|
|
1922
|
+
const tempReportPath = path4.join(resolvedOutputDir, `.checkly-report-${Date.now()}.json`);
|
|
1923
|
+
fs5.writeFileSync(tempReportPath, JSON.stringify(report, null, 2));
|
|
1924
|
+
const assets = await assetCollector.collectAssets(report);
|
|
1925
|
+
const zipResult = await zipper.createZip(tempReportPath, assets);
|
|
1926
|
+
log("\u{1F4E6} ZIP created", { path: zipResult.zipPath, size: `${(zipResult.size / 1024).toFixed(1)}KB` });
|
|
1927
|
+
if (api && testSession) {
|
|
1928
|
+
await uploadResults(log, report, zipResult.zipPath, zipResult.entries);
|
|
1929
|
+
if (!dryRun) {
|
|
1930
|
+
try {
|
|
1931
|
+
fs5.unlinkSync(zipResult.zipPath);
|
|
1932
|
+
} catch {
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
if (testSession.link) {
|
|
1936
|
+
addSummaryLine(`\u{1F517} Checkly Test Session: ${testSession.link}`);
|
|
1266
1937
|
}
|
|
1267
1938
|
}
|
|
1939
|
+
try {
|
|
1940
|
+
fs5.unlinkSync(tempReportPath);
|
|
1941
|
+
} catch {
|
|
1942
|
+
}
|
|
1943
|
+
} catch (err2) {
|
|
1944
|
+
console.error("[Checkly] Error in onEnd:", err2);
|
|
1268
1945
|
}
|
|
1269
|
-
if (this.testResults && this.testSession?.link) {
|
|
1270
|
-
this.printSummary(report, this.testSession);
|
|
1271
|
-
}
|
|
1272
|
-
} catch (error) {
|
|
1273
|
-
console.error("[Checkly Reporter] ERROR creating report:", error);
|
|
1274
1946
|
}
|
|
1947
|
+
};
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
// src/reporter.ts
|
|
1951
|
+
var import_node_fs = require("fs");
|
|
1952
|
+
var import_node_path = require("path");
|
|
1953
|
+
function getPackageVersion2() {
|
|
1954
|
+
try {
|
|
1955
|
+
const packageJson = JSON.parse((0, import_node_fs.readFileSync)((0, import_node_path.join)(__dirname, "..", "package.json"), "utf-8"));
|
|
1956
|
+
return packageJson.version;
|
|
1957
|
+
} catch {
|
|
1958
|
+
return "unknown";
|
|
1275
1959
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1960
|
+
}
|
|
1961
|
+
var pluralRules = new Intl.PluralRules("en-US");
|
|
1962
|
+
var projectForms = {
|
|
1963
|
+
zero: "Project",
|
|
1964
|
+
one: "Project",
|
|
1965
|
+
two: "Projects",
|
|
1966
|
+
few: "Projects",
|
|
1967
|
+
many: "Projects",
|
|
1968
|
+
other: "Projects"
|
|
1969
|
+
};
|
|
1970
|
+
var BaseReporter = class {
|
|
1971
|
+
config;
|
|
1972
|
+
suite;
|
|
1973
|
+
startTime;
|
|
1974
|
+
options;
|
|
1975
|
+
verbose;
|
|
1976
|
+
globalErrors = [];
|
|
1977
|
+
tests = /* @__PURE__ */ new Map();
|
|
1978
|
+
expectedCount = 0;
|
|
1979
|
+
unexpectedCount = 0;
|
|
1980
|
+
flakyCount = 0;
|
|
1981
|
+
skippedCount = 0;
|
|
1982
|
+
_report = null;
|
|
1983
|
+
extensions = [];
|
|
1984
|
+
summaryLines = [];
|
|
1985
|
+
// Reconstructed projects for merge-reports scenarios
|
|
1986
|
+
reconstructedProjects = /* @__PURE__ */ new Map();
|
|
1987
|
+
constructor(options = {}) {
|
|
1988
|
+
this.options = options;
|
|
1989
|
+
this.verbose = options.verbose ?? process.env.CHECKLY_REPORTER_VERBOSE === "true";
|
|
1284
1990
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
if (messages.length > 0) {
|
|
1298
|
-
this.consoleMessagesMap.set(key, messages);
|
|
1299
|
-
}
|
|
1300
|
-
const networkRequests = await reader.extractEvents('"type":"resource-snapshot"', toNetworkRequest);
|
|
1301
|
-
if (networkRequests.length > 0) {
|
|
1302
|
-
this.networkRequestsMap.set(key, networkRequests);
|
|
1303
|
-
}
|
|
1304
|
-
})().catch((error) => {
|
|
1305
|
-
console.error(`[Checkly Reporter] Failed to extract data from trace: ${error}`);
|
|
1306
|
-
})
|
|
1307
|
-
);
|
|
1991
|
+
use(extension) {
|
|
1992
|
+
this.extensions.push(extension);
|
|
1993
|
+
return this;
|
|
1994
|
+
}
|
|
1995
|
+
log(message, data) {
|
|
1996
|
+
if (!this.verbose) return;
|
|
1997
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[1].slice(0, 12);
|
|
1998
|
+
const prefix = `[Checkly ${timestamp}]`;
|
|
1999
|
+
if (data && Object.keys(data).length > 0) {
|
|
2000
|
+
console.log(`${prefix} ${message}`, data);
|
|
2001
|
+
} else {
|
|
2002
|
+
console.log(`${prefix} ${message}`);
|
|
1308
2003
|
}
|
|
1309
|
-
await Promise.all(extractionPromises);
|
|
1310
2004
|
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
*/
|
|
1315
|
-
injectDataIntoReport(report) {
|
|
1316
|
-
const processSuite = (suite) => {
|
|
1317
|
-
for (const spec of suite.specs) {
|
|
1318
|
-
for (const test of spec.tests) {
|
|
1319
|
-
for (const result of test.results) {
|
|
1320
|
-
const key = `${spec.id}:${result.retry}`;
|
|
1321
|
-
const steps = this.stepsMap.get(key);
|
|
1322
|
-
if (steps) {
|
|
1323
|
-
result.steps = steps;
|
|
1324
|
-
}
|
|
1325
|
-
const warnings = this.warningsMap.get(key);
|
|
1326
|
-
const consoleMessages = this.consoleMessagesMap.get(key);
|
|
1327
|
-
const networkRequests = this.networkRequestsMap.get(key);
|
|
1328
|
-
const hasData = warnings && warnings.length > 0 || consoleMessages && consoleMessages.length > 0 || networkRequests && networkRequests.length > 0;
|
|
1329
|
-
if (hasData) {
|
|
1330
|
-
result._checkly = {
|
|
1331
|
-
...warnings && warnings.length > 0 ? { warnings } : {},
|
|
1332
|
-
...consoleMessages && consoleMessages.length > 0 ? { console: consoleMessages } : {},
|
|
1333
|
-
...networkRequests && networkRequests.length > 0 ? { network: networkRequests } : {}
|
|
1334
|
-
};
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
|
-
}
|
|
1339
|
-
if (suite.suites) {
|
|
1340
|
-
for (const nestedSuite of suite.suites) {
|
|
1341
|
-
processSuite(nestedSuite);
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
2005
|
+
createExtensionLogger(extensionName) {
|
|
2006
|
+
return (message, data) => {
|
|
2007
|
+
this.log(`[${extensionName}] ${message}`, data);
|
|
1344
2008
|
};
|
|
1345
|
-
for (const suite of report.suites) {
|
|
1346
|
-
processSuite(suite);
|
|
1347
|
-
}
|
|
1348
|
-
this.reconstructProjectsFromTests(report);
|
|
1349
2009
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
const projectNames = /* @__PURE__ */ new Set();
|
|
1357
|
-
let testsWithMissingProjectId = 0;
|
|
1358
|
-
const configAny = report.config;
|
|
1359
|
-
const originalProjectsCount = configAny.projects?.length ?? 0;
|
|
1360
|
-
this.log("reconstructProjectsFromTests started", {
|
|
1361
|
-
originalProjectsCount,
|
|
1362
|
-
suitesCount: report.suites?.length ?? 0
|
|
1363
|
-
});
|
|
1364
|
-
const collectProjectNames = (suite) => {
|
|
1365
|
-
for (const spec of suite.specs) {
|
|
1366
|
-
for (const test of spec.tests) {
|
|
1367
|
-
const testAny = test;
|
|
1368
|
-
if (testAny.projectName) {
|
|
1369
|
-
projectNames.add(testAny.projectName);
|
|
1370
|
-
}
|
|
1371
|
-
if (testAny.projectName && !testAny.projectId) {
|
|
1372
|
-
testAny.projectId = testAny.projectName;
|
|
1373
|
-
testsWithMissingProjectId++;
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
2010
|
+
onBegin(config, suite) {
|
|
2011
|
+
const deprecated = ["outputFile", "testResultsDir", "outputPath"];
|
|
2012
|
+
const opts = this.options;
|
|
2013
|
+
for (const key of deprecated) {
|
|
2014
|
+
if (key in opts && opts[key] !== void 0) {
|
|
2015
|
+
throw new Error(`[Checkly] "${key}" option is no longer supported. Use outputDir instead.`);
|
|
1376
2016
|
}
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
2017
|
+
}
|
|
2018
|
+
this.config = config;
|
|
2019
|
+
this.suite = suite;
|
|
2020
|
+
this.startTime = /* @__PURE__ */ new Date();
|
|
2021
|
+
this.tests.clear();
|
|
2022
|
+
this.globalErrors = [];
|
|
2023
|
+
this.expectedCount = 0;
|
|
2024
|
+
this.unexpectedCount = 0;
|
|
2025
|
+
this.flakyCount = 0;
|
|
2026
|
+
this.skippedCount = 0;
|
|
2027
|
+
this._report = null;
|
|
2028
|
+
this.reconstructedProjects.clear();
|
|
2029
|
+
this.reconstructProjectsIfNeeded();
|
|
2030
|
+
const testCount = this.countTests(suite);
|
|
2031
|
+
const projectNames = config.projects.length > 0 ? config.projects.map((p) => p.name).join(", ") : Array.from(this.reconstructedProjects.keys()).join(", ") || "default";
|
|
2032
|
+
this.log(`\u{1F3AC} Starting test run`, { tests: testCount, projects: projectNames, workers: config.workers });
|
|
2033
|
+
for (const ext of this.extensions) {
|
|
2034
|
+
ext.onBegin?.({ config, suite, log: this.createExtensionLogger(ext.name) });
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
onTestBegin(test, result) {
|
|
2038
|
+
for (const ext of this.extensions) {
|
|
2039
|
+
ext.onTestBegin?.({ test, result, log: this.createExtensionLogger(ext.name) });
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
onStepBegin(test, result, step) {
|
|
2043
|
+
for (const ext of this.extensions) {
|
|
2044
|
+
ext.onStepBegin?.({ test, result, step, log: this.createExtensionLogger(ext.name) });
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
onStepEnd(test, result, step) {
|
|
2048
|
+
for (const ext of this.extensions) {
|
|
2049
|
+
ext.onStepEnd?.({ test, result, step, log: this.createExtensionLogger(ext.name) });
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
onTestEnd(test, result) {
|
|
2053
|
+
const testId = test.id;
|
|
2054
|
+
let testData = this.tests.get(testId);
|
|
2055
|
+
if (!testData) {
|
|
2056
|
+
testData = { testCase: test, results: [] };
|
|
2057
|
+
this.tests.set(testId, testData);
|
|
2058
|
+
}
|
|
2059
|
+
testData.results.push(result);
|
|
2060
|
+
for (const ext of this.extensions) {
|
|
2061
|
+
ext.onTestEnd?.({ test, result, log: this.createExtensionLogger(ext.name) });
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
onStdOut(chunk, test, result) {
|
|
2065
|
+
for (const ext of this.extensions) {
|
|
2066
|
+
ext.onStdOut?.({ chunk, test, result, log: this.createExtensionLogger(ext.name) });
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
onStdErr(chunk, test, result) {
|
|
2070
|
+
for (const ext of this.extensions) {
|
|
2071
|
+
ext.onStdErr?.({ chunk, test, result, log: this.createExtensionLogger(ext.name) });
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
onError(error) {
|
|
2075
|
+
this.globalErrors.push(error);
|
|
2076
|
+
this.log(`\u{1F4A5} Global error`, { message: error.message?.slice(0, 100) });
|
|
2077
|
+
for (const ext of this.extensions) {
|
|
2078
|
+
ext.onError?.({ error, log: this.createExtensionLogger(ext.name) });
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
async onEnd(result) {
|
|
2082
|
+
for (const testData of this.tests.values()) {
|
|
2083
|
+
switch (testData.testCase.outcome()) {
|
|
2084
|
+
case "expected":
|
|
2085
|
+
this.expectedCount++;
|
|
2086
|
+
break;
|
|
2087
|
+
case "unexpected":
|
|
2088
|
+
this.unexpectedCount++;
|
|
2089
|
+
break;
|
|
2090
|
+
case "flaky":
|
|
2091
|
+
this.flakyCount++;
|
|
2092
|
+
break;
|
|
2093
|
+
case "skipped":
|
|
2094
|
+
this.skippedCount++;
|
|
2095
|
+
break;
|
|
1381
2096
|
}
|
|
1382
|
-
};
|
|
1383
|
-
for (const suite of report.suites) {
|
|
1384
|
-
collectProjectNames(suite);
|
|
1385
2097
|
}
|
|
1386
|
-
this.
|
|
1387
|
-
|
|
1388
|
-
|
|
2098
|
+
this._report = this.buildReport(result);
|
|
2099
|
+
this.log(`\u{1F3C1} Test run finished`, {
|
|
2100
|
+
status: result.status,
|
|
2101
|
+
duration: `${result.duration}ms`,
|
|
2102
|
+
passed: this.expectedCount,
|
|
2103
|
+
failed: this.unexpectedCount,
|
|
2104
|
+
flaky: this.flakyCount,
|
|
2105
|
+
skipped: this.skippedCount
|
|
1389
2106
|
});
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
2107
|
+
const outputDir = this.options.outputDir;
|
|
2108
|
+
if (outputDir) {
|
|
2109
|
+
const fs6 = await import("fs");
|
|
2110
|
+
fs6.mkdirSync(outputDir, { recursive: true });
|
|
2111
|
+
const outputPath = `${outputDir}/checkly-report.json`;
|
|
2112
|
+
fs6.writeFileSync(outputPath, JSON.stringify(this._report, null, 2));
|
|
2113
|
+
this.log(`\u{1F4C4} Report saved`, { path: outputPath });
|
|
2114
|
+
}
|
|
2115
|
+
for (const ext of this.extensions) {
|
|
2116
|
+
await ext.onEnd?.({
|
|
2117
|
+
result,
|
|
2118
|
+
report: this._report,
|
|
2119
|
+
log: this.createExtensionLogger(ext.name),
|
|
2120
|
+
addSummaryLine: (line) => this.summaryLines.push(line)
|
|
1402
2121
|
});
|
|
1403
2122
|
}
|
|
2123
|
+
this.printSummary();
|
|
1404
2124
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
2125
|
+
async onExit() {
|
|
2126
|
+
this.log(`\u{1F44B} Reporter exiting`);
|
|
2127
|
+
for (const ext of this.extensions) {
|
|
2128
|
+
await ext.onExit?.({ log: this.createExtensionLogger(ext.name) });
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
printsToStdio() {
|
|
2132
|
+
return false;
|
|
2133
|
+
}
|
|
2134
|
+
getReport() {
|
|
2135
|
+
if (this._report) return this._report;
|
|
2136
|
+
return this.buildReport({
|
|
2137
|
+
status: "passed",
|
|
2138
|
+
startTime: this.startTime,
|
|
2139
|
+
duration: Date.now() - this.startTime.getTime()
|
|
1414
2140
|
});
|
|
1415
|
-
|
|
1416
|
-
|
|
2141
|
+
}
|
|
2142
|
+
buildReport(fullResult) {
|
|
2143
|
+
return {
|
|
2144
|
+
config: this.serializeConfig(),
|
|
2145
|
+
suites: this.serializeSuites(),
|
|
2146
|
+
errors: this.globalErrors.map((e) => this.serializeError(e, true)),
|
|
2147
|
+
stats: {
|
|
2148
|
+
startTime: this.startTime.toISOString(),
|
|
2149
|
+
duration: fullResult.duration,
|
|
2150
|
+
expected: this.expectedCount,
|
|
2151
|
+
unexpected: this.unexpectedCount,
|
|
2152
|
+
flaky: this.flakyCount,
|
|
2153
|
+
skipped: this.skippedCount
|
|
2154
|
+
}
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
reconstructProjectsIfNeeded() {
|
|
2158
|
+
if (this.config.projects.length > 0) {
|
|
1417
2159
|
return;
|
|
1418
2160
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
const
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
2161
|
+
this.log("\u{1F504} Detected merge-reports scenario (empty config.projects), reconstructing projects");
|
|
2162
|
+
for (const projectSuite of this.suite.suites) {
|
|
2163
|
+
const project = projectSuite.project();
|
|
2164
|
+
if (project) {
|
|
2165
|
+
const name = project.name || "default";
|
|
2166
|
+
if (!this.reconstructedProjects.has(name)) {
|
|
2167
|
+
this.reconstructedProjects.set(name, {
|
|
2168
|
+
id: name,
|
|
2169
|
+
name,
|
|
2170
|
+
testDir: project.testDir,
|
|
2171
|
+
outputDir: project.outputDir,
|
|
2172
|
+
timeout: project.timeout,
|
|
2173
|
+
retries: project.retries,
|
|
2174
|
+
repeatEach: project.repeatEach,
|
|
2175
|
+
metadata: project.metadata ?? {},
|
|
2176
|
+
testMatch: Array.isArray(project.testMatch) ? project.testMatch.map(String) : [String(project.testMatch)],
|
|
2177
|
+
testIgnore: Array.isArray(project.testIgnore) ? project.testIgnore.map(String) : [String(project.testIgnore)]
|
|
2178
|
+
});
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
if (this.reconstructedProjects.size === 0) {
|
|
2183
|
+
this.collectProjectsFromTests(this.suite);
|
|
2184
|
+
}
|
|
2185
|
+
this.log("\u{1F504} Reconstructed projects", {
|
|
2186
|
+
count: this.reconstructedProjects.size,
|
|
2187
|
+
names: Array.from(this.reconstructedProjects.keys())
|
|
2188
|
+
});
|
|
2189
|
+
}
|
|
2190
|
+
collectProjectsFromTests(suite) {
|
|
2191
|
+
for (const test of suite.allTests()) {
|
|
2192
|
+
const project = test.parent.project();
|
|
2193
|
+
const projectName = project?.name || "default";
|
|
2194
|
+
if (!this.reconstructedProjects.has(projectName)) {
|
|
2195
|
+
if (project) {
|
|
2196
|
+
this.reconstructedProjects.set(projectName, {
|
|
2197
|
+
id: projectName,
|
|
2198
|
+
name: projectName,
|
|
2199
|
+
testDir: project.testDir,
|
|
2200
|
+
outputDir: project.outputDir,
|
|
2201
|
+
timeout: project.timeout,
|
|
2202
|
+
retries: project.retries,
|
|
2203
|
+
repeatEach: project.repeatEach,
|
|
2204
|
+
metadata: project.metadata ?? {},
|
|
2205
|
+
testMatch: Array.isArray(project.testMatch) ? project.testMatch.map(String) : [String(project.testMatch)],
|
|
2206
|
+
testIgnore: Array.isArray(project.testIgnore) ? project.testIgnore.map(String) : [String(project.testIgnore)]
|
|
2207
|
+
});
|
|
1457
2208
|
} else {
|
|
1458
|
-
this.
|
|
2209
|
+
this.reconstructedProjects.set(projectName, {
|
|
2210
|
+
id: projectName,
|
|
2211
|
+
name: projectName,
|
|
2212
|
+
testDir: "",
|
|
2213
|
+
outputDir: "",
|
|
2214
|
+
timeout: 0,
|
|
2215
|
+
retries: 0,
|
|
2216
|
+
repeatEach: 1,
|
|
2217
|
+
metadata: {},
|
|
2218
|
+
testMatch: [],
|
|
2219
|
+
testIgnore: []
|
|
2220
|
+
});
|
|
1459
2221
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
serializeConfig() {
|
|
2226
|
+
const c = this.config;
|
|
2227
|
+
const projects = c.projects.length > 0 ? c.projects.map((p) => this.serializeProject(p)) : Array.from(this.reconstructedProjects.values());
|
|
2228
|
+
return {
|
|
2229
|
+
rootDir: c.rootDir,
|
|
2230
|
+
configFile: c.configFile ?? void 0,
|
|
2231
|
+
version: c.version,
|
|
2232
|
+
workers: c.workers,
|
|
2233
|
+
fullyParallel: c.fullyParallel,
|
|
2234
|
+
forbidOnly: c.forbidOnly,
|
|
2235
|
+
globalTimeout: c.globalTimeout,
|
|
2236
|
+
maxFailures: c.maxFailures,
|
|
2237
|
+
metadata: c.metadata ?? {},
|
|
2238
|
+
projects,
|
|
2239
|
+
shard: c.shard ?? null,
|
|
2240
|
+
tags: c.tags ?? [],
|
|
2241
|
+
updateSourceMethod: c.updateSourceMethod,
|
|
2242
|
+
preserveOutput: c.preserveOutput,
|
|
2243
|
+
quiet: c.quiet,
|
|
2244
|
+
reportSlowTests: c.reportSlowTests ?? null,
|
|
2245
|
+
webServer: c.webServer ?? null,
|
|
2246
|
+
globalSetup: c.globalSetup ?? null,
|
|
2247
|
+
globalTeardown: c.globalTeardown ?? null,
|
|
2248
|
+
grep: c.grep,
|
|
2249
|
+
grepInvert: c.grepInvert,
|
|
2250
|
+
reporter: c.reporter,
|
|
2251
|
+
updateSnapshots: c.updateSnapshots
|
|
2252
|
+
};
|
|
2253
|
+
}
|
|
2254
|
+
serializeProject(p) {
|
|
2255
|
+
return {
|
|
2256
|
+
id: p.name,
|
|
2257
|
+
name: p.name,
|
|
2258
|
+
testDir: p.testDir,
|
|
2259
|
+
outputDir: p.outputDir,
|
|
2260
|
+
timeout: p.timeout,
|
|
2261
|
+
retries: p.retries,
|
|
2262
|
+
repeatEach: p.repeatEach,
|
|
2263
|
+
metadata: p.metadata ?? {},
|
|
2264
|
+
testMatch: Array.isArray(p.testMatch) ? p.testMatch.map(String) : [String(p.testMatch)],
|
|
2265
|
+
testIgnore: Array.isArray(p.testIgnore) ? p.testIgnore.map(String) : [String(p.testIgnore)]
|
|
2266
|
+
};
|
|
2267
|
+
}
|
|
2268
|
+
serializeSuites() {
|
|
2269
|
+
const fileSuites = /* @__PURE__ */ new Map();
|
|
2270
|
+
for (const projectSuite of this.suite.suites) {
|
|
2271
|
+
for (const fileSuite of projectSuite.suites) {
|
|
2272
|
+
const file = fileSuite.location?.file;
|
|
2273
|
+
if (!file) continue;
|
|
2274
|
+
const fileName = this.getFileName(file);
|
|
2275
|
+
const serialized = this.serializeSuite(fileSuite, fileName);
|
|
2276
|
+
if (!serialized) continue;
|
|
2277
|
+
const existing = fileSuites.get(file);
|
|
2278
|
+
if (existing) {
|
|
2279
|
+
this.mergeSuites(existing, serialized);
|
|
2280
|
+
} else {
|
|
2281
|
+
fileSuites.set(file, serialized);
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
return Array.from(fileSuites.values());
|
|
2286
|
+
}
|
|
2287
|
+
serializeSuite(suite, fileName) {
|
|
2288
|
+
const allTests = suite.allTests();
|
|
2289
|
+
if (allTests.length === 0) return null;
|
|
2290
|
+
const childSuites = [];
|
|
2291
|
+
for (const child of suite.suites) {
|
|
2292
|
+
const serialized = this.serializeSuite(child, fileName);
|
|
2293
|
+
if (serialized) childSuites.push(serialized);
|
|
2294
|
+
}
|
|
2295
|
+
const specs = [];
|
|
2296
|
+
for (const test of suite.tests) {
|
|
2297
|
+
const testData = this.tests.get(test.id);
|
|
2298
|
+
if (testData) {
|
|
2299
|
+
specs.push(this.serializeSpec(testData));
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
return {
|
|
2303
|
+
title: suite.title || fileName,
|
|
2304
|
+
file: fileName,
|
|
2305
|
+
line: suite.location?.line ?? 0,
|
|
2306
|
+
column: suite.location?.column ?? 0,
|
|
2307
|
+
specs,
|
|
2308
|
+
suites: childSuites.length ? childSuites : void 0
|
|
2309
|
+
};
|
|
2310
|
+
}
|
|
2311
|
+
mergeSuites(to, from) {
|
|
2312
|
+
for (const fromSuite of from.suites || []) {
|
|
2313
|
+
const toSuite = to.suites?.find(
|
|
2314
|
+
(s) => s.title === fromSuite.title && s.line === fromSuite.line && s.column === fromSuite.column
|
|
2315
|
+
);
|
|
2316
|
+
if (toSuite) {
|
|
2317
|
+
this.mergeSuites(toSuite, fromSuite);
|
|
1480
2318
|
} else {
|
|
1481
|
-
|
|
2319
|
+
to.suites = to.suites ?? [];
|
|
2320
|
+
to.suites.push(fromSuite);
|
|
1482
2321
|
}
|
|
1483
|
-
} catch (error) {
|
|
1484
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1485
|
-
console.error("[Checkly Reporter] Failed to upload results:", errorMessage);
|
|
1486
|
-
this.log("uploadResults failed", { error: errorMessage });
|
|
1487
2322
|
}
|
|
2323
|
+
to.specs.push(...from.specs);
|
|
1488
2324
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
2325
|
+
serializeSpec(data) {
|
|
2326
|
+
const { testCase } = data;
|
|
2327
|
+
const outcome = testCase.outcome();
|
|
2328
|
+
return {
|
|
2329
|
+
id: testCase.id,
|
|
2330
|
+
title: testCase.title,
|
|
2331
|
+
file: this.getFileName(testCase.location.file),
|
|
2332
|
+
line: testCase.location.line,
|
|
2333
|
+
column: testCase.location.column,
|
|
2334
|
+
tags: this.extractTags(testCase),
|
|
2335
|
+
ok: outcome === "expected" || outcome === "flaky" || outcome === "skipped",
|
|
2336
|
+
tests: [this.serializeTest(data)]
|
|
2337
|
+
};
|
|
2338
|
+
}
|
|
2339
|
+
extractTags(testCase) {
|
|
2340
|
+
const runtimeTags = testCase.tags;
|
|
2341
|
+
if (runtimeTags && runtimeTags.length > 0) {
|
|
2342
|
+
return runtimeTags.map((t) => t.replace(/^@/, ""));
|
|
2343
|
+
}
|
|
2344
|
+
const titleTags = testCase.title.match(/@[\w-]+/g);
|
|
2345
|
+
return titleTags?.map((t) => t.replace(/^@/, "")) ?? [];
|
|
2346
|
+
}
|
|
2347
|
+
serializeTest(data) {
|
|
2348
|
+
const { testCase, results } = data;
|
|
2349
|
+
const projectName = this.getProjectName(testCase);
|
|
2350
|
+
return {
|
|
2351
|
+
projectId: projectName,
|
|
2352
|
+
projectName,
|
|
2353
|
+
timeout: testCase.timeout,
|
|
2354
|
+
expectedStatus: testCase.expectedStatus,
|
|
2355
|
+
annotations: this.serializeAnnotations(testCase.annotations),
|
|
2356
|
+
results: results.map((r) => this.serializeTestResult(r)),
|
|
2357
|
+
status: this.mapOutcome(testCase.outcome())
|
|
2358
|
+
};
|
|
2359
|
+
}
|
|
2360
|
+
getProjectName(testCase) {
|
|
2361
|
+
const project = testCase.parent.project();
|
|
2362
|
+
if (project && typeof project.name === "string") {
|
|
2363
|
+
return project.name;
|
|
2364
|
+
}
|
|
2365
|
+
let current = testCase.parent;
|
|
2366
|
+
while (current) {
|
|
2367
|
+
const suiteProject = current.project();
|
|
2368
|
+
if (suiteProject && typeof suiteProject.name === "string") {
|
|
2369
|
+
return suiteProject.name;
|
|
2370
|
+
}
|
|
2371
|
+
current = current.parent;
|
|
2372
|
+
}
|
|
2373
|
+
return "default";
|
|
2374
|
+
}
|
|
2375
|
+
serializeTestResult(r) {
|
|
2376
|
+
return {
|
|
2377
|
+
workerIndex: r.workerIndex,
|
|
2378
|
+
parallelIndex: r.parallelIndex ?? 0,
|
|
2379
|
+
status: r.status,
|
|
2380
|
+
duration: r.duration,
|
|
2381
|
+
startTime: r.startTime.toISOString(),
|
|
2382
|
+
retry: r.retry,
|
|
2383
|
+
errors: r.errors.map((e) => this.serializeError(e, true)),
|
|
2384
|
+
error: r.error ? this.serializeError(r.error, false) : void 0,
|
|
2385
|
+
errorLocation: r.error?.location,
|
|
2386
|
+
stdout: r.stdout.map(
|
|
2387
|
+
(s) => typeof s === "string" ? { text: s } : Buffer.isBuffer(s) ? { buffer: s.toString("base64") } : s
|
|
2388
|
+
),
|
|
2389
|
+
stderr: r.stderr.map(
|
|
2390
|
+
(s) => typeof s === "string" ? { text: s } : Buffer.isBuffer(s) ? { buffer: s.toString("base64") } : s
|
|
2391
|
+
),
|
|
2392
|
+
attachments: r.attachments.map((a) => ({
|
|
2393
|
+
name: a.name,
|
|
2394
|
+
contentType: a.contentType,
|
|
2395
|
+
path: a.path,
|
|
2396
|
+
body: a.body ? a.body.toString("base64") : void 0
|
|
2397
|
+
})),
|
|
2398
|
+
steps: r.steps.map((s) => this.serializeStep(s)),
|
|
2399
|
+
annotations: this.serializeAnnotations(
|
|
2400
|
+
r.annotations ?? []
|
|
2401
|
+
)
|
|
2402
|
+
};
|
|
2403
|
+
}
|
|
2404
|
+
serializeStep(step) {
|
|
2405
|
+
return {
|
|
2406
|
+
title: step.title,
|
|
2407
|
+
duration: step.duration,
|
|
2408
|
+
error: step.error ? this.serializeError(step.error, false) : void 0,
|
|
2409
|
+
steps: step.steps?.map((s) => this.serializeStep(s))
|
|
2410
|
+
};
|
|
2411
|
+
}
|
|
2412
|
+
serializeError(error, includeContext) {
|
|
2413
|
+
if (error.value !== void 0) {
|
|
2414
|
+
return { message: error.value, value: error.value };
|
|
2415
|
+
}
|
|
2416
|
+
let msg = error.message ?? "Unknown error";
|
|
2417
|
+
if (includeContext && !/^(\w+Error|Error):/.test(msg)) {
|
|
2418
|
+
msg = "Error: " + msg;
|
|
2419
|
+
}
|
|
2420
|
+
if (includeContext) {
|
|
2421
|
+
if (error.snippet) msg += "\n\n" + error.snippet;
|
|
2422
|
+
if (error.stack) {
|
|
2423
|
+
const frames = error.stack.split("\n").filter((l) => l.trim().startsWith("at "));
|
|
2424
|
+
if (frames.length) msg += "\n" + frames.join("\n");
|
|
2425
|
+
} else if (error.location) {
|
|
2426
|
+
msg += `
|
|
2427
|
+
at ${error.location.file}:${error.location.line}:${error.location.column}`;
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
return {
|
|
2431
|
+
message: msg,
|
|
2432
|
+
location: error.location,
|
|
2433
|
+
stack: error.stack,
|
|
2434
|
+
snippet: error.snippet
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
serializeAnnotations(annotations) {
|
|
2438
|
+
return annotations.map((a) => ({ type: a.type, description: a.description, location: a.location }));
|
|
2439
|
+
}
|
|
2440
|
+
countTests(suite) {
|
|
2441
|
+
let count = suite.tests?.length ?? 0;
|
|
2442
|
+
for (const child of suite.suites ?? []) {
|
|
2443
|
+
count += this.countTests(child);
|
|
2444
|
+
}
|
|
2445
|
+
return count;
|
|
2446
|
+
}
|
|
2447
|
+
getFileName(filePath) {
|
|
2448
|
+
return filePath.split("/").pop() ?? filePath;
|
|
2449
|
+
}
|
|
2450
|
+
mapOutcome(outcome) {
|
|
2451
|
+
if (outcome === "expected" || outcome === "unexpected" || outcome === "flaky" || outcome === "skipped") {
|
|
2452
|
+
return outcome;
|
|
2453
|
+
}
|
|
2454
|
+
return "unexpected";
|
|
2455
|
+
}
|
|
2456
|
+
printSummary() {
|
|
2457
|
+
const pkgVersion = getPackageVersion2();
|
|
2458
|
+
const playwrightVersion = this.config.version;
|
|
2459
|
+
const projectNames = this.config.projects.length > 0 ? this.config.projects.map((p) => p.name).join(", ") : Array.from(this.reconstructedProjects.keys()).join(", ") || "default";
|
|
2460
|
+
const projectCount = this.config.projects.length > 0 ? this.config.projects.length : this.reconstructedProjects.size || 1;
|
|
2461
|
+
const rule = pluralRules.select(projectCount);
|
|
2462
|
+
console.log("\n======================================================\n");
|
|
2463
|
+
console.log(`\u{1F99D} Checkly reporter: ${pkgVersion}`);
|
|
2464
|
+
console.log(`\u{1F3AD} Playwright: ${playwrightVersion}`);
|
|
2465
|
+
console.log(`\u{1F4D4} ${projectForms[rule]}: ${projectNames}`);
|
|
2466
|
+
for (const line of this.summaryLines) {
|
|
2467
|
+
console.log(line);
|
|
2468
|
+
}
|
|
2469
|
+
console.log("\n======================================================");
|
|
1494
2470
|
}
|
|
1495
2471
|
};
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
2472
|
+
|
|
2473
|
+
// src/index.ts
|
|
2474
|
+
var ChecklyReporter = class extends BaseReporter {
|
|
2475
|
+
constructor(options = {}) {
|
|
2476
|
+
super(options);
|
|
2477
|
+
this.use(checklyUpload(options));
|
|
2478
|
+
}
|
|
1501
2479
|
};
|
|
2480
|
+
var index_default = ChecklyReporter;
|
|
2481
|
+
function createChecklyReporter(options = {}) {
|
|
2482
|
+
return ["@checkly/playwright-reporter", options];
|
|
2483
|
+
}
|
|
2484
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2485
|
+
0 && (module.exports = {
|
|
2486
|
+
MissingCredentialsError,
|
|
2487
|
+
createChecklyReporter
|
|
2488
|
+
});
|