Initial commit

This commit is contained in:
Dom
2026-03-05 00:20:25 +01:00
commit dcd4de9945
1954 changed files with 669380 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
"""
Tests d'intégration pour la récupération d'erreurs
Teste les scénarios complets de gestion d'erreurs :
- Récupération après échec de matching
- Récupération après target introuvable avec fallbacks
- Récupération après violation de post-conditions
- Détection et gestion de changements UI
- Rollback d'actions
"""
import pytest
import numpy as np
from pathlib import Path
from datetime import datetime
from unittest.mock import Mock, patch
import tempfile
import shutil
from core.execution.error_handler import ErrorHandler, RecoveryStrategy
from core.execution.action_executor import ActionExecutor, ExecutionStatus
from core.execution.target_resolver import TargetResolver
from core.graph.node_matcher import NodeMatcher
from core.models.screen_state import ScreenState, RawLevel, PerceptionLevel
from core.models.workflow_graph import WorkflowNode, WorkflowEdge, Action, ActionType
from core.models.ui_element import UIElement
from core.embedding.state_embedding_builder import StateEmbeddingBuilder
@pytest.fixture
def temp_dirs():
"""Créer des répertoires temporaires pour les tests."""
error_dir = tempfile.mkdtemp()
failed_matches_dir = tempfile.mkdtemp()
yield error_dir, failed_matches_dir
shutil.rmtree(error_dir)
shutil.rmtree(failed_matches_dir)
@pytest.fixture
def error_handler(temp_dirs):
"""Créer ErrorHandler pour les tests."""
error_dir, _ = temp_dirs
return ErrorHandler(error_log_dir=error_dir)
@pytest.fixture
def action_executor(error_handler):
"""Créer ActionExecutor avec ErrorHandler."""
target_resolver = TargetResolver()
return ActionExecutor(
target_resolver=target_resolver,
error_handler=error_handler,
verify_postconditions=True
)
@pytest.fixture
def node_matcher(error_handler, temp_dirs):
"""Créer NodeMatcher avec ErrorHandler."""
_, failed_matches_dir = temp_dirs
embedding_builder = StateEmbeddingBuilder()
return NodeMatcher(
embedding_builder=embedding_builder,
error_handler=error_handler,
failed_matches_dir=failed_matches_dir
)
@pytest.fixture
def mock_screen_state_with_button():
"""Créer un ScreenState avec un bouton."""
raw_level = RawLevel(
window_title="Test App",
screenshot_path=Path("/tmp/test.png"),
timestamp=datetime.now()
)
button = UIElement(
element_id="btn_1",
role="button",
text="Submit",
bbox=(100, 100, 200, 150)
)
perception_level = PerceptionLevel(
ui_elements=[button],
timestamp=datetime.now()
)
return ScreenState(
raw_level=raw_level,
perception_level=perception_level
)
class TestActionExecutorErrorRecovery:
"""Tests de récupération d'erreurs dans ActionExecutor."""
def test_target_not_found_triggers_error_handler(
self, action_executor
):
"""Test que target introuvable déclenche ErrorHandler."""
# Créer un état sans le bouton attendu
raw_level = RawLevel(
window_title="Test App",
screenshot_path=Path("/tmp/test.png"),
timestamp=datetime.now()
)
perception_level = PerceptionLevel(ui_elements=[], timestamp=datetime.now())
screen_state = ScreenState(raw_level=raw_level, perception_level=perception_level)
action = Action(
type=ActionType.MOUSE_CLICK,
target=Mock(role="button", text_pattern="Submit")
)
edge = WorkflowEdge(from_node="node_1", to_node="node_2", action=action)
result = action_executor.execute_edge(edge=edge, screen_state=screen_state)
assert result.status == ExecutionStatus.TARGET_NOT_FOUND
stats = action_executor.get_error_statistics()
assert stats['total_errors'] >= 1
class TestNodeMatcherErrorRecovery:
"""Tests de récupération d'erreurs dans NodeMatcher."""
def test_matching_failure_triggers_error_handler(
self, node_matcher, mock_screen_state_with_button
):
"""Test que l'échec de matching déclenche ErrorHandler."""
node = WorkflowNode(node_id="node_1", label="Different State")
node.matches = Mock(return_value=(False, 0.50))
result = node_matcher.match(
current_state=mock_screen_state_with_button,
candidate_nodes=[node]
)
assert result is None
stats = node_matcher.get_error_statistics()
assert stats['total_errors'] >= 1
if __name__ == '__main__':
pytest.main([__file__, '-v'])

