1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
# Author: cirakg & claude ai
# Summary: Tests for the UI flow driver's pure parts: key layout, JSON lookup, the app-log reader, barcode reading.
from __future__ import annotations
import json
import threading
import time
from pathlib import Path
import pytest
import segno
import ui_flow
from PIL import Image
def write_sim(tmp_path: Path, config: dict[str, object]) -> Path:
(tmp_path / "simulator.json").write_text(json.dumps(config), encoding="utf-8")
return tmp_path
def test_load_keys_gives_button_centres(tmp_path: Path) -> None:
device = write_sim(
tmp_path,
{
"keys": [
{"id": "enter", "behavior": "onSelect", "location": {"x": 10, "y": 20, "width": 30, "height": 40}},
{
"id": "menu",
"behavior": "onMenu",
"isHold": True,
"location": {"x": 0, "y": 0, "width": 2, "height": 2},
},
{"id": "start", "location": {"x": 5, "y": 5, "width": 10, "height": 10}},
]
},
)
keys = ui_flow.load_keys(device)
assert keys["enter"] == ui_flow.Key(25, 40, "onSelect", False)
assert keys["menu"].hold
assert keys["start"].behavior == ""
def test_find_key_searches_nested_structures() -> None:
data = {"display": {"isTouch": True}, "glance": [{"contentArea": {"x": 1}}]}
assert ui_flow.find_key(data, "isTouch") is True
assert ui_flow.find_key(data, "contentArea") == {"x": 1}
assert ui_flow.find_key(data, "missing") is None
def test_app_log_waits_only_for_lines_after_the_mark(tmp_path: Path) -> None:
log_path = tmp_path / "app.log"
log_path.write_text("DIAG shown list\n", encoding="utf-8")
log = ui_flow.AppLog(log_path)
assert log.wait_for(r"DIAG shown list\s*$", 1).group(0).startswith("DIAG shown list")
log.set_mark()
def append_later() -> None:
time.sleep(0.2)
with log_path.open("a", encoding="utf-8") as f:
f.write("DIAG shown otp\n")
writer = threading.Thread(target=append_later)
writer.start()
assert log.wait_for(r"DIAG shown otp", 3)
writer.join()
with pytest.raises(ui_flow.FlowError):
log.wait_for(r"DIAG shown list", 0.3) # only before the mark
def test_app_log_latest_returns_the_last_match(tmp_path: Path) -> None:
log_path = tmp_path / "app.log"
log_path.write_text("DIAG list_focus y=10\nother\nDIAG list_focus y=42\n", encoding="utf-8")
match = ui_flow.AppLog(log_path).latest(r"DIAG list_focus y=(\d+)")
assert match is not None and match.group(1) == "42"
assert ui_flow.AppLog(tmp_path / "missing.log").latest("x") is None
def test_barcodes_on_reads_a_drawn_code(tmp_path: Path) -> None:
path = tmp_path / "qr.png"
segno.make("OTPW stress", error="m").save(str(path), scale=4, border=4)
screen = Image.open(path).convert("RGB")
assert ui_flow.barcodes_on(screen) == ["OTPW stress"]
assert ui_flow.barcodes_on(Image.new("RGB", (100, 100), "white")) == []
|