Initial commit: Vigilar DIY home security system
Phase 1 (Foundation): project skeleton, TOML config + Pydantic validation, MQTT bus wrapper, SQLite schema (9 tables), Click CLI, process supervisor. Phase 2 (Camera): RTSP capture via OpenCV, MOG2 motion detection with configurable sensitivity/zones, adaptive FPS recording (2fps idle/30fps motion) via FFmpeg subprocess, HLS live streaming, pre-motion ring buffer. Phase 3 (Web UI): Flask + Bootstrap 5 dark theme, 6 blueprints, Jinja2 templates (dashboard, kiosk 2x2 grid, events, sensors, recordings, settings), PWA with service worker + Web Push, full admin settings UI with config persistence. Remote Access: WireGuard tunnel configs, nginx reverse proxy with HLS caching + rate limiting, bandwidth-optimized remote HLS stream (426x240 @ 500kbps), DO droplet setup script, certbot TLS. 29 tests passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
104
tests/unit/test_web.py
Normal file
104
tests/unit/test_web.py
Normal file
@@ -0,0 +1,104 @@
|
||||
"""Tests for Flask web application."""
|
||||
|
||||
from vigilar.config import CameraConfig, VigilarConfig
|
||||
from vigilar.web.app import create_app
|
||||
|
||||
|
||||
def test_app_creates():
|
||||
cfg = VigilarConfig()
|
||||
app = create_app(cfg)
|
||||
assert app is not None
|
||||
|
||||
|
||||
def test_index_loads():
|
||||
cfg = VigilarConfig(cameras=[
|
||||
CameraConfig(id="test", display_name="Test", rtsp_url="rtsp://localhost"),
|
||||
])
|
||||
app = create_app(cfg)
|
||||
with app.test_client() as client:
|
||||
resp = client.get("/")
|
||||
assert resp.status_code == 200
|
||||
assert b"Vigilar" in resp.data
|
||||
assert b"Test" in resp.data
|
||||
|
||||
|
||||
def test_settings_loads():
|
||||
cfg = VigilarConfig()
|
||||
app = create_app(cfg)
|
||||
with app.test_client() as client:
|
||||
resp = client.get("/system/settings")
|
||||
assert resp.status_code == 200
|
||||
assert b"Settings" in resp.data
|
||||
|
||||
|
||||
def test_kiosk_loads():
|
||||
cfg = VigilarConfig(cameras=[
|
||||
CameraConfig(id="cam1", display_name="Cam 1", rtsp_url="rtsp://a"),
|
||||
])
|
||||
app = create_app(cfg)
|
||||
with app.test_client() as client:
|
||||
resp = client.get("/kiosk/")
|
||||
assert resp.status_code == 200
|
||||
assert b"Cam 1" in resp.data
|
||||
assert b"kiosk-grid" in resp.data
|
||||
|
||||
|
||||
def test_system_status_api():
|
||||
cfg = VigilarConfig()
|
||||
app = create_app(cfg)
|
||||
with app.test_client() as client:
|
||||
resp = client.get("/system/status")
|
||||
assert resp.status_code == 200
|
||||
data = resp.get_json()
|
||||
assert "arm_state" in data
|
||||
|
||||
|
||||
def test_config_api():
|
||||
cfg = VigilarConfig()
|
||||
app = create_app(cfg)
|
||||
with app.test_client() as client:
|
||||
resp = client.get("/system/api/config")
|
||||
assert resp.status_code == 200
|
||||
data = resp.get_json()
|
||||
assert "system" in data
|
||||
assert "cameras" in data
|
||||
# Secrets should be redacted
|
||||
assert "password_hash" not in data.get("web", {})
|
||||
|
||||
|
||||
def test_camera_status_api():
|
||||
cfg = VigilarConfig(cameras=[
|
||||
CameraConfig(id="test", display_name="Test", rtsp_url="rtsp://localhost"),
|
||||
])
|
||||
app = create_app(cfg)
|
||||
with app.test_client() as client:
|
||||
resp = client.get("/cameras/api/status")
|
||||
assert resp.status_code == 200
|
||||
data = resp.get_json()
|
||||
assert len(data) == 1
|
||||
assert data[0]["id"] == "test"
|
||||
|
||||
|
||||
def test_events_page_loads():
|
||||
cfg = VigilarConfig()
|
||||
app = create_app(cfg)
|
||||
with app.test_client() as client:
|
||||
resp = client.get("/events/")
|
||||
assert resp.status_code == 200
|
||||
assert b"Event Log" in resp.data
|
||||
|
||||
|
||||
def test_sensors_page_loads():
|
||||
cfg = VigilarConfig()
|
||||
app = create_app(cfg)
|
||||
with app.test_client() as client:
|
||||
resp = client.get("/sensors/")
|
||||
assert resp.status_code == 200
|
||||
|
||||
|
||||
def test_recordings_page_loads():
|
||||
cfg = VigilarConfig()
|
||||
app = create_app(cfg)
|
||||
with app.test_client() as client:
|
||||
resp = client.get("/recordings/")
|
||||
assert resp.status_code == 200
|
||||
Reference in New Issue
Block a user