Skip to content

Commit c1fa8bc

Browse files
committed
chore: format with black
1 parent c6fb87f commit c1fa8bc

File tree

2 files changed

+193
-44
lines changed

2 files changed

+193
-44
lines changed

tests/utest/test_base_locator_agent.py

Lines changed: 108 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
import sys
2-
import types
3-
import pytest
41
import asyncio
52
import importlib
3+
import sys
4+
import types
65
from typing import Any, Callable, List, Optional, Tuple
76

7+
import pytest
88

9-
MODULE_PATH: str = "SelfhealingAgents.self_healing_system.agents.locator_agent.base_locator_agent"
9+
MODULE_PATH: str = (
10+
"SelfhealingAgents.self_healing_system.agents.locator_agent.base_locator_agent"
11+
)
1012

1113

1214
def _run(coro):
@@ -16,6 +18,7 @@ def _run(coro):
1618
class _LoggerStub:
1719
def __init__(self) -> None:
1820
self.infos: List[str] = []
21+
1922
def info(self, msg: str, *args: Any, **kwargs: Any) -> None:
2023
self.infos.append(str(msg))
2124

@@ -32,20 +35,25 @@ def __init__(self, request_limit: int, total_tokens_limit: int) -> None:
3235

3336

3437
class _FakeAgent:
35-
def __init__(self, *, model: Any, system_prompt: str, deps_type: Any, output_type: Any) -> None:
38+
def __init__(
39+
self, *, model: Any, system_prompt: str, deps_type: Any, output_type: Any
40+
) -> None:
3641
self.model = model
3742
self.system_prompt = system_prompt
3843
self.deps_type = deps_type
3944
self.output_type = output_type
4045
self.run_result: _FakeAgentRunResult = _FakeAgentRunResult(None)
4146
self.validator: Optional[Callable[..., Any]] = None
4247
self.run_calls: int = 0
48+
4349
@classmethod
4450
def __class_getitem__(cls, item: Any) -> "_FakeAgent":
4551
return cls
52+
4653
def output_validator(self, func: Callable[..., Any]) -> Callable[..., Any]:
4754
self.validator = func
4855
return func
56+
4957
async def run(self, *args: Any, **kwargs: Any) -> _FakeAgentRunResult:
5058
self.run_calls += 1
5159
return self.run_result
@@ -74,7 +82,9 @@ def _install_stubs() -> _LoggerStub:
7482
robot_api_mod = types.ModuleType("robot.api")
7583
robot_api_mod.__path__ = []
7684
robot_api_interfaces_mod = types.ModuleType("robot.api.interfaces")
85+
7786
class ListenerV3: ...
87+
7888
robot_api_interfaces_mod.ListenerV3 = ListenerV3
7989
logger = _LoggerStub()
8090
robot_api_mod.logger = logger
@@ -85,7 +95,9 @@ class ListenerV3: ...
8595
_force_module("robot.running", types.ModuleType("robot.running"))
8696

8797
listener_stub = types.ModuleType("SelfhealingAgents.listener")
98+
8899
class SelfhealingAgents: ...
100+
89101
listener_stub.SelfhealingAgents = SelfhealingAgents
90102
_force_module("SelfhealingAgents.listener", listener_stub)
91103

@@ -105,55 +117,84 @@ class SelfhealingAgents: ...
105117

106118
aid_utils = types.ModuleType("SelfhealingAgents.utils")
107119
logging_mod = types.ModuleType("SelfhealingAgents.utils.logging")
120+
108121
def log(f: Callable[..., Any]) -> Callable[..., Any]:
109122
return f
123+
110124
logging_mod.log = log
111125
cfg_mod = types.ModuleType("SelfhealingAgents.utils.cfg")
126+
112127
class Cfg:
113128
def __init__(self) -> None:
114129
self.request_limit: int = 10
115130
self.total_tokens_limit: int = 1000
116131
self.use_llm_for_locator_generation: bool = True
117132
self.locator_agent_provider: str = "prov"
118133
self.locator_agent_model: str = "mod"
134+
119135
cfg_mod.Cfg = Cfg
120136
_force_module("SelfhealingAgents.utils", aid_utils)
121137
_force_module("SelfhealingAgents.utils.logging", logging_mod)
122138
_force_module("SelfhealingAgents.utils.cfg", cfg_mod)
123139

