Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rpm/quads-lib.spec
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
%define name quads-lib
%define reponame python-quads-lib
%define branch development
%define version 0.1.13
%define version 0.1.14
%define build_timestamp %{lua: print(os.date("%Y%m%d"))}

Summary: Python client library for interacting with the QUADS API
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def read(*names, **kwargs):

setup(
name="quads-lib",
version="0.1.13",
version="0.1.14",
license="LGPL-3.0-only",
description="Python client library for interacting with the QUADS API",
long_description="{}\n{}".format(
Expand Down
2 changes: 1 addition & 1 deletion src/quads_lib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.1.13"
__version__ = "0.1.14"

from .quads import QuadsApi

Expand Down
4 changes: 2 additions & 2 deletions src/quads_lib/quads.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def login(self) -> dict:
self.session.headers.update({"Authorization": f"Bearer {self.token}"})
return json_response

def get_current_user(self) -> dict:
return self.get("me")
def get_user(self, email: str) -> dict:
return self.get(f"users/{email}")

def logout(self) -> dict:
json_response = self._make_request("POST", "logout")
Expand Down
60 changes: 60 additions & 0 deletions tests/test_quads.py
Original file line number Diff line number Diff line change
Expand Up @@ -2067,6 +2067,66 @@ def test_create_self_assignment_limit_reached(self, mock_request, mock_print):
assert result == error_response


class TestApiTokenAuth:
"""Tests for qat_ API token authentication"""

def test_init_with_api_token(self):
"""Test that api_token sets Bearer header and skips BasicAuth"""
api = QuadsApi("", "", "http://example.com/", api_token="qat_test123")
assert api.token == "qat_test123"
assert api.auth is None
assert api.session.headers.get("Authorization") == "Bearer qat_test123"

def test_init_without_api_token(self):
"""Test that without api_token, BasicAuth is set"""
api = QuadsApi("user", "pass", "http://example.com/")
assert api.token is None
assert api.auth is not None

def test_login_noop_with_qat_token(self):
"""Test that login() returns synthetic success for qat_ tokens"""
api = QuadsApi("", "", "http://example.com/", api_token="qat_abc123")
result = api.login()
assert result["status_code"] == 201
assert result["status"] == "success"
assert result["auth_token"] == "qat_abc123"

def test_login_noop_does_not_make_request(self):
"""Test that login() with qat_ token makes no HTTP request"""
api = QuadsApi("", "", "http://example.com/", api_token="qat_abc123")
api.session.post = Mock(side_effect=AssertionError("should not be called"))
result = api.login()
assert result["status"] == "success"

@patch("requests.Session.request")
def test_get_user(self, mock_request):
"""Test get_user calls /users/{email}"""
api = QuadsApi("user", "pass", "http://example.com/")
expected = {"email": "bob@example.com", "roles": ["user"]}
mock_response = Mock()
mock_response.json.return_value = expected
mock_request.return_value = mock_response

result = api.get_user("bob@example.com")

mock_request.assert_called_once()
assert str(mock_request.call_args[0][1]).endswith("/users/bob@example.com")
assert result == expected

@patch("requests.Session.request")
def test_get_user_with_api_token(self, mock_request):
"""Test get_user works with api_token auth"""
api = QuadsApi("", "", "http://example.com/", api_token="qat_test")
expected = {"email": "admin@example.com", "roles": ["admin"]}
mock_response = Mock()
mock_response.json.return_value = expected
mock_request.return_value = mock_response

result = api.get_user("admin@example.com")

assert result == expected


class TestQuadsBase:
@pytest.fixture(autouse=True)
def setup(self):
Expand Down
Loading