@monoes/monobrowse 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/__tests__/box-model.test.d.ts +2 -0
- package/dist/src/__tests__/box-model.test.d.ts.map +1 -0
- package/dist/src/__tests__/box-model.test.js +36 -0
- package/dist/src/__tests__/box-model.test.js.map +1 -0
- package/dist/src/browser/snapshot.d.ts +11 -0
- package/dist/src/browser/snapshot.d.ts.map +1 -1
- package/dist/src/browser/snapshot.js +11 -0
- package/dist/src/browser/snapshot.js.map +1 -1
- package/dist/src/cli/commands.d.ts +21 -0
- package/dist/src/cli/commands.d.ts.map +1 -1
- package/dist/src/cli/commands.js +27 -3
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/__tests__/box-model.test.ts +39 -0
- package/src/browser/snapshot.ts +11 -0
- package/src/cli/commands.ts +29 -3
package/package.json
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { deriveBoxOutput } from '../cli/commands.js';
|
|
3
|
+
import { getElementBox } from '../browser/snapshot.js';
|
|
4
|
+
import type { ElementRef } from '../browser/types.js';
|
|
5
|
+
|
|
6
|
+
describe('getElementBox (issue #15: center-vs-top-left contract)', () => {
|
|
7
|
+
it('averages the CDP content quad\'s four corners into a center point', async () => {
|
|
8
|
+
// Content quad order per CDP DOM.getBoxModel: [x1,y1 top-left, x2,y2
|
|
9
|
+
// top-right, x3,y3 bottom-right, x4,y4 bottom-left]. A 372x37 box whose
|
|
10
|
+
// top-left is (454, 513.5) — matching the issue's own reproduction data.
|
|
11
|
+
const client = {
|
|
12
|
+
send: vi.fn().mockResolvedValue({
|
|
13
|
+
model: {
|
|
14
|
+
content: [454, 513.5, 826, 513.5, 826, 550.5, 454, 550.5],
|
|
15
|
+
width: 372,
|
|
16
|
+
height: 37,
|
|
17
|
+
},
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
const ref = { backendDOMNodeId: 1 } as unknown as ElementRef;
|
|
21
|
+
const box = await getElementBox(client as any, 'session-1', ref);
|
|
22
|
+
expect(box).toEqual({ x: 640, y: 532, width: 372, height: 37 });
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('deriveBoxOutput (issue #15: get box exposing both conventions)', () => {
|
|
27
|
+
it('derives true top-left x/y from the center point, alongside explicit centerX/centerY', () => {
|
|
28
|
+
const center = { x: 640, y: 532, width: 372, height: 37 };
|
|
29
|
+
const result = deriveBoxOutput(center);
|
|
30
|
+
expect(result).toEqual({
|
|
31
|
+
x: 454, y: 513.5, width: 372, height: 37,
|
|
32
|
+
centerX: 640, centerY: 532,
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('returns null when there is no box (element not in DOM)', () => {
|
|
37
|
+
expect(deriveBoxOutput(null)).toBeNull();
|
|
38
|
+
});
|
|
39
|
+
});
|
package/src/browser/snapshot.ts
CHANGED
|
@@ -217,6 +217,17 @@ export async function getObjectIdForRef(
|
|
|
217
217
|
return result.object?.objectId ?? null;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Returns the element's content box — but `x`/`y` are the CENTER point
|
|
222
|
+
* (averaged across all four corners of CDP's content quad), not the
|
|
223
|
+
* top-left origin a `getBoundingClientRect()`-style box normally implies.
|
|
224
|
+
* This is deliberate: every caller in this file (clickElement, fillElement,
|
|
225
|
+
* hoverElement, dragElement, ...) uses box.x/box.y directly as the
|
|
226
|
+
* interaction target, which should land at the element's center. Do NOT
|
|
227
|
+
* add width/2 or height/2 to these values — that double-offsets away from
|
|
228
|
+
* the element (see issue #15). If you need the true top-left origin, derive
|
|
229
|
+
* it as `x - width / 2, y - height / 2`.
|
|
230
|
+
*/
|
|
220
231
|
export async function getElementBox(
|
|
221
232
|
client: CdpClient,
|
|
222
233
|
sessionId: string,
|
package/src/cli/commands.ts
CHANGED
|
@@ -777,7 +777,8 @@ const getCommand: Command = {
|
|
|
777
777
|
const refKey = refArg.startsWith('@') ? refArg.slice(1) : refArg;
|
|
778
778
|
const ref = _refs.get(refKey);
|
|
779
779
|
if (!ref) throw new Error(`Ref @${refKey} not found`);
|
|
780
|
-
|
|
780
|
+
const center = await browser.getElementBox(client, sessionId, ref);
|
|
781
|
+
value = deriveBoxOutput(center);
|
|
781
782
|
break;
|
|
782
783
|
}
|
|
783
784
|
case 'styles': {
|
|
@@ -1591,8 +1592,11 @@ const tapCommand: Command = {
|
|
|
1591
1592
|
const ref = await browser.resolveRef(client, sessionId, _refs, key);
|
|
1592
1593
|
const box = await browser.getElementBox(client, sessionId, ref);
|
|
1593
1594
|
if (!box) throw new Error(`Cannot get bounds for @${key}`);
|
|
1594
|
-
|
|
1595
|
-
|
|
1595
|
+
// box.x/box.y from getElementBox() ARE already the center point (see
|
|
1596
|
+
// its own doc comment) — adding width/2 here double-offset the tap
|
|
1597
|
+
// target away from the element (issue #15).
|
|
1598
|
+
x = Math.round(box.x);
|
|
1599
|
+
y = Math.round(box.y);
|
|
1596
1600
|
} else {
|
|
1597
1601
|
const posJson = await browser.evaluateJs(client, sessionId,
|
|
1598
1602
|
`(function(){var el=document.querySelector(${JSON.stringify(arg)});if(!el)return null;var r=el.getBoundingClientRect();return JSON.stringify({x:r.left+r.width/2,y:r.top+r.height/2});})()`) as string | null;
|
|
@@ -2497,8 +2501,30 @@ function tokenizeBatchCommand(input: string): string[] {
|
|
|
2497
2501
|
* only its own known --flags are consumed from the front; everything after
|
|
2498
2502
|
* them is taken verbatim as one argument, untouched by tokenization.
|
|
2499
2503
|
*
|
|
2504
|
+
/**
|
|
2505
|
+
* `get box`'s output shape: browser.getElementBox() returns the element's
|
|
2506
|
+
* CENTER point under x/y (correct for internal click-target callers), but
|
|
2507
|
+
* `get box` is a bounding-box accessor where x/y conventionally means the
|
|
2508
|
+
* top-left origin — a caller computing its own center as `box.x + width/2`
|
|
2509
|
+
* would otherwise double-offset away from the element (issue #15). Expose
|
|
2510
|
+
* both conventions, explicitly labeled, so neither is ambiguous.
|
|
2511
|
+
*
|
|
2500
2512
|
* Exported for direct unit testing — not part of the CLI's public API.
|
|
2501
2513
|
*/
|
|
2514
|
+
export function deriveBoxOutput(
|
|
2515
|
+
center: { x: number; y: number; width: number; height: number } | null
|
|
2516
|
+
): { x: number; y: number; width: number; height: number; centerX: number; centerY: number } | null {
|
|
2517
|
+
if (!center) return null;
|
|
2518
|
+
return {
|
|
2519
|
+
x: center.x - center.width / 2,
|
|
2520
|
+
y: center.y - center.height / 2,
|
|
2521
|
+
width: center.width,
|
|
2522
|
+
height: center.height,
|
|
2523
|
+
centerX: center.x,
|
|
2524
|
+
centerY: center.y,
|
|
2525
|
+
};
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2502
2528
|
export function parseBatchCommandLine(cmdStr: string): { subName: string; subArgs: string[]; flags: Record<string, unknown> } {
|
|
2503
2529
|
const trimmed = cmdStr.trim();
|
|
2504
2530
|
const evalMatch = trimmed.match(/^eval\b\s*/);
|