chore: Add test reports directory creation step in CI workflows
Some checks failed
Docker Build and Push / build-and-push (push) Failing after 36s
LabFusion CI/CD Pipeline / api-gateway (push) Failing after 1m11s
Integration Tests / integration-tests (push) Failing after 29s
LabFusion CI/CD Pipeline / api-docs (push) Successful in 1m42s
Integration Tests / performance-tests (push) Has been skipped
Service Adapters (Python FastAPI) / test (3.1) (push) Failing after 11s
Service Adapters (Python FastAPI) / test (3.11) (push) Failing after 19s
LabFusion CI/CD Pipeline / frontend (push) Failing after 1m50s
LabFusion CI/CD Pipeline / integration-tests (push) Has been skipped
Service Adapters (Python FastAPI) / test (3.12) (push) Failing after 20s
Service Adapters (Python FastAPI) / test (3.9) (push) Failing after 21s
Service Adapters (Python FastAPI) / build (push) Has been skipped
LabFusion CI/CD Pipeline / service-adapters (push) Failing after 20s
Some checks failed
Docker Build and Push / build-and-push (push) Failing after 36s
LabFusion CI/CD Pipeline / api-gateway (push) Failing after 1m11s
Integration Tests / integration-tests (push) Failing after 29s
LabFusion CI/CD Pipeline / api-docs (push) Successful in 1m42s
Integration Tests / performance-tests (push) Has been skipped
Service Adapters (Python FastAPI) / test (3.1) (push) Failing after 11s
Service Adapters (Python FastAPI) / test (3.11) (push) Failing after 19s
LabFusion CI/CD Pipeline / frontend (push) Failing after 1m50s
LabFusion CI/CD Pipeline / integration-tests (push) Has been skipped
Service Adapters (Python FastAPI) / test (3.12) (push) Failing after 20s
Service Adapters (Python FastAPI) / test (3.9) (push) Failing after 21s
Service Adapters (Python FastAPI) / build (push) Has been skipped
LabFusion CI/CD Pipeline / service-adapters (push) Failing after 20s
### Summary of Changes - Introduced a step to create a `tests/reports` directory in both CI workflows for Service Adapters and the main CI configuration. - This ensures that test reports have a designated location for output, improving organization and accessibility. ### Expected Results - Enhanced structure for test report generation, facilitating easier access to test results and improving overall CI workflow clarity.
This commit is contained in:
@@ -108,6 +108,10 @@ jobs:
|
|||||||
- name: Run linting
|
- name: Run linting
|
||||||
run: flake8 . --count --max-complexity=10 --max-line-length=150
|
run: flake8 . --count --max-complexity=10 --max-line-length=150
|
||||||
|
|
||||||
|
- name: Create test reports directory
|
||||||
|
run: |
|
||||||
|
mkdir -p tests/reports
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
pytest --cov=. --cov-report=xml --cov-report=html --junitxml=tests/reports/junit.xml
|
pytest --cov=. --cov-report=xml --cov-report=html --junitxml=tests/reports/junit.xml
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ jobs:
|
|||||||
bandit -r . -f json -o bandit-report.json
|
bandit -r . -f json -o bandit-report.json
|
||||||
safety check --json --output safety-report.json
|
safety check --json --output safety-report.json
|
||||||
|
|
||||||
|
- name: Create test reports directory
|
||||||
|
run: |
|
||||||
|
mkdir -p tests/reports
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
pytest --cov=. --cov-report=xml --cov-report=html --cov-report=term-missing --junitxml=tests/reports/junit.xml
|
pytest --cov=. --cov-report=xml --cov-report=html --cov-report=term-missing --junitxml=tests/reports/junit.xml
|
||||||
|
|||||||
19
services/service-adapters/pytest.ini
Normal file
19
services/service-adapters/pytest.ini
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[tool:pytest]
|
||||||
|
testpaths = tests
|
||||||
|
python_files = test_*.py
|
||||||
|
python_classes = Test*
|
||||||
|
python_functions = test_*
|
||||||
|
addopts =
|
||||||
|
-v
|
||||||
|
--tb=short
|
||||||
|
--strict-markers
|
||||||
|
--disable-warnings
|
||||||
|
--cov=.
|
||||||
|
--cov-report=term-missing
|
||||||
|
--cov-report=html
|
||||||
|
--cov-report=xml
|
||||||
|
--junitxml=tests/reports/junit.xml
|
||||||
|
markers =
|
||||||
|
unit: Unit tests
|
||||||
|
integration: Integration tests
|
||||||
|
slow: Slow running tests
|
||||||
44
services/service-adapters/run_tests.py
Normal file
44
services/service-adapters/run_tests.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test runner script for LabFusion Service Adapters
|
||||||
|
"""
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def run_tests():
|
||||||
|
"""Run the test suite"""
|
||||||
|
print("🧪 Running LabFusion Service Adapters Tests")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# Ensure test reports directory exists
|
||||||
|
os.makedirs("tests/reports", exist_ok=True)
|
||||||
|
|
||||||
|
# Run pytest with coverage
|
||||||
|
cmd = [
|
||||||
|
"pytest",
|
||||||
|
"tests/",
|
||||||
|
"-v",
|
||||||
|
"--cov=.",
|
||||||
|
"--cov-report=term-missing",
|
||||||
|
"--cov-report=html",
|
||||||
|
"--cov-report=xml",
|
||||||
|
"--junitxml=tests/reports/junit.xml",
|
||||||
|
"--tb=short"
|
||||||
|
]
|
||||||
|
|
||||||
|
print(f"Running: {' '.join(cmd)}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
result = subprocess.run(cmd, cwd=os.path.dirname(__file__))
|
||||||
|
|
||||||
|
if result.returncode == 0:
|
||||||
|
print("\n✅ All tests passed!")
|
||||||
|
else:
|
||||||
|
print("\n❌ Some tests failed!")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_tests()
|
||||||
1
services/service-adapters/tests/__init__.py
Normal file
1
services/service-adapters/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Test package for LabFusion Service Adapters
|
||||||
106
services/service-adapters/tests/conftest.py
Normal file
106
services/service-adapters/tests/conftest.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
"""
|
||||||
|
Pytest configuration and fixtures for service adapters tests
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from main import app
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def client():
|
||||||
|
"""Provide a test client for the FastAPI app"""
|
||||||
|
return TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_services_config():
|
||||||
|
"""Mock services configuration for testing"""
|
||||||
|
return {
|
||||||
|
"home_assistant": {
|
||||||
|
"enabled": True,
|
||||||
|
"url": "http://homeassistant.local:8123",
|
||||||
|
"token": "test_token"
|
||||||
|
},
|
||||||
|
"frigate": {
|
||||||
|
"enabled": True,
|
||||||
|
"url": "http://frigate.local:5000"
|
||||||
|
},
|
||||||
|
"immich": {
|
||||||
|
"enabled": False,
|
||||||
|
"url": "http://immich.local:2283",
|
||||||
|
"api_key": "test_key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def sample_ha_entities():
|
||||||
|
"""Sample Home Assistant entities for testing"""
|
||||||
|
return {
|
||||||
|
"sensor.temperature": {
|
||||||
|
"entity_id": "sensor.temperature",
|
||||||
|
"state": "22.5",
|
||||||
|
"attributes": {
|
||||||
|
"unit_of_measurement": "°C",
|
||||||
|
"friendly_name": "Temperature"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"light.living_room": {
|
||||||
|
"entity_id": "light.living_room",
|
||||||
|
"state": "on",
|
||||||
|
"attributes": {
|
||||||
|
"friendly_name": "Living Room Light"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def sample_frigate_events():
|
||||||
|
"""Sample Frigate events for testing"""
|
||||||
|
return {
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"id": "event_123",
|
||||||
|
"timestamp": "2024-01-01T12:00:00Z",
|
||||||
|
"camera": "front_door",
|
||||||
|
"label": "person",
|
||||||
|
"confidence": 0.95
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "event_456",
|
||||||
|
"timestamp": "2024-01-01T12:05:00Z",
|
||||||
|
"camera": "back_yard",
|
||||||
|
"label": "car",
|
||||||
|
"confidence": 0.87
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def sample_immich_assets():
|
||||||
|
"""Sample Immich assets for testing"""
|
||||||
|
return {
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"id": "asset_123",
|
||||||
|
"filename": "IMG_20240101_120000.jpg",
|
||||||
|
"created_at": "2024-01-01T12:00:00Z",
|
||||||
|
"tags": ["family", "vacation"],
|
||||||
|
"faces": ["person_1", "person_2"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def mock_redis():
|
||||||
|
"""Mock Redis client for all tests"""
|
||||||
|
with patch('services.redis_client.redis_client') as mock_redis:
|
||||||
|
mock_redis.ping.return_value = True
|
||||||
|
mock_redis.set.return_value = True
|
||||||
|
mock_redis.get.return_value = None
|
||||||
|
yield mock_redis
|
||||||
87
services/service-adapters/tests/test_general_routes.py
Normal file
87
services/service-adapters/tests/test_general_routes.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
"""
|
||||||
|
Tests for general API routes
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from main import app
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGeneralRoutes:
|
||||||
|
"""Test general API routes"""
|
||||||
|
|
||||||
|
def test_root_endpoint(self):
|
||||||
|
"""Test the root endpoint"""
|
||||||
|
response = client.get("/")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
assert data["message"] == "LabFusion Service Adapters API"
|
||||||
|
assert data["version"] == "1.0.0"
|
||||||
|
|
||||||
|
def test_health_check(self):
|
||||||
|
"""Test the health check endpoint"""
|
||||||
|
response = client.get("/health")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
assert data["status"] == "healthy"
|
||||||
|
assert "timestamp" in data
|
||||||
|
# Verify timestamp is in ISO format
|
||||||
|
assert "T" in data["timestamp"] or "Z" in data["timestamp"]
|
||||||
|
|
||||||
|
@patch('services.config.SERVICES')
|
||||||
|
def test_get_services(self, mock_services):
|
||||||
|
"""Test the get services endpoint"""
|
||||||
|
# Mock the services configuration
|
||||||
|
mock_services.items.return_value = [
|
||||||
|
("home_assistant", {
|
||||||
|
"enabled": True,
|
||||||
|
"url": "http://homeassistant.local:8123"
|
||||||
|
}),
|
||||||
|
("frigate", {
|
||||||
|
"enabled": True,
|
||||||
|
"url": "http://frigate.local:5000"
|
||||||
|
}),
|
||||||
|
("immich", {
|
||||||
|
"enabled": False,
|
||||||
|
"url": "http://immich.local:2283"
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
|
response = client.get("/services")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
assert "home_assistant" in data
|
||||||
|
assert "frigate" in data
|
||||||
|
assert "immich" in data
|
||||||
|
|
||||||
|
# Check service status structure
|
||||||
|
ha_service = data["home_assistant"]
|
||||||
|
assert ha_service["enabled"] is True
|
||||||
|
assert ha_service["url"] == "http://homeassistant.local:8123"
|
||||||
|
assert ha_service["status"] == "unknown"
|
||||||
|
|
||||||
|
def test_health_check_response_model(self):
|
||||||
|
"""Test that health check returns proper response model"""
|
||||||
|
response = client.get("/health")
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
# Verify all required fields are present
|
||||||
|
required_fields = ["status", "timestamp"]
|
||||||
|
for field in required_fields:
|
||||||
|
assert field in data
|
||||||
|
|
||||||
|
def test_root_response_model(self):
|
||||||
|
"""Test that root endpoint returns proper response model"""
|
||||||
|
response = client.get("/")
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
# Verify all required fields are present
|
||||||
|
required_fields = ["message", "version"]
|
||||||
|
for field in required_fields:
|
||||||
|
assert field in data
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
"""
|
||||||
|
Tests for Home Assistant routes
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
from unittest.mock import patch, AsyncMock
|
||||||
|
|
||||||
|
from main import app
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
|
class TestHomeAssistantRoutes:
|
||||||
|
"""Test Home Assistant API routes"""
|
||||||
|
|
||||||
|
@patch('routes.home_assistant.httpx.AsyncClient')
|
||||||
|
async def test_get_entities_success(self, mock_client_class):
|
||||||
|
"""Test successful retrieval of Home Assistant entities"""
|
||||||
|
# Mock the HTTP client response
|
||||||
|
mock_response = AsyncMock()
|
||||||
|
mock_response.json.return_value = {
|
||||||
|
"sensor.temperature": {
|
||||||
|
"entity_id": "sensor.temperature",
|
||||||
|
"state": "22.5",
|
||||||
|
"attributes": {
|
||||||
|
"unit_of_measurement": "°C",
|
||||||
|
"friendly_name": "Temperature"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"light.living_room": {
|
||||||
|
"entity_id": "light.living_room",
|
||||||
|
"state": "on",
|
||||||
|
"attributes": {
|
||||||
|
"friendly_name": "Living Room Light"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mock_response.status_code = 200
|
||||||
|
|
||||||
|
mock_client = AsyncMock()
|
||||||
|
mock_client.get.return_value = mock_response
|
||||||
|
mock_client_class.return_value.__aenter__.return_value = mock_client
|
||||||
|
|
||||||
|
response = client.get("/home-assistant/entities")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
assert "entities" in data
|
||||||
|
assert len(data["entities"]) == 2
|
||||||
|
|
||||||
|
# Check first entity
|
||||||
|
temp_entity = data["entities"][0]
|
||||||
|
assert temp_entity["entity_id"] == "sensor.temperature"
|
||||||
|
assert temp_entity["state"] == "22.5"
|
||||||
|
assert temp_entity["attributes"]["unit_of_measurement"] == "°C"
|
||||||
|
|
||||||
|
@patch('routes.home_assistant.httpx.AsyncClient')
|
||||||
|
async def test_get_entities_api_error(self, mock_client_class):
|
||||||
|
"""Test handling of Home Assistant API errors"""
|
||||||
|
# Mock HTTP error response
|
||||||
|
mock_response = AsyncMock()
|
||||||
|
mock_response.status_code = 500
|
||||||
|
mock_response.text = "Internal Server Error"
|
||||||
|
|
||||||
|
mock_client = AsyncMock()
|
||||||
|
mock_client.get.return_value = mock_response
|
||||||
|
mock_client_class.return_value.__aenter__.return_value = mock_client
|
||||||
|
|
||||||
|
response = client.get("/home-assistant/entities")
|
||||||
|
assert response.status_code == 500
|
||||||
|
|
||||||
|
@patch('routes.home_assistant.httpx.AsyncClient')
|
||||||
|
async def test_get_entities_connection_error(self, mock_client_class):
|
||||||
|
"""Test handling of connection errors"""
|
||||||
|
# Mock connection error
|
||||||
|
mock_client_class.return_value.__aenter__.side_effect = Exception("Connection failed")
|
||||||
|
|
||||||
|
response = client.get("/home-assistant/entities")
|
||||||
|
assert response.status_code == 500
|
||||||
|
|
||||||
|
def test_get_entities_endpoint_exists(self):
|
||||||
|
"""Test that the entities endpoint exists"""
|
||||||
|
# This will fail if the route doesn't exist, but we can't test the actual
|
||||||
|
# functionality without mocking the Home Assistant API
|
||||||
|
response = client.get("/home-assistant/entities")
|
||||||
|
# Should return either 200 (success) or 500 (API error)
|
||||||
|
assert response.status_code in [200, 500]
|
||||||
|
|
||||||
|
def test_home_assistant_routes_available(self):
|
||||||
|
"""Test that Home Assistant routes are available"""
|
||||||
|
# Check that the router is included by testing a known endpoint
|
||||||
|
response = client.get("/home-assistant/entities")
|
||||||
|
# Should not return 404 (route not found)
|
||||||
|
assert response.status_code != 404
|
||||||
49
services/service-adapters/tests/test_main.py
Normal file
49
services/service-adapters/tests/test_main.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
"""
|
||||||
|
Tests for the main FastAPI application
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
|
from main import app
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMainApp:
|
||||||
|
"""Test the main FastAPI application"""
|
||||||
|
|
||||||
|
def test_app_creation(self):
|
||||||
|
"""Test that the FastAPI app is created correctly"""
|
||||||
|
assert app is not None
|
||||||
|
assert app.title == "LabFusion Service Adapters"
|
||||||
|
assert app.version == "1.0.0"
|
||||||
|
|
||||||
|
def test_cors_middleware(self):
|
||||||
|
"""Test that CORS middleware is properly configured"""
|
||||||
|
# Test a simple request to verify CORS headers
|
||||||
|
response = client.get("/")
|
||||||
|
assert response.status_code == 200
|
||||||
|
# CORS headers should be present
|
||||||
|
assert "access-control-allow-origin" in response.headers
|
||||||
|
|
||||||
|
def test_routers_included(self):
|
||||||
|
"""Test that all routers are included"""
|
||||||
|
# Check that all expected routes are available
|
||||||
|
routes = [route.path for route in app.routes]
|
||||||
|
|
||||||
|
# General routes
|
||||||
|
assert "/" in routes
|
||||||
|
assert "/health" in routes
|
||||||
|
assert "/services" in routes
|
||||||
|
|
||||||
|
# Other service routes should be included
|
||||||
|
# (exact paths depend on router definitions)
|
||||||
|
|
||||||
|
def test_openapi_docs(self):
|
||||||
|
"""Test that OpenAPI documentation is available"""
|
||||||
|
response = client.get("/docs")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
response = client.get("/openapi.json")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "openapi" in response.json()
|
||||||
181
services/service-adapters/tests/test_models.py
Normal file
181
services/service-adapters/tests/test_models.py
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
"""
|
||||||
|
Tests for Pydantic models and schemas
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
|
from models.schemas import (
|
||||||
|
ServiceStatus, HAAttributes, HAEntity, HAEntitiesResponse,
|
||||||
|
FrigateEvent, FrigateEventsResponse, ImmichAsset, ImmichAssetsResponse,
|
||||||
|
EventData, EventResponse, Event, EventsResponse,
|
||||||
|
HealthResponse, RootResponse
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestServiceStatus:
|
||||||
|
"""Test ServiceStatus model"""
|
||||||
|
|
||||||
|
def test_service_status_creation(self):
|
||||||
|
"""Test creating a ServiceStatus instance"""
|
||||||
|
service = ServiceStatus(
|
||||||
|
enabled=True,
|
||||||
|
url="http://example.com",
|
||||||
|
status="healthy"
|
||||||
|
)
|
||||||
|
assert service.enabled is True
|
||||||
|
assert service.url == "http://example.com"
|
||||||
|
assert service.status == "healthy"
|
||||||
|
|
||||||
|
def test_service_status_validation(self):
|
||||||
|
"""Test ServiceStatus validation"""
|
||||||
|
# Valid data
|
||||||
|
service = ServiceStatus(
|
||||||
|
enabled=False,
|
||||||
|
url="https://api.example.com",
|
||||||
|
status="unhealthy"
|
||||||
|
)
|
||||||
|
assert service.enabled is False
|
||||||
|
|
||||||
|
def test_service_status_required_fields(self):
|
||||||
|
"""Test that required fields are enforced"""
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
ServiceStatus() # Missing required fields
|
||||||
|
|
||||||
|
|
||||||
|
class TestHAAttributes:
|
||||||
|
"""Test HAAttributes model"""
|
||||||
|
|
||||||
|
def test_ha_attributes_creation(self):
|
||||||
|
"""Test creating HAAttributes instance"""
|
||||||
|
attrs = HAAttributes(
|
||||||
|
unit_of_measurement="°C",
|
||||||
|
friendly_name="Living Room Temperature"
|
||||||
|
)
|
||||||
|
assert attrs.unit_of_measurement == "°C"
|
||||||
|
assert attrs.friendly_name == "Living Room Temperature"
|
||||||
|
|
||||||
|
def test_ha_attributes_optional_fields(self):
|
||||||
|
"""Test that fields are optional"""
|
||||||
|
attrs = HAAttributes()
|
||||||
|
assert attrs.unit_of_measurement is None
|
||||||
|
assert attrs.friendly_name is None
|
||||||
|
|
||||||
|
|
||||||
|
class TestHAEntity:
|
||||||
|
"""Test HAEntity model"""
|
||||||
|
|
||||||
|
def test_ha_entity_creation(self):
|
||||||
|
"""Test creating HAEntity instance"""
|
||||||
|
attributes = HAAttributes(
|
||||||
|
unit_of_measurement="°C",
|
||||||
|
friendly_name="Temperature"
|
||||||
|
)
|
||||||
|
entity = HAEntity(
|
||||||
|
entity_id="sensor.temperature",
|
||||||
|
state="22.5",
|
||||||
|
attributes=attributes
|
||||||
|
)
|
||||||
|
assert entity.entity_id == "sensor.temperature"
|
||||||
|
assert entity.state == "22.5"
|
||||||
|
assert entity.attributes.unit_of_measurement == "°C"
|
||||||
|
|
||||||
|
|
||||||
|
class TestFrigateEvent:
|
||||||
|
"""Test FrigateEvent model"""
|
||||||
|
|
||||||
|
def test_frigate_event_creation(self):
|
||||||
|
"""Test creating FrigateEvent instance"""
|
||||||
|
event = FrigateEvent(
|
||||||
|
id="event_123",
|
||||||
|
timestamp="2024-01-01T12:00:00Z",
|
||||||
|
camera="front_door",
|
||||||
|
label="person",
|
||||||
|
confidence=0.95
|
||||||
|
)
|
||||||
|
assert event.id == "event_123"
|
||||||
|
assert event.camera == "front_door"
|
||||||
|
assert event.label == "person"
|
||||||
|
assert event.confidence == 0.95
|
||||||
|
|
||||||
|
def test_frigate_event_confidence_validation(self):
|
||||||
|
"""Test confidence validation (0-1 range)"""
|
||||||
|
# Valid confidence
|
||||||
|
event = FrigateEvent(
|
||||||
|
id="event_123",
|
||||||
|
timestamp="2024-01-01T12:00:00Z",
|
||||||
|
camera="front_door",
|
||||||
|
label="person",
|
||||||
|
confidence=0.5
|
||||||
|
)
|
||||||
|
assert event.confidence == 0.5
|
||||||
|
|
||||||
|
# Invalid confidence (too high)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
FrigateEvent(
|
||||||
|
id="event_123",
|
||||||
|
timestamp="2024-01-01T12:00:00Z",
|
||||||
|
camera="front_door",
|
||||||
|
label="person",
|
||||||
|
confidence=1.5
|
||||||
|
)
|
||||||
|
|
||||||
|
# Invalid confidence (negative)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
FrigateEvent(
|
||||||
|
id="event_123",
|
||||||
|
timestamp="2024-01-01T12:00:00Z",
|
||||||
|
camera="front_door",
|
||||||
|
label="person",
|
||||||
|
confidence=-0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestEventData:
|
||||||
|
"""Test EventData model"""
|
||||||
|
|
||||||
|
def test_event_data_creation(self):
|
||||||
|
"""Test creating EventData instance"""
|
||||||
|
event = EventData(
|
||||||
|
service="home_assistant",
|
||||||
|
event_type="state_changed",
|
||||||
|
metadata={"entity_id": "sensor.temperature", "new_state": "22.5"}
|
||||||
|
)
|
||||||
|
assert event.service == "home_assistant"
|
||||||
|
assert event.event_type == "state_changed"
|
||||||
|
assert event.metadata["entity_id"] == "sensor.temperature"
|
||||||
|
|
||||||
|
def test_event_data_default_metadata(self):
|
||||||
|
"""Test default metadata is empty dict"""
|
||||||
|
event = EventData(
|
||||||
|
service="test_service",
|
||||||
|
event_type="test_event"
|
||||||
|
)
|
||||||
|
assert event.metadata == {}
|
||||||
|
|
||||||
|
|
||||||
|
class TestHealthResponse:
|
||||||
|
"""Test HealthResponse model"""
|
||||||
|
|
||||||
|
def test_health_response_creation(self):
|
||||||
|
"""Test creating HealthResponse instance"""
|
||||||
|
timestamp = datetime.now().isoformat()
|
||||||
|
health = HealthResponse(
|
||||||
|
status="healthy",
|
||||||
|
timestamp=timestamp
|
||||||
|
)
|
||||||
|
assert health.status == "healthy"
|
||||||
|
assert health.timestamp == timestamp
|
||||||
|
|
||||||
|
|
||||||
|
class TestRootResponse:
|
||||||
|
"""Test RootResponse model"""
|
||||||
|
|
||||||
|
def test_root_response_creation(self):
|
||||||
|
"""Test creating RootResponse instance"""
|
||||||
|
response = RootResponse(
|
||||||
|
message="Test API",
|
||||||
|
version="1.0.0"
|
||||||
|
)
|
||||||
|
assert response.message == "Test API"
|
||||||
|
assert response.version == "1.0.0"
|
||||||
Reference in New Issue
Block a user