From 46b22d552588b046c6d73c662f88af133ca6965d Mon Sep 17 00:00:00 2001 From: mshriver Date: Mon, 24 Nov 2025 13:41:13 -0500 Subject: [PATCH 1/3] Rework test coverage for api modules --- test/conftest.py | 467 +++++++++++++++++++++++++ test/test_admin_user_management_api.py | 262 ++++++++++++-- test/test_group_api.py | 240 ++++++++++--- test/test_import_api.py | 206 ++++++++++- test/test_login_api.py | 322 +++++++++++++++-- test/test_task_api.py | 178 +++++++++- test/test_user_api.py | 292 +++++++++++++--- test/test_widget_api.py | 182 +++++++++- test/test_widget_config_api.py | 265 ++++++++++++-- 9 files changed, 2194 insertions(+), 220 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 439732b..136ebd0 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,6 +1,7 @@ """Test configuration and fixtures for ibutsu_client tests.""" import json +import uuid from typing import Any from unittest.mock import Mock @@ -68,3 +69,469 @@ def mock_getheaders() -> dict[str, str]: def mock_rest_response(): """Fixture that provides the create_mock_response function.""" return create_mock_response + + +# ==================== Test Data Factories ==================== + + +@pytest.fixture +def sample_project_data(): + """Factory function to create sample project data. + + Returns: + A function that creates project data dictionaries with realistic values. + """ + + def _create_project( + project_id: str | None = None, + name: str = "test-project", + title: str = "Test Project", + owner_id: str | None = None, + group_id: str | None = None, + ) -> dict[str, Any]: + """Create a sample project data dictionary. + + Args: + project_id: Project UUID (generated if not provided) + name: Machine name of the project + title: Human-readable title + owner_id: Owner UUID + group_id: Group UUID + + Returns: + Dictionary with project data + """ + if project_id is None: + project_id = str(uuid.uuid4()) + if owner_id is None: + owner_id = str(uuid.uuid4()) + if group_id is None: + group_id = str(uuid.uuid4()) + + return { + "id": project_id, + "name": name, + "title": title, + "owner_id": owner_id, + "group_id": group_id, + } + + return _create_project + + +@pytest.fixture +def sample_run_data(): + """Factory function to create sample test run data. + + Returns: + A function that creates run data dictionaries with realistic values. + """ + + def _create_run( + run_id: str | None = None, + project_id: str | None = None, + created: str = "2024-01-15T10:00:00", + start_time: str = "2024-01-15T10:00:00", + duration: float = 120.5, + source: str = "pytest", + component: str = "api", + env: str = "test", + summary: dict[str, Any] | None = None, + metadata: dict[str, Any] | None = None, + ) -> dict[str, Any]: + """Create a sample run data dictionary. + + Args: + run_id: Run UUID (generated if not provided) + project_id: Project UUID (generated if not provided) + created: ISO timestamp of creation + start_time: ISO timestamp of run start + duration: Duration in seconds + source: Source system identifier + component: Component under test + env: Test environment + summary: Summary statistics + metadata: Additional metadata + + Returns: + Dictionary with run data + """ + if run_id is None: + run_id = str(uuid.uuid4()) + if project_id is None: + project_id = str(uuid.uuid4()) + if summary is None: + summary = {"passed": 10, "failed": 2, "skipped": 1, "errors": 0, "xfailed": 0} + if metadata is None: + metadata = {"jenkins_build": "123", "branch": "main"} + + return { + "id": run_id, + "project_id": project_id, + "created": created, + "start_time": start_time, + "duration": duration, + "source": source, + "component": component, + "env": env, + "summary": summary, + "metadata": metadata, + } + + return _create_run + + +@pytest.fixture +def sample_result_data(): + """Factory function to create sample test result data. + + Returns: + A function that creates result data dictionaries with realistic values. + """ + + def _create_result( + result_id: str | None = None, + run_id: str | None = None, + project_id: str | None = None, + test_id: str = "test_example.py::TestClass::test_method", + start_time: str = "2024-01-15T10:00:00", + duration: float = 1.5, + result: str = "passed", + component: str = "api", + env: str = "test", + source: str = "pytest", + metadata: dict[str, Any] | None = None, + params: dict[str, Any] | None = None, + ) -> dict[str, Any]: + """Create a sample result data dictionary. + + Args: + result_id: Result UUID (generated if not provided) + run_id: Associated run UUID (generated if not provided) + project_id: Project UUID (generated if not provided) + test_id: Test identifier + start_time: ISO timestamp + duration: Duration in seconds + result: Test result status (passed, failed, error, skipped, etc.) + component: Component under test + env: Test environment + source: Source system identifier + metadata: Additional metadata + params: Test parameters + + Returns: + Dictionary with result data + """ + if result_id is None: + result_id = str(uuid.uuid4()) + if run_id is None: + run_id = str(uuid.uuid4()) + if project_id is None: + project_id = str(uuid.uuid4()) + if metadata is None: + metadata = {"test_file": "test_example.py", "line_number": 42} + if params is None: + params = {} + + return { + "id": result_id, + "run_id": run_id, + "project_id": project_id, + "test_id": test_id, + "start_time": start_time, + "duration": duration, + "result": result, + "component": component, + "env": env, + "source": source, + "metadata": metadata, + "params": params, + } + + return _create_result + + +@pytest.fixture +def sample_artifact_data(): + """Factory function to create sample artifact data. + + Returns: + A function that creates artifact data dictionaries with realistic values. + """ + + def _create_artifact( + artifact_id: str | None = None, + filename: str = "test_log.txt", + result_id: str | None = None, + run_id: str | None = None, + project_id: str | None = None, + ) -> dict[str, Any]: + """Create a sample artifact data dictionary. + + Args: + artifact_id: Artifact UUID (generated if not provided) + filename: Artifact filename + result_id: Associated result UUID + run_id: Associated run UUID + project_id: Project UUID + + Returns: + Dictionary with artifact data + """ + if artifact_id is None: + artifact_id = str(uuid.uuid4()) + if result_id is None: + result_id = str(uuid.uuid4()) + if run_id is None: + run_id = str(uuid.uuid4()) + if project_id is None: + project_id = str(uuid.uuid4()) + + return { + "id": artifact_id, + "filename": filename, + "result_id": result_id, + "run_id": run_id, + "project_id": project_id, + } + + return _create_artifact + + +@pytest.fixture +def sample_pagination_data(): + """Factory function to create sample pagination data. + + Returns: + A function that creates pagination data for list responses. + """ + + def _create_pagination( + page: int = 1, + page_size: int = 25, + total_items: int = 100, + total_pages: int = 4, + ) -> dict[str, Any]: + """Create sample pagination data. + + Args: + page: Current page number + page_size: Number of items per page + total_items: Total number of items + total_pages: Total number of pages + + Returns: + Dictionary with pagination data + """ + return { + "page": page, + "pageSize": page_size, + "totalItems": total_items, + "totalPages": total_pages, + } + + return _create_pagination + + +@pytest.fixture +def sample_user_data(): + """Factory function to create sample user data. + + Returns: + A function that creates user data dictionaries with realistic values. + """ + + def _create_user( + user_id: str | None = None, + email: str = "test@example.com", + name: str = "Test User", + is_superadmin: bool = False, + is_active: bool = True, + ) -> dict[str, Any]: + """Create a sample user data dictionary. + + Args: + user_id: User UUID (generated if not provided) + email: User email address + name: User full name + is_superadmin: Whether user is a superadmin + is_active: Whether user account is active + + Returns: + Dictionary with user data + """ + if user_id is None: + user_id = str(uuid.uuid4()) + + return { + "id": user_id, + "email": email, + "name": name, + "is_superadmin": is_superadmin, + "is_active": is_active, + } + + return _create_user + + +@pytest.fixture +def sample_dashboard_data(): + """Factory function to create sample dashboard data. + + Returns: + A function that creates dashboard data dictionaries with realistic values. + """ + + def _create_dashboard( + dashboard_id: str | None = None, + title: str = "Test Dashboard", + project_id: str | None = None, + widgets: list[dict[str, Any]] | None = None, + ) -> dict[str, Any]: + """Create a sample dashboard data dictionary. + + Args: + dashboard_id: Dashboard UUID (generated if not provided) + title: Dashboard title + project_id: Project UUID (generated if not provided) + widgets: List of widget configurations + + Returns: + Dictionary with dashboard data + """ + if dashboard_id is None: + dashboard_id = str(uuid.uuid4()) + if project_id is None: + project_id = str(uuid.uuid4()) + if widgets is None: + widgets = [] + + return { + "id": dashboard_id, + "title": title, + "project_id": project_id, + "widgets": widgets, + } + + return _create_dashboard + + +@pytest.fixture +def sample_widget_config_data(): + """Factory function to create sample widget configuration data. + + Returns: + A function that creates widget config data dictionaries with realistic values. + """ + + def _create_widget_config( + widget_id: str | None = None, + widget: str = "result-summary", + config_type: str = "widget", + weight: int = 0, + params: dict[str, Any] | None = None, + title: str | None = None, + ) -> dict[str, Any]: + """Create a sample widget config data dictionary. + + Args: + widget_id: Widget UUID (generated if not provided) + widget: Widget name to render + config_type: Type of config ("widget" or "view") + weight: Widget display weight/order + params: Widget parameters + title: Widget title + + Returns: + Dictionary with widget config data + """ + if widget_id is None: + widget_id = str(uuid.uuid4()) + if params is None: + params = {} + + return { + "id": widget_id, + "type": config_type, + "widget": widget, + "weight": weight, + "params": params, + "title": title, + } + + return _create_widget_config + + +@pytest.fixture +def sample_group_data(): + """Factory function to create sample group data. + + Returns: + A function that creates group data dictionaries with realistic values. + """ + + def _create_group( + group_id: str | None = None, + name: str = "test-group", + ) -> dict[str, Any]: + """Create a sample group data dictionary. + + Args: + group_id: Group UUID (generated if not provided) + name: Group name + + Returns: + Dictionary with group data + """ + if group_id is None: + group_id = str(uuid.uuid4()) + + return { + "id": group_id, + "name": name, + } + + return _create_group + + +@pytest.fixture +def sample_token_data(): + """Factory function to create sample token data. + + Returns: + A function that creates token data dictionaries with realistic values. + """ + + def _create_token( + token_id: str | None = None, + user_id: str | None = None, + name: str = "test-token", + token: str = "test-token-value", + expires: str | None = "2025-12-31", + ) -> dict[str, Any]: + """Create a sample token data dictionary. + + Args: + token_id: Token UUID (generated if not provided) + user_id: User UUID (generated if not provided) + name: Token name/identifier + token: The actual token string + expires: Expiration date + + Returns: + Dictionary with token data + """ + if token_id is None: + token_id = str(uuid.uuid4()) + if user_id is None: + user_id = str(uuid.uuid4()) + + return { + "id": token_id, + "user_id": user_id, + "name": name, + "token": token, + "expires": expires, + } + + return _create_token diff --git a/test/test_admin_user_management_api.py b/test/test_admin_user_management_api.py index 6424685..1a7c86f 100644 --- a/test/test_admin_user_management_api.py +++ b/test/test_admin_user_management_api.py @@ -9,50 +9,254 @@ Do not edit the class manually. """ -import unittest +import pytest from ibutsu_client.api.admin_user_management_api import AdminUserManagementApi +from ibutsu_client.exceptions import NotFoundException, ServiceException +from ibutsu_client.models.user import User +from ibutsu_client.models.user_list import UserList +from test.conftest import create_mock_response -class TestAdminUserManagementApi(unittest.TestCase): - """AdminUserManagementApi unit test stubs""" +class TestAdminUserManagementApi: + """AdminUserManagementApi comprehensive tests""" - def setUp(self) -> None: - self.api = AdminUserManagementApi() + def test_admin_add_user_success(self, mocker, sample_user_data): + """Test case for admin_add_user - successfully add a user""" + api = AdminUserManagementApi() + user_data = sample_user_data(email="newuser@example.com", name="New User") + mock_response = create_mock_response(user_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def tearDown(self) -> None: - pass + user = User(email="newuser@example.com", name="New User") + result = api.admin_add_user(user=user) - def test_admin_add_user(self) -> None: - """Test case for admin_add_user + assert isinstance(result, User) + assert result.email == "newuser@example.com" + assert result.name == "New User" + api.api_client.call_api.assert_called_once() - Administration endpoint to manually add a user. Only accessible to superadmins. - """ + def test_admin_add_user_unauthorized(self, mocker): + """Test case for admin_add_user without superadmin privileges""" + api = AdminUserManagementApi() + mock_response = create_mock_response({"error": "unauthorized"}, status=403) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def test_admin_delete_user(self) -> None: - """Test case for admin_delete_user + user = User(email="test@example.com", name="Test") + with pytest.raises((ServiceException, Exception)): + api.admin_add_user(user=user) - Administration endpoint to delete a user. Only accessible to superadmins. - """ + def test_admin_add_user_conflict(self, mocker): + """Test case for admin_add_user with existing email""" + api = AdminUserManagementApi() + mock_response = create_mock_response({"error": "user already exists"}, status=409) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def test_admin_get_user(self) -> None: - """Test case for admin_get_user + user = User(email="existing@example.com", name="Existing User") + with pytest.raises((ServiceException, Exception)): + api.admin_add_user(user=user) - Administration endpoint to return a user. Only accessible to superadmins. - """ + def test_admin_add_user_with_http_info(self, mocker, sample_user_data): + """Test case for admin_add_user_with_http_info""" + api = AdminUserManagementApi() + user_data = sample_user_data() + mock_response = create_mock_response(user_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def test_admin_get_user_list(self) -> None: - """Test case for admin_get_user_list + user = User(email="test@example.com", name="Test User") + result = api.admin_add_user_with_http_info(user=user) - Administration endpoint to return a list of users. Only accessible to superadmins. - """ + assert result.status_code == 201 + assert isinstance(result.data, User) - def test_admin_update_user(self) -> None: - """Test case for admin_update_user + def test_admin_delete_user_success(self, mocker): + """Test case for admin_delete_user - successfully delete a user""" + api = AdminUserManagementApi() + mock_response = create_mock_response({}, status=204) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - Administration endpoint to update a user. Only accessible to superadmins. - """ + user_id = "550e8400-e29b-41d4-a716-446655440000" + api.admin_delete_user(id=user_id) + # 204 No Content typically returns None + api.api_client.call_api.assert_called_once() -if __name__ == "__main__": - unittest.main() + def test_admin_delete_user_not_found(self, mocker): + """Test case for admin_delete_user with non-existent user""" + api = AdminUserManagementApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.admin_delete_user(id=user_id) + + def test_admin_delete_user_forbidden(self, mocker): + """Test case for admin_delete_user without superadmin privileges""" + api = AdminUserManagementApi() + mock_response = create_mock_response({"error": "forbidden"}, status=403) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises((ServiceException, Exception)): + api.admin_delete_user(id=user_id) + + def test_admin_delete_user_with_http_info(self, mocker): + """Test case for admin_delete_user_with_http_info""" + api = AdminUserManagementApi() + mock_response = create_mock_response({}, status=204) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.admin_delete_user_with_http_info(id=user_id) + + assert result.status_code == 204 + + def test_admin_get_user_success(self, mocker, sample_user_data): + """Test case for admin_get_user - retrieve a single user""" + api = AdminUserManagementApi() + user_data = sample_user_data(email="admin@example.com", is_superadmin=True) + mock_response = create_mock_response(user_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.admin_get_user(id=user_id) + + assert isinstance(result, User) + assert result.email == "admin@example.com" + assert result.is_superadmin is True + + def test_admin_get_user_not_found(self, mocker): + """Test case for admin_get_user with non-existent user""" + api = AdminUserManagementApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.admin_get_user(id=user_id) + + def test_admin_get_user_with_http_info(self, mocker, sample_user_data): + """Test case for admin_get_user_with_http_info""" + api = AdminUserManagementApi() + user_data = sample_user_data() + mock_response = create_mock_response(user_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.admin_get_user_with_http_info(id=user_id) + + assert result.status_code == 200 + assert isinstance(result.data, User) + + def test_admin_get_user_list_success(self, mocker, sample_user_data, sample_pagination_data): + """Test case for admin_get_user_list - retrieve list of users""" + api = AdminUserManagementApi() + user1 = sample_user_data(email="user1@example.com", name="User One") + user2 = sample_user_data(email="user2@example.com", name="User Two") + pagination = sample_pagination_data(total_items=2) + + response_data = {"users": [user1, user2], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.admin_get_user_list() + + assert isinstance(result, UserList) + assert len(result.users) == 2 + + def test_admin_get_user_list_with_pagination( + self, mocker, sample_user_data, sample_pagination_data + ): + """Test case for admin_get_user_list with pagination parameters""" + api = AdminUserManagementApi() + user1 = sample_user_data() + pagination = sample_pagination_data(page=2, page_size=10, total_items=15) + + response_data = {"users": [user1], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.admin_get_user_list(page=2, page_size=10) + + assert isinstance(result, UserList) + api.api_client.call_api.assert_called_once() + + def test_admin_get_user_list_with_filters( + self, mocker, sample_user_data, sample_pagination_data + ): + """Test case for admin_get_user_list with filter parameters""" + api = AdminUserManagementApi() + user1 = sample_user_data(is_superadmin=True) + pagination = sample_pagination_data(total_items=1) + + response_data = {"users": [user1], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.admin_get_user_list(filter=["is_superadmin=true"]) + + assert isinstance(result, UserList) + + def test_admin_get_user_list_with_http_info(self, mocker, sample_pagination_data): + """Test case for admin_get_user_list_with_http_info""" + api = AdminUserManagementApi() + pagination = sample_pagination_data() + response_data = {"users": [], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.admin_get_user_list_with_http_info() + + assert result.status_code == 200 + assert isinstance(result.data, UserList) + + def test_admin_update_user_success(self, mocker, sample_user_data): + """Test case for admin_update_user - successfully update a user""" + api = AdminUserManagementApi() + updated_data = sample_user_data(email="updated@example.com", is_superadmin=True) + mock_response = create_mock_response(updated_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + user = User(email="updated@example.com", is_superadmin=True) + result = api.admin_update_user(id=user_id, user=user) + + assert isinstance(result, User) + assert result.is_superadmin is True + + def test_admin_update_user_not_found(self, mocker): + """Test case for admin_update_user with non-existent user""" + api = AdminUserManagementApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + user = User(email="test@example.com", name="Test") + with pytest.raises(NotFoundException): + api.admin_update_user(id=user_id, user=user) + + def test_admin_update_user_with_http_info(self, mocker, sample_user_data): + """Test case for admin_update_user_with_http_info""" + api = AdminUserManagementApi() + user_data = sample_user_data() + mock_response = create_mock_response(user_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + user = User(email="test@example.com", name="Test") + result = api.admin_update_user_with_http_info(id=user_id, user=user) + + assert result.status_code == 200 + assert isinstance(result.data, User) + + def test_admin_update_user_server_error(self, mocker): + """Test case for admin_update_user with server error""" + api = AdminUserManagementApi() + mock_response = create_mock_response({"error": "internal error"}, status=500) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + user_id = "550e8400-e29b-41d4-a716-446655440000" + user = User(email="test@example.com", name="Test") + with pytest.raises(ServiceException): + api.admin_update_user(id=user_id, user=user) diff --git a/test/test_group_api.py b/test/test_group_api.py index 638f8a7..ae258b5 100644 --- a/test/test_group_api.py +++ b/test/test_group_api.py @@ -9,44 +9,206 @@ Do not edit the class manually. """ -import unittest +import pytest from ibutsu_client.api.group_api import GroupApi - - -class TestGroupApi(unittest.TestCase): - """GroupApi unit test stubs""" - - def setUp(self) -> None: - self.api = GroupApi() - - def tearDown(self) -> None: - pass - - def test_add_group(self) -> None: - """Test case for add_group - - Create a new group - """ - - def test_get_group(self) -> None: - """Test case for get_group - - Get a group - """ - - def test_get_group_list(self) -> None: - """Test case for get_group_list - - Get a list of groups - """ - - def test_update_group(self) -> None: - """Test case for update_group - - Update a group - """ - - -if __name__ == "__main__": - unittest.main() +from ibutsu_client.exceptions import NotFoundException, ServiceException +from ibutsu_client.models.group import Group +from ibutsu_client.models.group_list import GroupList +from test.conftest import create_mock_response + + +class TestGroupApi: + """GroupApi comprehensive tests""" + + def test_add_group_success(self, mocker, sample_group_data): + """Test case for add_group - successfully create a new group""" + api = GroupApi() + group_data = sample_group_data(name="engineering-team") + mock_response = create_mock_response(group_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group = Group(name="engineering-team") + result = api.add_group(group=group) + + assert isinstance(result, Group) + assert result.name == "engineering-team" + api.api_client.call_api.assert_called_once() + + def test_add_group_unauthorized(self, mocker): + """Test case for add_group without proper authentication""" + api = GroupApi() + mock_response = create_mock_response({"error": "unauthorized"}, status=401) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group = Group(name="test-group") + with pytest.raises((ServiceException, Exception)): + api.add_group(group=group) + + def test_add_group_conflict(self, mocker): + """Test case for add_group with existing group name""" + api = GroupApi() + mock_response = create_mock_response({"error": "group already exists"}, status=409) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group = Group(name="existing-group") + with pytest.raises((ServiceException, Exception)): + api.add_group(group=group) + + def test_add_group_with_http_info(self, mocker, sample_group_data): + """Test case for add_group_with_http_info""" + api = GroupApi() + group_data = sample_group_data(name="new-team") + mock_response = create_mock_response(group_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group = Group(name="new-team") + result = api.add_group_with_http_info(group=group) + + assert result.status_code == 201 + assert isinstance(result.data, Group) + + def test_get_group_success(self, mocker, sample_group_data): + """Test case for get_group - retrieve a single group""" + api = GroupApi() + group_data = sample_group_data(name="qa-team") + mock_response = create_mock_response(group_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_group(id=group_id) + + assert isinstance(result, Group) + assert result.name == "qa-team" + + def test_get_group_not_found(self, mocker): + """Test case for get_group with non-existent group""" + api = GroupApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.get_group(id=group_id) + + def test_get_group_with_http_info(self, mocker, sample_group_data): + """Test case for get_group_with_http_info""" + api = GroupApi() + group_data = sample_group_data() + mock_response = create_mock_response(group_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_group_with_http_info(id=group_id) + + assert result.status_code == 200 + assert isinstance(result.data, Group) + + def test_get_group_list_success(self, mocker, sample_group_data, sample_pagination_data): + """Test case for get_group_list - retrieve list of groups""" + api = GroupApi() + group1 = sample_group_data(name="team-alpha") + group2 = sample_group_data(name="team-beta") + pagination = sample_pagination_data(total_items=2) + + response_data = {"groups": [group1, group2], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_group_list() + + assert isinstance(result, GroupList) + assert len(result.groups) == 2 + + def test_get_group_list_with_pagination( + self, mocker, sample_group_data, sample_pagination_data + ): + """Test case for get_group_list with pagination parameters""" + api = GroupApi() + group1 = sample_group_data() + pagination = sample_pagination_data(page=2, page_size=10) + + response_data = {"groups": [group1], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_group_list(page=2, page_size=10) + + assert isinstance(result, GroupList) + api.api_client.call_api.assert_called_once() + + def test_get_group_list_empty(self, mocker, sample_pagination_data): + """Test case for get_group_list with no groups""" + api = GroupApi() + pagination = sample_pagination_data(total_items=0) + response_data = {"groups": [], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_group_list() + + assert isinstance(result, GroupList) + assert len(result.groups) == 0 + + def test_get_group_list_with_http_info(self, mocker, sample_pagination_data): + """Test case for get_group_list_with_http_info""" + api = GroupApi() + pagination = sample_pagination_data() + response_data = {"groups": [], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_group_list_with_http_info() + + assert result.status_code == 200 + assert isinstance(result.data, GroupList) + + def test_update_group_success(self, mocker, sample_group_data): + """Test case for update_group - successfully update a group""" + api = GroupApi() + updated_data = sample_group_data(name="updated-team-name") + mock_response = create_mock_response(updated_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group_id = "550e8400-e29b-41d4-a716-446655440000" + group = Group(name="updated-team-name") + result = api.update_group(id=group_id, group=group) + + assert isinstance(result, Group) + assert result.name == "updated-team-name" + + def test_update_group_not_found(self, mocker): + """Test case for update_group with non-existent group""" + api = GroupApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group_id = "550e8400-e29b-41d4-a716-446655440000" + group = Group(name="test-group") + with pytest.raises(NotFoundException): + api.update_group(id=group_id, group=group) + + def test_update_group_with_http_info(self, mocker, sample_group_data): + """Test case for update_group_with_http_info""" + api = GroupApi() + group_data = sample_group_data() + mock_response = create_mock_response(group_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group_id = "550e8400-e29b-41d4-a716-446655440000" + group = Group(name="test-group") + result = api.update_group_with_http_info(id=group_id, group=group) + + assert result.status_code == 200 + assert isinstance(result.data, Group) + + def test_update_group_server_error(self, mocker): + """Test case for update_group with server error""" + api = GroupApi() + mock_response = create_mock_response({"error": "internal error"}, status=500) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + group_id = "550e8400-e29b-41d4-a716-446655440000" + group = Group(name="test-group") + with pytest.raises(ServiceException): + api.update_group(id=group_id, group=group) diff --git a/test/test_import_api.py b/test/test_import_api.py index 4bd70fd..6e5c9c2 100644 --- a/test/test_import_api.py +++ b/test/test_import_api.py @@ -9,32 +9,204 @@ Do not edit the class manually. """ -import unittest +import pytest from ibutsu_client.api.import_api import ImportApi +from ibutsu_client.exceptions import NotFoundException, ServiceException +from ibutsu_client.models.model_import import ModelImport +from test.conftest import create_mock_response -class TestImportApi(unittest.TestCase): - """ImportApi unit test stubs""" +class TestImportApi: + """ImportApi comprehensive tests""" - def setUp(self) -> None: - self.api = ImportApi() + def test_add_import_success(self, mocker): + """Test case for add_import - successfully import a file""" + api = ImportApi() + import_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test_results.xml", + "format": "junit", + "status": "pending", + } + mock_response = create_mock_response(import_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def tearDown(self) -> None: - pass + # Mock file upload - import_file as tuple (filename, content) + result = api.add_import( + import_file=("test_results.xml", b"test content"), + ) - def test_add_import(self) -> None: - """Test case for add_import + assert isinstance(result, ModelImport) + assert result.filename == "test_results.xml" + assert result.format == "junit" + api.api_client.call_api.assert_called_once() - Import a file into Ibutsu. This can be either a JUnit XML file, or an Ibutsu archive - """ + def test_add_import_with_project(self, mocker): + """Test case for add_import with project parameter""" + api = ImportApi() + import_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "results.xml", + "format": "junit", + "project": "test-project", + "status": "pending", + } + mock_response = create_mock_response(import_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def test_get_import(self) -> None: - """Test case for get_import + result = api.add_import( + import_file=("results.xml", b"test"), + project="test-project", + ) - Get the status of an import - """ + assert isinstance(result, ModelImport) + assert result.filename == "results.xml" + api.api_client.call_api.assert_called_once() + def test_add_import_archive_format(self, mocker): + """Test case for add_import with Ibutsu archive format""" + api = ImportApi() + import_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "archive.tar.gz", + "format": "ibutsu", + "status": "pending", + } + mock_response = create_mock_response(import_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) -if __name__ == "__main__": - unittest.main() + result = api.add_import( + import_file=("archive.tar.gz", b"binary archive content"), + ) + + assert isinstance(result, ModelImport) + assert result.format == "ibutsu" + + def test_add_import_invalid_file(self, mocker): + """Test case for add_import with invalid file""" + api = ImportApi() + mock_response = create_mock_response({"error": "invalid file format"}, status=400) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + with pytest.raises((ServiceException, Exception)): + api.add_import(import_file=("invalid.txt", b"invalid content")) + + def test_add_import_unauthorized(self, mocker): + """Test case for add_import without authentication""" + api = ImportApi() + mock_response = create_mock_response({"error": "unauthorized"}, status=401) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + with pytest.raises((ServiceException, Exception)): + api.add_import(import_file=("test.xml", b"content")) + + def test_add_import_with_http_info(self, mocker): + """Test case for add_import_with_http_info""" + api = ImportApi() + import_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test.xml", + "status": "pending", + } + mock_response = create_mock_response(import_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.add_import_with_http_info( + import_file=("test.xml", b"content"), + ) + + assert result.status_code == 201 + assert isinstance(result.data, ModelImport) + + def test_get_import_success(self, mocker): + """Test case for get_import - retrieve import status""" + api = ImportApi() + import_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test_results.xml", + "format": "junit", + "status": "done", + "run_id": "660e8400-e29b-41d4-a716-446655440000", + } + mock_response = create_mock_response(import_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + import_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_import(id=import_id) + + assert isinstance(result, ModelImport) + assert result.status == "done" + assert result.run_id is not None + + def test_get_import_pending_status(self, mocker): + """Test case for get_import with pending status""" + api = ImportApi() + import_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test.xml", + "status": "pending", + } + mock_response = create_mock_response(import_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + import_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_import(id=import_id) + + assert isinstance(result, ModelImport) + assert result.status == "pending" + + def test_get_import_running_status(self, mocker): + """Test case for get_import with running status""" + api = ImportApi() + import_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test.xml", + "status": "running", + "format": "junit", + } + mock_response = create_mock_response(import_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + import_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_import(id=import_id) + + assert isinstance(result, ModelImport) + assert result.status == "running" + + def test_get_import_not_found(self, mocker): + """Test case for get_import with non-existent import""" + api = ImportApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + import_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.get_import(id=import_id) + + def test_get_import_with_http_info(self, mocker): + """Test case for get_import_with_http_info""" + api = ImportApi() + import_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test.xml", + "status": "done", + } + mock_response = create_mock_response(import_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + import_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_import_with_http_info(id=import_id) + + assert result.status_code == 200 + assert isinstance(result.data, ModelImport) + + def test_get_import_server_error(self, mocker): + """Test case for get_import with server error""" + api = ImportApi() + mock_response = create_mock_response({"error": "internal error"}, status=500) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + import_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(ServiceException): + api.get_import(id=import_id) diff --git a/test/test_login_api.py b/test/test_login_api.py index f68ef31..fd814df 100644 --- a/test/test_login_api.py +++ b/test/test_login_api.py @@ -9,44 +9,316 @@ Do not edit the class manually. """ -import unittest +import pytest from ibutsu_client.api.login_api import LoginApi +from ibutsu_client.exceptions import NotFoundException, ServiceException +from ibutsu_client.models.login_config import LoginConfig +from ibutsu_client.models.login_support import LoginSupport +from ibutsu_client.models.login_token import LoginToken +from test.conftest import create_mock_response -class TestLoginApi(unittest.TestCase): - """LoginApi unit test stubs""" +class TestLoginApi: + """LoginApi comprehensive tests""" - def setUp(self) -> None: - self.api = LoginApi() + def test_activate_success(self, mocker): + """Test case for activate with successful activation""" + api = LoginApi() + from ibutsu_client.api_response import ApiResponse - def tearDown(self) -> None: - pass + # Mock response_deserialize to return ApiResponse with None data (302 redirect) + mock_api_response = ApiResponse(status_code=302, data=None, headers={}, raw_data=b"") + mocker.patch.object(api.api_client, "response_deserialize", return_value=mock_api_response) + mocker.patch.object(api.api_client, "call_api") - def test_activate(self) -> None: - """Test case for activate""" + # Should not raise exception for 302 redirect + result = api.activate(activation_code="test-activation-code") + assert result is None + api.api_client.call_api.assert_called_once() - def test_auth(self) -> None: - """Test case for auth""" + def test_activate_not_found(self, mocker): + """Test case for activate with invalid activation code""" + api = LoginApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def test_config(self) -> None: - """Test case for config""" + with pytest.raises(NotFoundException): + api.activate(activation_code="invalid-code") - def test_login(self) -> None: - """Test case for login""" + def test_activate_with_http_info(self, mocker): + """Test case for activate_with_http_info""" + api = LoginApi() + from ibutsu_client.api_response import ApiResponse - def test_recover(self) -> None: - """Test case for recover""" + # Mock response_deserialize to return ApiResponse with None data (302 redirect) + mock_api_response = ApiResponse(status_code=302, data=None, headers={}, raw_data=b"") + mocker.patch.object(api.api_client, "response_deserialize", return_value=mock_api_response) + mocker.patch.object(api.api_client, "call_api") - def test_register(self) -> None: - """Test case for register""" + result = api.activate_with_http_info(activation_code="test-code") + assert result.status_code == 302 + assert result.data is None - def test_reset_password(self) -> None: - """Test case for reset_password""" + def test_auth_success(self, mocker): + """Test case for auth - redirects to OAuth provider""" + api = LoginApi() + from ibutsu_client.api_response import ApiResponse - def test_support(self) -> None: - """Test case for support""" + # auth() returns None (302 redirect to OAuth provider) + mock_api_response = ApiResponse(status_code=302, data=None, headers={}, raw_data=b"") + mocker.patch.object(api.api_client, "response_deserialize", return_value=mock_api_response) + mocker.patch.object(api.api_client, "call_api") + result = api.auth(provider="oidc") + assert result is None + api.api_client.call_api.assert_called_once() -if __name__ == "__main__": - unittest.main() + def test_auth_unauthorized(self, mocker): + """Test case for auth with invalid provider""" + api = LoginApi() + mock_response = create_mock_response({"error": "invalid provider"}, status=400) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + with pytest.raises( + (ServiceException, Exception) + ): # Should raise appropriate auth exception + api.auth(provider="invalid") + + def test_auth_with_http_info(self, mocker): + """Test case for auth_with_http_info - redirects to OAuth provider""" + api = LoginApi() + from ibutsu_client.api_response import ApiResponse + + # auth() returns None (302 redirect to OAuth provider) + mock_api_response = ApiResponse(status_code=302, data=None, headers={}, raw_data=b"") + mocker.patch.object(api.api_client, "response_deserialize", return_value=mock_api_response) + mocker.patch.object(api.api_client, "call_api") + + result = api.auth_with_http_info(provider="oidc") + assert result.status_code == 302 + assert result.data is None + + def test_config_success(self, mocker): + """Test case for config - get login configuration""" + api = LoginApi() + response_data = { + "client_id": "test-client-id", + "redirect_uri": "https://example.com/callback", + "scope": "openid profile email", + } + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.config(provider="oidc") + assert isinstance(result, LoginConfig) + assert result.client_id == "test-client-id" + assert result.redirect_uri == "https://example.com/callback" + + def test_config_with_http_info(self, mocker): + """Test case for config_with_http_info""" + api = LoginApi() + response_data = {"client_id": "test-client"} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.config_with_http_info(provider="oidc") + assert result.status_code == 200 + assert isinstance(result.data, LoginConfig) + + def test_login_success(self, mocker): + """Test case for login with valid credentials""" + api = LoginApi() + response_data = { + "token": "jwt-token-here", + "refresh_token": "refresh-token-here", + } + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.credentials import Credentials + + credentials = Credentials(email="test@example.com", password="password123") + result = api.login(credentials=credentials) + assert isinstance(result, LoginToken) + assert result.token == "jwt-token-here" + + def test_login_invalid_credentials(self, mocker): + """Test case for login with invalid credentials""" + api = LoginApi() + mock_response = create_mock_response({"error": "invalid credentials"}, status=401) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.credentials import Credentials + + credentials = Credentials(email="wrong@example.com", password="wrongpass") + with pytest.raises((ServiceException, Exception)): + api.login(credentials=credentials) + + def test_login_with_http_info(self, mocker): + """Test case for login_with_http_info""" + api = LoginApi() + response_data = {"token": "test-token"} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.credentials import Credentials + + credentials = Credentials(email="test@example.com", password="pass") + result = api.login_with_http_info(credentials=credentials) + assert result.status_code == 200 + assert isinstance(result.data, LoginToken) + + def test_recover_success(self, mocker): + """Test case for recover - initiate password recovery""" + api = LoginApi() + mock_response = create_mock_response({}, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.account_recovery import AccountRecovery + + recovery_data = AccountRecovery(email="test@example.com") + api.recover(account_recovery=recovery_data) + # Method should complete without raising exception + api.api_client.call_api.assert_called_once() + + def test_recover_not_found(self, mocker): + """Test case for recover with non-existent email""" + api = LoginApi() + mock_response = create_mock_response({"error": "user not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.account_recovery import AccountRecovery + + recovery_data = AccountRecovery(email="nonexistent@example.com") + with pytest.raises(NotFoundException): + api.recover(account_recovery=recovery_data) + + def test_recover_with_http_info(self, mocker): + """Test case for recover_with_http_info""" + api = LoginApi() + mock_response = create_mock_response({}, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.account_recovery import AccountRecovery + + recovery_data = AccountRecovery(email="test@example.com") + result = api.recover_with_http_info(account_recovery=recovery_data) + assert result.status_code == 200 + + def test_register_success(self, mocker): + """Test case for register with valid registration data""" + api = LoginApi() + response_data = {"message": "Registration successful"} + mock_response = create_mock_response(response_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.account_registration import AccountRegistration + + registration = AccountRegistration( + email="newuser@example.com", password="securepass123", name="New User" + ) + api.register(account_registration=registration) + api.api_client.call_api.assert_called_once() + + def test_register_conflict(self, mocker): + """Test case for register with existing email""" + api = LoginApi() + mock_response = create_mock_response({"error": "email already exists"}, status=409) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.account_registration import AccountRegistration + + registration = AccountRegistration( + email="existing@example.com", password="pass123", name="User" + ) + with pytest.raises((ServiceException, Exception)): # Should raise conflict exception + api.register(account_registration=registration) + + def test_register_with_http_info(self, mocker): + """Test case for register_with_http_info""" + api = LoginApi() + response_data = {"message": "success"} + mock_response = create_mock_response(response_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.account_registration import AccountRegistration + + registration = AccountRegistration(email="test@example.com", password="pass", name="Test") + result = api.register_with_http_info(account_registration=registration) + assert result.status_code == 201 + + def test_reset_password_success(self, mocker): + """Test case for reset_password with valid reset data""" + api = LoginApi() + mock_response = create_mock_response({}, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.account_reset import AccountReset + + reset_data = AccountReset(activation_code="reset-code-123", password="newpass123") + api.reset_password(account_reset=reset_data) + api.api_client.call_api.assert_called_once() + + def test_reset_password_invalid_code(self, mocker): + """Test case for reset_password with invalid reset code""" + api = LoginApi() + mock_response = create_mock_response({"error": "invalid reset code"}, status=400) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.account_reset import AccountReset + + reset_data = AccountReset(activation_code="invalid-code", password="newpass") + with pytest.raises((ServiceException, Exception)): + api.reset_password(account_reset=reset_data) + + def test_reset_password_with_http_info(self, mocker): + """Test case for reset_password_with_http_info""" + api = LoginApi() + mock_response = create_mock_response({}, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + from ibutsu_client.models.account_reset import AccountReset + + reset_data = AccountReset(activation_code="code", password="newpass") + result = api.reset_password_with_http_info(account_reset=reset_data) + assert result.status_code == 200 + + def test_support_success(self, mocker): + """Test case for support - get support configuration""" + api = LoginApi() + response_data = { + "user": True, + "keycloak": True, + "google": False, + "github": False, + "facebook": False, + "gitlab": False, + } + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.support() + assert isinstance(result, LoginSupport) + assert result.user is True + assert result.keycloak is True + + def test_support_with_http_info(self, mocker): + """Test case for support_with_http_info""" + api = LoginApi() + response_data = {"user": True, "google": True} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.support_with_http_info() + assert result.status_code == 200 + assert isinstance(result.data, LoginSupport) + + def test_support_server_error(self, mocker): + """Test case for support with server error""" + api = LoginApi() + mock_response = create_mock_response({"error": "internal error"}, status=500) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + with pytest.raises(ServiceException): + api.support() diff --git a/test/test_task_api.py b/test/test_task_api.py index 31d589f..0c460b3 100644 --- a/test/test_task_api.py +++ b/test/test_task_api.py @@ -9,26 +9,178 @@ Do not edit the class manually. """ -import unittest +import pytest from ibutsu_client.api.task_api import TaskApi +from ibutsu_client.exceptions import NotFoundException, ServiceException +from test.conftest import create_mock_response -class TestTaskApi(unittest.TestCase): - """TaskApi unit test stubs""" +class TestTaskApi: + """TaskApi comprehensive tests""" - def setUp(self) -> None: - self.api = TaskApi() + def test_get_task_pending(self, mocker): + """Test case for get_task with pending status""" + api = TaskApi() + task_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "pending", + "task_type": "export", + } + mock_response = create_mock_response(task_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def tearDown(self) -> None: - pass + task_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_task(id=task_id) - def test_get_task(self) -> None: - """Test case for get_task + assert result is not None + assert result["status"] == "pending" + assert result["task_type"] == "export" + api.api_client.call_api.assert_called_once() - Get the status or result of a task - """ + def test_get_task_running(self, mocker): + """Test case for get_task with running status""" + api = TaskApi() + task_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "running", + "task_type": "bulk_update", + "progress": 45, + } + mock_response = create_mock_response(task_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + task_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_task(id=task_id) -if __name__ == "__main__": - unittest.main() + assert result is not None + assert result["status"] == "running" + assert result["progress"] == 45 + + def test_get_task_completed(self, mocker): + """Test case for get_task with completed status""" + api = TaskApi() + task_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "completed", + "task_type": "export", + "result": { + "file_url": "https://example.com/exports/results.tar.gz", + "file_size": 1024000, + }, + } + mock_response = create_mock_response(task_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + task_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_task(id=task_id) + + assert result is not None + assert result["status"] == "completed" + assert result["result"]["file_url"] == "https://example.com/exports/results.tar.gz" + + def test_get_task_failed(self, mocker): + """Test case for get_task with failed status""" + api = TaskApi() + task_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "failed", + "task_type": "bulk_update", + "error": "Database connection timeout", + } + mock_response = create_mock_response(task_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + task_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_task(id=task_id) + + assert result is not None + assert result["status"] == "failed" + assert result["error"] == "Database connection timeout" + + def test_get_task_not_found(self, mocker): + """Test case for get_task with non-existent task""" + api = TaskApi() + mock_response = create_mock_response({"error": "task not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + task_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.get_task(id=task_id) + + def test_get_task_with_http_info(self, mocker): + """Test case for get_task_with_http_info""" + api = TaskApi() + task_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "completed", + } + mock_response = create_mock_response(task_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + task_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_task_with_http_info(id=task_id) + + assert result.status_code == 200 + assert result.data is not None + + def test_get_task_unauthorized(self, mocker): + """Test case for get_task without authentication""" + api = TaskApi() + mock_response = create_mock_response({"error": "unauthorized"}, status=401) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + task_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises((ServiceException, Exception)): + api.get_task(id=task_id) + + def test_get_task_server_error(self, mocker): + """Test case for get_task with server error""" + api = TaskApi() + mock_response = create_mock_response({"error": "internal error"}, status=500) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + task_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(ServiceException): + api.get_task(id=task_id) + + def test_get_task_export_type(self, mocker): + """Test case for get_task with export task type""" + api = TaskApi() + task_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "completed", + "task_type": "export", + "result": { + "format": "json", + "records_exported": 1000, + }, + } + mock_response = create_mock_response(task_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + task_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_task(id=task_id) + + assert result["task_type"] == "export" + assert result["result"]["records_exported"] == 1000 + + def test_get_task_bulk_update_type(self, mocker): + """Test case for get_task with bulk_update task type""" + api = TaskApi() + task_data = { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "completed", + "task_type": "bulk_update", + "result": { + "updated_count": 150, + }, + } + mock_response = create_mock_response(task_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + task_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_task(id=task_id) + + assert result["task_type"] == "bulk_update" + assert result["result"]["updated_count"] == 150 diff --git a/test/test_user_api.py b/test/test_user_api.py index d43a303..d7201ac 100644 --- a/test/test_user_api.py +++ b/test/test_user_api.py @@ -9,56 +9,246 @@ Do not edit the class manually. """ -import unittest +import pytest from ibutsu_client.api.user_api import UserApi - - -class TestUserApi(unittest.TestCase): - """UserApi unit test stubs""" - - def setUp(self) -> None: - self.api = UserApi() - - def tearDown(self) -> None: - pass - - def test_add_token(self) -> None: - """Test case for add_token - - Create a token for the current user - """ - - def test_delete_token(self) -> None: - """Test case for delete_token - - Delete the token - """ - - def test_get_current_user(self) -> None: - """Test case for get_current_user - - Return the user details for the current user - """ - - def test_get_token(self) -> None: - """Test case for get_token - - Retrieve a single token for the current user - """ - - def test_get_token_list(self) -> None: - """Test case for get_token_list - - Return the tokens for the user - """ - - def test_update_current_user(self) -> None: - """Test case for update_current_user - - Return the user details for the current user - """ - - -if __name__ == "__main__": - unittest.main() +from ibutsu_client.exceptions import NotFoundException, ServiceException +from ibutsu_client.models.create_token import CreateToken +from ibutsu_client.models.token import Token +from ibutsu_client.models.token_list import TokenList +from ibutsu_client.models.user import User +from test.conftest import create_mock_response + + +class TestUserApi: + """UserApi comprehensive tests""" + + def test_add_token_success(self, mocker, sample_token_data): + """Test case for add_token - successfully create a token""" + api = UserApi() + token_data = sample_token_data(name="api-token", expires="2025-12-31") + mock_response = create_mock_response(token_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + create_token = CreateToken(name="api-token", expires="2025-12-31") + result = api.add_token(create_token=create_token) + + assert isinstance(result, Token) + assert result.name == "api-token" + assert result.expires == "2025-12-31" + api.api_client.call_api.assert_called_once() + + def test_add_token_unauthorized(self, mocker): + """Test case for add_token with no authentication""" + api = UserApi() + mock_response = create_mock_response({"error": "unauthorized"}, status=401) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + create_token = CreateToken(name="test-token", expires="2025-12-31") + with pytest.raises((ServiceException, Exception)): # Should raise unauthorized exception + api.add_token(create_token=create_token) + + def test_add_token_with_http_info(self, mocker, sample_token_data): + """Test case for add_token_with_http_info""" + api = UserApi() + token_data = sample_token_data(name="test-token") + mock_response = create_mock_response(token_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + create_token = CreateToken(name="test-token", expires="2025-12-31") + result = api.add_token_with_http_info(create_token=create_token) + + assert result.status_code == 201 + assert isinstance(result.data, Token) + + def test_delete_token_success(self, mocker): + """Test case for delete_token - successfully delete a token""" + api = UserApi() + mock_response = create_mock_response({}, status=204) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + token_id = "550e8400-e29b-41d4-a716-446655440000" + api.delete_token(id=token_id) + + # 204 No Content typically returns None + api.api_client.call_api.assert_called_once() + + def test_delete_token_not_found(self, mocker): + """Test case for delete_token with non-existent token""" + api = UserApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + token_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.delete_token(id=token_id) + + def test_delete_token_with_http_info(self, mocker): + """Test case for delete_token_with_http_info""" + api = UserApi() + mock_response = create_mock_response({}, status=204) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + token_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.delete_token_with_http_info(id=token_id) + + assert result.status_code == 204 + + def test_get_current_user_success(self, mocker, sample_user_data): + """Test case for get_current_user - retrieve current user details""" + api = UserApi() + user_data = sample_user_data(email="current@example.com", name="Current User") + mock_response = create_mock_response(user_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_current_user() + + assert isinstance(result, User) + assert result.email == "current@example.com" + assert result.name == "Current User" + + def test_get_current_user_unauthorized(self, mocker): + """Test case for get_current_user without authentication""" + api = UserApi() + mock_response = create_mock_response({"error": "unauthorized"}, status=401) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + with pytest.raises((ServiceException, Exception)): + api.get_current_user() + + def test_get_current_user_with_http_info(self, mocker, sample_user_data): + """Test case for get_current_user_with_http_info""" + api = UserApi() + user_data = sample_user_data() + mock_response = create_mock_response(user_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_current_user_with_http_info() + + assert result.status_code == 200 + assert isinstance(result.data, User) + + def test_get_token_success(self, mocker, sample_token_data): + """Test case for get_token - retrieve a single token""" + api = UserApi() + token_data = sample_token_data(name="specific-token") + mock_response = create_mock_response(token_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + token_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_token(id=token_id) + + assert isinstance(result, Token) + assert result.name == "specific-token" + + def test_get_token_not_found(self, mocker): + """Test case for get_token with non-existent token""" + api = UserApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + token_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.get_token(id=token_id) + + def test_get_token_with_http_info(self, mocker, sample_token_data): + """Test case for get_token_with_http_info""" + api = UserApi() + token_data = sample_token_data() + mock_response = create_mock_response(token_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + token_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_token_with_http_info(id=token_id) + + assert result.status_code == 200 + assert isinstance(result.data, Token) + + def test_get_token_list_success(self, mocker, sample_token_data, sample_pagination_data): + """Test case for get_token_list - retrieve list of tokens""" + api = UserApi() + token1 = sample_token_data(name="token1") + token2 = sample_token_data(name="token2") + pagination = sample_pagination_data(page=1, page_size=25, total_items=2) + + response_data = {"tokens": [token1, token2], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_token_list() + + assert isinstance(result, TokenList) + assert len(result.tokens) == 2 + + def test_get_token_list_with_pagination( + self, mocker, sample_token_data, sample_pagination_data + ): + """Test case for get_token_list with pagination parameters""" + api = UserApi() + token1 = sample_token_data() + pagination = sample_pagination_data(page=2, page_size=10) + + response_data = {"tokens": [token1], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_token_list(page=2, page_size=10) + + assert isinstance(result, TokenList) + api.api_client.call_api.assert_called_once() + + def test_get_token_list_with_http_info(self, mocker, sample_pagination_data): + """Test case for get_token_list_with_http_info""" + api = UserApi() + pagination = sample_pagination_data() + response_data = {"tokens": [], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_token_list_with_http_info() + + assert result.status_code == 200 + assert isinstance(result.data, TokenList) + + def test_update_current_user_success(self, mocker, sample_user_data): + """Test case for update_current_user - get current user details""" + api = UserApi() + user_data = sample_user_data(email="current@example.com", name="Current User") + mock_response = create_mock_response(user_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.update_current_user() + + assert isinstance(result, User) + assert result.email == "current@example.com" + assert result.name == "Current User" + + def test_update_current_user_unauthorized(self, mocker): + """Test case for update_current_user without authentication""" + api = UserApi() + mock_response = create_mock_response({"error": "unauthorized"}, status=401) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + with pytest.raises((ServiceException, Exception)): + api.update_current_user() + + def test_update_current_user_with_http_info(self, mocker, sample_user_data): + """Test case for update_current_user_with_http_info""" + api = UserApi() + user_data = sample_user_data() + mock_response = create_mock_response(user_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.update_current_user_with_http_info() + + assert result.status_code == 200 + assert isinstance(result.data, User) + + def test_update_current_user_server_error(self, mocker): + """Test case for update_current_user with server error""" + api = UserApi() + mock_response = create_mock_response({"error": "internal error"}, status=500) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + with pytest.raises(ServiceException): + api.update_current_user() diff --git a/test/test_widget_api.py b/test/test_widget_api.py index 345f8cb..62620bd 100644 --- a/test/test_widget_api.py +++ b/test/test_widget_api.py @@ -9,32 +9,180 @@ Do not edit the class manually. """ -import unittest +import pytest from ibutsu_client.api.widget_api import WidgetApi +from ibutsu_client.exceptions import NotFoundException, ServiceException +from ibutsu_client.models.widget_type_list import WidgetTypeList +from test.conftest import create_mock_response -class TestWidgetApi(unittest.TestCase): - """WidgetApi unit test stubs""" +class TestWidgetApi: + """WidgetApi comprehensive tests""" - def setUp(self) -> None: - self.api = WidgetApi() + def test_get_widget_success(self, mocker): + """Test case for get_widget - successfully generate widget data""" + api = WidgetApi() + widget_data = { + "type": "result-summary", + "data": { + "passed": 100, + "failed": 5, + "skipped": 2, + "error": 0, + }, + } + mock_response = create_mock_response(widget_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def tearDown(self) -> None: - pass + widget_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget(id=widget_id) - def test_get_widget(self) -> None: - """Test case for get_widget + assert result is not None + assert result["type"] == "result-summary" + assert result["data"]["passed"] == 100 + api.api_client.call_api.assert_called_once() - Generate data for a dashboard widget - """ + def test_get_widget_with_filters(self, mocker): + """Test case for get_widget with filter parameters""" + api = WidgetApi() + widget_data = { + "type": "jenkins-heatmap", + "data": {"rows": [], "columns": []}, + } + mock_response = create_mock_response(widget_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def test_get_widget_types(self) -> None: - """Test case for get_widget_types + widget_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget( + id=widget_id, + params={"project": "test-project", "env": "production"}, + ) - Get a list of widget types - """ + assert result is not None + assert result["type"] == "jenkins-heatmap" + api.api_client.call_api.assert_called_once() + def test_get_widget_with_additional_params(self, mocker): + """Test case for get_widget with additional parameters""" + api = WidgetApi() + widget_data = { + "type": "result-aggregation", + "data": {"aggregations": []}, + } + mock_response = create_mock_response(widget_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) -if __name__ == "__main__": - unittest.main() + widget_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget( + id=widget_id, + params={"group_by": "component", "limit": 10}, + ) + + assert result is not None + api.api_client.call_api.assert_called_once() + + def test_get_widget_not_found(self, mocker): + """Test case for get_widget with invalid widget name""" + api = WidgetApi() + mock_response = create_mock_response({"error": "widget not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.get_widget(id=widget_id) + + def test_get_widget_server_error(self, mocker): + """Test case for get_widget with server error""" + api = WidgetApi() + mock_response = create_mock_response({"error": "internal error"}, status=500) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(ServiceException): + api.get_widget(id=widget_id) + + def test_get_widget_with_http_info(self, mocker): + """Test case for get_widget_with_http_info""" + api = WidgetApi() + widget_data = {"type": "test-widget", "data": {}} + mock_response = create_mock_response(widget_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget_with_http_info(id=widget_id) + + assert result.status_code == 200 + assert result.data is not None + + def test_get_widget_types_success(self, mocker): + """Test case for get_widget_types - retrieve list of available widget types""" + api = WidgetApi() + widget_types_data = { + "types": [ + { + "name": "result-summary", + "description": "Summary of test results", + "params": [], + }, + { + "name": "jenkins-heatmap", + "description": "Jenkins build heatmap", + "params": [], + }, + { + "name": "result-aggregation", + "description": "Aggregated test results", + "params": [], + }, + ] + } + mock_response = create_mock_response(widget_types_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_widget_types() + + assert isinstance(result, WidgetTypeList) + assert len(result.types) == 3 + api.api_client.call_api.assert_called_once() + + def test_get_widget_types_empty(self, mocker): + """Test case for get_widget_types with no types available""" + api = WidgetApi() + widget_types_data = {"types": []} + mock_response = create_mock_response(widget_types_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_widget_types() + + assert isinstance(result, WidgetTypeList) + assert len(result.types) == 0 + + def test_get_widget_types_with_http_info(self, mocker): + """Test case for get_widget_types_with_http_info""" + api = WidgetApi() + widget_types_data = { + "types": [ + { + "name": "result-summary", + "description": "Summary", + "params": [], + } + ] + } + mock_response = create_mock_response(widget_types_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + result = api.get_widget_types_with_http_info() + + assert result.status_code == 200 + assert isinstance(result.data, WidgetTypeList) + + def test_get_widget_types_server_error(self, mocker): + """Test case for get_widget_types with server error""" + api = WidgetApi() + mock_response = create_mock_response({"error": "internal error"}, status=500) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + with pytest.raises(ServiceException): + api.get_widget_types() diff --git a/test/test_widget_config_api.py b/test/test_widget_config_api.py index 486e106..51a9129 100644 --- a/test/test_widget_config_api.py +++ b/test/test_widget_config_api.py @@ -9,50 +9,257 @@ Do not edit the class manually. """ -import unittest +import pytest from ibutsu_client.api.widget_config_api import WidgetConfigApi +from ibutsu_client.exceptions import NotFoundException, ServiceException +from ibutsu_client.models.widget_config import WidgetConfig +from ibutsu_client.models.widget_config_list import WidgetConfigList +from test.conftest import create_mock_response -class TestWidgetConfigApi(unittest.TestCase): - """WidgetConfigApi unit test stubs""" +class TestWidgetConfigApi: + """WidgetConfigApi comprehensive tests""" - def setUp(self) -> None: - self.api = WidgetConfigApi() + def test_add_widget_config_success(self, mocker, sample_widget_config_data): + """Test case for add_widget_config - successfully create a widget config""" + api = WidgetConfigApi() + widget_data = sample_widget_config_data(widget_type="result-summary", weight=0) + mock_response = create_mock_response(widget_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def tearDown(self) -> None: - pass + widget_config = WidgetConfig(widget_type="result-summary", weight=0, params={}) + result = api.add_widget_config(widget_config=widget_config) - def test_add_widget_config(self) -> None: - """Test case for add_widget_config + assert isinstance(result, WidgetConfig) + assert result.widget_type == "result-summary" + assert result.weight == 0 + api.api_client.call_api.assert_called_once() - Create a widget configuration - """ + def test_add_widget_config_with_params(self, mocker, sample_widget_config_data): + """Test case for add_widget_config with widget parameters""" + api = WidgetConfigApi() + params = {"filter": "result:passed", "chart_type": "bar"} + widget_data = sample_widget_config_data( + widget_type="result-aggregation", weight=5, params=params + ) + mock_response = create_mock_response(widget_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - def test_delete_widget_config(self) -> None: - """Test case for delete_widget_config + widget_config = WidgetConfig(widget_type="result-aggregation", weight=5, params=params) + result = api.add_widget_config(widget_config=widget_config) - Delete a widget configuration - """ + assert isinstance(result, WidgetConfig) + assert result.params == params - def test_get_widget_config(self) -> None: - """Test case for get_widget_config + def test_add_widget_config_unauthorized(self, mocker): + """Test case for add_widget_config without authentication""" + api = WidgetConfigApi() + mock_response = create_mock_response({"error": "unauthorized"}, status=401) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - Get a single widget configuration - """ + widget_config = WidgetConfig(widget_type="test", weight=0) + with pytest.raises((ServiceException, Exception)): + api.add_widget_config(widget_config=widget_config) - def test_get_widget_config_list(self) -> None: - """Test case for get_widget_config_list + def test_add_widget_config_with_http_info(self, mocker, sample_widget_config_data): + """Test case for add_widget_config_with_http_info""" + api = WidgetConfigApi() + widget_data = sample_widget_config_data() + mock_response = create_mock_response(widget_data, status=201) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - Get the list of widget configurations - """ + widget_config = WidgetConfig(widget_type="test", weight=0) + result = api.add_widget_config_with_http_info(widget_config=widget_config) - def test_update_widget_config(self) -> None: - """Test case for update_widget_config + assert result.status_code == 201 + assert isinstance(result.data, WidgetConfig) - Updates a single widget configuration - """ + def test_delete_widget_config_success(self, mocker): + """Test case for delete_widget_config - successfully delete a widget""" + api = WidgetConfigApi() + mock_response = create_mock_response({}, status=204) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + widget_id = "550e8400-e29b-41d4-a716-446655440000" + api.delete_widget_config(id=widget_id) -if __name__ == "__main__": - unittest.main() + # 204 No Content typically returns None + api.api_client.call_api.assert_called_once() + + def test_delete_widget_config_not_found(self, mocker): + """Test case for delete_widget_config with non-existent widget""" + api = WidgetConfigApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.delete_widget_config(id=widget_id) + + def test_delete_widget_config_with_http_info(self, mocker): + """Test case for delete_widget_config_with_http_info""" + api = WidgetConfigApi() + mock_response = create_mock_response({}, status=204) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.delete_widget_config_with_http_info(id=widget_id) + + assert result.status_code == 204 + + def test_get_widget_config_success(self, mocker, sample_widget_config_data): + """Test case for get_widget_config - retrieve a single widget config""" + api = WidgetConfigApi() + widget_data = sample_widget_config_data(widget_type="jenkins-heatmap") + mock_response = create_mock_response(widget_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget_config(id=widget_id) + + assert isinstance(result, WidgetConfig) + assert result.widget_type == "jenkins-heatmap" + + def test_get_widget_config_not_found(self, mocker): + """Test case for get_widget_config with non-existent widget""" + api = WidgetConfigApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + with pytest.raises(NotFoundException): + api.get_widget_config(id=widget_id) + + def test_get_widget_config_with_http_info(self, mocker, sample_widget_config_data): + """Test case for get_widget_config_with_http_info""" + api = WidgetConfigApi() + widget_data = sample_widget_config_data() + mock_response = create_mock_response(widget_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget_config_with_http_info(id=widget_id) + + assert result.status_code == 200 + assert isinstance(result.data, WidgetConfig) + + def test_get_widget_config_list_success( + self, mocker, sample_widget_config_data, sample_pagination_data + ): + """Test case for get_widget_config_list - retrieve list of widget configs""" + api = WidgetConfigApi() + widget1 = sample_widget_config_data(widget_type="result-summary", weight=0) + widget2 = sample_widget_config_data(widget_type="jenkins-heatmap", weight=1) + pagination = sample_pagination_data(total_items=2) + + response_data = { + "widgets": [widget1, widget2], + "pagination": pagination, + } + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + dashboard_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget_config_list(dashboard_id=dashboard_id) + + assert isinstance(result, WidgetConfigList) + assert len(result.widgets) == 2 + + def test_get_widget_config_list_with_filters( + self, mocker, sample_widget_config_data, sample_pagination_data + ): + """Test case for get_widget_config_list with filter parameters""" + api = WidgetConfigApi() + widget1 = sample_widget_config_data() + pagination = sample_pagination_data(total_items=1) + + response_data = {"widgets": [widget1], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + dashboard_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget_config_list( + dashboard_id=dashboard_id, filter=["widget_type=result-summary"] + ) + + assert isinstance(result, WidgetConfigList) + api.api_client.call_api.assert_called_once() + + def test_get_widget_config_list_empty(self, mocker, sample_pagination_data): + """Test case for get_widget_config_list with no widgets""" + api = WidgetConfigApi() + pagination = sample_pagination_data(total_items=0) + response_data = {"widgets": [], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + dashboard_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget_config_list(dashboard_id=dashboard_id) + + assert isinstance(result, WidgetConfigList) + assert len(result.widgets) == 0 + + def test_get_widget_config_list_with_http_info(self, mocker, sample_pagination_data): + """Test case for get_widget_config_list_with_http_info""" + api = WidgetConfigApi() + pagination = sample_pagination_data() + response_data = {"widgets": [], "pagination": pagination} + mock_response = create_mock_response(response_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + dashboard_id = "550e8400-e29b-41d4-a716-446655440000" + result = api.get_widget_config_list_with_http_info(dashboard_id=dashboard_id) + + assert result.status_code == 200 + assert isinstance(result.data, WidgetConfigList) + + def test_update_widget_config_success(self, mocker, sample_widget_config_data): + """Test case for update_widget_config - successfully update a widget config""" + api = WidgetConfigApi() + updated_data = sample_widget_config_data(widget_type="result-summary", weight=10) + mock_response = create_mock_response(updated_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + widget_config = WidgetConfig(widget_type="result-summary", weight=10) + result = api.update_widget_config(id=widget_id, widget_config=widget_config) + + assert isinstance(result, WidgetConfig) + assert result.weight == 10 + + def test_update_widget_config_not_found(self, mocker): + """Test case for update_widget_config with non-existent widget""" + api = WidgetConfigApi() + mock_response = create_mock_response({"error": "not found"}, status=404) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + widget_config = WidgetConfig(widget_type="test", weight=0) + with pytest.raises(NotFoundException): + api.update_widget_config(id=widget_id, widget_config=widget_config) + + def test_update_widget_config_with_http_info(self, mocker, sample_widget_config_data): + """Test case for update_widget_config_with_http_info""" + api = WidgetConfigApi() + widget_data = sample_widget_config_data() + mock_response = create_mock_response(widget_data, status=200) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + widget_config = WidgetConfig(widget_type="test", weight=5) + result = api.update_widget_config_with_http_info(id=widget_id, widget_config=widget_config) + + assert result.status_code == 200 + assert isinstance(result.data, WidgetConfig) + + def test_update_widget_config_server_error(self, mocker): + """Test case for update_widget_config with server error""" + api = WidgetConfigApi() + mock_response = create_mock_response({"error": "internal error"}, status=500) + mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + + widget_id = "550e8400-e29b-41d4-a716-446655440000" + widget_config = WidgetConfig(widget_type="test", weight=0) + with pytest.raises(ServiceException): + api.update_widget_config(id=widget_id, widget_config=widget_config) From 4c8a44db506e744f21b567d2acd7b3008825dcda Mon Sep 17 00:00:00 2001 From: mshriver Date: Mon, 24 Nov 2025 15:05:56 -0500 Subject: [PATCH 2/3] Use an indirect fixture --- test/__init__.py | 52 +++++ test/conftest.py | 70 ++++-- test/test_admin_user_management_api.py | 2 +- test/test_group_api.py | 2 +- test/test_health_api.py | 2 +- test/test_import_api.py | 2 +- test/test_login_api.py | 2 +- test/test_task_api.py | 2 +- test/test_user_api.py | 2 +- test/test_widget_api.py | 308 +++++++++++++------------ test/test_widget_config_api.py | 50 ++-- 11 files changed, 300 insertions(+), 194 deletions(-) diff --git a/test/__init__.py b/test/__init__.py index e69de29..1d6190d 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -0,0 +1,52 @@ +"""Test utilities for ibutsu_client tests.""" + +import json +from typing import Any +from unittest.mock import Mock + +from ibutsu_client.rest import RESTResponse + + +def create_mock_response( + data: dict[str, Any] | list[Any] | None = None, + status: int = 200, + headers: dict[str, str] | None = None, +) -> RESTResponse: + """Create a mock REST response for testing. + + Args: + data: The response data (will be JSON-encoded) + status: HTTP status code + headers: Response headers + + Returns: + A mock RESTResponse object + """ + if headers is None: + headers = {"Content-Type": "application/json; charset=utf-8"} + + if data is None: + data = {} + + response = Mock(spec=RESTResponse) + response.status = status + response.headers = headers + response.data = json.dumps(data).encode("utf-8") + response.reason = "OK" if status < 400 else "Error" + + def mock_read(): + """Mock the read method to decode the response data.""" + return response.data + + def mock_getheader(name: str, default: str | None = None) -> str | None: + """Mock the getheader method.""" + return headers.get(name, default) + + def mock_getheaders() -> dict[str, str]: + """Mock the getheaders method.""" + return headers + + response.read = mock_read + response.getheader = mock_getheader + response.getheaders = mock_getheaders + return response diff --git a/test/conftest.py b/test/conftest.py index 136ebd0..0252ca1 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -10,22 +10,12 @@ from ibutsu_client.rest import RESTResponse -@pytest.fixture -def mock_api_client(mocker): - """Create a mock ApiClient for testing API methods.""" - from ibutsu_client.api_client import ApiClient - - client = ApiClient() - mocker.patch.object(client, "call_api") - return client - - -def create_mock_response( +def _make_mock_response( data: dict[str, Any] | list[Any] | None = None, status: int = 200, headers: dict[str, str] | None = None, ) -> RESTResponse: - """Create a mock REST response for testing. + """Internal helper to create a mock REST response. Args: data: The response data (will be JSON-encoded) @@ -66,9 +56,59 @@ def mock_getheaders() -> dict[str, str]: @pytest.fixture -def mock_rest_response(): - """Fixture that provides the create_mock_response function.""" - return create_mock_response +def mock_api_client(mocker): + """Create a mock ApiClient for testing API methods.""" + from ibutsu_client.api_client import ApiClient + + client = ApiClient() + mocker.patch.object(client, "call_api") + return client + + +@pytest.fixture +def create_mock_response(request): + """Parametrized fixture for creating mock API responses. + + Use with indirect parametrization: + + Example: + @pytest.mark.parametrize('create_mock_response', [ + {'data': {'id': 'test'}, 'status': 200}, + {'data': {'error': 'not found'}, 'status': 404}, + ], indirect=True) + def test_api_method(self, mocker, create_mock_response): + api = SomeApi() + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) + result = api.method() + ... + + Args: + request.param: Dict with keys: + - data: Response data dict/list (required) + - status: HTTP status code (default: 200) + - headers: Response headers dict (optional) + + Returns: + Mock RESTResponse object ready to use + """ + params = request.param + data = params.get("data", {}) + status = params.get("status", 200) + headers = params.get("headers", None) + + return _make_mock_response(data=data, status=status, headers=headers) + + +# Common error response templates for parametrization +COMMON_ERROR_RESPONSES = { + "not_found": {"data": {"error": "not found"}, "status": 404}, + "unauthorized": {"data": {"error": "unauthorized"}, "status": 401}, + "forbidden": {"data": {"error": "forbidden"}, "status": 403}, + "bad_request": {"data": {"error": "bad request"}, "status": 400}, + "conflict": {"data": {"error": "conflict"}, "status": 409}, + "server_error": {"data": {"error": "internal error"}, "status": 500}, + "no_content": {"data": {}, "status": 204}, +} # ==================== Test Data Factories ==================== diff --git a/test/test_admin_user_management_api.py b/test/test_admin_user_management_api.py index 1a7c86f..fefd7ee 100644 --- a/test/test_admin_user_management_api.py +++ b/test/test_admin_user_management_api.py @@ -15,7 +15,7 @@ from ibutsu_client.exceptions import NotFoundException, ServiceException from ibutsu_client.models.user import User from ibutsu_client.models.user_list import UserList -from test.conftest import create_mock_response +from test import create_mock_response class TestAdminUserManagementApi: diff --git a/test/test_group_api.py b/test/test_group_api.py index ae258b5..0f4a0da 100644 --- a/test/test_group_api.py +++ b/test/test_group_api.py @@ -15,7 +15,7 @@ from ibutsu_client.exceptions import NotFoundException, ServiceException from ibutsu_client.models.group import Group from ibutsu_client.models.group_list import GroupList -from test.conftest import create_mock_response +from test import create_mock_response class TestGroupApi: diff --git a/test/test_health_api.py b/test/test_health_api.py index f8a8a31..347d13f 100644 --- a/test/test_health_api.py +++ b/test/test_health_api.py @@ -15,7 +15,7 @@ from ibutsu_client.exceptions import ServiceException from ibutsu_client.models.health import Health from ibutsu_client.models.health_info import HealthInfo -from test.conftest import create_mock_response +from test import create_mock_response class TestHealthApi: diff --git a/test/test_import_api.py b/test/test_import_api.py index 6e5c9c2..59bdd1e 100644 --- a/test/test_import_api.py +++ b/test/test_import_api.py @@ -14,7 +14,7 @@ from ibutsu_client.api.import_api import ImportApi from ibutsu_client.exceptions import NotFoundException, ServiceException from ibutsu_client.models.model_import import ModelImport -from test.conftest import create_mock_response +from test import create_mock_response class TestImportApi: diff --git a/test/test_login_api.py b/test/test_login_api.py index fd814df..60dccf9 100644 --- a/test/test_login_api.py +++ b/test/test_login_api.py @@ -16,7 +16,7 @@ from ibutsu_client.models.login_config import LoginConfig from ibutsu_client.models.login_support import LoginSupport from ibutsu_client.models.login_token import LoginToken -from test.conftest import create_mock_response +from test import create_mock_response class TestLoginApi: diff --git a/test/test_task_api.py b/test/test_task_api.py index 0c460b3..9686cf4 100644 --- a/test/test_task_api.py +++ b/test/test_task_api.py @@ -13,7 +13,7 @@ from ibutsu_client.api.task_api import TaskApi from ibutsu_client.exceptions import NotFoundException, ServiceException -from test.conftest import create_mock_response +from test import create_mock_response class TestTaskApi: diff --git a/test/test_user_api.py b/test/test_user_api.py index d7201ac..40860be 100644 --- a/test/test_user_api.py +++ b/test/test_user_api.py @@ -17,7 +17,7 @@ from ibutsu_client.models.token import Token from ibutsu_client.models.token_list import TokenList from ibutsu_client.models.user import User -from test.conftest import create_mock_response +from test import create_mock_response class TestUserApi: diff --git a/test/test_widget_api.py b/test/test_widget_api.py index 62620bd..7fb7145 100644 --- a/test/test_widget_api.py +++ b/test/test_widget_api.py @@ -14,100 +14,97 @@ from ibutsu_client.api.widget_api import WidgetApi from ibutsu_client.exceptions import NotFoundException, ServiceException from ibutsu_client.models.widget_type_list import WidgetTypeList -from test.conftest import create_mock_response class TestWidgetApi: """WidgetApi comprehensive tests""" - def test_get_widget_success(self, mocker): - """Test case for get_widget - successfully generate widget data""" - api = WidgetApi() - widget_data = { - "type": "result-summary", - "data": { - "passed": 100, - "failed": 5, - "skipped": 2, - "error": 0, - }, - } - mock_response = create_mock_response(widget_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - - widget_id = "550e8400-e29b-41d4-a716-446655440000" - result = api.get_widget(id=widget_id) - - assert result is not None - assert result["type"] == "result-summary" - assert result["data"]["passed"] == 100 - api.api_client.call_api.assert_called_once() - - def test_get_widget_with_filters(self, mocker): - """Test case for get_widget with filter parameters""" - api = WidgetApi() - widget_data = { - "type": "jenkins-heatmap", - "data": {"rows": [], "columns": []}, - } - mock_response = create_mock_response(widget_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - - widget_id = "550e8400-e29b-41d4-a716-446655440000" - result = api.get_widget( - id=widget_id, - params={"project": "test-project", "env": "production"}, - ) - - assert result is not None - assert result["type"] == "jenkins-heatmap" - api.api_client.call_api.assert_called_once() - - def test_get_widget_with_additional_params(self, mocker): - """Test case for get_widget with additional parameters""" - api = WidgetApi() - widget_data = { - "type": "result-aggregation", - "data": {"aggregations": []}, - } - mock_response = create_mock_response(widget_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - - widget_id = "550e8400-e29b-41d4-a716-446655440000" - result = api.get_widget( - id=widget_id, - params={"group_by": "component", "limit": 10}, - ) - - assert result is not None - api.api_client.call_api.assert_called_once() - - def test_get_widget_not_found(self, mocker): - """Test case for get_widget with invalid widget name""" - api = WidgetApi() - mock_response = create_mock_response({"error": "widget not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - - widget_id = "550e8400-e29b-41d4-a716-446655440000" - with pytest.raises(NotFoundException): - api.get_widget(id=widget_id) - - def test_get_widget_server_error(self, mocker): - """Test case for get_widget with server error""" + # Parametrized tests for get_widget with various scenarios + @pytest.mark.parametrize( + "create_mock_response,widget_params,expected_type,expected_exception", + [ + pytest.param( + { + "data": { + "type": "result-summary", + "data": {"passed": 100, "failed": 5, "skipped": 2, "error": 0}, + }, + "status": 200, + }, + {}, + "result-summary", + None, + id="success_basic", + ), + pytest.param( + { + "data": {"type": "jenkins-heatmap", "data": {"rows": [], "columns": []}}, + "status": 200, + }, + {"params": {"project": "test-project", "env": "production"}}, + "jenkins-heatmap", + None, + id="success_with_filters", + ), + pytest.param( + { + "data": {"type": "result-aggregation", "data": {"aggregations": []}}, + "status": 200, + }, + {"params": {"group_by": "component", "limit": 10}}, + "result-aggregation", + None, + id="success_with_params", + ), + pytest.param( + {"data": {"error": "widget not found"}, "status": 404}, + {}, + None, + NotFoundException, + id="not_found", + ), + pytest.param( + {"data": {"error": "internal error"}, "status": 500}, + {}, + None, + ServiceException, + id="server_error", + ), + ], + indirect=["create_mock_response"], + ) + def test_get_widget( + self, mocker, create_mock_response, widget_params, expected_type, expected_exception + ): + """Test get_widget with various response scenarios.""" api = WidgetApi() - mock_response = create_mock_response({"error": "internal error"}, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" - with pytest.raises(ServiceException): - api.get_widget(id=widget_id) - def test_get_widget_with_http_info(self, mocker): - """Test case for get_widget_with_http_info""" + if expected_exception: + with pytest.raises(expected_exception): + api.get_widget(id=widget_id, **widget_params) + else: + result = api.get_widget(id=widget_id, **widget_params) + assert result is not None + assert result["type"] == expected_type + api.api_client.call_api.assert_called_once() + + @pytest.mark.parametrize( + "create_mock_response", + [ + pytest.param( + {"data": {"type": "test-widget", "data": {}}, "status": 200}, + id="http_info_success", + ), + ], + indirect=True, + ) + def test_get_widget_with_http_info(self, mocker, create_mock_response): + """Test get_widget_with_http_info.""" api = WidgetApi() - widget_data = {"type": "test-widget", "data": {}} - mock_response = create_mock_response(widget_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_widget_with_http_info(id=widget_id) @@ -115,74 +112,95 @@ def test_get_widget_with_http_info(self, mocker): assert result.status_code == 200 assert result.data is not None - def test_get_widget_types_success(self, mocker): - """Test case for get_widget_types - retrieve list of available widget types""" - api = WidgetApi() - widget_types_data = { - "types": [ - { - "name": "result-summary", - "description": "Summary of test results", - "params": [], - }, + # Parametrized tests for get_widget_types + @pytest.mark.parametrize( + "create_mock_response,expected_count,expected_exception", + [ + pytest.param( { - "name": "jenkins-heatmap", - "description": "Jenkins build heatmap", - "params": [], + "data": { + "types": [ + { + "name": "result-summary", + "description": "Summary of test results", + "params": [], + }, + { + "name": "jenkins-heatmap", + "description": "Jenkins build heatmap", + "params": [], + }, + { + "name": "result-aggregation", + "description": "Aggregated test results", + "params": [], + }, + ] + }, + "status": 200, }, + 3, + None, + id="success_multiple_types", + ), + pytest.param( + {"data": {"types": []}, "status": 200}, + 0, + None, + id="success_empty", + ), + pytest.param( + {"data": {"error": "internal error"}, "status": 500}, + None, + ServiceException, + id="server_error", + ), + ], + indirect=["create_mock_response"], + ) + def test_get_widget_types( + self, mocker, create_mock_response, expected_count, expected_exception + ): + """Test get_widget_types with various response scenarios.""" + api = WidgetApi() + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) + + if expected_exception: + with pytest.raises(expected_exception): + api.get_widget_types() + else: + result = api.get_widget_types() + assert isinstance(result, WidgetTypeList) + assert len(result.types) == expected_count + api.api_client.call_api.assert_called_once() + + @pytest.mark.parametrize( + "create_mock_response", + [ + pytest.param( { - "name": "result-aggregation", - "description": "Aggregated test results", - "params": [], + "data": { + "types": [ + { + "name": "result-summary", + "description": "Summary", + "params": [], + } + ] + }, + "status": 200, }, - ] - } - mock_response = create_mock_response(widget_types_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - - result = api.get_widget_types() - - assert isinstance(result, WidgetTypeList) - assert len(result.types) == 3 - api.api_client.call_api.assert_called_once() - - def test_get_widget_types_empty(self, mocker): - """Test case for get_widget_types with no types available""" - api = WidgetApi() - widget_types_data = {"types": []} - mock_response = create_mock_response(widget_types_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - - result = api.get_widget_types() - - assert isinstance(result, WidgetTypeList) - assert len(result.types) == 0 - - def test_get_widget_types_with_http_info(self, mocker): - """Test case for get_widget_types_with_http_info""" + id="http_info_success", + ), + ], + indirect=True, + ) + def test_get_widget_types_with_http_info(self, mocker, create_mock_response): + """Test get_widget_types_with_http_info.""" api = WidgetApi() - widget_types_data = { - "types": [ - { - "name": "result-summary", - "description": "Summary", - "params": [], - } - ] - } - mock_response = create_mock_response(widget_types_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_widget_types_with_http_info() assert result.status_code == 200 assert isinstance(result.data, WidgetTypeList) - - def test_get_widget_types_server_error(self, mocker): - """Test case for get_widget_types with server error""" - api = WidgetApi() - mock_response = create_mock_response({"error": "internal error"}, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - - with pytest.raises(ServiceException): - api.get_widget_types() diff --git a/test/test_widget_config_api.py b/test/test_widget_config_api.py index 51a9129..0837208 100644 --- a/test/test_widget_config_api.py +++ b/test/test_widget_config_api.py @@ -15,7 +15,7 @@ from ibutsu_client.exceptions import NotFoundException, ServiceException from ibutsu_client.models.widget_config import WidgetConfig from ibutsu_client.models.widget_config_list import WidgetConfigList -from test.conftest import create_mock_response +from test import create_mock_response class TestWidgetConfigApi: @@ -24,15 +24,15 @@ class TestWidgetConfigApi: def test_add_widget_config_success(self, mocker, sample_widget_config_data): """Test case for add_widget_config - successfully create a widget config""" api = WidgetConfigApi() - widget_data = sample_widget_config_data(widget_type="result-summary", weight=0) + widget_data = sample_widget_config_data(widget="result-summary", weight=0) mock_response = create_mock_response(widget_data, status=201) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - widget_config = WidgetConfig(widget_type="result-summary", weight=0, params={}) + widget_config = WidgetConfig(type="widget", widget="result-summary", weight=0, params={}) result = api.add_widget_config(widget_config=widget_config) assert isinstance(result, WidgetConfig) - assert result.widget_type == "result-summary" + assert result.widget == "result-summary" assert result.weight == 0 api.api_client.call_api.assert_called_once() @@ -41,12 +41,14 @@ def test_add_widget_config_with_params(self, mocker, sample_widget_config_data): api = WidgetConfigApi() params = {"filter": "result:passed", "chart_type": "bar"} widget_data = sample_widget_config_data( - widget_type="result-aggregation", weight=5, params=params + widget="result-aggregation", weight=5, params=params ) mock_response = create_mock_response(widget_data, status=201) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - widget_config = WidgetConfig(widget_type="result-aggregation", weight=5, params=params) + widget_config = WidgetConfig( + type="widget", widget="result-aggregation", weight=5, params=params + ) result = api.add_widget_config(widget_config=widget_config) assert isinstance(result, WidgetConfig) @@ -58,7 +60,7 @@ def test_add_widget_config_unauthorized(self, mocker): mock_response = create_mock_response({"error": "unauthorized"}, status=401) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - widget_config = WidgetConfig(widget_type="test", weight=0) + widget_config = WidgetConfig(type="widget", widget="test", weight=0) with pytest.raises((ServiceException, Exception)): api.add_widget_config(widget_config=widget_config) @@ -69,7 +71,7 @@ def test_add_widget_config_with_http_info(self, mocker, sample_widget_config_dat mock_response = create_mock_response(widget_data, status=201) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - widget_config = WidgetConfig(widget_type="test", weight=0) + widget_config = WidgetConfig(type="widget", widget="test", weight=0) result = api.add_widget_config_with_http_info(widget_config=widget_config) assert result.status_code == 201 @@ -111,7 +113,7 @@ def test_delete_widget_config_with_http_info(self, mocker): def test_get_widget_config_success(self, mocker, sample_widget_config_data): """Test case for get_widget_config - retrieve a single widget config""" api = WidgetConfigApi() - widget_data = sample_widget_config_data(widget_type="jenkins-heatmap") + widget_data = sample_widget_config_data(widget="jenkins-heatmap") mock_response = create_mock_response(widget_data, status=200) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) @@ -119,7 +121,7 @@ def test_get_widget_config_success(self, mocker, sample_widget_config_data): result = api.get_widget_config(id=widget_id) assert isinstance(result, WidgetConfig) - assert result.widget_type == "jenkins-heatmap" + assert result.widget == "jenkins-heatmap" def test_get_widget_config_not_found(self, mocker): """Test case for get_widget_config with non-existent widget""" @@ -149,8 +151,8 @@ def test_get_widget_config_list_success( ): """Test case for get_widget_config_list - retrieve list of widget configs""" api = WidgetConfigApi() - widget1 = sample_widget_config_data(widget_type="result-summary", weight=0) - widget2 = sample_widget_config_data(widget_type="jenkins-heatmap", weight=1) + widget1 = sample_widget_config_data(widget="result-summary", weight=0) + widget2 = sample_widget_config_data(widget="jenkins-heatmap", weight=1) pagination = sample_pagination_data(total_items=2) response_data = { @@ -160,8 +162,7 @@ def test_get_widget_config_list_success( mock_response = create_mock_response(response_data, status=200) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - dashboard_id = "550e8400-e29b-41d4-a716-446655440000" - result = api.get_widget_config_list(dashboard_id=dashboard_id) + result = api.get_widget_config_list() assert isinstance(result, WidgetConfigList) assert len(result.widgets) == 2 @@ -178,10 +179,7 @@ def test_get_widget_config_list_with_filters( mock_response = create_mock_response(response_data, status=200) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - dashboard_id = "550e8400-e29b-41d4-a716-446655440000" - result = api.get_widget_config_list( - dashboard_id=dashboard_id, filter=["widget_type=result-summary"] - ) + result = api.get_widget_config_list(filter=["widget_type=result-summary"]) assert isinstance(result, WidgetConfigList) api.api_client.call_api.assert_called_once() @@ -194,8 +192,7 @@ def test_get_widget_config_list_empty(self, mocker, sample_pagination_data): mock_response = create_mock_response(response_data, status=200) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - dashboard_id = "550e8400-e29b-41d4-a716-446655440000" - result = api.get_widget_config_list(dashboard_id=dashboard_id) + result = api.get_widget_config_list() assert isinstance(result, WidgetConfigList) assert len(result.widgets) == 0 @@ -208,8 +205,7 @@ def test_get_widget_config_list_with_http_info(self, mocker, sample_pagination_d mock_response = create_mock_response(response_data, status=200) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) - dashboard_id = "550e8400-e29b-41d4-a716-446655440000" - result = api.get_widget_config_list_with_http_info(dashboard_id=dashboard_id) + result = api.get_widget_config_list_with_http_info() assert result.status_code == 200 assert isinstance(result.data, WidgetConfigList) @@ -217,12 +213,12 @@ def test_get_widget_config_list_with_http_info(self, mocker, sample_pagination_d def test_update_widget_config_success(self, mocker, sample_widget_config_data): """Test case for update_widget_config - successfully update a widget config""" api = WidgetConfigApi() - updated_data = sample_widget_config_data(widget_type="result-summary", weight=10) + updated_data = sample_widget_config_data(widget="result-summary", weight=10) mock_response = create_mock_response(updated_data, status=200) mocker.patch.object(api.api_client, "call_api", return_value=mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" - widget_config = WidgetConfig(widget_type="result-summary", weight=10) + widget_config = WidgetConfig(type="widget", widget="result-summary", weight=10) result = api.update_widget_config(id=widget_id, widget_config=widget_config) assert isinstance(result, WidgetConfig) @@ -235,7 +231,7 @@ def test_update_widget_config_not_found(self, mocker): mocker.patch.object(api.api_client, "call_api", return_value=mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" - widget_config = WidgetConfig(widget_type="test", weight=0) + widget_config = WidgetConfig(type="widget", widget="test", weight=0) with pytest.raises(NotFoundException): api.update_widget_config(id=widget_id, widget_config=widget_config) @@ -247,7 +243,7 @@ def test_update_widget_config_with_http_info(self, mocker, sample_widget_config_ mocker.patch.object(api.api_client, "call_api", return_value=mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" - widget_config = WidgetConfig(widget_type="test", weight=5) + widget_config = WidgetConfig(type="widget", widget="test", weight=5) result = api.update_widget_config_with_http_info(id=widget_id, widget_config=widget_config) assert result.status_code == 200 @@ -260,6 +256,6 @@ def test_update_widget_config_server_error(self, mocker): mocker.patch.object(api.api_client, "call_api", return_value=mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" - widget_config = WidgetConfig(widget_type="test", weight=0) + widget_config = WidgetConfig(type="widget", widget="test", weight=0) with pytest.raises(ServiceException): api.update_widget_config(id=widget_id, widget_config=widget_config) From 9c20c028d1bbd3d2ac4e15bbdf0a84b195e2be95 Mon Sep 17 00:00:00 2001 From: mshriver Date: Mon, 24 Nov 2025 15:25:39 -0500 Subject: [PATCH 3/3] Adding api module coverage Use sample_* functions to provide data during parametrization into the mock_response fixture --- pyproject.toml | 1 + test/__init__.py | 51 --- test/conftest.py | 501 +--------------------- test/test_admin_project_management_api.py | 124 ++++-- test/test_admin_user_management_api.py | 262 +++++++---- test/test_artifact_api.py | 137 ++++-- test/test_dashboard_api.py | 124 ++++-- test/test_group_api.py | 208 ++++++--- test/test_health_api.py | 88 ++-- test/test_import_api.py | 247 +++++++---- test/test_login_api.py | 242 +++++++---- test/test_project_api.py | 132 ++++-- test/test_result_api.py | 128 ++++-- test/test_run_api.py | 151 +++++-- test/test_task_api.py | 223 ++++++---- test/test_user_api.py | 250 +++++++---- test/test_widget_config_api.py | 272 ++++++++---- test/utils.py | 372 ++++++++++++++++ 18 files changed, 2136 insertions(+), 1377 deletions(-) create mode 100644 test/utils.py diff --git a/pyproject.toml b/pyproject.toml index 809dd45..b960d20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ Tracker = "https://github.com/ibutsu/ibutsu-client-python/issues" test = [ "pytest", "pytest-cov", + "pytest-mock", "coverage[toml]", ] dev = [ diff --git a/test/__init__.py b/test/__init__.py index 1d6190d..dd9545f 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,52 +1 @@ """Test utilities for ibutsu_client tests.""" - -import json -from typing import Any -from unittest.mock import Mock - -from ibutsu_client.rest import RESTResponse - - -def create_mock_response( - data: dict[str, Any] | list[Any] | None = None, - status: int = 200, - headers: dict[str, str] | None = None, -) -> RESTResponse: - """Create a mock REST response for testing. - - Args: - data: The response data (will be JSON-encoded) - status: HTTP status code - headers: Response headers - - Returns: - A mock RESTResponse object - """ - if headers is None: - headers = {"Content-Type": "application/json; charset=utf-8"} - - if data is None: - data = {} - - response = Mock(spec=RESTResponse) - response.status = status - response.headers = headers - response.data = json.dumps(data).encode("utf-8") - response.reason = "OK" if status < 400 else "Error" - - def mock_read(): - """Mock the read method to decode the response data.""" - return response.data - - def mock_getheader(name: str, default: str | None = None) -> str | None: - """Mock the getheader method.""" - return headers.get(name, default) - - def mock_getheaders() -> dict[str, str]: - """Mock the getheaders method.""" - return headers - - response.read = mock_read - response.getheader = mock_getheader - response.getheaders = mock_getheaders - return response diff --git a/test/conftest.py b/test/conftest.py index 0252ca1..627bf93 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,7 +1,6 @@ """Test configuration and fixtures for ibutsu_client tests.""" import json -import uuid from typing import Any from unittest.mock import Mock @@ -11,14 +10,14 @@ def _make_mock_response( - data: dict[str, Any] | list[Any] | None = None, + data: dict[str, Any] | list[Any] | bytes | None = None, status: int = 200, headers: dict[str, str] | None = None, ) -> RESTResponse: """Internal helper to create a mock REST response. Args: - data: The response data (will be JSON-encoded) + data: The response data (will be JSON-encoded unless bytes) status: HTTP status code headers: Response headers @@ -34,7 +33,11 @@ def _make_mock_response( response = Mock(spec=RESTResponse) response.status = status response.headers = headers - response.data = json.dumps(data).encode("utf-8") + # Handle bytes data directly without JSON encoding + if isinstance(data, bytes): + response.data = data + else: + response.data = json.dumps(data).encode("utf-8") response.reason = "OK" if status < 400 else "Error" def mock_read(): @@ -56,12 +59,12 @@ def mock_getheaders() -> dict[str, str]: @pytest.fixture -def mock_api_client(mocker): +def mock_api_client(): """Create a mock ApiClient for testing API methods.""" from ibutsu_client.api_client import ApiClient client = ApiClient() - mocker.patch.object(client, "call_api") + client.call_api = Mock() return client @@ -69,11 +72,13 @@ def mock_api_client(mocker): def create_mock_response(request): """Parametrized fixture for creating mock API responses. - Use with indirect parametrization: + Use with indirect parametrization. Call factory functions directly in the parametrize decorator: Example: + from test.utils import sample_project_data + @pytest.mark.parametrize('create_mock_response', [ - {'data': {'id': 'test'}, 'status': 200}, + {'data': sample_project_data(name='test', title='Test'), 'status': 201}, {'data': {'error': 'not found'}, 'status': 404}, ], indirect=True) def test_api_method(self, mocker, create_mock_response): @@ -84,7 +89,7 @@ def test_api_method(self, mocker, create_mock_response): Args: request.param: Dict with keys: - - data: Response data dict/list (required) + - data: Response data dict/list/bytes - status: HTTP status code (default: 200) - headers: Response headers dict (optional) @@ -97,481 +102,3 @@ def test_api_method(self, mocker, create_mock_response): headers = params.get("headers", None) return _make_mock_response(data=data, status=status, headers=headers) - - -# Common error response templates for parametrization -COMMON_ERROR_RESPONSES = { - "not_found": {"data": {"error": "not found"}, "status": 404}, - "unauthorized": {"data": {"error": "unauthorized"}, "status": 401}, - "forbidden": {"data": {"error": "forbidden"}, "status": 403}, - "bad_request": {"data": {"error": "bad request"}, "status": 400}, - "conflict": {"data": {"error": "conflict"}, "status": 409}, - "server_error": {"data": {"error": "internal error"}, "status": 500}, - "no_content": {"data": {}, "status": 204}, -} - - -# ==================== Test Data Factories ==================== - - -@pytest.fixture -def sample_project_data(): - """Factory function to create sample project data. - - Returns: - A function that creates project data dictionaries with realistic values. - """ - - def _create_project( - project_id: str | None = None, - name: str = "test-project", - title: str = "Test Project", - owner_id: str | None = None, - group_id: str | None = None, - ) -> dict[str, Any]: - """Create a sample project data dictionary. - - Args: - project_id: Project UUID (generated if not provided) - name: Machine name of the project - title: Human-readable title - owner_id: Owner UUID - group_id: Group UUID - - Returns: - Dictionary with project data - """ - if project_id is None: - project_id = str(uuid.uuid4()) - if owner_id is None: - owner_id = str(uuid.uuid4()) - if group_id is None: - group_id = str(uuid.uuid4()) - - return { - "id": project_id, - "name": name, - "title": title, - "owner_id": owner_id, - "group_id": group_id, - } - - return _create_project - - -@pytest.fixture -def sample_run_data(): - """Factory function to create sample test run data. - - Returns: - A function that creates run data dictionaries with realistic values. - """ - - def _create_run( - run_id: str | None = None, - project_id: str | None = None, - created: str = "2024-01-15T10:00:00", - start_time: str = "2024-01-15T10:00:00", - duration: float = 120.5, - source: str = "pytest", - component: str = "api", - env: str = "test", - summary: dict[str, Any] | None = None, - metadata: dict[str, Any] | None = None, - ) -> dict[str, Any]: - """Create a sample run data dictionary. - - Args: - run_id: Run UUID (generated if not provided) - project_id: Project UUID (generated if not provided) - created: ISO timestamp of creation - start_time: ISO timestamp of run start - duration: Duration in seconds - source: Source system identifier - component: Component under test - env: Test environment - summary: Summary statistics - metadata: Additional metadata - - Returns: - Dictionary with run data - """ - if run_id is None: - run_id = str(uuid.uuid4()) - if project_id is None: - project_id = str(uuid.uuid4()) - if summary is None: - summary = {"passed": 10, "failed": 2, "skipped": 1, "errors": 0, "xfailed": 0} - if metadata is None: - metadata = {"jenkins_build": "123", "branch": "main"} - - return { - "id": run_id, - "project_id": project_id, - "created": created, - "start_time": start_time, - "duration": duration, - "source": source, - "component": component, - "env": env, - "summary": summary, - "metadata": metadata, - } - - return _create_run - - -@pytest.fixture -def sample_result_data(): - """Factory function to create sample test result data. - - Returns: - A function that creates result data dictionaries with realistic values. - """ - - def _create_result( - result_id: str | None = None, - run_id: str | None = None, - project_id: str | None = None, - test_id: str = "test_example.py::TestClass::test_method", - start_time: str = "2024-01-15T10:00:00", - duration: float = 1.5, - result: str = "passed", - component: str = "api", - env: str = "test", - source: str = "pytest", - metadata: dict[str, Any] | None = None, - params: dict[str, Any] | None = None, - ) -> dict[str, Any]: - """Create a sample result data dictionary. - - Args: - result_id: Result UUID (generated if not provided) - run_id: Associated run UUID (generated if not provided) - project_id: Project UUID (generated if not provided) - test_id: Test identifier - start_time: ISO timestamp - duration: Duration in seconds - result: Test result status (passed, failed, error, skipped, etc.) - component: Component under test - env: Test environment - source: Source system identifier - metadata: Additional metadata - params: Test parameters - - Returns: - Dictionary with result data - """ - if result_id is None: - result_id = str(uuid.uuid4()) - if run_id is None: - run_id = str(uuid.uuid4()) - if project_id is None: - project_id = str(uuid.uuid4()) - if metadata is None: - metadata = {"test_file": "test_example.py", "line_number": 42} - if params is None: - params = {} - - return { - "id": result_id, - "run_id": run_id, - "project_id": project_id, - "test_id": test_id, - "start_time": start_time, - "duration": duration, - "result": result, - "component": component, - "env": env, - "source": source, - "metadata": metadata, - "params": params, - } - - return _create_result - - -@pytest.fixture -def sample_artifact_data(): - """Factory function to create sample artifact data. - - Returns: - A function that creates artifact data dictionaries with realistic values. - """ - - def _create_artifact( - artifact_id: str | None = None, - filename: str = "test_log.txt", - result_id: str | None = None, - run_id: str | None = None, - project_id: str | None = None, - ) -> dict[str, Any]: - """Create a sample artifact data dictionary. - - Args: - artifact_id: Artifact UUID (generated if not provided) - filename: Artifact filename - result_id: Associated result UUID - run_id: Associated run UUID - project_id: Project UUID - - Returns: - Dictionary with artifact data - """ - if artifact_id is None: - artifact_id = str(uuid.uuid4()) - if result_id is None: - result_id = str(uuid.uuid4()) - if run_id is None: - run_id = str(uuid.uuid4()) - if project_id is None: - project_id = str(uuid.uuid4()) - - return { - "id": artifact_id, - "filename": filename, - "result_id": result_id, - "run_id": run_id, - "project_id": project_id, - } - - return _create_artifact - - -@pytest.fixture -def sample_pagination_data(): - """Factory function to create sample pagination data. - - Returns: - A function that creates pagination data for list responses. - """ - - def _create_pagination( - page: int = 1, - page_size: int = 25, - total_items: int = 100, - total_pages: int = 4, - ) -> dict[str, Any]: - """Create sample pagination data. - - Args: - page: Current page number - page_size: Number of items per page - total_items: Total number of items - total_pages: Total number of pages - - Returns: - Dictionary with pagination data - """ - return { - "page": page, - "pageSize": page_size, - "totalItems": total_items, - "totalPages": total_pages, - } - - return _create_pagination - - -@pytest.fixture -def sample_user_data(): - """Factory function to create sample user data. - - Returns: - A function that creates user data dictionaries with realistic values. - """ - - def _create_user( - user_id: str | None = None, - email: str = "test@example.com", - name: str = "Test User", - is_superadmin: bool = False, - is_active: bool = True, - ) -> dict[str, Any]: - """Create a sample user data dictionary. - - Args: - user_id: User UUID (generated if not provided) - email: User email address - name: User full name - is_superadmin: Whether user is a superadmin - is_active: Whether user account is active - - Returns: - Dictionary with user data - """ - if user_id is None: - user_id = str(uuid.uuid4()) - - return { - "id": user_id, - "email": email, - "name": name, - "is_superadmin": is_superadmin, - "is_active": is_active, - } - - return _create_user - - -@pytest.fixture -def sample_dashboard_data(): - """Factory function to create sample dashboard data. - - Returns: - A function that creates dashboard data dictionaries with realistic values. - """ - - def _create_dashboard( - dashboard_id: str | None = None, - title: str = "Test Dashboard", - project_id: str | None = None, - widgets: list[dict[str, Any]] | None = None, - ) -> dict[str, Any]: - """Create a sample dashboard data dictionary. - - Args: - dashboard_id: Dashboard UUID (generated if not provided) - title: Dashboard title - project_id: Project UUID (generated if not provided) - widgets: List of widget configurations - - Returns: - Dictionary with dashboard data - """ - if dashboard_id is None: - dashboard_id = str(uuid.uuid4()) - if project_id is None: - project_id = str(uuid.uuid4()) - if widgets is None: - widgets = [] - - return { - "id": dashboard_id, - "title": title, - "project_id": project_id, - "widgets": widgets, - } - - return _create_dashboard - - -@pytest.fixture -def sample_widget_config_data(): - """Factory function to create sample widget configuration data. - - Returns: - A function that creates widget config data dictionaries with realistic values. - """ - - def _create_widget_config( - widget_id: str | None = None, - widget: str = "result-summary", - config_type: str = "widget", - weight: int = 0, - params: dict[str, Any] | None = None, - title: str | None = None, - ) -> dict[str, Any]: - """Create a sample widget config data dictionary. - - Args: - widget_id: Widget UUID (generated if not provided) - widget: Widget name to render - config_type: Type of config ("widget" or "view") - weight: Widget display weight/order - params: Widget parameters - title: Widget title - - Returns: - Dictionary with widget config data - """ - if widget_id is None: - widget_id = str(uuid.uuid4()) - if params is None: - params = {} - - return { - "id": widget_id, - "type": config_type, - "widget": widget, - "weight": weight, - "params": params, - "title": title, - } - - return _create_widget_config - - -@pytest.fixture -def sample_group_data(): - """Factory function to create sample group data. - - Returns: - A function that creates group data dictionaries with realistic values. - """ - - def _create_group( - group_id: str | None = None, - name: str = "test-group", - ) -> dict[str, Any]: - """Create a sample group data dictionary. - - Args: - group_id: Group UUID (generated if not provided) - name: Group name - - Returns: - Dictionary with group data - """ - if group_id is None: - group_id = str(uuid.uuid4()) - - return { - "id": group_id, - "name": name, - } - - return _create_group - - -@pytest.fixture -def sample_token_data(): - """Factory function to create sample token data. - - Returns: - A function that creates token data dictionaries with realistic values. - """ - - def _create_token( - token_id: str | None = None, - user_id: str | None = None, - name: str = "test-token", - token: str = "test-token-value", - expires: str | None = "2025-12-31", - ) -> dict[str, Any]: - """Create a sample token data dictionary. - - Args: - token_id: Token UUID (generated if not provided) - user_id: User UUID (generated if not provided) - name: Token name/identifier - token: The actual token string - expires: Expiration date - - Returns: - Dictionary with token data - """ - if token_id is None: - token_id = str(uuid.uuid4()) - if user_id is None: - user_id = str(uuid.uuid4()) - - return { - "id": token_id, - "user_id": user_id, - "name": name, - "token": token, - "expires": expires, - } - - return _create_token diff --git a/test/test_admin_project_management_api.py b/test/test_admin_project_management_api.py index b159f9e..8acf403 100644 --- a/test/test_admin_project_management_api.py +++ b/test/test_admin_project_management_api.py @@ -3,6 +3,8 @@ from urllib.parse import parse_qs, urlparse from uuid import uuid4 +import pytest + from ibutsu_client.api.admin_project_management_api import AdminProjectManagementApi from ibutsu_client.models.project import Project from ibutsu_client.models.project_list import ProjectList @@ -11,19 +13,30 @@ class TestAdminProjectManagementApi: """AdminProjectManagementApi Tests""" - def test_admin_add_project(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "PROJECT_ID_PLACEHOLDER", + "name": "New Project", + "title": "New Project Title", + }, + "status": 201, + } + ], + indirect=True, + ) + def test_admin_add_project(self, mock_api_client, create_mock_response): """Test case for admin_add_project""" api = AdminProjectManagementApi(api_client=mock_api_client) project_id = uuid4() - project_data = { - "id": str(project_id), - "name": "New Project", - "title": "New Project Title", - } - # Mock the API response - mock_response = mock_rest_response(data=project_data, status=201) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual project_id + create_mock_response.data = create_mock_response.data.replace( + b"PROJECT_ID_PLACEHOLDER", str(project_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API new_project = Project(name="New Project", title="New Project Title") @@ -40,14 +53,18 @@ def test_admin_add_project(self, mock_api_client, mock_rest_response): assert args[0] == "POST" assert args[1].endswith("/admin/project") - def test_admin_delete_project(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 200}], + indirect=True, + ) + def test_admin_delete_project(self, mock_api_client, create_mock_response): """Test case for admin_delete_project""" api = AdminProjectManagementApi(api_client=mock_api_client) project_id = uuid4() # Mock the API response - mock_response = mock_rest_response(status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API api.admin_delete_project(id=project_id) @@ -58,18 +75,29 @@ def test_admin_delete_project(self, mock_api_client, mock_rest_response): assert args[0] == "DELETE" assert args[1].endswith(f"/admin/project/{project_id}") - def test_admin_get_project(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "PROJECT_ID_PLACEHOLDER", + "name": "My Project", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_admin_get_project(self, mock_api_client, create_mock_response): """Test case for admin_get_project""" api = AdminProjectManagementApi(api_client=mock_api_client) project_id = uuid4() - project_data = { - "id": str(project_id), - "name": "My Project", - } - # Mock the API response - mock_response = mock_rest_response(data=project_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual project_id + create_mock_response.data = create_mock_response.data.replace( + b"PROJECT_ID_PLACEHOLDER", str(project_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.admin_get_project(id=project_id) @@ -85,21 +113,28 @@ def test_admin_get_project(self, mock_api_client, mock_rest_response): assert args[0] == "GET" assert args[1].endswith(f"/admin/project/{project_id}") - def test_admin_get_project_list(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "projects": [ + {"id": "00000000-0000-0000-0000-000000000001", "name": "Project 1"}, + {"id": "00000000-0000-0000-0000-000000000002", "name": "Project 2"}, + ], + "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_admin_get_project_list(self, mock_api_client, create_mock_response): """Test case for admin_get_project_list""" api = AdminProjectManagementApi(api_client=mock_api_client) - project_list_data = { - "projects": [ - {"id": str(uuid4()), "name": "Project 1"}, - {"id": str(uuid4()), "name": "Project 2"}, - ], - "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, - } - # Mock the API response - mock_response = mock_rest_response(data=project_list_data, status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.admin_get_project_list(page=1, page_size=25) @@ -121,18 +156,29 @@ def test_admin_get_project_list(self, mock_api_client, mock_rest_response): assert query_params["page"] == ["1"] assert query_params["pageSize"] == ["25"] - def test_admin_update_project(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "PROJECT_ID_PLACEHOLDER", + "name": "Updated Project", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_admin_update_project(self, mock_api_client, create_mock_response): """Test case for admin_update_project""" api = AdminProjectManagementApi(api_client=mock_api_client) project_id = uuid4() - project_data = { - "id": str(project_id), - "name": "Updated Project", - } - # Mock the API response - mock_response = mock_rest_response(data=project_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual project_id + create_mock_response.data = create_mock_response.data.replace( + b"PROJECT_ID_PLACEHOLDER", str(project_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API update_project = Project(name="Updated Project") diff --git a/test/test_admin_user_management_api.py b/test/test_admin_user_management_api.py index fefd7ee..2d8db01 100644 --- a/test/test_admin_user_management_api.py +++ b/test/test_admin_user_management_api.py @@ -15,18 +15,21 @@ from ibutsu_client.exceptions import NotFoundException, ServiceException from ibutsu_client.models.user import User from ibutsu_client.models.user_list import UserList -from test import create_mock_response +from test.utils import sample_pagination_data, sample_user_data class TestAdminUserManagementApi: """AdminUserManagementApi comprehensive tests""" - def test_admin_add_user_success(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_user_data(email="newuser@example.com", name="New User"), "status": 201}], + indirect=True, + ) + def test_admin_add_user_success(self, mocker, create_mock_response): """Test case for admin_add_user - successfully add a user""" api = AdminUserManagementApi() - user_data = sample_user_data(email="newuser@example.com", name="New User") - mock_response = create_mock_response(user_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user = User(email="newuser@example.com", name="New User") result = api.admin_add_user(user=user) @@ -36,32 +39,43 @@ def test_admin_add_user_success(self, mocker, sample_user_data): assert result.name == "New User" api.api_client.call_api.assert_called_once() - def test_admin_add_user_unauthorized(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "unauthorized"}, "status": 403}], + indirect=True, + ) + def test_admin_add_user_unauthorized(self, mocker, create_mock_response): """Test case for admin_add_user without superadmin privileges""" api = AdminUserManagementApi() - mock_response = create_mock_response({"error": "unauthorized"}, status=403) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user = User(email="test@example.com", name="Test") with pytest.raises((ServiceException, Exception)): api.admin_add_user(user=user) - def test_admin_add_user_conflict(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "user already exists"}, "status": 409}], + indirect=True, + ) + def test_admin_add_user_conflict(self, mocker, create_mock_response): """Test case for admin_add_user with existing email""" api = AdminUserManagementApi() - mock_response = create_mock_response({"error": "user already exists"}, status=409) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user = User(email="existing@example.com", name="Existing User") with pytest.raises((ServiceException, Exception)): api.admin_add_user(user=user) - def test_admin_add_user_with_http_info(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_user_data(), "status": 201}], + indirect=True, + ) + def test_admin_add_user_with_http_info(self, mocker, create_mock_response): """Test case for admin_add_user_with_http_info""" api = AdminUserManagementApi() - user_data = sample_user_data() - mock_response = create_mock_response(user_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user = User(email="test@example.com", name="Test User") result = api.admin_add_user_with_http_info(user=user) @@ -69,11 +83,15 @@ def test_admin_add_user_with_http_info(self, mocker, sample_user_data): assert result.status_code == 201 assert isinstance(result.data, User) - def test_admin_delete_user_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 204}], + indirect=True, + ) + def test_admin_delete_user_success(self, mocker, create_mock_response): """Test case for admin_delete_user - successfully delete a user""" api = AdminUserManagementApi() - mock_response = create_mock_response({}, status=204) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" api.admin_delete_user(id=user_id) @@ -81,43 +99,63 @@ def test_admin_delete_user_success(self, mocker): # 204 No Content typically returns None api.api_client.call_api.assert_called_once() - def test_admin_delete_user_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_admin_delete_user_not_found(self, mocker, create_mock_response): """Test case for admin_delete_user with non-existent user""" api = AdminUserManagementApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(NotFoundException): api.admin_delete_user(id=user_id) - def test_admin_delete_user_forbidden(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "forbidden"}, "status": 403}], + indirect=True, + ) + def test_admin_delete_user_forbidden(self, mocker, create_mock_response): """Test case for admin_delete_user without superadmin privileges""" api = AdminUserManagementApi() - mock_response = create_mock_response({"error": "forbidden"}, status=403) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises((ServiceException, Exception)): api.admin_delete_user(id=user_id) - def test_admin_delete_user_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 204}], + indirect=True, + ) + def test_admin_delete_user_with_http_info(self, mocker, create_mock_response): """Test case for admin_delete_user_with_http_info""" api = AdminUserManagementApi() - mock_response = create_mock_response({}, status=204) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" result = api.admin_delete_user_with_http_info(id=user_id) assert result.status_code == 204 - def test_admin_get_user_success(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": sample_user_data(email="admin@example.com", is_superadmin=True), + "status": 200, + } + ], + indirect=True, + ) + def test_admin_get_user_success(self, mocker, create_mock_response): """Test case for admin_get_user - retrieve a single user""" api = AdminUserManagementApi() - user_data = sample_user_data(email="admin@example.com", is_superadmin=True) - mock_response = create_mock_response(user_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" result = api.admin_get_user(id=user_id) @@ -126,22 +164,29 @@ def test_admin_get_user_success(self, mocker, sample_user_data): assert result.email == "admin@example.com" assert result.is_superadmin is True - def test_admin_get_user_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_admin_get_user_not_found(self, mocker, create_mock_response): """Test case for admin_get_user with non-existent user""" api = AdminUserManagementApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(NotFoundException): api.admin_get_user(id=user_id) - def test_admin_get_user_with_http_info(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_user_data(), "status": 200}], + indirect=True, + ) + def test_admin_get_user_with_http_info(self, mocker, create_mock_response): """Test case for admin_get_user_with_http_info""" api = AdminUserManagementApi() - user_data = sample_user_data() - mock_response = create_mock_response(user_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" result = api.admin_get_user_with_http_info(id=user_id) @@ -149,74 +194,114 @@ def test_admin_get_user_with_http_info(self, mocker, sample_user_data): assert result.status_code == 200 assert isinstance(result.data, User) - def test_admin_get_user_list_success(self, mocker, sample_user_data, sample_pagination_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "users": [ + sample_user_data(email="user1@example.com", name="User One"), + sample_user_data(email="user2@example.com", name="User Two"), + ], + "pagination": sample_pagination_data(total_items=2), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_admin_get_user_list_success(self, mocker, create_mock_response): """Test case for admin_get_user_list - retrieve list of users""" api = AdminUserManagementApi() - user1 = sample_user_data(email="user1@example.com", name="User One") - user2 = sample_user_data(email="user2@example.com", name="User Two") - pagination = sample_pagination_data(total_items=2) - - response_data = {"users": [user1, user2], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.admin_get_user_list() assert isinstance(result, UserList) assert len(result.users) == 2 - def test_admin_get_user_list_with_pagination( - self, mocker, sample_user_data, sample_pagination_data - ): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "users": [sample_user_data()], + "pagination": sample_pagination_data(page=2, page_size=10, total_items=15), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_admin_get_user_list_with_pagination(self, mocker, create_mock_response): """Test case for admin_get_user_list with pagination parameters""" api = AdminUserManagementApi() - user1 = sample_user_data() - pagination = sample_pagination_data(page=2, page_size=10, total_items=15) - - response_data = {"users": [user1], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.admin_get_user_list(page=2, page_size=10) assert isinstance(result, UserList) api.api_client.call_api.assert_called_once() - def test_admin_get_user_list_with_filters( - self, mocker, sample_user_data, sample_pagination_data - ): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "users": [sample_user_data(is_superadmin=True)], + "pagination": sample_pagination_data(total_items=1), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_admin_get_user_list_with_filters(self, mocker, create_mock_response): """Test case for admin_get_user_list with filter parameters""" api = AdminUserManagementApi() - user1 = sample_user_data(is_superadmin=True) - pagination = sample_pagination_data(total_items=1) - - response_data = {"users": [user1], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.admin_get_user_list(filter=["is_superadmin=true"]) assert isinstance(result, UserList) - def test_admin_get_user_list_with_http_info(self, mocker, sample_pagination_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "users": [], + "pagination": sample_pagination_data(), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_admin_get_user_list_with_http_info(self, mocker, create_mock_response): """Test case for admin_get_user_list_with_http_info""" api = AdminUserManagementApi() - pagination = sample_pagination_data() - response_data = {"users": [], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.admin_get_user_list_with_http_info() assert result.status_code == 200 assert isinstance(result.data, UserList) - def test_admin_update_user_success(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": sample_user_data(email="updated@example.com", is_superadmin=True), + "status": 200, + } + ], + indirect=True, + ) + def test_admin_update_user_success(self, mocker, create_mock_response): """Test case for admin_update_user - successfully update a user""" api = AdminUserManagementApi() - updated_data = sample_user_data(email="updated@example.com", is_superadmin=True) - mock_response = create_mock_response(updated_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" user = User(email="updated@example.com", is_superadmin=True) @@ -225,23 +310,30 @@ def test_admin_update_user_success(self, mocker, sample_user_data): assert isinstance(result, User) assert result.is_superadmin is True - def test_admin_update_user_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_admin_update_user_not_found(self, mocker, create_mock_response): """Test case for admin_update_user with non-existent user""" api = AdminUserManagementApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" user = User(email="test@example.com", name="Test") with pytest.raises(NotFoundException): api.admin_update_user(id=user_id, user=user) - def test_admin_update_user_with_http_info(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_user_data(), "status": 200}], + indirect=True, + ) + def test_admin_update_user_with_http_info(self, mocker, create_mock_response): """Test case for admin_update_user_with_http_info""" api = AdminUserManagementApi() - user_data = sample_user_data() - mock_response = create_mock_response(user_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" user = User(email="test@example.com", name="Test") @@ -250,11 +342,15 @@ def test_admin_update_user_with_http_info(self, mocker, sample_user_data): assert result.status_code == 200 assert isinstance(result.data, User) - def test_admin_update_user_server_error(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "internal error"}, "status": 500}], + indirect=True, + ) + def test_admin_update_user_server_error(self, mocker, create_mock_response): """Test case for admin_update_user with server error""" api = AdminUserManagementApi() - mock_response = create_mock_response({"error": "internal error"}, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) user_id = "550e8400-e29b-41d4-a716-446655440000" user = User(email="test@example.com", name="Test") diff --git a/test/test_artifact_api.py b/test/test_artifact_api.py index b879858..2893d3a 100644 --- a/test/test_artifact_api.py +++ b/test/test_artifact_api.py @@ -2,6 +2,8 @@ from uuid import uuid4 +import pytest + from ibutsu_client.api.artifact_api import ArtifactApi from ibutsu_client.models.artifact import Artifact from ibutsu_client.models.artifact_list import ArtifactList @@ -10,21 +12,36 @@ class TestArtifactApi: """ArtifactApi Tests""" - def test_get_artifact_list(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "artifacts": [ + { + "id": "00000000-0000-0000-0000-000000000001", + "filename": "test1.txt", + "mime_type": "text/plain", + }, + { + "id": "00000000-0000-0000-0000-000000000002", + "filename": "test2.png", + "mime_type": "image/png", + }, + ], + "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_artifact_list(self, mock_api_client, create_mock_response): """Test case for get_artifact_list""" api = ArtifactApi(api_client=mock_api_client) - artifact_list_data = { - "artifacts": [ - {"id": str(uuid4()), "filename": "test1.txt", "mime_type": "text/plain"}, - {"id": str(uuid4()), "filename": "test2.png", "mime_type": "image/png"}, - ], - "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, - } - # Mock the API response - mock_response = mock_rest_response(data=artifact_list_data, status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_artifact_list(page=1, page_size=25) @@ -43,19 +60,30 @@ def test_get_artifact_list(self, mock_api_client, mock_rest_response): assert "page=1" in args[1] assert "pageSize=25" in args[1] - def test_get_artifact(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "ARTIFACT_ID_PLACEHOLDER", + "filename": "test.txt", + "mime_type": "text/plain", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_artifact(self, mock_api_client, create_mock_response): """Test case for get_artifact""" api = ArtifactApi(api_client=mock_api_client) artifact_id = uuid4() - artifact_data = { - "id": str(artifact_id), - "filename": "test.txt", - "mime_type": "text/plain", - } - # Mock the API response - mock_response = mock_rest_response(data=artifact_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual artifact_id + create_mock_response.data = create_mock_response.data.replace( + b"ARTIFACT_ID_PLACEHOLDER", str(artifact_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_artifact(id=artifact_id) @@ -71,17 +99,19 @@ def test_get_artifact(self, mock_api_client, mock_rest_response): assert args[0] == "GET" assert args[1].endswith(f"/artifact/{artifact_id}") - def test_download_artifact(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": b"file content", "status": 200}], + indirect=True, + ) + def test_download_artifact(self, mock_api_client, create_mock_response): """Test case for download_artifact""" api = ArtifactApi(api_client=mock_api_client) artifact_id = uuid4() file_content = b"file content" # Mock the API response - # Note: download_artifact returns bytearray, so we mock the raw data - mock_response = mock_rest_response(status=200) - mock_response.data = file_content - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.download_artifact(id=artifact_id) @@ -95,16 +125,19 @@ def test_download_artifact(self, mock_api_client, mock_rest_response): assert args[0] == "GET" assert args[1].endswith(f"/artifact/{artifact_id}/download") - def test_view_artifact(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": b"file content", "status": 200}], + indirect=True, + ) + def test_view_artifact(self, mock_api_client, create_mock_response): """Test case for view_artifact""" api = ArtifactApi(api_client=mock_api_client) artifact_id = uuid4() file_content = b"file content" # Mock the API response - mock_response = mock_rest_response(status=200) - mock_response.data = file_content - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.view_artifact(id=artifact_id) @@ -118,23 +151,37 @@ def test_view_artifact(self, mock_api_client, mock_rest_response): assert args[0] == "GET" assert args[1].endswith(f"/artifact/{artifact_id}/view") - def test_upload_artifact(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "ARTIFACT_ID_PLACEHOLDER", + "filename": "test.txt", + "result_id": None, + "run_id": "RUN_ID_PLACEHOLDER", + }, + "status": 201, + } + ], + indirect=True, + ) + def test_upload_artifact(self, mock_api_client, create_mock_response): """Test case for upload_artifact""" api = ArtifactApi(api_client=mock_api_client) run_id = uuid4() + artifact_id = uuid4() filename = "test.txt" file_content = b"content" - artifact_data = { - "id": str(uuid4()), - "filename": filename, - "result_id": None, - "run_id": str(run_id), - } - - # Mock the API response - mock_response = mock_rest_response(data=artifact_data, status=201) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual IDs + create_mock_response.data = create_mock_response.data.replace( + b"ARTIFACT_ID_PLACEHOLDER", str(artifact_id).encode() + ) + create_mock_response.data = create_mock_response.data.replace( + b"RUN_ID_PLACEHOLDER", str(run_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.upload_artifact(filename=filename, file=file_content, run_id=run_id) @@ -161,14 +208,18 @@ def test_upload_artifact(self, mock_api_client, mock_rest_response): ) assert file_found - def test_delete_artifact(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 200}], + indirect=True, + ) + def test_delete_artifact(self, mock_api_client, create_mock_response): """Test case for delete_artifact""" api = ArtifactApi(api_client=mock_api_client) artifact_id = uuid4() # Mock the API response - mock_response = mock_rest_response(status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API api.delete_artifact(id=artifact_id) diff --git a/test/test_dashboard_api.py b/test/test_dashboard_api.py index a6cb58d..c8702c3 100644 --- a/test/test_dashboard_api.py +++ b/test/test_dashboard_api.py @@ -3,6 +3,8 @@ from urllib.parse import parse_qs, urlparse from uuid import uuid4 +import pytest + from ibutsu_client.api.dashboard_api import DashboardApi from ibutsu_client.models.dashboard import Dashboard from ibutsu_client.models.dashboard_list import DashboardList @@ -11,19 +13,30 @@ class TestDashboardApi: """DashboardApi Tests""" - def test_add_dashboard(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "DASHBOARD_ID_PLACEHOLDER", + "title": "New Dashboard", + "description": "Description", + }, + "status": 201, + } + ], + indirect=True, + ) + def test_add_dashboard(self, mock_api_client, create_mock_response): """Test case for add_dashboard""" api = DashboardApi(api_client=mock_api_client) dashboard_id = uuid4() - dashboard_data = { - "id": str(dashboard_id), - "title": "New Dashboard", - "description": "Description", - } - # Mock the API response - mock_response = mock_rest_response(data=dashboard_data, status=201) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual dashboard_id + create_mock_response.data = create_mock_response.data.replace( + b"DASHBOARD_ID_PLACEHOLDER", str(dashboard_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API new_dashboard = Dashboard(title="New Dashboard", description="Description") @@ -40,14 +53,18 @@ def test_add_dashboard(self, mock_api_client, mock_rest_response): assert args[0] == "POST" assert args[1].endswith("/dashboard") - def test_delete_dashboard(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 200}], + indirect=True, + ) + def test_delete_dashboard(self, mock_api_client, create_mock_response): """Test case for delete_dashboard""" api = DashboardApi(api_client=mock_api_client) dashboard_id = uuid4() # Mock the API response - mock_response = mock_rest_response(status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API api.delete_dashboard(id=dashboard_id) @@ -58,18 +75,29 @@ def test_delete_dashboard(self, mock_api_client, mock_rest_response): assert args[0] == "DELETE" assert args[1].endswith(f"/dashboard/{dashboard_id}") - def test_get_dashboard(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "DASHBOARD_ID_PLACEHOLDER", + "title": "My Dashboard", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_dashboard(self, mock_api_client, create_mock_response): """Test case for get_dashboard""" api = DashboardApi(api_client=mock_api_client) dashboard_id = uuid4() - dashboard_data = { - "id": str(dashboard_id), - "title": "My Dashboard", - } - # Mock the API response - mock_response = mock_rest_response(data=dashboard_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual dashboard_id + create_mock_response.data = create_mock_response.data.replace( + b"DASHBOARD_ID_PLACEHOLDER", str(dashboard_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_dashboard(id=dashboard_id) @@ -85,21 +113,28 @@ def test_get_dashboard(self, mock_api_client, mock_rest_response): assert args[0] == "GET" assert args[1].endswith(f"/dashboard/{dashboard_id}") - def test_get_dashboard_list(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "dashboards": [ + {"id": "00000000-0000-0000-0000-000000000001", "title": "Dashboard 1"}, + {"id": "00000000-0000-0000-0000-000000000002", "title": "Dashboard 2"}, + ], + "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_dashboard_list(self, mock_api_client, create_mock_response): """Test case for get_dashboard_list""" api = DashboardApi(api_client=mock_api_client) - dashboard_list_data = { - "dashboards": [ - {"id": str(uuid4()), "title": "Dashboard 1"}, - {"id": str(uuid4()), "title": "Dashboard 2"}, - ], - "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, - } - # Mock the API response - mock_response = mock_rest_response(data=dashboard_list_data, status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_dashboard_list(page=1, page_size=25) @@ -121,18 +156,29 @@ def test_get_dashboard_list(self, mock_api_client, mock_rest_response): assert query_params["page"] == ["1"] assert query_params["pageSize"] == ["25"] - def test_update_dashboard(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "DASHBOARD_ID_PLACEHOLDER", + "title": "Updated Dashboard", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_update_dashboard(self, mock_api_client, create_mock_response): """Test case for update_dashboard""" api = DashboardApi(api_client=mock_api_client) dashboard_id = uuid4() - dashboard_data = { - "id": str(dashboard_id), - "title": "Updated Dashboard", - } - # Mock the API response - mock_response = mock_rest_response(data=dashboard_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual dashboard_id + create_mock_response.data = create_mock_response.data.replace( + b"DASHBOARD_ID_PLACEHOLDER", str(dashboard_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API update_dashboard = Dashboard(title="Updated Dashboard") diff --git a/test/test_group_api.py b/test/test_group_api.py index 0f4a0da..d286ac5 100644 --- a/test/test_group_api.py +++ b/test/test_group_api.py @@ -15,18 +15,21 @@ from ibutsu_client.exceptions import NotFoundException, ServiceException from ibutsu_client.models.group import Group from ibutsu_client.models.group_list import GroupList -from test import create_mock_response +from test.utils import sample_group_data, sample_pagination_data class TestGroupApi: """GroupApi comprehensive tests""" - def test_add_group_success(self, mocker, sample_group_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_group_data(name="engineering-team"), "status": 201}], + indirect=True, + ) + def test_add_group_success(self, mocker, create_mock_response): """Test case for add_group - successfully create a new group""" api = GroupApi() - group_data = sample_group_data(name="engineering-team") - mock_response = create_mock_response(group_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group = Group(name="engineering-team") result = api.add_group(group=group) @@ -35,32 +38,43 @@ def test_add_group_success(self, mocker, sample_group_data): assert result.name == "engineering-team" api.api_client.call_api.assert_called_once() - def test_add_group_unauthorized(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "unauthorized"}, "status": 401}], + indirect=True, + ) + def test_add_group_unauthorized(self, mocker, create_mock_response): """Test case for add_group without proper authentication""" api = GroupApi() - mock_response = create_mock_response({"error": "unauthorized"}, status=401) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group = Group(name="test-group") with pytest.raises((ServiceException, Exception)): api.add_group(group=group) - def test_add_group_conflict(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "group already exists"}, "status": 409}], + indirect=True, + ) + def test_add_group_conflict(self, mocker, create_mock_response): """Test case for add_group with existing group name""" api = GroupApi() - mock_response = create_mock_response({"error": "group already exists"}, status=409) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group = Group(name="existing-group") with pytest.raises((ServiceException, Exception)): api.add_group(group=group) - def test_add_group_with_http_info(self, mocker, sample_group_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_group_data(name="new-team"), "status": 201}], + indirect=True, + ) + def test_add_group_with_http_info(self, mocker, create_mock_response): """Test case for add_group_with_http_info""" api = GroupApi() - group_data = sample_group_data(name="new-team") - mock_response = create_mock_response(group_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group = Group(name="new-team") result = api.add_group_with_http_info(group=group) @@ -68,12 +82,15 @@ def test_add_group_with_http_info(self, mocker, sample_group_data): assert result.status_code == 201 assert isinstance(result.data, Group) - def test_get_group_success(self, mocker, sample_group_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_group_data(name="qa-team"), "status": 200}], + indirect=True, + ) + def test_get_group_success(self, mocker, create_mock_response): """Test case for get_group - retrieve a single group""" api = GroupApi() - group_data = sample_group_data(name="qa-team") - mock_response = create_mock_response(group_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_group(id=group_id) @@ -81,22 +98,29 @@ def test_get_group_success(self, mocker, sample_group_data): assert isinstance(result, Group) assert result.name == "qa-team" - def test_get_group_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_get_group_not_found(self, mocker, create_mock_response): """Test case for get_group with non-existent group""" api = GroupApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(NotFoundException): api.get_group(id=group_id) - def test_get_group_with_http_info(self, mocker, sample_group_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_group_data(), "status": 200}], + indirect=True, + ) + def test_get_group_with_http_info(self, mocker, create_mock_response): """Test case for get_group_with_http_info""" api = GroupApi() - group_data = sample_group_data() - mock_response = create_mock_response(group_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_group_with_http_info(id=group_id) @@ -104,71 +128,110 @@ def test_get_group_with_http_info(self, mocker, sample_group_data): assert result.status_code == 200 assert isinstance(result.data, Group) - def test_get_group_list_success(self, mocker, sample_group_data, sample_pagination_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "groups": [ + sample_group_data(name="team-alpha"), + sample_group_data(name="team-beta"), + ], + "pagination": sample_pagination_data(total_items=2), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_group_list_success(self, mocker, create_mock_response): """Test case for get_group_list - retrieve list of groups""" api = GroupApi() - group1 = sample_group_data(name="team-alpha") - group2 = sample_group_data(name="team-beta") - pagination = sample_pagination_data(total_items=2) - - response_data = {"groups": [group1, group2], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_group_list() assert isinstance(result, GroupList) assert len(result.groups) == 2 - def test_get_group_list_with_pagination( - self, mocker, sample_group_data, sample_pagination_data - ): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "groups": [sample_group_data()], + "pagination": sample_pagination_data(page=2, page_size=10), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_group_list_with_pagination(self, mocker, create_mock_response): """Test case for get_group_list with pagination parameters""" api = GroupApi() - group1 = sample_group_data() - pagination = sample_pagination_data(page=2, page_size=10) - - response_data = {"groups": [group1], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_group_list(page=2, page_size=10) assert isinstance(result, GroupList) api.api_client.call_api.assert_called_once() - def test_get_group_list_empty(self, mocker, sample_pagination_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "groups": [], + "pagination": sample_pagination_data(total_items=0), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_group_list_empty(self, mocker, create_mock_response): """Test case for get_group_list with no groups""" api = GroupApi() - pagination = sample_pagination_data(total_items=0) - response_data = {"groups": [], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_group_list() assert isinstance(result, GroupList) assert len(result.groups) == 0 - def test_get_group_list_with_http_info(self, mocker, sample_pagination_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "groups": [], + "pagination": sample_pagination_data(), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_group_list_with_http_info(self, mocker, create_mock_response): """Test case for get_group_list_with_http_info""" api = GroupApi() - pagination = sample_pagination_data() - response_data = {"groups": [], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_group_list_with_http_info() assert result.status_code == 200 assert isinstance(result.data, GroupList) - def test_update_group_success(self, mocker, sample_group_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_group_data(name="updated-team-name"), "status": 200}], + indirect=True, + ) + def test_update_group_success(self, mocker, create_mock_response): """Test case for update_group - successfully update a group""" api = GroupApi() - updated_data = sample_group_data(name="updated-team-name") - mock_response = create_mock_response(updated_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group_id = "550e8400-e29b-41d4-a716-446655440000" group = Group(name="updated-team-name") @@ -177,23 +240,30 @@ def test_update_group_success(self, mocker, sample_group_data): assert isinstance(result, Group) assert result.name == "updated-team-name" - def test_update_group_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_update_group_not_found(self, mocker, create_mock_response): """Test case for update_group with non-existent group""" api = GroupApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group_id = "550e8400-e29b-41d4-a716-446655440000" group = Group(name="test-group") with pytest.raises(NotFoundException): api.update_group(id=group_id, group=group) - def test_update_group_with_http_info(self, mocker, sample_group_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_group_data(), "status": 200}], + indirect=True, + ) + def test_update_group_with_http_info(self, mocker, create_mock_response): """Test case for update_group_with_http_info""" api = GroupApi() - group_data = sample_group_data() - mock_response = create_mock_response(group_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group_id = "550e8400-e29b-41d4-a716-446655440000" group = Group(name="test-group") @@ -202,11 +272,15 @@ def test_update_group_with_http_info(self, mocker, sample_group_data): assert result.status_code == 200 assert isinstance(result.data, Group) - def test_update_group_server_error(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "internal error"}, "status": 500}], + indirect=True, + ) + def test_update_group_server_error(self, mocker, create_mock_response): """Test case for update_group with server error""" api = GroupApi() - mock_response = create_mock_response({"error": "internal error"}, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) group_id = "550e8400-e29b-41d4-a716-446655440000" group = Group(name="test-group") diff --git a/test/test_health_api.py b/test/test_health_api.py index 347d13f..0094771 100644 --- a/test/test_health_api.py +++ b/test/test_health_api.py @@ -15,26 +15,26 @@ from ibutsu_client.exceptions import ServiceException from ibutsu_client.models.health import Health from ibutsu_client.models.health_info import HealthInfo -from test import create_mock_response class TestHealthApi: """HealthApi unit tests""" - def test_get_database_health(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"status": "ok", "message": "Database is healthy"}, "status": 200}], + indirect=True, + ) + def test_get_database_health(self, mocker, create_mock_response): """Test case for get_database_health Get a health report for the database """ - # Mock response data - response_data = {"status": "ok", "message": "Database is healthy"} - # Create API instance api = HealthApi() # Mock the call_api method - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) # Call the method result = api.get_database_health() @@ -47,13 +47,15 @@ def test_get_database_health(self, mocker): # Verify call_api was called api.api_client.call_api.assert_called_once() - def test_get_database_health_error(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"status": "error", "message": "Database connection failed"}, "status": 500}], + indirect=True, + ) + def test_get_database_health_error(self, mocker, create_mock_response): """Test case for get_database_health with error response""" - response_data = {"status": "error", "message": "Database connection failed"} - api = HealthApi() - mock_response = create_mock_response(response_data, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) # 500 errors raise ServiceException with pytest.raises(ServiceException) as exc_info: @@ -62,16 +64,18 @@ def test_get_database_health_error(self, mocker): assert exc_info.value.status == 500 assert "error" in str(exc_info.value.body).lower() - def test_get_health(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"status": "ok", "message": "Service is healthy"}, "status": 200}], + indirect=True, + ) + def test_get_health(self, mocker, create_mock_response): """Test case for get_health Get a general health report """ - response_data = {"status": "ok", "message": "Service is healthy"} - api = HealthApi() - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_health() @@ -79,20 +83,27 @@ def test_get_health(self, mocker): assert result.status == "ok" assert result.message == "Service is healthy" - def test_get_health_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "frontend": "https://ibutsu.example.com", + "backend": "https://api.ibutsu.example.com", + "api_ui": "https://api.ibutsu.example.com/docs", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_health_info(self, mocker, create_mock_response): """Test case for get_health_info Get information about the server """ - response_data = { - "frontend": "https://ibutsu.example.com", - "backend": "https://api.ibutsu.example.com", - "api_ui": "https://api.ibutsu.example.com/docs", - } - api = HealthApi() - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_health_info() @@ -101,17 +112,24 @@ def test_get_health_info(self, mocker): assert result.backend == "https://api.ibutsu.example.com" assert result.api_ui == "https://api.ibutsu.example.com/docs" - def test_get_health_info_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "frontend": "https://ibutsu.example.com", + "backend": "https://api.ibutsu.example.com", + "api_ui": "https://api.ibutsu.example.com/docs", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_health_info_with_http_info(self, mocker, create_mock_response): """Test case for get_health_info_with_http_info""" - response_data = { - "frontend": "https://ibutsu.example.com", - "backend": "https://api.ibutsu.example.com", - "api_ui": "https://api.ibutsu.example.com/docs", - } - api = HealthApi() - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_health_info_with_http_info() diff --git a/test/test_import_api.py b/test/test_import_api.py index 59bdd1e..a6f3edf 100644 --- a/test/test_import_api.py +++ b/test/test_import_api.py @@ -14,23 +14,30 @@ from ibutsu_client.api.import_api import ImportApi from ibutsu_client.exceptions import NotFoundException, ServiceException from ibutsu_client.models.model_import import ModelImport -from test import create_mock_response class TestImportApi: """ImportApi comprehensive tests""" - def test_add_import_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test_results.xml", + "format": "junit", + "status": "pending", + }, + "status": 201, + } + ], + indirect=True, + ) + def test_add_import_success(self, mocker, create_mock_response): """Test case for add_import - successfully import a file""" api = ImportApi() - import_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "filename": "test_results.xml", - "format": "junit", - "status": "pending", - } - mock_response = create_mock_response(import_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) # Mock file upload - import_file as tuple (filename, content) result = api.add_import( @@ -42,18 +49,26 @@ def test_add_import_success(self, mocker): assert result.format == "junit" api.api_client.call_api.assert_called_once() - def test_add_import_with_project(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "results.xml", + "format": "junit", + "project": "test-project", + "status": "pending", + }, + "status": 201, + } + ], + indirect=True, + ) + def test_add_import_with_project(self, mocker, create_mock_response): """Test case for add_import with project parameter""" api = ImportApi() - import_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "filename": "results.xml", - "format": "junit", - "project": "test-project", - "status": "pending", - } - mock_response = create_mock_response(import_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.add_import( import_file=("results.xml", b"test"), @@ -64,17 +79,25 @@ def test_add_import_with_project(self, mocker): assert result.filename == "results.xml" api.api_client.call_api.assert_called_once() - def test_add_import_archive_format(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "archive.tar.gz", + "format": "ibutsu", + "status": "pending", + }, + "status": 201, + } + ], + indirect=True, + ) + def test_add_import_archive_format(self, mocker, create_mock_response): """Test case for add_import with Ibutsu archive format""" api = ImportApi() - import_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "filename": "archive.tar.gz", - "format": "ibutsu", - "status": "pending", - } - mock_response = create_mock_response(import_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.add_import( import_file=("archive.tar.gz", b"binary archive content"), @@ -83,34 +106,50 @@ def test_add_import_archive_format(self, mocker): assert isinstance(result, ModelImport) assert result.format == "ibutsu" - def test_add_import_invalid_file(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "invalid file format"}, "status": 400}], + indirect=True, + ) + def test_add_import_invalid_file(self, mocker, create_mock_response): """Test case for add_import with invalid file""" api = ImportApi() - mock_response = create_mock_response({"error": "invalid file format"}, status=400) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) with pytest.raises((ServiceException, Exception)): api.add_import(import_file=("invalid.txt", b"invalid content")) - def test_add_import_unauthorized(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "unauthorized"}, "status": 401}], + indirect=True, + ) + def test_add_import_unauthorized(self, mocker, create_mock_response): """Test case for add_import without authentication""" api = ImportApi() - mock_response = create_mock_response({"error": "unauthorized"}, status=401) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) with pytest.raises((ServiceException, Exception)): api.add_import(import_file=("test.xml", b"content")) - def test_add_import_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test.xml", + "status": "pending", + }, + "status": 201, + } + ], + indirect=True, + ) + def test_add_import_with_http_info(self, mocker, create_mock_response): """Test case for add_import_with_http_info""" api = ImportApi() - import_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "filename": "test.xml", - "status": "pending", - } - mock_response = create_mock_response(import_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.add_import_with_http_info( import_file=("test.xml", b"content"), @@ -119,18 +158,26 @@ def test_add_import_with_http_info(self, mocker): assert result.status_code == 201 assert isinstance(result.data, ModelImport) - def test_get_import_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test_results.xml", + "format": "junit", + "status": "done", + "run_id": "660e8400-e29b-41d4-a716-446655440000", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_import_success(self, mocker, create_mock_response): """Test case for get_import - retrieve import status""" api = ImportApi() - import_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "filename": "test_results.xml", - "format": "junit", - "status": "done", - "run_id": "660e8400-e29b-41d4-a716-446655440000", - } - mock_response = create_mock_response(import_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) import_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_import(id=import_id) @@ -139,16 +186,24 @@ def test_get_import_success(self, mocker): assert result.status == "done" assert result.run_id is not None - def test_get_import_pending_status(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test.xml", + "status": "pending", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_import_pending_status(self, mocker, create_mock_response): """Test case for get_import with pending status""" api = ImportApi() - import_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "filename": "test.xml", - "status": "pending", - } - mock_response = create_mock_response(import_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) import_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_import(id=import_id) @@ -156,17 +211,25 @@ def test_get_import_pending_status(self, mocker): assert isinstance(result, ModelImport) assert result.status == "pending" - def test_get_import_running_status(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test.xml", + "status": "running", + "format": "junit", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_import_running_status(self, mocker, create_mock_response): """Test case for get_import with running status""" api = ImportApi() - import_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "filename": "test.xml", - "status": "running", - "format": "junit", - } - mock_response = create_mock_response(import_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) import_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_import(id=import_id) @@ -174,26 +237,38 @@ def test_get_import_running_status(self, mocker): assert isinstance(result, ModelImport) assert result.status == "running" - def test_get_import_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_get_import_not_found(self, mocker, create_mock_response): """Test case for get_import with non-existent import""" api = ImportApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) import_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(NotFoundException): api.get_import(id=import_id) - def test_get_import_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "filename": "test.xml", + "status": "done", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_import_with_http_info(self, mocker, create_mock_response): """Test case for get_import_with_http_info""" api = ImportApi() - import_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "filename": "test.xml", - "status": "done", - } - mock_response = create_mock_response(import_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) import_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_import_with_http_info(id=import_id) @@ -201,11 +276,15 @@ def test_get_import_with_http_info(self, mocker): assert result.status_code == 200 assert isinstance(result.data, ModelImport) - def test_get_import_server_error(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "internal error"}, "status": 500}], + indirect=True, + ) + def test_get_import_server_error(self, mocker, create_mock_response): """Test case for get_import with server error""" api = ImportApi() - mock_response = create_mock_response({"error": "internal error"}, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) import_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(ServiceException): diff --git a/test/test_login_api.py b/test/test_login_api.py index 60dccf9..5a544e2 100644 --- a/test/test_login_api.py +++ b/test/test_login_api.py @@ -16,7 +16,6 @@ from ibutsu_client.models.login_config import LoginConfig from ibutsu_client.models.login_support import LoginSupport from ibutsu_client.models.login_token import LoginToken -from test import create_mock_response class TestLoginApi: @@ -37,11 +36,15 @@ def test_activate_success(self, mocker): assert result is None api.api_client.call_api.assert_called_once() - def test_activate_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_activate_not_found(self, mocker, create_mock_response): """Test case for activate with invalid activation code""" api = LoginApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) with pytest.raises(NotFoundException): api.activate(activation_code="invalid-code") @@ -74,11 +77,15 @@ def test_auth_success(self, mocker): assert result is None api.api_client.call_api.assert_called_once() - def test_auth_unauthorized(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "invalid provider"}, "status": 400}], + indirect=True, + ) + def test_auth_unauthorized(self, mocker, create_mock_response): """Test case for auth with invalid provider""" api = LoginApi() - mock_response = create_mock_response({"error": "invalid provider"}, status=400) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) with pytest.raises( (ServiceException, Exception) @@ -99,42 +106,61 @@ def test_auth_with_http_info(self, mocker): assert result.status_code == 302 assert result.data is None - def test_config_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "client_id": "test-client-id", + "redirect_uri": "https://example.com/callback", + "scope": "openid profile email", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_config_success(self, mocker, create_mock_response): """Test case for config - get login configuration""" api = LoginApi() - response_data = { - "client_id": "test-client-id", - "redirect_uri": "https://example.com/callback", - "scope": "openid profile email", - } - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.config(provider="oidc") assert isinstance(result, LoginConfig) assert result.client_id == "test-client-id" assert result.redirect_uri == "https://example.com/callback" - def test_config_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"client_id": "test-client"}, "status": 200}], + indirect=True, + ) + def test_config_with_http_info(self, mocker, create_mock_response): """Test case for config_with_http_info""" api = LoginApi() - response_data = {"client_id": "test-client"} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.config_with_http_info(provider="oidc") assert result.status_code == 200 assert isinstance(result.data, LoginConfig) - def test_login_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "token": "jwt-token-here", + "refresh_token": "refresh-token-here", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_login_success(self, mocker, create_mock_response): """Test case for login with valid credentials""" api = LoginApi() - response_data = { - "token": "jwt-token-here", - "refresh_token": "refresh-token-here", - } - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.credentials import Credentials @@ -143,11 +169,15 @@ def test_login_success(self, mocker): assert isinstance(result, LoginToken) assert result.token == "jwt-token-here" - def test_login_invalid_credentials(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "invalid credentials"}, "status": 401}], + indirect=True, + ) + def test_login_invalid_credentials(self, mocker, create_mock_response): """Test case for login with invalid credentials""" api = LoginApi() - mock_response = create_mock_response({"error": "invalid credentials"}, status=401) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.credentials import Credentials @@ -155,12 +185,15 @@ def test_login_invalid_credentials(self, mocker): with pytest.raises((ServiceException, Exception)): api.login(credentials=credentials) - def test_login_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"token": "test-token"}, "status": 200}], + indirect=True, + ) + def test_login_with_http_info(self, mocker, create_mock_response): """Test case for login_with_http_info""" api = LoginApi() - response_data = {"token": "test-token"} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.credentials import Credentials @@ -169,11 +202,15 @@ def test_login_with_http_info(self, mocker): assert result.status_code == 200 assert isinstance(result.data, LoginToken) - def test_recover_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 200}], + indirect=True, + ) + def test_recover_success(self, mocker, create_mock_response): """Test case for recover - initiate password recovery""" api = LoginApi() - mock_response = create_mock_response({}, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.account_recovery import AccountRecovery @@ -182,11 +219,15 @@ def test_recover_success(self, mocker): # Method should complete without raising exception api.api_client.call_api.assert_called_once() - def test_recover_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "user not found"}, "status": 404}], + indirect=True, + ) + def test_recover_not_found(self, mocker, create_mock_response): """Test case for recover with non-existent email""" api = LoginApi() - mock_response = create_mock_response({"error": "user not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.account_recovery import AccountRecovery @@ -194,11 +235,15 @@ def test_recover_not_found(self, mocker): with pytest.raises(NotFoundException): api.recover(account_recovery=recovery_data) - def test_recover_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 200}], + indirect=True, + ) + def test_recover_with_http_info(self, mocker, create_mock_response): """Test case for recover_with_http_info""" api = LoginApi() - mock_response = create_mock_response({}, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.account_recovery import AccountRecovery @@ -206,12 +251,15 @@ def test_recover_with_http_info(self, mocker): result = api.recover_with_http_info(account_recovery=recovery_data) assert result.status_code == 200 - def test_register_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"message": "Registration successful"}, "status": 201}], + indirect=True, + ) + def test_register_success(self, mocker, create_mock_response): """Test case for register with valid registration data""" api = LoginApi() - response_data = {"message": "Registration successful"} - mock_response = create_mock_response(response_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.account_registration import AccountRegistration @@ -221,11 +269,15 @@ def test_register_success(self, mocker): api.register(account_registration=registration) api.api_client.call_api.assert_called_once() - def test_register_conflict(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "email already exists"}, "status": 409}], + indirect=True, + ) + def test_register_conflict(self, mocker, create_mock_response): """Test case for register with existing email""" api = LoginApi() - mock_response = create_mock_response({"error": "email already exists"}, status=409) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.account_registration import AccountRegistration @@ -235,12 +287,15 @@ def test_register_conflict(self, mocker): with pytest.raises((ServiceException, Exception)): # Should raise conflict exception api.register(account_registration=registration) - def test_register_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"message": "success"}, "status": 201}], + indirect=True, + ) + def test_register_with_http_info(self, mocker, create_mock_response): """Test case for register_with_http_info""" api = LoginApi() - response_data = {"message": "success"} - mock_response = create_mock_response(response_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.account_registration import AccountRegistration @@ -248,11 +303,15 @@ def test_register_with_http_info(self, mocker): result = api.register_with_http_info(account_registration=registration) assert result.status_code == 201 - def test_reset_password_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 200}], + indirect=True, + ) + def test_reset_password_success(self, mocker, create_mock_response): """Test case for reset_password with valid reset data""" api = LoginApi() - mock_response = create_mock_response({}, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.account_reset import AccountReset @@ -260,11 +319,15 @@ def test_reset_password_success(self, mocker): api.reset_password(account_reset=reset_data) api.api_client.call_api.assert_called_once() - def test_reset_password_invalid_code(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "invalid reset code"}, "status": 400}], + indirect=True, + ) + def test_reset_password_invalid_code(self, mocker, create_mock_response): """Test case for reset_password with invalid reset code""" api = LoginApi() - mock_response = create_mock_response({"error": "invalid reset code"}, status=400) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.account_reset import AccountReset @@ -272,11 +335,15 @@ def test_reset_password_invalid_code(self, mocker): with pytest.raises((ServiceException, Exception)): api.reset_password(account_reset=reset_data) - def test_reset_password_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 200}], + indirect=True, + ) + def test_reset_password_with_http_info(self, mocker, create_mock_response): """Test case for reset_password_with_http_info""" api = LoginApi() - mock_response = create_mock_response({}, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) from ibutsu_client.models.account_reset import AccountReset @@ -284,41 +351,56 @@ def test_reset_password_with_http_info(self, mocker): result = api.reset_password_with_http_info(account_reset=reset_data) assert result.status_code == 200 - def test_support_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "user": True, + "keycloak": True, + "google": False, + "github": False, + "facebook": False, + "gitlab": False, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_support_success(self, mocker, create_mock_response): """Test case for support - get support configuration""" api = LoginApi() - response_data = { - "user": True, - "keycloak": True, - "google": False, - "github": False, - "facebook": False, - "gitlab": False, - } - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.support() assert isinstance(result, LoginSupport) assert result.user is True assert result.keycloak is True - def test_support_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"user": True, "google": True}, "status": 200}], + indirect=True, + ) + def test_support_with_http_info(self, mocker, create_mock_response): """Test case for support_with_http_info""" api = LoginApi() - response_data = {"user": True, "google": True} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.support_with_http_info() assert result.status_code == 200 assert isinstance(result.data, LoginSupport) - def test_support_server_error(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "internal error"}, "status": 500}], + indirect=True, + ) + def test_support_server_error(self, mocker, create_mock_response): """Test case for support with server error""" api = LoginApi() - mock_response = create_mock_response({"error": "internal error"}, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) with pytest.raises(ServiceException): api.support() diff --git a/test/test_project_api.py b/test/test_project_api.py index 971ec31..9d05c4f 100644 --- a/test/test_project_api.py +++ b/test/test_project_api.py @@ -3,6 +3,8 @@ from urllib.parse import parse_qs, urlparse from uuid import uuid4 +import pytest + from ibutsu_client.api.project_api import ProjectApi from ibutsu_client.models.project import Project from ibutsu_client.models.project_list import ProjectList @@ -11,19 +13,30 @@ class TestProjectApi: """ProjectApi Tests""" - def test_add_project(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "PROJECT_ID_PLACEHOLDER", + "name": "test-project", + "title": "Test Project", + }, + "status": 201, + } + ], + indirect=True, + ) + def test_add_project(self, mock_api_client, create_mock_response): """Test case for add_project""" api = ProjectApi(api_client=mock_api_client) project_id = uuid4() - project_data = { - "id": str(project_id), - "name": "test-project", - "title": "Test Project", - } - # Mock the API response - mock_response = mock_rest_response(data=project_data, status=201) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual project_id + create_mock_response.data = create_mock_response.data.replace( + b"PROJECT_ID_PLACEHOLDER", str(project_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Create project object to send project_item = Project(name="test-project", title="Test Project") @@ -47,18 +60,29 @@ def test_add_project(self, mock_api_client, mock_rest_response): assert args[3]["name"] == "test-project" assert args[3]["title"] == "Test Project" - def test_get_project(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "PROJECT_ID_PLACEHOLDER", + "name": "test-project", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_project(self, mock_api_client, create_mock_response): """Test case for get_project""" api = ProjectApi(api_client=mock_api_client) project_id = uuid4() - project_data = { - "id": str(project_id), - "name": "test-project", - } - # Mock the API response - mock_response = mock_rest_response(data=project_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual project_id + create_mock_response.data = create_mock_response.data.replace( + b"PROJECT_ID_PLACEHOLDER", str(project_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_project(id=str(project_id)) @@ -74,21 +98,28 @@ def test_get_project(self, mock_api_client, mock_rest_response): assert args[0] == "GET" assert args[1].endswith(f"/project/{project_id}") - def test_get_project_list(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "projects": [ + {"id": "00000000-0000-0000-0000-000000000001", "name": "project1"}, + {"id": "00000000-0000-0000-0000-000000000002", "name": "project2"}, + ], + "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_project_list(self, mock_api_client, create_mock_response): """Test case for get_project_list""" api = ProjectApi(api_client=mock_api_client) - project_list_data = { - "projects": [ - {"id": str(uuid4()), "name": "project1"}, - {"id": str(uuid4()), "name": "project2"}, - ], - "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, - } - # Mock the API response - mock_response = mock_rest_response(data=project_list_data, status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_project_list(page=1, page_size=25, owner_id="user1") @@ -112,18 +143,29 @@ def test_get_project_list(self, mock_api_client, mock_rest_response): assert query_params["pageSize"] == ["25"] assert query_params["ownerId"] == ["user1"] - def test_update_project(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "PROJECT_ID_PLACEHOLDER", + "name": "updated-project", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_update_project(self, mock_api_client, create_mock_response): """Test case for update_project""" api = ProjectApi(api_client=mock_api_client) project_id = uuid4() - project_data = { - "id": str(project_id), - "name": "updated-project", - } - # Mock the API response - mock_response = mock_rest_response(data=project_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual project_id + create_mock_response.data = create_mock_response.data.replace( + b"PROJECT_ID_PLACEHOLDER", str(project_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Update object project_update = Project(name="updated-project") @@ -146,22 +188,30 @@ def test_update_project(self, mock_api_client, mock_rest_response): assert isinstance(args[3], dict) assert args[3]["name"] == "updated-project" - def test_get_filter_params(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": ["env", "component", "tag"], + "status": 200, + } + ], + indirect=True, + ) + def test_get_filter_params(self, mock_api_client, create_mock_response): """Test case for get_filter_params""" api = ProjectApi(api_client=mock_api_client) project_id = uuid4() - filter_params = ["env", "component", "tag"] # Mock the API response - mock_response = mock_rest_response(data=filter_params, status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call API response = api.get_filter_params(id=str(project_id)) # Verify result assert isinstance(response, list) - assert response == filter_params + assert response == ["env", "component", "tag"] # Verify call mock_api_client.call_api.assert_called_once() diff --git a/test/test_result_api.py b/test/test_result_api.py index a122d12..0593c49 100644 --- a/test/test_result_api.py +++ b/test/test_result_api.py @@ -3,6 +3,8 @@ from urllib.parse import parse_qs, urlparse from uuid import uuid4 +import pytest + from ibutsu_client.api.result_api import ResultApi from ibutsu_client.models.result import Result from ibutsu_client.models.result_list import ResultList @@ -11,20 +13,31 @@ class TestResultApi: """ResultApi Tests""" - def test_add_result(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "RESULT_ID_PLACEHOLDER", + "test_id": "test_case_1", + "result": "passed", + "duration": 1.5, + }, + "status": 201, + } + ], + indirect=True, + ) + def test_add_result(self, mock_api_client, create_mock_response): """Test case for add_result""" api = ResultApi(api_client=mock_api_client) result_id = uuid4() - result_data = { - "id": str(result_id), - "test_id": "test_case_1", - "result": "passed", - "duration": 1.5, - } - # Mock the API response - mock_response = mock_rest_response(data=result_data, status=201) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual result_id + create_mock_response.data = create_mock_response.data.replace( + b"RESULT_ID_PLACEHOLDER", str(result_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Create result object to send result_item = Result(test_id="test_case_1", result="passed", duration=1.5) @@ -50,19 +63,30 @@ def test_add_result(self, mock_api_client, mock_rest_response): assert args[3]["result"] == "passed" assert args[3]["duration"] == 1.5 - def test_get_result(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "RESULT_ID_PLACEHOLDER", + "test_id": "test_case_1", + "result": "passed", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_result(self, mock_api_client, create_mock_response): """Test case for get_result""" api = ResultApi(api_client=mock_api_client) result_id = uuid4() - result_data = { - "id": str(result_id), - "test_id": "test_case_1", - "result": "passed", - } - # Mock the API response - mock_response = mock_rest_response(data=result_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual result_id + create_mock_response.data = create_mock_response.data.replace( + b"RESULT_ID_PLACEHOLDER", str(result_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_result(id=result_id) @@ -78,21 +102,36 @@ def test_get_result(self, mock_api_client, mock_rest_response): assert args[0] == "GET" assert args[1].endswith(f"/result/{result_id}") - def test_get_result_list(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "results": [ + { + "id": "00000000-0000-0000-0000-000000000001", + "test_id": "test_1", + "result": "passed", + }, + { + "id": "00000000-0000-0000-0000-000000000002", + "test_id": "test_2", + "result": "failed", + }, + ], + "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_result_list(self, mock_api_client, create_mock_response): """Test case for get_result_list""" api = ResultApi(api_client=mock_api_client) - result_list_data = { - "results": [ - {"id": str(uuid4()), "test_id": "test_1", "result": "passed"}, - {"id": str(uuid4()), "test_id": "test_2", "result": "failed"}, - ], - "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, - } - # Mock the API response - mock_response = mock_rest_response(data=result_list_data, status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_result_list(page=1, page_size=25, filter=["result=passed"]) @@ -116,19 +155,30 @@ def test_get_result_list(self, mock_api_client, mock_rest_response): assert query_params["pageSize"] == ["25"] assert query_params["filter"] == ["result=passed"] - def test_update_result(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "RESULT_ID_PLACEHOLDER", + "test_id": "test_case_1", + "result": "failed", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_update_result(self, mock_api_client, create_mock_response): """Test case for update_result""" api = ResultApi(api_client=mock_api_client) result_id = uuid4() - result_data = { - "id": str(result_id), - "test_id": "test_case_1", - "result": "failed", # Updated result - } - # Mock the API response - mock_response = mock_rest_response(data=result_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual result_id + create_mock_response.data = create_mock_response.data.replace( + b"RESULT_ID_PLACEHOLDER", str(result_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Update object result_update = Result(result="failed") diff --git a/test/test_run_api.py b/test/test_run_api.py index 22ace4e..0ecde65 100644 --- a/test/test_run_api.py +++ b/test/test_run_api.py @@ -3,6 +3,8 @@ from urllib.parse import parse_qs, urlparse from uuid import uuid4 +import pytest + from ibutsu_client.api.run_api import RunApi from ibutsu_client.models.run import Run from ibutsu_client.models.run_list import RunList @@ -12,19 +14,30 @@ class TestRunApi: """RunApi Tests""" - def test_add_run(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "RUN_ID_PLACEHOLDER", + "component": "test-component", + "env": "ci", + }, + "status": 201, + } + ], + indirect=True, + ) + def test_add_run(self, mock_api_client, create_mock_response): """Test case for add_run""" api = RunApi(api_client=mock_api_client) run_id = uuid4() - run_data = { - "id": str(run_id), - "component": "test-component", - "env": "ci", - } - # Mock the API response - mock_response = mock_rest_response(data=run_data, status=201) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual run_id + create_mock_response.data = create_mock_response.data.replace( + b"RUN_ID_PLACEHOLDER", str(run_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Create run object to send run_item = Run(component="test-component", env="ci") @@ -48,18 +61,29 @@ def test_add_run(self, mock_api_client, mock_rest_response): assert args[3]["component"] == "test-component" assert args[3]["env"] == "ci" - def test_get_run(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "RUN_ID_PLACEHOLDER", + "component": "test-component", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_run(self, mock_api_client, create_mock_response): """Test case for get_run""" api = RunApi(api_client=mock_api_client) run_id = uuid4() - run_data = { - "id": str(run_id), - "component": "test-component", - } - # Mock the API response - mock_response = mock_rest_response(data=run_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual run_id + create_mock_response.data = create_mock_response.data.replace( + b"RUN_ID_PLACEHOLDER", str(run_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_run(id=run_id) @@ -75,21 +99,28 @@ def test_get_run(self, mock_api_client, mock_rest_response): assert args[0] == "GET" assert args[1].endswith(f"/run/{run_id}") - def test_get_run_list(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "runs": [ + {"id": "00000000-0000-0000-0000-000000000001", "component": "comp1"}, + {"id": "00000000-0000-0000-0000-000000000002", "component": "comp2"}, + ], + "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_run_list(self, mock_api_client, create_mock_response): """Test case for get_run_list""" api = RunApi(api_client=mock_api_client) - run_list_data = { - "runs": [ - {"id": str(uuid4()), "component": "comp1"}, - {"id": str(uuid4()), "component": "comp2"}, - ], - "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, - } - # Mock the API response - mock_response = mock_rest_response(data=run_list_data, status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Call the API response = api.get_run_list(page=1, page_size=25, filter=["env=ci"]) @@ -113,18 +144,29 @@ def test_get_run_list(self, mock_api_client, mock_rest_response): assert query_params["pageSize"] == ["25"] assert query_params["filter"] == ["env=ci"] - def test_update_run(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "RUN_ID_PLACEHOLDER", + "component": "updated-component", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_update_run(self, mock_api_client, create_mock_response): """Test case for update_run""" api = RunApi(api_client=mock_api_client) run_id = uuid4() - run_data = { - "id": str(run_id), - "component": "updated-component", - } - # Mock the API response - mock_response = mock_rest_response(data=run_data, status=200) - mock_api_client.call_api.return_value = mock_response + # Update the mock response with the actual run_id + create_mock_response.data = create_mock_response.data.replace( + b"RUN_ID_PLACEHOLDER", str(run_id).encode() + ) + mock_api_client.call_api.return_value = create_mock_response # Update object run_update = Run(component="updated-component") @@ -147,21 +189,36 @@ def test_update_run(self, mock_api_client, mock_rest_response): assert isinstance(args[3], dict) assert args[3]["component"] == "updated-component" - def test_bulk_update(self, mock_api_client, mock_rest_response): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "runs": [ + { + "id": "00000000-0000-0000-0000-000000000001", + "component": "comp1", + "metadata": {"new": "val"}, + }, + { + "id": "00000000-0000-0000-0000-000000000002", + "component": "comp2", + "metadata": {"new": "val"}, + }, + ], + "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_bulk_update(self, mock_api_client, create_mock_response): """Test case for bulk_update""" api = RunApi(api_client=mock_api_client) - run_list_data = { - "runs": [ - {"id": str(uuid4()), "component": "comp1", "metadata": {"new": "val"}}, - {"id": str(uuid4()), "component": "comp2", "metadata": {"new": "val"}}, - ], - "pagination": {"page": 1, "pageSize": 25, "totalItems": 2, "totalPages": 1}, - } - # Mock the API response - mock_response = mock_rest_response(data=run_list_data, status=200) - mock_api_client.call_api.return_value = mock_response + mock_api_client.call_api.return_value = create_mock_response # Update object update_data = UpdateRun(metadata={"new": "val"}) diff --git a/test/test_task_api.py b/test/test_task_api.py index 9686cf4..558c837 100644 --- a/test/test_task_api.py +++ b/test/test_task_api.py @@ -13,22 +13,29 @@ from ibutsu_client.api.task_api import TaskApi from ibutsu_client.exceptions import NotFoundException, ServiceException -from test import create_mock_response class TestTaskApi: """TaskApi comprehensive tests""" - def test_get_task_pending(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "pending", + "task_type": "export", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_task_pending(self, mocker, create_mock_response): """Test case for get_task with pending status""" api = TaskApi() - task_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "status": "pending", - "task_type": "export", - } - mock_response = create_mock_response(task_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_task(id=task_id) @@ -38,17 +45,25 @@ def test_get_task_pending(self, mocker): assert result["task_type"] == "export" api.api_client.call_api.assert_called_once() - def test_get_task_running(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "running", + "task_type": "bulk_update", + "progress": 45, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_task_running(self, mocker, create_mock_response): """Test case for get_task with running status""" api = TaskApi() - task_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "status": "running", - "task_type": "bulk_update", - "progress": 45, - } - mock_response = create_mock_response(task_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_task(id=task_id) @@ -57,20 +72,28 @@ def test_get_task_running(self, mocker): assert result["status"] == "running" assert result["progress"] == 45 - def test_get_task_completed(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "completed", + "task_type": "export", + "result": { + "file_url": "https://example.com/exports/results.tar.gz", + "file_size": 1024000, + }, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_task_completed(self, mocker, create_mock_response): """Test case for get_task with completed status""" api = TaskApi() - task_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "status": "completed", - "task_type": "export", - "result": { - "file_url": "https://example.com/exports/results.tar.gz", - "file_size": 1024000, - }, - } - mock_response = create_mock_response(task_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_task(id=task_id) @@ -79,17 +102,25 @@ def test_get_task_completed(self, mocker): assert result["status"] == "completed" assert result["result"]["file_url"] == "https://example.com/exports/results.tar.gz" - def test_get_task_failed(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "failed", + "task_type": "bulk_update", + "error": "Database connection timeout", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_task_failed(self, mocker, create_mock_response): """Test case for get_task with failed status""" api = TaskApi() - task_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "status": "failed", - "task_type": "bulk_update", - "error": "Database connection timeout", - } - mock_response = create_mock_response(task_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_task(id=task_id) @@ -98,25 +129,37 @@ def test_get_task_failed(self, mocker): assert result["status"] == "failed" assert result["error"] == "Database connection timeout" - def test_get_task_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "task not found"}, "status": 404}], + indirect=True, + ) + def test_get_task_not_found(self, mocker, create_mock_response): """Test case for get_task with non-existent task""" api = TaskApi() - mock_response = create_mock_response({"error": "task not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(NotFoundException): api.get_task(id=task_id) - def test_get_task_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "completed", + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_task_with_http_info(self, mocker, create_mock_response): """Test case for get_task_with_http_info""" api = TaskApi() - task_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "status": "completed", - } - mock_response = create_mock_response(task_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_task_with_http_info(id=task_id) @@ -124,40 +167,56 @@ def test_get_task_with_http_info(self, mocker): assert result.status_code == 200 assert result.data is not None - def test_get_task_unauthorized(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "unauthorized"}, "status": 401}], + indirect=True, + ) + def test_get_task_unauthorized(self, mocker, create_mock_response): """Test case for get_task without authentication""" api = TaskApi() - mock_response = create_mock_response({"error": "unauthorized"}, status=401) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises((ServiceException, Exception)): api.get_task(id=task_id) - def test_get_task_server_error(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "internal error"}, "status": 500}], + indirect=True, + ) + def test_get_task_server_error(self, mocker, create_mock_response): """Test case for get_task with server error""" api = TaskApi() - mock_response = create_mock_response({"error": "internal error"}, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(ServiceException): api.get_task(id=task_id) - def test_get_task_export_type(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "completed", + "task_type": "export", + "result": { + "format": "json", + "records_exported": 1000, + }, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_task_export_type(self, mocker, create_mock_response): """Test case for get_task with export task type""" api = TaskApi() - task_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "status": "completed", - "task_type": "export", - "result": { - "format": "json", - "records_exported": 1000, - }, - } - mock_response = create_mock_response(task_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_task(id=task_id) @@ -165,19 +224,27 @@ def test_get_task_export_type(self, mocker): assert result["task_type"] == "export" assert result["result"]["records_exported"] == 1000 - def test_get_task_bulk_update_type(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "id": "550e8400-e29b-41d4-a716-446655440000", + "status": "completed", + "task_type": "bulk_update", + "result": { + "updated_count": 150, + }, + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_task_bulk_update_type(self, mocker, create_mock_response): """Test case for get_task with bulk_update task type""" api = TaskApi() - task_data = { - "id": "550e8400-e29b-41d4-a716-446655440000", - "status": "completed", - "task_type": "bulk_update", - "result": { - "updated_count": 150, - }, - } - mock_response = create_mock_response(task_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) task_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_task(id=task_id) diff --git a/test/test_user_api.py b/test/test_user_api.py index 40860be..5207938 100644 --- a/test/test_user_api.py +++ b/test/test_user_api.py @@ -17,18 +17,21 @@ from ibutsu_client.models.token import Token from ibutsu_client.models.token_list import TokenList from ibutsu_client.models.user import User -from test import create_mock_response +from test.utils import sample_pagination_data, sample_token_data, sample_user_data class TestUserApi: """UserApi comprehensive tests""" - def test_add_token_success(self, mocker, sample_token_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_token_data(name="api-token", expires="2025-12-31"), "status": 201}], + indirect=True, + ) + def test_add_token_success(self, mocker, create_mock_response): """Test case for add_token - successfully create a token""" api = UserApi() - token_data = sample_token_data(name="api-token", expires="2025-12-31") - mock_response = create_mock_response(token_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) create_token = CreateToken(name="api-token", expires="2025-12-31") result = api.add_token(create_token=create_token) @@ -38,22 +41,29 @@ def test_add_token_success(self, mocker, sample_token_data): assert result.expires == "2025-12-31" api.api_client.call_api.assert_called_once() - def test_add_token_unauthorized(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "unauthorized"}, "status": 401}], + indirect=True, + ) + def test_add_token_unauthorized(self, mocker, create_mock_response): """Test case for add_token with no authentication""" api = UserApi() - mock_response = create_mock_response({"error": "unauthorized"}, status=401) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) create_token = CreateToken(name="test-token", expires="2025-12-31") with pytest.raises((ServiceException, Exception)): # Should raise unauthorized exception api.add_token(create_token=create_token) - def test_add_token_with_http_info(self, mocker, sample_token_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_token_data(name="test-token"), "status": 201}], + indirect=True, + ) + def test_add_token_with_http_info(self, mocker, create_mock_response): """Test case for add_token_with_http_info""" api = UserApi() - token_data = sample_token_data(name="test-token") - mock_response = create_mock_response(token_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) create_token = CreateToken(name="test-token", expires="2025-12-31") result = api.add_token_with_http_info(create_token=create_token) @@ -61,11 +71,15 @@ def test_add_token_with_http_info(self, mocker, sample_token_data): assert result.status_code == 201 assert isinstance(result.data, Token) - def test_delete_token_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 204}], + indirect=True, + ) + def test_delete_token_success(self, mocker, create_mock_response): """Test case for delete_token - successfully delete a token""" api = UserApi() - mock_response = create_mock_response({}, status=204) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) token_id = "550e8400-e29b-41d4-a716-446655440000" api.delete_token(id=token_id) @@ -73,33 +87,49 @@ def test_delete_token_success(self, mocker): # 204 No Content typically returns None api.api_client.call_api.assert_called_once() - def test_delete_token_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_delete_token_not_found(self, mocker, create_mock_response): """Test case for delete_token with non-existent token""" api = UserApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) token_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(NotFoundException): api.delete_token(id=token_id) - def test_delete_token_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 204}], + indirect=True, + ) + def test_delete_token_with_http_info(self, mocker, create_mock_response): """Test case for delete_token_with_http_info""" api = UserApi() - mock_response = create_mock_response({}, status=204) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) token_id = "550e8400-e29b-41d4-a716-446655440000" result = api.delete_token_with_http_info(id=token_id) assert result.status_code == 204 - def test_get_current_user_success(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": sample_user_data(email="current@example.com", name="Current User"), + "status": 200, + } + ], + indirect=True, + ) + def test_get_current_user_success(self, mocker, create_mock_response): """Test case for get_current_user - retrieve current user details""" api = UserApi() - user_data = sample_user_data(email="current@example.com", name="Current User") - mock_response = create_mock_response(user_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_current_user() @@ -107,33 +137,43 @@ def test_get_current_user_success(self, mocker, sample_user_data): assert result.email == "current@example.com" assert result.name == "Current User" - def test_get_current_user_unauthorized(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "unauthorized"}, "status": 401}], + indirect=True, + ) + def test_get_current_user_unauthorized(self, mocker, create_mock_response): """Test case for get_current_user without authentication""" api = UserApi() - mock_response = create_mock_response({"error": "unauthorized"}, status=401) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) with pytest.raises((ServiceException, Exception)): api.get_current_user() - def test_get_current_user_with_http_info(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_user_data(), "status": 200}], + indirect=True, + ) + def test_get_current_user_with_http_info(self, mocker, create_mock_response): """Test case for get_current_user_with_http_info""" api = UserApi() - user_data = sample_user_data() - mock_response = create_mock_response(user_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_current_user_with_http_info() assert result.status_code == 200 assert isinstance(result.data, User) - def test_get_token_success(self, mocker, sample_token_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_token_data(name="specific-token"), "status": 200}], + indirect=True, + ) + def test_get_token_success(self, mocker, create_mock_response): """Test case for get_token - retrieve a single token""" api = UserApi() - token_data = sample_token_data(name="specific-token") - mock_response = create_mock_response(token_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) token_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_token(id=token_id) @@ -141,22 +181,29 @@ def test_get_token_success(self, mocker, sample_token_data): assert isinstance(result, Token) assert result.name == "specific-token" - def test_get_token_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_get_token_not_found(self, mocker, create_mock_response): """Test case for get_token with non-existent token""" api = UserApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) token_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(NotFoundException): api.get_token(id=token_id) - def test_get_token_with_http_info(self, mocker, sample_token_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_token_data(), "status": 200}], + indirect=True, + ) + def test_get_token_with_http_info(self, mocker, create_mock_response): """Test case for get_token_with_http_info""" api = UserApi() - token_data = sample_token_data() - mock_response = create_mock_response(token_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) token_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_token_with_http_info(id=token_id) @@ -164,58 +211,92 @@ def test_get_token_with_http_info(self, mocker, sample_token_data): assert result.status_code == 200 assert isinstance(result.data, Token) - def test_get_token_list_success(self, mocker, sample_token_data, sample_pagination_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "tokens": [ + sample_token_data(name="token1"), + sample_token_data(name="token2"), + ], + "pagination": sample_pagination_data(page=1, page_size=25, total_items=2), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_token_list_success(self, mocker, create_mock_response): """Test case for get_token_list - retrieve list of tokens""" api = UserApi() - token1 = sample_token_data(name="token1") - token2 = sample_token_data(name="token2") - pagination = sample_pagination_data(page=1, page_size=25, total_items=2) - - response_data = {"tokens": [token1, token2], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_token_list() assert isinstance(result, TokenList) assert len(result.tokens) == 2 - def test_get_token_list_with_pagination( - self, mocker, sample_token_data, sample_pagination_data - ): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "tokens": [sample_token_data()], + "pagination": sample_pagination_data(page=2, page_size=10), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_token_list_with_pagination(self, mocker, create_mock_response): """Test case for get_token_list with pagination parameters""" api = UserApi() - token1 = sample_token_data() - pagination = sample_pagination_data(page=2, page_size=10) - - response_data = {"tokens": [token1], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_token_list(page=2, page_size=10) assert isinstance(result, TokenList) api.api_client.call_api.assert_called_once() - def test_get_token_list_with_http_info(self, mocker, sample_pagination_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "tokens": [], + "pagination": sample_pagination_data(), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_token_list_with_http_info(self, mocker, create_mock_response): """Test case for get_token_list_with_http_info""" api = UserApi() - pagination = sample_pagination_data() - response_data = {"tokens": [], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_token_list_with_http_info() assert result.status_code == 200 assert isinstance(result.data, TokenList) - def test_update_current_user_success(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": sample_user_data(email="current@example.com", name="Current User"), + "status": 200, + } + ], + indirect=True, + ) + def test_update_current_user_success(self, mocker, create_mock_response): """Test case for update_current_user - get current user details""" api = UserApi() - user_data = sample_user_data(email="current@example.com", name="Current User") - mock_response = create_mock_response(user_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.update_current_user() @@ -223,32 +304,43 @@ def test_update_current_user_success(self, mocker, sample_user_data): assert result.email == "current@example.com" assert result.name == "Current User" - def test_update_current_user_unauthorized(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "unauthorized"}, "status": 401}], + indirect=True, + ) + def test_update_current_user_unauthorized(self, mocker, create_mock_response): """Test case for update_current_user without authentication""" api = UserApi() - mock_response = create_mock_response({"error": "unauthorized"}, status=401) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) with pytest.raises((ServiceException, Exception)): api.update_current_user() - def test_update_current_user_with_http_info(self, mocker, sample_user_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_user_data(), "status": 200}], + indirect=True, + ) + def test_update_current_user_with_http_info(self, mocker, create_mock_response): """Test case for update_current_user_with_http_info""" api = UserApi() - user_data = sample_user_data() - mock_response = create_mock_response(user_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.update_current_user_with_http_info() assert result.status_code == 200 assert isinstance(result.data, User) - def test_update_current_user_server_error(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "internal error"}, "status": 500}], + indirect=True, + ) + def test_update_current_user_server_error(self, mocker, create_mock_response): """Test case for update_current_user with server error""" api = UserApi() - mock_response = create_mock_response({"error": "internal error"}, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) with pytest.raises(ServiceException): api.update_current_user() diff --git a/test/test_widget_config_api.py b/test/test_widget_config_api.py index 0837208..e568c52 100644 --- a/test/test_widget_config_api.py +++ b/test/test_widget_config_api.py @@ -15,18 +15,26 @@ from ibutsu_client.exceptions import NotFoundException, ServiceException from ibutsu_client.models.widget_config import WidgetConfig from ibutsu_client.models.widget_config_list import WidgetConfigList -from test import create_mock_response +from test.utils import sample_pagination_data, sample_widget_config_data class TestWidgetConfigApi: """WidgetConfigApi comprehensive tests""" - def test_add_widget_config_success(self, mocker, sample_widget_config_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": sample_widget_config_data(widget="result-summary", weight=0), + "status": 201, + } + ], + indirect=True, + ) + def test_add_widget_config_success(self, mocker, create_mock_response): """Test case for add_widget_config - successfully create a widget config""" api = WidgetConfigApi() - widget_data = sample_widget_config_data(widget="result-summary", weight=0) - mock_response = create_mock_response(widget_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_config = WidgetConfig(type="widget", widget="result-summary", weight=0, params={}) result = api.add_widget_config(widget_config=widget_config) @@ -36,16 +44,26 @@ def test_add_widget_config_success(self, mocker, sample_widget_config_data): assert result.weight == 0 api.api_client.call_api.assert_called_once() - def test_add_widget_config_with_params(self, mocker, sample_widget_config_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": sample_widget_config_data( + widget="result-aggregation", + weight=5, + params={"filter": "result:passed", "chart_type": "bar"}, + ), + "status": 201, + } + ], + indirect=True, + ) + def test_add_widget_config_with_params(self, mocker, create_mock_response): """Test case for add_widget_config with widget parameters""" api = WidgetConfigApi() - params = {"filter": "result:passed", "chart_type": "bar"} - widget_data = sample_widget_config_data( - widget="result-aggregation", weight=5, params=params - ) - mock_response = create_mock_response(widget_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) + params = {"filter": "result:passed", "chart_type": "bar"} widget_config = WidgetConfig( type="widget", widget="result-aggregation", weight=5, params=params ) @@ -54,22 +72,29 @@ def test_add_widget_config_with_params(self, mocker, sample_widget_config_data): assert isinstance(result, WidgetConfig) assert result.params == params - def test_add_widget_config_unauthorized(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "unauthorized"}, "status": 401}], + indirect=True, + ) + def test_add_widget_config_unauthorized(self, mocker, create_mock_response): """Test case for add_widget_config without authentication""" api = WidgetConfigApi() - mock_response = create_mock_response({"error": "unauthorized"}, status=401) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_config = WidgetConfig(type="widget", widget="test", weight=0) with pytest.raises((ServiceException, Exception)): api.add_widget_config(widget_config=widget_config) - def test_add_widget_config_with_http_info(self, mocker, sample_widget_config_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_widget_config_data(), "status": 201}], + indirect=True, + ) + def test_add_widget_config_with_http_info(self, mocker, create_mock_response): """Test case for add_widget_config_with_http_info""" api = WidgetConfigApi() - widget_data = sample_widget_config_data() - mock_response = create_mock_response(widget_data, status=201) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_config = WidgetConfig(type="widget", widget="test", weight=0) result = api.add_widget_config_with_http_info(widget_config=widget_config) @@ -77,11 +102,15 @@ def test_add_widget_config_with_http_info(self, mocker, sample_widget_config_dat assert result.status_code == 201 assert isinstance(result.data, WidgetConfig) - def test_delete_widget_config_success(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 204}], + indirect=True, + ) + def test_delete_widget_config_success(self, mocker, create_mock_response): """Test case for delete_widget_config - successfully delete a widget""" api = WidgetConfigApi() - mock_response = create_mock_response({}, status=204) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" api.delete_widget_config(id=widget_id) @@ -89,33 +118,49 @@ def test_delete_widget_config_success(self, mocker): # 204 No Content typically returns None api.api_client.call_api.assert_called_once() - def test_delete_widget_config_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_delete_widget_config_not_found(self, mocker, create_mock_response): """Test case for delete_widget_config with non-existent widget""" api = WidgetConfigApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(NotFoundException): api.delete_widget_config(id=widget_id) - def test_delete_widget_config_with_http_info(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {}, "status": 204}], + indirect=True, + ) + def test_delete_widget_config_with_http_info(self, mocker, create_mock_response): """Test case for delete_widget_config_with_http_info""" api = WidgetConfigApi() - mock_response = create_mock_response({}, status=204) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" result = api.delete_widget_config_with_http_info(id=widget_id) assert result.status_code == 204 - def test_get_widget_config_success(self, mocker, sample_widget_config_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": sample_widget_config_data(widget="jenkins-heatmap"), + "status": 200, + } + ], + indirect=True, + ) + def test_get_widget_config_success(self, mocker, create_mock_response): """Test case for get_widget_config - retrieve a single widget config""" api = WidgetConfigApi() - widget_data = sample_widget_config_data(widget="jenkins-heatmap") - mock_response = create_mock_response(widget_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_widget_config(id=widget_id) @@ -123,22 +168,29 @@ def test_get_widget_config_success(self, mocker, sample_widget_config_data): assert isinstance(result, WidgetConfig) assert result.widget == "jenkins-heatmap" - def test_get_widget_config_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_get_widget_config_not_found(self, mocker, create_mock_response): """Test case for get_widget_config with non-existent widget""" api = WidgetConfigApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" with pytest.raises(NotFoundException): api.get_widget_config(id=widget_id) - def test_get_widget_config_with_http_info(self, mocker, sample_widget_config_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_widget_config_data(), "status": 200}], + indirect=True, + ) + def test_get_widget_config_with_http_info(self, mocker, create_mock_response): """Test case for get_widget_config_with_http_info""" api = WidgetConfigApi() - widget_data = sample_widget_config_data() - mock_response = create_mock_response(widget_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" result = api.get_widget_config_with_http_info(id=widget_id) @@ -146,76 +198,115 @@ def test_get_widget_config_with_http_info(self, mocker, sample_widget_config_dat assert result.status_code == 200 assert isinstance(result.data, WidgetConfig) - def test_get_widget_config_list_success( - self, mocker, sample_widget_config_data, sample_pagination_data - ): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "widgets": [ + sample_widget_config_data(widget="result-summary", weight=0), + sample_widget_config_data(widget="jenkins-heatmap", weight=1), + ], + "pagination": sample_pagination_data(total_items=2), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_widget_config_list_success(self, mocker, create_mock_response): """Test case for get_widget_config_list - retrieve list of widget configs""" api = WidgetConfigApi() - widget1 = sample_widget_config_data(widget="result-summary", weight=0) - widget2 = sample_widget_config_data(widget="jenkins-heatmap", weight=1) - pagination = sample_pagination_data(total_items=2) - - response_data = { - "widgets": [widget1, widget2], - "pagination": pagination, - } - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_widget_config_list() assert isinstance(result, WidgetConfigList) assert len(result.widgets) == 2 - def test_get_widget_config_list_with_filters( - self, mocker, sample_widget_config_data, sample_pagination_data - ): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "widgets": [sample_widget_config_data()], + "pagination": sample_pagination_data(total_items=1), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_widget_config_list_with_filters(self, mocker, create_mock_response): """Test case for get_widget_config_list with filter parameters""" api = WidgetConfigApi() - widget1 = sample_widget_config_data() - pagination = sample_pagination_data(total_items=1) - - response_data = {"widgets": [widget1], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_widget_config_list(filter=["widget_type=result-summary"]) assert isinstance(result, WidgetConfigList) api.api_client.call_api.assert_called_once() - def test_get_widget_config_list_empty(self, mocker, sample_pagination_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "widgets": [], + "pagination": sample_pagination_data(total_items=0), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_widget_config_list_empty(self, mocker, create_mock_response): """Test case for get_widget_config_list with no widgets""" api = WidgetConfigApi() - pagination = sample_pagination_data(total_items=0) - response_data = {"widgets": [], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_widget_config_list() assert isinstance(result, WidgetConfigList) assert len(result.widgets) == 0 - def test_get_widget_config_list_with_http_info(self, mocker, sample_pagination_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": { + "widgets": [], + "pagination": sample_pagination_data(), + }, + "status": 200, + } + ], + indirect=True, + ) + def test_get_widget_config_list_with_http_info(self, mocker, create_mock_response): """Test case for get_widget_config_list_with_http_info""" api = WidgetConfigApi() - pagination = sample_pagination_data() - response_data = {"widgets": [], "pagination": pagination} - mock_response = create_mock_response(response_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) result = api.get_widget_config_list_with_http_info() assert result.status_code == 200 assert isinstance(result.data, WidgetConfigList) - def test_update_widget_config_success(self, mocker, sample_widget_config_data): + @pytest.mark.parametrize( + "create_mock_response", + [ + { + "data": sample_widget_config_data(widget="result-summary", weight=10), + "status": 200, + } + ], + indirect=True, + ) + def test_update_widget_config_success(self, mocker, create_mock_response): """Test case for update_widget_config - successfully update a widget config""" api = WidgetConfigApi() - updated_data = sample_widget_config_data(widget="result-summary", weight=10) - mock_response = create_mock_response(updated_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" widget_config = WidgetConfig(type="widget", widget="result-summary", weight=10) @@ -224,23 +315,30 @@ def test_update_widget_config_success(self, mocker, sample_widget_config_data): assert isinstance(result, WidgetConfig) assert result.weight == 10 - def test_update_widget_config_not_found(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "not found"}, "status": 404}], + indirect=True, + ) + def test_update_widget_config_not_found(self, mocker, create_mock_response): """Test case for update_widget_config with non-existent widget""" api = WidgetConfigApi() - mock_response = create_mock_response({"error": "not found"}, status=404) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" widget_config = WidgetConfig(type="widget", widget="test", weight=0) with pytest.raises(NotFoundException): api.update_widget_config(id=widget_id, widget_config=widget_config) - def test_update_widget_config_with_http_info(self, mocker, sample_widget_config_data): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": sample_widget_config_data(), "status": 200}], + indirect=True, + ) + def test_update_widget_config_with_http_info(self, mocker, create_mock_response): """Test case for update_widget_config_with_http_info""" api = WidgetConfigApi() - widget_data = sample_widget_config_data() - mock_response = create_mock_response(widget_data, status=200) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" widget_config = WidgetConfig(type="widget", widget="test", weight=5) @@ -249,11 +347,15 @@ def test_update_widget_config_with_http_info(self, mocker, sample_widget_config_ assert result.status_code == 200 assert isinstance(result.data, WidgetConfig) - def test_update_widget_config_server_error(self, mocker): + @pytest.mark.parametrize( + "create_mock_response", + [{"data": {"error": "internal error"}, "status": 500}], + indirect=True, + ) + def test_update_widget_config_server_error(self, mocker, create_mock_response): """Test case for update_widget_config with server error""" api = WidgetConfigApi() - mock_response = create_mock_response({"error": "internal error"}, status=500) - mocker.patch.object(api.api_client, "call_api", return_value=mock_response) + mocker.patch.object(api.api_client, "call_api", return_value=create_mock_response) widget_id = "550e8400-e29b-41d4-a716-446655440000" widget_config = WidgetConfig(type="widget", widget="test", weight=0) diff --git a/test/utils.py b/test/utils.py new file mode 100644 index 0000000..f32e4f5 --- /dev/null +++ b/test/utils.py @@ -0,0 +1,372 @@ +"""Test data factory functions for ibutsu_client tests.""" + +import uuid +from typing import Any + + +def sample_project_data( + project_id: str | None = None, + name: str = "test-project", + title: str = "Test Project", + owner_id: str | None = None, + group_id: str | None = None, +) -> dict[str, Any]: + """Factory function to create sample project data. + + Args: + project_id: Project UUID (generated if not provided) + name: Machine name of the project + title: Human-readable title + owner_id: Owner UUID + group_id: Group UUID + + Returns: + Dictionary with project data + """ + if project_id is None: + project_id = str(uuid.uuid4()) + if owner_id is None: + owner_id = str(uuid.uuid4()) + if group_id is None: + group_id = str(uuid.uuid4()) + + return { + "id": project_id, + "name": name, + "title": title, + "owner_id": owner_id, + "group_id": group_id, + } + + +def sample_run_data( + run_id: str | None = None, + project_id: str | None = None, + created: str = "2024-01-15T10:00:00", + start_time: str = "2024-01-15T10:00:00", + duration: float = 120.5, + source: str = "pytest", + component: str = "api", + env: str = "test", + summary: dict[str, Any] | None = None, + metadata: dict[str, Any] | None = None, +) -> dict[str, Any]: + """Factory function to create sample test run data. + + Args: + run_id: Run UUID (generated if not provided) + project_id: Project UUID (generated if not provided) + created: ISO timestamp of creation + start_time: ISO timestamp of run start + duration: Duration in seconds + source: Source system identifier + component: Component under test + env: Test environment + summary: Summary statistics + metadata: Additional metadata + + Returns: + Dictionary with run data + """ + if run_id is None: + run_id = str(uuid.uuid4()) + if project_id is None: + project_id = str(uuid.uuid4()) + if summary is None: + summary = {"passed": 10, "failed": 2, "skipped": 1, "errors": 0, "xfailed": 0} + if metadata is None: + metadata = {"jenkins_build": "123", "branch": "main"} + + return { + "id": run_id, + "project_id": project_id, + "created": created, + "start_time": start_time, + "duration": duration, + "source": source, + "component": component, + "env": env, + "summary": summary, + "metadata": metadata, + } + + +def sample_result_data( + result_id: str | None = None, + run_id: str | None = None, + project_id: str | None = None, + test_id: str = "test_example.py::TestClass::test_method", + start_time: str = "2024-01-15T10:00:00", + duration: float = 1.5, + result: str = "passed", + component: str = "api", + env: str = "test", + source: str = "pytest", + metadata: dict[str, Any] | None = None, + params: dict[str, Any] | None = None, +) -> dict[str, Any]: + """Factory function to create sample test result data. + + Args: + result_id: Result UUID (generated if not provided) + run_id: Associated run UUID (generated if not provided) + project_id: Project UUID (generated if not provided) + test_id: Test identifier + start_time: ISO timestamp + duration: Duration in seconds + result: Test result status (passed, failed, error, skipped, etc.) + component: Component under test + env: Test environment + source: Source system identifier + metadata: Additional metadata + params: Test parameters + + Returns: + Dictionary with result data + """ + if result_id is None: + result_id = str(uuid.uuid4()) + if run_id is None: + run_id = str(uuid.uuid4()) + if project_id is None: + project_id = str(uuid.uuid4()) + if metadata is None: + metadata = {"test_file": "test_example.py", "line_number": 42} + if params is None: + params = {} + + return { + "id": result_id, + "run_id": run_id, + "project_id": project_id, + "test_id": test_id, + "start_time": start_time, + "duration": duration, + "result": result, + "component": component, + "env": env, + "source": source, + "metadata": metadata, + "params": params, + } + + +def sample_artifact_data( + artifact_id: str | None = None, + filename: str = "test_log.txt", + result_id: str | None = None, + run_id: str | None = None, + project_id: str | None = None, +) -> dict[str, Any]: + """Factory function to create sample artifact data. + + Args: + artifact_id: Artifact UUID (generated if not provided) + filename: Artifact filename + result_id: Associated result UUID + run_id: Associated run UUID + project_id: Project UUID + + Returns: + Dictionary with artifact data + """ + if artifact_id is None: + artifact_id = str(uuid.uuid4()) + if result_id is None: + result_id = str(uuid.uuid4()) + if run_id is None: + run_id = str(uuid.uuid4()) + if project_id is None: + project_id = str(uuid.uuid4()) + + return { + "id": artifact_id, + "filename": filename, + "result_id": result_id, + "run_id": run_id, + "project_id": project_id, + } + + +def sample_pagination_data( + page: int = 1, + page_size: int = 25, + total_items: int = 100, + total_pages: int = 4, +) -> dict[str, Any]: + """Factory function to create sample pagination data. + + Args: + page: Current page number + page_size: Number of items per page + total_items: Total number of items + total_pages: Total number of pages + + Returns: + Dictionary with pagination data + """ + return { + "page": page, + "pageSize": page_size, + "totalItems": total_items, + "totalPages": total_pages, + } + + +def sample_user_data( + user_id: str | None = None, + email: str = "test@example.com", + name: str = "Test User", + is_superadmin: bool = False, + is_active: bool = True, +) -> dict[str, Any]: + """Factory function to create sample user data. + + Args: + user_id: User UUID (generated if not provided) + email: User email address + name: User full name + is_superadmin: Whether user is a superadmin + is_active: Whether user account is active + + Returns: + Dictionary with user data + """ + if user_id is None: + user_id = str(uuid.uuid4()) + + return { + "id": user_id, + "email": email, + "name": name, + "is_superadmin": is_superadmin, + "is_active": is_active, + } + + +def sample_dashboard_data( + dashboard_id: str | None = None, + title: str = "Test Dashboard", + project_id: str | None = None, + description: str | None = None, + filters: str | None = None, +) -> dict[str, Any]: + """Factory function to create sample dashboard data. + + Args: + dashboard_id: Dashboard UUID (generated if not provided) + title: Dashboard title + project_id: Project UUID (generated if not provided) + description: Dashboard description + filters: Dashboard filters + + Returns: + Dictionary with dashboard data + """ + if dashboard_id is None: + dashboard_id = str(uuid.uuid4()) + if project_id is None: + project_id = str(uuid.uuid4()) + + data = { + "id": dashboard_id, + "title": title, + "project_id": project_id, + } + if description is not None: + data["description"] = description + if filters is not None: + data["filters"] = filters + + return data + + +def sample_widget_config_data( + widget_id: str | None = None, + widget: str = "result-summary", + config_type: str = "widget", + weight: int = 0, + params: dict[str, Any] | None = None, + title: str | None = None, +) -> dict[str, Any]: + """Factory function to create sample widget configuration data. + + Args: + widget_id: Widget UUID (generated if not provided) + widget: Widget name to render + config_type: Type of config ("widget" or "view") + weight: Widget display weight/order + params: Widget parameters + title: Widget title + + Returns: + Dictionary with widget config data + """ + if widget_id is None: + widget_id = str(uuid.uuid4()) + if params is None: + params = {} + + return { + "id": widget_id, + "type": config_type, + "widget": widget, + "weight": weight, + "params": params, + "title": title, + } + + +def sample_group_data( + group_id: str | None = None, + name: str = "test-group", +) -> dict[str, Any]: + """Factory function to create sample group data. + + Args: + group_id: Group UUID (generated if not provided) + name: Group name + + Returns: + Dictionary with group data + """ + if group_id is None: + group_id = str(uuid.uuid4()) + + return { + "id": group_id, + "name": name, + } + + +def sample_token_data( + token_id: str | None = None, + user_id: str | None = None, + name: str = "test-token", + token: str = "test-token-value", + expires: str | None = "2025-12-31", +) -> dict[str, Any]: + """Factory function to create sample token data. + + Args: + token_id: Token UUID (generated if not provided) + user_id: User UUID (generated if not provided) + name: Token name/identifier + token: The actual token string + expires: Expiration date + + Returns: + Dictionary with token data + """ + if token_id is None: + token_id = str(uuid.uuid4()) + if user_id is None: + user_id = str(uuid.uuid4()) + + return { + "id": token_id, + "user_id": user_id, + "name": name, + "token": token, + "expires": expires, + }