@shivaedev/vitest-rerun 0.0.0-stage → 0.1.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 +9 -0
- package/LICENSE +21 -0
- package/README.md +93 -2
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +1 -0
- package/dist/error.d.ts +11 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +7 -0
- package/dist/error.js.map +1 -0
- package/dist/flakyTests.d.ts +30 -0
- package/dist/flakyTests.d.ts.map +1 -0
- package/dist/flakyTests.js +24 -0
- package/dist/flakyTests.js.map +1 -0
- package/dist/internal/TimedJsonReporter.d.ts +5 -0
- package/dist/internal/TimedJsonReporter.d.ts.map +1 -0
- package/dist/internal/TimedJsonReporter.js +17 -0
- package/dist/internal/TimedJsonReporter.js.map +1 -0
- package/dist/internal/attempt.d.ts +2 -0
- package/dist/internal/attempt.d.ts.map +1 -0
- package/dist/internal/attempt.js +10 -0
- package/dist/internal/attempt.js.map +1 -0
- package/dist/internal/junit.d.ts +8 -0
- package/dist/internal/junit.d.ts.map +1 -0
- package/dist/internal/junit.js +22 -0
- package/dist/internal/junit.js.map +1 -0
- package/dist/internal/main.d.ts +3 -0
- package/dist/internal/main.d.ts.map +1 -0
- package/dist/internal/main.js +7 -0
- package/dist/internal/main.js.map +1 -0
- package/dist/internal/mergeAttempt.d.ts +9 -0
- package/dist/internal/mergeAttempt.d.ts.map +1 -0
- package/dist/internal/mergeAttempt.js +87 -0
- package/dist/internal/mergeAttempt.js.map +1 -0
- package/dist/internal/reportPaths.d.ts +13 -0
- package/dist/internal/reportPaths.d.ts.map +1 -0
- package/dist/internal/reportPaths.js +18 -0
- package/dist/internal/reportPaths.js.map +1 -0
- package/dist/internal/runAttempt.d.ts +8 -0
- package/dist/internal/runAttempt.d.ts.map +1 -0
- package/dist/internal/runAttempt.js +102 -0
- package/dist/internal/runAttempt.js.map +1 -0
- package/dist/internal/snapshot.d.ts +20 -0
- package/dist/internal/snapshot.d.ts.map +1 -0
- package/dist/internal/snapshot.js +22 -0
- package/dist/internal/snapshot.js.map +1 -0
- package/dist/options.d.ts +12 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +40 -0
- package/dist/options.js.map +1 -0
- package/dist/rerun.d.ts +5 -0
- package/dist/rerun.d.ts.map +1 -0
- package/dist/rerun.js +51 -0
- package/dist/rerun.js.map +1 -0
- package/docs/north-star.md +38 -0
- package/docs/roadmap.md +18 -0
- package/package.json +77 -3
- package/src/cli.ts +7 -0
- package/src/error.ts +10 -0
- package/src/flakyTests.ts +31 -0
- package/src/internal/TimedJsonReporter.ts +17 -0
- package/src/internal/attempt.ts +15 -0
- package/src/internal/junit.ts +25 -0
- package/src/internal/main.ts +10 -0
- package/src/internal/mergeAttempt.ts +105 -0
- package/src/internal/reportPaths.ts +20 -0
- package/src/internal/runAttempt.ts +126 -0
- package/src/internal/snapshot.ts +43 -0
- package/src/options.ts +47 -0
- package/src/rerun.ts +64 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 - 2026-10-18
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Add the `vitest-rerun` command, which runs Vitest with retries off and reruns only the failed tests in a fresh process, up to `--reruns` times (default 1), while the final JSON, JUnit and coverage reports describe the whole run.
|
|
8
|
+
- Write `flaky-tests.json` whenever a test fails and then passes, with each test's JUnit `classname` and `name`, its file, its attempt count and the messages of its failed attempts; read it with the `FlakyTests` schema from `flakyTests.ts`.
|
|
9
|
+
- Name the Vitest project in the JUnit `classname`, so a file that runs in two projects keeps a distinct identity in each.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ShivaeDev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,94 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @shivaedev/vitest-rerun
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A flaky test should get a clean second chance, and you should learn that it needed one. This package runs Vitest, reruns only the failed tests in a fresh process, and writes the tests that passed only on a rerun to `flaky-tests.json` beside the usual JUnit report.
|
|
4
|
+
|
|
5
|
+
## Why you want this
|
|
6
|
+
|
|
7
|
+
Vitest's built-in `retry` repeats a failed test in the same worker, with the same module state, mocks and open handles that may have caused the failure. A retry there can fail for the wrong reason, or pass while hiding that the first attempt broke something. A rerun in a new process starts from nothing, like the first attempt did.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
vitest-rerun -- --coverage
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
When a test fails once and then passes, the run succeeds and `test-results/flaky-tests.json` names it:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
[
|
|
17
|
+
{
|
|
18
|
+
"classname": "src/checkout.test.ts",
|
|
19
|
+
"name": "checkout > charges the card once",
|
|
20
|
+
"file": "src/checkout.test.ts",
|
|
21
|
+
"attempts": 2,
|
|
22
|
+
"messages": ["expected 2 to be 1"]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The final JUnit and JSON reports still describe the whole run, so CI, coverage and test dashboards see one result per test.
|
|
28
|
+
|
|
29
|
+
## Using it
|
|
30
|
+
|
|
31
|
+
### How a run works
|
|
32
|
+
|
|
33
|
+
`vitest-rerun` runs `vitest run` once in a child process with Vitest's own retries turned off. If tests failed, it starts a new process that runs only the failed tests: tests that passed are skipped by their Vitest test IDs, including passing tests in a failed file. A file that failed to load runs again in full. Each rerun is one more attempt, and only tests still failing take part in the next one. The run ends when every test passes or the reruns are used up, and its exit code is the last attempt's: `0` when everything passed, `1` when a test is still failing, and `2` for invalid options.
|
|
34
|
+
|
|
35
|
+
An unhandled error, such as an exception thrown after a test finished, cannot be fixed by running a test again, so a run with one is not rerun and fails.
|
|
36
|
+
|
|
37
|
+
### Options
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
vitest-rerun [--reruns <count>] [--output-dir <directory>] [--] [vitest run arguments]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`--reruns` sets how many fresh-process reruns may follow the first attempt; it defaults to `1`, and `0` turns reruns off. `--output-dir` sets where the reports go; it defaults to `test-results`. Every other argument, and everything after `--`, goes to `vitest run`, for example `--config`, `--project`, `--shard` or `--coverage`. `vitest-rerun` supplies Vitest's reporters itself: the default terminal reporter, a JSON report and a JUnit report.
|
|
44
|
+
|
|
45
|
+
### Reports
|
|
46
|
+
|
|
47
|
+
A run first deletes the reports of an earlier run in its output directory, then writes:
|
|
48
|
+
|
|
49
|
+
| File | Contents |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `tests.json` | Vitest's JSON report for the whole run, with each test's final result and a `durationMs` per file that adds up every attempt. |
|
|
52
|
+
| `tests.junit.xml` | The JUnit report for the whole run, written with `addFileAttribute`. |
|
|
53
|
+
| `flaky-tests.json` | Written only when a test failed and then passed on a rerun. |
|
|
54
|
+
| `tests.attempt-<n>.json`, `tests.attempt-<n>.junit.xml` | The raw reports of each attempt, kept once a rerun happens. |
|
|
55
|
+
|
|
56
|
+
Coverage, when enabled, merges every attempt into the configured reports directory, so tests that passed the first time keep their coverage and rerun coverage adds to it. Reruns use their own Vite cache in `<output-dir>/vite-rerun`, so the first attempt's results cache, which Vitest uses to order test files, stays intact. Each recovered test also prints a `- Flaky:` line, which is appended to the GitHub Actions job summary when `GITHUB_STEP_SUMMARY` is set; a file that failed to load and then passed is reported there as a collection failure.
|
|
57
|
+
|
|
58
|
+
### flaky-tests.json
|
|
59
|
+
|
|
60
|
+
The file holds one entry per test that passed only on a rerun:
|
|
61
|
+
|
|
62
|
+
| Field | Value |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `classname` | The JUnit `classname` of the test's `testcase`, exactly as in `tests.junit.xml`. |
|
|
65
|
+
| `name` | The JUnit `name` of the test's `testcase`: its describe blocks and title joined by ` > `. |
|
|
66
|
+
| `file` | The test file's path relative to the Vitest root, the same as the JUnit `file` attribute. |
|
|
67
|
+
| `attempts` | How many attempts the test took, counting the one that passed. |
|
|
68
|
+
| `messages` | The error message of each failed attempt, in order. |
|
|
69
|
+
|
|
70
|
+
The JUnit `classname` is the file's path relative to the Vitest root. When the test runs in a named Vitest project, the project comes first, as in `|unit| src/checkout.test.ts`, so a file that runs in two projects has a distinct `classname` in each. A file that failed to load has no test to name, so it appears only in the job summary.
|
|
71
|
+
|
|
72
|
+
Read the file with the `FlakyTests` schema from `@shivaedev/vitest-rerun/flakyTests.ts`:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { Schema } from "effect";
|
|
76
|
+
import { FlakyTests } from "@shivaedev/vitest-rerun/flakyTests.ts";
|
|
77
|
+
|
|
78
|
+
const flaky = Schema.decodeUnknownSync(Schema.fromJsonString(FlakyTests))(contents);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### From Effect
|
|
82
|
+
|
|
83
|
+
The command line is a thin wrapper over two Effect functions. `parseOptions(args, cwd)` from `@shivaedev/vitest-rerun/options.ts` turns command-line arguments into `RerunOptions`, with the output directory resolved against `cwd`, the directory every attempt runs in, failing with a `VitestRerunError` from `/error.ts` for an invalid rerun count. `rerun(options)` from `/rerun.ts` performs the run and succeeds with its exit code; it needs `FileSystem` and `ChildProcessSpawner`, which `NodeServices.layer` from `@effect/platform-node` provides.
|
|
84
|
+
|
|
85
|
+
### Install and limits
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
npm install --save-dev @shivaedev/vitest-rerun vitest@5.0.3 effect@4.0.4 @effect/platform-node@4.0.4 @effect/platform-node-shared@4.0.4
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`vitest`, `effect` and the Effect Node platform packages are peers, so your own versions run the tests. The package needs Node 24 or later.
|
|
92
|
+
|
|
93
|
+
- Vitest's `retry` is always `0`; the fresh-process rerun replaces it.
|
|
94
|
+
- The package is built for ShivaeDev repositories and may change without a deprecation period.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { NodeServices } from "@effect/platform-node";
|
|
4
|
+
import { Effect } from "effect";
|
|
5
|
+
import { main } from "#internal/main.ts";
|
|
6
|
+
process.exitCode = await Effect.runPromise(main(process.argv.slice(2), process.cwd()).pipe(Effect.provide(NodeServices.layer)));
|
|
7
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare const VitestRerunError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
2
|
+
readonly _tag: "VitestRerunError";
|
|
3
|
+
} & Readonly<A>;
|
|
4
|
+
export declare class VitestRerunError extends VitestRerunError_base<{
|
|
5
|
+
readonly message: string;
|
|
6
|
+
readonly cause?: unknown;
|
|
7
|
+
}> {
|
|
8
|
+
}
|
|
9
|
+
export declare function failWith(message: string): (cause: unknown) => VitestRerunError;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":";;;AAEA,qBAAa,gBAAiB,SAAQ,sBAAqC;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;CAAG;AAEL,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,WACxB,OAAO,KAAG,gBAAgB,CACzC"}
|
package/dist/error.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,MAAM,OAAO,gBAAiB,SAAQ,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAGvE;CAAG;AAEL,MAAM,UAAU,QAAQ,CAAC,OAAe;IACvC,OAAO,CAAC,KAAc,EAAoB,EAAE,CAAC,IAAI,gBAAgB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AACvF,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Effect, FileSystem, Schema } from "effect";
|
|
2
|
+
import type { Task } from "#internal/snapshot.ts";
|
|
3
|
+
export declare const FlakyTest: Schema.Struct<{
|
|
4
|
+
readonly attempts: Schema.Number;
|
|
5
|
+
readonly classname: Schema.String;
|
|
6
|
+
readonly file: Schema.String;
|
|
7
|
+
readonly messages: Schema.$Array<Schema.String>;
|
|
8
|
+
readonly name: Schema.String;
|
|
9
|
+
}>;
|
|
10
|
+
export type FlakyTest = typeof FlakyTest.Type;
|
|
11
|
+
export declare const FlakyTests: Schema.$Array<Schema.Struct<{
|
|
12
|
+
readonly attempts: Schema.Number;
|
|
13
|
+
readonly classname: Schema.String;
|
|
14
|
+
readonly file: Schema.String;
|
|
15
|
+
readonly messages: Schema.$Array<Schema.String>;
|
|
16
|
+
readonly name: Schema.String;
|
|
17
|
+
}>>;
|
|
18
|
+
export declare function testcases(tasks: readonly Task[], ancestors?: string): {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly task: Task;
|
|
21
|
+
}[];
|
|
22
|
+
export declare function failureMessage(task: Task): string;
|
|
23
|
+
export declare const writeFlakyTests: (path: string, flaky: readonly {
|
|
24
|
+
readonly attempts: number;
|
|
25
|
+
readonly classname: string;
|
|
26
|
+
readonly file: string;
|
|
27
|
+
readonly messages: readonly string[];
|
|
28
|
+
readonly name: string;
|
|
29
|
+
}[]) => Effect.Effect<void, import("effect/PlatformError").PlatformError | Schema.SchemaError, FileSystem.FileSystem>;
|
|
30
|
+
//# sourceMappingURL=flakyTests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flakyTests.d.ts","sourceRoot":"","sources":["../src/flakyTests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAElD,eAAO,MAAM,SAAS;;;;;;EAMpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAC;AAE9C,eAAO,MAAM,UAAU;;;;;;GAA0B,CAAC;AAElD,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,SAAS,SAAK,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CAAE,EAAE,CAKlH;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEjD;AAID,eAAO,MAAM,eAAe;;;;;;qHAG1B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Effect, FileSystem, Schema } from "effect";
|
|
2
|
+
export const FlakyTest = Schema.Struct({
|
|
3
|
+
attempts: Schema.Number,
|
|
4
|
+
classname: Schema.String,
|
|
5
|
+
file: Schema.String,
|
|
6
|
+
messages: Schema.Array(Schema.String),
|
|
7
|
+
name: Schema.String,
|
|
8
|
+
});
|
|
9
|
+
export const FlakyTests = Schema.Array(FlakyTest);
|
|
10
|
+
export function testcases(tasks, ancestors = "") {
|
|
11
|
+
return tasks.flatMap((task) => {
|
|
12
|
+
const name = ancestors === "" ? task.name : `${ancestors} > ${task.name}`;
|
|
13
|
+
return task.type === "suite" ? testcases(task.tasks, name) : [{ name, task }];
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function failureMessage(task) {
|
|
17
|
+
return (task.result?.errors ?? []).map((error) => error.message).join("\n");
|
|
18
|
+
}
|
|
19
|
+
const encode = Schema.encodeEffect(Schema.fromJsonString(FlakyTests));
|
|
20
|
+
export const writeFlakyTests = Effect.fn("VitestRerun.writeFlakyTests")(function* (path, flaky) {
|
|
21
|
+
const fs = yield* FileSystem.FileSystem;
|
|
22
|
+
yield* fs.writeFileString(path, `${yield* encode(flaky)}\n`);
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=flakyTests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flakyTests.js","sourceRoot":"","sources":["../src/flakyTests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGpD,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC,MAAM;IACvB,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC,MAAM;CACnB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AAElD,MAAM,UAAU,SAAS,CAAC,KAAsB,EAAE,SAAS,GAAG,EAAE;IAC/D,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1E,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAU;IACxC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;AAEtE,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC,6BAA6B,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAY,EAAE,KAA2B;IAC3H,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;IACxC,KAAK,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimedJsonReporter.d.ts","sourceRoot":"","sources":["../../src/internal/TimedJsonReporter.ts"],"names":[],"mappings":"AACA,OAAO,EAA8B,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAExF,qBAAa,iBAAkB,SAAQ,YAAY;IACnC,YAAY,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,iBAWzD;CACD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { experimental_getRunnerTask, JsonReporter } from "vitest/node";
|
|
3
|
+
export class TimedJsonReporter extends JsonReporter {
|
|
4
|
+
async onTestRunEnd(modules) {
|
|
5
|
+
await super.onTestRunEnd([...modules]);
|
|
6
|
+
const path = this.options.outputFile;
|
|
7
|
+
if (path === undefined) {
|
|
8
|
+
throw new Error("Timed JSON reports require an output file");
|
|
9
|
+
}
|
|
10
|
+
const report = JSON.parse(readFileSync(path, "utf8"));
|
|
11
|
+
for (const [index, module] of modules.entries()) {
|
|
12
|
+
report.testResults[index].durationMs = experimental_getRunnerTask(module).result?.duration ?? 0;
|
|
13
|
+
}
|
|
14
|
+
writeFileSync(path, JSON.stringify(report));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=TimedJsonReporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimedJsonReporter.js","sourceRoot":"","sources":["../../src/internal/TimedJsonReporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,YAAY,EAAmB,MAAM,aAAa,CAAC;AAExF,MAAM,OAAO,iBAAkB,SAAQ,YAAY;IACzC,KAAK,CAAC,YAAY,CAAC,OAA8B;QACzD,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,IAAI,CAAC,CAAC;QACjG,CAAC;QACD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C,CAAC;CACD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attempt.d.ts","sourceRoot":"","sources":["../../src/internal/attempt.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { NodeServices } from "@effect/platform-node";
|
|
3
|
+
import { Console, Effect } from "effect";
|
|
4
|
+
import { runAttempt } from "#internal/runAttempt.ts";
|
|
5
|
+
const [attempt = "1", outputDir = ".", ...vitestArgs] = process.argv.slice(2);
|
|
6
|
+
const failed = await Effect.runPromise(runAttempt({ attempt: Number(attempt), outputDir, vitestArgs }).pipe(Effect.catchTag("VitestRerunError", (error) => Effect.as(Console.error(`vitest-rerun: ${error.message}`, error.cause), true)), Effect.provide(NodeServices.layer)));
|
|
7
|
+
if (failed) {
|
|
8
|
+
process.exitCode = 1;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=attempt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attempt.js","sourceRoot":"","sources":["../../src/internal/attempt.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,SAAS,GAAG,GAAG,EAAE,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CACrC,UAAU,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC,IAAI,CACnE,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,EAC7H,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAClC,CACD,CAAC;AACF,IAAI,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { JUnitReporter, type Vitest } from "vitest/node";
|
|
2
|
+
export declare function junitClassname(file: string, project: string): string;
|
|
3
|
+
export declare class RerunJunitReporter extends JUnitReporter {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(outputFile: string);
|
|
6
|
+
onInit(vitest: Vitest): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=junit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"junit.d.ts","sourceRoot":"","sources":["../../src/internal/junit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAEzD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,qBAAa,kBAAmB,SAAQ,aAAa;;IAGpD,YAAY,UAAU,EAAE,MAAM,EAQ7B;IAEQ,MAAM,CAAC,MAAM,EAAE,MAAM,iBAG7B;CACD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
import { JUnitReporter } from "vitest/node";
|
|
3
|
+
export function junitClassname(file, project) {
|
|
4
|
+
return project === "" ? file : `|${project}| ${file}`;
|
|
5
|
+
}
|
|
6
|
+
export class RerunJunitReporter extends JUnitReporter {
|
|
7
|
+
#root;
|
|
8
|
+
constructor(outputFile) {
|
|
9
|
+
const root = { path: "" };
|
|
10
|
+
super({
|
|
11
|
+
addFileAttribute: true,
|
|
12
|
+
classnameTemplate: ({ displayName, filepath }) => junitClassname(relative(root.path, filepath), displayName),
|
|
13
|
+
outputFile,
|
|
14
|
+
});
|
|
15
|
+
this.#root = root;
|
|
16
|
+
}
|
|
17
|
+
onInit(vitest) {
|
|
18
|
+
this.#root.path = vitest.config.root;
|
|
19
|
+
return super.onInit(vitest);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=junit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"junit.js","sourceRoot":"","sources":["../../src/internal/junit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,aAAa,EAAe,MAAM,aAAa,CAAC;AAEzD,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,OAAe;IAC3D,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,OAAO,kBAAmB,SAAQ,aAAa;IAC3C,KAAK,CAAmB;IAEjC,YAAY,UAAkB;QAC7B,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAC1B,KAAK,CAAC;YACL,gBAAgB,EAAE,IAAI;YACtB,iBAAiB,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,WAAW,CAAC;YAC5G,UAAU;SACV,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACnB,CAAC;IAEQ,MAAM,CAAC,MAAc;QAC7B,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;QACrC,OAAO,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;CACD"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
export declare function main(args: readonly string[], cwd: string): Effect.Effect<number, import("effect/PlatformError").PlatformError | import("effect/Schema").SchemaError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/FileSystem").FileSystem>;
|
|
3
|
+
//# sourceMappingURL=main.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/internal/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIzC,wBAAgB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,wNAKxD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Console, Effect } from "effect";
|
|
2
|
+
import { parseOptions } from "#options.ts";
|
|
3
|
+
import { rerun } from "#rerun.ts";
|
|
4
|
+
export function main(args, cwd) {
|
|
5
|
+
return parseOptions(args, cwd).pipe(Effect.flatMap(rerun), Effect.catchTag("VitestRerunError", (error) => Effect.as(Console.error(`vitest-rerun: ${error.message}`), 2)));
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/internal/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,MAAM,UAAU,IAAI,CAAC,IAAuB,EAAE,GAAW;IACxD,OAAO,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CAClC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EACrB,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAC7G,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type FlakyTest } from "#flakyTests.ts";
|
|
2
|
+
import { type FailureHistory, type Files, type Snapshot } from "#internal/snapshot.ts";
|
|
3
|
+
export interface Merged {
|
|
4
|
+
readonly failures: Readonly<Record<string, FailureHistory>>;
|
|
5
|
+
readonly files: Files;
|
|
6
|
+
readonly flaky: readonly FlakyTest[];
|
|
7
|
+
}
|
|
8
|
+
export declare function mergeAttempt(previous: Snapshot, rerun: Files, root: string, summary: (line: string) => void): Merged;
|
|
9
|
+
//# sourceMappingURL=mergeAttempt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mergeAttempt.d.ts","sourceRoot":"","sources":["../../src/internal/mergeAttempt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAA6B,MAAM,gBAAgB,CAAC;AAE3E,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,KAAK,EAAE,KAAK,QAAQ,EAAoB,MAAM,uBAAuB,CAAC;AAoFzG,MAAM,WAAW,MAAM;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;IAC5D,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;CACrC;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAWpH"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
import { failureMessage, testcases } from "#flakyTests.ts";
|
|
3
|
+
import { junitClassname } from "#internal/junit.ts";
|
|
4
|
+
import { tests } from "#internal/snapshot.ts";
|
|
5
|
+
function mergeTest(first, task) {
|
|
6
|
+
const unresolved = first.result?.state === "fail" && !["pass", "fail"].includes(task.result?.state ?? "");
|
|
7
|
+
if (first.result !== undefined && (first.result.state === "pass" || unresolved)) {
|
|
8
|
+
task.mode = first.mode;
|
|
9
|
+
task.result = first.result;
|
|
10
|
+
task.logs = first.logs ?? [];
|
|
11
|
+
}
|
|
12
|
+
else if (task.result !== undefined) {
|
|
13
|
+
task.result.duration = (task.result.duration ?? 0) + (first.result?.duration ?? 0);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function restorePassed(original, rerun) {
|
|
17
|
+
for (const task of rerun) {
|
|
18
|
+
const first = original.find((item) => item.id === task.id);
|
|
19
|
+
if (first === undefined) {
|
|
20
|
+
throw new Error(`Rerun collected an unexpected test: ${task.name}`);
|
|
21
|
+
}
|
|
22
|
+
if (task.type === "suite" && first.type === "suite") {
|
|
23
|
+
restorePassed(first.tasks, task.tasks);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
mergeTest(first, task);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function finishFile(file, next, ranTests) {
|
|
31
|
+
const duration = (file.result?.duration ?? 0) + (next.result?.duration ?? 0);
|
|
32
|
+
if (!ranTests && file.tasks.length > 0 && file.result !== undefined) {
|
|
33
|
+
next.result = { ...file.result };
|
|
34
|
+
}
|
|
35
|
+
if (next.result !== undefined) {
|
|
36
|
+
if (tests(next.tasks).some((test) => test.result?.state === "fail")) {
|
|
37
|
+
next.result.state = "fail";
|
|
38
|
+
}
|
|
39
|
+
next.result.startTime = file.result?.startTime ?? next.result.startTime ?? 0;
|
|
40
|
+
next.result.duration = duration;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function recordAttempts(file, retried, outcome) {
|
|
44
|
+
const path = relative(outcome.root, file.filepath);
|
|
45
|
+
const classname = junitClassname(path, file.projectName ?? "");
|
|
46
|
+
for (const { name, task } of testcases(file.tasks).filter((testcase) => testcase.task.result?.state === "fail")) {
|
|
47
|
+
const again = retried.find((item) => item.id === task.id);
|
|
48
|
+
const prior = outcome.failures[task.id] ?? { attempts: 1, messages: [failureMessage(task)] };
|
|
49
|
+
if (again?.result?.state === "pass") {
|
|
50
|
+
delete outcome.failures[task.id];
|
|
51
|
+
outcome.flaky.push({ attempts: prior.attempts + 1, classname, file: path, messages: prior.messages, name });
|
|
52
|
+
outcome.summary(`- Flaky: ${classname} — ${name}`);
|
|
53
|
+
}
|
|
54
|
+
else if (again?.result?.state === "fail") {
|
|
55
|
+
outcome.failures[task.id] = { attempts: prior.attempts + 1, messages: [...prior.messages, failureMessage(again)] };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function mergeFile(file, next, outcome) {
|
|
60
|
+
const original = tests(file.tasks);
|
|
61
|
+
const retried = tests(next.tasks);
|
|
62
|
+
if (original.some((test) => !retried.some((item) => item.id === test.id))) {
|
|
63
|
+
throw new Error(`Rerun did not collect every original test in ${file.filepath}`);
|
|
64
|
+
}
|
|
65
|
+
const ranTests = retried.some((test) => ["pass", "fail"].includes(test.result?.state ?? "") && original.some((item) => item.id === test.id && item.result?.state !== "pass"));
|
|
66
|
+
recordAttempts(file, retried, outcome);
|
|
67
|
+
if (original.length === 0 && next.result?.state === "pass") {
|
|
68
|
+
outcome.summary(`- Flaky: ${junitClassname(relative(outcome.root, file.filepath), file.projectName ?? "")} — collection failure`);
|
|
69
|
+
}
|
|
70
|
+
else if (original.length > 0) {
|
|
71
|
+
restorePassed(file.tasks, next.tasks);
|
|
72
|
+
}
|
|
73
|
+
finishFile(file, next, ranTests);
|
|
74
|
+
}
|
|
75
|
+
export function mergeAttempt(previous, rerun, root, summary) {
|
|
76
|
+
const outcome = { failures: { ...previous.failures }, flaky: [...previous.flaky], root, summary };
|
|
77
|
+
const files = previous.files.map((file) => {
|
|
78
|
+
const next = rerun.find((item) => item.id === file.id);
|
|
79
|
+
if (next === undefined) {
|
|
80
|
+
return file;
|
|
81
|
+
}
|
|
82
|
+
mergeFile(file, next, outcome);
|
|
83
|
+
return next;
|
|
84
|
+
});
|
|
85
|
+
return { failures: outcome.failures, files, flaky: outcome.flaky };
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=mergeAttempt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mergeAttempt.js","sourceRoot":"","sources":["../../src/internal/mergeAttempt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function reportPaths(outputDir: string): {
|
|
2
|
+
flaky: string;
|
|
3
|
+
json: string;
|
|
4
|
+
junit: string;
|
|
5
|
+
rerunCache: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function attemptPaths(outputDir: string, attempt: number): {
|
|
8
|
+
json: string;
|
|
9
|
+
junit: string;
|
|
10
|
+
snapshot: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const ATTEMPT_REPORT: RegExp;
|
|
13
|
+
//# sourceMappingURL=reportPaths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reportPaths.d.ts","sourceRoot":"","sources":["../../src/internal/reportPaths.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM;IAE3C,KAAK;IACL,IAAI;IACJ,KAAK;IACL,UAAU;EAEX;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAE7D,IAAI;IACJ,KAAK;IACL,QAAQ;EAET;AAED,eAAO,MAAM,cAAc,QAAmD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
export function reportPaths(outputDir) {
|
|
3
|
+
return {
|
|
4
|
+
flaky: join(outputDir, "flaky-tests.json"),
|
|
5
|
+
json: join(outputDir, "tests.json"),
|
|
6
|
+
junit: join(outputDir, "tests.junit.xml"),
|
|
7
|
+
rerunCache: join(outputDir, "vite-rerun"),
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function attemptPaths(outputDir, attempt) {
|
|
11
|
+
return {
|
|
12
|
+
json: join(outputDir, `tests.attempt-${attempt}.json`),
|
|
13
|
+
junit: join(outputDir, `tests.attempt-${attempt}.junit.xml`),
|
|
14
|
+
snapshot: join(outputDir, `tests.attempt-${attempt}.bin`),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export const ATTEMPT_REPORT = /^tests\.attempt-\d+\.(?:json|junit\.xml|bin)$/u;
|
|
18
|
+
//# sourceMappingURL=reportPaths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reportPaths.js","sourceRoot":"","sources":["../../src/internal/reportPaths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC5C,OAAO;QACN,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC;QAC1C,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC;QACnC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC;QACzC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC;KACzC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAiB,EAAE,OAAe;IAC9D,OAAO;QACN,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,iBAAiB,OAAO,OAAO,CAAC;QACtD,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,iBAAiB,OAAO,YAAY,CAAC;QAC5D,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,iBAAiB,OAAO,MAAM,CAAC;KACzD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,gDAAgD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Config, Effect, FileSystem, Schema } from "effect";
|
|
2
|
+
export interface Attempt {
|
|
3
|
+
readonly attempt: number;
|
|
4
|
+
readonly outputDir: string;
|
|
5
|
+
readonly vitestArgs: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
export declare const runAttempt: (input: Attempt) => Effect.Effect<boolean, Config.ConfigError | import("effect/PlatformError").PlatformError | Schema.SchemaError | import("#error.ts").VitestRerunError, FileSystem.FileSystem>;
|
|
8
|
+
//# sourceMappingURL=runAttempt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runAttempt.d.ts","sourceRoot":"","sources":["../../src/internal/runAttempt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAW,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAWrE,MAAM,WAAW,OAAO;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAiGD,eAAO,MAAM,UAAU,kMAaN,CAAC"}
|