import pytest import json from unittest.mock import patch, MagicMock from flask import Flask from routes.satellite import satellite_bp @pytest.fixture def app(): app = Flask(__name__) app.register_blueprint(satellite_bp) app.config['TESTING'] = True return app @pytest.fixture def client(app): return app.test_client() def test_predict_passes_invalid_coords(client): """Verify that invalid coordinates return a 400 error.""" payload = { "latitude": 150.0, # Invalid (>90) "longitude": -0.1278 } response = client.post('/satellite/predict', json=payload) assert response.status_code == 400 assert response.json['status'] == 'error' def test_fetch_celestrak_invalid_category(client): """Verify that an unauthorized category is rejected.""" response = client.get('/satellite/celestrak/category_fake') # The code returns 200 but includes an error message in the JSON body assert response.status_code == 200 assert response.json['status'] == 'error' assert 'Invalid category' in response.json['message'] # Mocking Tests (External Calls and Skyfield) @patch('urllib.request.urlopen') def test_update_tle_success(mock_urlopen, client): """Simulate a successful response from CelesTrak.""" mock_content = ( "ISS (ZARYA)\n" "1 25544U 98067A 23321.52083333 .00016717 00000-0 30171-3 0 9992\n" "2 25544 51.6416 20.4567 0004561 45.3212 67.8912 15.49876543123456\n" ).encode('utf-8') mock_response = MagicMock() mock_response.read.return_value = mock_content mock_response.__enter__.return_value = mock_response mock_urlopen.return_value = mock_response response = client.post('/satellite/update-tle') assert response.status_code == 200 assert response.json['status'] == 'success' assert 'ISS' in response.json['updated'] @patch('skyfield.api.load') def test_get_satellite_position_skyfield_error(mock_load, client): """Test behavior when Skyfield fails or data is missing.""" # Force the timescale load to fail mock_load.side_effect = Exception("Skyfield error") payload = { "latitude": 51.5, "longitude": -0.1, "satellites": ["ISS"] } response = client.post('/satellite/position', json=payload) # Should return success but an empty positions list due to internal try-except assert response.status_code == 200 assert response.json['positions'] == [] # Logic Integration Test (Simulating prediction) def test_predict_passes_empty_cache(client): """Verify that if the satellite is not in cache, no passes are returned.""" payload = { "latitude": 51.5, "longitude": -0.1, "satellites": ["SATELLITE_NON_EXISTENT"] } response = client.post('/satellite/predict', json=payload) assert response.status_code == 200 assert len(response.json['passes']) == 0