cssprobe-cli 0.4.0 → 0.4.1
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/AGENTS.md +6 -2
- package/CHANGELOG.md +9 -0
- package/README.md +6 -3
- package/dist/browser/interactions.d.ts +2 -2
- package/dist/browser/interactions.js +8 -4
- package/dist/cli/commands.js +1 -0
- package/dist/daemon/daemon.js +3 -1
- package/dist/daemon/flowRunner.d.ts +1 -0
- package/dist/daemon/flowRunner.js +6 -3
- package/dist/help.json +2 -1
- package/dist/scenario/runner.js +9 -2
- package/dist/scenario/schema.d.ts +60 -0
- package/dist/scenario/schema.js +6 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
`cssprobe-cli` — Runtime CSS probe for layout/scroll/overflow/color/font inspection with session-based browser management. Entrypoint: `bin/cssprobe-cli.js` → `require('../dist/index')`.
|
|
6
6
|
Build: `npm run build` (= `tsc` + `esbuild` collector IIFE bundle + `esbuild` daemon entry + `tsx scripts/generate-help.ts`).
|
|
7
|
-
Test: `npm test` (= `tsx --test tests/*.test.ts` — Node.js built-in test runner,
|
|
7
|
+
Test: `npm test` (= `tsx --test tests/*.test.ts` — Node.js built-in test runner, 173 tests).
|
|
8
8
|
Dependencies: `playwright-core`, `zod`. Dev: `typescript`, `@types/node`, `tsx`, `esbuild`.
|
|
9
9
|
|
|
10
10
|
## Architecture
|
|
@@ -63,6 +63,7 @@ src/
|
|
|
63
63
|
- **Output strategy**: `Output` interface → `TextOutput` (Markdown for inspect, tables for lists) / `JsonOutput` (machine-readable JSON).
|
|
64
64
|
- **Config priority**: CLI flags → env vars → `~/.cssprobe-clirc` profiles. Switch with `-p <profile>`.
|
|
65
65
|
- **State management**: `state-import` converts Netscape cookies; `state-save` persists the current session's cookies + localStorage after manual login. Session persists browser state until `close`.
|
|
66
|
+
- **Iframe guidance**: pages may contain hidden helper iframes (`about:blank`); use `frames` to pick the real one and `state: "attached"` for hidden targets. Preview frames can render in 6–8s while analytics keep `networkIdle` busy — use a fixed `wait` plus an in-frame `waitFor` instead of `networkIdle`.
|
|
66
67
|
- **Browser discovery**: `findBrowserExecutable()` scans the platform Playwright cache (macOS/Linux/Windows, `PLAYWRIGHT_BROWSERS_PATH` override), prefers the revision required by the bundled `playwright-core`, and falls back to the newest install. `doctor` reports expected vs installed revisions.
|
|
67
68
|
- **Error format**: `Error: <message>` → JSON mode: `{ isError: true, error: "<message>" }` → `process.exit(1)`
|
|
68
69
|
|
|
@@ -116,14 +117,17 @@ src/
|
|
|
116
117
|
- `wait-for --js "<predicate>"` — wait until a JS predicate is truthy
|
|
117
118
|
- `wait-for --network-idle` — wait until the page is network-idle
|
|
118
119
|
- `--timeout <ms>` — default 30000; timeout errors name the target
|
|
120
|
+
- `--frame <index|name|url-substring>` — wait inside a frame (selector/js only; `networkIdle` is page-level)
|
|
119
121
|
- `scenario run <file>` — Run a JSON scenario suite (fresh browser per case, assertions, artifacts, JUnit)
|
|
120
122
|
- `--state <file>` — Fallback state file for cases without one
|
|
121
123
|
- `--artifacts <dir>` — Artifact directory (default `~/.cssprobe-cli/scenario-runs/<suite>-<timestamp>`)
|
|
122
124
|
- `--junit <file>` — Write a JUnit XML report
|
|
123
125
|
- `--bail` — Stop after the first failing case
|
|
124
|
-
- Steps: `goto`, `reload`, `eval`, `sample`, `waitStable`, `click`, `waitFor`, `screenshot`, `assert`
|
|
126
|
+
- Steps: `goto`, `reload`, `wait`, `eval`, `sample`, `waitStable`, `click`, `waitFor`, `screenshot`, `assert`
|
|
127
|
+
- `wait` takes a fixed `ms`; `waitFor` accepts `frame` for in-iframe selector/js waits
|
|
125
128
|
- `run <file>` — Run a multi-step flow script inside the daemon
|
|
126
129
|
- Script default-exports an async function receiving the API object: `page`, `context`, `frames()`, `newPage()`, `click`, `hover`, `type`, `waitFor`, `inspect`, `screenshot`, `expect`, `log` (CJS also supported)
|
|
130
|
+
- `waitFor(target, { state, timeout, frame })`; `frame` targets iframe selector/js waits
|
|
127
131
|
- Uncaught page errors are collected in the envelope as `pageErrors[]`
|
|
128
132
|
- `--timeout <ms>` — whole-script guard (default 300000, 0 = unlimited); failure exits 1 and keeps the session alive
|
|
129
133
|
- `screenshot` relative paths resolve against the script's directory; logs collected and returned
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.1] - 2026-10-23
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `wait-for --frame` (selector/js), scenario `waitFor.frame`, and flow `waitFor(target, { frame })`
|
|
7
|
+
- Scenario `wait` step for fixed delays before slow-rendering preview frames
|
|
8
|
+
|
|
9
|
+
### Documentation
|
|
10
|
+
- Iframe/preview guidance: hidden helper frames need `state: "attached"`; prefer in-frame `waitFor` over `networkIdle` when analytics keep the page busy
|
|
11
|
+
|
|
3
12
|
## [0.4.0] - 2026-10-23
|
|
4
13
|
|
|
5
14
|
### Added
|
package/README.md
CHANGED
|
@@ -202,7 +202,8 @@ Inspection commands accept `--frame <index|name|url-substring>` to target an ifr
|
|
|
202
202
|
| `type <selector> <text>` | Fill text (replaces value); `--press Enter` to submit; `--sequential` for real key events |
|
|
203
203
|
| `wait-for <selector>` | Wait for selector state (`--state visible\|hidden\|attached\|detached`, `--timeout ms`) |
|
|
204
204
|
| `wait-for --js "<predicate>"` | Wait until a JS predicate is truthy |
|
|
205
|
-
| `wait-for --network-idle` | Wait until the page is network-idle |
|
|
205
|
+
| `wait-for --network-idle` | Wait until the page is network-idle (page-level; no `--frame`) |
|
|
206
|
+
| `wait-for ... --frame <spec>` | Wait inside an iframe (selector/js modes) |
|
|
206
207
|
| `sample "<expr>"` | Sample an expression over time (`--interval`, `--duration`, `--key`, `--frame`); returns timeline + summary |
|
|
207
208
|
| `wait-stable "<expr>"` | Wait until an expression stops changing (`--tolerance`, `--window`, `--timeout`) |
|
|
208
209
|
| `run <file>` | Run a multi-step flow script |
|
|
@@ -269,7 +270,7 @@ export default async ({ page, context, frames, newPage, click, waitFor, type, in
|
|
|
269
270
|
cssprobe-cli run ./flow.js # --timeout ms for the whole script (default 300000, 0 = unlimited)
|
|
270
271
|
```
|
|
271
272
|
|
|
272
|
-
Scripts must `default-export` an async function receiving the API object: `page`, `context`, `frames()`, `newPage()`, `click`, `hover`, `type`, `waitFor`, `inspect`, `screenshot`, `expect`, `log`. Uncaught page errors are collected into the result envelope as `pageErrors`. `screenshot` relative paths resolve against the script's directory; logs (`log()` and `console.*`) are collected and returned with the result. On failure the command exits `1`, prints the collected logs, and keeps the session alive.
|
|
273
|
+
Scripts must `default-export` an async function receiving the API object: `page`, `context`, `frames()`, `newPage()`, `click`, `hover`, `type`, `waitFor`, `inspect`, `screenshot`, `expect`, `log`. `waitFor` accepts `{ state, timeout, frame }`. Uncaught page errors are collected into the result envelope as `pageErrors`. `screenshot` relative paths resolve against the script's directory; logs (`log()` and `console.*`) are collected and returned with the result. On failure the command exits `1`, prints the collected logs, and keeps the session alive.
|
|
273
274
|
|
|
274
275
|
> Scripts are executed by the local daemon with full Node privileges — only run trusted scripts.
|
|
275
276
|
|
|
@@ -313,7 +314,9 @@ cssprobe-cli scenario run suites/ticket-26571394.json \
|
|
|
313
314
|
}
|
|
314
315
|
```
|
|
315
316
|
|
|
316
|
-
Steps: `goto`, `reload`, `eval`, `sample`, `waitStable`, `click`, `waitFor`, `screenshot`, `assert`. `sample` and `eval` save values with `save: "<name>"`; assertions read them with `on: "<name>"` + `path`, or check live `state` (`url`, `title`, `frames`), `url`, `globals`, `absent`. `sample` supports `key`, `tailFrom`, `ignoreErrors`; every run writes `summary.json`, per-case `case.json`, sample series and failure screenshots.
|
|
317
|
+
Steps: `goto`, `reload`, `wait`, `eval`, `sample`, `waitStable`, `click`, `waitFor`, `screenshot`, `assert`. `wait` takes a fixed `ms`; `waitFor` supports `frame` for in-iframe selector/js waits. `sample` and `eval` save values with `save: "<name>"`; assertions read them with `on: "<name>"` + `path`, or check live `state` (`url`, `title`, `frames`), `url`, `globals`, `absent`. `sample` supports `key`, `tailFrom`, `ignoreErrors`; every run writes `summary.json`, per-case `case.json`, sample series and failure screenshots.
|
|
318
|
+
|
|
319
|
+
**Iframe and preview pages.** A page can contain hidden helper iframes (`about:blank`); use `frames` to pick the real one, and `state: "attached"` when waiting for a frame element that is not visible. Preview frames can take 6–8s to render and analytics requests keep `networkIdle` busy — prefer a fixed `wait` step followed by a `waitFor` inside the frame (`frame: "i/preview"`) instead of `networkIdle`.
|
|
317
320
|
|
|
318
321
|
## Confidence Model
|
|
319
322
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Page } from 'playwright-core';
|
|
1
|
+
import type { Frame, Page } from 'playwright-core';
|
|
2
2
|
export interface ElementDescriptor {
|
|
3
3
|
tag: string;
|
|
4
4
|
classes: string[];
|
|
@@ -46,4 +46,4 @@ export declare function resolveWaitTarget(selector: string | undefined, opts: {
|
|
|
46
46
|
state?: string;
|
|
47
47
|
}): WaitTarget;
|
|
48
48
|
export declare function normalizePredicateExpression(expression: string): string;
|
|
49
|
-
export declare function waitForCondition(
|
|
49
|
+
export declare function waitForCondition(host: Page | Frame, target: WaitTarget, timeout: number): Promise<number>;
|
|
@@ -78,17 +78,21 @@ function normalizePredicateExpression(expression) {
|
|
|
78
78
|
return trimmed;
|
|
79
79
|
return `(${trimmed})()`;
|
|
80
80
|
}
|
|
81
|
-
async function waitForCondition(
|
|
81
|
+
async function waitForCondition(host, target, timeout) {
|
|
82
|
+
const isPage = typeof host.setViewportSize === 'function';
|
|
83
|
+
if (target.kind === 'networkIdle' && !isPage) {
|
|
84
|
+
throw new Error('networkIdle waits are page-level; remove the frame target');
|
|
85
|
+
}
|
|
82
86
|
const started = Date.now();
|
|
83
87
|
switch (target.kind) {
|
|
84
88
|
case 'selector':
|
|
85
|
-
await
|
|
89
|
+
await host.waitForSelector(target.selector, { state: target.state, timeout });
|
|
86
90
|
break;
|
|
87
91
|
case 'js':
|
|
88
|
-
await
|
|
92
|
+
await host.waitForFunction(normalizePredicateExpression(target.expression), null, { timeout });
|
|
89
93
|
break;
|
|
90
94
|
case 'networkIdle':
|
|
91
|
-
await
|
|
95
|
+
await host.waitForLoadState('networkidle', { timeout });
|
|
92
96
|
break;
|
|
93
97
|
}
|
|
94
98
|
return Date.now() - started;
|
package/dist/cli/commands.js
CHANGED
|
@@ -259,6 +259,7 @@ const waitForCmd = (0, command_1.declareCommand)({
|
|
|
259
259
|
state: z.enum(['visible', 'hidden', 'attached', 'detached']).optional().describe('selector state to wait for (default visible)'),
|
|
260
260
|
js: z.string().optional().describe('JS predicate, e.g. "() => document.querySelector(\'.x\')?.offsetHeight > 100"'),
|
|
261
261
|
'network-idle': z.boolean().optional().describe('wait until the page is network-idle'),
|
|
262
|
+
frame: z.string().optional().describe('wait inside a frame: index, name, or URL substring'),
|
|
262
263
|
timeout: numberArg.optional().describe('timeout in ms (default 30000)'),
|
|
263
264
|
}),
|
|
264
265
|
});
|
package/dist/daemon/daemon.js
CHANGED
|
@@ -278,9 +278,11 @@ async function executeCommand(launcher, args) {
|
|
|
278
278
|
networkIdle: args['network-idle'],
|
|
279
279
|
state: args.state,
|
|
280
280
|
});
|
|
281
|
+
const page = requirePage(launcher);
|
|
282
|
+
const waitHost = args.frame ? (0, frames_1.resolveFrame)(page, args.frame) : page;
|
|
281
283
|
let elapsedMs;
|
|
282
284
|
try {
|
|
283
|
-
elapsedMs = await (0, interactions_1.waitForCondition)(
|
|
285
|
+
elapsedMs = await (0, interactions_1.waitForCondition)(waitHost, target, timeout);
|
|
284
286
|
}
|
|
285
287
|
catch (e) {
|
|
286
288
|
throw new Error(`wait-for failed for ${(0, interactions_1.describeWaitTarget)(target)} within ${timeout}ms: ${e.message}`);
|
|
@@ -66,20 +66,23 @@ function requirePage(launcher) {
|
|
|
66
66
|
return page;
|
|
67
67
|
}
|
|
68
68
|
async function flowWaitFor(page, target, opts) {
|
|
69
|
+
const host = opts?.frame ? (0, frames_1.resolveFrame)(page, opts.frame) : page;
|
|
69
70
|
if (typeof target === 'string') {
|
|
70
71
|
const state = opts?.state ?? 'visible';
|
|
71
72
|
const timeout = opts?.timeout ?? 30_000;
|
|
72
|
-
const elapsedMs = await (0, interactions_1.waitForCondition)(
|
|
73
|
+
const elapsedMs = await (0, interactions_1.waitForCondition)(host, { kind: 'selector', selector: target, state }, timeout);
|
|
73
74
|
return { waitedFor: 'selector', state, elapsedMs };
|
|
74
75
|
}
|
|
75
76
|
if ('js' in target) {
|
|
76
77
|
const timeout = target.timeout ?? 30_000;
|
|
77
|
-
const elapsedMs = await (0, interactions_1.waitForCondition)(
|
|
78
|
+
const elapsedMs = await (0, interactions_1.waitForCondition)(host, { kind: 'js', expression: target.js }, timeout);
|
|
78
79
|
return { waitedFor: 'js', elapsedMs };
|
|
79
80
|
}
|
|
80
81
|
if (target.networkIdle) {
|
|
82
|
+
if (opts?.frame)
|
|
83
|
+
throw new Error('networkIdle waits are page-level; remove opts.frame');
|
|
81
84
|
const timeout = target.timeout ?? 30_000;
|
|
82
|
-
const elapsedMs = await (0, interactions_1.waitForCondition)(
|
|
85
|
+
const elapsedMs = await (0, interactions_1.waitForCondition)(host, { kind: 'networkIdle' }, timeout);
|
|
83
86
|
return { waitedFor: 'networkidle', elapsedMs };
|
|
84
87
|
}
|
|
85
88
|
throw new Error('waitFor requires a selector string, { js }, or { networkIdle: true }');
|
package/dist/help.json
CHANGED
|
@@ -175,11 +175,12 @@
|
|
|
175
175
|
]
|
|
176
176
|
},
|
|
177
177
|
"wait-for": {
|
|
178
|
-
"help": "cssprobe-cli wait-for [selector]\n\nWait for a condition: selector state, JS predicate, or network idle\n\nArguments:\n [selector] css selector to wait for\nOptions:\n --state selector state to wait for (default visible)\n --js js predicate, e.g. \"() => document.queryselector('.x')?.offsetheight > 100\"\n --network-idle wait until the page is network-idle\n --timeout timeout in ms (default 30000)\n\nGlobal options:\n --json output as JSON\n --profile, -p <name> use named profile",
|
|
178
|
+
"help": "cssprobe-cli wait-for [selector]\n\nWait for a condition: selector state, JS predicate, or network idle\n\nArguments:\n [selector] css selector to wait for\nOptions:\n --state selector state to wait for (default visible)\n --js js predicate, e.g. \"() => document.queryselector('.x')?.offsetheight > 100\"\n --network-idle wait until the page is network-idle\n --frame wait inside a frame: index, name, or url substring\n --timeout timeout in ms (default 30000)\n\nGlobal options:\n --json output as JSON\n --profile, -p <name> use named profile",
|
|
179
179
|
"flags": {
|
|
180
180
|
"state": "string",
|
|
181
181
|
"js": "string",
|
|
182
182
|
"network-idle": "boolean",
|
|
183
|
+
"frame": "string",
|
|
183
184
|
"timeout": "string"
|
|
184
185
|
},
|
|
185
186
|
"args": [
|
package/dist/scenario/runner.js
CHANGED
|
@@ -207,20 +207,27 @@ async function executeStep(step, context) {
|
|
|
207
207
|
}
|
|
208
208
|
case 'waitFor': {
|
|
209
209
|
const timeout = step.timeout ?? 30000;
|
|
210
|
+
const frameSpec = step.frame ?? context.frameSpec;
|
|
210
211
|
if (step.networkIdle) {
|
|
212
|
+
if (frameSpec)
|
|
213
|
+
throw new Error('networkIdle waits are page-level; remove frame');
|
|
211
214
|
await (0, interactions_1.waitForCondition)(page, { kind: 'networkIdle' }, timeout);
|
|
212
215
|
}
|
|
213
216
|
else if (step.js) {
|
|
214
|
-
await (0, interactions_1.waitForCondition)(page, { kind: 'js', expression: step.js }, timeout);
|
|
217
|
+
await (0, interactions_1.waitForCondition)(frameSpec ? (0, frames_1.resolveFrame)(page, frameSpec) : page, { kind: 'js', expression: step.js }, timeout);
|
|
215
218
|
}
|
|
216
219
|
else if (step.selector) {
|
|
217
|
-
await (0, interactions_1.waitForCondition)(page, { kind: 'selector', selector: step.selector, state: step.state ?? 'visible' }, timeout);
|
|
220
|
+
await (0, interactions_1.waitForCondition)(frameSpec ? (0, frames_1.resolveFrame)(page, frameSpec) : page, { kind: 'selector', selector: step.selector, state: step.state ?? 'visible' }, timeout);
|
|
218
221
|
}
|
|
219
222
|
else {
|
|
220
223
|
throw new Error('waitFor requires selector, js, or networkIdle');
|
|
221
224
|
}
|
|
222
225
|
return;
|
|
223
226
|
}
|
|
227
|
+
case 'wait': {
|
|
228
|
+
await new Promise(resolve => setTimeout(resolve, step.ms));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
224
231
|
case 'screenshot': {
|
|
225
232
|
const buffer = await page.screenshot({ fullPage: step.fullPage });
|
|
226
233
|
const out = path_1.default.resolve(caseDir, step.path ?? `step-${stepIndex + 1}-screenshot.png`);
|
|
@@ -177,11 +177,13 @@ export declare const stepSchema: z.ZodDiscriminatedUnion<"do", [z.ZodObject<{
|
|
|
177
177
|
js: z.ZodOptional<z.ZodString>;
|
|
178
178
|
networkIdle: z.ZodOptional<z.ZodBoolean>;
|
|
179
179
|
state: z.ZodOptional<z.ZodEnum<["visible", "hidden", "attached", "detached"]>>;
|
|
180
|
+
frame: z.ZodOptional<z.ZodString>;
|
|
180
181
|
timeout: z.ZodOptional<z.ZodNumber>;
|
|
181
182
|
}, "strip", z.ZodTypeAny, {
|
|
182
183
|
do: "waitFor";
|
|
183
184
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
184
185
|
selector?: string | undefined;
|
|
186
|
+
frame?: string | undefined;
|
|
185
187
|
timeout?: number | undefined;
|
|
186
188
|
js?: string | undefined;
|
|
187
189
|
networkIdle?: boolean | undefined;
|
|
@@ -189,9 +191,19 @@ export declare const stepSchema: z.ZodDiscriminatedUnion<"do", [z.ZodObject<{
|
|
|
189
191
|
do: "waitFor";
|
|
190
192
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
191
193
|
selector?: string | undefined;
|
|
194
|
+
frame?: string | undefined;
|
|
192
195
|
timeout?: number | undefined;
|
|
193
196
|
js?: string | undefined;
|
|
194
197
|
networkIdle?: boolean | undefined;
|
|
198
|
+
}>, z.ZodObject<{
|
|
199
|
+
do: z.ZodLiteral<"wait">;
|
|
200
|
+
ms: z.ZodNumber;
|
|
201
|
+
}, "strip", z.ZodTypeAny, {
|
|
202
|
+
do: "wait";
|
|
203
|
+
ms: number;
|
|
204
|
+
}, {
|
|
205
|
+
do: "wait";
|
|
206
|
+
ms: number;
|
|
195
207
|
}>, z.ZodObject<{
|
|
196
208
|
do: z.ZodLiteral<"screenshot">;
|
|
197
209
|
path: z.ZodOptional<z.ZodString>;
|
|
@@ -387,11 +399,13 @@ export declare const caseSchema: z.ZodObject<{
|
|
|
387
399
|
js: z.ZodOptional<z.ZodString>;
|
|
388
400
|
networkIdle: z.ZodOptional<z.ZodBoolean>;
|
|
389
401
|
state: z.ZodOptional<z.ZodEnum<["visible", "hidden", "attached", "detached"]>>;
|
|
402
|
+
frame: z.ZodOptional<z.ZodString>;
|
|
390
403
|
timeout: z.ZodOptional<z.ZodNumber>;
|
|
391
404
|
}, "strip", z.ZodTypeAny, {
|
|
392
405
|
do: "waitFor";
|
|
393
406
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
394
407
|
selector?: string | undefined;
|
|
408
|
+
frame?: string | undefined;
|
|
395
409
|
timeout?: number | undefined;
|
|
396
410
|
js?: string | undefined;
|
|
397
411
|
networkIdle?: boolean | undefined;
|
|
@@ -399,9 +413,19 @@ export declare const caseSchema: z.ZodObject<{
|
|
|
399
413
|
do: "waitFor";
|
|
400
414
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
401
415
|
selector?: string | undefined;
|
|
416
|
+
frame?: string | undefined;
|
|
402
417
|
timeout?: number | undefined;
|
|
403
418
|
js?: string | undefined;
|
|
404
419
|
networkIdle?: boolean | undefined;
|
|
420
|
+
}>, z.ZodObject<{
|
|
421
|
+
do: z.ZodLiteral<"wait">;
|
|
422
|
+
ms: z.ZodNumber;
|
|
423
|
+
}, "strip", z.ZodTypeAny, {
|
|
424
|
+
do: "wait";
|
|
425
|
+
ms: number;
|
|
426
|
+
}, {
|
|
427
|
+
do: "wait";
|
|
428
|
+
ms: number;
|
|
405
429
|
}>, z.ZodObject<{
|
|
406
430
|
do: z.ZodLiteral<"screenshot">;
|
|
407
431
|
path: z.ZodOptional<z.ZodString>;
|
|
@@ -516,9 +540,13 @@ export declare const caseSchema: z.ZodObject<{
|
|
|
516
540
|
do: "waitFor";
|
|
517
541
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
518
542
|
selector?: string | undefined;
|
|
543
|
+
frame?: string | undefined;
|
|
519
544
|
timeout?: number | undefined;
|
|
520
545
|
js?: string | undefined;
|
|
521
546
|
networkIdle?: boolean | undefined;
|
|
547
|
+
} | {
|
|
548
|
+
do: "wait";
|
|
549
|
+
ms: number;
|
|
522
550
|
} | {
|
|
523
551
|
do: "screenshot";
|
|
524
552
|
path?: string | undefined;
|
|
@@ -588,9 +616,13 @@ export declare const caseSchema: z.ZodObject<{
|
|
|
588
616
|
do: "waitFor";
|
|
589
617
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
590
618
|
selector?: string | undefined;
|
|
619
|
+
frame?: string | undefined;
|
|
591
620
|
timeout?: number | undefined;
|
|
592
621
|
js?: string | undefined;
|
|
593
622
|
networkIdle?: boolean | undefined;
|
|
623
|
+
} | {
|
|
624
|
+
do: "wait";
|
|
625
|
+
ms: number;
|
|
594
626
|
} | {
|
|
595
627
|
do: "screenshot";
|
|
596
628
|
path?: string | undefined;
|
|
@@ -775,11 +807,13 @@ export declare const suiteSchema: z.ZodObject<{
|
|
|
775
807
|
js: z.ZodOptional<z.ZodString>;
|
|
776
808
|
networkIdle: z.ZodOptional<z.ZodBoolean>;
|
|
777
809
|
state: z.ZodOptional<z.ZodEnum<["visible", "hidden", "attached", "detached"]>>;
|
|
810
|
+
frame: z.ZodOptional<z.ZodString>;
|
|
778
811
|
timeout: z.ZodOptional<z.ZodNumber>;
|
|
779
812
|
}, "strip", z.ZodTypeAny, {
|
|
780
813
|
do: "waitFor";
|
|
781
814
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
782
815
|
selector?: string | undefined;
|
|
816
|
+
frame?: string | undefined;
|
|
783
817
|
timeout?: number | undefined;
|
|
784
818
|
js?: string | undefined;
|
|
785
819
|
networkIdle?: boolean | undefined;
|
|
@@ -787,9 +821,19 @@ export declare const suiteSchema: z.ZodObject<{
|
|
|
787
821
|
do: "waitFor";
|
|
788
822
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
789
823
|
selector?: string | undefined;
|
|
824
|
+
frame?: string | undefined;
|
|
790
825
|
timeout?: number | undefined;
|
|
791
826
|
js?: string | undefined;
|
|
792
827
|
networkIdle?: boolean | undefined;
|
|
828
|
+
}>, z.ZodObject<{
|
|
829
|
+
do: z.ZodLiteral<"wait">;
|
|
830
|
+
ms: z.ZodNumber;
|
|
831
|
+
}, "strip", z.ZodTypeAny, {
|
|
832
|
+
do: "wait";
|
|
833
|
+
ms: number;
|
|
834
|
+
}, {
|
|
835
|
+
do: "wait";
|
|
836
|
+
ms: number;
|
|
793
837
|
}>, z.ZodObject<{
|
|
794
838
|
do: z.ZodLiteral<"screenshot">;
|
|
795
839
|
path: z.ZodOptional<z.ZodString>;
|
|
@@ -904,9 +948,13 @@ export declare const suiteSchema: z.ZodObject<{
|
|
|
904
948
|
do: "waitFor";
|
|
905
949
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
906
950
|
selector?: string | undefined;
|
|
951
|
+
frame?: string | undefined;
|
|
907
952
|
timeout?: number | undefined;
|
|
908
953
|
js?: string | undefined;
|
|
909
954
|
networkIdle?: boolean | undefined;
|
|
955
|
+
} | {
|
|
956
|
+
do: "wait";
|
|
957
|
+
ms: number;
|
|
910
958
|
} | {
|
|
911
959
|
do: "screenshot";
|
|
912
960
|
path?: string | undefined;
|
|
@@ -976,9 +1024,13 @@ export declare const suiteSchema: z.ZodObject<{
|
|
|
976
1024
|
do: "waitFor";
|
|
977
1025
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
978
1026
|
selector?: string | undefined;
|
|
1027
|
+
frame?: string | undefined;
|
|
979
1028
|
timeout?: number | undefined;
|
|
980
1029
|
js?: string | undefined;
|
|
981
1030
|
networkIdle?: boolean | undefined;
|
|
1031
|
+
} | {
|
|
1032
|
+
do: "wait";
|
|
1033
|
+
ms: number;
|
|
982
1034
|
} | {
|
|
983
1035
|
do: "screenshot";
|
|
984
1036
|
path?: string | undefined;
|
|
@@ -1051,9 +1103,13 @@ export declare const suiteSchema: z.ZodObject<{
|
|
|
1051
1103
|
do: "waitFor";
|
|
1052
1104
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
1053
1105
|
selector?: string | undefined;
|
|
1106
|
+
frame?: string | undefined;
|
|
1054
1107
|
timeout?: number | undefined;
|
|
1055
1108
|
js?: string | undefined;
|
|
1056
1109
|
networkIdle?: boolean | undefined;
|
|
1110
|
+
} | {
|
|
1111
|
+
do: "wait";
|
|
1112
|
+
ms: number;
|
|
1057
1113
|
} | {
|
|
1058
1114
|
do: "screenshot";
|
|
1059
1115
|
path?: string | undefined;
|
|
@@ -1135,9 +1191,13 @@ export declare const suiteSchema: z.ZodObject<{
|
|
|
1135
1191
|
do: "waitFor";
|
|
1136
1192
|
state?: "visible" | "hidden" | "attached" | "detached" | undefined;
|
|
1137
1193
|
selector?: string | undefined;
|
|
1194
|
+
frame?: string | undefined;
|
|
1138
1195
|
timeout?: number | undefined;
|
|
1139
1196
|
js?: string | undefined;
|
|
1140
1197
|
networkIdle?: boolean | undefined;
|
|
1198
|
+
} | {
|
|
1199
|
+
do: "wait";
|
|
1200
|
+
ms: number;
|
|
1141
1201
|
} | {
|
|
1142
1202
|
do: "screenshot";
|
|
1143
1203
|
path?: string | undefined;
|
package/dist/scenario/schema.js
CHANGED
|
@@ -94,8 +94,13 @@ const waitForStep = z.object({
|
|
|
94
94
|
js: z.string().optional(),
|
|
95
95
|
networkIdle: z.boolean().optional(),
|
|
96
96
|
state: z.enum(['visible', 'hidden', 'attached', 'detached']).optional(),
|
|
97
|
+
frame: z.string().optional(),
|
|
97
98
|
timeout: z.number().optional(),
|
|
98
99
|
});
|
|
100
|
+
const waitStep = z.object({
|
|
101
|
+
do: z.literal('wait'),
|
|
102
|
+
ms: z.number().positive(),
|
|
103
|
+
});
|
|
99
104
|
const screenshotStep = z.object({
|
|
100
105
|
do: z.literal('screenshot'),
|
|
101
106
|
path: z.string().optional(),
|
|
@@ -119,6 +124,7 @@ exports.stepSchema = z.discriminatedUnion('do', [
|
|
|
119
124
|
waitStableStep,
|
|
120
125
|
clickStep,
|
|
121
126
|
waitForStep,
|
|
127
|
+
waitStep,
|
|
122
128
|
screenshotStep,
|
|
123
129
|
assertStep,
|
|
124
130
|
]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cssprobe-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"mcpName": "io.github.mack-peng/cssprobe-cli",
|
|
5
5
|
"description": "Runtime CSS probe — inspect layout, colors, backgrounds, fonts and more in a live browser. AI agents and shell automation.",
|
|
6
6
|
"keywords": [
|