mcp-web-inspector 0.1.1 → 0.1.2
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/toolHandler.js
CHANGED
|
@@ -11,7 +11,7 @@ import { FindByTextTool } from './tools/browser/findByText.js';
|
|
|
11
11
|
import { GetComputedStylesTool } from './tools/browser/computedStyles.js';
|
|
12
12
|
import { MeasureElementTool } from './tools/browser/measureElement.js';
|
|
13
13
|
import { ElementExistsTool } from './tools/browser/elementExists.js';
|
|
14
|
-
import {
|
|
14
|
+
import { CompareElementAlignmentTool } from './tools/browser/compareElementAlignment.js';
|
|
15
15
|
import { GoBackTool, GoForwardTool } from './tools/browser/navigation.js';
|
|
16
16
|
import { DragTool, PressKeyTool } from './tools/browser/interaction.js';
|
|
17
17
|
import { WaitForElementTool } from './tools/browser/waitForElement.js';
|
|
@@ -96,7 +96,7 @@ let findByTextTool;
|
|
|
96
96
|
let getComputedStylesTool;
|
|
97
97
|
let measureElementTool;
|
|
98
98
|
let elementExistsTool;
|
|
99
|
-
let
|
|
99
|
+
let compareElementAlignmentTool;
|
|
100
100
|
let waitForElementTool;
|
|
101
101
|
let waitForNetworkIdleTool;
|
|
102
102
|
let listNetworkRequestsTool;
|
|
@@ -510,8 +510,8 @@ function initializeTools(server) {
|
|
|
510
510
|
measureElementTool = new MeasureElementTool(server);
|
|
511
511
|
if (!elementExistsTool)
|
|
512
512
|
elementExistsTool = new ElementExistsTool(server);
|
|
513
|
-
if (!
|
|
514
|
-
|
|
513
|
+
if (!compareElementAlignmentTool)
|
|
514
|
+
compareElementAlignmentTool = new CompareElementAlignmentTool(server);
|
|
515
515
|
if (!waitForElementTool)
|
|
516
516
|
waitForElementTool = new WaitForElementTool(server);
|
|
517
517
|
if (!waitForNetworkIdleTool)
|
|
@@ -651,8 +651,8 @@ export async function handleToolCall(name, args, server) {
|
|
|
651
651
|
return await measureElementTool.execute(args, context);
|
|
652
652
|
case "element_exists":
|
|
653
653
|
return await elementExistsTool.execute(args, context);
|
|
654
|
-
case "
|
|
655
|
-
return await
|
|
654
|
+
case "compare_element_alignment":
|
|
655
|
+
return await compareElementAlignmentTool.execute(args, context);
|
|
656
656
|
case "wait_for_element":
|
|
657
657
|
return await waitForElementTool.execute(args, context);
|
|
658
658
|
case "wait_for_network_idle":
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BrowserToolBase } from './base.js';
|
|
2
|
+
import { ToolContext, ToolResponse } from '../common/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Tool for comparing alignment of two elements
|
|
5
|
+
*/
|
|
6
|
+
export declare class CompareElementAlignmentTool extends BrowserToolBase {
|
|
7
|
+
/**
|
|
8
|
+
* Execute the compare element alignment tool
|
|
9
|
+
*/
|
|
10
|
+
execute(args: any, context: ToolContext): Promise<ToolResponse>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { BrowserToolBase } from './base.js';
|
|
2
|
+
import { createSuccessResponse, createErrorResponse } from '../common/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Tool for comparing alignment of two elements
|
|
5
|
+
*/
|
|
6
|
+
export class CompareElementAlignmentTool extends BrowserToolBase {
|
|
7
|
+
/**
|
|
8
|
+
* Execute the compare element alignment tool
|
|
9
|
+
*/
|
|
10
|
+
async execute(args, context) {
|
|
11
|
+
return this.safeExecute(context, async (page) => {
|
|
12
|
+
const selector1 = this.normalizeSelector(args.selector1);
|
|
13
|
+
const selector2 = this.normalizeSelector(args.selector2);
|
|
14
|
+
try {
|
|
15
|
+
// Get locators for both elements
|
|
16
|
+
const locator1 = page.locator(selector1);
|
|
17
|
+
const locator2 = page.locator(selector2);
|
|
18
|
+
// Check if both elements exist
|
|
19
|
+
const count1 = await locator1.count();
|
|
20
|
+
const count2 = await locator2.count();
|
|
21
|
+
if (count1 === 0) {
|
|
22
|
+
return createErrorResponse(`First element not found: ${args.selector1}`);
|
|
23
|
+
}
|
|
24
|
+
if (count2 === 0) {
|
|
25
|
+
return createErrorResponse(`Second element not found: ${args.selector2}`);
|
|
26
|
+
}
|
|
27
|
+
// Handle multiple matches by using first() - show warning
|
|
28
|
+
const targetLocator1 = count1 > 1 ? locator1.first() : locator1;
|
|
29
|
+
const targetLocator2 = count2 > 1 ? locator2.first() : locator2;
|
|
30
|
+
let warnings = '';
|
|
31
|
+
if (count1 > 1) {
|
|
32
|
+
warnings += `⚠ Warning: First selector matched ${count1} elements, using first\n`;
|
|
33
|
+
}
|
|
34
|
+
if (count2 > 1) {
|
|
35
|
+
warnings += `⚠ Warning: Second selector matched ${count2} elements, using first\n`;
|
|
36
|
+
}
|
|
37
|
+
if (warnings) {
|
|
38
|
+
warnings += '\n';
|
|
39
|
+
}
|
|
40
|
+
// Get bounding boxes
|
|
41
|
+
const box1 = await targetLocator1.boundingBox();
|
|
42
|
+
const box2 = await targetLocator2.boundingBox();
|
|
43
|
+
// Get element descriptors
|
|
44
|
+
const getDescriptor = async (locator) => {
|
|
45
|
+
return await locator.evaluate((element) => {
|
|
46
|
+
const tagName = element.tagName.toLowerCase();
|
|
47
|
+
const testId = element.getAttribute('data-testid') || element.getAttribute('data-test') || element.getAttribute('data-cy');
|
|
48
|
+
const id = element.id ? `#${element.id}` : '';
|
|
49
|
+
const classes = element.className && typeof element.className === 'string'
|
|
50
|
+
? `.${element.className.split(' ').filter(c => c).join('.')}`
|
|
51
|
+
: '';
|
|
52
|
+
let descriptor = `<${tagName}`;
|
|
53
|
+
if (testId)
|
|
54
|
+
descriptor += ` data-testid="${testId}"`;
|
|
55
|
+
else if (id)
|
|
56
|
+
descriptor += id;
|
|
57
|
+
else if (classes)
|
|
58
|
+
descriptor += classes;
|
|
59
|
+
descriptor += '>';
|
|
60
|
+
return descriptor;
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
const descriptor1 = await getDescriptor(targetLocator1);
|
|
64
|
+
const descriptor2 = await getDescriptor(targetLocator2);
|
|
65
|
+
// Handle hidden elements
|
|
66
|
+
if (!box1) {
|
|
67
|
+
return createErrorResponse(`First element is hidden or has no dimensions: ${descriptor1}`);
|
|
68
|
+
}
|
|
69
|
+
if (!box2) {
|
|
70
|
+
return createErrorResponse(`Second element is hidden or has no dimensions: ${descriptor2}`);
|
|
71
|
+
}
|
|
72
|
+
// Extract short name from descriptor for compact output
|
|
73
|
+
const getShortName = (descriptor, selector) => {
|
|
74
|
+
const testIdMatch = descriptor.match(/data-testid="([^"]+)"/);
|
|
75
|
+
if (testIdMatch)
|
|
76
|
+
return testIdMatch[1];
|
|
77
|
+
const idMatch = descriptor.match(/#([^>]+)/);
|
|
78
|
+
if (idMatch)
|
|
79
|
+
return idMatch[1];
|
|
80
|
+
// Use original selector if available
|
|
81
|
+
return selector;
|
|
82
|
+
};
|
|
83
|
+
const name1 = getShortName(descriptor1, args.selector1);
|
|
84
|
+
const name2 = getShortName(descriptor2, args.selector2);
|
|
85
|
+
// Calculate all alignment values
|
|
86
|
+
const tolerance = 2; // Allow 2px tolerance for rounding
|
|
87
|
+
// Edge positions
|
|
88
|
+
const top1 = Math.round(box1.y);
|
|
89
|
+
const top2 = Math.round(box2.y);
|
|
90
|
+
const topDiff = Math.abs(top1 - top2);
|
|
91
|
+
const topAligned = topDiff <= tolerance;
|
|
92
|
+
const left1 = Math.round(box1.x);
|
|
93
|
+
const left2 = Math.round(box2.x);
|
|
94
|
+
const leftDiff = Math.abs(left1 - left2);
|
|
95
|
+
const leftAligned = leftDiff <= tolerance;
|
|
96
|
+
const right1 = Math.round(box1.x + box1.width);
|
|
97
|
+
const right2 = Math.round(box2.x + box2.width);
|
|
98
|
+
const rightDiff = Math.abs(right1 - right2);
|
|
99
|
+
const rightAligned = rightDiff <= tolerance;
|
|
100
|
+
const bottom1 = Math.round(box1.y + box1.height);
|
|
101
|
+
const bottom2 = Math.round(box2.y + box2.height);
|
|
102
|
+
const bottomDiff = Math.abs(bottom1 - bottom2);
|
|
103
|
+
const bottomAligned = bottomDiff <= tolerance;
|
|
104
|
+
// Center positions
|
|
105
|
+
const centerH1 = Math.round(box1.x + box1.width / 2);
|
|
106
|
+
const centerH2 = Math.round(box2.x + box2.width / 2);
|
|
107
|
+
const centerHDiff = Math.abs(centerH1 - centerH2);
|
|
108
|
+
const centerHAligned = centerHDiff <= tolerance;
|
|
109
|
+
const centerV1 = Math.round(box1.y + box1.height / 2);
|
|
110
|
+
const centerV2 = Math.round(box2.y + box2.height / 2);
|
|
111
|
+
const centerVDiff = Math.abs(centerV1 - centerV2);
|
|
112
|
+
const centerVAligned = centerVDiff <= tolerance;
|
|
113
|
+
// Dimensions
|
|
114
|
+
const width1 = Math.round(box1.width);
|
|
115
|
+
const width2 = Math.round(box2.width);
|
|
116
|
+
const widthDiff = Math.abs(width1 - width2);
|
|
117
|
+
const widthSame = widthDiff <= tolerance;
|
|
118
|
+
const height1 = Math.round(box1.height);
|
|
119
|
+
const height2 = Math.round(box2.height);
|
|
120
|
+
const heightDiff = Math.abs(height1 - height2);
|
|
121
|
+
const heightSame = heightDiff <= tolerance;
|
|
122
|
+
// Format compact output
|
|
123
|
+
const formatAlignment = (aligned, val1, val2, diff, unit = 'px') => {
|
|
124
|
+
const symbol = aligned ? '✓' : '✗';
|
|
125
|
+
const status = aligned ? 'aligned' : 'not aligned';
|
|
126
|
+
if (aligned) {
|
|
127
|
+
return `${symbol} ${status} (both @ ${val1}${unit})`;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
return `${symbol} ${status} (${val1}${unit} vs ${val2}${unit}, diff: ${diff}${unit})`;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
const formatDimension = (same, val1, val2, diff, unit = 'px') => {
|
|
134
|
+
const symbol = same ? '✓' : '✗';
|
|
135
|
+
const status = same ? 'same' : 'different';
|
|
136
|
+
if (same) {
|
|
137
|
+
return `${symbol} ${status} (${val1}${unit})`;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
return `${symbol} ${status} (${val1}${unit} vs ${val2}${unit}, diff: ${diff}${unit})`;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
// Build output
|
|
144
|
+
const lines = [
|
|
145
|
+
warnings,
|
|
146
|
+
`Alignment: ${descriptor1} vs ${descriptor2}`,
|
|
147
|
+
` ${name1}: @ (${left1},${top1}) ${width1}×${height1}px`,
|
|
148
|
+
` ${name2}: @ (${left2},${top2}) ${width2}×${height2}px`,
|
|
149
|
+
'',
|
|
150
|
+
'Edges:',
|
|
151
|
+
` Top: ${formatAlignment(topAligned, top1, top2, topDiff)}`,
|
|
152
|
+
` Left: ${formatAlignment(leftAligned, left1, left2, leftDiff)}`,
|
|
153
|
+
` Right: ${formatAlignment(rightAligned, right1, right2, rightDiff)}`,
|
|
154
|
+
` Bottom: ${formatAlignment(bottomAligned, bottom1, bottom2, bottomDiff)}`,
|
|
155
|
+
'',
|
|
156
|
+
'Centers:',
|
|
157
|
+
` Horizontal: ${formatAlignment(centerHAligned, centerH1, centerH2, centerHDiff)}`,
|
|
158
|
+
` Vertical: ${formatAlignment(centerVAligned, centerV1, centerV2, centerVDiff)}`,
|
|
159
|
+
'',
|
|
160
|
+
'Dimensions:',
|
|
161
|
+
` Width: ${formatDimension(widthSame, width1, width2, widthDiff)}`,
|
|
162
|
+
` Height: ${formatDimension(heightSame, height1, height2, heightDiff)}`
|
|
163
|
+
];
|
|
164
|
+
return createSuccessResponse(lines.filter(l => l !== undefined).join('\n'));
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
return createErrorResponse(`Failed to compare element alignment: ${error.message}`);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -391,6 +391,13 @@ export class InspectDomTool extends BrowserToolBase {
|
|
|
391
391
|
lines.push(`${prefix} ${tag}${roleInfo}`);
|
|
392
392
|
// Position
|
|
393
393
|
lines.push(` @ (${child.position.x},${child.position.y}) ${child.position.width}x${child.position.height}px`);
|
|
394
|
+
// Calculate distances from all parent edges
|
|
395
|
+
const fromLeft = child.position.x - target.position.x;
|
|
396
|
+
const fromRight = (target.position.x + target.position.width) - (child.position.x + child.position.width);
|
|
397
|
+
const fromTop = child.position.y - target.position.y;
|
|
398
|
+
const fromBottom = (target.position.y + target.position.height) - (child.position.y + child.position.height);
|
|
399
|
+
// Format edge distances (centering is obvious: equal left/right = horizontal center, equal top/bottom = vertical center)
|
|
400
|
+
lines.push(` from edges: ←${fromLeft}px →${fromRight}px ↑${fromTop}px ↓${fromBottom}px`);
|
|
394
401
|
// Calculate offset from previous sibling
|
|
395
402
|
if (index > 0) {
|
|
396
403
|
const prev = children[index - 1];
|
package/dist/tools.d.ts
CHANGED
|
@@ -314,7 +314,7 @@ export declare function createToolDefinitions(sessionConfig?: SessionConfig): [{
|
|
|
314
314
|
};
|
|
315
315
|
}, {
|
|
316
316
|
readonly name: "inspect_dom";
|
|
317
|
-
readonly description: "START HERE FOR LAYOUT DEBUGGING:
|
|
317
|
+
readonly description: "START HERE FOR LAYOUT DEBUGGING: Progressive DOM inspection that shows parent-child relationships, centering issues, and spacing gaps. Skips wrapper divs and shows only semantic elements (header, nav, main, form, button, elements with test IDs, ARIA roles, etc.).\n\nWORKFLOW: Call without selector for page overview, then drill down by calling with child's selector.\n\nDETECTS: Parent-relative positioning, vertical/horizontal centering, sibling spacing gaps, layout patterns.\n\nOUTPUT FORMAT:\n[0] <button data-testid=\"menu\">\n @ (16,8) 40×40px ← Absolute viewport position (x,y) and size\n from edges: ←16px →1144px ↑8px ↓8px ← Distance from parent edges (↑8px = ↓8px means vertically centered)\n \"Menu\"\n ✓ visible, ⚡ interactive\n\n[1] <div data-testid=\"title\">\n @ (260,2) 131×28px\n from edges: ←244px →244px ↑2px ↓42px ← Equal left/right (244px) = horizontally centered, unequal top/bottom = NOT vertically centered\n gap from [0]: →16px ← Spacing between siblings\n \"Title\"\n ✓ visible, 2 children\n\nSYMBOLS: ✓=visible, ✗=hidden, ⚡=interactive, ←→=horizontal edges, ↑↓=vertical edges\nCENTERING: Equal left/right distances = horizontally centered, equal top/bottom = vertically centered\n\nRELATED TOOLS: For comparing TWO elements' alignment (not parent-child), use compare_element_alignment(). For box model (padding/margin), use measure_element().\n\nMore efficient than get_html() or evaluate(). Supports testid shortcuts.";
|
|
318
318
|
readonly inputSchema: {
|
|
319
319
|
readonly type: "object";
|
|
320
320
|
readonly properties: {
|
|
@@ -427,7 +427,7 @@ export declare function createToolDefinitions(sessionConfig?: SessionConfig): [{
|
|
|
427
427
|
};
|
|
428
428
|
}, {
|
|
429
429
|
readonly name: "measure_element";
|
|
430
|
-
readonly description: "DEBUG SPACING ISSUES: See padding, margin, and border measurements in visual box model format. Use when elements have unexpected spacing or size. Returns compact visual representation showing content → padding → border → margin with directional arrows (↑24px for top margin, etc.). More readable than get_computed_styles() for box model debugging.";
|
|
430
|
+
readonly description: "DEBUG SPACING ISSUES: See padding, margin, and border measurements in visual box model format. Use when elements have unexpected spacing or size. Returns compact visual representation showing content → padding → border → margin with directional arrows (↑24px for top margin, etc.). For parent-child centering issues, use inspect_dom() first (shows if child is centered in parent). For comparing alignment between two elements, use compare_element_alignment(). More readable than get_computed_styles() for box model debugging.";
|
|
431
431
|
readonly inputSchema: {
|
|
432
432
|
readonly type: "object";
|
|
433
433
|
readonly properties: {
|
|
@@ -452,8 +452,8 @@ export declare function createToolDefinitions(sessionConfig?: SessionConfig): [{
|
|
|
452
452
|
readonly required: readonly ["selector"];
|
|
453
453
|
};
|
|
454
454
|
}, {
|
|
455
|
-
readonly name: "
|
|
456
|
-
readonly description: "
|
|
455
|
+
readonly name: "compare_element_alignment";
|
|
456
|
+
readonly description: "COMPARE TWO ELEMENTS: Get comprehensive alignment and dimension comparison in one call. Shows edge alignment (top, left, right, bottom), center alignment (horizontal, vertical), and dimensions (width, height). Perfect for debugging 'are these headers aligned?' or 'do these panels match?'. Returns all alignment info with ✓/✗ symbols and pixel differences. For parent-child centering, use inspect_dom() instead (automatically shows if children are centered in parent). More efficient than evaluate() with manual getBoundingClientRect() calculations.";
|
|
457
457
|
readonly inputSchema: {
|
|
458
458
|
readonly type: "object";
|
|
459
459
|
readonly properties: {
|
|
@@ -465,13 +465,8 @@ export declare function createToolDefinitions(sessionConfig?: SessionConfig): [{
|
|
|
465
465
|
readonly type: "string";
|
|
466
466
|
readonly description: "CSS selector, text selector, or testid shorthand for the second element (e.g., 'testid:chat-header', '#secondary-header')";
|
|
467
467
|
};
|
|
468
|
-
readonly checkAlignment: {
|
|
469
|
-
readonly type: "string";
|
|
470
|
-
readonly description: "What to check: 'top', 'left', 'right', 'bottom' (edge alignment), or 'width', 'height' (dimension matching)";
|
|
471
|
-
readonly enum: readonly ["top", "left", "right", "bottom", "width", "height"];
|
|
472
|
-
};
|
|
473
468
|
};
|
|
474
|
-
readonly required: readonly ["selector1", "selector2"
|
|
469
|
+
readonly required: readonly ["selector1", "selector2"];
|
|
475
470
|
};
|
|
476
471
|
}, {
|
|
477
472
|
readonly name: "wait_for_element";
|
package/dist/tools.js
CHANGED
|
@@ -250,7 +250,32 @@ export function createToolDefinitions(sessionConfig) {
|
|
|
250
250
|
},
|
|
251
251
|
{
|
|
252
252
|
name: "inspect_dom",
|
|
253
|
-
description:
|
|
253
|
+
description: `START HERE FOR LAYOUT DEBUGGING: Progressive DOM inspection that shows parent-child relationships, centering issues, and spacing gaps. Skips wrapper divs and shows only semantic elements (header, nav, main, form, button, elements with test IDs, ARIA roles, etc.).
|
|
254
|
+
|
|
255
|
+
WORKFLOW: Call without selector for page overview, then drill down by calling with child's selector.
|
|
256
|
+
|
|
257
|
+
DETECTS: Parent-relative positioning, vertical/horizontal centering, sibling spacing gaps, layout patterns.
|
|
258
|
+
|
|
259
|
+
OUTPUT FORMAT:
|
|
260
|
+
[0] <button data-testid="menu">
|
|
261
|
+
@ (16,8) 40×40px ← Absolute viewport position (x,y) and size
|
|
262
|
+
from edges: ←16px →1144px ↑8px ↓8px ← Distance from parent edges (↑8px = ↓8px means vertically centered)
|
|
263
|
+
"Menu"
|
|
264
|
+
✓ visible, ⚡ interactive
|
|
265
|
+
|
|
266
|
+
[1] <div data-testid="title">
|
|
267
|
+
@ (260,2) 131×28px
|
|
268
|
+
from edges: ←244px →244px ↑2px ↓42px ← Equal left/right (244px) = horizontally centered, unequal top/bottom = NOT vertically centered
|
|
269
|
+
gap from [0]: →16px ← Spacing between siblings
|
|
270
|
+
"Title"
|
|
271
|
+
✓ visible, 2 children
|
|
272
|
+
|
|
273
|
+
SYMBOLS: ✓=visible, ✗=hidden, ⚡=interactive, ←→=horizontal edges, ↑↓=vertical edges
|
|
274
|
+
CENTERING: Equal left/right distances = horizontally centered, equal top/bottom = vertically centered
|
|
275
|
+
|
|
276
|
+
RELATED TOOLS: For comparing TWO elements' alignment (not parent-child), use compare_element_alignment(). For box model (padding/margin), use measure_element().
|
|
277
|
+
|
|
278
|
+
More efficient than get_html() or evaluate(). Supports testid shortcuts.`,
|
|
254
279
|
inputSchema: {
|
|
255
280
|
type: "object",
|
|
256
281
|
properties: {
|
|
@@ -368,7 +393,7 @@ export function createToolDefinitions(sessionConfig) {
|
|
|
368
393
|
},
|
|
369
394
|
{
|
|
370
395
|
name: "measure_element",
|
|
371
|
-
description: "DEBUG SPACING ISSUES: See padding, margin, and border measurements in visual box model format. Use when elements have unexpected spacing or size. Returns compact visual representation showing content → padding → border → margin with directional arrows (↑24px for top margin, etc.). More readable than get_computed_styles() for box model debugging.",
|
|
396
|
+
description: "DEBUG SPACING ISSUES: See padding, margin, and border measurements in visual box model format. Use when elements have unexpected spacing or size. Returns compact visual representation showing content → padding → border → margin with directional arrows (↑24px for top margin, etc.). For parent-child centering issues, use inspect_dom() first (shows if child is centered in parent). For comparing alignment between two elements, use compare_element_alignment(). More readable than get_computed_styles() for box model debugging.",
|
|
372
397
|
inputSchema: {
|
|
373
398
|
type: "object",
|
|
374
399
|
properties: {
|
|
@@ -395,8 +420,8 @@ export function createToolDefinitions(sessionConfig) {
|
|
|
395
420
|
},
|
|
396
421
|
},
|
|
397
422
|
{
|
|
398
|
-
name: "
|
|
399
|
-
description: "
|
|
423
|
+
name: "compare_element_alignment",
|
|
424
|
+
description: "COMPARE TWO ELEMENTS: Get comprehensive alignment and dimension comparison in one call. Shows edge alignment (top, left, right, bottom), center alignment (horizontal, vertical), and dimensions (width, height). Perfect for debugging 'are these headers aligned?' or 'do these panels match?'. Returns all alignment info with ✓/✗ symbols and pixel differences. For parent-child centering, use inspect_dom() instead (automatically shows if children are centered in parent). More efficient than evaluate() with manual getBoundingClientRect() calculations.",
|
|
400
425
|
inputSchema: {
|
|
401
426
|
type: "object",
|
|
402
427
|
properties: {
|
|
@@ -407,14 +432,9 @@ export function createToolDefinitions(sessionConfig) {
|
|
|
407
432
|
selector2: {
|
|
408
433
|
type: "string",
|
|
409
434
|
description: "CSS selector, text selector, or testid shorthand for the second element (e.g., 'testid:chat-header', '#secondary-header')"
|
|
410
|
-
},
|
|
411
|
-
checkAlignment: {
|
|
412
|
-
type: "string",
|
|
413
|
-
description: "What to check: 'top', 'left', 'right', 'bottom' (edge alignment), or 'width', 'height' (dimension matching)",
|
|
414
|
-
enum: ["top", "left", "right", "bottom", "width", "height"]
|
|
415
435
|
}
|
|
416
436
|
},
|
|
417
|
-
required: ["selector1", "selector2"
|
|
437
|
+
required: ["selector1", "selector2"],
|
|
418
438
|
},
|
|
419
439
|
},
|
|
420
440
|
{
|
|
@@ -502,7 +522,7 @@ export const BROWSER_TOOLS = [
|
|
|
502
522
|
"find_by_text",
|
|
503
523
|
// Visibility & Position
|
|
504
524
|
"check_visibility",
|
|
505
|
-
"
|
|
525
|
+
"compare_element_alignment",
|
|
506
526
|
"element_exists",
|
|
507
527
|
"wait_for_element",
|
|
508
528
|
"wait_for_network_idle",
|