Every tool now returns a structured BaseModel instead of dict[str, Any], giving callers attribute access, IDE autocomplete, and schema validation. Adds ~30 model classes to models.py and updates all test assertions.
121 lines
4.4 KiB
Python
121 lines
4.4 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.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
|