Skip to content

Commit

Permalink
tests: experiment results api
Browse files Browse the repository at this point in the history
  • Loading branch information
v-rocheleau committed Nov 22, 2024
1 parent 96a1fc8 commit 323f32a
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 38 deletions.
5 changes: 1 addition & 4 deletions authz_plugins/api_key/authz.module.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from logging import Logger
from typing import Annotated, Any, Awaitable, Callable, Coroutine, Sequence
from fastapi import Depends, FastAPI, HTTPException, Header, Request, Response
from fastapi import Depends, HTTPException, Header, Request, Response
from fastapi.responses import JSONResponse

from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware
Expand Down Expand Up @@ -40,9 +40,6 @@ def __init__(self, config: Config, logger: Logger) -> None:

# Middleware lifecycle

def attach(self, app: FastAPI):
app.middleware("http")(self.dispatch)

async def dispatch(
self, request: Request, call_next: Callable[[Request], Awaitable[Response]]
) -> Coroutine[Any, Any, Response]:
Expand Down
15 changes: 12 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest_asyncio
from httpx._types import HeaderTypes

from tests.test_db import TEST_EXPERIMENT_RESULT
from transcriptomics_data_service.db import Database, get_db
from transcriptomics_data_service.logger import get_logger

Expand Down Expand Up @@ -51,6 +52,11 @@ async def db_cleanup(db: Database):
await db.close()


@pytest_asyncio.fixture
async def db_with_experiment(db: Database):
await db.create_experiment_result(TEST_EXPERIMENT_RESULT)


@pytest.fixture
def test_client(db: Database):
with TestClient(app) as client:
Expand All @@ -61,6 +67,9 @@ def test_client(db: Database):
@pytest.fixture
def authz_headers(config) -> HeaderTypes:
api_key = config.model_extra.get("api_key")
return {
"x-api-key": api_key
}
return {"x-api-key": api_key}


@pytest.fixture
def authz_headers_bad() -> HeaderTypes:
return {"x-api-key": "bad key"}
10 changes: 6 additions & 4 deletions tests/test_authz_plugin.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from transcriptomics_data_service.authz.plugin import import_module_from_path


class AuthzDisabled:
bento_authz_enabled = False


def test_import_authz_plugin_disabled():
config = lambda: None
config.bento_authz_enabled = False
authz_plugin = import_module_from_path("", config)
assert authz_plugin == None
authz_plugin = import_module_from_path("", AuthzDisabled())
assert authz_plugin is None
52 changes: 52 additions & 0 deletions tests/test_experiments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from fastapi import status

from tests.test_db import TEST_EXPERIMENT_RESULT
from transcriptomics_data_service.config import get_config
from transcriptomics_data_service.logger import get_logger
from transcriptomics_data_service.models import ExperimentResult

config = get_config()
logger = get_logger(config)


