foxygit / RPA-Remisser Log in
commit 46f1625647080af02dd7bea664321a3ce9563f39
Author:     Jens Kristoffersson <jens.kristoffersson.se@gmail.com>
AuthorDate: Fri Sep 4 13:50:00 2026 +0200
Commit:     Jens Kristoffersson <jens.kristoffersson.se@gmail.com>
CommitDate: Fri Sep 4 13:50:00 2026 +0200

    skip_browser: ignorera inaktiverade steg + logga vad som kraver webblasaren

    - ett inaktiverat webblasarsteg (enabled:false) tvingar inte langre igang Chromium
    - korloggen sager nu "Startar webblasare (kravs av steg: click 'knappen')" sa det
      gar att se varfor den oppnades
---
 rpa/flow_engine.py         | 34 +++++++++++++++++++++++++++++++++-
 tests/test_skip_browser.py | 17 +++++++++++++++++
 2 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/rpa/flow_engine.py b/rpa/flow_engine.py
index df020ba..602454b 100644
--- a/rpa/flow_engine.py
+++ b/rpa/flow_engine.py
@@ -170,7 +170,10 @@ def _condition_needs_browser(cond: dict) -> bool:


 def _step_needs_browser(step: dict) -> bool:
-    """True om steget (eller något nästlat steg / if-villkor) kräver Playwright."""
+    """True om steget (eller något nästlat steg / if-villkor) kräver Playwright.
+    Inaktiverade steg räknas inte - de hoppas över vid körning."""
+    if step.get("enabled") is False:
+        return False
     t = step.get("type")
     if t in _DESKTOP_STEPS or (t in _NO_BROWSER_STEPS and t not in ("loop", "if")):
         return False
@@ -190,6 +193,31 @@ def _flow_needs_browser(steps: list) -> bool:
     return any(_step_needs_browser(s) for s in steps)


+def _first_browser_step(steps: list) -> str | None:
+    """Beskrivning av det första steget som gör att webbläsaren måste startas -
+    för att kunna säga det i körloggen. Ignorerar inaktiverade steg? Nej, motorn
+    startar webbläsaren oavsett enabled (enkelhet)."""
+    for step in steps:
+        if not _step_needs_browser(step):
+            continue
+        t = step.get("type")
+        if t == "loop":
+            inner = _first_browser_step(step.get("steps", []))
+            return f"loop -> {inner}" if inner else t
+        if t == "if":
+            for br in step.get("branches", []):
+                if _condition_needs_browser(br.get("condition", {})):
+                    return f"if ({br['condition'].get('kind')})"
+                inner = _first_browser_step(br.get("steps", []))
+                if inner:
+                    return f"if -> {inner}"
+            inner = _first_browser_step(step.get("else") or [])
+            return f"if/else -> {inner}" if inner else t
+        label = step.get("label")
+        return f"{t}" + (f" '{label}'" if label else "")
+    return None
+
+
 _BAD_FILENAME_CHARS = re.compile(r'[<>:"/\\|?*\x00-\x1f]')


@@ -1119,6 +1147,10 @@ def run_flow(
         )
         return

+    reason = _first_browser_step(steps)
+    if reason:
+        log(f"Startar webbläsare (krävs av steg: {reason}).")
+
     with sync_playwright() as p:
         context = launch_context(p, settings)
         if trace_path is not None:
diff --git a/tests/test_skip_browser.py b/tests/test_skip_browser.py
index 4ce1b4c..c124cb0 100644
--- a/tests/test_skip_browser.py
+++ b/tests/test_skip_browser.py
@@ -42,6 +42,23 @@ def test_if_with_element_condition_needs_browser():
     assert flow_engine._flow_needs_browser(steps) is True


+def test_disabled_browser_step_does_not_force_browser():
+    steps = [
+        {"type": "desktop_launch", "path": "notepad.exe"},
+        {"type": "click", "by": "text", "value": "X", "enabled": False},
+    ]
+    assert flow_engine._flow_needs_browser(steps) is False
+
+
+def test_first_browser_step_names_the_trigger():
+    steps = [
+        {"type": "desktop_launch", "path": "x"},
+        {"type": "click", "by": "text", "value": "Y", "label": "knappen"},
+    ]
+    assert flow_engine._first_browser_step(steps) == "click 'knappen'"
+    assert flow_engine._first_browser_step([{"type": "set_var", "var": "a", "text": "1"}]) is None
+
+
 # --- integration: webbläsaren startas inte -------------------------------

 def test_run_flow_skips_browser_for_var_only(tmp_path, monkeypatch):