99 lines
2.9 KiB
Python
99 lines
2.9 KiB
Python
"""
|
|
Shared fixtures for Demeter server tests.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from typing import Any
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
from app.config import DeviceConfig, DevicesConfig, ResourceConfig, Settings
|
|
from app.device_store import DeviceStore
|
|
from app.metrics import MetricsCollector
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_devices_config() -> DevicesConfig:
|
|
"""A minimal device config for testing."""
|
|
return DevicesConfig(
|
|
devices=[
|
|
DeviceConfig(
|
|
id="test-plant-01",
|
|
name="Test Plant",
|
|
ip="192.168.1.100",
|
|
port=5683,
|
|
enabled=True,
|
|
resources=[
|
|
ResourceConfig(uri="sensors/soil_moisture", name="Soil Moisture", type="periodic"),
|
|
ResourceConfig(uri="sensors/temperature", name="Temperature", type="periodic"),
|
|
ResourceConfig(uri="events/trigger", name="Trigger", type="event"),
|
|
],
|
|
),
|
|
DeviceConfig(
|
|
id="test-aquarium-01",
|
|
name="Test Aquarium",
|
|
ip="192.168.1.101",
|
|
port=5683,
|
|
enabled=True,
|
|
resources=[
|
|
ResourceConfig(uri="sensors/temperature", name="Water Temp", type="periodic"),
|
|
],
|
|
),
|
|
DeviceConfig(
|
|
id="test-disabled",
|
|
name="Disabled Device",
|
|
ip="192.168.1.102",
|
|
port=5683,
|
|
enabled=False,
|
|
resources=[],
|
|
),
|
|
]
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def store(sample_devices_config: DevicesConfig) -> DeviceStore:
|
|
"""An initialized DeviceStore with sample devices."""
|
|
return DeviceStore(sample_devices_config)
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_observer() -> MagicMock:
|
|
"""A mock CoapObserverClient for API tests."""
|
|
observer = MagicMock()
|
|
observer.active_subscriptions = 3
|
|
observer.subscription_status.return_value = {
|
|
"test-plant-01/sensors/soil_moisture": "running",
|
|
"test-plant-01/sensors/temperature": "running",
|
|
"test-aquarium-01/sensors/temperature": "running",
|
|
}
|
|
observer.coap_get = AsyncMock(return_value={
|
|
"device": "test-plant-01",
|
|
"temperature": 24.5,
|
|
"unit": "celsius",
|
|
})
|
|
observer.coap_put = AsyncMock(return_value={"interval": 10})
|
|
return observer
|
|
|
|
|
|
@pytest.fixture
|
|
def app(store: DeviceStore, mock_observer: MagicMock):
|
|
"""FastAPI app with mocked dependencies."""
|
|
from app.main import create_app
|
|
|
|
test_app = create_app()
|
|
test_app.state.store = store
|
|
test_app.state.observer = mock_observer
|
|
test_app.state.settings = Settings()
|
|
return test_app
|
|
|
|
|
|
@pytest.fixture
|
|
def client(app) -> TestClient:
|
|
"""FastAPI TestClient (no lifespan — dependencies are mocked)."""
|
|
return TestClient(app, raise_server_exceptions=False)
|