Skip to content

Commit fd124c8

Browse files
authored
Merge pull request #15 from ZhikharevAl/tests/tests
add tests
2 parents 0730b8e + df04cc8 commit fd124c8

19 files changed

+642
-4
lines changed

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ Automatically run before each commit:
8787

8888
### Example Model
8989

90-
9190
```python
9291
from pydantic import BaseModel, Field
9392

@@ -152,6 +151,21 @@ project-root/
152151
└── .pre-commit-config.yaml # Pre-commit configuration
153152
```
154153

154+
## Coverage Report 📊
155+
156+
```python
157+
pytest --cov=tests/
158+
```
159+
160+
| Name | Stmts | Miss | Cover |
161+
|-------------------------|-------|------|-------|
162+
| tests\__init__.py | 0 | 0 | 100% |
163+
| tests\test_games.py | 45 | 6 | 87% |
164+
| tests\test_users.py | 80 | 26 | 68% |
165+
| tests\test_wishlist.py | 28 | 3 | 89% |
166+
|-------------------------|-------|------|-------|
167+
| TOTAL | 153 | 35 | 77% |
168+
155169
## Best Practices 📘
156170

157171
- Use `uv` for dependency management
@@ -162,6 +176,13 @@ project-root/
162176
- Use fixtures for test setup/teardown
163177
- Parameterize tests
164178
- Validate response schemas
179+
- coverage report
180+
181+
## 📝 TODO
182+
183+
- [ ] Refactor tests to use fixtures
184+
- [ ] 🎯 Target: 90%+ test coverage
185+
- [ ] Dynamic test data generation
165186

166187
## License
167188

conftest.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from services.games.games_api_client import GamesAPIClient
1111
from services.users.user_api_client import UserAPIClient
12+
from services.wishlist.api_client_wishlist import WishlistAPIClient
1213

1314
load_dotenv()
1415

@@ -44,6 +45,12 @@ def game_api_client(api_request_context: APIRequestContext) -> GamesAPIClient:
4445
return GamesAPIClient(api_request_context)
4546

4647

