11from typing import Optional , Tuple , Union
22
33import pytest
4+ from httpx import HTTPStatusError
45
56from askui import ConfigurableRetry , LocateModel , VisionAgent
67from askui .locators .locators import Locator
78from askui .models import ModelComposition
8- from askui .models .exceptions import ElementNotFoundError
9+ from askui .models .exceptions import ElementNotFoundError , ModelNotFoundError
910from askui .tools .toolbox import AgentToolbox
1011from askui .utils .image_utils import ImageSource
1112
@@ -52,6 +53,26 @@ def vision_agent_with_retry(
5253 )
5354
5455
56+ @pytest .fixture
57+ def vision_agent_with_retry_on_multiple_exceptions (
58+ failing_model : FailingLocateModel , agent_toolbox_mock : AgentToolbox
59+ ) -> VisionAgent :
60+ return VisionAgent (
61+ models = {"failing-locate" : failing_model },
62+ tools = agent_toolbox_mock ,
63+ retry = ConfigurableRetry (
64+ on_exception_types = (
65+ ElementNotFoundError ,
66+ HTTPStatusError ,
67+ ModelNotFoundError ,
68+ ),
69+ strategy = "Fixed" ,
70+ retry_count = 3 ,
71+ base_delay = 1 ,
72+ ),
73+ )
74+
75+
5576@pytest .fixture
5677def vision_agent_always_fail (
5778 always_failing_model : FailingLocateModel , agent_toolbox_mock : AgentToolbox
@@ -78,6 +99,17 @@ def test_locate_retries_and_succeeds(
7899 assert failing_model .calls == 3 # 2 fails + 1 success
79100
80101
102+ def test_locate_retries_on_multiple_exceptions_and_succeeds (
103+ vision_agent_with_retry_on_multiple_exceptions : VisionAgent ,
104+ failing_model : FailingLocateModel ,
105+ ) -> None :
106+ result = vision_agent_with_retry_on_multiple_exceptions .locate (
107+ "something" , screenshot = None , model = "failing-locate"
108+ )
109+ assert result == (10 , 10 )
110+ assert failing_model .calls == 3
111+
112+
81113def test_locate_retries_and_fails (
82114 vision_agent_always_fail : VisionAgent , always_failing_model : FailingLocateModel
83115) -> None :
0 commit comments