foxygit / RPA-Remisser Log in
commits tags

/tests/test_migrate.py · 3.97 KB

raw
"""Migrering: gammalt nästlat {steps} -> nod/kant-graf, som sedan körs och ger
samma variabelutfall som den gamla listmotorn gav."""

import pytest

from rpa import graph_engine, migrate
from rpa.flow_engine import FlowError


def run_steps(steps, vars_=None):
    g = migrate.steps_to_graph(steps)
    v = dict(vars_ or {})
    logs: list[str] = []
    graph_engine.run_graph(
        g["nodes"], g["edges"], logs.append,
        page=None, download_dir=None, vars_=v,
        desktop_holder={"session": None}, start=g["start"],
    )
    return v, g, logs


def test_linear_steps_preserve_order_and_ids():
    v, g, _ = run_steps([
        {"type": "set_var", "id": "s1", "var": "x", "text": "1"},
        {"type": "increment", "id": "s2", "var": "x", "by": 2},
    ])
    assert [n["id"] for n in g["nodes"]] == ["s1", "s2"]
    assert g["start"] == "s1"
    assert v["x"] == 3


def test_if_else_merges_and_continues():
    steps = [
        {"type": "set_var", "var": "r", "text": "start"},
        {"type": "if", "branches": [
            {"condition": {"kind": "var_equals", "var": "läge", "text": "prod"},
             "steps": [{"type": "set_var", "var": "r", "text": "PROD"}]},
        ], "else": [{"type": "set_var", "var": "r", "text": "ELSE"}]},
        {"type": "set_var", "var": "efter", "text": "körd"},
    ]
    for läge, expected in (("prod", "PROD"), ("test", "ELSE")):
        v, _, _ = run_steps(steps, {"läge": läge})
        assert v["r"] == expected
        assert v["efter"] == "körd"  # båda grenar mynnar i efter-noden


def test_if_without_else_falls_through():
    steps = [
        {"type": "if", "branches": [
            {"condition": {"kind": "var_equals", "var": "x", "text": "1"},
             "steps": [{"type": "set_var", "var": "r", "text": "träff"}]},
        ]},
        {"type": "set_var", "var": "efter", "text": "körd"},
    ]
    v, _, _ = run_steps(steps, {"x": "0"})
    assert "r" not in v and v["efter"] == "körd"


def test_loop_body_loops_back_and_done_continues():
    steps = [
        {"type": "loop", "over": "poster", "item_var": "it", "index_var": "i", "steps": [
            {"type": "increment", "var": "antal", "by": 1},
            {"type": "set_var", "var": "sista", "text": "{it}"},
        ]},
        {"type": "save_var", "var": "sista", "filename": "x.json"},
    ]
    v, g, _ = run_steps(steps, {"poster": ["a", "b"], "antal": "0"})
    assert v["antal"] == 2 and v["sista"] == "b" and v["i"] == 2
    # loop-noden har en each-kant och en done-kant, kroppen loopar tillbaka till in
    loop_id = next(n["id"] for n in g["nodes"] if n["type"] == "loop")
    handles = {e["sourceHandle"] for e in g["edges"] if e["source"] == loop_id}
    assert {"each", "done"} <= handles
    assert any(e["target"] == loop_id for e in g["edges"])  # loopback


def test_jump_to_label_becomes_a_plain_edge():
    steps = [
        {"type": "set_var", "id": "a", "var": "r", "text": "1"},
        {"type": "jump_to_label", "target": "slut"},
        {"type": "set_var", "id": "skip", "var": "r", "text": "HOPPAD"},
        {"type": "set_var", "id": "b", "var": "r", "text": "2", "label": "slut"},
    ]
    v, g, _ = run_steps(steps)
    assert "jump_to_label" not in {n["type"] for n in g["nodes"]}
    assert v["r"] == "2"  # 'skip'-noden nås aldrig


def test_flat_node_drops_container_keys():
    g = migrate.steps_to_graph([
        {"type": "loop", "over": "x", "steps": [{"type": "wait", "seconds": 0}]},
        {"type": "if", "branches": [{"condition": {"kind": "var_equals", "var": "a", "text": "b"},
                                     "steps": [{"type": "wait", "seconds": 0}]}], "else": []},
    ])
    for n in g["nodes"]:
        assert "steps" not in n
        if n["type"] == "if":
            assert all(set(b) == {"condition"} for b in n["branches"])
        else:
            assert "branches" not in n


def test_flow_to_graph_is_noop_for_graph_form():
    graph = {"nodes": [{"id": "a", "type": "wait", "seconds": 1}], "edges": []}
    assert migrate.flow_to_graph(graph) is graph