🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
200 lines
6.7 KiB
Python
200 lines
6.7 KiB
Python
"""Integration tests for PM3 API endpoints.
|
|
|
|
Tests the refactored PM3 API endpoints to ensure:
|
|
- Proper integration with PM3Service
|
|
- Correct HTTP status codes for different error types
|
|
- Request/response format consistency
|
|
- Session management integration
|
|
"""
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from unittest.mock import patch, AsyncMock, Mock
|
|
|
|
from app.backend.services.pm3_service import PM3ServiceResult, PM3ServiceError
|
|
|
|
|
|
class TestPM3APIStatus:
|
|
"""Test /api/pm3/status endpoint."""
|
|
|
|
def test_get_status_success(self, test_client, mock_pm3_service):
|
|
"""Test successful status retrieval."""
|
|
# Arrange
|
|
mock_pm3_service.get_status.return_value = PM3ServiceResult(
|
|
success=True,
|
|
data={
|
|
"connected": True,
|
|
"device_path": "/dev/ttyACM0",
|
|
"version": "Proxmark3 v4.0",
|
|
"session_active": False
|
|
}
|
|
)
|
|
|
|
# Act
|
|
with patch('app.backend.api.pm3.container') as mock_container:
|
|
mock_container.pm3_service = mock_pm3_service
|
|
response = test_client.get("/api/pm3/status")
|
|
|
|
# Assert
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["connected"] is True
|
|
assert data["device"] == "/dev/ttyACM0"
|
|
assert "Proxmark3" in data["version"]
|
|
|
|
def test_get_status_error(self, test_client, mock_pm3_service):
|
|
"""Test status retrieval with error."""
|
|
# Arrange
|
|
mock_pm3_service.get_status.return_value = PM3ServiceResult(
|
|
success=False,
|
|
error=PM3ServiceError(
|
|
code="status_error",
|
|
message="Failed to query status"
|
|
)
|
|
)
|
|
|
|
# Act
|
|
with patch('app.backend.api.pm3.container') as mock_container:
|
|
mock_container.pm3_service = mock_pm3_service
|
|
response = test_client.get("/api/pm3/status")
|
|
|
|
# Assert
|
|
assert response.status_code == 500
|
|
assert "Failed to query status" in response.json()["detail"]
|
|
|
|
|
|
class TestPM3APICommand:
|
|
"""Test /api/pm3/command endpoint."""
|
|
|
|
def test_execute_command_success(self, test_client, mock_pm3_service):
|
|
"""Test successful command execution."""
|
|
# Arrange
|
|
mock_pm3_service.execute_command.return_value = PM3ServiceResult(
|
|
success=True,
|
|
data={
|
|
"output": "Proxmark3 RFID instrument",
|
|
"command": "hw version",
|
|
"session_id": "test-session"
|
|
}
|
|
)
|
|
|
|
# Act
|
|
with patch('app.backend.api.pm3.container') as mock_container:
|
|
mock_container.pm3_service = mock_pm3_service
|
|
response = test_client.post(
|
|
"/api/pm3/command",
|
|
json={"command": "hw version", "session_id": "test-session"}
|
|
)
|
|
|
|
# Assert
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["success"] is True
|
|
assert "Proxmark3" in data["output"]
|
|
assert data["error"] is None
|
|
|
|
def test_execute_command_session_locked(self, test_client, mock_pm3_service):
|
|
"""Test command execution with session locked."""
|
|
# Arrange
|
|
mock_pm3_service.execute_command.return_value = PM3ServiceResult(
|
|
success=False,
|
|
error=PM3ServiceError(
|
|
code="session_locked",
|
|
message="Another session is active"
|
|
)
|
|
)
|
|
|
|
# Act
|
|
with patch('app.backend.api.pm3.container') as mock_container:
|
|
mock_container.pm3_service = mock_pm3_service
|
|
response = test_client.post(
|
|
"/api/pm3/command",
|
|
json={"command": "hw version", "session_id": "test-session"}
|
|
)
|
|
|
|
# Assert
|
|
assert response.status_code == 423 # Locked
|
|
assert "Another session is active" in response.json()["detail"]
|
|
|
|
def test_execute_command_pm3_not_connected(self, test_client, mock_pm3_service):
|
|
"""Test command execution when PM3 not connected."""
|
|
# Arrange
|
|
mock_pm3_service.execute_command.return_value = PM3ServiceResult(
|
|
success=False,
|
|
error=PM3ServiceError(
|
|
code="pm3_not_connected",
|
|
message="Proxmark3 not connected"
|
|
)
|
|
)
|
|
|
|
# Act
|
|
with patch('app.backend.api.pm3.container') as mock_container:
|
|
mock_container.pm3_service = mock_pm3_service
|
|
response = test_client.post(
|
|
"/api/pm3/command",
|
|
json={"command": "hw version"}
|
|
)
|
|
|
|
# Assert
|
|
assert response.status_code == 200 # Returns in body, not HTTP error
|
|
data = response.json()
|
|
assert data["success"] is False
|
|
assert "not connected" in data["error"].lower()
|
|
|
|
|
|
class TestPM3APIConnection:
|
|
"""Test PM3 connection endpoints."""
|
|
|
|
def test_connect_success(self, test_client, mock_pm3_service):
|
|
"""Test successful PM3 connection."""
|
|
# Arrange
|
|
mock_pm3_service.connect.return_value = PM3ServiceResult(
|
|
success=True,
|
|
data={"message": "Connected to Proxmark3"}
|
|
)
|
|
|
|
# Act
|
|
with patch('app.backend.api.pm3.container') as mock_container:
|
|
mock_container.pm3_service = mock_pm3_service
|
|
response = test_client.post("/api/pm3/connect")
|
|
|
|
# Assert
|
|
assert response.status_code == 200
|
|
assert response.json()["success"] is True
|
|
|
|
def test_connect_failure(self, test_client, mock_pm3_service):
|
|
"""Test PM3 connection failure."""
|
|
# Arrange
|
|
mock_pm3_service.connect.return_value = PM3ServiceResult(
|
|
success=False,
|
|
error=PM3ServiceError(
|
|
code="connection_error",
|
|
message="Device not found"
|
|
)
|
|
)
|
|
|
|
# Act
|
|
with patch('app.backend.api.pm3.container') as mock_container:
|
|
mock_container.pm3_service = mock_pm3_service
|
|
response = test_client.post("/api/pm3/connect")
|
|
|
|
# Assert
|
|
assert response.status_code == 503
|
|
assert "Device not found" in response.json()["detail"]
|
|
|
|
def test_disconnect_success(self, test_client, mock_pm3_service):
|
|
"""Test successful PM3 disconnection."""
|
|
# Arrange
|
|
mock_pm3_service.disconnect.return_value = PM3ServiceResult(
|
|
success=True,
|
|
data={"message": "Disconnected from Proxmark3"}
|
|
)
|
|
|
|
# Act
|
|
with patch('app.backend.api.pm3.container') as mock_container:
|
|
mock_container.pm3_service = mock_pm3_service
|
|
response = test_client.post("/api/pm3/disconnect")
|
|
|
|
# Assert
|
|
assert response.status_code == 200
|
|
assert response.json()["success"] is True
|