Skip to content

Commit 6c4ab2f

Browse files
committed
Fix test expectations and apply formatting
1 parent 71b6ee1 commit 6c4ab2f

File tree

13 files changed

+94
-64
lines changed

13 files changed

+94
-64
lines changed

extension/src/__tests__/highlight-detection.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ describe('highlight-detection helpers', () => {
111111
const end = script.indexOf('function compareCandidates', start);
112112
const resolveElementCandidateSource = script.slice(start, end);
113113

114-
expect(resolveElementCandidateSource).toContain("if (requestedType === 'any')");
114+
expect(resolveElementCandidateSource).toContain(
115+
"if (requestedType === 'any')",
116+
);
115117
expect(resolveElementCandidateSource).toContain(
116118
"candidates.push(buildResolvedCandidate(el, 'scrollable', 'scrollable'));",
117119
);
@@ -141,23 +143,25 @@ describe('highlight-detection helpers', () => {
141143
);
142144
});
143145

144-
test("buildHighlightDetectionScript prioritizes prominent scrollable containers for display", () => {
146+
test('buildHighlightDetectionScript prioritizes prominent scrollable containers for display', () => {
145147
const script = buildHighlightDetectionScript({ elementType: 'any' });
146148
const start = script.indexOf('function isProminentScrollableCandidate');
147149
const end = script.indexOf('function getOverlapArea', start);
148150
const displayOrderingSource = script.slice(start, end);
149151

152+
expect(displayOrderingSource).toContain("candidate.type !== 'scrollable'");
150153
expect(displayOrderingSource).toContain(
151-
"candidate.type !== 'scrollable'",
154+
'candidate.area >= viewportArea * 0.12',
152155
);
153-
expect(displayOrderingSource).toContain('candidate.area >= viewportArea * 0.12');
154156
expect(displayOrderingSource).toContain(
155157
'candidate.rect.height >= window.innerHeight * 0.35',
156158
);
157159
expect(displayOrderingSource).toContain(
158160
'candidate.rect.width >= window.innerWidth * 0.5',
159161
);
160-
expect(displayOrderingSource).toContain('function compareDisplayCandidates');
162+
expect(displayOrderingSource).toContain(
163+
'function compareDisplayCandidates',
164+
);
161165
expect(displayOrderingSource).toContain(
162166
"a.type === 'scrollable' && a.element.contains(b.element)",
163167
);

extension/src/background/index.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,14 @@ class CommandQueueManager {
268268
timestamp: Date.now(),
269269
};
270270

271-
wsClient.sendMessage({
272-
type: 'command_response',
273-
...responseWithId,
274-
}).catch((error) => {
275-
console.error('Failed to send response:', error);
276-
});
271+
wsClient
272+
.sendMessage({
273+
type: 'command_response',
274+
...responseWithId,
275+
})
276+
.catch((error) => {
277+
console.error('Failed to send response:', error);
278+
});
277279
}
278280

279281
return response;

extension/src/commands/element-actions.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -543,13 +543,7 @@ export async function performElementHover(
543543
* Scroll direction type
544544
*/
545545
export type ScrollDirection = 'up' | 'down' | 'left' | 'right';
546-
export type SwipeDirection =
547-
| 'next'
548-
| 'prev'
549-
| 'left'
550-
| 'right'
551-
| 'up'
552-
| 'down';
546+
export type SwipeDirection = 'next' | 'prev' | 'left' | 'right' | 'up' | 'down';
553547

554548
/**
555549
* Result type for element scroll operation
@@ -1630,9 +1624,7 @@ export async function performElementSwipe(
16301624
if (!swipeResult?.swiped) {
16311625
const isStale = swipeResult?.stale === true;
16321626
const error = swipeResult?.error || 'Swipe could not be performed';
1633-
console.log(
1634-
`❌ [ElementSwipe] Swipe failed: ${error}, stale=${isStale}`,
1635-
);
1627+
console.log(`❌ [ElementSwipe] Swipe failed: ${error}, stale=${isStale}`);
16361628
return {
16371629
success: false,
16381630
elementId,

extension/src/commands/highlight-detection.injected.js

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ function hasCallableMethod(value, methodNames) {
4141
return false;
4242
}
4343

44-
return methodNames.some((methodName) => typeof value[methodName] === 'function');
44+
return methodNames.some(
45+
(methodName) => typeof value[methodName] === 'function',
46+
);
4547
}
4648

4749
function createHighlightTrace() {
@@ -147,9 +149,7 @@ function getClassTokens(el) {
147149
return Array.from(el.classList)
148150
.filter(
149151
(token) =>
150-
token.length > 1 &&
151-
token.length <= 40 &&
152-
/^[a-z0-9_-]+$/i.test(token),
152+
token.length > 1 && token.length <= 40 && /^[a-z0-9_-]+$/i.test(token),
153153
)
154154
.slice(0, 8);
155155
}
@@ -267,7 +267,10 @@ function getTabIndexValue(el) {
267267
}
268268

269269
function isDisabledForDetection(el) {
270-
if (el.hasAttribute('disabled') || el.getAttribute('aria-disabled') === 'true') {
270+
if (
271+
el.hasAttribute('disabled') ||
272+
el.getAttribute('aria-disabled') === 'true'
273+
) {
271274
return true;
272275
}
273276

@@ -322,7 +325,11 @@ function getControlAffinityScore(el) {
322325
score += Math.min(40, text.length);
323326
}
324327

325-
if (/\b(button|btn|filter|follow|like|refresh|reload|reply|search|share|submit|toggle)\b/i.test(searchText)) {
328+
if (
329+
/\b(button|btn|filter|follow|like|refresh|reload|reply|search|share|submit|toggle)\b/i.test(
330+
searchText,
331+
)
332+
) {
326333
score += 12;
327334
}
328335

@@ -430,7 +437,10 @@ function getStructuralClickableSignal(el) {
430437
return null;
431438
}
432439

433-
if (hasExplicitClickableAncestor(el) || hasStructuredInteractiveDescendant(el)) {
440+
if (
441+
hasExplicitClickableAncestor(el) ||
442+
hasStructuredInteractiveDescendant(el)
443+
) {
434444
return null;
435445
}
436446

@@ -760,7 +770,10 @@ function isHoverableCandidate(el) {
760770
return false;
761771
}
762772

763-
if (hasExplicitClickableAncestor(el) || hasStructuredInteractiveDescendant(el)) {
773+
if (
774+
hasExplicitClickableAncestor(el) ||
775+
hasStructuredInteractiveDescendant(el)
776+
) {
764777
return false;
765778
}
766779

@@ -812,7 +825,8 @@ function hasHorizontalSwipeLayout(el) {
812825
overflowX.includes('auto');
813826

814827
const visibleChildren = Array.from(el.children).filter(
815-
(child) => child instanceof HTMLElement && isElementVisibleForDetection(child),
828+
(child) =>
829+
child instanceof HTMLElement && isElementVisibleForDetection(child),
816830
);
817831

818832
if (visibleChildren.length === 0) {
@@ -831,14 +845,16 @@ function hasHorizontalSwipeLayout(el) {
831845
childStyle.display.includes('flex') ||
832846
childStyle.whiteSpace === 'nowrap'
833847
);
834-
}) || (visibleChildren[0] instanceof HTMLElement ? visibleChildren[0] : null);
848+
}) ||
849+
(visibleChildren[0] instanceof HTMLElement ? visibleChildren[0] : null);
835850

836851
if (!(primaryTrack instanceof HTMLElement)) {
837852
return false;
838853
}
839854

840855
const trackChildren = Array.from(primaryTrack.children).filter(
841-
(child) => child instanceof HTMLElement && isElementVisibleForDetection(child),
856+
(child) =>
857+
child instanceof HTMLElement && isElementVisibleForDetection(child),
842858
);
843859

844860
if (trackChildren.length < 2) {
@@ -863,7 +879,10 @@ function hasHorizontalSwipeLayout(el) {
863879
if (childRect.left > previousRect.left + 12) {
864880
horizontalSteps += 1;
865881
}
866-
if (Math.abs(childRect.top - previousRect.top) <= Math.max(24, rect.height * 0.2)) {
882+
if (
883+
Math.abs(childRect.top - previousRect.top) <=
884+
Math.max(24, rect.height * 0.2)
885+
) {
867886
verticalAligned += 1;
868887
}
869888
}
@@ -949,7 +968,10 @@ function findSwipeContext(el, maxDepth = 4) {
949968
return current;
950969
}
951970

952-
if (hasHorizontalSwipeLayout(current) && current.getBoundingClientRect().width >= 180) {
971+
if (
972+
hasHorizontalSwipeLayout(current) &&
973+
current.getBoundingClientRect().width >= 180
974+
) {
953975
return current;
954976
}
955977

@@ -1066,7 +1088,9 @@ function generateSelector(el) {
10661088

10671089
function getCandidateSignal(type, signalSource) {
10681090
if (type === 'clickable') {
1069-
return HIGHLIGHT_SIGNAL_SCORE[signalSource] || HIGHLIGHT_SIGNAL_SCORE.pointer;
1091+
return (
1092+
HIGHLIGHT_SIGNAL_SCORE[signalSource] || HIGHLIGHT_SIGNAL_SCORE.pointer
1093+
);
10701094
}
10711095

10721096
return HIGHLIGHT_SIGNAL_SCORE[type] || 0;
@@ -1430,7 +1454,9 @@ function isRectInViewport(rect) {
14301454
}
14311455

14321456
function isMetricsTimeBudgetExceeded(startTime) {
1433-
return performance.now() - startTime >= layoutStabilityConfig.metricsTimeBudgetMs;
1457+
return (
1458+
performance.now() - startTime >= layoutStabilityConfig.metricsTimeBudgetMs
1459+
);
14341460
}
14351461

14361462
function countPendingViewportImages(metricsStartTime) {
@@ -1568,11 +1594,12 @@ function getPageMetrics() {
15681594
const metricsStartTime = performance.now();
15691595
const viewportText = collectViewportTextMetrics(metricsStartTime);
15701596
const viewportMedia = countViewportMedia(metricsStartTime);
1571-
const placeholderSignals =
1572-
countViewportPlaceholderSignals(metricsStartTime);
1597+
const placeholderSignals = countViewportPlaceholderSignals(metricsStartTime);
15731598

15741599
return {
1575-
bodyHeight: document.body ? document.body.getBoundingClientRect().height : 0,
1600+
bodyHeight: document.body
1601+
? document.body.getBoundingClientRect().height
1602+
: 0,
15761603
scrollHeight: document.documentElement
15771604
? document.documentElement.scrollHeight
15781605
: 0,

extension/src/commands/highlight-detection.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ export function getHighlightKeywordHaystack(
5050
}
5151

5252
return [element.text, element.selector, element.tagName, element.html]
53-
.filter((value): value is string => typeof value === 'string' && value.length > 0)
53+
.filter(
54+
(value): value is string => typeof value === 'string' && value.length > 0,
55+
)
5456
.join(' ')
5557
.toLowerCase();
5658
}

extension/src/utils/layout-stability.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,15 @@ export function evaluateLayoutReadiness(
117117
}
118118

119119
if (
120-
metrics.skeletonLikeCount >= HIGHLIGHT_LAYOUT_STABILITY_CONFIG.skeletonLikeThreshold
120+
metrics.skeletonLikeCount >=
121+
HIGHLIGHT_LAYOUT_STABILITY_CONFIG.skeletonLikeThreshold
121122
) {
122123
reasons.push('skeleton-placeholders');
123124
}
124125

125126
if (
126-
metrics.spinnerLikeCount >= HIGHLIGHT_LAYOUT_STABILITY_CONFIG.spinnerLikeThreshold
127+
metrics.spinnerLikeCount >=
128+
HIGHLIGHT_LAYOUT_STABILITY_CONFIG.spinnerLikeThreshold
127129
) {
128130
reasons.push('loading-spinner');
129131
}
@@ -157,13 +159,13 @@ export function evaluateLayoutReadiness(
157159
if (
158160
!hasHardBlocker &&
159161
contentScore >= HIGHLIGHT_LAYOUT_STABILITY_CONFIG.readyContentScore &&
160-
metrics.pendingImages <= HIGHLIGHT_LAYOUT_STABILITY_CONFIG.readyPendingImages
162+
metrics.pendingImages <=
163+
HIGHLIGHT_LAYOUT_STABILITY_CONFIG.readyPendingImages
161164
) {
162165
state = 'ready';
163166
} else if (
164167
!hasHardBlocker &&
165-
contentScore >=
166-
HIGHLIGHT_LAYOUT_STABILITY_CONFIG.provisionalContentScore &&
168+
contentScore >= HIGHLIGHT_LAYOUT_STABILITY_CONFIG.provisionalContentScore &&
167169
metrics.pendingImages <=
168170
HIGHLIGHT_LAYOUT_STABILITY_CONFIG.provisionalPendingImages
169171
) {

server/agent/tools/base.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,9 @@ def to_llm_content(self) -> Sequence[TextContent | ImageContent]:
312312
for el in self.highlighted_elements:
313313
el_id = el.get("id", "unknown")
314314
el_type = el.get("type")
315-
raw_hints = el.get("interactionHints") or el.get("interaction_hints") or []
315+
raw_hints = (
316+
el.get("interactionHints") or el.get("interaction_hints") or []
317+
)
316318
interaction_hints = [
317319
hint
318320
for hint in raw_hints
@@ -323,9 +325,7 @@ def to_llm_content(self) -> Sequence[TextContent | ImageContent]:
323325
suffix_parts.append(el_type)
324326
suffix_parts.extend(interaction_hints)
325327
display_id = (
326-
f"{el_id}({', '.join(suffix_parts)})"
327-
if suffix_parts
328-
else el_id
328+
f"{el_id}({', '.join(suffix_parts)})" if suffix_parts else el_id
329329
)
330330
html = (el.get("html") or "").strip()
331331
# Skip truncation for selectable elements (show full options)
@@ -363,7 +363,9 @@ def to_llm_content(self) -> Sequence[TextContent | ImageContent]:
363363
text_parts.append(full_html)
364364
text_parts.append("```")
365365
text_parts.append("")
366-
text_parts.append("**To confirm this action, use the `element_interaction` tool with:**")
366+
text_parts.append(
367+
"**To confirm this action, use the `element_interaction` tool with:**"
368+
)
367369
action_type = self.pending_confirmation.get("action_type", "")
368370
element_id = self.pending_confirmation.get("element_id", "")
369371
confirm_cmd = (

server/agent/tools/browser_executor.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -596,9 +596,7 @@ def _execute_element_interaction_action(
596596
if not result_dict or not result_dict.get("success"):
597597
ext_error = self._extract_result_error(result_dict)
598598
raise RuntimeError(f"Failed to swipe element: {ext_error}")
599-
message = (
600-
f"Swiped element (previously confirmed): {action.element_id}"
601-
)
599+
message = f"Swiped element (previously confirmed): {action.element_id}"
602600
return self._build_observation_from_result(
603601
result_dict, message, element_id=action.element_id
604602
)

server/main.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ def cli():
4646
def serve(host, port, websocket_port, log_level, multi_process):
4747
"""Start the Local Chrome Server"""
4848
if multi_process is not None:
49-
os.environ["CHROME_SERVER_MULTI_PROCESS_MODE"] = (
50-
"1" if multi_process else "0"
51-
)
49+
os.environ["CHROME_SERVER_MULTI_PROCESS_MODE"] = "1" if multi_process else "0"
5250

5351
import uvicorn
5452
from server.api.main import app

server/tests/unit/test_agent_browser_executor.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Regression tests for agent BrowserExecutor result handling."""
22

3+
import server.agent.tools.browser_executor as browser_executor_module
4+
35
from server.agent.tools.browser_executor import BrowserExecutor
46
from server.agent.tools.element_interaction_tool import ElementInteractionAction
57
from server.models.commands import SwipeElementCommand
@@ -21,7 +23,8 @@ def test_execute_command_sync_promotes_nested_error_to_top_level(monkeypatch) ->
2123
executor.conversation_id = "conv-swipe-error"
2224

2325
monkeypatch.setattr(
24-
"server.agent.tools.browser_executor.requests.post",
26+
browser_executor_module.requests,
27+
"post",
2528
lambda *args, **kwargs: _FakeResponse(
2629
{
2730
"success": False,
@@ -71,6 +74,8 @@ def test_confirm_swipe_reports_nested_extension_error(monkeypatch) -> None:
7174
)
7275

7376
assert observation.success is False
74-
assert observation.error == "Failed to swipe element: No swipeable container found for element"
77+
assert (
78+
observation.error
79+
== "Failed to swipe element: No swipeable container found for element"
80+
)
7581
assert "None" not in observation.message
76-

0 commit comments

Comments
 (0)