def test_get_experiment(test_client, authz_headers, db_with_experiment, db_cleanup):
# TEST_EXPERIMENT_RESULT_ID
response = test_client.get(
f"/experiment/{TEST_EXPERIMENT_RESULT.experiment_result_id}",
headers=authz_headers,
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert TEST_EXPERIMENT_RESULT == ExperimentResult(**data)


# EMPTY DB
def test_get_experiment_400(test_client):
# Missing api-key
response = test_client.get("/experiment/non-existant")
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_get_experiment_200_empty(test_client, authz_headers):
# Missing api-key
response = test_client.get("/experiment/non-existant", headers=authz_headers)
assert response.status_code == status.HTTP_200_OK
assert response.json() is None


def test_delete_experiment_400(test_client):
# Missing api-key
response = test_client.delete("/experiment/non-existant")
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_delete_experiment_403(test_client, authz_headers_bad):
# Missing api-key
response = test_client.delete("/experiment/non-existant", headers=authz_headers_bad)
assert response.status_code == status.HTTP_403_FORBIDDEN


def test_delete_experiment_200(test_client, authz_headers):
# Missing api-key
response = test_client.delete("/experiment/non-existant", headers=authz_headers)
assert response.status_code == status.HTTP_200_OK
2 changes: 2 additions & 0 deletions tests/test_expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@

api_key = config.model_extra.get("api_key")


def test_expressions_unauthorized(test_client: TestClient):
response = test_client.get("/expressions")
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_expressions_authorized(test_client: TestClient, authz_headers):
response = test_client.get("/expressions", headers=authz_headers)
assert response.status_code == status.HTTP_200_OK
45 changes: 31 additions & 14 deletions tests/test_ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,55 +45,72 @@ def test_ingest_missing_api_key(test_client: TestClient, db_cleanup):
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_ingest_unauthorized(test_client: TestClient, db_cleanup):
def test_ingest_unauthorized(test_client, authz_headers_bad, db_cleanup):
response = _ingest_rcm_file(
test_client,
file_path=RCM_FILE_PATH,
headers={"x-api-key": "THIS KEY IS INVALID"},
headers=authz_headers_bad,
**INGEST_ARGS,
)
assert response.status_code == status.HTTP_403_FORBIDDEN


def test_ingest_authorized(test_client: TestClient, db_cleanup):
api_key = config.model_extra.get("api_key")
def test_ingest_authorized(test_client, authz_headers, db_cleanup):
response = _ingest_rcm_file(
test_client,
file_path=RCM_FILE_PATH,
headers={"x-api-key": api_key},
headers=authz_headers,
**INGEST_ARGS,
)
assert response.status_code == status.HTTP_200_OK


def test_ingest_authorized_duplicate(test_client: TestClient, db_cleanup):
api_key = config.model_extra.get("api_key")
def test_ingest_authorized_duplicate(test_client, authz_headers, db_cleanup):
response = _ingest_rcm_file(
test_client,
file_path=f"{TEST_FILES_DIR}/rcm_file_duplicates.csv",
headers={"x-api-key": api_key},
headers=authz_headers,
**INGEST_ARGS,
)
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_ingest_parser_error(test_client: TestClient, db_cleanup):
api_key = config.model_extra.get("api_key")
def test_ingest_parser_error(test_client, authz_headers, db_cleanup):
response = _ingest_rcm_file(
test_client,
file_path=f"{TEST_FILES_DIR}/rcm_file_bad_values.csv",
headers={"x-api-key": api_key},
headers=authz_headers,
**INGEST_ARGS,
)
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_ingest_invalid_csv(test_client: TestClient, db_cleanup):
api_key = config.model_extra.get("api_key")
def test_ingest_invalid_csv(test_client, authz_headers, db_cleanup):
response = _ingest_rcm_file(
test_client,
file_path=f"{TEST_FILES_DIR}/rcm_file_bad_column.csv",
headers={"x-api-key": api_key},
headers=authz_headers,
**INGEST_ARGS,
)
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_normalize_400(test_client: TestClient, db_cleanup):
response = test_client.post("/normalize/some-id")
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_normalize_403(test_client: TestClient, authz_headers_bad, db_cleanup):
response = test_client.post("/normalize/some-id", headers=authz_headers_bad)
assert response.status_code == status.HTTP_403_FORBIDDEN


def test_normalize_200(test_client: TestClient, authz_headers, db_cleanup):
# TODO real tests in normalization PR
with open(f"{TEST_FILES_DIR}/gene_lengths.csv", "rb") as file:
response = test_client.post(
url="/normalize/some-id",
files=[("features_lengths_file", file)],
headers=authz_headers,
)
assert response.status_code == status.HTTP_200_OK
10 changes: 0 additions & 10 deletions transcriptomics_data_service/authz/exceptions.py

This file was deleted.

5 changes: 2 additions & 3 deletions transcriptomics_data_service/authz/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

__all__ = ["authz_plugin"]


def import_module_from_path(path, config) -> None | ModuleType:
if config.bento_authz_enabled:
spec = importlib.util.spec_from_file_location("authz_plugin", path)
Expand All @@ -17,6 +18,4 @@ def import_module_from_path(path, config) -> None | ModuleType:


# Get the concrete authz middleware from the provided plugin module
authz_plugin: BaseAuthzMiddleware = import_module_from_path(
"./lib/authz.module.py", get_config()
)
authz_plugin: BaseAuthzMiddleware = import_module_from_path("./lib/authz.module.py", get_config())

0 comments on commit 323f32a

Please sign in to comment.