#!/usr/bin/env python3 """ Tests for PUT /api/peers/. Key scenarios: - 404 when peer_registry.get_peer returns None - 200 on successful update - config_needs_reinstall=True in response when internet_access changes - config_needs_reinstall=False (config_changed=False) when only description changes """ import sys import json import unittest from pathlib import Path from unittest.mock import patch, MagicMock api_dir = Path(__file__).parent.parent / 'api' sys.path.insert(0, str(api_dir)) from app import app class TestUpdatePeer(unittest.TestCase): def setUp(self): app.config['TESTING'] = True self.client = app.test_client() @patch('app.firewall_manager') @patch('app.peer_registry') def test_update_peer_returns_404_when_peer_not_found(self, mock_reg, mock_fw): mock_reg.get_peer.return_value = None r = self.client.put( '/api/peers/ghost', data=json.dumps({'description': 'updated'}), content_type='application/json', ) self.assertEqual(r.status_code, 404) data = json.loads(r.data) self.assertIn('error', data) @patch('app.firewall_manager') @patch('app.peer_registry') def test_update_peer_returns_200_on_success(self, mock_reg, mock_fw): existing = { 'peer': 'alice', 'ip': '10.0.0.2', 'internet_access': True, 'public_key': 'KEY==', } mock_reg.get_peer.return_value = existing mock_reg.update_peer.return_value = True mock_reg.list_peers.return_value = [existing] mock_fw.apply_peer_rules.return_value = None mock_fw.apply_all_dns_rules.return_value = None r = self.client.put( '/api/peers/alice', data=json.dumps({'description': 'my laptop'}), content_type='application/json', ) self.assertEqual(r.status_code, 200) data = json.loads(r.data) self.assertIn('message', data) @patch('app.firewall_manager') @patch('app.peer_registry') def test_update_peer_config_changed_true_when_internet_access_changes( self, mock_reg, mock_fw ): existing = { 'peer': 'alice', 'ip': '10.0.0.2', 'internet_access': True, 'public_key': 'KEY==', } mock_reg.get_peer.return_value = existing mock_reg.update_peer.return_value = True mock_reg.list_peers.return_value = [existing] mock_fw.apply_peer_rules.return_value = None mock_fw.apply_all_dns_rules.return_value = None r = self.client.put( '/api/peers/alice', data=json.dumps({'internet_access': False}), content_type='application/json', ) self.assertEqual(r.status_code, 200) data = json.loads(r.data) self.assertTrue(data['config_changed']) @patch('app.firewall_manager') @patch('app.peer_registry') def test_update_peer_config_changed_false_when_only_description_changes( self, mock_reg, mock_fw ): existing = { 'peer': 'alice', 'ip': '10.0.0.2', 'internet_access': True, 'public_key': 'KEY==', } mock_reg.get_peer.return_value = existing mock_reg.update_peer.return_value = True mock_reg.list_peers.return_value = [existing] mock_fw.apply_peer_rules.return_value = None mock_fw.apply_all_dns_rules.return_value = None r = self.client.put( '/api/peers/alice', data=json.dumps({'description': 'just a label'}), content_type='application/json', ) self.assertEqual(r.status_code, 200) data = json.loads(r.data) self.assertFalse(data['config_changed']) @patch('app.firewall_manager') @patch('app.peer_registry') def test_update_peer_returns_500_when_update_fails(self, mock_reg, mock_fw): existing = { 'peer': 'alice', 'ip': '10.0.0.2', 'internet_access': True, 'public_key': 'KEY==', } mock_reg.get_peer.return_value = existing mock_reg.update_peer.return_value = False r = self.client.put( '/api/peers/alice', data=json.dumps({'description': 'fail'}), content_type='application/json', ) self.assertEqual(r.status_code, 500) self.assertIn('error', json.loads(r.data)) @patch('app.firewall_manager') @patch('app.peer_registry') def test_update_peer_config_changed_true_when_ip_changes(self, mock_reg, mock_fw): existing = { 'peer': 'alice', 'ip': '10.0.0.2', 'internet_access': True, 'public_key': 'KEY==', } mock_reg.get_peer.return_value = existing mock_reg.update_peer.return_value = True mock_reg.list_peers.return_value = [existing] mock_fw.apply_peer_rules.return_value = None mock_fw.apply_all_dns_rules.return_value = None r = self.client.put( '/api/peers/alice', data=json.dumps({'ip': '10.0.0.99'}), content_type='application/json', ) self.assertEqual(r.status_code, 200) data = json.loads(r.data) self.assertTrue(data['config_changed']) @patch('app.peer_registry') def test_update_peer_returns_500_on_exception(self, mock_reg): mock_reg.get_peer.side_effect = Exception('disk error') r = self.client.put( '/api/peers/alice', data=json.dumps({'description': 'test'}), content_type='application/json', ) self.assertEqual(r.status_code, 500) self.assertIn('error', json.loads(r.data)) if __name__ == '__main__': unittest.main()