Skip to content

Commit 67973bb

Browse files
authored
Merge pull request #1 from nim444/tests
Tests case
2 parents b5e3268 + 8a715d4 commit 67973bb

File tree

6 files changed

+932
-13
lines changed

6 files changed

+932
-13
lines changed

.github/workflows/ci.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: CI Pipeline
2+
3+
on:
4+
push:
5+
branches: [ "main", "tests"]
6+
pull_request:
7+
branches: [ "main" ]
8+
workflow_dispatch: # Allows manual triggering
9+
10+
11+
12+
jobs:
13+
lint:
14+
name: Lint & Format Check
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
20+
- name: Set up Python 3.13
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: "3.13"
24+
25+
- name: Install uv
26+
run: curl -LsSf https://astral.sh/uv/install.sh | sh
27+
# Add uv to the PATH
28+
- name: Add uv to PATH
29+
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
30+
31+
- name: Install dependencies (including dev)
32+
run: uv pip install --system .
33+
34+
- name: Lint with Ruff
35+
run: uv run ruff check server.py
36+
37+
38+
test:
39+
name: Run Tests
40+
runs-on: ubuntu-latest
41+
needs: lint # Ensure linting passes before testing
42+
steps:
43+
- name: Checkout code
44+
uses: actions/checkout@v4
45+
46+
- name: Set up Python 3.13
47+
uses: actions/setup-python@v5
48+
with:
49+
python-version: "3.13"
50+
51+
- name: Install uv
52+
run: curl -LsSf https://astral.sh/uv/install.sh | sh
53+
# Add uv to the PATH
54+
- name: Add uv to PATH
55+
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
56+
57+
58+
- name: Install dependencies (including test)
59+
run: uv pip install --system .
60+
61+
- name: Run tests with pytest
62+
run: uv run pytest -v

pyproject.toml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
[project]
22
name = "mcp-adb"
33
version = "0.1.0"
4-
description = "Add your description here"
4+
description = "An MCP server for Android automation using UIAutomator2"
55
readme = "README.md"
66
requires-python = ">=3.13"
77
dependencies = [
88
"asyncio>=3.4.3",
99
"mcp[cli]>=1.7.0",
10-
"uiautodev>=0.6.0",
10+
"uiautodev>=0.6.0", # This likely pins fastapi, which pins starlette < 0.38.0
1111
"uiautomator2>=3.2.9",
12+
"python-multipart>=0.0.9", # Already added
13+
# "starlette>=0.38.0", # This caused conflicts, so we revert this change
14+
"ruff>=0.11.8",
15+
"pytest>=8.3.5",
16+
"pytest-cov>=6.1.1",
17+
"pytest-asyncio>=0.26.0",
18+
]
19+
20+
[tool.pytest.ini_options]
21+
filterwarnings = [
22+
"ignore:Please use \\`import python_multipart\\` instead.:PendingDeprecationWarning:starlette\\.formparsers",
1223
]

readme.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
[![Python 3.13](https://img.shields.io/badge/python-3.13-blue.svg)](https://www.python.org/downloads/)
2-
[![PyPI](https://img.shields.io/pypi/v/uiautomator2.svg?label=uiautomator2)](https://pypi.python.org/pypi/uiautomator2)
3-
[![PyPI](https://img.shields.io/pypi/v/adbutils.svg?label=adbutils)](https://github.com/openatx/adbutils)
4-
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/openatx/android-uiautomator-server.svg?label=android-uiautomator-server)](https://github.com/openatx/android-uiautomator-server)
2+
[![CI Pipeline](https://github.com/nim444/fastapi-auth-multi-db/actions/workflows/ci.yml/badge.svg)](https://github.com/nim444/mcp-android-server-python/actions/workflows/ci.yml)
3+
[![Tests passing](https://img.shields.io/badge/Tests-passing-brightgreen.svg)](#running-tests) [![Code style: ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
54
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
65

76
# MCP Android Agent

server.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
# server.py
22
from mcp.server.fastmcp import FastMCP
33
import uiautomator2 as u2
4-
from typing import List, Optional, Dict, Any, Tuple
4+
from typing import List, Optional, Dict, Any
55
import shutil
66
import subprocess
77
import asyncio
8-
from dataclasses import dataclass
98
from typing import TypedDict
109

1110
# Create an MCP server
@@ -358,7 +357,7 @@ def click(
358357
else:
359358
raise ValueError(f"Invalid selector_type: {selector_type}")
360359

361-
if el:
360+
if el and el.exists:
362361
el.click()
363362
return True
364363
return False
@@ -423,7 +422,7 @@ def get_element_info(
423422
else:
424423
raise ValueError(f"Invalid selector_type: {selector_type}")
425424

426-
if el:
425+
if el and el.exists:
427426
info = el.info
428427
return {
429428
"text": info.get("text", ""),
@@ -500,7 +499,8 @@ def wait_for_element(
500499
elif selector_type == "resourceId":
501500
return d(resourceId=selector).wait(timeout=timeout)
502501
elif selector_type == "description":
503-
return d(description=selector).wait(timeout=timeout)
502+
el = d(description=selector).wait(timeout=timeout)
503+
return el is not None and el.exists
504504
else:
505505
raise ValueError(f"Invalid selector_type: {selector_type}")
506506
except Exception as e:
@@ -559,7 +559,7 @@ def long_click(
559559
else:
560560
raise ValueError(f"Invalid selector_type: {selector_type}")
561561

562-
if el.exists:
562+
if el and el.exists:
563563
el.long_click(duration=duration)
564564
return True
565565
return False
@@ -589,7 +589,8 @@ def scroll_to(
589589
elif selector_type == "resourceId":
590590
return d(scrollable=True).scroll.to(resourceId=selector)
591591
elif selector_type == "description":
592-
return d(scrollable=True).scroll.to(description=selector)
592+
el = d(scrollable=True).scroll.to(description=selector)
593+
return el is not None and el.exists
593594
else:
594595
raise ValueError(f"Invalid selector_type: {selector_type}")
595596
except Exception as e:
@@ -628,7 +629,7 @@ def drag(
628629
else:
629630
raise ValueError(f"Invalid selector_type: {selector_type}")
630631

631-
if el.exists:
632+
if el and el.exists:
632633
el.drag_to(to_x, to_y)
633634
return True
634635
return False

tests/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)