@uniflowed/test 0.3.0 → 0.5.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/internal/frames.js +8 -0
- package/internal/run.js +51 -2
- package/package.json +2 -2
- package/worker.js +3 -0
package/internal/frames.js
CHANGED
|
@@ -252,6 +252,14 @@ function sourceMapsForCallSites(): FindSourceMap | false {
|
|
|
252
252
|
nodeSourceMaps = false;
|
|
253
253
|
return false;
|
|
254
254
|
}
|
|
255
|
+
// A `uf test` worker whose loader maps lazily holds the maps Node would
|
|
256
|
+
// have, and answers for them the way `findSourceMap` would; see
|
|
257
|
+
// `@uniflowed/host`'s `internal/lazy-source-maps.js`.
|
|
258
|
+
const lazy = host[Symbol.for("@uniflowed/host/source-maps")];
|
|
259
|
+
if (typeof lazy?.findSourceMap === "function") {
|
|
260
|
+
nodeSourceMaps = (file) => lazy.findSourceMap(file);
|
|
261
|
+
return nodeSourceMaps;
|
|
262
|
+
}
|
|
255
263
|
const findSourceMap = process.getBuiltinModule("node:module")?.findSourceMap;
|
|
256
264
|
nodeSourceMaps =
|
|
257
265
|
typeof findSourceMap === "function"
|
package/internal/run.js
CHANGED
|
@@ -75,6 +75,19 @@ export type RunOptions = {|
|
|
|
75
75
|
* round. `uf test --bench` sets it.
|
|
76
76
|
*/
|
|
77
77
|
readonly bench?: boolean,
|
|
78
|
+
/**
|
|
79
|
+
* Run only share `index` of `count` of the file's cases, and report nothing
|
|
80
|
+
* about the rest.
|
|
81
|
+
*
|
|
82
|
+
* `uf test` splits a file long enough to hold up a run across several
|
|
83
|
+
* workers, and each is handed one share: the cases are numbered in the
|
|
84
|
+
* order the file registered them, and share `index` is the contiguous run
|
|
85
|
+
* from `index * n / count` to `(index + 1) * n / count`. Every worker
|
|
86
|
+
* imports the whole file and walks the same tree, so the shares between
|
|
87
|
+
* them report every case once. A case outside the share is not reported at
|
|
88
|
+
* all — not as skipped — because another worker is reporting it.
|
|
89
|
+
*/
|
|
90
|
+
readonly part?: {| readonly index: number, readonly count: number |} | null,
|
|
78
91
|
|};
|
|
79
92
|
|
|
80
93
|
/** Default budget for one case, matching what most runners use. */
|
|
@@ -381,7 +394,7 @@ async function runSuite(
|
|
|
381
394
|
options: RunOptions,
|
|
382
395
|
onlyMode: boolean,
|
|
383
396
|
emit: (result: Result) => void,
|
|
384
|
-
state: {| bail: boolean |},
|
|
397
|
+
state: {| bail: boolean, readonly owned: Set<Case> | null |},
|
|
385
398
|
setUpAncestors: () => Promise<void>,
|
|
386
399
|
): Promise<boolean> {
|
|
387
400
|
const skipped = context.skipped || node.modifier === "skip" || node.modifier === "todo";
|
|
@@ -430,6 +443,10 @@ async function runSuite(
|
|
|
430
443
|
break;
|
|
431
444
|
}
|
|
432
445
|
if (child.kind !== "suite") {
|
|
446
|
+
// Another worker's share: it reports this case, and sets up for it.
|
|
447
|
+
if (state.owned != null && !state.owned.has(child)) {
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
433
450
|
const willRun =
|
|
434
451
|
!inner.skipped &&
|
|
435
452
|
child.modifier !== "skip" &&
|
|
@@ -490,6 +507,7 @@ async function runSuite(
|
|
|
490
507
|
export async function run(options: RunOptions, emit: (result: Result) => void): Promise<void> {
|
|
491
508
|
const root = collected();
|
|
492
509
|
const onlyMode = hasOnly(root, false);
|
|
510
|
+
const owned = share(root, options.part);
|
|
493
511
|
const context: Context = {
|
|
494
512
|
path: [],
|
|
495
513
|
beforeEach: [],
|
|
@@ -497,5 +515,36 @@ export async function run(options: RunOptions, emit: (result: Result) => void):
|
|
|
497
515
|
skipped: false,
|
|
498
516
|
onlyPath: !onlyMode,
|
|
499
517
|
};
|
|
500
|
-
await runSuite(root, context, options, onlyMode, emit, { bail: false }, async () => {});
|
|
518
|
+
await runSuite(root, context, options, onlyMode, emit, { bail: false, owned }, async () => {});
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* The cases of `part`, or `null` for a run of every case.
|
|
523
|
+
*
|
|
524
|
+
* Numbered in the order a walk of the tree meets them, which is the order the
|
|
525
|
+
* file registered them and the order `runSuite` runs them in — the same in
|
|
526
|
+
* every worker that imported the file, which is what lets each work out its
|
|
527
|
+
* own share without being told the others'.
|
|
528
|
+
*/
|
|
529
|
+
function share(
|
|
530
|
+
root: Suite,
|
|
531
|
+
part: ?{| readonly index: number, readonly count: number |},
|
|
532
|
+
): Set<Case> | null {
|
|
533
|
+
if (part == null || part.count < 2) {
|
|
534
|
+
return null;
|
|
535
|
+
}
|
|
536
|
+
const cases: Array<Case> = [];
|
|
537
|
+
const walk = (node: Suite) => {
|
|
538
|
+
for (const child of node.children) {
|
|
539
|
+
if (child.kind === "suite") {
|
|
540
|
+
walk(child);
|
|
541
|
+
} else {
|
|
542
|
+
cases.push(child);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
walk(root);
|
|
547
|
+
const from = Math.floor((part.index * cases.length) / part.count);
|
|
548
|
+
const to = Math.floor(((part.index + 1) * cases.length) / part.count);
|
|
549
|
+
return new Set(cases.slice(from, to));
|
|
501
550
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniflowed/test",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The test API and worker for `uf test`: describe/it, a full matcher set, and the process uf fans test files out to.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"!*.test.js"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@uniflowed/host": "0.
|
|
41
|
+
"@uniflowed/host": "0.5.0",
|
|
42
42
|
"pixelmatch": "^7.1.0",
|
|
43
43
|
"pngjs": "^7.0.0"
|
|
44
44
|
},
|
package/worker.js
CHANGED
|
@@ -86,6 +86,8 @@ type Request = {|
|
|
|
86
86
|
*/
|
|
87
87
|
readonly invalidate?: $ReadOnlyArray<string>,
|
|
88
88
|
readonly filter?: string | null,
|
|
89
|
+
/** Run only this share of the file's cases; see `RunOptions.part`. */
|
|
90
|
+
readonly part?: {| readonly index: number, readonly count: number |} | null,
|
|
89
91
|
readonly timeoutMs?: number,
|
|
90
92
|
/**
|
|
91
93
|
* Which request this is, counting from one within this worker.
|
|
@@ -259,6 +261,7 @@ async function runImportedFile(
|
|
|
259
261
|
await run(
|
|
260
262
|
{
|
|
261
263
|
filter: request.filter ?? null,
|
|
264
|
+
part: request.part ?? null,
|
|
262
265
|
timeoutMs: request.timeoutMs,
|
|
263
266
|
file: absolute,
|
|
264
267
|
bench: benching(),
|