-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from TheJacksonLaboratory/G3-9-get-geneset-by-i…
…d-endpoint G3 9 get geneset by id endpoint
- Loading branch information
Showing
12 changed files
with
1,175 additions
and
811 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
"""Constants key/value messages.""" | ||
|
||
|
||
##Errors | ||
ACCESS_FORBIDEN = "Forbidden" | ||
UNEXPECTED_ERROR = "Unexpected Error" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,36 @@ | ||
"""Service functions for dealing with genesets.""" | ||
|
||
from fastapi.logger import logger | ||
from geneweaver.api.controller import message | ||
from geneweaver.api.schemas.auth import User | ||
from geneweaver.db import geneset as db_geneset | ||
from geneweaver.db import geneset_value as db_geneset_value | ||
from geneweaver.db.geneset import is_readable as db_is_readable | ||
from psycopg import Cursor | ||
|
||
|
||
def get_geneset(cursor: Cursor, geneset_id: int, user: User) -> dict: | ||
"""Get a geneset by ID.""" | ||
try: | ||
if not is_geneset_readable_by_user(cursor, geneset_id, user): | ||
return {"error": True, "message": message.ACCESS_FORBIDEN} | ||
|
||
geneset = db_geneset.by_id(cursor, geneset_id) | ||
geneset_values = db_geneset_value.by_geneset_id(cursor, geneset_id) | ||
return {"geneset": geneset, "geneset_values": geneset_values} | ||
|
||
except Exception as err: | ||
logger.error(err) | ||
raise err | ||
|
||
|
||
def is_geneset_readable_by_user(cursor: Cursor, geneset_id: int, user: User) -> bool: | ||
"""Check if the user can read the geneset from DB.""" | ||
readable: bool = False | ||
try: | ||
readable = db_is_readable(cursor, user.id, geneset_id) | ||
except Exception as err: | ||
logger.error(err) | ||
raise err | ||
|
||
return readable |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""Tests for controllers.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
"""Fixtures for the controller tests.""" | ||
import importlib.resources | ||
import json | ||
from unittest.mock import Mock | ||
|
||
import psycopg | ||
import pytest | ||
from fastapi.testclient import TestClient | ||
from geneweaver.api.core.config_class import GeneweaverAPIConfig | ||
|
||
# Load test data | ||
# Opening JSON file | ||
str_json = importlib.resources.read_text("tests.data", "response_geneset_1234.json") | ||
# returns JSON string as a dictionary | ||
test_data = json.loads(str_json) | ||
|
||
response_mock = Mock() | ||
response_mock.status_code = 200 | ||
response_mock.json.return_value = test_data | ||
|
||
|
||
# Mock dependencies | ||
def mock_full_user() -> Mock: | ||
"""User auth mock.""" | ||
m1 = Mock() | ||
return m1.AsyncMock() | ||
|
||
|
||
def mock_cursor() -> psycopg.Cursor: | ||
"""DB cursor mock.""" | ||
m2 = Mock() | ||
return m2.AsyncMock() | ||
|
||
|
||
@pytest.fixture() | ||
def mock_settings(monkeypatch) -> GeneweaverAPIConfig: | ||
"""Patch the settings class to return a test settings instance. | ||
returns: A patched settings instance. | ||
""" | ||
test_settings = GeneweaverAPIConfig( | ||
DB_HOST="localhost", | ||
DB_USERNAME="postgres", | ||
DB_PASSWORD="postgres", | ||
DB_NAME="geneweaver", | ||
) | ||
|
||
monkeypatch.setattr( | ||
"geneweaver.api.core.config_class.GeneweaverAPIConfig", lambda: test_settings | ||
) | ||
|
||
return test_settings | ||
|
||
|
||
@pytest.fixture() | ||
def client(mock_settings) -> TestClient: | ||
"""Provide a mocked FastAPI application. | ||
returns: A mocked FastAPI application. | ||
""" | ||
from geneweaver.api.dependencies import cursor, full_user | ||
from geneweaver.api.main import app | ||
|
||
test_app = TestClient(app) | ||
|
||
app.dependency_overrides.update({full_user: mock_full_user, cursor: mock_cursor}) | ||
|
||
return test_app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
"""Tests for geneset API.""" | ||
from unittest.mock import patch | ||
|
||
import pytest | ||
|
||
from tests.controllers.conftest import test_data | ||
|
||
|
||
@patch("geneweaver.api.services.geneset.get_geneset") | ||
@patch("geneweaver.api.services.geneset.is_geneset_readable_by_user") | ||
def test_get_geneset_response(mock_genset_is_readable, mock_get_genenset, client): | ||
"""Test get geneset ID data response.""" | ||
mock_genset_is_readable.return_value = True | ||
mock_get_genenset.return_value = test_data | ||
|
||
response = client.get("/api/genesets/1234") | ||
assert response.status_code == 200 | ||
assert response.json() == test_data | ||
|
||
|
||
@patch("geneweaver.api.services.geneset.db_is_readable") | ||
def test_get_geneset_forbidden(mock_genset_is_readable, client): | ||
"""Test forbidden response.""" | ||
mock_genset_is_readable.return_value = False | ||
response = client.get("/api/genesets/1234") | ||
|
||
assert response.json() == {"detail": "Forbidden"} | ||
assert response.status_code == 403 | ||
|
||
|
||
@patch("geneweaver.api.services.geneset.db_is_readable") | ||
def test_get_geneset_unexpected_error(mock_genset_is_readable, client): | ||
"""Test unexpected error response.""" | ||
mock_genset_is_readable.side_effect = Exception | ||
|
||
with pytest.raises(expected_exception=Exception): | ||
client.get("/api/genesets/1234") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""Data package for tests.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
{ | ||
"geneset": null, | ||
"geneset_values": [ | ||
{ | ||
"gs_id": 1234, | ||
"ode_gene_id": 70495, | ||
"gsv_value": 1, | ||
"gsv_hits": 1, | ||
"gsv_source_list": [ | ||
"PDE4DIP" | ||
], | ||
"gsv_value_list": [ | ||
1 | ||
], | ||
"gsv_in_threshold": true, | ||
"gsv_date": "2020-05-05", | ||
"ode_ref_id": "PDE4DIP" | ||
}, | ||
{ | ||
"gs_id": 1234, | ||
"ode_gene_id": 83819, | ||
"gsv_value": 1, | ||
"gsv_hits": 1, | ||
"gsv_source_list": [ | ||
"TMEPAI" | ||
], | ||
"gsv_value_list": [ | ||
1 | ||
], | ||
"gsv_in_threshold": true, | ||
"gsv_date": "2020-05-05", | ||
"ode_ref_id": "PMEPA1" | ||
}, | ||
{ | ||
"gs_id": 1234, | ||
"ode_gene_id": 90284, | ||
"gsv_value": 1, | ||
"gsv_hits": 1, | ||
"gsv_source_list": [ | ||
"PREPL" | ||
], | ||
"gsv_value_list": [ | ||
1 | ||
], | ||
"gsv_in_threshold": true, | ||
"gsv_date": "2020-05-05", | ||
"ode_ref_id": "PREPL" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
"""Tests for geneset Service.""" | ||
|
||
import importlib.resources | ||
import json | ||
from unittest.mock import patch | ||
|
||
import pytest | ||
from geneweaver.api.controller import message | ||
from geneweaver.api.services import geneset | ||
|
||
## Load test data | ||
# Opening JSON file | ||
str_json = importlib.resources.read_text("tests.data", "response_geneset_1234.json") | ||
# returns JSON string as a dictionary | ||
test_data = json.loads(str_json) | ||
|
||
|
||
@patch("geneweaver.api.services.geneset.db_geneset") | ||
@patch("geneweaver.api.services.geneset.db_geneset_value") | ||
@patch("geneweaver.api.services.geneset.is_geneset_readable_by_user") | ||
def test_get_geneset(mock_genset_readable_func, mock_db_geneset, mock_db_genset_value): | ||
"""Test basic get geneset by ID.""" | ||
mock_genset_readable_func.return_value = True | ||
mock_db_geneset.by_id.return_value = {} | ||
mock_db_genset_value.by_id.return_value = {} | ||
response = geneset.get_geneset(None, 1234, None) | ||
assert response.get("error") is None | ||
|
||
|
||
@patch("geneweaver.api.services.geneset.is_geneset_readable_by_user") | ||
def test_get_geneset_no_user_access(mock_genset_readable_func): | ||
"""Test get geneset by ID with no user access.""" | ||
mock_genset_readable_func.return_value = False | ||
response = geneset.get_geneset(None, 1234, None) | ||
assert response.get("error") is True | ||
assert response.get("message") == message.ACCESS_FORBIDEN | ||
|
||
|
||
@patch("geneweaver.api.services.geneset.db_geneset") | ||
@patch("geneweaver.api.services.geneset.db_geneset_value") | ||
@patch("geneweaver.api.services.geneset.is_geneset_readable_by_user") | ||
def test_get_geneset_returned_values( | ||
mock_genset_readable_func, mock_db_genset_value, mock_db_geneset | ||
): | ||
"""Test get geneset by ID data response structure.""" | ||
mock_genset_readable_func.return_value = True | ||
mock_db_geneset.by_id.return_value = test_data.get("geneset") | ||
mock_db_genset_value.by_geneset_id.return_value = test_data.get("geneset_values") | ||
response = geneset.get_geneset(None, 1234, None) | ||
|
||
assert response.get("genset") == test_data["geneset"] | ||
assert response.get("geneset_values") == test_data["geneset_values"] | ||
|
||
|
||
@patch("geneweaver.api.services.geneset.db_is_readable") | ||
@patch("geneweaver.api.services.geneset.User") | ||
def test_is_redable_by_user(mock_user, mock_genset_is_readable): | ||
"""Test is geneset ID readable by passed user.""" | ||
mock_genset_is_readable.return_value = True | ||
response = geneset.is_geneset_readable_by_user(None, 1234, mock_user) | ||
assert response is True | ||
|
||
|
||
@patch("geneweaver.db.geneset.is_readable") | ||
@patch("geneweaver.api.services.geneset.User") | ||
def test_is_redable_by_user_error(mock_user, mock_genset_is_readable): | ||
"""Test is geneset ID readable with server error.""" | ||
mock_genset_is_readable.sideEffect = Exception | ||
|
||
with pytest.raises(expected_exception=Exception): | ||
geneset.is_geneset_readable_by_user(None, 1234, mock_user) |