donobu 5.60.1 → 5.60.3
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/dist/cli/donobu-cli.js +158 -52
- package/dist/envVars.d.ts +4 -0
- package/dist/envVars.js +12 -0
- package/dist/esm/cli/donobu-cli.js +158 -52
- package/dist/esm/envVars.d.ts +4 -0
- package/dist/esm/envVars.js +12 -0
- package/dist/esm/lib/page/extendPage.d.ts +6 -0
- package/dist/esm/lib/page/extendPage.js +24 -1
- package/dist/esm/lib/test/healRerunGate.d.ts +102 -0
- package/dist/esm/lib/test/healRerunGate.js +228 -0
- package/dist/esm/lib/test/testExtension.d.ts +1 -0
- package/dist/esm/lib/test/testExtension.js +20 -10
- package/dist/esm/managers/DonobuStack.d.ts +19 -19
- package/dist/esm/reporter/buildReport.js +54 -1
- package/dist/esm/reporter/merge.d.ts +1 -6
- package/dist/esm/reporter/merge.js +57 -35
- package/dist/esm/reporter/model.d.ts +16 -0
- package/dist/esm/reporter/model.js +10 -1
- package/dist/esm/reporter/render.js +34 -12
- package/dist/esm/reporter/renderMarkdown.js +148 -93
- package/dist/esm/reporter/renderSlack.js +39 -28
- package/dist/esm/reporter/reportWalk.d.ts +16 -6
- package/dist/esm/reporter/reportWalk.js +63 -13
- package/dist/esm/utils/BrowserUtils.d.ts +4 -4
- package/dist/lib/page/extendPage.d.ts +6 -0
- package/dist/lib/page/extendPage.js +24 -1
- package/dist/lib/test/healRerunGate.d.ts +102 -0
- package/dist/lib/test/healRerunGate.js +228 -0
- package/dist/lib/test/testExtension.d.ts +1 -0
- package/dist/lib/test/testExtension.js +20 -10
- package/dist/managers/DonobuStack.d.ts +19 -19
- package/dist/reporter/buildReport.js +54 -1
- package/dist/reporter/merge.d.ts +1 -6
- package/dist/reporter/merge.js +57 -35
- package/dist/reporter/model.d.ts +16 -0
- package/dist/reporter/model.js +10 -1
- package/dist/reporter/render.js +34 -12
- package/dist/reporter/renderMarkdown.js +148 -93
- package/dist/reporter/renderSlack.js +39 -28
- package/dist/reporter/reportWalk.d.ts +16 -6
- package/dist/reporter/reportWalk.js +63 -13
- package/dist/utils/BrowserUtils.d.ts +4 -4
- package/package.json +4 -4
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Shared helpers for walking a `DonobuReport` and classifying
|
|
3
|
-
* the tests inside it. Used by every renderer (HTML, Markdown, Slack)
|
|
4
|
-
* all agree on "what counts as self-healed"
|
|
3
|
+
* the tests inside it. Used by every renderer (HTML, Markdown, Slack) and the
|
|
4
|
+
* merge step's stats so they all agree on "what counts as self-healed",
|
|
5
|
+
* "what counts as flaky", and how suites nest.
|
|
5
6
|
*/
|
|
6
7
|
/**
|
|
7
8
|
* Recursively collect all specs from a suite and its nested sub-suites. The
|
|
@@ -18,11 +19,20 @@ export declare function collectSpecs(suite: any): any[];
|
|
|
18
19
|
*/
|
|
19
20
|
export declare function isSelfHealed(test: any): boolean;
|
|
20
21
|
/** Normalized test-status the renderers use for counts and labels. */
|
|
21
|
-
export type NormalizedStatus = 'passed' | 'failed' | 'healed' | 'timedOut' | 'skipped' | 'interrupted' | 'unknown';
|
|
22
|
+
export type NormalizedStatus = 'passed' | 'flaky' | 'expectedFailure' | 'failed' | 'healed' | 'timedOut' | 'skipped' | 'interrupted' | 'unknown';
|
|
22
23
|
/**
|
|
23
|
-
* Derive the display status for a test
|
|
24
|
-
*
|
|
25
|
-
*
|
|
24
|
+
* Derive the display status for a test from its full attempt history, not
|
|
25
|
+
* just the final attempt. The distinctions that matter:
|
|
26
|
+
*
|
|
27
|
+
* - A trailing `skipped` attempt must NOT erase an earlier real failure. An
|
|
28
|
+
* auto-heal rerun in which the test skipped itself (e.g. a precondition
|
|
29
|
+
* guard fired because a prerequisite test wasn't part of the rerun) appends
|
|
30
|
+
* a skipped result after genuine failures — the failure stands.
|
|
31
|
+
* - A failed-then-passed history is `'flaky'` (Playwright's own term), not a
|
|
32
|
+
* plain pass — unless the self-heal signal is present, which wins.
|
|
33
|
+
* - A test whose final attempt matches its `expectedStatus` (e.g.
|
|
34
|
+
* `test.fail()` specs) is an `'expectedFailure'`: expected for stats and
|
|
35
|
+
* exit-code purposes, but never presented as a pass.
|
|
26
36
|
*/
|
|
27
37
|
export declare function statusOf(test: any): NormalizedStatus;
|
|
28
38
|
//# sourceMappingURL=reportWalk.d.ts.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* @fileoverview Shared helpers for walking a `DonobuReport` and classifying
|
|
4
|
-
* the tests inside it. Used by every renderer (HTML, Markdown, Slack)
|
|
5
|
-
* all agree on "what counts as self-healed"
|
|
4
|
+
* the tests inside it. Used by every renderer (HTML, Markdown, Slack) and the
|
|
5
|
+
* merge step's stats so they all agree on "what counts as self-healed",
|
|
6
|
+
* "what counts as flaky", and how suites nest.
|
|
6
7
|
*/
|
|
7
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
9
|
exports.collectSpecs = collectSpecs;
|
|
@@ -32,28 +33,77 @@ function isSelfHealed(test) {
|
|
|
32
33
|
const hasAnnotation = annotations.some((a) => a?.type === 'self-healed');
|
|
33
34
|
return hasAnnotation || test?.donobuStatus === 'healed';
|
|
34
35
|
}
|
|
36
|
+
const FAILURE_RESULT_STATUSES = new Set(['failed', 'timedOut', 'interrupted']);
|
|
35
37
|
/**
|
|
36
|
-
* Derive the display status for a test
|
|
37
|
-
*
|
|
38
|
-
*
|
|
38
|
+
* Derive the display status for a test from its full attempt history, not
|
|
39
|
+
* just the final attempt. The distinctions that matter:
|
|
40
|
+
*
|
|
41
|
+
* - A trailing `skipped` attempt must NOT erase an earlier real failure. An
|
|
42
|
+
* auto-heal rerun in which the test skipped itself (e.g. a precondition
|
|
43
|
+
* guard fired because a prerequisite test wasn't part of the rerun) appends
|
|
44
|
+
* a skipped result after genuine failures — the failure stands.
|
|
45
|
+
* - A failed-then-passed history is `'flaky'` (Playwright's own term), not a
|
|
46
|
+
* plain pass — unless the self-heal signal is present, which wins.
|
|
47
|
+
* - A test whose final attempt matches its `expectedStatus` (e.g.
|
|
48
|
+
* `test.fail()` specs) is an `'expectedFailure'`: expected for stats and
|
|
49
|
+
* exit-code purposes, but never presented as a pass.
|
|
39
50
|
*/
|
|
40
51
|
function statusOf(test) {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
const results = test?.results ?? [];
|
|
53
|
+
const lastResult = results.at?.(-1);
|
|
54
|
+
// No attempts recorded — Playwright reports statically-skipped tests this
|
|
55
|
+
// way (and `test.status === 'skipped'` for runtime skips with no results).
|
|
56
|
+
if (!lastResult) {
|
|
44
57
|
return 'skipped';
|
|
45
58
|
}
|
|
46
59
|
if (isSelfHealed(test)) {
|
|
47
60
|
return 'healed';
|
|
48
61
|
}
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
const expectedStatus = test?.expectedStatus;
|
|
63
|
+
// An attempt "succeeded" when it passed outright, or when it landed on the
|
|
64
|
+
// declared expected outcome of a `test.fail()`-style spec. The two are kept
|
|
65
|
+
// distinct end-to-end: expected failures count as expected for stats and
|
|
66
|
+
// exit codes, but are never presented as passes.
|
|
67
|
+
const successKindOf = (result) => {
|
|
68
|
+
if (result?.status === 'passed') {
|
|
69
|
+
return 'passed';
|
|
70
|
+
}
|
|
71
|
+
if (expectedStatus !== undefined &&
|
|
72
|
+
expectedStatus !== 'passed' &&
|
|
73
|
+
expectedStatus !== 'skipped' &&
|
|
74
|
+
result?.status === expectedStatus) {
|
|
75
|
+
return 'expectedFailure';
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
};
|
|
79
|
+
const hadRealFailure = results.some((r) => FAILURE_RESULT_STATUSES.has(r?.status) && successKindOf(r) === null);
|
|
80
|
+
// A success anywhere in the history. Within a single run retries stop at
|
|
81
|
+
// the first success, so a success followed by a failure/skip only arises
|
|
82
|
+
// from a merged auto-heal rerun — and the rerun is advisory: it may flip a
|
|
83
|
+
// failure to healed but never an initial success to failed/skipped.
|
|
84
|
+
const priorSuccess = results.map(successKindOf).find((kind) => kind !== null) ?? null;
|
|
85
|
+
// Skips are handled first: a runtime-skipped test has
|
|
86
|
+
// `expectedStatus: 'skipped'` and must stay skipped.
|
|
87
|
+
if (lastResult.status === 'skipped') {
|
|
88
|
+
// A skip can't launder an earlier failure; surface the worst attempt.
|
|
89
|
+
if (hadRealFailure) {
|
|
90
|
+
const failure = results.find((r) => FAILURE_RESULT_STATUSES.has(r?.status) && successKindOf(r) === null);
|
|
91
|
+
return failure.status;
|
|
92
|
+
}
|
|
93
|
+
return priorSuccess ?? 'skipped';
|
|
94
|
+
}
|
|
95
|
+
const lastSuccess = successKindOf(lastResult);
|
|
96
|
+
if (lastSuccess === 'passed') {
|
|
97
|
+
return hadRealFailure ? 'flaky' : 'passed';
|
|
98
|
+
}
|
|
99
|
+
if (lastSuccess === 'expectedFailure') {
|
|
100
|
+
return 'expectedFailure';
|
|
101
|
+
}
|
|
102
|
+
switch (lastResult.status) {
|
|
52
103
|
case 'failed':
|
|
53
104
|
case 'timedOut':
|
|
54
|
-
case 'skipped':
|
|
55
105
|
case 'interrupted':
|
|
56
|
-
return status;
|
|
106
|
+
return priorSuccess ?? lastResult.status;
|
|
57
107
|
default:
|
|
58
108
|
return 'unknown';
|
|
59
109
|
}
|
|
@@ -71,10 +71,10 @@ export declare class BrowserUtils {
|
|
|
71
71
|
* @throws {InvalidParamValueException} When an invalid browser type is specified.
|
|
72
72
|
*/
|
|
73
73
|
static create(browserConfig: BrowserConfig, videoDir?: string, storageState?: BrowserStorageState, environ?: import("env-struct").Env<{
|
|
74
|
-
BROWSERBASE_API_KEY: import("zod
|
|
75
|
-
PROXY_SERVER: import("zod
|
|
76
|
-
PROXY_USERNAME: import("zod
|
|
77
|
-
PROXY_PASSWORD: import("zod
|
|
74
|
+
BROWSERBASE_API_KEY: import("zod").ZodOptional<import("zod").ZodString>;
|
|
75
|
+
PROXY_SERVER: import("zod").ZodOptional<import("zod").ZodString>;
|
|
76
|
+
PROXY_USERNAME: import("zod").ZodOptional<import("zod").ZodString>;
|
|
77
|
+
PROXY_PASSWORD: import("zod").ZodOptional<import("zod").ZodString>;
|
|
78
78
|
}, {
|
|
79
79
|
BROWSERBASE_API_KEY?: string | undefined;
|
|
80
80
|
PROXY_SERVER?: string | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "donobu",
|
|
3
|
-
"version": "5.60.
|
|
3
|
+
"version": "5.60.3",
|
|
4
4
|
"description": "Create browser automations with an LLM agent and replay them as Playwright scripts.",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"module": "dist/esm/main.js",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"license": "UNLICENSED",
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@eslint/js": "^10.0.1",
|
|
49
|
-
"@playwright/test": "^1.
|
|
49
|
+
"@playwright/test": "^1.60.0",
|
|
50
50
|
"@types/better-sqlite3": "^7.6.13",
|
|
51
51
|
"@types/express": "^5.0.6",
|
|
52
52
|
"@types/node": "^22.10.5",
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"eslint-plugin-perfectionist": "^5.9.0",
|
|
60
60
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
61
61
|
"globals": "^16.0.0",
|
|
62
|
-
"playwright": "^1.
|
|
63
|
-
"playwright-core": "^1.
|
|
62
|
+
"playwright": "^1.60.0",
|
|
63
|
+
"playwright-core": "^1.60.0",
|
|
64
64
|
"typescript-eslint": "^8.47.0",
|
|
65
65
|
"vitest": "^4.0.17",
|
|
66
66
|
"winston-transport": "^4.9.0"
|