qemu: scroll and home verbs in the driver

scroll X Y DY and home are judged by the channel's own ack, like nav and
wake: the deterministic stand-in for a swipe that only brings a control
into view (flare-edge #174), and the fresh-boot state a live panel needs
before each flow (flare-edge #173).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3G6m9Aw5RyVY4ZowtKzEj
This commit is contained in:
Noah
2026-09-08 16:48:09 -06:00
co-authored by Claude Fable 5.1
parent bd5c5af9db
commit a512d56650
2 changed files with 25 additions and 2 deletions
+9 -2
View File
@@ -42,6 +42,10 @@ class FakeCtl:
return "page: Demo/Rows\ncpu: 12%\nfps: 10\nrender: 3.20 ms/frame\nrga: 0%\nidle: 0"
if cmd == "wake":
return "wake: ok"
if cmd == "home":
return "home: ok"
if cmd.startswith("scroll "):
return "scroll: ok y=300 of 900" if not cmd.endswith(" 0") else "scroll: expected X Y DY (DY non-zero pixels)"
if cmd.startswith("@cat "):
return json.dumps({"a": {"b": 1}, "list": [1, 2], "name": "warden"})
if cmd.startswith("hit "):
@@ -129,9 +133,11 @@ class DriveVerbs(unittest.TestCase):
"capture_region r1 0 0 8 8 exact\n"
"assert_region r1 exact\n"
"assert_region r1\n"
"scroll 360 400 300\n"
"home\n"
)
self.assertIsNone(rc, [r for r in rows if r["status"] != "ok"])
self.assertEqual(len(rows), 12)
self.assertEqual(len(rows), 14)
self.assertTrue(all(r["status"] == "ok" for r in rows))
def test_mismatches_are_fails_not_stops(self):
@@ -142,11 +148,12 @@ class DriveVerbs(unittest.TestCase):
"wait_json a.b eq 2 1\n"
"assert_json a.zz eq 1\n"
"assert_stat fps lt 0\n"
"scroll 360 400 0\n"
"assert_page Demo/Rows\n"
)
self.assertEqual(rc, 1)
self.assertEqual([r["status"] for r in rows],
["fail", "fail", "fail", "fail", "fail", "ok"])
["fail", "fail", "fail", "fail", "fail", "fail", "ok"])
self.assertIn("moved", by["assert_hit 47 676 obj box=0,0,1x1"]["detail"])
self.assertGreaterEqual(time.monotonic() - t0, 1.0, "wait_json must honour its timeout")