View File

@@ -0,0 +1,81 @@
-v'])e__, 'in([__fil pytest.maain__':
me__ == '__m
if __na600
<= height'] ox[' + bbbox['y']sert b as
<= 800'] bbox['width + bbox['x'] assert 0
> ['height'] bbox assert > 0
dth'] x['wit bboasser
'] >= 0box['yssert b a >= 0
x['x'] bbossert a t.bbox
lemenbbox = e nts:
nt in elemeeme for el
image)ts(_elemenctetector.detelf.dlements = se
e00)ge(800, 6te_test_imaelf.crea s image =""
s."ident valxes soounding bo les b que """Test (self):
ditylinding_box_va test_bouef
d"
ut of boundsfidence} olement.con{efidence on f"C \
= 1.0, nce <onfident.c eleme0 <=0. assert ements:
elelement in for
(image)
elementsetect_ector.delf.det = sements el)
ge(est_imaelf.create_t = simage"
" et 1."e 0entrnce est confiae la"Test qu "" self):
ounds(onfidence_bef test_c d
nk']
eckbox', 'li'ch', t_inpututton', 'texype in ['bt element_t asser
n réelledétectio lors de la fiéeera vériopriété stte pr# Ce ):
ions.items(d_combinatin valioles d_re, valiypelement_tfor s
ces règlespecte ecteur re le détr quefie # Véri
} '],
ernal_linkion', 'extgatvi'na [k': 'lin e'],
t', 'toggl['form_inpueckbox': 'chd'],
sword_fielield', 'pasarch_fsenput', ' ['form_it_input': 'tex '],
ionondary_act 'sec'submit',cel', ', 'canction'primary_aton': [ 'but ns = {
ombinatiod_c valie
de cohérencègles finir les r # Dé
"""types.s et ôlence entre rreCohéerty 13: "Prop "" elf):
sistency(sone_c_typty_roleest_properef t
d0
ts) >= enlen(elemassert e
age blanch ime surut être vid # Pet)
ts, lisance(elemensert isinst as
ge)
ments(imat_eler.detectoec self.detements = el()
age_test_imcreateself.= image e."""
mage simpl sur it détection"Tes ""):
e_image(selfplect_on_simtest_detdef
elements')detect_ector, 'self.det hasattr(assert e
Non is not.detectorlfrt se asse "
""eur.ctteon du désatiiali init"Test ""
elf):lization(stor_initiaest_detec def t
hite')
or='wight), colhe, idthB', (ww('RGrn Image.ne retu""
".est de tgeimar une ""Crée "=600):
=800, heightidthge(self, wate_test_imacre def
tor()
tecector = UIDe self.det "
ue test.""aqchant av """Setup f):
ethod(selup_mef set
d"ctor.""teur UIDe po"Tests"":
tUIDetectores Tclass
tectorIDemport U_detector in.uiore.detectioion_v3.cispa_vfrom rport Image
L imm PIs np
fropy at nummpor
itest
import py
"""
3.3equirementses: Rlidat- Va
s typesrtain ce'àgnés quassieuvent être ôles ne pains r- Certs Per Type
enest Role Uniqu: UIElemen
Property 13 testing.
ty-based properector avecetr UIDaires pous unit"
Test""