diff --git a/tests/test_main.py b/tests/test_main.py new file mode 100644 index 0000000..609be9e --- /dev/null +++ b/tests/test_main.py @@ -0,0 +1,73 @@ +import pytest +from fastapi.testclient import TestClient +from app.main import app, lifespan +from unittest.mock import patch, MagicMock + +@pytest.fixture +def client(): + """Test client for FastAPI app""" + return TestClient(app) + +def test_root_endpoint(client): + """Test root endpoint returns expected message""" + response = client.get("/") + assert response.status_code == 200 + assert response.json() == {"message": "IPTV Updater API"} + +def test_openapi_schema_generation(client): + """Test OpenAPI schema is properly generated""" + # First call - generate schema + response = client.get("/openapi.json") + assert response.status_code == 200 + schema = response.json() + assert schema["openapi"] == "3.1.0" + assert "securitySchemes" in schema["components"] + assert "Bearer" in schema["components"]["securitySchemes"] + + # Test empty components initialization + with patch("app.main.get_openapi", return_value={"info": {}}): + # Clear cached schema + app.openapi_schema = None + # Get schema with empty response + response = client.get("/openapi.json") + assert response.status_code == 200 + schema = response.json() + assert "components" in schema + assert "schemas" in schema["components"] + +def test_openapi_schema_caching(mocker): + """Test OpenAPI schema caching behavior""" + # Clear any existing schema + app.openapi_schema = None + + # Mock get_openapi to return test schema + mock_schema = {"test": "schema"} + mocker.patch("app.main.get_openapi", return_value=mock_schema) + + # First call - should call get_openapi + schema = app.openapi() + assert schema == mock_schema + assert app.openapi_schema == mock_schema + + # Second call - should return cached schema + with patch("app.main.get_openapi") as mock_get_openapi: + schema = app.openapi() + assert schema == mock_schema + mock_get_openapi.assert_not_called() + +@pytest.mark.asyncio +async def test_lifespan_init_db(mocker): + """Test lifespan manager initializes database""" + mock_init_db = mocker.patch("app.main.init_db") + async with lifespan(app): + pass # Just enter/exit context + mock_init_db.assert_called_once() + +def test_router_inclusion(): + """Test all routers are properly included""" + route_paths = {route.path for route in app.routes} + assert "/" in route_paths + assert any(path.startswith("/auth") for path in route_paths) + assert any(path.startswith("/channels") for path in route_paths) + assert any(path.startswith("/playlist") for path in route_paths) + assert any(path.startswith("/priorities") for path in route_paths) \ No newline at end of file