test: add extended tests to improve coverage to 93%

This commit is contained in:
root 2026-03-29 08:01:07 +00:00
parent b9a20bdfae
commit 1c81fa9b3c

View File

@ -0,0 +1,743 @@
"""
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 KworkClient, KworkAuthError, KworkApiError
from kwork_api.models import (
NotificationsResponse,
Kwork,
Dialog,
City,
Country,
TimeZone,
Feature,
Badge,
Project,
)
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