import pytest import tempfile import json import sqlite3 from pathlib import Path from datetime import datetime from sensorpajen.config import SensorConfig from sensorpajen.discovery_manager import DiscoveryManager def test_tui_sensor_config_edit(): """Integration test: Test that editing a sensor works end-to-end""" with tempfile.TemporaryDirectory() as tmpdir: config_file = Path(tmpdir) / "sensors.json" db_file = Path(tmpdir) / "test.db" # Create initial config initial_data = { "sensors": [ {"mac": "AA:BB:CC:DD:EE:FF", "name": "Living Room Sensor"} ] } config_file.write_text(json.dumps(initial_data, indent=2)) # Initialize database conn = sqlite3.connect(str(db_file)) cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS discovered_sensors ( mac TEXT PRIMARY KEY, name TEXT, rssi INTEGER, first_seen TIMESTAMP, last_seen TIMESTAMP, count INTEGER DEFAULT 0, last_temp REAL, last_humidity REAL, last_battery_percent INTEGER, last_battery_voltage INTEGER, status TEXT DEFAULT 'pending', reviewed BOOLEAN DEFAULT 0, ignored_at TIMESTAMP, ignore_reason TEXT ) """) now = datetime.now().isoformat() cursor.execute(""" INSERT INTO discovered_sensors (mac, name, rssi, first_seen, last_seen, count, last_temp, last_humidity, last_battery_percent, last_battery_voltage, status, reviewed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'approved', 1) """, ("AA:BB:CC:DD:EE:FF", "Living Room Sensor", -65, now, now, 50, 23.5, 55, 85, 2950)) conn.commit() conn.close() # Load config and discovery manager (simulating TUI) config = SensorConfig(str(config_file)) dm = DiscoveryManager(str(db_file), config) # Verify initial state assert config.sensors["AA:BB:CC:DD:EE:FF"] == "Living Room Sensor" # Edit sensor (simulate user action in TUI) config.add_sensor("AA:BB:CC:DD:EE:FF", "Bedroom Sensor") # Verify in-memory update assert config.sensors["AA:BB:CC:DD:EE:FF"] == "Bedroom Sensor" # Verify disk update saved_data = json.loads(config_file.read_text()) assert saved_data["sensors"][0]["name"] == "Bedroom Sensor" # Simulate refresh_data() - create new config instance and verify config2 = SensorConfig(str(config_file)) assert config2.sensors["AA:BB:CC:DD:EE:FF"] == "Bedroom Sensor" def test_sensor_config_edit_updates_memory(): """Test that editing a sensor updates both disk and memory""" with tempfile.TemporaryDirectory() as tmpdir: config_file = Path(tmpdir) / "sensors.json" # Create initial config initial_data = { "sensors": [ {"mac": "AA:BB:CC:DD:EE:FF", "name": "Original Name"} ] } config_file.write_text(json.dumps(initial_data, indent=2)) # Load config config = SensorConfig(str(config_file)) assert config.sensors["AA:BB:CC:DD:EE:FF"] == "Original Name" # Edit sensor config.add_sensor("AA:BB:CC:DD:EE:FF", "Updated Name") # Check in-memory is updated assert config.sensors["AA:BB:CC:DD:EE:FF"] == "Updated Name" # Check disk is updated saved_data = json.loads(config_file.read_text()) assert saved_data["sensors"][0]["name"] == "Updated Name" # Reload from disk and verify config2 = SensorConfig(str(config_file)) assert config2.sensors["AA:BB:CC:DD:EE:FF"] == "Updated Name" def test_sensor_config_remove_sensor(): """Test that removing a sensor works correctly""" with tempfile.TemporaryDirectory() as tmpdir: config_file = Path(tmpdir) / "sensors.json" # Create config with multiple sensors initial_data = { "sensors": [ {"mac": "AA:BB:CC:DD:EE:FF", "name": "Sensor 1"}, {"mac": "AA:BB:CC:DD:EE:11", "name": "Sensor 2"} ] } config_file.write_text(json.dumps(initial_data, indent=2)) # Load and verify config = SensorConfig(str(config_file)) assert len(config.sensors) == 2 # Remove one sensor config.remove_sensor("AA:BB:CC:DD:EE:FF") # Check in-memory removal assert "AA:BB:CC:DD:EE:FF" not in config.sensors assert "AA:BB:CC:DD:EE:11" in config.sensors # Check disk update saved_data = json.loads(config_file.read_text()) assert len(saved_data["sensors"]) == 1 assert saved_data["sensors"][0]["mac"] == "AA:BB:CC:DD:EE:11" def test_sensor_config_reload(): """Test that reload() re-reads from disk""" with tempfile.TemporaryDirectory() as tmpdir: config_file = Path(tmpdir) / "sensors.json" # Create initial config initial_data = { "sensors": [ {"mac": "AA:BB:CC:DD:EE:FF", "name": "Original Name"} ] } config_file.write_text(json.dumps(initial_data, indent=2)) # Load config config = SensorConfig(str(config_file)) assert config.sensors["AA:BB:CC:DD:EE:FF"] == "Original Name" # Manually modify file on disk new_data = { "sensors": [ {"mac": "AA:BB:CC:DD:EE:FF", "name": "Externally Modified"} ] } config_file.write_text(json.dumps(new_data, indent=2)) # Reload should pick up the changes config.load() assert config.sensors["AA:BB:CC:DD:EE:FF"] == "Externally Modified" def test_discovery_manager_approve_sensor(): """Test that approving a sensor works correctly""" with tempfile.TemporaryDirectory() as tmpdir: config_file = Path(tmpdir) / "sensors.json" db_file = Path(tmpdir) / "test.db" # Create empty config config_file.write_text(json.dumps({"sensors": []}, indent=2)) # Initialize database with pending sensor conn = sqlite3.connect(str(db_file)) cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS discovered_sensors ( mac TEXT PRIMARY KEY, name TEXT, rssi INTEGER, first_seen TIMESTAMP, last_seen TIMESTAMP, count INTEGER DEFAULT 0, last_temp REAL, last_humidity REAL, last_battery_percent INTEGER, last_battery_voltage INTEGER, status TEXT DEFAULT 'pending', reviewed BOOLEAN DEFAULT 0, ignored_at TIMESTAMP, ignore_reason TEXT ) """) now = datetime.now().isoformat() cursor.execute(""" INSERT INTO discovered_sensors (mac, name, rssi, first_seen, last_seen, count, status) VALUES (?, ?, ?, ?, ?, ?, ?) """, ("AA:BB:CC:DD:EE:33", "Unknown Sensor", -80, now, now, 1, "pending")) conn.commit() conn.close() # Load config and DM config = SensorConfig(str(config_file)) dm = DiscoveryManager(str(db_file), config) # Verify sensor is pending pending = dm.get_pending() assert len(pending) == 1 assert pending[0].mac == "AA:BB:CC:DD:EE:33" # Approve and add to config (simulate TUI action) config.add_sensor("AA:BB:CC:DD:EE:33", "Kitchen Sensor") dm.approve("AA:BB:CC:DD:EE:33") # Verify sensor is no longer pending (filtered by config) pending = dm.get_pending() assert len(pending) == 0 # Verify it's in config assert config.sensors["AA:BB:CC:DD:EE:33"] == "Kitchen Sensor"