mcp-adb/tests/test_files.py
Ryan Malloy fb297f7937 Add pytest suite (216 tests) and fix UI/notification parser bugs
Test infrastructure with conftest fixtures mocking run_shell_args/run_adb
for device-free testing across all 8 mixins.

Fixed: UI parser regex couldn't match hyphenated XML attributes
(content-desc, resource-id). Notification parser captured trailing
parenthesis in package names.
2026-02-11 03:38:37 -07:00

121 lines
4.5 KiB
Python

"""Tests for files mixin (push, pull, list, delete, exists)."""
import pytest
from tests.conftest import fail, ok
class TestFilePush:
@pytest.mark.usefixtures("_dev_mode")
async def test_push(self, server, ctx, tmp_path):
local_file = tmp_path / "test.txt"
local_file.write_text("content")
server.run_adb.return_value = ok(stdout="1 file pushed")
result = await server.file_push(ctx, str(local_file), "/sdcard/test.txt")
assert result["success"] is True
assert result["device_path"] == "/sdcard/test.txt"
@pytest.mark.usefixtures("_dev_mode")
async def test_local_not_found(self, server, ctx):
result = await server.file_push(ctx, "/nonexistent/file.txt", "/sdcard/")
assert result["success"] is False
assert "not found" in result["error"]
@pytest.mark.usefixtures("_no_dev_mode")
async def test_requires_dev_mode(self, server, ctx):
result = await server.file_push(ctx, "/tmp/f", "/sdcard/f")
assert result["success"] is False
class TestFilePull:
@pytest.mark.usefixtures("_dev_mode")
async def test_pull(self, server, ctx, tmp_path):
server.run_adb.return_value = ok(stdout="1 file pulled")
result = await server.file_pull(
ctx, "/sdcard/test.txt", str(tmp_path / "out.txt")
)
assert result["success"] is True
@pytest.mark.usefixtures("_dev_mode")
async def test_default_local_path(self, server, ctx):
server.run_adb.return_value = ok()
result = await server.file_pull(ctx, "/sdcard/data.db")
assert "data.db" in result["local_path"]
@pytest.mark.usefixtures("_no_dev_mode")
async def test_requires_dev_mode(self, server, ctx):
result = await server.file_pull(ctx, "/sdcard/f")
assert result["success"] is False
class TestFileList:
@pytest.mark.usefixtures("_dev_mode")
async def test_parse_ls(self, server):
server.run_shell_args.return_value = ok(
stdout=(
"total 16\n"
"drwxr-xr-x 2 root root 4096 2024-01-15 10:30 Documents\n"
"-rw-r--r-- 1 root root 1234 2024-01-15 10:31 test.txt\n"
)
)
result = await server.file_list("/sdcard/")
assert result["success"] is True
assert result["count"] == 2
assert result["files"][0]["name"] == "Documents"
assert result["files"][0]["is_directory"] is True
assert result["files"][1]["name"] == "test.txt"
assert result["files"][1]["is_directory"] is False
@pytest.mark.usefixtures("_dev_mode")
async def test_failure(self, server):
server.run_shell_args.return_value = fail("No such file")
result = await server.file_list("/nonexistent/")
assert result["success"] is False
@pytest.mark.usefixtures("_no_dev_mode")
async def test_requires_dev_mode(self, server):
result = await server.file_list()
assert result["success"] is False
class TestFileDelete:
@pytest.mark.usefixtures("_dev_mode")
async def test_delete(self, server, ctx):
ctx.set_elicit("accept", "Yes, delete")
server.run_shell_args.return_value = ok()
result = await server.file_delete(ctx, "/sdcard/old.txt")
assert result["success"] is True
assert result["path"] == "/sdcard/old.txt"
@pytest.mark.usefixtures("_dev_mode")
async def test_cancelled(self, server, ctx):
ctx.set_elicit("accept", "Cancel")
result = await server.file_delete(ctx, "/sdcard/keep.txt")
assert result["success"] is False
assert result.get("cancelled") is True
@pytest.mark.usefixtures("_no_dev_mode")
async def test_requires_dev_mode(self, server, ctx):
result = await server.file_delete(ctx, "/sdcard/f")
assert result["success"] is False
class TestFileExists:
@pytest.mark.usefixtures("_dev_mode")
async def test_exists(self, server):
server.run_shell_args.return_value = ok()
result = await server.file_exists("/sdcard/file.txt")
assert result["success"] is True
assert result["exists"] is True
@pytest.mark.usefixtures("_dev_mode")
async def test_not_exists(self, server):
server.run_shell_args.return_value = fail()
result = await server.file_exists("/sdcard/missing.txt")
assert result["exists"] is False
@pytest.mark.usefixtures("_no_dev_mode")
async def test_requires_dev_mode(self, server):
result = await server.file_exists("/sdcard/f")
assert result["success"] is False