test: raise coverage 68.7% -> ~80.4%; add ~250 tests for new egress/DDNS/network paths
Unit Tests / test (push) Successful in 12m6s

Coverage was below acceptable levels and several newly-added code paths
(sshuttle egress, proxy egress, DDNS provider stubs, DNS overview route,
peer-registry provisioning) had zero test coverage.

~250 new unit tests are added across 16 new test files. Existing test files
are updated to match refactored interfaces (DHCP removed, constants
introduced, network_manager restructured). .coveragerc is added to pin the
source mapping and the 70% floor so regressions are caught at commit time.

tests/test_enhanced_api.py was previously living in api/ (wrong location)
and is moved to tests/ where it belongs.

Integration test files are updated to remove references to DHCP endpoints
and add coverage for the new DNS overview and DDNS sync endpoints.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 09:03:39 -04:00
parent c41cadafb4
commit aa1e5c41ec
33 changed files with 9446 additions and 631 deletions
+205
View File
@@ -131,3 +131,208 @@ def test_complete_setup_fires_identity_changed_on_success(client):
mock_sbus.publish_event.assert_called_once()
event_args = mock_sbus.publish_event.call_args
assert event_args[0][1] == 'setup'
# ---------------------------------------------------------------------------
# GET /api/setup/status
# ---------------------------------------------------------------------------
def test_get_setup_status_returns_200_when_incomplete(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.get_setup_status.return_value = {'step': 'cell_name', 'complete': False}
with patch('app.setup_manager', mock_sm):
resp = client.get('/api/setup/status')
assert resp.status_code == 200
def test_get_setup_status_returns_410_when_already_complete(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = True
with patch('app.setup_manager', mock_sm):
resp = client.get('/api/setup/status')
assert resp.status_code == 410
def test_get_setup_status_returns_setup_data(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.get_setup_status.return_value = {'step': 'cell_name', 'options': {}}
with patch('app.setup_manager', mock_sm):
resp = client.get('/api/setup/status')
data = json.loads(resp.data)
assert 'step' in data
# ---------------------------------------------------------------------------
# POST /api/setup/validate
# ---------------------------------------------------------------------------
def _post_validate(client, payload):
return client.post(
'/api/setup/validate',
data=json.dumps(payload),
content_type='application/json',
)
def test_validate_cell_name_valid(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.validate_cell_name.return_value = []
with patch('app.setup_manager', mock_sm):
resp = _post_validate(client, {'step': 'cell_name', 'data': {'cell_name': 'mycel'}})
assert resp.status_code == 200
data = json.loads(resp.data)
assert data['valid'] is True
assert data['errors'] == []
def test_validate_cell_name_invalid(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.validate_cell_name.return_value = ['Name too short']
with patch('app.setup_manager', mock_sm):
resp = _post_validate(client, {'step': 'cell_name', 'data': {'cell_name': 'a'}})
assert resp.status_code == 200
data = json.loads(resp.data)
assert data['valid'] is False
assert len(data['errors']) > 0
def test_validate_password_valid(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.validate_password.return_value = []
with patch('app.setup_manager', mock_sm):
resp = _post_validate(client, {'step': 'password', 'data': {'password': 'StrongPass1!'}})
assert resp.status_code == 200
data = json.loads(resp.data)
assert data['valid'] is True
def test_validate_password_invalid(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.validate_password.return_value = ['Too short']
with patch('app.setup_manager', mock_sm):
resp = _post_validate(client, {'step': 'password', 'data': {'password': 'weak'}})
data = json.loads(resp.data)
assert data['valid'] is False
def test_validate_pic_ngo_available_when_available(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.validate_cell_name.return_value = []
with patch('app.setup_manager', mock_sm), \
patch('routes.setup._check_pic_ngo_available', return_value=True):
resp = _post_validate(client, {
'step': 'pic_ngo_available', 'data': {'cell_name': 'mycel'}})
data = json.loads(resp.data)
assert data['available'] is True
def test_validate_pic_ngo_available_when_taken(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.validate_cell_name.return_value = []
with patch('app.setup_manager', mock_sm), \
patch('routes.setup._check_pic_ngo_available', return_value=False):
resp = _post_validate(client, {
'step': 'pic_ngo_available', 'data': {'cell_name': 'mycel'}})
data = json.loads(resp.data)
assert data['available'] is False
def test_validate_pic_ngo_name_errors_block_check(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.validate_cell_name.return_value = ['Invalid name']
with patch('app.setup_manager', mock_sm):
resp = _post_validate(client, {
'step': 'pic_ngo_available', 'data': {'cell_name': 'a'}})
data = json.loads(resp.data)
assert data['available'] is False
def test_validate_pic_ngo_service_unreachable_returns_503(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
mock_sm.validate_cell_name.return_value = []
with patch('app.setup_manager', mock_sm), \
patch('routes.setup._check_pic_ngo_available', side_effect=Exception('timeout')):
resp = _post_validate(client, {
'step': 'pic_ngo_available', 'data': {'cell_name': 'mycel'}})
assert resp.status_code == 503
data = json.loads(resp.data)
assert data['available'] is False
def test_validate_cloudflare_token_valid(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
with patch('app.setup_manager', mock_sm), \
patch('routes.setup._verify_cloudflare_token', return_value=True):
resp = _post_validate(client, {
'step': 'cloudflare_token', 'data': {'token': 'mytoken'}})
data = json.loads(resp.data)
assert data['valid'] is True
def test_validate_cloudflare_token_missing(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
with patch('app.setup_manager', mock_sm):
resp = _post_validate(client, {
'step': 'cloudflare_token', 'data': {'token': ''}})
data = json.loads(resp.data)
assert data['valid'] is False
def test_validate_cloudflare_token_invalid(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
with patch('app.setup_manager', mock_sm), \
patch('routes.setup._verify_cloudflare_token', return_value=False):
resp = _post_validate(client, {
'step': 'cloudflare_token', 'data': {'token': 'badtoken'}})
data = json.loads(resp.data)
assert data['valid'] is False
def test_validate_duckdns_token_valid(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
with patch('app.setup_manager', mock_sm), \
patch('routes.setup._verify_duckdns_token', return_value=True):
resp = _post_validate(client, {
'step': 'duckdns_token', 'data': {'subdomain': 'mycel', 'token': 'abc'}})
data = json.loads(resp.data)
assert data['valid'] is True
def test_validate_duckdns_token_missing_fields(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
with patch('app.setup_manager', mock_sm):
resp = _post_validate(client, {
'step': 'duckdns_token', 'data': {'subdomain': '', 'token': ''}})
data = json.loads(resp.data)
assert data['valid'] is False
def test_validate_unknown_step_returns_400(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = False
with patch('app.setup_manager', mock_sm):
resp = _post_validate(client, {'step': 'unknown_step', 'data': {}})
assert resp.status_code == 400
def test_validate_returns_410_when_setup_complete(client):
mock_sm = MagicMock()
mock_sm.is_setup_complete.return_value = True
with patch('app.setup_manager', mock_sm):
resp = _post_validate(client, {'step': 'cell_name', 'data': {'cell_name': 'x'}})
assert resp.status_code == 410