From 8283bc2b7b9a3ab52caa7c30fb4a5561c26c179b Mon Sep 17 00:00:00 2001 From: Nikolay Shirokov Date: Fri, 18 Sep 2026 13:26:15 +0300 Subject: [PATCH 1/3] test(project): create project fixtures --- backend/schemas/project.py | 2 +- backend/tests/test_schemas/conftest.py | 74 +++++++++++ backend/tests/test_schemas/test_project.py | 139 +++++++++++++++++++++ backend/tests/test_schemas/test_render.py | 74 ----------- 4 files changed, 214 insertions(+), 75 deletions(-) create mode 100644 backend/tests/test_schemas/test_project.py diff --git a/backend/schemas/project.py b/backend/schemas/project.py index c2fab3cd..c61a2662 100644 --- a/backend/schemas/project.py +++ b/backend/schemas/project.py @@ -64,7 +64,7 @@ class ProjectResponse(ProjectBase): visibility: ProjectVisibility status: RenderStatus user_id: int - render_id: int | None + render_id: int | None = None id: int diff --git a/backend/tests/test_schemas/conftest.py b/backend/tests/test_schemas/conftest.py index 48811eea..eeec8f94 100644 --- a/backend/tests/test_schemas/conftest.py +++ b/backend/tests/test_schemas/conftest.py @@ -90,3 +90,77 @@ def file_create_data(file_base_data: dict, file_location_data: dict) -> dict: def file_response_data(file_base_data: dict) -> dict: file_base_data["id"] = 1 return file_base_data + + +@pytest.fixture +def sun_info_data() -> dict: + return { + "direction": [1.0, 1.0, 1.0], + "color": [2.0, 2.0, 2.0], + "exponent": 5, + } + + +@pytest.fixture +def render_base_data() -> dict: + return { + "width": 1000, + "height": 1000, + "samples": 150, + "denoiser": True, + "gpu": False, + } + + +@pytest.fixture +def render_create_data(render_base_data: dict) -> dict: + return { + **render_base_data, + } + + +@pytest.fixture +def render_create_payload_data(render_create_data: dict, sun_info_data: dict) -> dict: + return { + **render_create_data, + "background": [1.0, 1.0, 1.0], + "sun": sun_info_data, + } + + +@pytest.fixture +def render_response_data(render_base_data: dict) -> dict: + return { + **render_base_data, + "id": 1, + "file_id": 1, + } + + +@pytest.fixture +def render_full_response_data(render_response_data: dict) -> dict: + return { + **render_response_data, + "url": "http://example.com", + } + + +@pytest.fixture +def render_with_file_response_data( + render_response_data: dict, file_response_data: dict +) -> dict: + return { + **render_response_data, + "file": file_response_data, + } + + +@pytest.fixture +def render_with_file_full_response_data( + render_full_response_data: dict, + file_response_data: dict, +) -> dict: + return { + **render_full_response_data, + "file": file_response_data, + } diff --git a/backend/tests/test_schemas/test_project.py b/backend/tests/test_schemas/test_project.py new file mode 100644 index 00000000..7b035b5d --- /dev/null +++ b/backend/tests/test_schemas/test_project.py @@ -0,0 +1,139 @@ +import pytest + + +@pytest.fixture +def project_base_data() -> dict: + return { + "name": "name", + "description": "description", + "source_file_id": 1, + } + + +@pytest.fixture +def project_create_data(project_base_data: dict) -> dict: + return { + **project_base_data, + "visibility": "public", + } + + +@pytest.fixture +def project_with_render_create_data( + render_create_payload_data: dict, + project_create_data: dict, +) -> dict: + return { + "render": render_create_payload_data, + "project": project_create_data, + } + + +@pytest.fixture +def project_partial_update_data() -> dict: + return { + "name": "name", + "description": "description", + "visibility": "public", + } + + +@pytest.fixture +def project_response_data() -> dict: + return { + "visibility": "public", + "status": "rendering", + "user_id": 1, + "render_id": 1, + "id": 1, + } + + +@pytest.fixture +def project_full_response_data(project_response_data: dict) -> dict: + return { + **project_response_data, + "url": "http://example.com", + } + + +@pytest.fixture +def project_with_render_file_full_response_data( + project_full_response_data: dict, + render_with_file_full_response: dict, +) -> dict: + return { + **project_full_response_data, + "render": render_with_file_full_response, + } + + +@pytest.fixture +def project_with_render_response_data( + project_response_data: dict, + render_response_data: dict, +) -> dict: + return { + **project_response_data, + "render": render_response_data, + } + + +@pytest.fixture +def project_with_render_file_response_data( + project_response_data: dict, + render_with_file_response_data: dict, +) -> dict: + return { + **project_response_data, + "render": render_with_file_response_data, + } + + +@pytest.fixture +def project_response_list_data() -> dict: + return { + "project_list": [ + { + "visibility": "public", + "status": "rendering", + "user_id": 1, + "render_id": 1, + "id": 1, + }, + { + "visibility": "private", + "status": "rendering", + "user_id": 2, + "render_id": 2, + "id": 2, + }, + ], + "size": 1, + "page": 1, + } + + +@pytest.fixture +def project_with_render_file_response_list_data() -> dict: + return { + "visibility": "public", + "status": "rendering", + "user_id": 1, + "render_id": 1, + "id": 1, + "render": { + "width": 1000, + "height": 1000, + "samples": 150, + "denoiser": True, + "gpu": False, + "id": 1, + "file_id": 1, + "file": { + "name": "file_name", + "size": 1000, + "id": 1, + }, + }, + } diff --git a/backend/tests/test_schemas/test_render.py b/backend/tests/test_schemas/test_render.py index ea801cc0..afe39bf7 100644 --- a/backend/tests/test_schemas/test_render.py +++ b/backend/tests/test_schemas/test_render.py @@ -21,80 +21,6 @@ from tests.test_schemas.helpers import assert_validation_error -@pytest.fixture -def sun_info_data() -> dict: - return { - "direction": [1.0, 1.0, 1.0], - "color": [2.0, 2.0, 2.0], - "exponent": 5, - } - - -@pytest.fixture -def render_base_data() -> dict: - return { - "width": 1000, - "height": 1000, - "samples": 150, - "denoiser": True, - "gpu": False, - } - - -@pytest.fixture -def render_create_data(render_base_data: dict) -> dict: - return { - **render_base_data, - } - - -@pytest.fixture -def render_create_payload_data(render_create_data: dict, sun_info_data: dict) -> dict: - return { - **render_create_data, - "background": [1.0, 1.0, 1.0], - "sun": sun_info_data, - } - - -@pytest.fixture -def render_response_data(render_base_data: dict) -> dict: - return { - **render_base_data, - "id": 1, - "file_id": 1, - } - - -@pytest.fixture -def render_full_response_data(render_response_data: dict) -> dict: - return { - **render_response_data, - "url": "http://example.com", - } - - -@pytest.fixture -def render_with_file_response_data( - render_response_data: dict, file_response_data: dict -) -> dict: - return { - **render_response_data, - "file": file_response_data, - } - - -@pytest.fixture -def render_with_file_full_response_data( - render_full_response_data: dict, - file_response_data: dict, -) -> dict: - return { - **render_full_response_data, - "file": file_response_data, - } - - class TestSunInfo: def test_sun_info_valid(self, sun_info_data: dict) -> None: sun_info = SunInfo(**sun_info_data) From e36ab75c1229ca87da79c235c735be3f719f11f8 Mon Sep 17 00:00:00 2001 From: Nikolay Shirokov Date: Sat, 19 Sep 2026 17:11:21 +0300 Subject: [PATCH 2/3] test(project): add tests on project schemas --- backend/schemas/project.py | 14 +- backend/tests/test_schemas/test_project.py | 481 ++++++++++++++++++++- 2 files changed, 478 insertions(+), 17 deletions(-) diff --git a/backend/schemas/project.py b/backend/schemas/project.py index c61a2662..b654f52c 100644 --- a/backend/schemas/project.py +++ b/backend/schemas/project.py @@ -105,12 +105,12 @@ async def get_from_database( expires_in=settings.minio.presigned_url_ttl_seconds, client_method="get_object", ) - render.url = render_file_url.replace("minio", "localhost") + render.url = render_file_url.replace(settings.minio.host, "localhost") return cls( **project_response.model_dump(), render=render, - url=source_file_url.replace("minio", "localhost"), + url=source_file_url.replace(settings.minio.host, "localhost"), ) @@ -147,13 +147,3 @@ class ProjectResponseList(BaseModel): project_list: list[ProjectResponse] size: SizeConstraint page: PageConstraint - - -class ProjectWithRenderFileResponseList(BaseModel): - """ - Схема для вывода информации о списке проектов с рендером. - """ - - project_list: list[ProjectWithRenderFileResponse] - size: SizeConstraint - page: PageConstraint diff --git a/backend/tests/test_schemas/test_project.py b/backend/tests/test_schemas/test_project.py index 7b035b5d..5ad30b39 100644 --- a/backend/tests/test_schemas/test_project.py +++ b/backend/tests/test_schemas/test_project.py @@ -1,10 +1,31 @@ import pytest +from pydantic import ValidationError + +from core.constants import ( + PROJECT_NAME_MIN_LENGTH, + PROJECT_NAME_MAX_LENGTH, + PROJECT_DESCRIPTION_MAX_LENGTH, + PROJECT_DESCRIPTION_MIN_LENGTH, +) +from schemas.project import ( + ProjectBase, + ProjectCreate, + ProjectWithRenderCreate, + ProjectPartialUpdate, + ProjectResponse, + ProjectFullResponse, + ProjectWithRenderFileFullResponse, + ProjectWithRenderResponse, + ProjectWithRenderFileResponse, + ProjectResponseList, +) +from tests.test_schemas.helpers import assert_validation_error @pytest.fixture def project_base_data() -> dict: return { - "name": "name", + "name": "project_name", "description": "description", "source_file_id": 1, } @@ -32,15 +53,16 @@ def project_with_render_create_data( @pytest.fixture def project_partial_update_data() -> dict: return { - "name": "name", + "name": "project_name", "description": "description", "visibility": "public", } @pytest.fixture -def project_response_data() -> dict: +def project_response_data(project_base_data: dict) -> dict: return { + **project_base_data, "visibility": "public", "status": "rendering", "user_id": 1, @@ -60,11 +82,11 @@ def project_full_response_data(project_response_data: dict) -> dict: @pytest.fixture def project_with_render_file_full_response_data( project_full_response_data: dict, - render_with_file_full_response: dict, + render_with_file_full_response_data: dict, ) -> dict: return { **project_full_response_data, - "render": render_with_file_full_response, + "render": render_with_file_full_response_data, } @@ -95,6 +117,9 @@ def project_response_list_data() -> dict: return { "project_list": [ { + "name": "project_name1", + "description": "description1", + "source_file_id": 1, "visibility": "public", "status": "rendering", "user_id": 1, @@ -102,6 +127,9 @@ def project_response_list_data() -> dict: "id": 1, }, { + "name": "project_name2", + "description": "description2", + "source_file_id": 2, "visibility": "private", "status": "rendering", "user_id": 2, @@ -137,3 +165,446 @@ def project_with_render_file_response_list_data() -> dict: }, }, } + + +class TestProjectBase: + def test_project_base_valid(self, project_base_data: dict) -> None: + project_base = ProjectBase(**project_base_data) + assert project_base.model_dump() == project_base_data + + @pytest.mark.parametrize( + "field, value, expected_error", + [ + ["name", "a" * (PROJECT_NAME_MIN_LENGTH - 1), "string_too_short"], + ["name", "a" * (PROJECT_NAME_MAX_LENGTH + 1), "string_too_long"], + [ + "description", + "a" * (PROJECT_DESCRIPTION_MAX_LENGTH + 1), + "string_too_long", + ], + ], + ) + def test_project_base_not_valid_field_value( + self, + project_base_data: dict, + field: str, + value: str, + expected_error: str, + ) -> None: + project_base_data[field] = value + with pytest.raises(ValidationError) as exc_info: + ProjectBase(**project_base_data) + + assert_validation_error( + exc_info, + expected_error, + field, + ) + + @pytest.mark.parametrize( + "field, value", + [ + ["name", "a" * PROJECT_NAME_MIN_LENGTH], + ["name", "a" * PROJECT_NAME_MAX_LENGTH], + ["description", "a" * PROJECT_DESCRIPTION_MIN_LENGTH], + ["description", "a" * PROJECT_DESCRIPTION_MAX_LENGTH], + ], + ) + def test_project_base_boundary_field_value( + self, + project_base_data: dict, + field: str, + value: str, + ) -> None: + project_base_data[field] = value + project_base = ProjectBase(**project_base_data) + assert project_base.model_dump() == project_base_data + + +class TestProjectCreate: + @pytest.mark.parametrize( + "visibility", + ["public", "private"], + ) + def test_project_create_valid( + self, project_create_data: dict, visibility: str + ) -> None: + project_create_data["visibility"] = visibility + project_create = ProjectCreate(**project_create_data) + assert project_create.model_dump() == project_create_data + + @pytest.mark.parametrize( + "visibility", + [ + "pending", + "sent", + "rendering", + "completed", + ], + ) + def test_project_create_not_valid_visibility( + self, + project_create_data: dict, + visibility: str, + ) -> None: + project_create_data["visibility"] = visibility + with pytest.raises(ValidationError) as exc_info: + ProjectCreate(**project_create_data) + + assert_validation_error( + exc_info, + "enum", + "visibility", + ) + + +class TestProjectWithRenderCreate: + def test_project_with_render_create_valid( + self, project_with_render_create_data: dict + ) -> None: + project_with_render_create = ProjectWithRenderCreate( + **project_with_render_create_data + ) + assert ( + project_with_render_create.model_dump() == project_with_render_create_data + ) + + @pytest.mark.parametrize( + "field", + ["render", "project"], + ) + def test_project_with_render_create_without_required_fields( + self, + project_with_render_create_data: dict, + field: str, + ) -> None: + project_with_render_create_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectWithRenderCreate(**project_with_render_create_data) + assert_validation_error( + exc_info, + "missing", + field, + ) + + +class TestProjectPartialUpdate: + def test_project_partial_update_valid( + self, + project_partial_update_data: dict, + ) -> None: + project_partial_update = ProjectPartialUpdate(**project_partial_update_data) + assert project_partial_update.model_dump() == project_partial_update_data + + @pytest.mark.parametrize( + "field, value, expected_error", + [ + ["name", "a" * (PROJECT_NAME_MIN_LENGTH - 1), "string_too_short"], + ["name", "a" * (PROJECT_NAME_MAX_LENGTH + 1), "string_too_long"], + [ + "description", + "a" * (PROJECT_DESCRIPTION_MAX_LENGTH + 1), + "string_too_long", + ], + ], + ) + def test_project_partial_update_not_valid_field_value( + self, + project_partial_update_data: dict, + field: str, + value: str, + expected_error: str, + ) -> None: + project_partial_update_data[field] = value + with pytest.raises(ValidationError) as exc_info: + ProjectPartialUpdate(**project_partial_update_data) + + assert_validation_error( + exc_info, + expected_error, + field, + ) + + @pytest.mark.parametrize( + "field, value", + [ + ["name", "a" * PROJECT_NAME_MIN_LENGTH], + ["name", "a" * PROJECT_NAME_MAX_LENGTH], + ["description", "a" * PROJECT_DESCRIPTION_MIN_LENGTH], + ["description", "a" * PROJECT_DESCRIPTION_MAX_LENGTH], + ], + ) + def test_project_partial_update_boundary_field_value( + self, + project_partial_update_data: dict, + field: str, + value: str, + ) -> None: + project_partial_update_data[field] = value + project_partial_update = ProjectPartialUpdate(**project_partial_update_data) + assert project_partial_update.model_dump() == project_partial_update_data + + @pytest.mark.parametrize( + "field", + ["name", "description", "visibility"], + ) + def test_project_partial_update_without_optional_field( + self, + project_partial_update_data: dict, + field: str, + ) -> None: + project_partial_update_data.pop(field) + project_partial_update = ProjectPartialUpdate(**project_partial_update_data) + assert getattr(project_partial_update, field) is None + + @pytest.mark.parametrize( + "visibility", + [ + "pending", + "sent", + "rendering", + "completed", + ], + ) + def test_project_partial_update_not_valid_visibility( + self, + project_partial_update_data: dict, + visibility: str, + ) -> None: + project_partial_update_data["visibility"] = visibility + with pytest.raises(ValidationError) as exc_info: + ProjectPartialUpdate(**project_partial_update_data) + + assert_validation_error( + exc_info, + "enum", + "visibility", + ) + + +class TestProjectResponse: + @pytest.mark.parametrize( + "field, value", + [ + ["visibility", "pending"], + ["visibility", "completed"], + ["status", "rendering"], + ["status", "completed"], + ], + ) + def test_project_response_valid( + self, + project_response_data: dict, + field: str, + value: str, + ) -> None: + project_response = ProjectResponse(**project_response_data) + assert project_response.model_dump() == project_response_data + + @pytest.mark.parametrize( + "visibility", + [ + "pending", + "sent", + "rendering", + "completed", + ], + ) + def test_project_response_not_valid_visibility( + self, + project_response_data: dict, + visibility: str, + ) -> None: + project_response_data["visibility"] = visibility + with pytest.raises(ValidationError) as exc_info: + ProjectResponse(**project_response_data) + + assert_validation_error( + exc_info, + "enum", + "visibility", + ) + + @pytest.mark.parametrize( + "status", + [ + "pending", + "sent", + "public", + "private", + ], + ) + def test_project_response_not_valid_status( + self, + project_response_data: dict, + status: str, + ) -> None: + project_response_data["status"] = status + with pytest.raises(ValidationError) as exc_info: + ProjectResponse(**project_response_data) + + assert_validation_error( + exc_info, + "enum", + "status", + ) + + @pytest.mark.parametrize( + "field", + ["render_id"], + ) + def test_project_response_without_optional_field( + self, + project_response_data: dict, + field: str, + ) -> None: + project_response_data.pop(field) + project_response = ProjectResponse(**project_response_data) + assert getattr(project_response, field) is None + + +class TestProjectFullResponse: + def test_project_full_response_valid( + self, project_full_response_data: dict + ) -> None: + project_full_response = ProjectFullResponse(**project_full_response_data) + assert project_full_response.model_dump() == project_full_response_data + + @pytest.mark.parametrize( + "field", + ["url"], + ) + def test_project_full_response_without_required_field( + self, + project_full_response_data: dict, + field: str, + ) -> None: + project_full_response_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectFullResponse(**project_full_response_data) + + assert_validation_error( + exc_info, + "missing", + field, + ) + + +class TestProjectWithRenderFileFullResponse: + def test_project_with_render_file_full_response_valid( + self, + project_with_render_file_full_response_data: dict, + ) -> None: + project_with_render_file_full_response = ProjectWithRenderFileFullResponse( + **project_with_render_file_full_response_data + ) + assert ( + project_with_render_file_full_response.model_dump() + == project_with_render_file_full_response_data + ) + + @pytest.mark.parametrize("field", ["render"]) + def test_project_with_render_file_full_without_required_field( + self, + project_with_render_file_full_response_data: dict, + field: str, + ) -> None: + project_with_render_file_full_response_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectWithRenderFileFullResponse( + **project_with_render_file_full_response_data + ) + + assert_validation_error( + exc_info, + "missing", + field, + ) + + +class TestProjectWithRenderResponse: + def test_project_with_render_response_valid( + self, + project_with_render_response_data: dict, + ) -> None: + project_with_render_response = ProjectWithRenderResponse( + **project_with_render_response_data + ) + assert ( + project_with_render_response.model_dump() + == project_with_render_response_data + ) + + @pytest.mark.parametrize("field", ["render"]) + def test_project_with_render_response_without_required_field( + self, + project_with_render_response_data: dict, + field: str, + ) -> None: + project_with_render_response_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectWithRenderResponse(**project_with_render_response_data) + + assert_validation_error( + exc_info, + "missing", + field, + ) + + +class TestProjectWithRenderFileResponse: + def test_project_with_render_file_response_valid( + self, + project_with_render_file_response_data: dict, + ) -> None: + project_with_render_file_response = ProjectWithRenderFileResponse( + **project_with_render_file_response_data + ) + assert ( + project_with_render_file_response.model_dump() + == project_with_render_file_response_data + ) + + @pytest.mark.parametrize("field", ["render"]) + def test_project_with_render_file_response_without_required_field( + self, + project_with_render_file_response_data: dict, + field: str, + ) -> None: + project_with_render_file_response_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectWithRenderFileResponse(**project_with_render_file_response_data) + + assert_validation_error( + exc_info, + "missing", + field, + ) + + +class TestProjectResponseList: + def test_project_response_list_valid( + self, + project_response_list_data: dict, + ) -> None: + project_response_list = ProjectResponseList(**project_response_list_data) + assert project_response_list.model_dump() == project_response_list_data + + @pytest.mark.parametrize( + "field", + ["project_list", "size", "page"], + ) + def test_project_response_list_without_required_field( + self, + project_response_list_data: dict, + field: str, + ) -> None: + project_response_list_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectResponseList(**project_response_list_data) + + assert_validation_error( + exc_info, + "missing", + field, + ) From 0186813fced243b7f5dec413e59e9b1cffc5dc6d Mon Sep 17 00:00:00 2001 From: Nikolay Shirokov Date: Sat, 19 Sep 2026 17:32:13 +0300 Subject: [PATCH 3/3] refactor(tests): split project tests into separate files --- backend/tests/test_schemas/test_project.py | 610 ------------------ .../test_schemas/test_project/__init__.py | 0 .../test_schemas/test_project/conftest.py | 146 +++++ .../test_project/test_project_base.py | 65 ++ .../test_project/test_project_create.py | 72 +++ .../test_project/test_project_response.py | 141 ++++ .../test_project/test_project_update.py | 105 +++ .../test_project/test_project_with_render.py | 101 +++ 8 files changed, 630 insertions(+), 610 deletions(-) delete mode 100644 backend/tests/test_schemas/test_project.py create mode 100644 backend/tests/test_schemas/test_project/__init__.py create mode 100644 backend/tests/test_schemas/test_project/conftest.py create mode 100644 backend/tests/test_schemas/test_project/test_project_base.py create mode 100644 backend/tests/test_schemas/test_project/test_project_create.py create mode 100644 backend/tests/test_schemas/test_project/test_project_response.py create mode 100644 backend/tests/test_schemas/test_project/test_project_update.py create mode 100644 backend/tests/test_schemas/test_project/test_project_with_render.py diff --git a/backend/tests/test_schemas/test_project.py b/backend/tests/test_schemas/test_project.py deleted file mode 100644 index 5ad30b39..00000000 --- a/backend/tests/test_schemas/test_project.py +++ /dev/null @@ -1,610 +0,0 @@ -import pytest -from pydantic import ValidationError - -from core.constants import ( - PROJECT_NAME_MIN_LENGTH, - PROJECT_NAME_MAX_LENGTH, - PROJECT_DESCRIPTION_MAX_LENGTH, - PROJECT_DESCRIPTION_MIN_LENGTH, -) -from schemas.project import ( - ProjectBase, - ProjectCreate, - ProjectWithRenderCreate, - ProjectPartialUpdate, - ProjectResponse, - ProjectFullResponse, - ProjectWithRenderFileFullResponse, - ProjectWithRenderResponse, - ProjectWithRenderFileResponse, - ProjectResponseList, -) -from tests.test_schemas.helpers import assert_validation_error - - -@pytest.fixture -def project_base_data() -> dict: - return { - "name": "project_name", - "description": "description", - "source_file_id": 1, - } - - -@pytest.fixture -def project_create_data(project_base_data: dict) -> dict: - return { - **project_base_data, - "visibility": "public", - } - - -@pytest.fixture -def project_with_render_create_data( - render_create_payload_data: dict, - project_create_data: dict, -) -> dict: - return { - "render": render_create_payload_data, - "project": project_create_data, - } - - -@pytest.fixture -def project_partial_update_data() -> dict: - return { - "name": "project_name", - "description": "description", - "visibility": "public", - } - - -@pytest.fixture -def project_response_data(project_base_data: dict) -> dict: - return { - **project_base_data, - "visibility": "public", - "status": "rendering", - "user_id": 1, - "render_id": 1, - "id": 1, - } - - -@pytest.fixture -def project_full_response_data(project_response_data: dict) -> dict: - return { - **project_response_data, - "url": "http://example.com", - } - - -@pytest.fixture -def project_with_render_file_full_response_data( - project_full_response_data: dict, - render_with_file_full_response_data: dict, -) -> dict: - return { - **project_full_response_data, - "render": render_with_file_full_response_data, - } - - -@pytest.fixture -def project_with_render_response_data( - project_response_data: dict, - render_response_data: dict, -) -> dict: - return { - **project_response_data, - "render": render_response_data, - } - - -@pytest.fixture -def project_with_render_file_response_data( - project_response_data: dict, - render_with_file_response_data: dict, -) -> dict: - return { - **project_response_data, - "render": render_with_file_response_data, - } - - -@pytest.fixture -def project_response_list_data() -> dict: - return { - "project_list": [ - { - "name": "project_name1", - "description": "description1", - "source_file_id": 1, - "visibility": "public", - "status": "rendering", - "user_id": 1, - "render_id": 1, - "id": 1, - }, - { - "name": "project_name2", - "description": "description2", - "source_file_id": 2, - "visibility": "private", - "status": "rendering", - "user_id": 2, - "render_id": 2, - "id": 2, - }, - ], - "size": 1, - "page": 1, - } - - -@pytest.fixture -def project_with_render_file_response_list_data() -> dict: - return { - "visibility": "public", - "status": "rendering", - "user_id": 1, - "render_id": 1, - "id": 1, - "render": { - "width": 1000, - "height": 1000, - "samples": 150, - "denoiser": True, - "gpu": False, - "id": 1, - "file_id": 1, - "file": { - "name": "file_name", - "size": 1000, - "id": 1, - }, - }, - } - - -class TestProjectBase: - def test_project_base_valid(self, project_base_data: dict) -> None: - project_base = ProjectBase(**project_base_data) - assert project_base.model_dump() == project_base_data - - @pytest.mark.parametrize( - "field, value, expected_error", - [ - ["name", "a" * (PROJECT_NAME_MIN_LENGTH - 1), "string_too_short"], - ["name", "a" * (PROJECT_NAME_MAX_LENGTH + 1), "string_too_long"], - [ - "description", - "a" * (PROJECT_DESCRIPTION_MAX_LENGTH + 1), - "string_too_long", - ], - ], - ) - def test_project_base_not_valid_field_value( - self, - project_base_data: dict, - field: str, - value: str, - expected_error: str, - ) -> None: - project_base_data[field] = value - with pytest.raises(ValidationError) as exc_info: - ProjectBase(**project_base_data) - - assert_validation_error( - exc_info, - expected_error, - field, - ) - - @pytest.mark.parametrize( - "field, value", - [ - ["name", "a" * PROJECT_NAME_MIN_LENGTH], - ["name", "a" * PROJECT_NAME_MAX_LENGTH], - ["description", "a" * PROJECT_DESCRIPTION_MIN_LENGTH], - ["description", "a" * PROJECT_DESCRIPTION_MAX_LENGTH], - ], - ) - def test_project_base_boundary_field_value( - self, - project_base_data: dict, - field: str, - value: str, - ) -> None: - project_base_data[field] = value - project_base = ProjectBase(**project_base_data) - assert project_base.model_dump() == project_base_data - - -class TestProjectCreate: - @pytest.mark.parametrize( - "visibility", - ["public", "private"], - ) - def test_project_create_valid( - self, project_create_data: dict, visibility: str - ) -> None: - project_create_data["visibility"] = visibility - project_create = ProjectCreate(**project_create_data) - assert project_create.model_dump() == project_create_data - - @pytest.mark.parametrize( - "visibility", - [ - "pending", - "sent", - "rendering", - "completed", - ], - ) - def test_project_create_not_valid_visibility( - self, - project_create_data: dict, - visibility: str, - ) -> None: - project_create_data["visibility"] = visibility - with pytest.raises(ValidationError) as exc_info: - ProjectCreate(**project_create_data) - - assert_validation_error( - exc_info, - "enum", - "visibility", - ) - - -class TestProjectWithRenderCreate: - def test_project_with_render_create_valid( - self, project_with_render_create_data: dict - ) -> None: - project_with_render_create = ProjectWithRenderCreate( - **project_with_render_create_data - ) - assert ( - project_with_render_create.model_dump() == project_with_render_create_data - ) - - @pytest.mark.parametrize( - "field", - ["render", "project"], - ) - def test_project_with_render_create_without_required_fields( - self, - project_with_render_create_data: dict, - field: str, - ) -> None: - project_with_render_create_data.pop(field) - with pytest.raises(ValidationError) as exc_info: - ProjectWithRenderCreate(**project_with_render_create_data) - assert_validation_error( - exc_info, - "missing", - field, - ) - - -class TestProjectPartialUpdate: - def test_project_partial_update_valid( - self, - project_partial_update_data: dict, - ) -> None: - project_partial_update = ProjectPartialUpdate(**project_partial_update_data) - assert project_partial_update.model_dump() == project_partial_update_data - - @pytest.mark.parametrize( - "field, value, expected_error", - [ - ["name", "a" * (PROJECT_NAME_MIN_LENGTH - 1), "string_too_short"], - ["name", "a" * (PROJECT_NAME_MAX_LENGTH + 1), "string_too_long"], - [ - "description", - "a" * (PROJECT_DESCRIPTION_MAX_LENGTH + 1), - "string_too_long", - ], - ], - ) - def test_project_partial_update_not_valid_field_value( - self, - project_partial_update_data: dict, - field: str, - value: str, - expected_error: str, - ) -> None: - project_partial_update_data[field] = value - with pytest.raises(ValidationError) as exc_info: - ProjectPartialUpdate(**project_partial_update_data) - - assert_validation_error( - exc_info, - expected_error, - field, - ) - - @pytest.mark.parametrize( - "field, value", - [ - ["name", "a" * PROJECT_NAME_MIN_LENGTH], - ["name", "a" * PROJECT_NAME_MAX_LENGTH], - ["description", "a" * PROJECT_DESCRIPTION_MIN_LENGTH], - ["description", "a" * PROJECT_DESCRIPTION_MAX_LENGTH], - ], - ) - def test_project_partial_update_boundary_field_value( - self, - project_partial_update_data: dict, - field: str, - value: str, - ) -> None: - project_partial_update_data[field] = value - project_partial_update = ProjectPartialUpdate(**project_partial_update_data) - assert project_partial_update.model_dump() == project_partial_update_data - - @pytest.mark.parametrize( - "field", - ["name", "description", "visibility"], - ) - def test_project_partial_update_without_optional_field( - self, - project_partial_update_data: dict, - field: str, - ) -> None: - project_partial_update_data.pop(field) - project_partial_update = ProjectPartialUpdate(**project_partial_update_data) - assert getattr(project_partial_update, field) is None - - @pytest.mark.parametrize( - "visibility", - [ - "pending", - "sent", - "rendering", - "completed", - ], - ) - def test_project_partial_update_not_valid_visibility( - self, - project_partial_update_data: dict, - visibility: str, - ) -> None: - project_partial_update_data["visibility"] = visibility - with pytest.raises(ValidationError) as exc_info: - ProjectPartialUpdate(**project_partial_update_data) - - assert_validation_error( - exc_info, - "enum", - "visibility", - ) - - -class TestProjectResponse: - @pytest.mark.parametrize( - "field, value", - [ - ["visibility", "pending"], - ["visibility", "completed"], - ["status", "rendering"], - ["status", "completed"], - ], - ) - def test_project_response_valid( - self, - project_response_data: dict, - field: str, - value: str, - ) -> None: - project_response = ProjectResponse(**project_response_data) - assert project_response.model_dump() == project_response_data - - @pytest.mark.parametrize( - "visibility", - [ - "pending", - "sent", - "rendering", - "completed", - ], - ) - def test_project_response_not_valid_visibility( - self, - project_response_data: dict, - visibility: str, - ) -> None: - project_response_data["visibility"] = visibility - with pytest.raises(ValidationError) as exc_info: - ProjectResponse(**project_response_data) - - assert_validation_error( - exc_info, - "enum", - "visibility", - ) - - @pytest.mark.parametrize( - "status", - [ - "pending", - "sent", - "public", - "private", - ], - ) - def test_project_response_not_valid_status( - self, - project_response_data: dict, - status: str, - ) -> None: - project_response_data["status"] = status - with pytest.raises(ValidationError) as exc_info: - ProjectResponse(**project_response_data) - - assert_validation_error( - exc_info, - "enum", - "status", - ) - - @pytest.mark.parametrize( - "field", - ["render_id"], - ) - def test_project_response_without_optional_field( - self, - project_response_data: dict, - field: str, - ) -> None: - project_response_data.pop(field) - project_response = ProjectResponse(**project_response_data) - assert getattr(project_response, field) is None - - -class TestProjectFullResponse: - def test_project_full_response_valid( - self, project_full_response_data: dict - ) -> None: - project_full_response = ProjectFullResponse(**project_full_response_data) - assert project_full_response.model_dump() == project_full_response_data - - @pytest.mark.parametrize( - "field", - ["url"], - ) - def test_project_full_response_without_required_field( - self, - project_full_response_data: dict, - field: str, - ) -> None: - project_full_response_data.pop(field) - with pytest.raises(ValidationError) as exc_info: - ProjectFullResponse(**project_full_response_data) - - assert_validation_error( - exc_info, - "missing", - field, - ) - - -class TestProjectWithRenderFileFullResponse: - def test_project_with_render_file_full_response_valid( - self, - project_with_render_file_full_response_data: dict, - ) -> None: - project_with_render_file_full_response = ProjectWithRenderFileFullResponse( - **project_with_render_file_full_response_data - ) - assert ( - project_with_render_file_full_response.model_dump() - == project_with_render_file_full_response_data - ) - - @pytest.mark.parametrize("field", ["render"]) - def test_project_with_render_file_full_without_required_field( - self, - project_with_render_file_full_response_data: dict, - field: str, - ) -> None: - project_with_render_file_full_response_data.pop(field) - with pytest.raises(ValidationError) as exc_info: - ProjectWithRenderFileFullResponse( - **project_with_render_file_full_response_data - ) - - assert_validation_error( - exc_info, - "missing", - field, - ) - - -class TestProjectWithRenderResponse: - def test_project_with_render_response_valid( - self, - project_with_render_response_data: dict, - ) -> None: - project_with_render_response = ProjectWithRenderResponse( - **project_with_render_response_data - ) - assert ( - project_with_render_response.model_dump() - == project_with_render_response_data - ) - - @pytest.mark.parametrize("field", ["render"]) - def test_project_with_render_response_without_required_field( - self, - project_with_render_response_data: dict, - field: str, - ) -> None: - project_with_render_response_data.pop(field) - with pytest.raises(ValidationError) as exc_info: - ProjectWithRenderResponse(**project_with_render_response_data) - - assert_validation_error( - exc_info, - "missing", - field, - ) - - -class TestProjectWithRenderFileResponse: - def test_project_with_render_file_response_valid( - self, - project_with_render_file_response_data: dict, - ) -> None: - project_with_render_file_response = ProjectWithRenderFileResponse( - **project_with_render_file_response_data - ) - assert ( - project_with_render_file_response.model_dump() - == project_with_render_file_response_data - ) - - @pytest.mark.parametrize("field", ["render"]) - def test_project_with_render_file_response_without_required_field( - self, - project_with_render_file_response_data: dict, - field: str, - ) -> None: - project_with_render_file_response_data.pop(field) - with pytest.raises(ValidationError) as exc_info: - ProjectWithRenderFileResponse(**project_with_render_file_response_data) - - assert_validation_error( - exc_info, - "missing", - field, - ) - - -class TestProjectResponseList: - def test_project_response_list_valid( - self, - project_response_list_data: dict, - ) -> None: - project_response_list = ProjectResponseList(**project_response_list_data) - assert project_response_list.model_dump() == project_response_list_data - - @pytest.mark.parametrize( - "field", - ["project_list", "size", "page"], - ) - def test_project_response_list_without_required_field( - self, - project_response_list_data: dict, - field: str, - ) -> None: - project_response_list_data.pop(field) - with pytest.raises(ValidationError) as exc_info: - ProjectResponseList(**project_response_list_data) - - assert_validation_error( - exc_info, - "missing", - field, - ) diff --git a/backend/tests/test_schemas/test_project/__init__.py b/backend/tests/test_schemas/test_project/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/tests/test_schemas/test_project/conftest.py b/backend/tests/test_schemas/test_project/conftest.py new file mode 100644 index 00000000..3a7fe993 --- /dev/null +++ b/backend/tests/test_schemas/test_project/conftest.py @@ -0,0 +1,146 @@ +import pytest + + +@pytest.fixture +def project_base_data() -> dict: + return { + "name": "project_name", + "description": "description", + "source_file_id": 1, + } + + +@pytest.fixture +def project_create_data(project_base_data: dict) -> dict: + return { + **project_base_data, + "visibility": "public", + } + + +@pytest.fixture +def project_with_render_create_data( + render_create_payload_data: dict, + project_create_data: dict, +) -> dict: + return { + "render": render_create_payload_data, + "project": project_create_data, + } + + +@pytest.fixture +def project_partial_update_data() -> dict: + return { + "name": "project_name", + "description": "description", + "visibility": "public", + } + + +@pytest.fixture +def project_response_data(project_base_data: dict) -> dict: + return { + **project_base_data, + "visibility": "public", + "status": "rendering", + "user_id": 1, + "render_id": 1, + "id": 1, + } + + +@pytest.fixture +def project_full_response_data(project_response_data: dict) -> dict: + return { + **project_response_data, + "url": "http://example.com", + } + + +@pytest.fixture +def project_with_render_file_full_response_data( + project_full_response_data: dict, + render_with_file_full_response_data: dict, +) -> dict: + return { + **project_full_response_data, + "render": render_with_file_full_response_data, + } + + +@pytest.fixture +def project_with_render_response_data( + project_response_data: dict, + render_response_data: dict, +) -> dict: + return { + **project_response_data, + "render": render_response_data, + } + + +@pytest.fixture +def project_with_render_file_response_data( + project_response_data: dict, + render_with_file_response_data: dict, +) -> dict: + return { + **project_response_data, + "render": render_with_file_response_data, + } + + +@pytest.fixture +def project_response_list_data() -> dict: + return { + "project_list": [ + { + "name": "project_name1", + "description": "description1", + "source_file_id": 1, + "visibility": "public", + "status": "rendering", + "user_id": 1, + "render_id": 1, + "id": 1, + }, + { + "name": "project_name2", + "description": "description2", + "source_file_id": 2, + "visibility": "private", + "status": "rendering", + "user_id": 2, + "render_id": 2, + "id": 2, + }, + ], + "size": 1, + "page": 1, + } + + +@pytest.fixture +def project_with_render_file_response_list_data() -> dict: + return { + "visibility": "public", + "status": "rendering", + "user_id": 1, + "render_id": 1, + "id": 1, + "render": { + "width": 1000, + "height": 1000, + "samples": 150, + "denoiser": True, + "gpu": False, + "id": 1, + "file_id": 1, + "file": { + "name": "file_name", + "size": 1000, + "id": 1, + }, + }, + } diff --git a/backend/tests/test_schemas/test_project/test_project_base.py b/backend/tests/test_schemas/test_project/test_project_base.py new file mode 100644 index 00000000..40dfddda --- /dev/null +++ b/backend/tests/test_schemas/test_project/test_project_base.py @@ -0,0 +1,65 @@ +import pytest +from pydantic import ValidationError + +from core.constants import ( + PROJECT_NAME_MIN_LENGTH, + PROJECT_NAME_MAX_LENGTH, + PROJECT_DESCRIPTION_MAX_LENGTH, + PROJECT_DESCRIPTION_MIN_LENGTH, +) +from schemas.project import ProjectBase +from tests.test_schemas.helpers import assert_validation_error + + +class TestProjectBase: + def test_project_base_valid(self, project_base_data: dict) -> None: + project_base = ProjectBase(**project_base_data) + assert project_base.model_dump() == project_base_data + + @pytest.mark.parametrize( + "field, value, expected_error", + [ + ["name", "a" * (PROJECT_NAME_MIN_LENGTH - 1), "string_too_short"], + ["name", "a" * (PROJECT_NAME_MAX_LENGTH + 1), "string_too_long"], + [ + "description", + "a" * (PROJECT_DESCRIPTION_MAX_LENGTH + 1), + "string_too_long", + ], + ], + ) + def test_project_base_not_valid_field_value( + self, + project_base_data: dict, + field: str, + value: str, + expected_error: str, + ) -> None: + project_base_data[field] = value + with pytest.raises(ValidationError) as exc_info: + ProjectBase(**project_base_data) + + assert_validation_error( + exc_info, + expected_error, + field, + ) + + @pytest.mark.parametrize( + "field, value", + [ + ["name", "a" * PROJECT_NAME_MIN_LENGTH], + ["name", "a" * PROJECT_NAME_MAX_LENGTH], + ["description", "a" * PROJECT_DESCRIPTION_MIN_LENGTH], + ["description", "a" * PROJECT_DESCRIPTION_MAX_LENGTH], + ], + ) + def test_project_base_boundary_field_value( + self, + project_base_data: dict, + field: str, + value: str, + ) -> None: + project_base_data[field] = value + project_base = ProjectBase(**project_base_data) + assert project_base.model_dump() == project_base_data diff --git a/backend/tests/test_schemas/test_project/test_project_create.py b/backend/tests/test_schemas/test_project/test_project_create.py new file mode 100644 index 00000000..2fe70ed4 --- /dev/null +++ b/backend/tests/test_schemas/test_project/test_project_create.py @@ -0,0 +1,72 @@ +import pytest +from pydantic import ValidationError + +from schemas.project import ProjectCreate, ProjectWithRenderCreate +from tests.test_schemas.helpers import assert_validation_error + + +class TestProjectCreate: + @pytest.mark.parametrize( + "visibility", + ["public", "private"], + ) + def test_project_create_valid( + self, project_create_data: dict, visibility: str + ) -> None: + project_create_data["visibility"] = visibility + project_create = ProjectCreate(**project_create_data) + assert project_create.model_dump() == project_create_data + + @pytest.mark.parametrize( + "visibility", + [ + "pending", + "sent", + "rendering", + "completed", + ], + ) + def test_project_create_not_valid_visibility( + self, + project_create_data: dict, + visibility: str, + ) -> None: + project_create_data["visibility"] = visibility + with pytest.raises(ValidationError) as exc_info: + ProjectCreate(**project_create_data) + + assert_validation_error( + exc_info, + "enum", + "visibility", + ) + + +class TestProjectWithRenderCreate: + def test_project_with_render_create_valid( + self, project_with_render_create_data: dict + ) -> None: + project_with_render_create = ProjectWithRenderCreate( + **project_with_render_create_data + ) + assert ( + project_with_render_create.model_dump() == project_with_render_create_data + ) + + @pytest.mark.parametrize( + "field", + ["render", "project"], + ) + def test_project_with_render_create_without_required_fields( + self, + project_with_render_create_data: dict, + field: str, + ) -> None: + project_with_render_create_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectWithRenderCreate(**project_with_render_create_data) + assert_validation_error( + exc_info, + "missing", + field, + ) diff --git a/backend/tests/test_schemas/test_project/test_project_response.py b/backend/tests/test_schemas/test_project/test_project_response.py new file mode 100644 index 00000000..6c483ce0 --- /dev/null +++ b/backend/tests/test_schemas/test_project/test_project_response.py @@ -0,0 +1,141 @@ +import pytest +from pydantic import ValidationError + +from schemas.project import ProjectResponse, ProjectFullResponse, ProjectResponseList +from tests.test_schemas.helpers import assert_validation_error + + +class TestProjectResponse: + @pytest.mark.parametrize( + "field, value", + [ + ["visibility", "pending"], + ["visibility", "completed"], + ["status", "rendering"], + ["status", "completed"], + ], + ) + def test_project_response_valid( + self, + project_response_data: dict, + field: str, + value: str, + ) -> None: + project_response = ProjectResponse(**project_response_data) + assert project_response.model_dump() == project_response_data + + @pytest.mark.parametrize( + "visibility", + [ + "pending", + "sent", + "rendering", + "completed", + ], + ) + def test_project_response_not_valid_visibility( + self, + project_response_data: dict, + visibility: str, + ) -> None: + project_response_data["visibility"] = visibility + with pytest.raises(ValidationError) as exc_info: + ProjectResponse(**project_response_data) + + assert_validation_error( + exc_info, + "enum", + "visibility", + ) + + @pytest.mark.parametrize( + "status", + [ + "pending", + "sent", + "public", + "private", + ], + ) + def test_project_response_not_valid_status( + self, + project_response_data: dict, + status: str, + ) -> None: + project_response_data["status"] = status + with pytest.raises(ValidationError) as exc_info: + ProjectResponse(**project_response_data) + + assert_validation_error( + exc_info, + "enum", + "status", + ) + + @pytest.mark.parametrize( + "field", + ["render_id"], + ) + def test_project_response_without_optional_field( + self, + project_response_data: dict, + field: str, + ) -> None: + project_response_data.pop(field) + project_response = ProjectResponse(**project_response_data) + assert getattr(project_response, field) is None + + +class TestProjectFullResponse: + def test_project_full_response_valid( + self, project_full_response_data: dict + ) -> None: + project_full_response = ProjectFullResponse(**project_full_response_data) + assert project_full_response.model_dump() == project_full_response_data + + @pytest.mark.parametrize( + "field", + ["url"], + ) + def test_project_full_response_without_required_field( + self, + project_full_response_data: dict, + field: str, + ) -> None: + project_full_response_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectFullResponse(**project_full_response_data) + + assert_validation_error( + exc_info, + "missing", + field, + ) + + +class TestProjectResponseList: + def test_project_response_list_valid( + self, + project_response_list_data: dict, + ) -> None: + project_response_list = ProjectResponseList(**project_response_list_data) + assert project_response_list.model_dump() == project_response_list_data + + @pytest.mark.parametrize( + "field", + ["project_list", "size", "page"], + ) + def test_project_response_list_without_required_field( + self, + project_response_list_data: dict, + field: str, + ) -> None: + project_response_list_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectResponseList(**project_response_list_data) + + assert_validation_error( + exc_info, + "missing", + field, + ) diff --git a/backend/tests/test_schemas/test_project/test_project_update.py b/backend/tests/test_schemas/test_project/test_project_update.py new file mode 100644 index 00000000..f8c59749 --- /dev/null +++ b/backend/tests/test_schemas/test_project/test_project_update.py @@ -0,0 +1,105 @@ +import pytest +from pydantic import ValidationError + +from core.constants import ( + PROJECT_NAME_MIN_LENGTH, + PROJECT_NAME_MAX_LENGTH, + PROJECT_DESCRIPTION_MAX_LENGTH, + PROJECT_DESCRIPTION_MIN_LENGTH, +) +from schemas.project import ProjectPartialUpdate +from tests.test_schemas.helpers import assert_validation_error + + +class TestProjectPartialUpdate: + def test_project_partial_update_valid( + self, + project_partial_update_data: dict, + ) -> None: + project_partial_update = ProjectPartialUpdate(**project_partial_update_data) + assert project_partial_update.model_dump() == project_partial_update_data + + @pytest.mark.parametrize( + "field, value, expected_error", + [ + ["name", "a" * (PROJECT_NAME_MIN_LENGTH - 1), "string_too_short"], + ["name", "a" * (PROJECT_NAME_MAX_LENGTH + 1), "string_too_long"], + [ + "description", + "a" * (PROJECT_DESCRIPTION_MAX_LENGTH + 1), + "string_too_long", + ], + ], + ) + def test_project_partial_update_not_valid_field_value( + self, + project_partial_update_data: dict, + field: str, + value: str, + expected_error: str, + ) -> None: + project_partial_update_data[field] = value + with pytest.raises(ValidationError) as exc_info: + ProjectPartialUpdate(**project_partial_update_data) + + assert_validation_error( + exc_info, + expected_error, + field, + ) + + @pytest.mark.parametrize( + "field, value", + [ + ["name", "a" * PROJECT_NAME_MIN_LENGTH], + ["name", "a" * PROJECT_NAME_MAX_LENGTH], + ["description", "a" * PROJECT_DESCRIPTION_MIN_LENGTH], + ["description", "a" * PROJECT_DESCRIPTION_MAX_LENGTH], + ], + ) + def test_project_partial_update_boundary_field_value( + self, + project_partial_update_data: dict, + field: str, + value: str, + ) -> None: + project_partial_update_data[field] = value + project_partial_update = ProjectPartialUpdate(**project_partial_update_data) + assert project_partial_update.model_dump() == project_partial_update_data + + @pytest.mark.parametrize( + "field", + ["name", "description", "visibility"], + ) + def test_project_partial_update_without_optional_field( + self, + project_partial_update_data: dict, + field: str, + ) -> None: + project_partial_update_data.pop(field) + project_partial_update = ProjectPartialUpdate(**project_partial_update_data) + assert getattr(project_partial_update, field) is None + + @pytest.mark.parametrize( + "visibility", + [ + "pending", + "sent", + "rendering", + "completed", + ], + ) + def test_project_partial_update_not_valid_visibility( + self, + project_partial_update_data: dict, + visibility: str, + ) -> None: + project_partial_update_data["visibility"] = visibility + with pytest.raises(ValidationError) as exc_info: + ProjectPartialUpdate(**project_partial_update_data) + + assert_validation_error( + exc_info, + "enum", + "visibility", + ) diff --git a/backend/tests/test_schemas/test_project/test_project_with_render.py b/backend/tests/test_schemas/test_project/test_project_with_render.py new file mode 100644 index 00000000..dcedd4ef --- /dev/null +++ b/backend/tests/test_schemas/test_project/test_project_with_render.py @@ -0,0 +1,101 @@ +import pytest +from pydantic import ValidationError + +from schemas.project import ( + ProjectWithRenderFileFullResponse, + ProjectWithRenderResponse, + ProjectWithRenderFileResponse, +) +from tests.test_schemas.helpers import assert_validation_error + + +class TestProjectWithRenderFileFullResponse: + def test_project_with_render_file_full_response_valid( + self, + project_with_render_file_full_response_data: dict, + ) -> None: + project_with_render_file_full_response = ProjectWithRenderFileFullResponse( + **project_with_render_file_full_response_data + ) + assert ( + project_with_render_file_full_response.model_dump() + == project_with_render_file_full_response_data + ) + + @pytest.mark.parametrize("field", ["render"]) + def test_project_with_render_file_full_without_required_field( + self, + project_with_render_file_full_response_data: dict, + field: str, + ) -> None: + project_with_render_file_full_response_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectWithRenderFileFullResponse( + **project_with_render_file_full_response_data + ) + + assert_validation_error( + exc_info, + "missing", + field, + ) + + +class TestProjectWithRenderResponse: + def test_project_with_render_response_valid( + self, + project_with_render_response_data: dict, + ) -> None: + project_with_render_response = ProjectWithRenderResponse( + **project_with_render_response_data + ) + assert ( + project_with_render_response.model_dump() + == project_with_render_response_data + ) + + @pytest.mark.parametrize("field", ["render"]) + def test_project_with_render_response_without_required_field( + self, + project_with_render_response_data: dict, + field: str, + ) -> None: + project_with_render_response_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectWithRenderResponse(**project_with_render_response_data) + + assert_validation_error( + exc_info, + "missing", + field, + ) + + +class TestProjectWithRenderFileResponse: + def test_project_with_render_file_response_valid( + self, + project_with_render_file_response_data: dict, + ) -> None: + project_with_render_file_response = ProjectWithRenderFileResponse( + **project_with_render_file_response_data + ) + assert ( + project_with_render_file_response.model_dump() + == project_with_render_file_response_data + ) + + @pytest.mark.parametrize("field", ["render"]) + def test_project_with_render_file_response_without_required_field( + self, + project_with_render_file_response_data: dict, + field: str, + ) -> None: + project_with_render_file_response_data.pop(field) + with pytest.raises(ValidationError) as exc_info: + ProjectWithRenderFileResponse(**project_with_render_file_response_data) + + assert_validation_error( + exc_info, + "missing", + field, + )