@remix-run/test 0.2.0 → 0.3.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/README.md +39 -33
- package/dist/app/client/entry.js +4 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +68 -23
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/config.d.ts +35 -21
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +73 -33
- package/dist/lib/fake-timers.d.ts +7 -0
- package/dist/lib/fake-timers.d.ts.map +1 -1
- package/dist/lib/fake-timers.js +27 -8
- package/dist/lib/import-module.d.ts.map +1 -1
- package/dist/lib/import-module.js +11 -2
- package/dist/lib/reporters/dot.d.ts.map +1 -1
- package/dist/lib/reporters/dot.js +10 -0
- package/dist/lib/reporters/files.d.ts.map +1 -1
- package/dist/lib/reporters/files.js +10 -0
- package/dist/lib/reporters/spec.d.ts.map +1 -1
- package/dist/lib/reporters/spec.js +10 -0
- package/dist/lib/reporters/tap.d.ts.map +1 -1
- package/dist/lib/reporters/tap.js +10 -0
- package/dist/lib/runner-browser.d.ts.map +1 -1
- package/dist/lib/runner-browser.js +6 -0
- package/dist/lib/runner.d.ts +18 -1
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +187 -38
- package/dist/lib/worker-e2e-file.d.ts +11 -0
- package/dist/lib/worker-e2e-file.d.ts.map +1 -0
- package/dist/lib/worker-e2e-file.js +69 -0
- package/dist/lib/worker-e2e.js +11 -47
- package/dist/lib/worker-process.d.ts +2 -0
- package/dist/lib/worker-process.d.ts.map +1 -0
- package/dist/lib/worker-process.js +55 -0
- package/dist/lib/worker-results.d.ts +3 -0
- package/dist/lib/worker-results.d.ts.map +1 -0
- package/dist/lib/worker-results.js +20 -0
- package/dist/lib/worker-server.d.ts +10 -0
- package/dist/lib/worker-server.d.ts.map +1 -0
- package/dist/lib/worker-server.js +113 -0
- package/dist/lib/worker.js +6 -55
- package/package.json +4 -4
- package/src/app/client/entry.ts +4 -0
- package/src/cli.ts +91 -28
- package/src/index.ts +1 -1
- package/src/lib/config.ts +124 -58
- package/src/lib/fake-timers.ts +33 -8
- package/src/lib/import-module.ts +12 -2
- package/src/lib/reporters/dot.ts +9 -0
- package/src/lib/reporters/files.ts +9 -0
- package/src/lib/reporters/spec.ts +9 -0
- package/src/lib/reporters/tap.ts +9 -0
- package/src/lib/runner-browser.ts +6 -0
- package/src/lib/runner.ts +253 -50
- package/src/lib/worker-e2e-file.ts +98 -0
- package/src/lib/worker-e2e.ts +14 -51
- package/src/lib/worker-process.ts +69 -0
- package/src/lib/worker-results.ts +22 -0
- package/src/lib/worker-server.ts +123 -0
- package/src/lib/worker.ts +7 -47
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
export interface FakeTimers {
|
|
2
2
|
advance(ms: number): void;
|
|
3
|
+
/**
|
|
4
|
+
* Like `advance`, but yields to microtasks between each timer firing so
|
|
5
|
+
* Promise continuations (and any timers they schedule) can settle before
|
|
6
|
+
* the next firing is processed. Use this when a callback awaits work that
|
|
7
|
+
* itself depends on the fake clock.
|
|
8
|
+
*/
|
|
9
|
+
advanceAsync(ms: number): Promise<void>;
|
|
3
10
|
restore(): void;
|
|
4
11
|
}
|
|
5
12
|
export declare function createFakeTimers(): FakeTimers;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake-timers.d.ts","sourceRoot":"","sources":["../../src/lib/fake-timers.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,wBAAgB,gBAAgB,IAAI,UAAU,
|
|
1
|
+
{"version":3,"file":"fake-timers.d.ts","sourceRoot":"","sources":["../../src/lib/fake-timers.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvC,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,wBAAgB,gBAAgB,IAAI,UAAU,CA0E7C"}
|
package/dist/lib/fake-timers.js
CHANGED
|
@@ -15,21 +15,40 @@ export function createFakeTimers() {
|
|
|
15
15
|
let clearTimeoutMock = mock.method(globalThis, 'clearTimeout', cancel);
|
|
16
16
|
let setIntervalMock = mock.method(globalThis, 'setInterval', ((fn, delay = 0) => schedule(fn, delay, Math.max(0, delay))));
|
|
17
17
|
let clearIntervalMock = mock.method(globalThis, 'clearInterval', cancel);
|
|
18
|
+
function takeNext(targetTime) {
|
|
19
|
+
let next = pending.filter((t) => t.time <= targetTime).sort((a, b) => a.time - b.time)[0];
|
|
20
|
+
if (!next)
|
|
21
|
+
return null;
|
|
22
|
+
currentTime = next.time;
|
|
23
|
+
pending = pending.filter((t) => t.id !== next.id);
|
|
24
|
+
// Requeue intervals before running the callback so that calling
|
|
25
|
+
// clearInterval(id) from inside the callback can cancel the next firing.
|
|
26
|
+
if (next.repeatMs !== undefined) {
|
|
27
|
+
pending.push({ ...next, time: next.time + Math.max(1, next.repeatMs) });
|
|
28
|
+
}
|
|
29
|
+
return next;
|
|
30
|
+
}
|
|
18
31
|
return {
|
|
19
32
|
advance(ms) {
|
|
20
33
|
let targetTime = currentTime + ms;
|
|
21
34
|
while (true) {
|
|
22
|
-
let next =
|
|
35
|
+
let next = takeNext(targetTime);
|
|
36
|
+
if (!next)
|
|
37
|
+
break;
|
|
38
|
+
next.fn();
|
|
39
|
+
}
|
|
40
|
+
currentTime = targetTime;
|
|
41
|
+
},
|
|
42
|
+
async advanceAsync(ms) {
|
|
43
|
+
let targetTime = currentTime + ms;
|
|
44
|
+
while (true) {
|
|
45
|
+
let next = takeNext(targetTime);
|
|
23
46
|
if (!next)
|
|
24
47
|
break;
|
|
25
|
-
currentTime = next.time;
|
|
26
|
-
pending = pending.filter((t) => t.id !== next.id);
|
|
27
|
-
// Requeue intervals before running the callback so that calling
|
|
28
|
-
// clearInterval(id) from inside the callback can cancel the next firing.
|
|
29
|
-
if (next.repeatMs !== undefined) {
|
|
30
|
-
pending.push({ ...next, time: next.time + Math.max(1, next.repeatMs) });
|
|
31
|
-
}
|
|
32
48
|
next.fn();
|
|
49
|
+
// Drain microtasks so Promise continuations (and any timers they
|
|
50
|
+
// schedule) can settle before we look for the next firing.
|
|
51
|
+
await Promise.resolve();
|
|
33
52
|
}
|
|
34
53
|
currentTime = targetTime;
|
|
35
54
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-module.d.ts","sourceRoot":"","sources":["../../src/lib/import-module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import-module.d.ts","sourceRoot":"","sources":["../../src/lib/import-module.ts"],"names":[],"mappings":"AAoBA,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAkBpF"}
|
|
@@ -6,6 +6,8 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
6
6
|
}
|
|
7
7
|
return path;
|
|
8
8
|
};
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { pathToFileURL } from 'node:url';
|
|
9
11
|
import { tsImport } from 'tsx/esm/api';
|
|
10
12
|
import { IS_BUN } from "./runtime.js";
|
|
11
13
|
function hasImportMetaResolve(meta) {
|
|
@@ -19,11 +21,18 @@ function hasImportMetaResolve(meta) {
|
|
|
19
21
|
* @returns The imported module namespace.
|
|
20
22
|
*/
|
|
21
23
|
export async function importModule(specifier, meta) {
|
|
24
|
+
// Absolute Windows paths (`C:\foo\bar.ts`) aren't valid ESM specifiers — only
|
|
25
|
+
// `file:///C:/foo/bar.ts` URLs, relative specifiers, or POSIX absolute paths
|
|
26
|
+
// are. Convert any absolute filesystem path to its `file:` URL so loaders like
|
|
27
|
+
// `tsImport` and `import()` accept it on every platform. POSIX absolute paths
|
|
28
|
+
// happen to work as specifiers without conversion, but going through
|
|
29
|
+
// `pathToFileURL` is safe and platform-agnostic.
|
|
30
|
+
let resolvedSpecifier = path.isAbsolute(specifier) ? pathToFileURL(specifier).href : specifier;
|
|
22
31
|
if (IS_BUN) {
|
|
23
32
|
if (!hasImportMetaResolve(meta)) {
|
|
24
33
|
throw new Error('importModule() requires import.meta.resolve() in Bun');
|
|
25
34
|
}
|
|
26
|
-
return import(__rewriteRelativeImportExtension(meta.resolve(
|
|
35
|
+
return import(__rewriteRelativeImportExtension(meta.resolve(resolvedSpecifier, meta.url)));
|
|
27
36
|
}
|
|
28
|
-
return tsImport(
|
|
37
|
+
return tsImport(resolvedSpecifier, meta.url);
|
|
29
38
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dot.d.ts","sourceRoot":"","sources":["../../../src/lib/reporters/dot.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAc,WAAW,EAAE,MAAM,cAAc,CAAA;AAEnE,qBAAa,WAAY,YAAW,QAAQ;;
|
|
1
|
+
{"version":3,"file":"dot.d.ts","sourceRoot":"","sources":["../../../src/lib/reporters/dot.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAc,WAAW,EAAE,MAAM,cAAc,CAAA;AAEnE,qBAAa,WAAY,YAAW,QAAQ;;IAM1C,cAAc,CAAC,MAAM,EAAE,MAAM,QAAI;IAEjC,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,MAAM,QAmB3C;IAED,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QA+B3C;CACF"}
|
|
@@ -3,8 +3,16 @@ import { normalizeLine } from "../normalize.js";
|
|
|
3
3
|
export class DotReporter {
|
|
4
4
|
#failures = [];
|
|
5
5
|
#dotCount = 0;
|
|
6
|
+
#files = new Set();
|
|
7
|
+
#suites = new Set();
|
|
6
8
|
onSectionStart(_label) { }
|
|
7
9
|
onResult(results, _env) {
|
|
10
|
+
for (let test of results.tests) {
|
|
11
|
+
if (test.filePath)
|
|
12
|
+
this.#files.add(test.filePath);
|
|
13
|
+
if (test.suiteName)
|
|
14
|
+
this.#suites.add(test.suiteName);
|
|
15
|
+
}
|
|
8
16
|
for (let test of results.tests) {
|
|
9
17
|
if (test.status === 'passed') {
|
|
10
18
|
process.stdout.write(colors.green('.'));
|
|
@@ -43,6 +51,8 @@ export class DotReporter {
|
|
|
43
51
|
let { passed, failed, skipped, todo } = counts;
|
|
44
52
|
let info = colors.cyan('ℹ');
|
|
45
53
|
console.log();
|
|
54
|
+
console.log(`${info} files ${this.#files.size}`);
|
|
55
|
+
console.log(`${info} suites ${this.#suites.size}`);
|
|
46
56
|
console.log(`${info} tests ${passed + failed + skipped + todo}`);
|
|
47
57
|
console.log(`${info} pass ${passed}`);
|
|
48
58
|
console.log(`${info} fail ${failed}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../src/lib/reporters/files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAc,WAAW,EAAE,MAAM,cAAc,CAAA;AAEnE,qBAAa,aAAc,YAAW,QAAQ;;
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../src/lib/reporters/files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAc,WAAW,EAAE,MAAM,cAAc,CAAA;AAEnE,qBAAa,aAAc,YAAW,QAAQ;;IAK5C,cAAc,CAAC,MAAM,EAAE,MAAM,QAAI;IAEjC,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,QAmC1C;IAED,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAkC3C;CACF"}
|
|
@@ -3,8 +3,16 @@ import { colors } from "../colors.js";
|
|
|
3
3
|
import { normalizeLine } from "../normalize.js";
|
|
4
4
|
export class FilesReporter {
|
|
5
5
|
#failures = [];
|
|
6
|
+
#files = new Set();
|
|
7
|
+
#suites = new Set();
|
|
6
8
|
onSectionStart(_label) { }
|
|
7
9
|
onResult(results, env) {
|
|
10
|
+
for (let test of results.tests) {
|
|
11
|
+
if (test.filePath)
|
|
12
|
+
this.#files.add(test.filePath);
|
|
13
|
+
if (test.suiteName)
|
|
14
|
+
this.#suites.add(test.suiteName);
|
|
15
|
+
}
|
|
8
16
|
let filePath = results.tests[0]?.filePath;
|
|
9
17
|
let fileName = filePath ? path.relative(process.cwd(), filePath) : '(unknown)';
|
|
10
18
|
let envLabel = env ? ` ${colors.dim(`[${env}]`)}` : '';
|
|
@@ -58,6 +66,8 @@ export class FilesReporter {
|
|
|
58
66
|
let { passed, failed, skipped, todo } = counts;
|
|
59
67
|
let info = colors.cyan('ℹ');
|
|
60
68
|
console.log();
|
|
69
|
+
console.log(`${info} files ${this.#files.size}`);
|
|
70
|
+
console.log(`${info} suites ${this.#suites.size}`);
|
|
61
71
|
console.log(`${info} tests ${passed + failed + skipped + todo}`);
|
|
62
72
|
console.log(`${info} pass ${passed}`);
|
|
63
73
|
console.log(`${info} fail ${failed}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../../src/lib/reporters/spec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAc,WAAW,EAAE,MAAM,cAAc,CAAA;AAEnE,qBAAa,YAAa,YAAW,QAAQ;;
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../../src/lib/reporters/spec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAc,WAAW,EAAE,MAAM,cAAc,CAAA;AAEnE,qBAAa,YAAa,YAAW,QAAQ;;IAK3C,cAAc,CAAC,KAAK,EAAE,MAAM,QAE3B;IAED,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,QAmI1C;IAED,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAkC3C;CACF"}
|
|
@@ -2,10 +2,18 @@ import { colors } from "../colors.js";
|
|
|
2
2
|
import { normalizeLine } from "../normalize.js";
|
|
3
3
|
export class SpecReporter {
|
|
4
4
|
#failures = [];
|
|
5
|
+
#files = new Set();
|
|
6
|
+
#suites = new Set();
|
|
5
7
|
onSectionStart(label) {
|
|
6
8
|
console.log(label);
|
|
7
9
|
}
|
|
8
10
|
onResult(results, env) {
|
|
11
|
+
for (let test of results.tests) {
|
|
12
|
+
if (test.filePath)
|
|
13
|
+
this.#files.add(test.filePath);
|
|
14
|
+
if (test.suiteName)
|
|
15
|
+
this.#suites.add(test.suiteName);
|
|
16
|
+
}
|
|
9
17
|
let suiteMap = new Map();
|
|
10
18
|
for (let test of results.tests) {
|
|
11
19
|
let suite = test.suiteName || 'Global';
|
|
@@ -140,6 +148,8 @@ export class SpecReporter {
|
|
|
140
148
|
let { passed, failed, skipped, todo } = counts;
|
|
141
149
|
let info = colors.cyan('ℹ');
|
|
142
150
|
console.log();
|
|
151
|
+
console.log(`${info} files ${this.#files.size}`);
|
|
152
|
+
console.log(`${info} suites ${this.#suites.size}`);
|
|
143
153
|
console.log(`${info} tests ${passed + failed + skipped + todo}`);
|
|
144
154
|
console.log(`${info} pass ${passed}`);
|
|
145
155
|
console.log(`${info} fail ${failed}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tap.d.ts","sourceRoot":"","sources":["../../../src/lib/reporters/tap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAEvD,qBAAa,WAAY,YAAW,QAAQ;;
|
|
1
|
+
{"version":3,"file":"tap.d.ts","sourceRoot":"","sources":["../../../src/lib/reporters/tap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAEvD,qBAAa,WAAY,YAAW,QAAQ;;IAM1C,cAAc,CAAC,MAAM,EAAE,MAAM,QAAI;IAEjC,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,QAwC1C;IAED,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAW3C;CACF"}
|
|
@@ -2,12 +2,20 @@ import { normalizeLine } from "../normalize.js";
|
|
|
2
2
|
export class TapReporter {
|
|
3
3
|
#counter = 0;
|
|
4
4
|
#total = 0;
|
|
5
|
+
#files = new Set();
|
|
6
|
+
#suites = new Set();
|
|
5
7
|
onSectionStart(_label) { }
|
|
6
8
|
onResult(results, env) {
|
|
7
9
|
if (this.#counter === 0) {
|
|
8
10
|
console.log('TAP version 14');
|
|
9
11
|
}
|
|
10
12
|
let envComment = env ? ` # ${env}` : '';
|
|
13
|
+
for (let test of results.tests) {
|
|
14
|
+
if (test.filePath)
|
|
15
|
+
this.#files.add(test.filePath);
|
|
16
|
+
if (test.suiteName)
|
|
17
|
+
this.#suites.add(test.suiteName);
|
|
18
|
+
}
|
|
11
19
|
for (let test of results.tests) {
|
|
12
20
|
this.#counter++;
|
|
13
21
|
this.#total++;
|
|
@@ -42,6 +50,8 @@ export class TapReporter {
|
|
|
42
50
|
onSummary(counts, durationMs) {
|
|
43
51
|
let { passed, failed, skipped, todo } = counts;
|
|
44
52
|
console.log(`1..${this.#total}`);
|
|
53
|
+
console.log(`# files ${this.#files.size}`);
|
|
54
|
+
console.log(`# suites ${this.#suites.size}`);
|
|
45
55
|
console.log(`# tests ${passed + failed + skipped + todo}`);
|
|
46
56
|
console.log(`# pass ${passed}`);
|
|
47
57
|
console.log(`# fail ${failed}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-browser.d.ts","sourceRoot":"","sources":["../../src/lib/runner-browser.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAWzD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,QAAQ,CAAA;IAGlB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC;IACtE,OAAO,EAAE,WAAW,CAAA;IACpB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5B,CAAC,
|
|
1
|
+
{"version":3,"file":"runner-browser.d.ts","sourceRoot":"","sources":["../../src/lib/runner-browser.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAWzD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,QAAQ,CAAA;IAGlB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC;IACtE,OAAO,EAAE,WAAW,CAAA;IACpB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5B,CAAC,CA6HD"}
|
|
@@ -27,6 +27,12 @@ export async function runBrowserTests(options) {
|
|
|
27
27
|
try {
|
|
28
28
|
browser = await getBrowserLauncher(options.playwrightUseOpts).launch(getPlaywrightLaunchOptions(options.playwrightUseOpts));
|
|
29
29
|
page = await browser.newPage(getPlaywrightPageOptions(options.playwrightUseOpts));
|
|
30
|
+
// Cap how long we'll wait for a browser-test file to signal completion.
|
|
31
|
+
// Playwright's default is 30s; bumping to 60s buys headroom for slower
|
|
32
|
+
// suites without letting a hung test hide forever. Plumb this through
|
|
33
|
+
// config later if anyone needs to tune it.
|
|
34
|
+
page.setDefaultTimeout(90_000);
|
|
35
|
+
page.setDefaultNavigationTimeout(90_000);
|
|
30
36
|
if (options.console) {
|
|
31
37
|
page.on('console', (msg) => console.log(`${colors.dim('[browser console]')} ${msg.text()}`));
|
|
32
38
|
}
|
package/dist/lib/runner.d.ts
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
|
+
import { type RemixTestPool } from './config.ts';
|
|
1
2
|
import { type CoverageConfig, type CoverageMap } from './coverage.ts';
|
|
2
3
|
import { type PlaywrightUseOpts } from './playwright.ts';
|
|
3
4
|
import type { Reporter } from './reporters/index.ts';
|
|
4
|
-
import type { Counts } from './reporters/results.ts';
|
|
5
|
+
import type { Counts, TestResults } from './reporters/results.ts';
|
|
6
|
+
interface WorkerRun {
|
|
7
|
+
finished: Promise<void>;
|
|
8
|
+
exited: Promise<number | null>;
|
|
9
|
+
terminate(): Promise<boolean>;
|
|
10
|
+
}
|
|
11
|
+
interface RunFileOptions {
|
|
12
|
+
cwd?: string;
|
|
13
|
+
coverage?: CoverageConfig;
|
|
14
|
+
open?: boolean;
|
|
15
|
+
playwrightUseOpts?: PlaywrightUseOpts;
|
|
16
|
+
pool?: RemixTestPool;
|
|
17
|
+
}
|
|
5
18
|
export declare function runServerTests(files: string[], reporter: Reporter, concurrency: number, type: 'server' | 'e2e', options?: {
|
|
6
19
|
cwd?: string;
|
|
7
20
|
open?: boolean;
|
|
8
21
|
playwrightUseOpts?: PlaywrightUseOpts;
|
|
9
22
|
projectName?: string;
|
|
10
23
|
coverage?: CoverageConfig;
|
|
24
|
+
workerShutdownTimeoutMs?: number;
|
|
25
|
+
pool?: RemixTestPool;
|
|
11
26
|
}): Promise<Counts & {
|
|
12
27
|
coverageMap: CoverageMap | null;
|
|
13
28
|
}>;
|
|
29
|
+
export declare function runFileInWorker(file: string, type: 'server' | 'e2e', onResults: (results: TestResults) => void, options?: RunFileOptions): WorkerRun;
|
|
30
|
+
export {};
|
|
14
31
|
//# sourceMappingURL=runner.d.ts.map
|
package/dist/lib/runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"AAKA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AACrE,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAUjE,UAAU,SAAS;IACjB,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IACvB,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC9B,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;CAC9B;AAED,UAAU,cAAc;IACtB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,IAAI,CAAC,EAAE,aAAa,CAAA;CACrB;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,QAAQ,GAAG,KAAK,EACtB,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,IAAI,CAAC,EAAE,aAAa,CAAA;CAChB,GACL,OAAO,CAAC,MAAM,GAAG;IAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAAC,CAkFvD;AAwFD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,GAAG,KAAK,EACtB,SAAS,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,EACzC,OAAO,GAAE,cAAmB,GAC3B,SAAS,CAiEX"}
|
package/dist/lib/runner.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { fork } from 'node:child_process';
|
|
1
2
|
import * as fsp from 'node:fs/promises';
|
|
2
3
|
import * as path from 'node:path';
|
|
3
|
-
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
4
5
|
import { Worker } from 'node:worker_threads';
|
|
5
6
|
import { IS_RUNNING_FROM_SRC } from "./config.js";
|
|
6
7
|
import { collectCoverageMapFromPlaywright, collectServerCoverageMap, } from "./coverage.js";
|
|
@@ -10,11 +11,14 @@ import {} from "./playwright.js";
|
|
|
10
11
|
const ext = IS_RUNNING_FROM_SRC ? '.ts' : '.js';
|
|
11
12
|
const workerUrl = new URL(`./worker${ext}`, import.meta.url);
|
|
12
13
|
const workerE2EUrl = new URL(`./worker-e2e${ext}`, import.meta.url);
|
|
14
|
+
const workerProcessUrl = new URL(`./worker-process${ext}`, import.meta.url);
|
|
15
|
+
const DEFAULT_WORKER_SHUTDOWN_TIMEOUT_MS = 10_000;
|
|
13
16
|
export async function runServerTests(files, reporter, concurrency, type, options = {}) {
|
|
14
17
|
let counts = { passed: 0, failed: 0, skipped: 0, todo: 0 };
|
|
15
18
|
let coverageMap = null;
|
|
16
19
|
let cwd = options.cwd ?? process.cwd();
|
|
17
20
|
let envLabel = options.projectName ? `${type}:${options.projectName}` : type;
|
|
21
|
+
let pool = options.pool ?? 'forks';
|
|
18
22
|
function accumulate(results, file) {
|
|
19
23
|
reporter.onResult({ ...results, tests: results.tests.map((t) => ({ ...t, filePath: file })) }, envLabel);
|
|
20
24
|
counts.passed += results.passed;
|
|
@@ -24,15 +28,16 @@ export async function runServerTests(files, reporter, concurrency, type, options
|
|
|
24
28
|
}
|
|
25
29
|
if (type === 'e2e') {
|
|
26
30
|
let allBrowserCoverageEntries = [];
|
|
27
|
-
await runInConcurrentWorkers(files, concurrency, (file) =>
|
|
31
|
+
await runInConcurrentWorkers(files, concurrency, (file) => runFileInPool(file, type, (results) => {
|
|
28
32
|
accumulate(results, file);
|
|
29
33
|
if (results.e2eBrowserCoverageEntries) {
|
|
30
34
|
allBrowserCoverageEntries.push(...results.e2eBrowserCoverageEntries);
|
|
31
35
|
}
|
|
32
36
|
}, {
|
|
33
37
|
...options,
|
|
38
|
+
pool,
|
|
34
39
|
playwrightUseOpts: options.playwrightUseOpts,
|
|
35
|
-
}), () => counts.failed
|
|
40
|
+
}), () => counts.failed++, !options.open, options.workerShutdownTimeoutMs ?? DEFAULT_WORKER_SHUTDOWN_TIMEOUT_MS);
|
|
36
41
|
if (options.coverage && allBrowserCoverageEntries.length > 0) {
|
|
37
42
|
coverageMap = await collectCoverageMapFromPlaywright(allBrowserCoverageEntries.flatMap((e) => e.entries), cwd, new Set(files), async (urlPath) => (urlPath.startsWith('/') ? urlPath.slice(1) : urlPath));
|
|
38
43
|
}
|
|
@@ -44,7 +49,10 @@ export async function runServerTests(files, reporter, concurrency, type, options
|
|
|
44
49
|
await fsp.mkdir(coverageDataDir, { recursive: true });
|
|
45
50
|
process.env.NODE_V8_COVERAGE = coverageDataDir;
|
|
46
51
|
}
|
|
47
|
-
await runInConcurrentWorkers(files, concurrency, (file) =>
|
|
52
|
+
await runInConcurrentWorkers(files, concurrency, (file) => runFileInPool(file, type, (results) => accumulate(results, file), {
|
|
53
|
+
...options,
|
|
54
|
+
pool,
|
|
55
|
+
}), () => counts.failed++, true, options.workerShutdownTimeoutMs ?? DEFAULT_WORKER_SHUTDOWN_TIMEOUT_MS);
|
|
48
56
|
if (coverageDataDir) {
|
|
49
57
|
delete process.env.NODE_V8_COVERAGE;
|
|
50
58
|
let serverMap = await collectServerCoverageMap(coverageDataDir, cwd, new Set(files));
|
|
@@ -53,7 +61,7 @@ export async function runServerTests(files, reporter, concurrency, type, options
|
|
|
53
61
|
}
|
|
54
62
|
return { ...counts, coverageMap };
|
|
55
63
|
}
|
|
56
|
-
async function runInConcurrentWorkers(files, concurrency, runFile, onError) {
|
|
64
|
+
async function runInConcurrentWorkers(files, concurrency, runFile, onError, terminateWhenFinished, workerShutdownTimeoutMs) {
|
|
57
65
|
let index = 0;
|
|
58
66
|
let active = 0;
|
|
59
67
|
await new Promise((resolve) => {
|
|
@@ -62,7 +70,8 @@ async function runInConcurrentWorkers(files, concurrency, runFile, onError) {
|
|
|
62
70
|
let file = files[index];
|
|
63
71
|
index++;
|
|
64
72
|
active++;
|
|
65
|
-
runFile(file)
|
|
73
|
+
let run = runFile(file);
|
|
74
|
+
function complete() {
|
|
66
75
|
active--;
|
|
67
76
|
if (index < files.length) {
|
|
68
77
|
dispatch();
|
|
@@ -70,15 +79,32 @@ async function runInConcurrentWorkers(files, concurrency, runFile, onError) {
|
|
|
70
79
|
else if (active === 0) {
|
|
71
80
|
resolve();
|
|
72
81
|
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
}
|
|
83
|
+
run.finished.then(async () => {
|
|
84
|
+
try {
|
|
85
|
+
if (terminateWhenFinished) {
|
|
86
|
+
let exited = await waitForWorkerExit(run.exited, workerShutdownTimeoutMs);
|
|
87
|
+
if (!exited) {
|
|
88
|
+
let terminated = await run.terminate();
|
|
89
|
+
if (!terminated) {
|
|
90
|
+
onError();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
complete();
|
|
97
|
+
}
|
|
98
|
+
}, async (err) => {
|
|
99
|
+
try {
|
|
100
|
+
console.error(`Error running ${file}:`, err instanceof Error ? err.message : err);
|
|
101
|
+
console.error(err);
|
|
102
|
+
onError();
|
|
103
|
+
await run.terminate();
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
complete();
|
|
107
|
+
}
|
|
82
108
|
});
|
|
83
109
|
}
|
|
84
110
|
if (index >= files.length && active === 0)
|
|
@@ -87,32 +113,155 @@ async function runInConcurrentWorkers(files, concurrency, runFile, onError) {
|
|
|
87
113
|
dispatch();
|
|
88
114
|
});
|
|
89
115
|
}
|
|
90
|
-
function
|
|
91
|
-
return new Promise((resolve
|
|
92
|
-
let
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
function waitForWorkerExit(exited, timeoutMs) {
|
|
117
|
+
return new Promise((resolve) => {
|
|
118
|
+
let timeout = setTimeout(() => resolve(false), timeoutMs);
|
|
119
|
+
exited.then(() => {
|
|
120
|
+
clearTimeout(timeout);
|
|
121
|
+
resolve(true);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function runFileInPool(file, type, onResults, options) {
|
|
126
|
+
return options.pool === 'threads'
|
|
127
|
+
? runFileInWorker(file, type, onResults, options)
|
|
128
|
+
: runFileInProcess(file, type, onResults, options);
|
|
129
|
+
}
|
|
130
|
+
export function runFileInWorker(file, type, onResults, options = {}) {
|
|
131
|
+
let receivedResults = false;
|
|
132
|
+
let worker = type === 'e2e'
|
|
133
|
+
? new Worker(workerE2EUrl, {
|
|
134
|
+
workerData: {
|
|
135
|
+
file: pathToFileURL(file).href,
|
|
136
|
+
type,
|
|
137
|
+
coverage: options.coverage,
|
|
138
|
+
open: options.open,
|
|
139
|
+
playwrightUseOpts: options.playwrightUseOpts,
|
|
140
|
+
},
|
|
141
|
+
})
|
|
142
|
+
: new Worker(workerUrl, {
|
|
143
|
+
workerData: {
|
|
144
|
+
file: pathToFileURL(file).href,
|
|
145
|
+
type,
|
|
146
|
+
coverage: options.coverage,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
let exited = new Promise((resolve) => {
|
|
150
|
+
worker.once('exit', (code) => resolve(code));
|
|
151
|
+
});
|
|
152
|
+
let finished = new Promise((resolve, reject) => {
|
|
153
|
+
worker.once('message', (msg) => {
|
|
154
|
+
receivedResults = true;
|
|
155
|
+
try {
|
|
156
|
+
onResults(msg);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
reject(error);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (!options.open) {
|
|
163
|
+
resolve();
|
|
164
|
+
}
|
|
165
|
+
});
|
|
110
166
|
worker.once('error', reject);
|
|
111
|
-
|
|
112
|
-
if (code
|
|
167
|
+
exited.then((code) => {
|
|
168
|
+
if (receivedResults || code === 0) {
|
|
169
|
+
resolve();
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
113
172
|
reject(new Error(`Worker exited with code ${code}`));
|
|
114
|
-
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
return {
|
|
177
|
+
finished,
|
|
178
|
+
exited,
|
|
179
|
+
async terminate() {
|
|
180
|
+
try {
|
|
181
|
+
await worker.terminate();
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
console.error(`Error terminating worker for ${file}:`, err instanceof Error ? err.message : err);
|
|
186
|
+
console.error(err);
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function runFileInProcess(file, type, onResults, options = {}) {
|
|
193
|
+
let receivedResults = false;
|
|
194
|
+
let child = fork(fileURLToPath(workerProcessUrl), [], {
|
|
195
|
+
serialization: 'advanced',
|
|
196
|
+
stdio: ['ignore', 'inherit', 'inherit', 'ipc'],
|
|
197
|
+
});
|
|
198
|
+
let exited = new Promise((resolve) => {
|
|
199
|
+
child.once('exit', (code) => resolve(code));
|
|
200
|
+
});
|
|
201
|
+
let finished = new Promise((resolve, reject) => {
|
|
202
|
+
child.once('message', (msg) => {
|
|
203
|
+
if (!isTestResults(msg)) {
|
|
204
|
+
reject(new Error('Test worker process sent invalid results'));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
receivedResults = true;
|
|
208
|
+
try {
|
|
209
|
+
onResults(msg);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
reject(error);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (!options.open) {
|
|
115
216
|
resolve();
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
child.once('error', reject);
|
|
220
|
+
exited.then((code) => {
|
|
221
|
+
if (receivedResults || code === 0) {
|
|
222
|
+
resolve();
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
reject(new Error(`Worker process exited with code ${code}`));
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
child.send({
|
|
229
|
+
file: pathToFileURL(file).href,
|
|
230
|
+
type,
|
|
231
|
+
coverage: options.coverage,
|
|
232
|
+
open: options.open,
|
|
233
|
+
playwrightUseOpts: options.playwrightUseOpts,
|
|
234
|
+
}, (error) => {
|
|
235
|
+
if (error) {
|
|
236
|
+
reject(error);
|
|
237
|
+
}
|
|
116
238
|
});
|
|
117
239
|
});
|
|
240
|
+
return {
|
|
241
|
+
finished,
|
|
242
|
+
exited,
|
|
243
|
+
terminate: () => terminateChildProcess(child, exited),
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
async function terminateChildProcess(child, exited) {
|
|
247
|
+
if (child.exitCode !== null || child.signalCode !== null) {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
if (!child.kill()) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
return await waitForWorkerExit(exited, 5_000);
|
|
254
|
+
}
|
|
255
|
+
function isTestResults(value) {
|
|
256
|
+
if (!isRecord(value)) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
return (typeof value.passed === 'number' &&
|
|
260
|
+
typeof value.failed === 'number' &&
|
|
261
|
+
typeof value.skipped === 'number' &&
|
|
262
|
+
typeof value.todo === 'number' &&
|
|
263
|
+
Array.isArray(value.tests));
|
|
264
|
+
}
|
|
265
|
+
function isRecord(value) {
|
|
266
|
+
return typeof value === 'object' && value !== null;
|
|
118
267
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type PlaywrightUseOpts } from './playwright.ts';
|
|
2
|
+
import type { CoverageConfig } from './coverage.ts';
|
|
3
|
+
import type { TestResults } from './reporters/results.ts';
|
|
4
|
+
export interface E2ETestWorkerData {
|
|
5
|
+
file: string;
|
|
6
|
+
coverage?: CoverageConfig;
|
|
7
|
+
open?: boolean;
|
|
8
|
+
playwrightUseOpts?: PlaywrightUseOpts;
|
|
9
|
+
}
|
|
10
|
+
export declare function runE2ETestFile(value: unknown, onOpenResults?: (results: TestResults) => void | Promise<void>): Promise<TestResults | undefined>;
|
|
11
|
+
//# sourceMappingURL=worker-e2e-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-e2e-file.d.ts","sourceRoot":"","sources":["../../src/lib/worker-e2e-file.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAIzD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;CACtC;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,OAAO,EACd,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC7D,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAqClC"}
|