48+
@pytest.fixture
49+
def wishlist_api_client(api_request_context: APIRequestContext) -> WishlistAPIClient:
50+
"""Wishlist API client."""
51+
return WishlistAPIClient(api_request_context)
52+
53+
4754
@pytest.fixture(params=["api-3", "api-22"])
4855
def new_user(
4956
user_api_client: UserAPIClient, request: pytest.FixtureRequest
@@ -55,7 +62,7 @@ def new_user(
5562
:param request: Fixture request object, used for parametrization
5663
"""
5764
task_id = request.param
58-
user = user_api_client.create_user(task_id)
65+
user: dict[str, Any] = user_api_client.create_user(task_id)
5966

6067
yield user
6168

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Bug Report: Failed to Add Game to Wishlist
2+
3+
**ID**: BUG-WISHLIST-001
4+
**Title**: Unable to Add Game to User Wishlist with Unprocessable Entity Error
5+
6+
## Description
7+
8+
When attempting to add a game to a user's wishlist using the `add_an_item_to_wishlist` method, the API returns a 422 Unprocessable Entity error, preventing the game from being added to the wishlist.
9+
10+
## Steps to Reproduce
11+
12+
1. Create a new user
13+
2. Use a valid game UUID
14+
3. Call `add_an_item_to_wishlist` method
15+
4. Verify task IDs: `api-5`, `api-25`
16+
17+
## Expected Result
18+
19+
- Successfully add the game to the user's wishlist
20+
- Return a valid `Wishlist` object
21+
- Wishlist contains the added game item
22+
23+
## Actual Result
24+
25+
- HTTP Status Code: 422 Unprocessable Entity
26+
- Unable to add game to wishlist
27+
- Error prevents wishlist modification
28+
29+
## Technical Details
30+
31+
- Method: `add_an_item_to_wishlist()`
32+
- Endpoint: Likely `/wishlist/add`
33+
- Task-Ids: `api-5`
34+
- Game UUID: `03dbad48-ad81-433d-9901-dd5332f5d9ee`
35+
36+
## Impact
37+
38+
**High** - Prevents users from adding games to their wishlist
39+
40+
## Recommended Actions
41+
42+
1. Investigate API validation rules
43+
2. Check input parameter constraints
44+
3. Verify game and user UUID compatibility
45+
4. Review wishlist item addition logic
46+
5. Add detailed error messaging
47+
48+
## Priority
49+
50+
**High** - Critical for user experience
51+
52+
## Potential Root Causes
53+
54+
- Validation schema mismatch
55+
- Incorrect UUID processing
56+
- Backend constraint violations
57+
- Incomplete input validation
58+
59+
## Reproducibility
60+
61+
- Consistently reproducible
62+
- Occurs with multiple task IDs
63+
- Requires immediate investigation
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Test Case: Add Game to User Wishlist
2+
3+
**ID**: TC-WISHLIST-001
4+
**Objective**: Verify Game Addition to User Wishlist
5+
6+
## Description
7+
8+
Ensure users can successfully add a game to their wishlist with different task IDs and validate the response.
9+
10+
## Preconditions
11+
12+
1. Wishlist API is available
13+
2. User is authenticated
14+
3. Game UUID is valid
15+
4. Test environment is prepared
16+
17+
## Test Steps
18+
19+
1. Create a new user
20+
2. Prepare a valid game UUID
21+
3. Call `add_an_item_to_wishlist` method
22+
4. Validate response structure
23+
5. Verify wishlist contents
24+
25+
## Test Data
26+
27+
- Task-Ids:
28+
- `api-5`
29+
- `api-25`
30+
- Game UUID: `03dbad48-ad81-433d-9901-dd5332f5d9ee`
31+
- Expected Fields:
32+
- `user_uuid`: Matches created user
33+
- `items`: Contains added game
34+
- `items[0].uuid`: Matches input game UUID
35+
36+
## Expected Result
37+
38+
- HTTP Status Code: 200 OK
39+
- Successful wishlist update
40+
- Wishlist contains exactly one game item
41+
- Game UUID matches input
42+
43+
## Validation Checks
44+
45+
1. Response validation using Pydantic model
46+
2. User UUID consistency
47+
3. Wishlist item count
48+
4. Game UUID verification
49+
50+
## Postconditions
51+
52+
- Restore initial state
53+
- Remove added game from wishlist
54+
- Verify no side effects
55+
56+
## Risks
57+
58+
- Potential data integrity issues
59+
- Unauthorized wishlist modifications
60+
61+
## Acceptance Criteria
62+
63+
- Successful game addition
64+
- Correct response format
65+
- Consistent user and game data
66+
67+
## Test Environment
68+
69+
- API Endpoint: `/wishlist/add`
70+
- Test Framework: pytest
71+
- Validation: Pydantic models
72+
73+
## Additional Considerations
74+
75+
- Test with multiple game UUIDs
76+
- Edge case handling
77+
- Performance testing

pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
minversion = 6.0
33
addopts =
44
-ra -q
5-
5+
-n auto
66

77
testpaths =
88
tests

requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ certifi==2024.8.30
66
cfgv==3.4.0
77
charset-normalizer==3.4.0
88
colorama==0.4.6
9+
coverage==7.6.8
910
distlib==0.3.9
1011
dnspython==2.7.0
1112
email-validator==2.2.0
13+
execnet==2.1.1
1214
faker==33.1.0
1315
filelock==3.16.1
1416
greenlet==3.1.1
@@ -26,8 +28,10 @@ pydantic-core==2.27.1
2628
pyee==12.0.0
2729
pytest==8.3.3
2830
pytest-base-url==2.1.0
31+
pytest-cov==6.0.0
2932
pytest-playwright==0.6.2
3033
pytest-rerunfailures==15.0
34+
pytest-xdist==3.6.1
3135
python-dateutil==2.9.0.post0
3236
python-dotenv==1.0.1
3337
python-slugify==8.0.4

services/api_endpoints.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,9 @@ class APIEndpoints:
33

44
USERS_ENDPOINT = "users"
55
GAMES_ENDPOINT = "games"
6+
PAYMENTS_ENDPOINT = "payments"
7+
CATEGORIES_ENDPOINT = "categories"
8+
ORDERS_ENDPOINT = "orders"
9+
AVATAR_ENDPOINT = "avatar"
10+
WISHLIST_ENDPOINT = "wishlist"
11+
CART_ENDPOINT = "cart"

services/cart/cart_api_client.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from typing import Any
2+
3+
from playwright.sync_api import APIRequestContext
4+
5+
from services.api_endpoints import APIEndpoints
6+
from services.http_client import HTTPClient
7+
8+
CART_ENDPOINT = APIEndpoints.CART_ENDPOINT
9+
10+
11+
class CartAPIClient(HTTPClient):
12+
"""Cart API client."""
13+
14+
def __init__(self, api_context: APIRequestContext) -> None:
15+
"""
16+
Initializing the UserAPIClient with the passed APIRequestContext.
17+
18+
:param api_context: Context for executing API requests
19+
"""
20+
super().__init__(api_context)
21+
22+
def get_a_cart(self, task_id: str, user_uuid: str) -> dict[str, Any]:
23+
"""
24+
Getting a list of users with a Task-Id.
25+
26+
:param task_id: Task ID
27+
:return: Response from the API
28+
"""
29+
headers = {"X-Task-Id": task_id}
30+
endpoint = f"{APIEndpoints.USERS_ENDPOINT}/{user_uuid}/{CART_ENDPOINT}"
31+
response = self.get(endpoint, headers=headers)
32+
33+
if not response.ok:
34+
msg = f"Request failed with status {response.status}: {response.text}"
35+
raise ValueError(msg)
36+
37+
return response.json()
38+
39+
def add_an_item_to_cart(
40+
self, task_id: str, user_uuid: str, item_uuid: str
41+
) -> dict[str, Any]:
42+
"""
43+
Adding an item to the user's cart.
44+
45+
:param task_id: Task ID
46+
:param user_uuid: UUID of the user
47+
:param item_uuid: UUID of the item to add to the cart
48+
"""
49+
headers = {"X-Task-Id": task_id}
50+
endpoint = f"{APIEndpoints.USERS_ENDPOINT}/{user_uuid}/{CART_ENDPOINT}/add"
51+
data = {"item_uuid": item_uuid}
52+
response = self.post(endpoint, headers=headers, json=data)
53+
54+
if not response.ok:
55+
msg = f"Request failed with status {response.status}: {response.text}"
56+
raise ValueError(msg)
57+
58+
return response.json()
59+
60+
def change_item_quantity(
61+
self, task_id: str, user_uuid: str, item_uuid: str, quantity: int
62+
) -> dict[str, Any]:
63+
"""
64+
Changing the quantity of an item in the user's cart.
65+
66+
:param task_id: Task ID
67+
:param user_uuid: UUID of the user
68+
:param item_uuid: UUID of the item to change the quantity of
69+
:param quantity: New quantity of the item
70+
"""
71+
headers = {"X-Task-Id": task_id}
72+
endpoint = f"{APIEndpoints.USERS_ENDPOINT}/{user_uuid}/{CART_ENDPOINT}/change"
73+
data = {"item_uuid": item_uuid, "quantity": quantity}
74+
response = self.post(endpoint, headers=headers, json=data)
75+
76+
if not response.ok:
77+
msg = f"Request failed with status {response.status}: {response.text}"
78+
raise ValueError(msg)
79+
80+
return response.json()
81+
82+
def clear_cart(self, task_id: str, user_uuid: str) -> dict[str, Any]:
83+
"""
84+
Clearing the user's cart.
85+
86+
:param task_id: Task ID
87+
:param user_uuid: UUID of the user
88+
"""
89+
headers = {"X-Task-Id": task_id}
90+
endpoint = f"{APIEndpoints.USERS_ENDPOINT}/{user_uuid}/{CART_ENDPOINT}/clear"
91+
response = self.post(endpoint, headers=headers)
92+
93+
if not response.ok:
94+
msg = f"Request failed with status {response.status}: {response.text}"
95+
raise ValueError(msg)
96+
97+
return response.json()
98+
99+
def remove_an_item_from_cart(
100+
self, task_id: str, user_uuid: str, item_uuid: str
101+
) -> dict[str, Any]:
102+
"""
103+
Removing an item from the user's cart.
104+
105+
:param task_id: Task ID
106+
:param user_uuid: UUID of the user
107+
:param item_uuid: UUID of the item to remove from the cart
108+
"""
109+
headers = {"X-Task-Id": task_id}
110+
endpoint = f"{APIEndpoints.USERS_ENDPOINT}/{user_uuid}/{CART_ENDPOINT}/remove"
111+
data = {"item_uuid": item_uuid}
112+
response = self.post(endpoint, headers=headers, json=data)
113+
114+
if not response.ok:
115+
msg = f"Request failed with status {response.status}: {response.text}"
116+
raise ValueError(msg)
117+
118+
return response.json()

0 commit comments

Comments
 (0)