"""Tests for UI inspection mixin (dump, find, wait, tap_text).""" from tests.conftest import fail, ok SAMPLE_UI_XML = """ """ class TestUiDump: async def test_dump(self, server, ctx): server.run_shell_args.side_effect = [ ok(), # uiautomator dump ok(stdout=SAMPLE_UI_XML), # cat ok(), # rm cleanup ] result = await server.ui_dump(ctx) assert result.success is True assert result.element_count >= 2 # Settings + Wi-Fi at minimum assert result.xml is not None async def test_dump_failure(self, server, ctx): server.run_shell_args.return_value = fail("error") result = await server.ui_dump(ctx) assert result.success is False class TestParseUiElements: def test_parse_clickable(self, server): elements = server._parse_ui_elements(SAMPLE_UI_XML) texts = [e["text"] for e in elements] assert "Settings" in texts assert "Wi-Fi" in texts def test_center_coordinates(self, server): elements = server._parse_ui_elements(SAMPLE_UI_XML) settings = [e for e in elements if e["text"] == "Settings"][0] assert settings["center"] == {"x": 100, "y": 125} def test_content_desc_included(self, server): elements = server._parse_ui_elements(SAMPLE_UI_XML) icon = [e for e in elements if e["content_desc"] == "Settings icon"] assert len(icon) == 1 def test_empty_xml(self, server): elements = server._parse_ui_elements("") assert elements == [] class TestUiFindElement: async def test_find_by_text(self, server): server.run_shell_args.side_effect = [ok(), ok(stdout=SAMPLE_UI_XML), ok()] result = await server.ui_find_element(text="Settings") assert result.success is True assert result.count == 1 assert result.matches[0]["text"] == "Settings" async def test_find_by_resource_id(self, server): server.run_shell_args.side_effect = [ok(), ok(stdout=SAMPLE_UI_XML), ok()] result = await server.ui_find_element(resource_id="title") # Settings and Wi-Fi both have "title" in their resource-id assert result.count >= 2 async def test_not_found(self, server): server.run_shell_args.side_effect = [ok(), ok(stdout=SAMPLE_UI_XML), ok()] result = await server.ui_find_element(text="Missing") assert result.success is True assert result.count == 0 class TestWaitForText: async def test_found_immediately(self, server): server.run_shell_args.side_effect = [ok(), ok(stdout=SAMPLE_UI_XML), ok()] result = await server.wait_for_text("Settings", timeout_seconds=1) assert result.success is True assert result.found is True assert result.attempts == 1 async def test_timeout(self, server): server.run_shell_args.side_effect = [ ok(), ok(stdout=""), ok(), ] * 10 result = await server.wait_for_text( "Missing", timeout_seconds=0.1, poll_interval=0.05 ) assert result.success is False assert result.found is False class TestWaitForTextGone: async def test_already_gone(self, server): server.run_shell_args.side_effect = [ ok(), ok(stdout=""), ok(), ] result = await server.wait_for_text_gone("Missing", timeout_seconds=1) assert result.success is True assert result.gone is True class TestTapText: async def test_tap_found(self, server): # find_element calls ui_dump which has 3 calls, then tap has 1 server.run_shell_args.side_effect = [ ok(), ok(stdout=SAMPLE_UI_XML), ok(), # ui_dump for find ok(), # tap ] result = await server.tap_text("Settings") assert result.success is True assert result.coordinates == {"x": 100, "y": 125} async def test_not_found(self, server): server.run_shell_args.side_effect = [ ok(), ok(stdout=SAMPLE_UI_XML), ok(), # first search by text ok(), ok(stdout=SAMPLE_UI_XML), ok(), # fallback search by content_desc ] result = await server.tap_text("NonExistent") assert result.success is False assert "No element found" in result.error