Skip to content

Commit

Permalink
Fix SodarAPI implementation & add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicolai-vKuegelgen committed Jan 30, 2025
1 parent 76a5c4f commit 23dd84e
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/cubi_tk/sodar_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def _api_call(
# afterward remove the final trailing slash from the joined URL
base_url_parts = [
part if part.endswith("/") else f"{part}/"
for part in (self.sodar_url, "project", self.project_uuid, api, action)
for part in (self.sodar_url, api, "api", action, self.project_uuid)
]
url = reduce(urlparse.urljoin, base_url_parts)[:-1]
if params:
Expand Down
11 changes: 11 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ def germline_trio_sheet_object(germline_trio_sheet_tsv):
sheet=read_germline_tsv_sheet(germline_sheet_io, naming_scheme=NAMING_ONLY_SECONDARY_ID)
)

@pytest.fixture
def mock_toml_config():
return textwrap.dedent(
"""
[global]
sodar_server_url = "https://sodar.bihealth.org/"
sodar_api_token = "token123"
"""
).lstrip()



def my_exists(self):
"""Method is used to patch pathlib.Path.exists"""
Expand Down
114 changes: 114 additions & 0 deletions tests/test_sodar_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import os
import pytest
from unittest.mock import patch, MagicMock

from cubi_tk import sodar_api
from cubi_tk.common import GLOBAL_CONFIG_PATHS
from cubi_tk.exceptions import ParameterException, SodarAPIException


@pytest.fixture
def sodar_api_args():
return {
"sodar_url": "https://sodar.bihealth.org/",
"sodar_api_token": "token123",
"project_uuid": "123e4567-e89b-12d3-a456-426655440000",
}

@pytest.fixture
def sodar_api_instance(sodar_api_args):
return sodar_api.SodarAPI(**sodar_api_args)

def test_sodar_api_check_args(sodar_api_args, mock_toml_config, fs):
# Check args is automatically called in __init__, so we only need to create instances for testing
args = sodar_api_args.copy()

# Successful baseline creation
sodar_api.SodarAPI(**sodar_api_args)

# No toml config available, fail if any value is not given, or malformed
args["sodar_url"] = ""
with pytest.raises(ParameterException):
sodar_api.SodarAPI(**args)
args["sodar_url"] = "https://sodar.bihealth.org/"
args["sodar_api_token"] = ""
with pytest.raises(ParameterException):
sodar_api.SodarAPI(**args)
args["sodar_api_token"] = "token"
args["project_uuid"] = "not a uuid"
with pytest.raises(ParameterException):
sodar_api.SodarAPI(**args)

# With toml config available, only project_uuid is required
fs.create_file(os.path.expanduser(GLOBAL_CONFIG_PATHS[0]), contents=mock_toml_config)
sodar_api.SodarAPI(sodar_url='', sodar_api_token='', project_uuid='123e4567-e89b-12d3-a456-426655440000')


@patch("cubi_tk.sodar_api.requests.get")
@patch("cubi_tk.sodar_api.requests.post")
def test_sodar_api_api_call(mock_post, mock_get, sodar_api_instance):

mock_get.return_value.status_code = 200
mock_get.return_value.json = MagicMock(return_value={"test": "test"})

# Test simple request
out = sodar_api_instance._api_call("samplesheet", "test")
mock_get.assert_called_with(
"https://sodar.bihealth.org/samplesheet/api/test/123e4567-e89b-12d3-a456-426655440000",
headers={"Authorization": "token token123"},
)
assert out == {"test": "test"}

# Test request with params
#FIXME: also test proper URL encoding of params?
out = sodar_api_instance._api_call("samplesheet", "test", params={'test': 'test'})
mock_get.assert_called_with(
"https://sodar.bihealth.org/samplesheet/api/test/123e4567-e89b-12d3-a456-426655440000?test=test",
headers={"Authorization": "token token123"},
)

# Test request with error
mock_get.return_value.status_code = 123
with pytest.raises(SodarAPIException):
out = sodar_api_instance._api_call("samplesheet", "test/action")

# Test post request with extra data
mock_post.return_value.status_code = 200
out = sodar_api_instance._api_call(
"landingzones", "fake/upload", method="post", data={'test': 'test2'}
)
mock_post.assert_called_once_with(
"https://sodar.bihealth.org/landingzones/api/fake/upload/123e4567-e89b-12d3-a456-426655440000",
headers={"Authorization": "token token123"},
files=None, data={'test': 'test2'}
)


@patch("cubi_tk.sodar_api.SodarAPI._api_call")
def test_sodar_api_get_ISA_samplesheet(mock_api_call, sodar_api_instance):

mock_api_call.return_value = {
"investigation": {"path": "i_Investigation.txt", "tsv": ""},
"studies": {"s_Study_0.txt": {"tsv": ""}},
"assays": {"a_name_0": {"tsv": ""}},
'date_modified': '2021-09-01T12:00:00Z',
}
expected = {
"investigation": {"filename": "i_Investigation.txt", "content": ""},
"study": {"filename": "s_Study_0.txt", "content": ""},
"assay": {"filename": "a_name_0", "content": ""},
}
assert expected == sodar_api_instance.get_ISA_samplesheet()


mock_api_call.return_value = {
"investigation": {"path": "i_Investigation.txt", "tsv": ""},
"studies": {"s_Study_0.txt": {"tsv": ""}, "s_Study_1.txt": {"tsv": ""}},
"assays": {"a_name_0": {"tsv": ""}, "a_name_1": {"tsv": ""}},
'date_modified': '2021-09-01T12:00:00Z',
}
with pytest.raises(NotImplementedError):
sodar_api_instance.get_ISA_samplesheet()



0 comments on commit 23dd84e

Please sign in to comment.