124-
prompts_pkg = types.ModuleType("SelfhealingAgents.self_healing_system.agents.prompts.locator.prompts_locator")
140+
prompts_pkg = types.ModuleType(
141+
"SelfhealingAgents.self_healing_system.agents.prompts.locator.prompts_locator"
142+
)
143+
125144
class PromptsLocatorGenerationAgent:
126145
@staticmethod
127146
def get_system_msg(dom: Any) -> str:
128147
return "GEN_SYS"
148+
129149
@staticmethod
130150
def get_user_msg(ctx: Any) -> str:
131151
return "GEN_USER"
152+
132153
class PromptsLocatorSelectionAgent:
133154
@staticmethod
134155
def get_system_msg() -> str:
135156
return "SEL_SYS"
157+
136158
@staticmethod
137159
def get_user_msg(ctx: Any, suggestions: List[str], metadata: List[dict]) -> str:
138160
return "SEL_USER"
161+
139162
prompts_pkg.PromptsLocatorGenerationAgent = PromptsLocatorGenerationAgent
140163
prompts_pkg.PromptsLocatorSelectionAgent = PromptsLocatorSelectionAgent
141-
_force_module("SelfhealingAgents.self_healing_system.agents.prompts.locator.prompts_locator", prompts_pkg)
164+
_force_module(
165+
"SelfhealingAgents.self_healing_system.agents.prompts.locator.prompts_locator",
166+
prompts_pkg,
167+
)
168+
169+
client_model = types.ModuleType(
170+
"SelfhealingAgents.self_healing_system.llm.client_model"
171+
)
142172

143-
client_model = types.ModuleType("SelfhealingAgents.self_healing_system.llm.client_model")
144173
def get_client_model(provider: str, model: str, cfg: Any) -> str:
145174
return f"{provider}:{model}"
175+
146176
client_model.get_client_model = get_client_model
147-
_force_module("SelfhealingAgents.self_healing_system.llm.client_model", client_model)
177+
_force_module(
178+
"SelfhealingAgents.self_healing_system.llm.client_model", client_model
179+
)
180+
181+
loc_schema = types.ModuleType(
182+
"SelfhealingAgents.self_healing_system.schemas.api.locator_healing"
183+
)
148184

149-
loc_schema = types.ModuleType("SelfhealingAgents.self_healing_system.schemas.api.locator_healing")
150185
class LocatorHealingResponse:
151186
def __init__(self, suggestions: List[str]) -> None:
152187
self.suggestions: List[str] = suggestions
188+
153189
loc_schema.LocatorHealingResponse = LocatorHealingResponse
154-
_force_module("SelfhealingAgents.self_healing_system.schemas.api.locator_healing", loc_schema)
190+
_force_module(
191+
"SelfhealingAgents.self_healing_system.schemas.api.locator_healing", loc_schema
192+
)
193+
194+
payload_mod = types.ModuleType(
195+
"SelfhealingAgents.self_healing_system.schemas.internal_state.prompt_payload"
196+
)
155197

