@molecule/api-ai-tools 1.16.7 → 1.17.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 +341 -5
- package/dist/backends/local.d.ts.map +1 -1
- package/dist/backends/local.js +60 -14
- package/dist/command-plan.d.ts +71 -0
- package/dist/command-plan.d.ts.map +1 -0
- package/dist/command-plan.js +116 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/playwright-feedback-reporter.d.ts +16 -0
- package/dist/playwright-feedback-reporter.d.ts.map +1 -0
- package/dist/playwright-feedback-reporter.js +79 -0
- package/dist/playwright-feedback-selection.d.ts +13 -0
- package/dist/playwright-feedback-selection.d.ts.map +1 -0
- package/dist/playwright-feedback-selection.js +206 -0
- package/dist/playwright-feedback-types.d.ts +65 -0
- package/dist/playwright-feedback-types.d.ts.map +1 -0
- package/dist/playwright-feedback-types.js +1 -0
- package/dist/playwright-feedback.d.ts +42 -0
- package/dist/playwright-feedback.d.ts.map +1 -0
- package/dist/playwright-feedback.js +318 -0
- package/dist/suite-overlap.d.ts.map +1 -1
- package/dist/suite-overlap.js +2 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +49 -21
- package/dist/trace-artifacts.d.ts.map +1 -1
- package/dist/trace-artifacts.js +2 -1
- package/dist/utilities.d.ts +4 -1
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +14 -1
- package/package.json +5 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/** Logical commands and ordered log boundaries for launchers that execute opaque wrappers. */
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { gunzipSync, gzipSync } from 'node:zlib';
|
|
4
|
+
const HEADER = '# mol-command-plan-v1 ';
|
|
5
|
+
const TRUNCATED = '__MOL_COMMAND_LOG_TRUNCATED__';
|
|
6
|
+
/**
|
|
7
|
+
* Give already-prepared logical commands unique log boundaries.
|
|
8
|
+
* @param steps - Commands in execution order.
|
|
9
|
+
* @returns Metadata for the wrapper and the launcher that executes its steps.
|
|
10
|
+
*/
|
|
11
|
+
export function createCommandPlan(steps) {
|
|
12
|
+
const id = randomUUID();
|
|
13
|
+
return {
|
|
14
|
+
id,
|
|
15
|
+
steps: steps.map((step, index) => ({
|
|
16
|
+
...step,
|
|
17
|
+
startMarker: `__MOL_COMMAND_STEP_${id}_${index}_START__`,
|
|
18
|
+
endMarker: `__MOL_COMMAND_STEP_${id}_${index}_END__`,
|
|
19
|
+
})),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Preserve a wrapper's typed logical plan in its durable shell script, including across restarts.
|
|
24
|
+
* Shell comments keep this independent of the wrapper's executable, arguments and payload format.
|
|
25
|
+
* @param command - Executed wrapper.
|
|
26
|
+
* @param plan - Commands the launcher will actually execute and delimit.
|
|
27
|
+
* @returns A shell command with a passive metadata header.
|
|
28
|
+
*/
|
|
29
|
+
export function commandWithPlan(command, plan) {
|
|
30
|
+
return `${HEADER}${gzipSync(JSON.stringify(plan)).toString('base64')}\n${command}`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Read the shared descriptor, never a launcher's private wrapper format.
|
|
34
|
+
* @param command - Command or recovered task script.
|
|
35
|
+
* @returns A valid logical plan, or null for an ordinary command.
|
|
36
|
+
*/
|
|
37
|
+
export function commandPlan(command) {
|
|
38
|
+
const header = command.split('\n').find((line) => line.startsWith(HEADER));
|
|
39
|
+
if (!header || header.length > 1024 * 1024)
|
|
40
|
+
return null;
|
|
41
|
+
try {
|
|
42
|
+
const plan = JSON.parse(gunzipSync(Buffer.from(header.slice(HEADER.length), 'base64'), {
|
|
43
|
+
maxOutputLength: 1024 * 1024,
|
|
44
|
+
}).toString('utf8'));
|
|
45
|
+
if (!plan ||
|
|
46
|
+
!/^[a-f0-9-]{36}$/.test(plan.id) ||
|
|
47
|
+
!Array.isArray(plan.steps) ||
|
|
48
|
+
plan.steps.length === 0 ||
|
|
49
|
+
!plan.steps.every((step, index) => typeof step?.id === 'string' &&
|
|
50
|
+
typeof step.command === 'string' &&
|
|
51
|
+
step.startMarker === `__MOL_COMMAND_STEP_${plan.id}_${index}_START__` &&
|
|
52
|
+
step.endMarker === `__MOL_COMMAND_STEP_${plan.id}_${index}_END__`))
|
|
53
|
+
return null;
|
|
54
|
+
return plan;
|
|
55
|
+
}
|
|
56
|
+
catch (_error) {
|
|
57
|
+
// Metadata is advisory. An absent or malformed descriptor supplies no logical commands.
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Commands a wrapper will run, for static classification; live diagnostics use commandStepView.
|
|
63
|
+
* @param command - Executed command.
|
|
64
|
+
* @returns Logical commands in order, or the direct command unchanged.
|
|
65
|
+
*/
|
|
66
|
+
export function logicalCommandText(command) {
|
|
67
|
+
return (commandPlan(command)
|
|
68
|
+
?.steps.map((step) => step.command)
|
|
69
|
+
.join(';\n') ?? command);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Select only the step that owns the latest log boundary. Completed steps cannot supply a live
|
|
73
|
+
* failure, target, retry policy, file selection or rerun. Before the first boundary and between
|
|
74
|
+
* steps the live command is unknown; no diagnostic is permitted.
|
|
75
|
+
* @param command - Wrapper or direct command.
|
|
76
|
+
* @param output - Whole log, or the boundary-preserving bounded read.
|
|
77
|
+
* @returns Active command and its output, plus whether the entire step's output is available.
|
|
78
|
+
*/
|
|
79
|
+
export function commandStepView(command, output) {
|
|
80
|
+
const plan = commandPlan(command);
|
|
81
|
+
if (!plan)
|
|
82
|
+
return { command, output, complete: true };
|
|
83
|
+
let at = -1;
|
|
84
|
+
let selected;
|
|
85
|
+
let offset = 0;
|
|
86
|
+
for (const line of output.split('\n')) {
|
|
87
|
+
for (const step of plan.steps) {
|
|
88
|
+
if (line === step.startMarker || line === step.endMarker) {
|
|
89
|
+
at = offset + line.length + 1;
|
|
90
|
+
selected = line === step.startMarker ? step : undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
offset += line.length + 1;
|
|
94
|
+
}
|
|
95
|
+
const text = selected && at >= 0 ? output.slice(at) : '';
|
|
96
|
+
return {
|
|
97
|
+
stepKey: selected?.startMarker,
|
|
98
|
+
command: selected?.command ?? '',
|
|
99
|
+
output: text.replace(`${TRUNCATED}\n`, ''),
|
|
100
|
+
complete: !text.startsWith(TRUNCATED),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* AWK program for a bounded read that retains the active boundary even after a long step and
|
|
105
|
+
* discards prior steps. A truncated step cannot establish a universal failure across its history.
|
|
106
|
+
* @param plan - Logical plan whose boundaries the launcher emits.
|
|
107
|
+
* @param limit - Maximum output characters retained for diagnosis.
|
|
108
|
+
* @returns An AWK program; callers shell-quote it like every other argument.
|
|
109
|
+
*/
|
|
110
|
+
export function commandPlanLogRead(plan, limit) {
|
|
111
|
+
const markers = plan.steps.flatMap((step) => [step.startMarker, step.endMarker]);
|
|
112
|
+
return (`BEGIN { ${markers.map((marker) => `marks["${marker}"]=1`).join('; ')} }\n` +
|
|
113
|
+
'$0 in marks { marker=$0; text=""; cut=0; next }\n' +
|
|
114
|
+
`{ text=text $0 "\\n"; if(length(text)>${limit}) { text=substr(text,length(text)-${limit}+1); cut=1 } }\n` +
|
|
115
|
+
`END { if(marker!="") { print marker; if(cut) print "${TRUNCATED}"; printf "%s",text } }`);
|
|
116
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,19 @@
|
|
|
12
12
|
* (identity, tool listing, project docs, discovered skills).
|
|
13
13
|
*
|
|
14
14
|
* @remarks
|
|
15
|
+
* - **Background Playwright feedback:** `createPlaywrightFeedback({ load, run, onFailures })`
|
|
16
|
+
* coalesces `changed(paths)` events without delaying writes. Use `readFeedbackSources`
|
|
17
|
+
* to batch source reads over either backend and `runPlaywrightFeedback` to run each
|
|
18
|
+
* supplied spec through its native command. Its incremental reporter supplies exact
|
|
19
|
+
* locator failures and the failure-time page snapshot. Healthy runs emit no note;
|
|
20
|
+
* no suite schedules no runner. `settled()`/`close()` are for tests and shutdown,
|
|
21
|
+
* never a deployment barrier. Diagnoses are not whole-suite completion proof.
|
|
22
|
+
* - **Opaque command plans:** prepare each logical step with `streamingBackgroundCommand`,
|
|
23
|
+
* call `createCommandPlan`, and attach it to the executed wrapper with `commandWithPlan`.
|
|
24
|
+
* The launcher prints each step's `startMarker` and `endMarker` on their own lines around
|
|
25
|
+
* execution. `commandStepView` reads the active step for diagnostics; `logicalCommandText`
|
|
26
|
+
* exposes the planned commands for static classification. Preserve the descriptor when
|
|
27
|
+
* wrapping again. The metadata is advisory and never establishes a completed test result.
|
|
15
28
|
* - **`yieldOnFirstFailureFor`** can yield one still-running deployed task's concrete diagnostic; callers opt out after a prior wait result or unknown history.
|
|
16
29
|
* - **`wait_for_task` state probes report current progress without guessing log growth.**
|
|
17
30
|
* A call shorter than one normal two-second poll omits both growth and no-growth
|
|
@@ -149,6 +162,7 @@ export * from './backends/local.js';
|
|
|
149
162
|
export * from './backends/sandbox.js';
|
|
150
163
|
export * from './browser-guard.js';
|
|
151
164
|
export * from './browser-probe.js';
|
|
165
|
+
export * from './command-plan.js';
|
|
152
166
|
export * from './command-position.js';
|
|
153
167
|
export * from './cut-run.js';
|
|
154
168
|
export * from './failure-kind.js';
|
|
@@ -158,6 +172,9 @@ export * from './line-diff.js';
|
|
|
158
172
|
export * from './no-test-run.js';
|
|
159
173
|
export * from './output-filter.js';
|
|
160
174
|
export * from './pipeline-exit-note.js';
|
|
175
|
+
export * from './playwright-feedback.js';
|
|
176
|
+
export * from './playwright-feedback-selection.js';
|
|
177
|
+
export * from './playwright-feedback-types.js';
|
|
161
178
|
export * from './playwright-report.js';
|
|
162
179
|
export * from './schemas.js';
|
|
163
180
|
export * from './server-command.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+JG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,oCAAoC,CAAA;AAClD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA;AACpC,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,19 @@
|
|
|
12
12
|
* (identity, tool listing, project docs, discovered skills).
|
|
13
13
|
*
|
|
14
14
|
* @remarks
|
|
15
|
+
* - **Background Playwright feedback:** `createPlaywrightFeedback({ load, run, onFailures })`
|
|
16
|
+
* coalesces `changed(paths)` events without delaying writes. Use `readFeedbackSources`
|
|
17
|
+
* to batch source reads over either backend and `runPlaywrightFeedback` to run each
|
|
18
|
+
* supplied spec through its native command. Its incremental reporter supplies exact
|
|
19
|
+
* locator failures and the failure-time page snapshot. Healthy runs emit no note;
|
|
20
|
+
* no suite schedules no runner. `settled()`/`close()` are for tests and shutdown,
|
|
21
|
+
* never a deployment barrier. Diagnoses are not whole-suite completion proof.
|
|
22
|
+
* - **Opaque command plans:** prepare each logical step with `streamingBackgroundCommand`,
|
|
23
|
+
* call `createCommandPlan`, and attach it to the executed wrapper with `commandWithPlan`.
|
|
24
|
+
* The launcher prints each step's `startMarker` and `endMarker` on their own lines around
|
|
25
|
+
* execution. `commandStepView` reads the active step for diagnostics; `logicalCommandText`
|
|
26
|
+
* exposes the planned commands for static classification. Preserve the descriptor when
|
|
27
|
+
* wrapping again. The metadata is advisory and never establishes a completed test result.
|
|
15
28
|
* - **`yieldOnFirstFailureFor`** can yield one still-running deployed task's concrete diagnostic; callers opt out after a prior wait result or unknown history.
|
|
16
29
|
* - **`wait_for_task` state probes report current progress without guessing log growth.**
|
|
17
30
|
* A call shorter than one normal two-second poll omits both growth and no-growth
|
|
@@ -149,6 +162,7 @@ export * from './backends/local.js';
|
|
|
149
162
|
export * from './backends/sandbox.js';
|
|
150
163
|
export * from './browser-guard.js';
|
|
151
164
|
export * from './browser-probe.js';
|
|
165
|
+
export * from './command-plan.js';
|
|
152
166
|
export * from './command-position.js';
|
|
153
167
|
export * from './cut-run.js';
|
|
154
168
|
export * from './failure-kind.js';
|
|
@@ -158,6 +172,9 @@ export * from './line-diff.js';
|
|
|
158
172
|
export * from './no-test-run.js';
|
|
159
173
|
export * from './output-filter.js';
|
|
160
174
|
export * from './pipeline-exit-note.js';
|
|
175
|
+
export * from './playwright-feedback.js';
|
|
176
|
+
export * from './playwright-feedback-selection.js';
|
|
177
|
+
export * from './playwright-feedback-types.js';
|
|
161
178
|
export * from './playwright-report.js';
|
|
162
179
|
export * from './schemas.js';
|
|
163
180
|
export * from './server-command.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PlaywrightFeedbackFailure } from './playwright-feedback-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A standard Playwright reporter, placed beside each run's private outputs. It
|
|
4
|
+
* records onTestEnd, so the first exact failure need not wait for the rest of
|
|
5
|
+
* the spec file. No page injection, test rewrite, screenshots or trace overhead.
|
|
6
|
+
* @returns A CommonJS reporter loadable by the project's installed Playwright.
|
|
7
|
+
*/
|
|
8
|
+
export declare function feedbackReporterSource(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Read native failure events; incomplete final lines wait for the next read.
|
|
11
|
+
* @param text - Reporter JSONL, not runner-log inference.
|
|
12
|
+
* @param sourceFiles - Triggering source files from the scheduler.
|
|
13
|
+
* @returns Locator failures only, redacted and bounded.
|
|
14
|
+
*/
|
|
15
|
+
export declare function nativeFeedbackFailures(text: string, sourceFiles: string[]): PlaywrightFeedbackFailure[];
|
|
16
|
+
//# sourceMappingURL=playwright-feedback-reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-feedback-reporter.d.ts","sourceRoot":"","sources":["../src/playwright-feedback-reporter.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAA;AAG/E;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAyB/C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EAAE,GACpB,yBAAyB,EAAE,CAsC7B"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Playwright events for incremental background feedback.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { stripVTControlCharacters } from 'node:util';
|
|
7
|
+
import { redactSecrets } from './utilities.js';
|
|
8
|
+
/**
|
|
9
|
+
* A standard Playwright reporter, placed beside each run's private outputs. It
|
|
10
|
+
* records onTestEnd, so the first exact failure need not wait for the rest of
|
|
11
|
+
* the spec file. No page injection, test rewrite, screenshots or trace overhead.
|
|
12
|
+
* @returns A CommonJS reporter loadable by the project's installed Playwright.
|
|
13
|
+
*/
|
|
14
|
+
export function feedbackReporterSource() {
|
|
15
|
+
return String.raw `
|
|
16
|
+
const fs = require('node:fs');
|
|
17
|
+
module.exports = class FeedbackReporter {
|
|
18
|
+
onTestEnd(test, result) {
|
|
19
|
+
if (result.status === test.expectedStatus || !['failed','timedOut'].includes(result.status)) return;
|
|
20
|
+
const errors = result.errors || [];
|
|
21
|
+
const error = errors.map(e => e.message || '').join('\n');
|
|
22
|
+
const location = [...errors].reverse().find(e => e.location)?.location || test.location;
|
|
23
|
+
const attachment = result.attachments.find(a => a.name === 'error-context' && a.path);
|
|
24
|
+
let rendered;
|
|
25
|
+
if (attachment) try {
|
|
26
|
+
const text = fs.readFileSync(attachment.path, 'utf8');
|
|
27
|
+
const fence = String.fromCharCode(96).repeat(3);
|
|
28
|
+
const yaml = text.split(fence + 'yaml\n')[1];
|
|
29
|
+
if (yaml) rendered = yaml.split(fence)[0].trim().slice(0, 2000);
|
|
30
|
+
else {
|
|
31
|
+
const section = text.split('# Page snapshot')[1];
|
|
32
|
+
if (section) rendered = section.split(fence)[1]?.split('\n').slice(1).join('\n').trim().slice(0, 2000);
|
|
33
|
+
}
|
|
34
|
+
} catch {}
|
|
35
|
+
if (process.env.MOL_TEST_FEEDBACK_EVENTS) fs.appendFileSync(process.env.MOL_TEST_FEEDBACK_EVENTS,
|
|
36
|
+
JSON.stringify({spec: location.file, line: location.line, error: error.slice(0, 6000), rendered}) + '\n');
|
|
37
|
+
}
|
|
38
|
+
};`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Read native failure events; incomplete final lines wait for the next read.
|
|
42
|
+
* @param text - Reporter JSONL, not runner-log inference.
|
|
43
|
+
* @param sourceFiles - Triggering source files from the scheduler.
|
|
44
|
+
* @returns Locator failures only, redacted and bounded.
|
|
45
|
+
*/
|
|
46
|
+
export function nativeFeedbackFailures(text, sourceFiles) {
|
|
47
|
+
const out = [];
|
|
48
|
+
if (text.length > 1_000_000)
|
|
49
|
+
return out;
|
|
50
|
+
for (const line of text.split('\n').slice(0, -1)) {
|
|
51
|
+
try {
|
|
52
|
+
const event = JSON.parse(line);
|
|
53
|
+
if (typeof event.spec !== 'string' ||
|
|
54
|
+
typeof event.line !== 'number' ||
|
|
55
|
+
typeof event.error !== 'string')
|
|
56
|
+
continue;
|
|
57
|
+
const error = redactSecrets(stripVTControlCharacters(event.error).slice(0, 6_000));
|
|
58
|
+
const locator = /(?:Locator:\s*|waiting for )(locator\([^\n]+|getBy[^\n]+)/.exec(error)?.[1] ??
|
|
59
|
+
/strict mode violation: ([^\n]+)/.exec(error)?.[1] ??
|
|
60
|
+
/(?:^|\n)((?:Error: )?expect\([^\n]+|AssertionError:[^\n]+)/.exec(error)?.[1];
|
|
61
|
+
if (!locator)
|
|
62
|
+
continue;
|
|
63
|
+
out.push({
|
|
64
|
+
spec: event.spec,
|
|
65
|
+
line: event.line,
|
|
66
|
+
error,
|
|
67
|
+
locator,
|
|
68
|
+
...(typeof event.rendered === 'string' && event.rendered
|
|
69
|
+
? { rendered: redactSecrets(event.rendered.slice(0, 2000)) }
|
|
70
|
+
: {}),
|
|
71
|
+
sourceFiles,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch (_error) {
|
|
75
|
+
/* not a completed native event */
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FeedbackProject, FeedbackSpec } from './playwright-feedback-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Prioritize spec files potentially affected by writes. Every file still runs: a click or
|
|
4
|
+
* a helper can navigate somewhere a literal-goto index cannot see. This index never excludes work.
|
|
5
|
+
* @param project - Caller-supplied source and runner inventory.
|
|
6
|
+
* @param changed - Absolute source paths changed since the previous diagnosis.
|
|
7
|
+
* @returns Spec files to run, with their rendering-source context.
|
|
8
|
+
*/
|
|
9
|
+
export declare function selectFeedbackSpecs(project: FeedbackProject, changed: readonly string[]): Array<{
|
|
10
|
+
spec: FeedbackSpec;
|
|
11
|
+
sourceFiles: string[];
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=playwright-feedback-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-feedback-selection.d.ts","sourceRoot":"","sources":["../src/playwright-feedback-selection.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,eAAe,EAAkB,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAsLnG;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,KAAK,CAAC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAwBtD"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prioritize native spec files from explicit route declarations and source imports.
|
|
3
|
+
* TypeScript parses syntax; Playwright judges behavior. Unreadable/dynamic routing
|
|
4
|
+
* falls back to all specs, rather than treating an absent index entry as coverage.
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
import { posix } from 'node:path';
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
let compiler;
|
|
11
|
+
const typescript = () => (compiler ??= require('typescript'));
|
|
12
|
+
/** Get the text of a literal or the static prefix of a route template. */
|
|
13
|
+
function routeText(node) {
|
|
14
|
+
const ts = typescript();
|
|
15
|
+
if (!node)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (ts.isJsxExpression(node))
|
|
18
|
+
return routeText(node.expression);
|
|
19
|
+
if (ts.isStringLiteralLike(node))
|
|
20
|
+
return node.text;
|
|
21
|
+
if (ts.isTemplateExpression(node))
|
|
22
|
+
return `${node.head.text}*`;
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
/** Parse each file once, resolving only relative source imports we actually have. */
|
|
26
|
+
function sourceIndex(files) {
|
|
27
|
+
const ts = typescript();
|
|
28
|
+
const trees = new Map(files.map((f) => [
|
|
29
|
+
f.path,
|
|
30
|
+
ts.createSourceFile(f.path, f.content, ts.ScriptTarget.Latest, true),
|
|
31
|
+
]));
|
|
32
|
+
const imports = new Map();
|
|
33
|
+
const dependencies = new Map();
|
|
34
|
+
for (const [file, tree] of trees) {
|
|
35
|
+
const names = new Map(), deps = new Set();
|
|
36
|
+
const resolve = (text) => {
|
|
37
|
+
if (!text.startsWith('.'))
|
|
38
|
+
return undefined;
|
|
39
|
+
const base = posix.resolve(posix.dirname(file), text);
|
|
40
|
+
return [
|
|
41
|
+
base,
|
|
42
|
+
base.replace(/\.[cm]?jsx?$/, '.ts'),
|
|
43
|
+
base.replace(/\.[cm]?jsx?$/, '.tsx'),
|
|
44
|
+
...['.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.tsx'].map((ext) => base + ext),
|
|
45
|
+
].find((p) => trees.has(p));
|
|
46
|
+
};
|
|
47
|
+
const visit = (node) => {
|
|
48
|
+
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
49
|
+
const target = resolve(node.moduleSpecifier.text);
|
|
50
|
+
if (target) {
|
|
51
|
+
deps.add(target);
|
|
52
|
+
const clause = node.importClause;
|
|
53
|
+
if (clause?.name)
|
|
54
|
+
names.set(clause.name.text, target);
|
|
55
|
+
if (clause?.namedBindings && ts.isNamedImports(clause.namedBindings))
|
|
56
|
+
for (const n of clause.namedBindings.elements)
|
|
57
|
+
names.set(n.name.text, target);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (ts.isExportDeclaration(node) &&
|
|
61
|
+
node.moduleSpecifier &&
|
|
62
|
+
ts.isStringLiteral(node.moduleSpecifier)) {
|
|
63
|
+
const target = resolve(node.moduleSpecifier.text);
|
|
64
|
+
if (target)
|
|
65
|
+
deps.add(target);
|
|
66
|
+
}
|
|
67
|
+
if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
|
|
68
|
+
const text = routeText(node.arguments[0]), target = text && resolve(text);
|
|
69
|
+
if (target)
|
|
70
|
+
deps.add(target);
|
|
71
|
+
}
|
|
72
|
+
ts.forEachChild(node, visit);
|
|
73
|
+
};
|
|
74
|
+
visit(tree);
|
|
75
|
+
imports.set(file, names);
|
|
76
|
+
dependencies.set(file, deps);
|
|
77
|
+
}
|
|
78
|
+
return { trees, imports, dependencies };
|
|
79
|
+
}
|
|
80
|
+
/** The explicit routes a module declares; unknown framework shapes remain unindexed. */
|
|
81
|
+
function routeFiles(files) {
|
|
82
|
+
const ts = typescript();
|
|
83
|
+
const { trees, imports, dependencies } = sourceIndex(files);
|
|
84
|
+
const out = [];
|
|
85
|
+
const closure = (file, seen) => {
|
|
86
|
+
if (seen.has(file))
|
|
87
|
+
return;
|
|
88
|
+
seen.add(file);
|
|
89
|
+
for (const dep of dependencies.get(file) ?? [])
|
|
90
|
+
closure(dep, seen);
|
|
91
|
+
};
|
|
92
|
+
for (const [file, tree] of trees) {
|
|
93
|
+
const add = (path, element) => {
|
|
94
|
+
const route = routeText(path);
|
|
95
|
+
// Relative and nested declarations need the router's own resolution. Do not guess it.
|
|
96
|
+
if (!route?.startsWith('/') || !element)
|
|
97
|
+
return;
|
|
98
|
+
const selected = new Set([file]);
|
|
99
|
+
const refs = (node) => {
|
|
100
|
+
if (ts.isIdentifier(node)) {
|
|
101
|
+
const target = imports.get(file)?.get(node.text);
|
|
102
|
+
if (target)
|
|
103
|
+
closure(target, selected);
|
|
104
|
+
}
|
|
105
|
+
ts.forEachChild(node, refs);
|
|
106
|
+
};
|
|
107
|
+
refs(element);
|
|
108
|
+
// A local component, namespace or lazy binding cannot be resolved narrowly here.
|
|
109
|
+
if (selected.size === 1)
|
|
110
|
+
closure(file, selected);
|
|
111
|
+
out.push({ route, files: selected });
|
|
112
|
+
};
|
|
113
|
+
const visit = (node) => {
|
|
114
|
+
if (ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)) {
|
|
115
|
+
const attrs = node.attributes.properties.filter(ts.isJsxAttribute);
|
|
116
|
+
const path = attrs.find((a) => a.name.getText(tree) === 'path')?.initializer;
|
|
117
|
+
const element = attrs.find((a) => /^(element|component|Component)$/.test(a.name.getText(tree)))?.initializer;
|
|
118
|
+
add(path, element);
|
|
119
|
+
}
|
|
120
|
+
if (ts.isObjectLiteralExpression(node)) {
|
|
121
|
+
const props = node.properties.filter(ts.isPropertyAssignment);
|
|
122
|
+
add(props.find((p) => p.name.getText(tree).replace(/['"]/g, '') === 'path')?.initializer, props.find((p) => /^(element|component|Component)$/.test(p.name.getText(tree).replace(/['"]/g, '')))?.initializer);
|
|
123
|
+
}
|
|
124
|
+
ts.forEachChild(node, visit);
|
|
125
|
+
};
|
|
126
|
+
visit(tree);
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
/** Goto targets in a spec and its supplied helpers. Unknown targets force a conservative run. */
|
|
131
|
+
function specRoutes(spec, index) {
|
|
132
|
+
const ts = typescript();
|
|
133
|
+
const { trees, dependencies } = index;
|
|
134
|
+
const seen = new Set(), routes = [];
|
|
135
|
+
let unknown = false;
|
|
136
|
+
const read = (file) => {
|
|
137
|
+
if (seen.has(file))
|
|
138
|
+
return;
|
|
139
|
+
seen.add(file);
|
|
140
|
+
const tree = trees.get(file);
|
|
141
|
+
if (!tree) {
|
|
142
|
+
unknown = true;
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const visit = (node) => {
|
|
146
|
+
if (ts.isCallExpression(node) &&
|
|
147
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
148
|
+
node.expression.name.text === 'goto') {
|
|
149
|
+
const route = routeText(node.arguments[0]);
|
|
150
|
+
if (route?.startsWith('/'))
|
|
151
|
+
routes.push(route.split('?')[0].split('#')[0]);
|
|
152
|
+
else
|
|
153
|
+
unknown = true;
|
|
154
|
+
}
|
|
155
|
+
ts.forEachChild(node, visit);
|
|
156
|
+
};
|
|
157
|
+
visit(tree);
|
|
158
|
+
for (const dep of dependencies.get(file) ?? [])
|
|
159
|
+
read(dep);
|
|
160
|
+
};
|
|
161
|
+
read(spec.path);
|
|
162
|
+
return { routes, unknown: unknown || routes.length === 0 };
|
|
163
|
+
}
|
|
164
|
+
/** Compare route patterns for selection only, never for a correctness claim. */
|
|
165
|
+
function routeOverlaps(a, b) {
|
|
166
|
+
const left = a.split('/').filter(Boolean), right = b.split('/').filter(Boolean);
|
|
167
|
+
const n = Math.max(left.length, right.length);
|
|
168
|
+
for (let i = 0; i < n; i++) {
|
|
169
|
+
if (left[i] === '*' || right[i] === '*')
|
|
170
|
+
return true;
|
|
171
|
+
if (!left[i] || !right[i])
|
|
172
|
+
return false;
|
|
173
|
+
if (!left[i].startsWith(':') && !right[i].startsWith(':') && left[i] !== right[i])
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Prioritize spec files potentially affected by writes. Every file still runs: a click or
|
|
180
|
+
* a helper can navigate somewhere a literal-goto index cannot see. This index never excludes work.
|
|
181
|
+
* @param project - Caller-supplied source and runner inventory.
|
|
182
|
+
* @param changed - Absolute source paths changed since the previous diagnosis.
|
|
183
|
+
* @returns Spec files to run, with their rendering-source context.
|
|
184
|
+
*/
|
|
185
|
+
export function selectFeedbackSpecs(project, changed) {
|
|
186
|
+
if (project.specs.length === 0)
|
|
187
|
+
return [];
|
|
188
|
+
const routes = routeFiles(project.sources);
|
|
189
|
+
const affected = routes.filter((r) => changed.some((p) => r.files.has(p)));
|
|
190
|
+
const index = sourceIndex([...project.sources, ...project.specs]);
|
|
191
|
+
return project.specs
|
|
192
|
+
.map((spec) => {
|
|
193
|
+
const targets = specRoutes(spec, index);
|
|
194
|
+
const hits = affected.filter((r) => targets.routes.some((path) => routeOverlaps(r.route, path)));
|
|
195
|
+
return {
|
|
196
|
+
spec,
|
|
197
|
+
priority: hits.length,
|
|
198
|
+
sourceFiles: [
|
|
199
|
+
...new Set(hits.length
|
|
200
|
+
? hits.flatMap((r) => [...r.files]).filter((p) => changed.includes(p))
|
|
201
|
+
: changed),
|
|
202
|
+
],
|
|
203
|
+
};
|
|
204
|
+
})
|
|
205
|
+
.sort((a, b) => b.priority - a.priority);
|
|
206
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Playwright diagnosis while an app is being written.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { PlaywrightReportStats } from './playwright-report.js';
|
|
7
|
+
/** A source file already read by the caller. Paths are absolute. */
|
|
8
|
+
export interface FeedbackSource {
|
|
9
|
+
path: string;
|
|
10
|
+
content: string;
|
|
11
|
+
}
|
|
12
|
+
/** One supplied or scaffolded spec, with its normal, locally targeted runner command. */
|
|
13
|
+
export interface FeedbackSpec extends FeedbackSource {
|
|
14
|
+
command: string;
|
|
15
|
+
cwd: string;
|
|
16
|
+
}
|
|
17
|
+
/** The inputs the host already knows; no suite discovery or vendor selection in the scheduler. */
|
|
18
|
+
export interface FeedbackProject {
|
|
19
|
+
/** Base for relative source-change paths, already resolved by the host. */
|
|
20
|
+
root?: string;
|
|
21
|
+
sources: FeedbackSource[];
|
|
22
|
+
specs: FeedbackSpec[];
|
|
23
|
+
}
|
|
24
|
+
/** A native failure, never a static prediction or a completed-suite proof. */
|
|
25
|
+
export interface PlaywrightFeedbackFailure {
|
|
26
|
+
spec: string;
|
|
27
|
+
line: number;
|
|
28
|
+
error: string;
|
|
29
|
+
/** The native runner's locator or assertion, verbatim apart from redaction. */
|
|
30
|
+
locator: string;
|
|
31
|
+
/** Playwright's own failure-time accessibility snapshot, when recorded. */
|
|
32
|
+
rendered?: string;
|
|
33
|
+
/** Route render dependencies affected by this write, or the triggering source paths. */
|
|
34
|
+
sourceFiles: string[];
|
|
35
|
+
}
|
|
36
|
+
/** A diagnosis of one spec file at one source revision. A pass is not whole-suite proof. */
|
|
37
|
+
export interface PlaywrightFeedbackResult {
|
|
38
|
+
spec: string;
|
|
39
|
+
revision: number;
|
|
40
|
+
durationMs: number;
|
|
41
|
+
status: 'passed' | 'failed' | 'unavailable';
|
|
42
|
+
failures: PlaywrightFeedbackFailure[];
|
|
43
|
+
/** Native counts for this one diagnostic selection, never whole-suite proof. */
|
|
44
|
+
nativeStats?: PlaywrightReportStats;
|
|
45
|
+
reason?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Host operations for the same scheduler in a CLI process or a remote sandbox. */
|
|
48
|
+
export interface PlaywrightFeedbackOptions {
|
|
49
|
+
load: () => Promise<FeedbackProject>;
|
|
50
|
+
run: (spec: FeedbackSpec, sources: string[], revision: number, emit: (result: PlaywrightFeedbackResult) => void) => Promise<PlaywrightFeedbackResult>;
|
|
51
|
+
/** Only current native failures are delivered. Passing apps receive no note. */
|
|
52
|
+
onFailures?: (result: PlaywrightFeedbackResult) => void;
|
|
53
|
+
/** Operational state is separate from defect feedback. */
|
|
54
|
+
onResult?: (result: PlaywrightFeedbackResult) => void;
|
|
55
|
+
debounceMs?: number;
|
|
56
|
+
}
|
|
57
|
+
/** A nonblocking source-change subscription. */
|
|
58
|
+
export interface PlaywrightFeedback {
|
|
59
|
+
changed: (paths: readonly string[]) => void;
|
|
60
|
+
takeFailures: () => PlaywrightFeedbackResult[];
|
|
61
|
+
/** Wait only in tests or shutdown; file writes and deploys must never await this. */
|
|
62
|
+
settled: () => Promise<void>;
|
|
63
|
+
close: () => Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=playwright-feedback-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-feedback-types.d.ts","sourceRoot":"","sources":["../src/playwright-feedback-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAEnE,oEAAoE;AACpE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,yFAAyF;AACzF,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,kGAAkG;AAClG,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB;AAED,8EAA8E;AAC9E,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAA;IACf,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,wFAAwF;IACxF,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB;AAED,4FAA4F;AAC5F,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAA;IAC3C,QAAQ,EAAE,yBAAyB,EAAE,CAAA;IACrC,gFAAgF;IAChF,WAAW,CAAC,EAAE,qBAAqB,CAAA;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,mFAAmF;AACnF,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAA;IACpC,GAAG,EAAE,CACH,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,EAAE,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,KAC7C,OAAO,CAAC,wBAAwB,CAAC,CAAA;IACtC,gFAAgF;IAChF,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,CAAA;IACvD,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,CAAA;IACrD,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAA;IAC3C,YAAY,EAAE,MAAM,wBAAwB,EAAE,CAAA;IAC9C,qFAAqF;IACrF,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { FeedbackSource, FeedbackSpec, PlaywrightFeedback, PlaywrightFeedbackOptions, PlaywrightFeedbackResult } from './playwright-feedback-types.js';
|
|
2
|
+
import type { ExecutionBackend } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Whether a source change can alter markup, copy, styling or local runner configuration.
|
|
5
|
+
* @param path - The path reported by the host's file-change subscription.
|
|
6
|
+
* @returns True for app source and data formats; never a correctness judgment.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isPlaywrightFeedbackSource(path: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Subscribe to writes without making them wait for browser work.
|
|
11
|
+
* @param options - Source loader, native runner and delivery callbacks.
|
|
12
|
+
* @returns A source-change subscription; settle/close are for tests and shutdown only.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createPlaywrightFeedback(options: PlaywrightFeedbackOptions): PlaywrightFeedback;
|
|
15
|
+
/**
|
|
16
|
+
* Read explicit source roots and supplied helper/spec paths in one backend round trip.
|
|
17
|
+
* The standard filesystem and TypeScript parser own traversal/syntax; this is transport batching.
|
|
18
|
+
* @param backend - Local or sandbox execution backend.
|
|
19
|
+
* @param sourceRoots - App source directories, absolute.
|
|
20
|
+
* @param suiteFiles - Supplied spec/helper paths, absolute.
|
|
21
|
+
* @returns Existing, bounded text sources. Missing/unsupported files are ignored.
|
|
22
|
+
*/
|
|
23
|
+
export declare function readFeedbackSources(backend: ExecutionBackend, sourceRoots: readonly string[], suiteFiles: readonly string[]): Promise<FeedbackSource[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Run ONE spec's native command. Callers supply the correctly configured local command and
|
|
26
|
+
* append these runner flags at composition time (rather than modifying shell text here).
|
|
27
|
+
* Native failures are diagnosis, never proof that a complete supplied suite passed.
|
|
28
|
+
* @param backend - Existing execution backend.
|
|
29
|
+
* @param spec - The supplied spec and its normal per-file command.
|
|
30
|
+
* @param sourceFiles - Triggering component files, known to the write/index.
|
|
31
|
+
* @param revision - Source revision the scheduler will validate before delivery.
|
|
32
|
+
* @param options - Output location, command composition and a bounded backend budget.
|
|
33
|
+
* @returns The actual native outcome and actionable failures only.
|
|
34
|
+
*/
|
|
35
|
+
export declare function runPlaywrightFeedback(backend: ExecutionBackend, spec: FeedbackSpec, sourceFiles: string[], revision: number, options: {
|
|
36
|
+
command: (flags: string[]) => string;
|
|
37
|
+
scratchRoot?: string;
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
emit?: (result: PlaywrightFeedbackResult) => void;
|
|
40
|
+
pollMs?: number;
|
|
41
|
+
}): Promise<PlaywrightFeedbackResult>;
|
|
42
|
+
//# sourceMappingURL=playwright-feedback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-feedback.d.ts","sourceRoot":"","sources":["../src/playwright-feedback.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAEV,cAAc,EACd,YAAY,EACZ,kBAAkB,EAElB,yBAAyB,EACzB,wBAAwB,EACzB,MAAM,gCAAgC,CAAA;AAEvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAGlD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,kBAAkB,CAyG/F;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,gBAAgB,EACzB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,OAAO,CAAC,cAAc,EAAE,CAAC,CAkB3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,YAAY,EAClB,WAAW,EAAE,MAAM,EAAE,EACrB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IACP,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,MAAM,CAAA;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,CAAA;IACjD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GACA,OAAO,CAAC,wBAAwB,CAAC,CAwInC"}
|