Skip to content

Commit 8fe3511

Browse files
committed
add more tests
1 parent e4db8f8 commit 8fe3511

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ flexo-setup/docker-compose/env/*.env
2525
/build
2626
/src/sysmlv2_python_client.egg-info
2727
/test-results
28+
coverage.xml

tests/test_client.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import json
2+
13
import pytest
24
import requests_mock
35
import requests
@@ -93,6 +95,14 @@ def test_get_projects_success_no_elements_key(client, requests_mock):
9395

9496
assert projects == mock_response_data
9597

98+
def test_get_projects_success_unexpected_scalar_response(client, monkeypatch):
99+
"""Tests retrieving projects when the API returns a scalar value."""
100+
monkeypatch.setattr(client, "_request", lambda **kwargs: "unexpected")
101+
102+
projects = client.get_projects()
103+
104+
assert projects == []
105+
96106
def test_get_projects_auth_error(client, requests_mock):
97107
"""Tests authentication error during get_projects."""
98108
mock_url = f"{TEST_BASE_URL}/projects"
@@ -165,6 +175,17 @@ def test_create_project_api_error(client, requests_mock):
165175
with pytest.raises(SysMLV2APIError, match="Unexpected status code for POST /projects"):
166176
client.create_project(request_data)
167177

178+
def test_delete_project_success(client, requests_mock):
179+
"""Tests successfully deleting a project."""
180+
mock_url = f"{TEST_BASE_URL}/projects/{TEST_PROJECT_ID}"
181+
requests_mock.delete(mock_url, json={}, status_code=200)
182+
183+
result = client.delete_project(TEST_PROJECT_ID)
184+
185+
assert result == {}
186+
assert requests_mock.last_request.url == mock_url
187+
assert requests_mock.last_request.method == "DELETE"
188+
168189

169190
# --- Test Get Element ---
170191

@@ -229,6 +250,24 @@ def test_get_owned_elements_empty(client, requests_mock):
229250

230251
assert owned_elements == []
231252

253+
def test_get_owned_elements_success_list_response(client, requests_mock):
254+
"""Tests retrieving owned elements when the API returns a bare list."""
255+
mock_url = f"{TEST_BASE_URL}/projects/{TEST_PROJECT_ID}/commits/{TEST_COMMIT_ID}/elements/{TEST_ELEMENT_ID}/owned"
256+
mock_response_data = [{"id": "owned_elem_1"}]
257+
requests_mock.get(mock_url, json=mock_response_data, status_code=200)
258+
259+
owned_elements = client.get_owned_elements(TEST_PROJECT_ID, TEST_ELEMENT_ID, TEST_COMMIT_ID)
260+
261+
assert owned_elements == mock_response_data
262+
263+
def test_get_owned_elements_success_unexpected_scalar_response(client, monkeypatch):
264+
"""Tests retrieving owned elements when the API returns a scalar value."""
265+
monkeypatch.setattr(client, "_request", lambda **kwargs: "unexpected")
266+
267+
owned_elements = client.get_owned_elements(TEST_PROJECT_ID, TEST_ELEMENT_ID, TEST_COMMIT_ID)
268+
269+
assert owned_elements == []
270+
232271
# --- Test Create Commit ---
233272

234273
def test_create_commit_success(client, requests_mock):
@@ -378,6 +417,14 @@ def test_list_commits_success_dict_response(client, requests_mock):
378417

379418
assert commits == mock_response_data["elements"]
380419

420+
def test_list_commits_success_unexpected_scalar_response(client, monkeypatch):
421+
"""Tests listing commits when the API returns a scalar value."""
422+
monkeypatch.setattr(client, "_request", lambda **kwargs: "unexpected")
423+
424+
commits = client.list_commits(TEST_PROJECT_ID)
425+
426+
assert commits == []
427+
381428
def test_list_commits_project_not_found(client, requests_mock):
382429
"""Tests 404 when listing commits for a non-existent project."""
383430
mock_url = f"{TEST_BASE_URL}/projects/invalid_project/commits"
@@ -398,6 +445,18 @@ def test_list_branches_success(client, requests_mock):
398445
branches = client.list_branches(TEST_PROJECT_ID)
399446
assert branches == mock_response
400447

448+
def test_list_branches_success_dict_response(client, requests_mock):
449+
mock_url = f"{TEST_BASE_URL}/projects/{TEST_PROJECT_ID}/branches"
450+
mock_response = {"elements": [{"id": TEST_BRANCH_ID, "name": "develop"}]}
451+
requests_mock.get(mock_url, json=mock_response, status_code=200)
452+
branches = client.list_branches(TEST_PROJECT_ID)
453+
assert branches == mock_response["elements"]
454+
455+
def test_list_branches_success_unexpected_scalar_response(client, monkeypatch):
456+
monkeypatch.setattr(client, "_request", lambda **kwargs: "unexpected")
457+
branches = client.list_branches(TEST_PROJECT_ID)
458+
assert branches == []
459+
401460
def test_create_branch_success(client, requests_mock):
402461
mock_url = f"{TEST_BASE_URL}/projects/{TEST_PROJECT_ID}/branches"
403462
request_data = {"name": "feature-branch", "head": {"@id": TEST_COMMIT_ID}}
@@ -438,6 +497,18 @@ def test_list_tags_success(client, requests_mock):
438497
tags = client.list_tags(TEST_PROJECT_ID)
439498
assert tags == mock_response
440499

500+
def test_list_tags_success_dict_response(client, requests_mock):
501+
mock_url = f"{TEST_BASE_URL}/projects/{TEST_PROJECT_ID}/tags"
502+
mock_response = {"elements": [{"id": TEST_TAG_ID, "name": "v1.0"}]}
503+
requests_mock.get(mock_url, json=mock_response, status_code=200)
504+
tags = client.list_tags(TEST_PROJECT_ID)
505+
assert tags == mock_response["elements"]
506+
507+
def test_list_tags_success_unexpected_scalar_response(client, monkeypatch):
508+
monkeypatch.setattr(client, "_request", lambda **kwargs: "unexpected")
509+
tags = client.list_tags(TEST_PROJECT_ID)
510+
assert tags == []
511+
441512
def test_create_tag_success(client, requests_mock):
442513
mock_url = f"{TEST_BASE_URL}/projects/{TEST_PROJECT_ID}/tags"
443514
request_data = {"name": "v1.0-release", "taggedCommit": {"@id": TEST_COMMIT_ID}}
@@ -484,6 +555,20 @@ def test_list_elements_commit_not_found(client, requests_mock):
484555
with pytest.raises(SysMLV2NotFoundError):
485556
client.list_elements(TEST_PROJECT_ID, "invalid_commit")
486557

558+
def test_list_elements_success_dict_response(client, requests_mock):
559+
"""Tests listing elements when the API returns a dict with 'elements'."""
560+
mock_url = f"{TEST_BASE_URL}/projects/{TEST_PROJECT_ID}/commits/{TEST_COMMIT_ID}/elements"
561+
mock_response_data = {"elements": [{"id": "elem1"}, {"id": "elem2"}]}
562+
requests_mock.get(mock_url, json=mock_response_data, status_code=200)
563+
elements = client.list_elements(TEST_PROJECT_ID, TEST_COMMIT_ID)
564+
assert elements == mock_response_data["elements"]
565+
566+
def test_list_elements_success_unexpected_scalar_response(client, monkeypatch):
567+
"""Tests listing elements when the API returns a scalar value."""
568+
monkeypatch.setattr(client, "_request", lambda **kwargs: "unexpected")
569+
elements = client.list_elements(TEST_PROJECT_ID, TEST_COMMIT_ID)
570+
assert elements == []
571+
487572

488573
# --- Test List Relationships ---
489574

@@ -510,3 +595,62 @@ def test_list_relationships_element_not_found(client, requests_mock):
510595
requests_mock.get(mock_url, status_code=404)
511596
with pytest.raises(SysMLV2NotFoundError):
512597
client.list_relationships(TEST_PROJECT_ID, "invalid_element", TEST_COMMIT_ID)
598+
599+
def test_list_relationships_success_dict_response(client, requests_mock):
600+
"""Tests listing relationships when the API returns a dict with 'elements'."""
601+
mock_url = f"{TEST_BASE_URL}/projects/{TEST_PROJECT_ID}/commits/{TEST_COMMIT_ID}/elements/{TEST_ELEMENT_ID}/relationships?direction=both"
602+
mock_response_data = {"elements": [{"id": "rel1"}]}
603+
requests_mock.get(mock_url, json=mock_response_data, status_code=200)
604+
relationships = client.list_relationships(TEST_PROJECT_ID, TEST_ELEMENT_ID, TEST_COMMIT_ID)
605+
assert relationships == mock_response_data["elements"]
606+
607+
def test_list_relationships_success_unexpected_scalar_response(client, monkeypatch):
608+
"""Tests listing relationships when the API returns a scalar value."""
609+
monkeypatch.setattr(client, "_request", lambda **kwargs: "unexpected")
610+
relationships = client.list_relationships(TEST_PROJECT_ID, TEST_ELEMENT_ID, TEST_COMMIT_ID)
611+
assert relationships == []
612+
613+
614+
# --- Test _request Edge Cases ---
615+
616+
def test_request_bad_request_uses_text_when_json_decode_fails(client, monkeypatch):
617+
"""Tests 400 handling falls back to response text when JSON decoding fails."""
618+
619+
class FakeResponse:
620+
status_code = 400
621+
text = "plain error text"
622+
content = b"plain error text"
623+
624+
def json(self):
625+
raise json.JSONDecodeError("Expecting value", "plain error text", 0)
626+
627+
monkeypatch.setattr(client._session, "request", lambda **kwargs: FakeResponse())
628+
629+
with pytest.raises(SysMLV2BadRequestError, match="plain error text"):
630+
client._request(method="GET", endpoint="/projects")
631+
632+
def test_request_network_error_wrapped(client, monkeypatch):
633+
"""Tests request-layer network exceptions are wrapped in SysMLV2Error."""
634+
def raise_request_exception(**kwargs):
635+
raise requests.exceptions.ConnectionError("connection dropped")
636+
637+
monkeypatch.setattr(client._session, "request", raise_request_exception)
638+
639+
with pytest.raises(SysMLV2Error, match="Network error during request"):
640+
client._request(method="GET", endpoint="/projects")
641+
642+
def test_request_success_json_decode_error_wrapped(client, monkeypatch):
643+
"""Tests invalid JSON on a successful response is wrapped in SysMLV2Error."""
644+
645+
class FakeResponse:
646+
status_code = 200
647+
text = "not json"
648+
content = b"not json"
649+
650+
def json(self):
651+
raise json.JSONDecodeError("Expecting value", "not json", 0)
652+
653+
monkeypatch.setattr(client._session, "request", lambda **kwargs: FakeResponse())
654+
655+
with pytest.raises(SysMLV2Error, match="Failed to decode JSON response"):
656+
client._request(method="GET", endpoint="/projects")

0 commit comments

Comments
 (0)