@treelocator/runtime 0.4.7 → 0.6.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/.eslintignore +1 -0
- package/dist/_generated_styles.d.ts +1 -1
- package/dist/_generated_styles.js +20 -0
- package/dist/_generated_tree_icon.d.ts +1 -1
- package/dist/adapters/HtmlElementTreeNode.d.ts +2 -2
- package/dist/adapters/HtmlElementTreeNode.js +4 -6
- package/dist/adapters/createTreeNode.js +17 -44
- package/dist/adapters/detectFramework.d.ts +8 -0
- package/dist/adapters/detectFramework.js +25 -0
- package/dist/adapters/detectFramework.test.d.ts +1 -0
- package/dist/adapters/detectFramework.test.js +60 -0
- package/dist/adapters/jsx/jsxAdapter.js +54 -89
- package/dist/adapters/jsx/jsxAdapter.test.d.ts +1 -0
- package/dist/adapters/jsx/jsxAdapter.test.js +273 -0
- package/dist/adapters/nextjs/parseNextjsDataAttributes.js +1 -1
- package/dist/adapters/nextjs/parseNextjsDataAttributes.test.d.ts +1 -0
- package/dist/adapters/nextjs/parseNextjsDataAttributes.test.js +158 -0
- package/dist/adapters/react/findFiberByHtmlElement.d.ts +1 -1
- package/dist/adapters/react/findFiberByHtmlElement.js +1 -1
- package/dist/adapters/react/getAllParentsElementsAndRootComponent.js +4 -0
- package/dist/adapters/resolveAdapter.d.ts +1 -1
- package/dist/adapters/resolveAdapter.js +4 -8
- package/dist/adapters/svelte/svelteAdapter.test.d.ts +1 -0
- package/dist/adapters/svelte/svelteAdapter.test.js +280 -0
- package/dist/adapters/vue/vueAdapter.test.d.ts +1 -0
- package/dist/adapters/vue/vueAdapter.test.js +222 -0
- package/dist/browserApi.d.ts +148 -0
- package/dist/browserApi.js +146 -5
- package/dist/browserApi.test.d.ts +1 -0
- package/dist/browserApi.test.js +287 -0
- package/dist/components/RecordingPillButton.d.ts +11 -0
- package/dist/components/RecordingPillButton.js +202 -0
- package/dist/components/RecordingResults.d.ts +2 -0
- package/dist/components/RecordingResults.js +213 -78
- package/dist/components/Runtime.js +161 -554
- package/dist/components/SettingsPanel.d.ts +5 -0
- package/dist/components/SettingsPanel.js +312 -0
- package/dist/consoleCapture.d.ts +9 -0
- package/dist/consoleCapture.js +95 -0
- package/dist/dejitter/recorder.d.ts +7 -1
- package/dist/dejitter/recorder.js +64 -1
- package/dist/functions/cssRuleInspector.d.ts +83 -0
- package/dist/functions/cssRuleInspector.js +608 -0
- package/dist/functions/cssRuleInspector.test.d.ts +1 -0
- package/dist/functions/cssRuleInspector.test.js +439 -0
- package/dist/functions/deduplicateLabels.test.d.ts +1 -0
- package/dist/functions/deduplicateLabels.test.js +178 -0
- package/dist/functions/enrichAncestrySourceMaps.js +0 -1
- package/dist/functions/extractComputedStyles.d.ts +51 -0
- package/dist/functions/extractComputedStyles.js +447 -0
- package/dist/functions/extractComputedStyles.test.d.ts +1 -0
- package/dist/functions/extractComputedStyles.test.js +549 -0
- package/dist/functions/formatAncestryChain.d.ts +8 -0
- package/dist/functions/formatAncestryChain.js +21 -1
- package/dist/functions/formatAncestryChain.test.js +18 -0
- package/dist/functions/getUsableName.test.d.ts +1 -0
- package/dist/functions/getUsableName.test.js +219 -0
- package/dist/functions/isCombinationModifiersPressed.test.d.ts +1 -0
- package/dist/functions/isCombinationModifiersPressed.test.js +192 -0
- package/dist/functions/mergeRects.test.js +210 -1
- package/dist/functions/namedSnapshots.d.ts +52 -0
- package/dist/functions/namedSnapshots.js +161 -0
- package/dist/functions/namedSnapshots.test.d.ts +1 -0
- package/dist/functions/namedSnapshots.test.js +85 -0
- package/dist/functions/normalizeFilePath.test.d.ts +1 -0
- package/dist/functions/normalizeFilePath.test.js +66 -0
- package/dist/functions/parseDataId.test.d.ts +1 -0
- package/dist/functions/parseDataId.test.js +101 -0
- package/dist/hooks/getStorage.d.ts +3 -0
- package/dist/hooks/getStorage.js +17 -0
- package/dist/hooks/useEventListeners.d.ts +15 -0
- package/dist/hooks/useEventListeners.js +56 -0
- package/dist/hooks/useLocatorStorage.d.ts +18 -0
- package/dist/hooks/useLocatorStorage.js +41 -0
- package/dist/hooks/useLocatorStorage.test.d.ts +1 -0
- package/dist/hooks/useLocatorStorage.test.js +124 -0
- package/dist/hooks/useRecordingState.d.ts +43 -0
- package/dist/hooks/useRecordingState.js +387 -0
- package/dist/hooks/useSettings.d.ts +13 -0
- package/dist/hooks/useSettings.js +66 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +4 -2
- package/dist/initRuntime.d.ts +3 -1
- package/dist/initRuntime.js +4 -1
- package/dist/mcpBridge.d.ts +61 -0
- package/dist/mcpBridge.js +534 -0
- package/dist/mcpBridge.test.d.ts +1 -0
- package/dist/mcpBridge.test.js +248 -0
- package/dist/output.css +20 -0
- package/dist/visualDiff/diff.d.ts +9 -0
- package/dist/visualDiff/diff.js +209 -0
- package/dist/visualDiff/diff.test.d.ts +1 -0
- package/dist/visualDiff/diff.test.js +253 -0
- package/dist/visualDiff/settle.d.ts +3 -0
- package/dist/visualDiff/settle.js +50 -0
- package/dist/visualDiff/settle.test.d.ts +1 -0
- package/dist/visualDiff/settle.test.js +65 -0
- package/dist/visualDiff/snapshot.d.ts +4 -0
- package/dist/visualDiff/snapshot.js +84 -0
- package/dist/visualDiff/snapshot.test.d.ts +1 -0
- package/dist/visualDiff/snapshot.test.js +245 -0
- package/dist/visualDiff/types.d.ts +37 -0
- package/dist/visualDiff/types.js +1 -0
- package/package.json +2 -2
- package/scripts/wrapCSS.js +1 -1
- package/scripts/wrapImage.js +1 -1
- package/src/_generated_styles.ts +21 -1
- package/src/_generated_tree_icon.ts +1 -1
- package/src/adapters/HtmlElementTreeNode.ts +10 -7
- package/src/adapters/createTreeNode.ts +12 -51
- package/src/adapters/detectFramework.test.ts +73 -0
- package/src/adapters/detectFramework.ts +28 -0
- package/src/adapters/jsx/jsxAdapter.test.ts +240 -0
- package/src/adapters/jsx/jsxAdapter.ts +53 -106
- package/src/adapters/nextjs/parseNextjsDataAttributes.test.ts +212 -0
- package/src/adapters/nextjs/parseNextjsDataAttributes.ts +1 -1
- package/src/adapters/react/findDebugSource.ts +5 -6
- package/src/adapters/react/findFiberByHtmlElement.ts +3 -3
- package/src/adapters/react/getAllParentsElementsAndRootComponent.ts +3 -0
- package/src/adapters/react/reactAdapter.ts +1 -2
- package/src/adapters/resolveAdapter.ts +4 -14
- package/src/adapters/svelte/svelteAdapter.test.ts +334 -0
- package/src/adapters/vue/vueAdapter.test.ts +259 -0
- package/src/browserApi.test.ts +329 -0
- package/src/browserApi.ts +351 -4
- package/src/components/RecordingPillButton.tsx +301 -0
- package/src/components/RecordingResults.tsx +114 -13
- package/src/components/Runtime.tsx +176 -621
- package/src/components/SettingsPanel.tsx +339 -0
- package/src/consoleCapture.ts +113 -0
- package/src/dejitter/recorder.ts +67 -3
- package/src/functions/cssRuleInspector.test.ts +517 -0
- package/src/functions/cssRuleInspector.ts +708 -0
- package/src/functions/deduplicateLabels.test.ts +115 -0
- package/src/functions/enrichAncestrySourceMaps.ts +6 -3
- package/src/functions/extractComputedStyles.test.ts +681 -0
- package/src/functions/extractComputedStyles.ts +768 -0
- package/src/functions/formatAncestryChain.test.ts +23 -1
- package/src/functions/formatAncestryChain.ts +22 -1
- package/src/functions/getUsableName.test.ts +242 -0
- package/src/functions/isCombinationModifiersPressed.test.ts +156 -0
- package/src/functions/mergeRects.test.ts +111 -1
- package/src/functions/namedSnapshots.test.ts +106 -0
- package/src/functions/namedSnapshots.ts +232 -0
- package/src/functions/normalizeFilePath.test.ts +80 -0
- package/src/functions/parseDataId.test.ts +125 -0
- package/src/hooks/getStorage.ts +26 -0
- package/src/hooks/useEventListeners.ts +97 -0
- package/src/hooks/useLocatorStorage.test.ts +127 -0
- package/src/hooks/useLocatorStorage.ts +60 -0
- package/src/hooks/useRecordingState.ts +516 -0
- package/src/hooks/useSettings.ts +83 -0
- package/src/index.ts +10 -5
- package/src/initRuntime.ts +5 -0
- package/src/mcpBridge.test.ts +260 -0
- package/src/mcpBridge.ts +677 -0
- package/src/visualDiff/diff.test.ts +167 -0
- package/src/visualDiff/diff.ts +242 -0
- package/src/visualDiff/settle.test.ts +77 -0
- package/src/visualDiff/settle.ts +62 -0
- package/src/visualDiff/snapshot.test.ts +200 -0
- package/src/visualDiff/snapshot.ts +119 -0
- package/src/visualDiff/types.ts +40 -0
- package/tsconfig.json +3 -1
- package/vitest.config.ts +18 -0
- package/jest.config.ts +0 -195
package/src/browserApi.ts
CHANGED
|
@@ -3,11 +3,33 @@ import { createTreeNode } from "./adapters/createTreeNode";
|
|
|
3
3
|
import {
|
|
4
4
|
collectAncestry,
|
|
5
5
|
formatAncestryChain,
|
|
6
|
+
getElementLabel,
|
|
6
7
|
AncestryItem,
|
|
7
8
|
} from "./functions/formatAncestryChain";
|
|
8
9
|
import { enrichAncestryWithSourceMaps } from "./functions/enrichAncestrySourceMaps";
|
|
10
|
+
import {
|
|
11
|
+
inspectCSSRules,
|
|
12
|
+
formatCSSInspection,
|
|
13
|
+
CSSInspectionResult,
|
|
14
|
+
} from "./functions/cssRuleInspector";
|
|
15
|
+
import {
|
|
16
|
+
extractComputedStyles,
|
|
17
|
+
ComputedStylesResult,
|
|
18
|
+
ExtractOptions,
|
|
19
|
+
} from "./functions/extractComputedStyles";
|
|
20
|
+
import {
|
|
21
|
+
takeNamedSnapshot,
|
|
22
|
+
getNamedSnapshotDiff,
|
|
23
|
+
clearNamedSnapshot,
|
|
24
|
+
TakeSnapshotResult,
|
|
25
|
+
SnapshotDiffResult,
|
|
26
|
+
} from "./functions/namedSnapshots";
|
|
9
27
|
import type { DejitterFinding, DejitterSummary } from "./dejitter/recorder";
|
|
10
28
|
import type { InteractionEvent } from "./components/RecordingResults";
|
|
29
|
+
import { takeSnapshot } from "./visualDiff/snapshot";
|
|
30
|
+
import { computeDiff, formatReport } from "./visualDiff/diff";
|
|
31
|
+
import { waitForSettle } from "./visualDiff/settle";
|
|
32
|
+
import type { DeltaReport, ElementSnapshot } from "./visualDiff/types";
|
|
11
33
|
|
|
12
34
|
export interface LocatorJSAPI {
|
|
13
35
|
/**
|
|
@@ -93,6 +115,40 @@ export interface LocatorJSAPI {
|
|
|
93
115
|
elementOrSelector: HTMLElement | string
|
|
94
116
|
): Promise<{ path: string; ancestry: AncestryItem[] } | null>;
|
|
95
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Get computed styles for an element, formatted for AI consumption.
|
|
120
|
+
* Extracts layout, visual, typography, and interaction styles filtered against browser defaults.
|
|
121
|
+
* Clicking the same element twice within 30s returns a diff of changed properties.
|
|
122
|
+
*
|
|
123
|
+
* @param elementOrSelector - HTMLElement or CSS selector string
|
|
124
|
+
* @param options - Optional flags like { includeDefaults: true } for a fuller dump
|
|
125
|
+
* @returns Object with formatted string and raw snapshot, or null if element not found
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* // Get formatted computed styles
|
|
129
|
+
* const result = window.__treelocator__.getStyles('button.submit');
|
|
130
|
+
* console.log(result.formatted);
|
|
131
|
+
* // [ComputedStyles] Button at src/Button.tsx:23
|
|
132
|
+
* // ─────────────────────────────────────────
|
|
133
|
+
* // Layout
|
|
134
|
+
* // display: flex
|
|
135
|
+
* // padding: 8px 16px
|
|
136
|
+
* // ...
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* // In Playwright
|
|
140
|
+
* const styles = await page.evaluate(() => {
|
|
141
|
+
* return window.__treelocator__.getStyles('.my-element', {
|
|
142
|
+
* includeDefaults: true,
|
|
143
|
+
* });
|
|
144
|
+
* });
|
|
145
|
+
* console.log(styles?.formatted);
|
|
146
|
+
*/
|
|
147
|
+
getStyles(
|
|
148
|
+
elementOrSelector: HTMLElement | string,
|
|
149
|
+
options?: ExtractOptions
|
|
150
|
+
): ComputedStylesResult | null;
|
|
151
|
+
|
|
96
152
|
/**
|
|
97
153
|
* Display help information about the LocatorJS API.
|
|
98
154
|
* Shows usage examples and method descriptions for browser automation tools.
|
|
@@ -110,6 +166,98 @@ export interface LocatorJSAPI {
|
|
|
110
166
|
*/
|
|
111
167
|
help(): string;
|
|
112
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Inspect all CSS rules matching an element, grouped by property.
|
|
171
|
+
* Shows which rule wins for each property with specificity, source, and !important info.
|
|
172
|
+
* Returns structured data for programmatic use.
|
|
173
|
+
*
|
|
174
|
+
* @param elementOrSelector - HTMLElement or CSS selector string
|
|
175
|
+
* @returns Structured CSS inspection result, or null if element not found
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* // Get structured CSS data
|
|
179
|
+
* const result = window.__treelocator__.getCSSRules('button.primary');
|
|
180
|
+
* result.properties.forEach(p => {
|
|
181
|
+
* console.log(`${p.property}: ${p.value}`);
|
|
182
|
+
* p.rules.forEach(r => console.log(` ${r.winning ? '✓' : '✗'} ${r.selector}`));
|
|
183
|
+
* });
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* // In Playwright - debug why a style isn't applying
|
|
187
|
+
* const css = await page.evaluate(() =>
|
|
188
|
+
* window.__treelocator__.getCSSRules('.my-button')
|
|
189
|
+
* );
|
|
190
|
+
* const colorRules = css?.properties.find(p => p.property === 'color');
|
|
191
|
+
* console.log(colorRules);
|
|
192
|
+
*/
|
|
193
|
+
getCSSRules(
|
|
194
|
+
elementOrSelector: HTMLElement | string
|
|
195
|
+
): CSSInspectionResult | null;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Get a formatted human-readable report of all CSS rules matching an element.
|
|
199
|
+
* Shows winning/losing rules per property with specificity and source info.
|
|
200
|
+
* Ideal for pasting into AI chat or logging.
|
|
201
|
+
*
|
|
202
|
+
* @param elementOrSelector - HTMLElement or CSS selector string
|
|
203
|
+
* @param options - Optional filter: { properties?: string[] } to limit output to specific properties
|
|
204
|
+
* @returns Formatted string report, or null if element not found
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* // Get full CSS report
|
|
208
|
+
* console.log(window.__treelocator__.getCSSReport('button.primary'));
|
|
209
|
+
* // Output:
|
|
210
|
+
* // CSS Rules for button.primary
|
|
211
|
+
* // ════════════════════════════
|
|
212
|
+
* //
|
|
213
|
+
* // color: #333
|
|
214
|
+
* // ✓ .button.primary (0,2,0) — components.css
|
|
215
|
+
* // ✗ .button (0,1,0) — base.css
|
|
216
|
+
* // ✗ button (0,0,1) — reset.css
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* // Filter to specific properties
|
|
220
|
+
* console.log(window.__treelocator__.getCSSReport('.card', { properties: ['color', 'background'] }));
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* // In Playwright
|
|
224
|
+
* const report = await page.evaluate(() =>
|
|
225
|
+
* window.__treelocator__.getCSSReport('.error-message')
|
|
226
|
+
* );
|
|
227
|
+
* console.log(report);
|
|
228
|
+
*/
|
|
229
|
+
getCSSReport(
|
|
230
|
+
elementOrSelector: HTMLElement | string,
|
|
231
|
+
options?: { properties?: string[] }
|
|
232
|
+
): string | null;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Capture a baseline snapshot of an element's computed styles and persist
|
|
236
|
+
* it in localStorage under `snapshotId`. The baseline survives page reloads
|
|
237
|
+
* and is never mutated until you call `takeSnapshot` again with the same id.
|
|
238
|
+
*
|
|
239
|
+
* @param selector - CSS selector for the element to snapshot
|
|
240
|
+
* @param snapshotId - caller-chosen id used to retrieve the diff later
|
|
241
|
+
* @param options - optional `{ index, label }` (index picks among matches)
|
|
242
|
+
*/
|
|
243
|
+
takeSnapshot(
|
|
244
|
+
selector: string,
|
|
245
|
+
snapshotId: string,
|
|
246
|
+
options?: { index?: number; label?: string }
|
|
247
|
+
): TakeSnapshotResult;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Diff the current computed styles of the element against the baseline
|
|
251
|
+
* stored under `snapshotId`. Does not overwrite the baseline — safe to call
|
|
252
|
+
* repeatedly while iterating on a change.
|
|
253
|
+
*/
|
|
254
|
+
getSnapshotDiff(snapshotId: string): SnapshotDiffResult;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Remove a stored baseline snapshot.
|
|
258
|
+
*/
|
|
259
|
+
clearSnapshot(snapshotId: string): void;
|
|
260
|
+
|
|
113
261
|
/**
|
|
114
262
|
* Replay the last recorded interaction sequence.
|
|
115
263
|
* Dispatches the recorded clicks at the original positions and timing.
|
|
@@ -155,14 +303,59 @@ export interface LocatorJSAPI {
|
|
|
155
303
|
summary: DejitterSummary | null;
|
|
156
304
|
data: any;
|
|
157
305
|
interactions: InteractionEvent[];
|
|
306
|
+
visualDiff: DeltaReport | null;
|
|
158
307
|
} | null>;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Visual diff engine — snapshot page state before/after an action and return
|
|
311
|
+
* a compact delta report.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* // In browser console or Playwright
|
|
315
|
+
* const report = await window.__treelocator__.diff.captureDiff(() => {
|
|
316
|
+
* document.querySelector('button.submit')?.click();
|
|
317
|
+
* });
|
|
318
|
+
* console.log(report.text);
|
|
319
|
+
*/
|
|
320
|
+
diff: {
|
|
321
|
+
/**
|
|
322
|
+
* Capture a snapshot of all visible viewport elements right now.
|
|
323
|
+
* Pure — no side effects on the page.
|
|
324
|
+
*/
|
|
325
|
+
snapshot(): ElementSnapshot[];
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Compute the delta between two snapshots.
|
|
329
|
+
*/
|
|
330
|
+
computeDiff(
|
|
331
|
+
before: ElementSnapshot[],
|
|
332
|
+
after: ElementSnapshot[]
|
|
333
|
+
): DeltaReport;
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Take a before-snapshot, run the action, wait for the page to settle
|
|
337
|
+
* (animations idle + mutations silent for 150ms), take an after-snapshot,
|
|
338
|
+
* and return the computed delta.
|
|
339
|
+
*/
|
|
340
|
+
captureDiff(
|
|
341
|
+
action: () => void | Promise<void>,
|
|
342
|
+
opts?: { settleTimeoutMs?: number }
|
|
343
|
+
): Promise<DeltaReport>;
|
|
344
|
+
};
|
|
159
345
|
}
|
|
160
346
|
|
|
161
347
|
function resolveElement(
|
|
162
348
|
elementOrSelector: HTMLElement | string
|
|
163
349
|
): HTMLElement | null {
|
|
164
350
|
if (typeof elementOrSelector === "string") {
|
|
165
|
-
|
|
351
|
+
// querySelector throws DOMException for invalid selector strings
|
|
352
|
+
// (e.g. "!!!") — return null instead of crashing the API call.
|
|
353
|
+
let element: Element | null = null;
|
|
354
|
+
try {
|
|
355
|
+
element = document.querySelector(elementOrSelector);
|
|
356
|
+
} catch {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
166
359
|
return element instanceof HTMLElement ? element : null;
|
|
167
360
|
}
|
|
168
361
|
return elementOrSelector;
|
|
@@ -227,13 +420,52 @@ METHODS:
|
|
|
227
420
|
console.log(data.path) // formatted string
|
|
228
421
|
console.log(data.ancestry) // structured array
|
|
229
422
|
|
|
230
|
-
4.
|
|
423
|
+
4. getStyles(elementOrSelector, options?)
|
|
424
|
+
Returns computed styles for an element, optimized for AI consumption.
|
|
425
|
+
Filters out browser defaults and groups by category (Layout, Visual, Typography).
|
|
426
|
+
Pass { includeDefaults: true } for a fuller dump closer to DevTools.
|
|
427
|
+
Calling twice on the same element within 30s returns a diff of changes.
|
|
428
|
+
|
|
429
|
+
Usage:
|
|
430
|
+
const result = window.__treelocator__.getStyles('button.submit')
|
|
431
|
+
console.log(result.formatted) // formatted styles string
|
|
432
|
+
console.log(result.snapshot) // raw property values + bounding rect
|
|
433
|
+
const full = window.__treelocator__.getStyles('h1', { includeDefaults: true })
|
|
434
|
+
|
|
435
|
+
5. getCSSRules(elementOrSelector)
|
|
436
|
+
Returns structured CSS rule data for the element.
|
|
437
|
+
Shows all matching rules grouped by property with specificity and source.
|
|
438
|
+
|
|
439
|
+
Usage:
|
|
440
|
+
const result = window.__treelocator__.getCSSRules('button.primary')
|
|
441
|
+
result.properties.forEach(p => {
|
|
442
|
+
console.log(p.property + ': ' + p.value)
|
|
443
|
+
p.rules.forEach(r => console.log(' ' + (r.winning ? 'WIN' : ' ') + ' ' + r.selector))
|
|
444
|
+
})
|
|
445
|
+
|
|
446
|
+
6. getCSSReport(elementOrSelector, options?)
|
|
447
|
+
Returns a formatted string showing all CSS rules and which wins per property.
|
|
448
|
+
Pass { properties: ['color', 'font-size'] } to filter to specific properties.
|
|
449
|
+
|
|
450
|
+
Usage:
|
|
451
|
+
console.log(window.__treelocator__.getCSSReport('button.primary'))
|
|
452
|
+
console.log(window.__treelocator__.getCSSReport('.card', { properties: ['color'] }))
|
|
453
|
+
|
|
454
|
+
Returns:
|
|
455
|
+
"CSS Rules for button.primary
|
|
456
|
+
════════════════════════════
|
|
457
|
+
color: #333
|
|
458
|
+
✓ .button.primary (0,2,0) — components.css
|
|
459
|
+
✗ .button (0,1,0) — base.css
|
|
460
|
+
✗ button (0,0,1) — reset.css"
|
|
461
|
+
|
|
462
|
+
7. replay()
|
|
231
463
|
Replays the last recorded interaction sequence as a macro.
|
|
232
464
|
|
|
233
465
|
Usage:
|
|
234
466
|
window.__treelocator__.replay()
|
|
235
467
|
|
|
236
|
-
|
|
468
|
+
8. replayWithRecord(elementOrSelector)
|
|
237
469
|
Replays stored interactions while recording element changes.
|
|
238
470
|
Returns dejitter analysis when replay completes.
|
|
239
471
|
|
|
@@ -242,7 +474,17 @@ METHODS:
|
|
|
242
474
|
console.log(results.findings) // anomaly analysis
|
|
243
475
|
console.log(results.path) // component ancestry
|
|
244
476
|
|
|
245
|
-
|
|
477
|
+
9. diff.snapshot() / diff.computeDiff(before, after) / diff.captureDiff(action)
|
|
478
|
+
Visual diff engine. Captures viewport element state and returns a compact
|
|
479
|
+
delta showing what appeared, disappeared, moved, or changed.
|
|
480
|
+
|
|
481
|
+
Usage:
|
|
482
|
+
const report = await window.__treelocator__.diff.captureDiff(() => {
|
|
483
|
+
document.querySelector('button.submit').click();
|
|
484
|
+
});
|
|
485
|
+
console.log(report.text);
|
|
486
|
+
|
|
487
|
+
10. help()
|
|
246
488
|
Displays this help message.
|
|
247
489
|
|
|
248
490
|
PLAYWRIGHT EXAMPLES:
|
|
@@ -267,6 +509,19 @@ async function getComponentPath(page, selector) {
|
|
|
267
509
|
}, selector);
|
|
268
510
|
}
|
|
269
511
|
|
|
512
|
+
// Debug CSS specificity conflicts
|
|
513
|
+
const report = await page.evaluate(() => {
|
|
514
|
+
return window.__treelocator__.getCSSReport('.my-button', { properties: ['color', 'background'] });
|
|
515
|
+
});
|
|
516
|
+
console.log(report);
|
|
517
|
+
|
|
518
|
+
// Get structured CSS data for assertions
|
|
519
|
+
const css = await page.evaluate(() => {
|
|
520
|
+
return window.__treelocator__.getCSSRules('.my-button');
|
|
521
|
+
});
|
|
522
|
+
const colorRules = css?.properties.find(p => p.property === 'color');
|
|
523
|
+
console.log('Winning rule:', colorRules?.rules.find(r => r.winning));
|
|
524
|
+
|
|
270
525
|
PUPPETEER EXAMPLES:
|
|
271
526
|
------------------
|
|
272
527
|
|
|
@@ -338,6 +593,74 @@ export function createBrowserAPI(
|
|
|
338
593
|
);
|
|
339
594
|
},
|
|
340
595
|
|
|
596
|
+
getStyles(
|
|
597
|
+
elementOrSelector: HTMLElement | string,
|
|
598
|
+
options?: ExtractOptions
|
|
599
|
+
): ComputedStylesResult | null {
|
|
600
|
+
const element = resolveElement(elementOrSelector);
|
|
601
|
+
if (!element) return null;
|
|
602
|
+
|
|
603
|
+
const ancestry = getAncestryForElement(element, adapterId);
|
|
604
|
+
const label = ancestry ? getElementLabel(ancestry) : undefined;
|
|
605
|
+
|
|
606
|
+
return extractComputedStyles(element, label || undefined, options);
|
|
607
|
+
},
|
|
608
|
+
|
|
609
|
+
getCSSRules(
|
|
610
|
+
elementOrSelector: HTMLElement | string
|
|
611
|
+
): CSSInspectionResult | null {
|
|
612
|
+
let element: HTMLElement | null = null;
|
|
613
|
+
try {
|
|
614
|
+
element = resolveElement(elementOrSelector);
|
|
615
|
+
} catch {
|
|
616
|
+
return null;
|
|
617
|
+
}
|
|
618
|
+
if (!element) return null;
|
|
619
|
+
return inspectCSSRules(element);
|
|
620
|
+
},
|
|
621
|
+
|
|
622
|
+
getCSSReport(
|
|
623
|
+
elementOrSelector: HTMLElement | string,
|
|
624
|
+
options?: { properties?: string[] }
|
|
625
|
+
): string | null {
|
|
626
|
+
let element: HTMLElement | null = null;
|
|
627
|
+
try {
|
|
628
|
+
element = resolveElement(elementOrSelector);
|
|
629
|
+
} catch {
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
632
|
+
if (!element) return null;
|
|
633
|
+
const result = inspectCSSRules(element);
|
|
634
|
+
|
|
635
|
+
// Filter to requested properties if specified
|
|
636
|
+
if (options?.properties && options.properties.length > 0) {
|
|
637
|
+
const filterSet = new Set(
|
|
638
|
+
options.properties.map((p) => p.toLowerCase())
|
|
639
|
+
);
|
|
640
|
+
result.properties = result.properties.filter((p) =>
|
|
641
|
+
filterSet.has(p.property.toLowerCase())
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
return formatCSSInspection(result);
|
|
646
|
+
},
|
|
647
|
+
|
|
648
|
+
takeSnapshot(
|
|
649
|
+
selector: string,
|
|
650
|
+
snapshotId: string,
|
|
651
|
+
options?: { index?: number; label?: string }
|
|
652
|
+
): TakeSnapshotResult {
|
|
653
|
+
return takeNamedSnapshot(selector, snapshotId, options);
|
|
654
|
+
},
|
|
655
|
+
|
|
656
|
+
getSnapshotDiff(snapshotId: string): SnapshotDiffResult {
|
|
657
|
+
return getNamedSnapshotDiff(snapshotId);
|
|
658
|
+
},
|
|
659
|
+
|
|
660
|
+
clearSnapshot(snapshotId: string): void {
|
|
661
|
+
clearNamedSnapshot(snapshotId);
|
|
662
|
+
},
|
|
663
|
+
|
|
341
664
|
help(): string {
|
|
342
665
|
return HELP_TEXT;
|
|
343
666
|
},
|
|
@@ -350,6 +673,30 @@ export function createBrowserAPI(
|
|
|
350
673
|
// Replaced by Runtime component once mounted
|
|
351
674
|
return Promise.resolve(null);
|
|
352
675
|
},
|
|
676
|
+
|
|
677
|
+
diff: {
|
|
678
|
+
snapshot() {
|
|
679
|
+
return takeSnapshot();
|
|
680
|
+
},
|
|
681
|
+
computeDiff(before, after) {
|
|
682
|
+
return computeDiff(before, after);
|
|
683
|
+
},
|
|
684
|
+
async captureDiff(action, opts) {
|
|
685
|
+
const started = performance.now();
|
|
686
|
+
const before = takeSnapshot();
|
|
687
|
+
await action();
|
|
688
|
+
const settle = await waitForSettle(opts?.settleTimeoutMs);
|
|
689
|
+
const after = takeSnapshot();
|
|
690
|
+
const report = computeDiff(before, after);
|
|
691
|
+
report.elapsedMs = performance.now() - started;
|
|
692
|
+
report.settle = settle;
|
|
693
|
+
report.text = formatReport(report.entries, {
|
|
694
|
+
elapsedMs: report.elapsedMs,
|
|
695
|
+
settle,
|
|
696
|
+
});
|
|
697
|
+
return report;
|
|
698
|
+
},
|
|
699
|
+
},
|
|
353
700
|
};
|
|
354
701
|
}
|
|
355
702
|
|