From aefa88d3b13f22d91d7d3341026063f2c7a7518d Mon Sep 17 00:00:00 2001 From: msramalho <19508417+msramalho@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:04:36 +0100 Subject: [PATCH] default endpoints tested --- .gitignore | 3 +- Pipfile | 11 ++++ src/endpoints/default.py | 3 +- src/main.py | 15 ++++-- src/security.py | 2 - src/tests/endpoints/test_default.py | 79 +++++++++++++++++++++++++++++ src/tests/test_main.py | 22 ++++++++ src/tests/test_start.py | 13 ----- 8 files changed, 125 insertions(+), 23 deletions(-) create mode 100644 Pipfile create mode 100644 src/tests/endpoints/test_default.py create mode 100644 src/tests/test_main.py delete mode 100644 src/tests/test_start.py diff --git a/.gitignore b/.gitignore index 7df1354..e9ae646 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ wit* src/crawls .coverage .pytest_cache/* -htmlcov \ No newline at end of file +htmlcov +local_archive \ No newline at end of file diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..c398b0d --- /dev/null +++ b/Pipfile @@ -0,0 +1,11 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] + +[dev-packages] + +[requires] +python_version = "3.10" diff --git a/src/endpoints/default.py b/src/endpoints/default.py index 5580324..091202e 100644 --- a/src/endpoints/default.py +++ b/src/endpoints/default.py @@ -12,7 +12,6 @@ from security import get_user_auth, bearer_security default_router = APIRouter() - @default_router.get("/") async def home(request: Request): # TODO: maybe split into 2 routes: one non authenticated and one authenticated for the groups info only @@ -27,7 +26,7 @@ async def home(request: Request): @default_router.get("/health") -async def health(request: Request): +async def health(): return JSONResponse({"status": "ok"}) @default_router.get("/groups", response_model=list[str]) diff --git a/src/main.py b/src/main.py index 7424dee..369a206 100644 --- a/src/main.py +++ b/src/main.py @@ -50,11 +50,16 @@ app.include_router(interoperability_router) # prometheus exposed in /metrics with authentication Instrumentator(should_group_status_codes=False, excluded_handlers=["/metrics"]).instrument(app).expose(app, dependencies=[Depends(token_api_key_auth)]) -# used mostly for development in combination with local_archive -SERVE_LOCAL_ARCHIVE = os.environ.get("SERVE_LOCAL_ARCHIVE", "") -if len(SERVE_LOCAL_ARCHIVE) > 1 and os.path.isdir(SERVE_LOCAL_ARCHIVE): - logger.info(f"mounting local archive {SERVE_LOCAL_ARCHIVE}") - app.mount(SERVE_LOCAL_ARCHIVE, StaticFiles(directory=SERVE_LOCAL_ARCHIVE), name=SERVE_LOCAL_ARCHIVE) +def setup_local_archive_serve(): + # if env SERVE_LOCAL_ARCHIVE is set it serves files from that dir, useful for development and using local_archive + SERVE_LOCAL_ARCHIVE = os.environ.get("SERVE_LOCAL_ARCHIVE", "") + local_dir = SERVE_LOCAL_ARCHIVE + if not os.path.isdir(local_dir) and os.path.isdir(local_dir.replace("/app", ".")): + local_dir = local_dir.replace("/app", ".") + if len(SERVE_LOCAL_ARCHIVE) > 1 and os.path.isdir(local_dir): + logger.warning(f"MOUNTing local archive {SERVE_LOCAL_ARCHIVE}") + app.mount(SERVE_LOCAL_ARCHIVE, StaticFiles(directory=local_dir), name=SERVE_LOCAL_ARCHIVE) +setup_local_archive_serve() app.middleware("http")(logging_middleware) diff --git a/src/security.py b/src/security.py index f1e70f3..860a396 100644 --- a/src/security.py +++ b/src/security.py @@ -8,8 +8,6 @@ from core.config import CHROME_APP_IDS, BLOCKED_EMAILS assert len(CHROME_APP_IDS) > 0, "CHROME_APP_IDS env variable not properly set, it's a csv" for app_id in CHROME_APP_IDS: assert len(app_id) > 10, f"CHROME_APP_IDS got invalid id: {app_id} env variable not set" -logger.info(f"{CHROME_APP_IDS=}") -logger.info(f"{len(BLOCKED_EMAILS)=}") # Auth logic bearer_security = HTTPBearer() diff --git a/src/tests/endpoints/test_default.py b/src/tests/endpoints/test_default.py new file mode 100644 index 0000000..12a5e44 --- /dev/null +++ b/src/tests/endpoints/test_default.py @@ -0,0 +1,79 @@ +from unittest.mock import AsyncMock, patch +from fastapi.testclient import TestClient +from core.config import VERSION + + +def test_endpoint_home(): + from main import app + client = TestClient(app) + + r = client.get("/") + assert r.status_code == 200 + j = r.json() + assert "version" in j and j["version"] == VERSION + assert "breakingChanges" in j + assert "groups" not in j + + +@patch("endpoints.default.bearer_security", new_callable=AsyncMock) +@patch("endpoints.default.get_user_auth", new_callable=AsyncMock, return_value="test@example.com") +@patch("endpoints.default.crud.get_user_groups", return_value=["group1", "group2"]) +def test_endpoint_home_with_groups(m1, m2, m3): + from main import app + client = TestClient(app) + + r = client.get("/") + assert r.status_code == 200 + j = r.json() + assert "version" in j and j["version"] == VERSION + assert "breakingChanges" in j + assert "groups" in j + assert j["groups"] == ["group1", "group2"] + + +def test_endpoint_health(): + from main import app + client = TestClient(app) + + r = client.get("/health") + assert r.status_code == 200 + assert r.json() == {"status": "ok"} + + +def test_endpoint_groups_403(): + from main import app + client = TestClient(app) + r = client.get("/groups") + assert r.status_code == 403 + + +@patch("endpoints.default.crud.get_user_groups", return_value=["group1", "group2"]) +def test_endpoint_groups(m1): + async def mock_get_user_auth(): return True + from main import app + from security import get_user_auth + app.dependency_overrides[get_user_auth] = mock_get_user_auth + + client = TestClient(app) + r = client.get("/groups") + + assert r.status_code == 200 + j = r.json() + assert j == ["group1", "group2"] + + +def test_no_serve_local_archive_by_default(): + from main import app + client = TestClient(app) + + r = client.get("/app/local_archive_test/temp.txt") + assert r.status_code == 404 + + +def test_favicon(): + from main import app + client = TestClient(app) + + r = client.get("/favicon.ico") + assert r.status_code == 200 + assert r.headers["content-type"] == "image/vnd.microsoft.icon" diff --git a/src/tests/test_main.py b/src/tests/test_main.py new file mode 100644 index 0000000..4c26073 --- /dev/null +++ b/src/tests/test_main.py @@ -0,0 +1,22 @@ +import os +from fastapi.testclient import TestClient + + +def test_serve_local_archive_logic(): + os.environ["SERVE_LOCAL_ARCHIVE"] = "/app/local_archive_test" + + # create a test file + os.makedirs("local_archive_test", exist_ok=True) + with open("local_archive_test/temp.txt", "w") as f: + f.write("test") + + from main import app, setup_local_archive_serve + setup_local_archive_serve() + client = TestClient(app) + + r = client.get("/app/local_archive_test/temp.txt") + assert r.status_code == 200 + assert r.text == "test" + + os.remove("local_archive_test/temp.txt") + os.rmdir("local_archive_test") diff --git a/src/tests/test_start.py b/src/tests/test_start.py deleted file mode 100644 index 4fec658..0000000 --- a/src/tests/test_start.py +++ /dev/null @@ -1,13 +0,0 @@ -import pytest -from fastapi.testclient import TestClient -from core.config import VERSION - -def test_mock_logger(): - from main import app - - client = TestClient(app) - - response = client.get("/") - assert response.status_code == 200 - r = response.json() - assert "version" in r and r["version"] == VERSION \ No newline at end of file