""" Extended unit tests for KworkClient to improve coverage. These tests cover additional API endpoints and edge cases. """ import pytest import respx from httpx import Response from kwork_api import KworkApiError, KworkClient from kwork_api.models import ( Badge, City, Country, Dialog, Feature, Kwork, NotificationsResponse, Project, TimeZone, ) BASE_URL = "https://api.kwork.ru" class TestClientProperties: """Test client properties and initialization.""" def test_token_property(self): """Test token property getter.""" client = KworkClient(token="test_token_123") assert client.token == "test_token_123" def test_token_property_none(self): """Test token property when no token.""" client = KworkClient() assert client.token is None def test_cookies_property_empty(self): """Test cookies property with no cookies.""" client = KworkClient(token="test") assert client.cookies == {} def test_cookies_property_with_cookies(self): """Test cookies property returns copy.""" client = KworkClient(token="test", cookies={"userId": "123", "session": "abc"}) cookies = client.cookies assert cookies == {"userId": "123", "session": "abc"} cookies["modified"] = "value" assert "modified" not in client.cookies def test_credentials_property(self): """Test credentials property returns token and cookies.""" client = KworkClient(token="test_token", cookies={"userId": "123"}) creds = client.credentials assert creds["token"] == "test_token" assert creds["cookies"] == {"userId": "123"} def test_credentials_property_no_cookies(self): """Test credentials with no cookies.""" client = KworkClient(token="test_token") creds = client.credentials assert creds["token"] == "test_token" assert creds["cookies"] is None class TestCatalogAPIExtended: """Extended tests for CatalogAPI.""" @respx.mock async def test_get_details_extra(self): """Test get_details_extra endpoint.""" client = KworkClient(token="test") mock_data = { "id": 456, "title": "Extra Details Kwork", "extra_field": "extra_value", } respx.post(f"{BASE_URL}/getKworkDetailsExtra").mock( return_value=Response(200, json=mock_data) ) result = await client.catalog.get_details_extra(456) assert result["id"] == 456 assert result["extra_field"] == "extra_value" class TestProjectsAPIExtended: """Extended tests for ProjectsAPI.""" @respx.mock async def test_get_payer_orders(self): """Test getting payer orders.""" client = KworkClient(token="test") mock_data = { "orders": [ {"id": 101, "title": "Order 1", "amount": 5000.0, "status": "active"}, ] } respx.post(f"{BASE_URL}/payerOrders").mock(return_value=Response(200, json=mock_data)) result = await client.projects.get_payer_orders() assert isinstance(result, list) assert len(result) == 1 assert isinstance(result[0], Project) @respx.mock async def test_get_worker_orders(self): """Test getting worker orders.""" client = KworkClient(token="test") mock_data = { "orders": [ {"id": 202, "title": "Worker Order", "amount": 3000.0, "status": "completed"}, ] } respx.post(f"{BASE_URL}/workerOrders").mock(return_value=Response(200, json=mock_data)) result = await client.projects.get_worker_orders() assert isinstance(result, list) assert len(result) == 1 class TestUserAPI: """Tests for UserAPI.""" @respx.mock async def test_get_info(self): """Test getting user info.""" client = KworkClient(token="test") mock_data = { "userId": 12345, "username": "testuser", "email": "test@example.com", "balance": 50000.0, } respx.post(f"{BASE_URL}/user").mock(return_value=Response(200, json=mock_data)) result = await client.user.get_info() assert result["userId"] == 12345 assert result["username"] == "testuser" @respx.mock async def test_get_reviews(self): """Test getting user reviews.""" client = KworkClient(token="test") mock_data = { "reviews": [ { "id": 1, "rating": 5, "comment": "Great work!", "author": {"id": 999, "username": "client1"}, }, ], "pagination": {"current_page": 1, "total_pages": 5}, } respx.post(f"{BASE_URL}/userReviews").mock(return_value=Response(200, json=mock_data)) result = await client.user.get_reviews(user_id=12345, page=1) assert len(result.reviews) == 1 assert result.reviews[0].rating == 5 @respx.mock async def test_get_favorite_kworks(self): """Test getting favorite kworks.""" client = KworkClient(token="test") mock_data = { "kworks": [ {"id": 100, "title": "Favorite Kwork 1", "price": 2000.0}, {"id": 101, "title": "Favorite Kwork 2", "price": 3000.0}, ] } respx.post(f"{BASE_URL}/favoriteKworks").mock(return_value=Response(200, json=mock_data)) result = await client.user.get_favorite_kworks() assert isinstance(result, list) assert len(result) == 2 assert isinstance(result[0], Kwork) class TestReferenceAPI: """Tests for ReferenceAPI.""" @respx.mock async def test_get_cities(self): """Test getting cities list.""" client = KworkClient(token="test") mock_data = { "cities": [ {"id": 1, "name": "Москва", "country_id": 1}, {"id": 2, "name": "Санкт-Петербург", "country_id": 1}, ] } respx.post(f"{BASE_URL}/cities").mock(return_value=Response(200, json=mock_data)) result = await client.reference.get_cities() assert isinstance(result, list) assert len(result) == 2 assert isinstance(result[0], City) @respx.mock async def test_get_countries(self): """Test getting countries list.""" client = KworkClient(token="test") mock_data = { "countries": [ {"id": 1, "name": "Россия", "code": "RU"}, {"id": 2, "name": "Беларусь", "code": "BY"}, ] } respx.post(f"{BASE_URL}/countries").mock(return_value=Response(200, json=mock_data)) result = await client.reference.get_countries() assert isinstance(result, list) assert len(result) == 2 assert isinstance(result[0], Country) @respx.mock async def test_get_timezones(self): """Test getting timezones list.""" client = KworkClient(token="test") mock_data = { "timezones": [ {"id": 1, "name": "Europe/Moscow", "offset": "+03:00"}, {"id": 2, "name": "Europe/Kaliningrad", "offset": "+02:00"}, ] } respx.post(f"{BASE_URL}/timezones").mock(return_value=Response(200, json=mock_data)) result = await client.reference.get_timezones() assert isinstance(result, list) assert len(result) == 2 assert isinstance(result[0], TimeZone) @respx.mock async def test_get_features(self): """Test getting features list.""" client = KworkClient(token="test") mock_data = { "features": [ {"id": 1, "name": "Feature 1", "category_id": 5, "price": 1000, "type": "extra"}, {"id": 2, "name": "Feature 2", "category_id": 5, "price": 2000, "type": "extra"}, ] } respx.post(f"{BASE_URL}/getAvailableFeatures").mock( return_value=Response(200, json=mock_data) ) result = await client.reference.get_features() assert isinstance(result, list) assert len(result) == 2 assert isinstance(result[0], Feature) @respx.mock async def test_get_public_features(self): """Test getting public features list.""" client = KworkClient(token="test") mock_data = { "features": [ { "id": 10, "name": "Public Feature", "is_public": True, "price": 500, "type": "extra", }, ] } respx.post(f"{BASE_URL}/getPublicFeatures").mock(return_value=Response(200, json=mock_data)) result = await client.reference.get_public_features() assert isinstance(result, list) assert len(result) == 1 @respx.mock async def test_get_badges_info(self): """Test getting badges info.""" client = KworkClient(token="test") mock_data = { "badges": [ {"id": 1, "name": "Pro Seller", "icon_url": "https://example.com/badge1.png"}, {"id": 2, "name": "Verified", "icon_url": "https://example.com/badge2.png"}, ] } respx.post(f"{BASE_URL}/getBadgesInfo").mock(return_value=Response(200, json=mock_data)) result = await client.reference.get_badges_info() assert isinstance(result, list) assert len(result) == 2 assert isinstance(result[0], Badge) class TestNotificationsAPI: """Tests for NotificationsAPI.""" @respx.mock async def test_get_list(self): """Test getting notifications list.""" client = KworkClient(token="test") mock_data = { "notifications": [ { "id": 1, "type": "order", "title": "New Order", "message": "New order received", "is_read": False, }, { "id": 2, "type": "message", "title": "New Message", "message": "You have a new message", "is_read": True, }, ], "unread_count": 5, } respx.post(f"{BASE_URL}/notifications").mock(return_value=Response(200, json=mock_data)) result = await client.notifications.get_list() assert isinstance(result, NotificationsResponse) assert result.unread_count == 5 @respx.mock async def test_fetch(self): """Test fetching notifications.""" client = KworkClient(token="test") mock_data = { "notifications": [ { "id": 3, "type": "system", "title": "System Update", "message": "System update available", "is_read": False, }, ], "unread_count": 1, } respx.post(f"{BASE_URL}/notificationsFetch").mock( return_value=Response(200, json=mock_data) ) result = await client.notifications.fetch() assert isinstance(result, NotificationsResponse) assert len(result.notifications) == 1 @respx.mock async def test_get_dialogs(self): """Test getting dialogs.""" client = KworkClient(token="test") mock_data = { "dialogs": [ {"id": 1, "user_id": 100, "last_message": "Hello", "unread": 2}, {"id": 2, "user_id": 200, "last_message": "Hi", "unread": 0}, ] } respx.post(f"{BASE_URL}/dialogs").mock(return_value=Response(200, json=mock_data)) result = await client.notifications.get_dialogs() assert isinstance(result, list) assert len(result) == 2 assert isinstance(result[0], Dialog) @respx.mock async def test_get_blocked_dialogs(self): """Test getting blocked dialogs.""" client = KworkClient(token="test") mock_data = { "dialogs": [ {"id": 99, "user_id": 999, "last_message": "Spam", "blocked": True}, ] } respx.post(f"{BASE_URL}/blockedDialogList").mock(return_value=Response(200, json=mock_data)) result = await client.notifications.get_blocked_dialogs() assert isinstance(result, list) assert len(result) == 1 class TestOtherAPI: """Tests for OtherAPI.""" @respx.mock async def test_get_wants(self): """Test getting wants.""" client = KworkClient(token="test") mock_data = { "wants": [{"id": 1, "title": "I need a logo"}], "count": 1, } respx.post(f"{BASE_URL}/myWants").mock(return_value=Response(200, json=mock_data)) result = await client.other.get_wants() assert "wants" in result assert result["count"] == 1 @respx.mock async def test_get_wants_status(self): """Test getting wants status.""" client = KworkClient(token="test") mock_data = { "active_wants": 5, "completed_wants": 10, } respx.post(f"{BASE_URL}/wantsStatusList").mock(return_value=Response(200, json=mock_data)) result = await client.other.get_wants_status() assert result["active_wants"] == 5 @respx.mock async def test_get_kworks_status(self): """Test getting kworks status.""" client = KworkClient(token="test") mock_data = { "active_kworks": 3, "total_sales": 50, } respx.post(f"{BASE_URL}/kworksStatusList").mock(return_value=Response(200, json=mock_data)) result = await client.other.get_kworks_status() assert result["active_kworks"] == 3 @respx.mock async def test_get_offers(self): """Test getting offers.""" client = KworkClient(token="test") mock_data = { "offers": [{"id": 1, "title": "Special offer"}], } respx.post(f"{BASE_URL}/offers").mock(return_value=Response(200, json=mock_data)) result = await client.other.get_offers() assert "offers" in result @respx.mock async def test_get_exchange_info(self): """Test getting exchange info.""" client = KworkClient(token="test") mock_data = { "usd_rate": 90.5, "eur_rate": 98.2, } respx.post(f"{BASE_URL}/exchangeInfo").mock(return_value=Response(200, json=mock_data)) result = await client.other.get_exchange_info() assert result["usd_rate"] == 90.5 @respx.mock async def test_get_channel(self): """Test getting channel info.""" client = KworkClient(token="test") mock_data = { "channel_id": "main", "name": "Main Channel", } respx.post(f"{BASE_URL}/getChannel").mock(return_value=Response(200, json=mock_data)) result = await client.other.get_channel() assert result["channel_id"] == "main" @respx.mock async def test_get_in_app_notification(self): """Test getting in-app notifications.""" client = KworkClient(token="test") mock_data = { "notifications": [{"id": 1, "message": "App update"}], } respx.post(f"{BASE_URL}/getInAppNotification").mock( return_value=Response(200, json=mock_data) ) result = await client.other.get_in_app_notification() assert "notifications" in result @respx.mock async def test_get_security_user_data(self): """Test getting security user data.""" client = KworkClient(token="test") mock_data = { "two_factor_enabled": True, "last_login": "2024-01-01T00:00:00Z", } respx.post(f"{BASE_URL}/getSecurityUserData").mock( return_value=Response(200, json=mock_data) ) result = await client.other.get_security_user_data() assert result["two_factor_enabled"] is True @respx.mock async def test_is_dialog_allow_true(self): """Test is_dialog_allow returns True.""" client = KworkClient(token="test") respx.post(f"{BASE_URL}/isDialogAllow").mock( return_value=Response(200, json={"allowed": True}) ) result = await client.other.is_dialog_allow(12345) assert result is True @respx.mock async def test_is_dialog_allow_false(self): """Test is_dialog_allow returns False.""" client = KworkClient(token="test") respx.post(f"{BASE_URL}/isDialogAllow").mock( return_value=Response(200, json={"allowed": False}) ) result = await client.other.is_dialog_allow(67890) assert result is False @respx.mock async def test_get_viewed_kworks(self): """Test getting viewed kworks.""" client = KworkClient(token="test") mock_data = { "kworks": [ {"id": 500, "title": "Viewed Kwork", "price": 1500.0}, ] } respx.post(f"{BASE_URL}/viewedCatalogKworks").mock( return_value=Response(200, json=mock_data) ) result = await client.other.get_viewed_kworks() assert isinstance(result, list) assert len(result) == 1 assert isinstance(result[0], Kwork) @respx.mock async def test_get_favorite_categories(self): """Test getting favorite categories.""" client = KworkClient(token="test") mock_data = { "categories": [1, 5, 10, 15], } respx.post(f"{BASE_URL}/favoriteCategories").mock( return_value=Response(200, json=mock_data) ) result = await client.other.get_favorite_categories() assert isinstance(result, list) assert 1 in result assert 5 in result @respx.mock async def test_update_settings(self): """Test updating settings.""" client = KworkClient(token="test") mock_data = { "success": True, "updated": {"notifications_enabled": False}, } respx.post(f"{BASE_URL}/updateSettings").mock(return_value=Response(200, json=mock_data)) settings = {"notifications_enabled": False, "theme": "dark"} result = await client.other.update_settings(settings) assert result["success"] is True @respx.mock async def test_go_offline(self): """Test going offline.""" client = KworkClient(token="test") mock_data = { "success": True, "status": "offline", } respx.post(f"{BASE_URL}/offline").mock(return_value=Response(200, json=mock_data)) result = await client.other.go_offline() assert result["success"] is True assert result["status"] == "offline" @respx.mock async def test_get_actor(self): """Test getting actor info.""" client = KworkClient(token="test") mock_data = { "actor_id": 123, "name": "Test Actor", } respx.post(f"{BASE_URL}/actor").mock(return_value=Response(200, json=mock_data)) result = await client.other.get_actor() assert result["actor_id"] == 123 class TestClientInternals: """Tests for internal client methods.""" def test_handle_response_success(self): """Test _handle_response with successful response.""" import httpx client = KworkClient(token="test") response = httpx.Response(200, json={"success": True, "data": "test"}) result = client._handle_response(response) assert result["success"] is True assert result["data"] == "test" def test_handle_response_error(self): """Test _handle_response with error response.""" import httpx client = KworkClient(token="test") response = httpx.Response(400, json={"message": "Bad request"}) with pytest.raises(KworkApiError) as exc_info: client._handle_response(response) assert exc_info.value.status_code == 400 @respx.mock async def test_request_method(self): """Test _request method directly.""" client = KworkClient(token="test") mock_data = {"result": "success"} respx.post(f"{BASE_URL}/test-endpoint").mock(return_value=Response(200, json=mock_data)) result = await client._request("POST", "/test-endpoint", json={"param": "value"}) assert result["result"] == "success" async def test_context_manager_creates_client(self): """Test that context manager creates httpx client.""" async with KworkClient(token="test") as client: assert client.token == "test" assert client._client is None or client._client.is_closed