156-
payload_mod = types.ModuleType("SelfhealingAgents.self_healing_system.schemas.internal_state.prompt_payload")
157198
class PromptPayload:
158199
def __init__(
159200
self,
@@ -172,13 +213,24 @@ def __init__(
172213
self.keyword_args = keyword_args
173214
self.failed_locator = failed_locator
174215
self.tried_locator_memory = tried_locator_memory
216+
175217
payload_mod.PromptPayload = PromptPayload
176-
_force_module("SelfhealingAgents.self_healing_system.schemas.internal_state.prompt_payload", payload_mod)
218+
_force_module(
219+
"SelfhealingAgents.self_healing_system.schemas.internal_state.prompt_payload",
220+
payload_mod,
221+
)
222+
223+
base_dom = types.ModuleType(
224+
"SelfhealingAgents.self_healing_system.context_retrieving.library_dom_utils.base_dom_utils"
225+
)
177226

178-
base_dom = types.ModuleType("SelfhealingAgents.self_healing_system.context_retrieving.library_dom_utils.base_dom_utils")
179227
class BaseDomUtils: ...
228+
180229
base_dom.BaseDomUtils = BaseDomUtils
181-
_force_module("SelfhealingAgents.self_healing_system.context_retrieving.library_dom_utils.base_dom_utils", base_dom)
230+
_force_module(
231+
"SelfhealingAgents.self_healing_system.context_retrieving.library_dom_utils.base_dom_utils",
232+
base_dom,
233+
)
182234

183235
return logger
184236

@@ -224,18 +276,23 @@ def __init__(
224276
self._raise_valid = raise_valid
225277
self._raise_unique = raise_unique
226278
self._raise_clickable = raise_clickable
279+
227280
def get_locator_proposals(self, failed: str, keyword: str) -> List[str]:
228281
return list(self._proposals)
282+
229283
def get_locator_metadata(self, locator: str) -> List[dict]:
230284
return [self._metadata_map.get(locator, {"id": locator})]
285+
231286
def is_locator_valid(self, locator: str) -> bool:
232287
if self._raise_valid:
233288
raise RuntimeError("valid err")
234289
return self._valid
290+
235291
def is_locator_unique(self, locator: str) -> bool:
236292
if self._raise_unique:
237293
raise RuntimeError("unique err")
238294
return bool(self._unique_map.get(locator, False))
295+
239296
def is_element_clickable(self, locator: str) -> bool:
240297
if self._raise_clickable:
241298
raise RuntimeError("click err")
@@ -264,15 +321,18 @@ def make(BaseLocatorAgent: Any, dom: _DomStub, *, use_llm: bool) -> Any:
264321
class Impl(BaseLocatorAgent):
265322
def _process_locator(self, locator: str) -> str:
266323
return f"proc:{locator}"
324+
267325
@staticmethod
268326
def is_failed_locator_error(message: str) -> bool:
269327
return "failed" in message.lower()
328+
270329
class Cfg:
271330
request_limit: int = 9
272331
total_tokens_limit: int = 999
273332
use_llm_for_locator_generation: bool = use_llm
274333
locator_agent_provider: str = "prov"
275334
locator_agent_model: str = "mod"
335+
276336
return Impl(Cfg(), dom)
277337

278338

@@ -288,7 +348,9 @@ def test_init_configures_agents_by_mode(mod_and_cls: Tuple[Any, Any, Any, Any])
288348
assert inst_dom.selection_agent is not None
289349

290350

291-
def test_output_validator_processes_and_filters(mod_and_cls: Tuple[Any, Any, Any, Any]) -> None:
351+
def test_output_validator_processes_and_filters(
352+
mod_and_cls: Tuple[Any, Any, Any, Any],
353+
) -> None:
292354
BaseLocatorAgent, LocatorHealingResponse, PromptPayload, _ = mod_and_cls
293355
dom = _DomStub(
294356
valid=True,
@@ -302,14 +364,23 @@ def test_output_validator_processes_and_filters(mod_and_cls: Tuple[Any, Any, Any
302364
assert isinstance(res, LocatorHealingResponse)
303365
assert res.suggestions == ["proc:a"]
304366
with pytest.raises(_FakeModelRetry):
305-
_run(val(_ctx(_payload(PromptPayload, keyword="Click")), LocatorHealingResponse([])))
367+
_run(
368+
val(
369+
_ctx(_payload(PromptPayload, keyword="Click")),
370+
LocatorHealingResponse([]),
371+
)
372+
)
306373

307374

308-
def test_heal_with_llm_success_and_type_check(mod_and_cls: Tuple[Any, Any, Any, Any]) -> None:
375+
def test_heal_with_llm_success_and_type_check(
376+
mod_and_cls: Tuple[Any, Any, Any, Any],
377+
) -> None:
309378
BaseLocatorAgent, LocatorHealingResponse, PromptPayload, _ = mod_and_cls
310379
dom = _DomStub(valid=True)
311380
inst = _ConcreteAgentFactory.make(BaseLocatorAgent, dom, use_llm=True)
312-
inst.generation_agent.run_result = _FakeAgentRunResult(LocatorHealingResponse(["x"]))
381+
inst.generation_agent.run_result = _FakeAgentRunResult(
382+
LocatorHealingResponse(["x"])
383+
)
313384
out = _run(inst._heal_with_llm(_ctx(_payload(PromptPayload))))
314385
assert isinstance(out, LocatorHealingResponse)
315386
assert out.suggestions == ["x"]
@@ -318,7 +389,9 @@ def test_heal_with_llm_success_and_type_check(mod_and_cls: Tuple[Any, Any, Any,
318389
_run(inst._heal_with_llm(_ctx(_payload(PromptPayload))))
319390

320391

321-
def test_heal_with_dom_utils_json_and_raw_selection(mod_and_cls: Tuple[Any, Any, Any, Any]) -> None:
392+
def test_heal_with_dom_utils_json_and_raw_selection(
393+
mod_and_cls: Tuple[Any, Any, Any, Any],
394+
) -> None:
322395
BaseLocatorAgent, LocatorHealingResponse, PromptPayload, _ = mod_and_cls
323396
dom = _DomStub(
324397
proposals=["l2", "l1"],
@@ -328,25 +401,35 @@ def test_heal_with_dom_utils_json_and_raw_selection(mod_and_cls: Tuple[Any, Any,
328401
)
329402
inst = _ConcreteAgentFactory.make(BaseLocatorAgent, dom, use_llm=False)
330403
inst.selection_agent.run_result = _FakeAgentRunResult('{"suggestions":"#best"}')
331-
out = _run(inst._heal_with_dom_utils(_ctx(_payload(PromptPayload, keyword="Click"))))
404+
out = _run(
405+
inst._heal_with_dom_utils(_ctx(_payload(PromptPayload, keyword="Click")))
406+
)
332407
assert isinstance(out, LocatorHealingResponse)
333408
assert out.suggestions == ["#best"]
334409
inst.selection_agent.run_result = _FakeAgentRunResult("#alt")
335-
out2 = _run(inst._heal_with_dom_utils(_ctx(_payload(PromptPayload, keyword="Click"))))
410+
out2 = _run(
411+
inst._heal_with_dom_utils(_ctx(_payload(PromptPayload, keyword="Click")))
412+
)
336413
assert out2.suggestions == ["#alt"]
337414

338415

339-
def test_heal_with_dom_utils_empty_proposals_raises(mod_and_cls: Tuple[Any, Any, Any, Any]) -> None:
416+
def test_heal_with_dom_utils_empty_proposals_raises(
417+
mod_and_cls: Tuple[Any, Any, Any, Any],
418+
) -> None:
340419
BaseLocatorAgent, _, PromptPayload, _ = mod_and_cls
341420
dom = _DomStub(proposals=[], valid=True)
342421
inst = _ConcreteAgentFactory.make(BaseLocatorAgent, dom, use_llm=False)
343422
with pytest.raises(_FakeModelRetry):
344423
_run(inst._heal_with_dom_utils(_ctx(_payload(PromptPayload))))
345424

346425

347-
def test_is_locator_valid_unique_clickable_with_exceptions(mod_and_cls: Tuple[Any, Any, Any, Any]) -> None:
426+
def test_is_locator_valid_unique_clickable_with_exceptions(
427+
mod_and_cls: Tuple[Any, Any, Any, Any],
428+
) -> None:
348429
BaseLocatorAgent, _, __, ___ = mod_and_cls
349-
dom = _DomStub(valid=True, unique_map={"proc:x": True}, clickable_map={"proc:x": True})
430+
dom = _DomStub(
431+
valid=True, unique_map={"proc:x": True}, clickable_map={"proc:x": True}
432+
)
350433
inst = _ConcreteAgentFactory.make(BaseLocatorAgent, dom, use_llm=False)
351434
assert inst._is_locator_valid("proc:x") is True
352435
assert inst._is_locator_unique("proc:x") is True

0 commit comments

Comments
 (0)