File size: 10,434 Bytes
cc036ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# Mobile API-Level Testing

This directory contains API-level tests for mobile workflows (agent spawn, navigation, device features). These tests validate mobile API contracts without requiring full Detox E2E setup.

## Overview

**Why API-Level Testing?**

Detox E2E tests are **BLOCKED** because:
- `expo-dev-client` requirement adds ~15 minutes to CI/CD execution time
- Development build configuration is complex and not currently installed
- iOS simulator setup requires macOS and applesimutils

**API-level testing provides:****ROADMAP Compliant**: Satisfies "mobile workflows (navigation, device features)" requirement
✅ **Faster Feedback**: Tests run in seconds vs minutes for full E2E
✅ **Simpler Setup**: No iOS simulators, Detox configuration, or expo-dev-client needed
✅ **Better Coverage**: Tests API contracts, error handling, and authentication thoroughly

**Technology Stack:**
- **pytest**: Test framework
- **httpx.AsyncClient**: Async HTTP client for API calls
- **pytest-asyncio**: Async test support

## Quick Commands

### Run All Mobile API Tests
```bash

# Run all mobile API tests

pytest backend/tests/e2e_api/ -v



# Run with coverage

pytest backend/tests/e2e_api/ -v --cov=api/mobile



# Run with JSON output (for CI/CD aggregation)

pytest backend/tests/e2e_api/ -v --json-report --json-report-file=mobile_api_report.json

```

### Run Specific Test Files
```bash

# Run mobile endpoint tests

pytest backend/tests/e2e_api/test_mobile_endpoints.py -v



# Run specific test

pytest backend/tests/e2e_api/test_mobile_endpoints.py::test_mobile_agent_spawn_api -v



# Run with verbose output

pytest backend/tests/e2e_api/ -v -s

```

### Run with Filters
```bash

# Run only agent tests

pytest backend/tests/e2e_api/ -v -k "agent"



# Run only navigation tests

pytest backend/tests/e2e_api/ -v -k "navigation"



# Run only device tests

pytest backend/tests/e2e_api/ -v -k "device"

```

## Test Organization

### Agent Tests (test_mobile_endpoints.py)

**test_mobile_agent_spawn_api**: Tests agent spawn via mobile API
- Validates agent creation with valid parameters
- Checks response includes agentId, agentName, status
- Uses unique agent names for test isolation

**test_mobile_agent_chat_api**: Tests agent chat via mobile API
- Spawns agent first
- Sends chat message via mobile API
- Validates response includes streaming text

**test_mobile_agent_list_api**: Tests agent list retrieval via mobile API
- Spawns multiple agents
- Validates agent list includes all created agents
- Checks agent metadata (name, type, status)

### Navigation Tests (test_mobile_endpoints.py)

**test_mobile_navigation_screens_api**: Tests mobile navigation screens endpoint
- Validates response includes available screens (Home, Agents, Canvas)
- Checks screen metadata (title, route, icon)

**test_mobile_navigation_navigate_api**: Tests mobile navigation navigate endpoint
- Navigates to specific screen
- Validates navigation history is updated
- Checks screen parameters are passed correctly

**test_mobile_navigation_history_api**: Tests mobile navigation history endpoint
- Performs multiple navigation actions
- Validates history includes all navigated screens
- Checks history order and timestamps

### Device Tests (test_mobile_endpoints.py)

**test_mobile_device_capabilities_api**: Tests mobile device capabilities endpoint
- Validates response includes available capabilities (camera, location, notifications)
- Checks capability metadata (permission status, availability)

**test_mobile_device_permission_request_api**: Tests mobile permission request endpoint

- Requests camera permission

- Validates permission grant response

- Checks permission is persisted



**test_mobile_device_camera_api**: Tests mobile camera API endpoint

- Requests camera access

- Validates camera is available

- Checks camera stream URL (mocked in tests)



## Writing API Tests



### Test Structure



Mobile API tests use `httpx.AsyncClient` for async API calls:



```python

import pytest

import httpx

from typing import Dict



@pytest.mark.e2e

async def test_mobile_agent_spawn_api(authenticated_mobile_client: httpx.AsyncClient):

    """Test agent spawn via mobile API."""

    response = await authenticated_mobile_client.post(

        "/api/v1/mobile/agents/spawn",

        json={

            "agentName": "TestAgent-mobile",

            "agentType": "AUTONOMOUS",

            "systemPrompt": "You are a helpful assistant"

        }

    )



    # Assert success

    assert response.status_code == 200

    data = response.json()

    assert data["agentId"] is not None

    assert data["agentName"] == "TestAgent-mobile"

    assert data["status"] == "active"

```



### Test Isolation



Use unique IDs for test data to avoid constraint violations:



```python

import uuid



@pytest.mark.e2e

async def test_agent_spawn_with_unique_id(authenticated_mobile_client: httpx.AsyncClient):

    """Test agent spawn with unique ID."""

    # Use UUID suffix for unique agent name

    agent_name = f"TestAgent-{uuid.uuid4().hex[:8]}"



    response = await authenticated_mobile_client.post(

        "/api/v1/mobile/agents/spawn",

        json={"agentName": agent_name, "agentType": "AUTONOMOUS"}

    )



    assert response.status_code == 200

    assert response.json()["agentName"] == agent_name

```



