@joeytheman/gemini-mcp-tool 2.2.0 → 2.3.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 +10 -7
- package/dist/__tests__/agyModelSteps.test.d.ts +2 -0
- package/dist/__tests__/agyModelSteps.test.d.ts.map +1 -0
- package/dist/__tests__/agyModelSteps.test.js +58 -0
- package/dist/__tests__/agyModelSteps.test.js.map +1 -0
- package/dist/__tests__/capture-script.chromium.test.d.ts +2 -0
- package/dist/__tests__/capture-script.chromium.test.d.ts.map +1 -0
- package/dist/__tests__/capture-script.chromium.test.js +235 -0
- package/dist/__tests__/capture-script.chromium.test.js.map +1 -0
- package/dist/__tests__/layout-snippet.chromium.test.d.ts +2 -0
- package/dist/__tests__/layout-snippet.chromium.test.d.ts.map +1 -0
- package/dist/__tests__/layout-snippet.chromium.test.js +333 -0
- package/dist/__tests__/layout-snippet.chromium.test.js.map +1 -0
- package/dist/__tests__/layout-snippet.test.d.ts +2 -0
- package/dist/__tests__/layout-snippet.test.d.ts.map +1 -0
- package/dist/__tests__/layout-snippet.test.js +12 -0
- package/dist/__tests__/layout-snippet.test.js.map +1 -0
- package/dist/__tests__/live-pass.test.js +531 -7
- package/dist/__tests__/live-pass.test.js.map +1 -1
- package/dist/__tests__/screen-review.test.js +111 -2
- package/dist/__tests__/screen-review.test.js.map +1 -1
- package/dist/__tests__/server-progress.test.d.ts +2 -0
- package/dist/__tests__/server-progress.test.d.ts.map +1 -0
- package/dist/__tests__/server-progress.test.js +63 -0
- package/dist/__tests__/server-progress.test.js.map +1 -0
- package/dist/__tests__/server.test.js +1 -8
- package/dist/__tests__/server.test.js.map +1 -1
- package/dist/__tests__/simple-tools.test.js +8 -3
- package/dist/__tests__/simple-tools.test.js.map +1 -1
- package/dist/__tests__/tools.test.js +29 -1
- package/dist/__tests__/tools.test.js.map +1 -1
- package/dist/__tests__/utils/agyExecutor.test.js +176 -61
- package/dist/__tests__/utils/agyExecutor.test.js.map +1 -1
- package/dist/__tests__/utils/commandExecutor.test.js +155 -1
- package/dist/__tests__/utils/commandExecutor.test.js.map +1 -1
- package/dist/__tests__/utils/progressUpdates.test.d.ts +2 -0
- package/dist/__tests__/utils/progressUpdates.test.d.ts.map +1 -0
- package/dist/__tests__/utils/progressUpdates.test.js +62 -0
- package/dist/__tests__/utils/progressUpdates.test.js.map +1 -0
- package/dist/constants.d.ts +33 -10
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +42 -10
- package/dist/constants.js.map +1 -1
- package/dist/index.js +19 -94
- package/dist/index.js.map +1 -1
- package/dist/layoutCheckSnippet.generated.d.ts +2 -0
- package/dist/layoutCheckSnippet.generated.d.ts.map +1 -0
- package/dist/layoutCheckSnippet.generated.js +3 -0
- package/dist/layoutCheckSnippet.generated.js.map +1 -0
- package/dist/tools/ask-gemini.tool.d.ts.map +1 -1
- package/dist/tools/ask-gemini.tool.js +6 -5
- package/dist/tools/ask-gemini.tool.js.map +1 -1
- package/dist/tools/brainstorm.tool.d.ts.map +1 -1
- package/dist/tools/brainstorm.tool.js +2 -1
- package/dist/tools/brainstorm.tool.js.map +1 -1
- package/dist/tools/live-pass.tool.d.ts +24 -1
- package/dist/tools/live-pass.tool.d.ts.map +1 -1
- package/dist/tools/live-pass.tool.js +174 -52
- package/dist/tools/live-pass.tool.js.map +1 -1
- package/dist/tools/registry.d.ts +2 -2
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +2 -2
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/screen-review.tool.d.ts +3 -0
- package/dist/tools/screen-review.tool.d.ts.map +1 -1
- package/dist/tools/screen-review.tool.js +42 -8
- package/dist/tools/screen-review.tool.js.map +1 -1
- package/dist/tools/simple-tools.d.ts.map +1 -1
- package/dist/tools/simple-tools.js +6 -2
- package/dist/tools/simple-tools.js.map +1 -1
- package/dist/utils/agyExecutor.d.ts +9 -1
- package/dist/utils/agyExecutor.d.ts.map +1 -1
- package/dist/utils/agyExecutor.js +54 -48
- package/dist/utils/agyExecutor.js.map +1 -1
- package/dist/utils/agyModelSteps.d.ts +5 -0
- package/dist/utils/agyModelSteps.d.ts.map +1 -0
- package/dist/utils/agyModelSteps.js +33 -0
- package/dist/utils/agyModelSteps.js.map +1 -0
- package/dist/utils/artifactFile.d.ts +6 -0
- package/dist/utils/artifactFile.d.ts.map +1 -0
- package/dist/utils/artifactFile.js +55 -0
- package/dist/utils/artifactFile.js.map +1 -0
- package/dist/utils/captureScript.d.ts +24 -0
- package/dist/utils/captureScript.d.ts.map +1 -0
- package/dist/utils/captureScript.js +83 -0
- package/dist/utils/captureScript.js.map +1 -0
- package/dist/utils/commandExecutor.d.ts +7 -1
- package/dist/utils/commandExecutor.d.ts.map +1 -1
- package/dist/utils/commandExecutor.js +154 -22
- package/dist/utils/commandExecutor.js.map +1 -1
- package/dist/utils/gitCheckout.d.ts +14 -0
- package/dist/utils/gitCheckout.d.ts.map +1 -0
- package/dist/utils/gitCheckout.js +36 -0
- package/dist/utils/gitCheckout.js.map +1 -0
- package/dist/utils/layoutCheck.d.ts +58 -0
- package/dist/utils/layoutCheck.d.ts.map +1 -0
- package/dist/utils/layoutCheck.js +84 -0
- package/dist/utils/layoutCheck.js.map +1 -0
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +0 -6
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/progressUpdates.d.ts +14 -0
- package/dist/utils/progressUpdates.d.ts.map +1 -0
- package/dist/utils/progressUpdates.js +40 -0
- package/dist/utils/progressUpdates.js.map +1 -0
- package/package.json +13 -11
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ Version 2.0 moves the Gemini backend from the retired Gemini CLI/API path to Goo
|
|
|
60
60
|
|
|
61
61
|
Before using this tool, ensure you have:
|
|
62
62
|
|
|
63
|
-
1. **[Node.js](https://nodejs.org/)** (
|
|
63
|
+
1. **[Node.js](https://nodejs.org/)** (v20.12.0 or higher)
|
|
64
64
|
2. **Antigravity CLI (`agy`)** installed and configured
|
|
65
65
|
|
|
66
66
|
Verify `agy` before adding the MCP server:
|
|
@@ -171,12 +171,12 @@ After updating the configuration, restart your terminal session.
|
|
|
171
171
|
|
|
172
172
|
```bash
|
|
173
173
|
agy mcp add playwright -- npx -y @playwright/mcp@latest --browser chromium --headless --isolated \
|
|
174
|
-
--allow-unrestricted-file-access # artifact dirs live inside each worktree, so no fixed --output-dir
|
|
174
|
+
--codegen none --allow-unrestricted-file-access # artifact dirs live inside each worktree, so no fixed --output-dir
|
|
175
175
|
agy mcp add maestro /path/to/maestro mcp
|
|
176
176
|
agy mcp list # playwright + maestro
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
-
`--allow-unrestricted-file-access` is what lets
|
|
179
|
+
`--allow-unrestricted-file-access` is what lets `browser_run_code_unsafe` read each target's capture file and `browser_evaluate` write its layout file in a worktree-local artifact directory; the capture file's `page.screenshot` writes the PNG itself. `--codegen none` keeps `@playwright/mcp` from echoing each capture file's code back into Gemini's history under "Ran Playwright code", which would add about 5.5k characters per frame. A web pass needs a `@playwright/mcp` with `browser_run_code_unsafe` (0.0.84 has it). The tool compensates: `artifactDir` must be inside `workingDirectory`, every frame is checked on disk (matching PNG or JPEG filename and file signature, fresh, non-empty, inside the artifact dir), and the working tree is diffed before and after the run.
|
|
180
180
|
|
|
181
181
|
Add `.live-pass/` to the repository's `.gitignore` so frames never land in a commit; deleting the worktree then removes them. Add `.playwright-mcp/` too — the Playwright MCP server creates that directory in whatever it runs from, which the working-tree guard will otherwise report as a WARNING on every pass.
|
|
182
182
|
|
|
@@ -221,9 +221,9 @@ These tools are designed to be used by the AI assistant.
|
|
|
221
221
|
- **`changeMode`** (optional): Enable structured change mode for edit suggestions that Claude can apply directly.
|
|
222
222
|
- **`yolo`** (optional): Pass `--dangerously-skip-permissions`. Use with caution.
|
|
223
223
|
- **`includeDirectories`** (optional): Additional directories to include in the Antigravity workspace; maps to repeated `--add-dir`.
|
|
224
|
-
- **`printTimeout`** (optional): Pass `--print-timeout
|
|
224
|
+
- **`printTimeout`** (optional): Pass `--print-timeout`: a duration such as `90s`, `15m`, `2h30m` or `2.5h`, or `0` for no limit; other values are rejected. The server stops agy 2 minutes after this limit, or after 2 hours when no limit is given.
|
|
225
225
|
- **`resume`** (optional): `true`, `latest`, or `continue` maps to `--continue`; any other string maps to `--conversation <id>`.
|
|
226
|
-
- **`conversationId`** (optional): Resume this exact conversation (`--conversation <id>`); wins over `resume`.
|
|
226
|
+
- **`conversationId`** (optional): Resume this exact conversation (`--conversation <id>`); wins over `resume`. The call fails with `CONVERSATION_NOT_RESUMED` when agy silently starts a different conversation — a stale ID only warns on stderr and would otherwise return an unrelated answer. IDs come from the `[GEMINI_CONVERSATION_ID=...]` line of a previous json call; a text call reports its ID only when it fails with an empty answer.
|
|
227
227
|
- **`outputFormat`** (optional): `"text"` (default) or `"json"`. `"json"` returns agy's envelope rendered as the conversation line, the answer, and a usage line. `"stream-json"` is unsupported.
|
|
228
228
|
- **`jsonSchema`** (optional): Inline JSON Schema passed to `--json-schema`, constraining the answer to `structured_output`. Requires `outputFormat: "json"`.
|
|
229
229
|
- **`effort`** (optional): `low`, `medium`, or `high`, passed to `--effort`. Tiered Gemini names already encode effort in the name, and agy rejects `--effort` for them — the rejection is surfaced verbatim.
|
|
@@ -231,8 +231,8 @@ These tools are designed to be used by the AI assistant.
|
|
|
231
231
|
- **Unsupported legacy options**: `extensions`, `debug`, `promptInteractive`, `outputFormat: "stream-json"`, and `approvalMode` except `approvalMode: "yolo"`.
|
|
232
232
|
|
|
233
233
|
- **`live-pass`**: Delegate a live UI verification to Gemini. It drives its own Playwright or Maestro MCP server, captures the requested frames, looks at them, and returns text.
|
|
234
|
-
- **`targets`** (required): One `{screen, state, viewport, expected}` per frame the pass must produce
|
|
235
|
-
- **`brief`** (required):
|
|
234
|
+
- **`targets`** (required): One `{screen, state, viewport, expected}` per frame the pass must produce; for `playwright`, `viewport` must be `WxH`, such as `390x844`. `expected` is what that state must show — for an intentional error/empty/offline state, name the reason text and the recovery affordance. The effective verdict is derived from this list: **any target that produced no frame fails the pass**, whether Gemini skipped it with a reason or never reported it at all. A skip explains missing evidence; it does not excuse it. Each target's screenshot filename is derived in code from its `screen`/`state`/`viewport`, so two targets can never be answered by one image — a reused file is reported as `DUPLICATE` and fails the pass.
|
|
235
|
+
- **`brief`** (required): Every fact Gemini needs, because the pass forbids it to read product code, tests, docs, tool schemas or the database, or to run git: the app's start URL or app id, any link a user arrives by (an invite, email or share link) with where it comes from, the served-branch marker, and per target the user path, the labels or testIDs on it, the seed account and ids, and how long toasts and pending states stay on screen. App specifics belong here, not in the tool. The pass opens the app once, at its start URL (or by launching it on a device). A target may begin at a link of its own only when the brief says the user arrives by that link and names where it comes from; that frame quotes the source in `link_source`, and the report prints it. Every other target is reached by taps from the previous screen (sign-in form, navigation taps, form submits; no scripted shortcuts), and any other URL in the brief is context, never a navigation target. A reload opens the current URL, and only where the brief makes it part of the path. A target whose path breaks is skipped with the step where it broke, and one whose fact is missing is skipped with `brief missing: <fact>`; either fails the pass. The branch and HEAD of `workingDirectory` are read in code and printed in the prompt as context: the pass is BLOCKED only when the app's served-branch marker contradicts them (a detached HEAD never contradicts a branch name).
|
|
236
236
|
- **`workingDirectory`** (required): Absolute path to the worktree under test. Used as agy's cwd and workspace root.
|
|
237
237
|
- **`driver`** (required): `playwright` or `maestro`.
|
|
238
238
|
- **`artifactDir`** (optional): Absolute path, strictly inside `workingDirectory`. Defaults to `<workingDirectory>/.live-pass/<timestamp>`, so deleting the worktree cleans up the frames. Add `.live-pass/` to the repo's `.gitignore`.
|
|
@@ -240,6 +240,8 @@ These tools are designed to be used by the AI assistant.
|
|
|
240
240
|
- **`conversationId`** (optional): Resume the previous pass so Gemini reports deltas (`resolved`, `regressions`, `changes`) instead of a bare snapshot. The browser or simulator still starts fresh — resume only changes what Gemini remembers. Start fresh when the brief changed materially, after a BLOCKED pass, or after about three rounds (each resumed round roughly doubles input tokens).
|
|
241
241
|
- **`yolo`** (optional, default **true**): Without `--dangerously-skip-permissions`, headless agy denies the MCP tool calls and the pass is BLOCKED. The tool snapshots the working tree before and after — status lines *and* content hashes of every dirty file, since a file Gemini rewrites in a PR worktree was already modified before the run — and reports any change as a WARNING, including when the agy call itself fails.
|
|
242
242
|
- **`model`** (optional, default `Gemini 3.8 Flash (Medium)`), **`printTimeout`** (optional, default `15m`).
|
|
243
|
+
- **Capture files and layout checks** (`playwright` only): before agy starts, the tool writes one capture file per target next to its frame, `<frame>.capture.js`, and Gemini runs it with `browser_run_code_unsafe {filename}` once the state has settled. In one call it sets the target's viewport, measures how far the page or its largest shown scroller overflows (only scrollers inside an open `aria-modal` sheet count while one shows, and textareas never do), grows the viewport by that much and measures again, a few times at most, while the overflow keeps shrinking and up to 4000 px tall (a screen that still scrolls after that is shot as it stands), saves the PNG, runs a fixed layout snippet in the page at the shot's size, and restores the viewport. A failed restore is noted in the call's answer and never hides the capture's own result or error. Gemini then saves that snippet's result next to the frame as `<frame>.layout.json` with a one-line `browser_evaluate`. Neither snippet is in Gemini's prompt. A failed screenshot fails the capture, so Gemini skips the target; a failed layout step still keeps the frame and leaves the layout file "not run". The layout check lists horizontal page scroll, text spilling its box, clipped text, controls covered by something else (hit-testing only the part of a control its scroll containers show, and skipping controls under an open `aria-modal` sheet, and a control in a horizontal scroller only when what covers it belongs to that scroller's row: a sibling, or the row's edge control within the row's height), and controls cut off at the screen edge, each as `{kind, text, testID, rect}` (at most 50). A framework dev overlay (Expo's `#error-overlay` / `#error-toast`) is kept out of every check and reported once as `dev-overlay` when its host or anything inside it shows, including inside the host's shadow root as Expo draws it, with the largest shown box and its text, marking the frame as polluted. Text capped with `-webkit-line-clamp` or `text-overflow: ellipsis` (React Native Web's `numberOfLines`) is listed separately as "capped (line clamp / ellipsis)". The report's "Layout checks (measured in the page)" section shows each frame's entries, or "not run" when the file is missing, stale, outside `artifactDir`, malformed, or measured at another width than the frame. The snippet's readable source is `src/layout-check.snippet.js`; `npm run snippet:build` regenerates the minified constant, and `npm test` and the CI Chromium step fail when the two drift. The caller judges the entries; they never change the verdict.
|
|
244
|
+
- The usage line is followed by Gemini's model steps, read from agy's conversation store (`~/.gemini/antigravity-cli/conversations/<id>.db`), and per frame for a live pass. It prints `?` when the store can't be read.
|
|
243
245
|
|
|
244
246
|
- **`screen-review`**: Have Gemini judge captured screens, or inventory a route before it is built.
|
|
245
247
|
- **`mode`** (required): `review` judges PNGs after a live pass; `plan` inventories a route file and returns no verdict.
|
|
@@ -248,6 +250,7 @@ These tools are designed to be used by the AI assistant.
|
|
|
248
250
|
- **`images`** (review mode, required): Absolute PNG/JPEG paths that must exist. **`routeFile`** (plan mode, required): absolute path inside `workingDirectory`. Neither may contain whitespace — agy resolves an `@reference` up to the first space, so a spaced path would hang until `printTimeout`; the tool rejects it up front instead.
|
|
249
251
|
- **`context`** (optional): Composition contract, issue text, anything else the reviewer prompt cites.
|
|
250
252
|
- **`changedRoutes`** (optional, review mode): Repo-relative files the diff touched (from `git diff --name-only`). Gemini maps each image to the route file it shows, and a changed screen (under an `app/` directory) that no image shows makes the review REQUEST_CHANGES — partial screenshot coverage is as unreviewed as none. A changed file under `components/` only warns. The report prints a route → image coverage table.
|
|
253
|
+
- **`baseRef`** (optional, review mode): The git ref the diff is based on, such as `origin/main`. The tool resolves its merge base with HEAD in code and fails before calling Gemini when it does not resolve. Gemini may then run read-only `git diff <merge-base>...HEAD` (optionally `--name-only`, `-- <paths>`) and `git show <merge-base>:<path>`, so severity follows the branch's own diff (set `yolo: true`, since headless agy denies the shell otherwise); without it Gemini runs no git. Both modes bound Gemini's reads to the route file each image shows (or the plan's route file) and the components and primitives it renders, the changed files, the producer lines a capability check needs, and the cited rule files, READMEs and boards, and forbid running tests or npm and reading `node_modules` or release notes.
|
|
251
254
|
- **`conversationId`** (optional): Round 2 keeps round 1's visual analysis.
|
|
252
255
|
- **`model`** (optional, default `Gemini 3.8 Flash (Medium)`), **`printTimeout`** (optional, default `10m`).
|
|
253
256
|
- **`yolo`** (optional, default **false**): a review only reads. Set it to `true` when the instructions ask Gemini to read repository files that are not among the images — it reaches for a shell to do that, headless agy denies the shell, and the call fails naming the denied action.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agyModelSteps.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/agyModelSteps.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
6
|
+
import { agyConversationStore, countAgyModelSteps, formatModelSteps } from '../utils/agyModelSteps.js';
|
|
7
|
+
const CONVERSATION = '6a157307-cd13-4652-8725-f3500c103f2b';
|
|
8
|
+
const roots = [];
|
|
9
|
+
function storeWithSteps(stepTypes) {
|
|
10
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agy-steps-'));
|
|
11
|
+
roots.push(root);
|
|
12
|
+
const store = agyConversationStore(CONVERSATION, root);
|
|
13
|
+
fs.mkdirSync(path.dirname(store), { recursive: true });
|
|
14
|
+
const rows = stepTypes.map((type, idx) => `insert into steps (idx, step_type) values (${idx}, ${type});`).join('');
|
|
15
|
+
execFileSync('sqlite3', [store, `pragma journal_mode=wal;create table steps (idx integer primary key, step_type integer not null default 0);${rows}pragma wal_checkpoint(truncate);`]);
|
|
16
|
+
for (const side of ['-wal', '-shm'])
|
|
17
|
+
fs.rmSync(`${store}${side}`, { force: true });
|
|
18
|
+
return root;
|
|
19
|
+
}
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
for (const root of roots.splice(0))
|
|
22
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
23
|
+
});
|
|
24
|
+
describe('countAgyModelSteps', () => {
|
|
25
|
+
it("counts only agy's model steps (step_type 15), not the user turn or tool results", async () => {
|
|
26
|
+
const root = storeWithSteps([14, 15, 132, 15, 132, 15]);
|
|
27
|
+
await expect(countAgyModelSteps(CONVERSATION, root)).resolves.toBe(3);
|
|
28
|
+
});
|
|
29
|
+
it("reads agy's write-ahead-log store without leaving side files next to it", async () => {
|
|
30
|
+
const root = storeWithSteps([15, 15]);
|
|
31
|
+
const store = agyConversationStore(CONVERSATION, root);
|
|
32
|
+
await expect(countAgyModelSteps(CONVERSATION, root)).resolves.toBe(2);
|
|
33
|
+
expect(fs.readdirSync(path.dirname(store))).toEqual([path.basename(store)]);
|
|
34
|
+
});
|
|
35
|
+
it('is null when the conversation has no step store', async () => {
|
|
36
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agy-steps-'));
|
|
37
|
+
roots.push(root);
|
|
38
|
+
await expect(countAgyModelSteps(CONVERSATION, root)).resolves.toBeNull();
|
|
39
|
+
});
|
|
40
|
+
it('is null for a conversation id that is not a uuid, without touching the filesystem', async () => {
|
|
41
|
+
await expect(countAgyModelSteps('../../etc/passwd')).resolves.toBeNull();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('formatModelSteps', () => {
|
|
45
|
+
it('divides the steps by the reported frames, to one decimal', () => {
|
|
46
|
+
expect(formatModelSteps(81, 6)).toBe('Gemini steps: 81 (13.5 per frame, 6 frames)');
|
|
47
|
+
});
|
|
48
|
+
it('says so when no frame was reported', () => {
|
|
49
|
+
expect(formatModelSteps(12, 0)).toBe('Gemini steps: 12, no frames');
|
|
50
|
+
});
|
|
51
|
+
it('prints the bare count for a review, which has no frames', () => {
|
|
52
|
+
expect(formatModelSteps(9)).toBe('Gemini steps: 9');
|
|
53
|
+
});
|
|
54
|
+
it("marks an unreadable step store with ?", () => {
|
|
55
|
+
expect(formatModelSteps(null, 3)).toBe("Gemini steps: ? (agy's step store was unreadable)");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=agyModelSteps.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agyModelSteps.test.js","sourceRoot":"","sources":["../../src/__tests__/agyModelSteps.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture-script.chromium.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/capture-script.chromium.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import * as vm from 'vm';
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
6
|
+
import { chromium } from 'playwright-core';
|
|
7
|
+
import { LAYOUT_CHECK_SNIPPET, LIVE_PASS } from '../constants.js';
|
|
8
|
+
import { prescribedTargetFiles, writeCaptureScripts } from '../tools/live-pass.tool.js';
|
|
9
|
+
import { parseViewport, saveLayoutFunction } from '../utils/captureScript.js';
|
|
10
|
+
import { layoutFileName, readLayoutCheck } from '../utils/layoutCheck.js';
|
|
11
|
+
import { makeTempDir, cleanupTempDirs } from './utils/test-helpers.js';
|
|
12
|
+
const FIXTURES = path.join(path.dirname(fileURLToPath(import.meta.url)), 'fixtures', 'layout');
|
|
13
|
+
const START_VIEWPORT = { width: 1024, height: 768 };
|
|
14
|
+
// @playwright/mcp 0.0.84's runCode exposedGlobals, verbatim.
|
|
15
|
+
const RUN_CODE_EXPOSED_GLOBALS = [
|
|
16
|
+
'setTimeout',
|
|
17
|
+
'clearTimeout',
|
|
18
|
+
'setInterval',
|
|
19
|
+
'clearInterval',
|
|
20
|
+
'setImmediate',
|
|
21
|
+
'clearImmediate',
|
|
22
|
+
'queueMicrotask',
|
|
23
|
+
'URL',
|
|
24
|
+
'URLSearchParams',
|
|
25
|
+
'TextEncoder',
|
|
26
|
+
'TextDecoder',
|
|
27
|
+
'AbortController',
|
|
28
|
+
'AbortSignal',
|
|
29
|
+
'fetch',
|
|
30
|
+
'Headers',
|
|
31
|
+
'Request',
|
|
32
|
+
'Response',
|
|
33
|
+
'FormData',
|
|
34
|
+
'Blob',
|
|
35
|
+
'Buffer',
|
|
36
|
+
'crypto',
|
|
37
|
+
'atob',
|
|
38
|
+
'btoa',
|
|
39
|
+
'structuredClone',
|
|
40
|
+
];
|
|
41
|
+
let browser;
|
|
42
|
+
let page;
|
|
43
|
+
beforeAll(async () => {
|
|
44
|
+
browser = await chromium.launch();
|
|
45
|
+
page = await browser.newPage({ viewport: START_VIEWPORT });
|
|
46
|
+
});
|
|
47
|
+
afterAll(async () => {
|
|
48
|
+
await browser.close();
|
|
49
|
+
});
|
|
50
|
+
afterEach(cleanupTempDirs);
|
|
51
|
+
async function open(fixture) {
|
|
52
|
+
await page.setViewportSize(START_VIEWPORT);
|
|
53
|
+
await page.goto(pathToFileURL(path.join(FIXTURES, fixture)).href);
|
|
54
|
+
}
|
|
55
|
+
/** browser_run_code_unsafe {filename}: the file's text run as `(<text>)(page)` in a vm holding `page` and the exposed globals. */
|
|
56
|
+
async function runCaptureFile(file, runPage = page) {
|
|
57
|
+
const context = { page: runPage };
|
|
58
|
+
for (const name of RUN_CODE_EXPOSED_GLOBALS)
|
|
59
|
+
context[name] = globalThis[name];
|
|
60
|
+
vm.createContext(context);
|
|
61
|
+
context.__fn__ = vm.runInContext('(' + fs.readFileSync(file, 'utf-8') + ')', context);
|
|
62
|
+
return JSON.stringify(await vm.runInContext('__fn__(page)', context));
|
|
63
|
+
}
|
|
64
|
+
/** browser_evaluate {function, filename}: the result written as JSON, then read back by the report's validator. */
|
|
65
|
+
async function saveLayout(key, file, artifactDir, width) {
|
|
66
|
+
const runStartMs = Date.now();
|
|
67
|
+
const result = await page.evaluate(async (expression) => {
|
|
68
|
+
const value = eval(`(${expression})`);
|
|
69
|
+
return await (typeof value === 'function' ? value() : value);
|
|
70
|
+
}, saveLayoutFunction(key));
|
|
71
|
+
fs.writeFileSync(file, JSON.stringify(result, null, 2) ?? 'undefined', 'utf-8');
|
|
72
|
+
return readLayoutCheck(file, artifactDir, runStartMs, width);
|
|
73
|
+
}
|
|
74
|
+
/** The page, except that every setViewportSize after the screenshot attempt fails. */
|
|
75
|
+
function failingRestore(target) {
|
|
76
|
+
let shotAttempted = false;
|
|
77
|
+
return new Proxy(target, {
|
|
78
|
+
get(_page, prop) {
|
|
79
|
+
if (prop === 'screenshot') {
|
|
80
|
+
return async (...args) => {
|
|
81
|
+
try {
|
|
82
|
+
return await target.screenshot(...args);
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
shotAttempted = true;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (prop === 'setViewportSize') {
|
|
90
|
+
return async (size) => {
|
|
91
|
+
if (shotAttempted)
|
|
92
|
+
throw new Error('restore boom\n at the page');
|
|
93
|
+
return target.setViewportSize(size);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const value = Reflect.get(target, prop);
|
|
97
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function pngSize(file) {
|
|
102
|
+
const header = fs.readFileSync(file).subarray(0, 24);
|
|
103
|
+
return { width: header.readUInt32BE(16), height: header.readUInt32BE(20) };
|
|
104
|
+
}
|
|
105
|
+
function targetFiles(viewport, artifactDir) {
|
|
106
|
+
const target = { screen: 'screen', state: 'state', viewport, expected: 'x' };
|
|
107
|
+
writeCaptureScripts([target], artifactDir);
|
|
108
|
+
return [...prescribedTargetFiles([target], artifactDir).values()][0];
|
|
109
|
+
}
|
|
110
|
+
async function capture(viewport, artifactDir = makeTempDir('capture')) {
|
|
111
|
+
const files = targetFiles(viewport, artifactDir);
|
|
112
|
+
const result = await runCaptureFile(files.capture);
|
|
113
|
+
const viewportAfter = page.viewportSize();
|
|
114
|
+
const layout = await saveLayout(files.frameName, files.layout, artifactDir, parseViewport(viewport).width);
|
|
115
|
+
return { result, frameFile: files.frame, frameName: files.frameName, viewportAfter, layout };
|
|
116
|
+
}
|
|
117
|
+
describe('capture script in headless Chromium, run as browser_run_code_unsafe runs it', () => {
|
|
118
|
+
it.each([
|
|
119
|
+
['a page that fits beside an overflowing textarea and aria-hidden and inert scrollers', 'capture-fits.html', '390x844', 844],
|
|
120
|
+
['a page whose content ends 14 px above the bottom edge', 'capture-near-bottom.html', '390x844', 844],
|
|
121
|
+
['a page 1 px taller than the viewport, inside the rounding guard', 'capture-one-px.html', '390x844', 844],
|
|
122
|
+
['an RN-web screen with a fixed header, an inner scroller of tight text rows and a tab bar', 'capture-rn-web.html', '390x844', 1550],
|
|
123
|
+
['a flex-grow centred screen 12 px taller than 568', 'capture-centred.html', '320x568', 580],
|
|
124
|
+
['a screen 12 px taller than 568 with a bottom-anchored toast', 'capture-toast.html', '320x568', 580],
|
|
125
|
+
['an aria-modal sheet over a tall list', 'capture-sheet.html', '320x568', 568],
|
|
126
|
+
['two side-by-side scrollers, grown by the larger overflow only', 'capture-two-columns.html', '390x844', 1344],
|
|
127
|
+
['a list taller than the height cap', 'capture-tall-list.html', '390x844', 4000],
|
|
128
|
+
['a fixed-height inner scroller, which stops growing after one re-check', 'capture-fixed-scroller.html', '390x844', 1544],
|
|
129
|
+
['a scroller sharing its growth with a capped flex panel, grown three times until it fits', 'capture-shared-flex.html', '390x844', 1750],
|
|
130
|
+
])('captures %s at its known height and leaves the viewport at the target size', async (_label, fixture, viewport, shotHeight) => {
|
|
131
|
+
const { width, height } = parseViewport(viewport);
|
|
132
|
+
await open(fixture);
|
|
133
|
+
const shot = await capture(viewport);
|
|
134
|
+
expect(shot.result).toBe(JSON.stringify(`saved ${shot.frameFile} at ${width}x${shotHeight}`));
|
|
135
|
+
expect(pngSize(shot.frameFile)).toEqual({ width, height: shotHeight });
|
|
136
|
+
expect(shot.viewportAfter).toEqual({ width, height });
|
|
137
|
+
expect(shot.layout.status).toBe('OK');
|
|
138
|
+
});
|
|
139
|
+
it('stores the report of a page that fits, measured at the target viewport', async () => {
|
|
140
|
+
await open('capture-fits.html');
|
|
141
|
+
const shot = await capture('390x844');
|
|
142
|
+
expect(shot.layout.report).toEqual({
|
|
143
|
+
check: LIVE_PASS.LAYOUT_CHECK_ID,
|
|
144
|
+
viewport: { width: 390, height: 844 },
|
|
145
|
+
found: 0,
|
|
146
|
+
entries: [],
|
|
147
|
+
clamped: [],
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
it("stores the report of a scrolling screen, equal to the layout snippet run directly at the shot's size", async () => {
|
|
151
|
+
await open('capture-rn-web.html');
|
|
152
|
+
const shot = await capture('390x844');
|
|
153
|
+
await page.setViewportSize({ width: 390, height: 1550 });
|
|
154
|
+
const direct = await page.evaluate((expression) => eval(`(${expression})`)(), LAYOUT_CHECK_SNIPPET);
|
|
155
|
+
expect(shot.layout.report?.viewport).toEqual({ width: 390, height: 1550 });
|
|
156
|
+
expect(shot.layout.report).toEqual(direct);
|
|
157
|
+
});
|
|
158
|
+
it('shoots a pre-scrolled inner list at its full height from its first row', async () => {
|
|
159
|
+
await open('capture-rn-web.html');
|
|
160
|
+
const scrollTop = () => page.evaluate(() => document.querySelector('[data-testid="dance-list"]').scrollTop);
|
|
161
|
+
await page.evaluate(() => { document.querySelector('[data-testid="dance-list"]').scrollTop = 500; });
|
|
162
|
+
expect(await scrollTop()).toBe(500);
|
|
163
|
+
const shot = await capture('390x844');
|
|
164
|
+
expect(pngSize(shot.frameFile)).toEqual({ width: 390, height: 1550 });
|
|
165
|
+
expect(await scrollTop()).toBe(0);
|
|
166
|
+
});
|
|
167
|
+
it('still saves the frame and restores the viewport when the layout step throws, and leaves no earlier report behind', async () => {
|
|
168
|
+
await open('capture-fits.html');
|
|
169
|
+
await page.evaluate(() => {
|
|
170
|
+
window.__livePassLayout = { 'screen-state-390x844.png': { earlier: true } };
|
|
171
|
+
document.createRange = () => { throw new Error('layout boom'); };
|
|
172
|
+
});
|
|
173
|
+
const shot = await capture('390x844');
|
|
174
|
+
expect(shot.result).toBe(JSON.stringify(`saved ${shot.frameFile} at 390x844; layout not measured: page.evaluate: Error: layout boom`));
|
|
175
|
+
expect(pngSize(shot.frameFile)).toEqual({ width: 390, height: 844 });
|
|
176
|
+
expect(shot.viewportAfter).toEqual({ width: 390, height: 844 });
|
|
177
|
+
expect(shot.layout).toMatchObject({ status: 'MALFORMED', problem: 'not valid JSON' });
|
|
178
|
+
});
|
|
179
|
+
it('fails the capture when the screenshot cannot be saved, and still restores the viewport it grew', async () => {
|
|
180
|
+
const artifactDir = makeTempDir('capture');
|
|
181
|
+
const files = targetFiles('390x844', artifactDir);
|
|
182
|
+
fs.mkdirSync(files.frame);
|
|
183
|
+
await open('capture-rn-web.html');
|
|
184
|
+
await expect(runCaptureFile(files.capture)).rejects.toThrow(/EISDIR/);
|
|
185
|
+
expect(page.viewportSize()).toEqual({ width: 390, height: 844 });
|
|
186
|
+
});
|
|
187
|
+
it('notes a failed restore after a failed layout step, and still answers saved', async () => {
|
|
188
|
+
await open('capture-fits.html');
|
|
189
|
+
await page.evaluate(() => { document.createRange = () => { throw new Error('layout boom'); }; });
|
|
190
|
+
const files = targetFiles('390x844', makeTempDir('capture'));
|
|
191
|
+
const result = await runCaptureFile(files.capture, failingRestore(page));
|
|
192
|
+
expect(result).toBe(JSON.stringify(`saved ${files.frame} at 390x844; layout not measured: page.evaluate: Error: layout boom; viewport not restored: restore boom`));
|
|
193
|
+
expect(pngSize(files.frame)).toEqual({ width: 390, height: 844 });
|
|
194
|
+
});
|
|
195
|
+
it('throws the screenshot error, not the restore error, when both fail', async () => {
|
|
196
|
+
const files = targetFiles('390x844', makeTempDir('capture'));
|
|
197
|
+
fs.mkdirSync(files.frame);
|
|
198
|
+
await open('capture-rn-web.html');
|
|
199
|
+
const running = runCaptureFile(files.capture, failingRestore(page));
|
|
200
|
+
await expect(running).rejects.toThrow(/EISDIR/);
|
|
201
|
+
await expect(running).rejects.not.toThrow(/restore boom/);
|
|
202
|
+
});
|
|
203
|
+
it('captures a quirks-mode page whose body scrolls, where document.scrollingElement is null', async () => {
|
|
204
|
+
await open('capture-quirks.html');
|
|
205
|
+
expect(await page.evaluate(() => [document.compatMode, document.scrollingElement])).toEqual(['BackCompat', null]);
|
|
206
|
+
const shot = await capture('390x844');
|
|
207
|
+
expect(shot.result).toBe(JSON.stringify(`saved ${shot.frameFile} at 390x1200`));
|
|
208
|
+
expect(pngSize(shot.frameFile)).toEqual({ width: 390, height: 1200 });
|
|
209
|
+
expect(shot.viewportAfter).toEqual({ width: 390, height: 844 });
|
|
210
|
+
});
|
|
211
|
+
it('captures to the right file when the worktree path holds quotes, a backslash and ${', async () => {
|
|
212
|
+
const artifactDir = path.join(makeTempDir('capture'), `it's "a" \\ \${x}`, '.live-pass');
|
|
213
|
+
fs.mkdirSync(artifactDir, { recursive: true });
|
|
214
|
+
await open('capture-fits.html');
|
|
215
|
+
const shot = await capture('390x844', artifactDir);
|
|
216
|
+
expect(shot.frameFile.startsWith(artifactDir)).toBe(true);
|
|
217
|
+
expect(shot.result).toBe(JSON.stringify(`saved ${shot.frameFile} at 390x844`));
|
|
218
|
+
expect(pngSize(shot.frameFile)).toEqual({ width: 390, height: 844 });
|
|
219
|
+
expect(shot.layout.status).toBe('OK');
|
|
220
|
+
});
|
|
221
|
+
it('saves undefined for a key whose capture never ran, which the report reads as not run', async () => {
|
|
222
|
+
const artifactDir = makeTempDir('capture');
|
|
223
|
+
const file = path.join(artifactDir, layoutFileName('never-captured.png'));
|
|
224
|
+
await open('capture-fits.html');
|
|
225
|
+
const beforeAnyCapture = await saveLayout('never-captured.png', file, artifactDir, 390);
|
|
226
|
+
await page.evaluate(() => {
|
|
227
|
+
window.__livePassLayout = { 'another-target.png': { check: 'layout-check/1' } };
|
|
228
|
+
});
|
|
229
|
+
const besideAnotherReport = await saveLayout('never-captured.png', file, artifactDir, 390);
|
|
230
|
+
expect(fs.readFileSync(file, 'utf-8')).toBe('undefined');
|
|
231
|
+
expect(beforeAnyCapture).toMatchObject({ status: 'MALFORMED', problem: 'not valid JSON' });
|
|
232
|
+
expect(besideAnotherReport).toMatchObject({ status: 'MALFORMED', problem: 'not valid JSON' });
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
//# sourceMappingURL=capture-script.chromium.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture-script.chromium.test.js","sourceRoot":"","sources":["../../src/__tests__/capture-script.chromium.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout-snippet.chromium.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/layout-snippet.chromium.test.ts"],"names":[],"mappings":""}
|