From bb210921052d2f30562b3ca3153e1e2625f842a8 Mon Sep 17 00:00:00 2001 From: kriptoburak Date: Thu, 2 Jul 2026 11:58:15 +0300 Subject: [PATCH 1/2] Validate squad numbers --- models/player_model.py | 6 +++--- tests/test_main.py | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/models/player_model.py b/models/player_model.py index aa85389..4aa6cae 100644 --- a/models/player_model.py +++ b/models/player_model.py @@ -5,7 +5,7 @@ - `PlayerRequestModel`: Represents player data for Create and Update operations. - `PlayerResponseModel`: Represents player data including UUID for Retrieve operations. -Design decision — single request model vs split models: +Design decision - single request model vs split models: A single `PlayerRequestModel` is intentionally shared by both POST (Create) and PUT (Update). Per-operation differences are handled at the route layer rather than by duplicating the model: @@ -19,7 +19,7 @@ from typing import Optional from uuid import UUID -from pydantic import BaseModel, ConfigDict +from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel @@ -67,7 +67,7 @@ class PlayerRequestModel(MainModel): middle_name: Optional[str] = None last_name: str date_of_birth: Optional[str] = None - squad_number: int + squad_number: int = Field(gt=0) position: str abbr_position: Optional[str] = None team: Optional[str] = None diff --git a/tests/test_main.py b/tests/test_main.py index a27242c..28ffc08 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -190,6 +190,19 @@ def test_request_post_player_body_existing_response_body_detail(client): ) +def test_request_post_player_body_zero_squad_number_response_status_unprocessable( + client, +): + """POST /players/ with squad number zero returns 422 Unprocessable Entity""" + # Arrange + player = nonexistent_player() + payload = player.__dict__ | {"squad_number": 0} + # Act + response = client.post(PATH, json=payload) + # Assert + assert response.status_code == 422 + + def test_request_post_player_body_nonexistent_response_status_created(client): """POST /players/ with nonexistent player returns 201 Created with a valid UUID""" # Arrange @@ -203,7 +216,7 @@ def test_request_post_player_body_nonexistent_response_status_created(client): assert "id" in body assert UUID(body["id"]).version == 4 # UUID v4 (API-created) finally: - # Teardown — remove the created player + # Teardown - remove the created player client.delete(PATH + "squadnumber/" + str(player.squad_number)) @@ -250,7 +263,7 @@ def test_request_put_player_squadnumber_existing_response_status_no_content(clie # Assert assert response.status_code == 204 finally: - # Teardown — restore Damián Martínez to its seeded state + # Teardown - restore Damián Martínez to its seeded state seed = existing_player() client.put(PATH + "squadnumber/" + str(seed.squad_number), json=seed.__dict__) From e09daef8fb3b0a1d3c78a47d5aab4bf7e005c416 Mon Sep 17 00:00:00 2001 From: kriptoburak Date: Thu, 2 Jul 2026 12:04:37 +0300 Subject: [PATCH 2/2] Document squad number constraint --- models/player_model.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/models/player_model.py b/models/player_model.py index 4aa6cae..1797c3b 100644 --- a/models/player_model.py +++ b/models/player_model.py @@ -53,7 +53,8 @@ class PlayerRequestModel(MainModel): middle_name (Optional[str]): The middle name of the Player, if any. last_name (str): The last name of the Player. date_of_birth (Optional[str]): The date of birth of the Player, if provided. - squad_number (int): The unique squad number assigned to the Player. + squad_number (int): The unique, positive squad number assigned to the + Player. position (str): The playing position of the Player. abbr_position (Optional[str]): The abbreviated form of the Player's position, if any.