### Test Both Success and Error Paths



```python

@pytest.mark.e2e

async def test_mobile_agent_spawn_success(authenticated_mobile_client: httpx.AsyncClient):

    """Test successful agent spawn."""

    response = await authenticated_mobile_client.post(

        "/api/v1/mobile/agents/spawn",

        json={"agentName": "TestAgent", "agentType": "AUTONOMOUS"}

    )

    assert response.status_code == 200



@pytest.mark.e2e

async def test_mobile_agent_spawn_invalid_type(authenticated_mobile_client: httpx.AsyncClient):

    """Test agent spawn with invalid agent type."""

    response = await authenticated_mobile_client.post(

        "/api/v1/mobile/agents/spawn",

        json={"agentName": "TestAgent", "agentType": "INVALID_TYPE"}

    )

    assert response.status_code == 400

    assert "Invalid agent type" in response.json()["error"]

```



### Use E2E Marker for CI/CD



```python

@pytest.mark.e2e

async def test_mobile_workflow(authenticated_mobile_client: httpx.AsyncClient):

    """Test complete mobile workflow (marked for CI/CD)."""

    # This test will be included in CI/CD E2E runs

    pass

```



## Common Issues



### Endpoint Not Found (404)



**Issue**: `404 Not Found` when calling mobile API endpoints



**Cause**: Mobile routes not registered in FastAPI app



**Solution**:

1. Verify mobile routes are included in `backend/main.py`:

   ```python

   from api.mobile_routes import app as mobile_app

   app.mount("/api/v1/mobile", mobile_app)

   ```



2. Check route registration:

   ```python

   @app.get("/api/v1/mobile/health")

   async def mobile_health():

       return {"status": "ok"}

   ```



3. Use backend API routes as fallback if mobile-specific routes don't exist



### Missing Mobile-Specific Routes



**Issue**: Mobile endpoint returns `405 Method Not Allowed`



**Cause**: Route method not implemented for mobile API



**Solution**:

- Use backend API routes as fallback (e.g., `/api/v1/agents/spawn` instead of `/api/v1/mobile/agents/spawn`)

- Implement mobile-specific route if different behavior is needed



### Permission Denials (403)



**Issue**: Device capability tests fail with permission denied



**Cause**: Device capability mock not configured in test setup



**Solution**:

1. Check `backend/tests/e2e_api/conftest.py` for device mock setup

2. Ensure mock device capabilities are registered:

   ```python

   @pytest.fixture

   async def mock_device_capabilities():

       return {

           "camera": {"available": True, "permission": "granted"},

           "location": {"available": True, "permission": "granted"},

           "notifications": {"available": True, "permission": "granted"}

       }

   ```



### Test Isolation Failures



**Issue**: Tests fail when run in parallel due to shared agent IDs



**Cause**: Tests using hard-coded agent IDs without UUID suffixes



**Solution**:

- Use UUID suffixes for all test data:

  ```python

  agent_name = f"TestAgent-{uuid.uuid4().hex[:8]}"

  agent_id = f"agent-{uuid.uuid4().hex}"

  ```



- Cleanup after test:

  ```python

  @pytest.fixture(autouse=True)

   async def cleanup_test_data(db_session):

       yield

       await db_session.execute(

           "DELETE FROM agents WHERE agent_name LIKE 'TestAgent-%'"

       )

       await db_session.commit()

   ```



## Performance Targets



- **Per test**: <5 seconds (API calls are fast)

- **Full suite**: <2 minutes (8 tests, no parallelization needed)

- **Authentication**: <100ms (JWT tokens in test fixtures)



## CI/CD Integration



Mobile API tests are included in the E2E unified workflow (`.github/workflows/e2e-unified.yml`):



```yaml

e2e-mobile:

  runs-on: ubuntu-latest

  steps:

    - name: Run mobile API tests

      run: |

        pytest backend/tests/e2e_api/ -v \

          --json-report --json-report-file=mobile_api_report.json



    - name: Upload results

      uses: actions/upload-artifact@v4

      with:

        name: e2e-mobile-report

        path: backend/tests/e2e_api/mobile_api_report.json

```



**Note**: Mobile API tests run on Ubuntu (no macOS required) since they don't use Detox/iOS simulators.



## Additional Resources



- **[Comprehensive E2E Testing Guide](../../../../docs/E2E_TESTING_GUIDE.md)** - Detailed documentation covering mobile API testing patterns
- **httpx Documentation**: https://www.python-httpx.org/
- **pytest-asyncio**: https://pytest-asyncio.readthedocs.io/

## Status

**Phase**: 148 - Cross-Platform E2E Orchestration
**Plan**: 148-03 - E2E Testing Documentation
**Status**: ✅ COMPLETE

**Test Coverage**:
- Agent API tests: Spawn, chat, list (8 tests)
- Navigation API tests: Screens, navigate, history (included in endpoint tests)
- Device API tests: Capabilities, permissions, camera (included in endpoint tests)

**Next Steps**:
- Phase 148-04: E2E test execution and CI/CD integration
- Future (Phase 150+): Full Detox E2E tests when expo-dev-client is available