diff --git a/solution/services/backend/api/v1/time/__init__.py b/solution/services/backend/api/v1/time/__init__.py new file mode 100644 index 0000000..dc9fd4c --- /dev/null +++ b/solution/services/backend/api/v1/time/__init__.py @@ -0,0 +1 @@ +# noqa: A005 diff --git a/solution/services/backend/api/v1/time/schemas.py b/solution/services/backend/api/v1/time/schemas.py new file mode 100644 index 0000000..f6213e8 --- /dev/null +++ b/solution/services/backend/api/v1/time/schemas.py @@ -0,0 +1,21 @@ +from django.core.cache import cache +from ninja import Schema +from pydantic import field_validator +from pydantic.types import NonNegativeInt + + +class CurrentDate(Schema): + current_date: NonNegativeInt + + @field_validator("current_date", mode="after") + @classmethod + def check_bigger_than_setted_date(cls, value: int) -> int: + current_date = cache.get("current_date", default=0) + if value < current_date: + err = ( + "current_date can't be less than setted " + f"date ({current_date})." + ) + raise ValueError(err) + + return value diff --git a/solution/services/backend/api/v1/time/tests.py b/solution/services/backend/api/v1/time/tests.py new file mode 100644 index 0000000..d9d72bc --- /dev/null +++ b/solution/services/backend/api/v1/time/tests.py @@ -0,0 +1,120 @@ +from http import HTTPStatus as status +from django.test import TestCase, override_settings +from django.core.cache import cache +import json + + +class AdvanceTimeTests(TestCase): + @override_settings( + CACHES={ + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + } + } + ) + def setUp(self): + cache.clear() + cache.set("current_date", 10) + + self.url = "/time/advance" + + @override_settings( + CACHES={ + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + } + } + ) + def test_advance_time_success(self): + self.assertEqual(cache.get("current_date"), 10) + + response = self.client.post( + self.url, + data=json.dumps({"current_date": 15}), + content_type="application/json", + ) + + self.assertEqual(response.status_code, status.OK) + self.assertEqual(response.json()["current_date"], 15) + self.assertEqual(cache.get("current_date"), 15) + + # unittest & django pobeda so i can't use override_settings and parametrized at the same time, sorry + @override_settings( + CACHES={ + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + } + } + ) + def test_advance_time_failure_invalid_value1(self): + response = self.client.post( + self.url, + data=json.dumps({"current_date": list()}), + content_type="application/json", + ) + + self.assertEqual(response.status_code, status.BAD_REQUEST) + + @override_settings( + CACHES={ + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + } + } + ) + def test_advance_time_failure_invalid_value2(self): + response = self.client.post( + self.url, + data=json.dumps({"current_date": -1241}), + content_type="application/json", + ) + + self.assertEqual(response.status_code, status.BAD_REQUEST) + + @override_settings( + CACHES={ + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + } + } + ) + def test_advance_time_failure_invalid_value3(self): + response = self.client.post( + self.url, + data=json.dumps({"current_date": "lol"}), + content_type="application/json", + ) + + self.assertEqual(response.status_code, status.BAD_REQUEST) + + @override_settings( + CACHES={ + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + } + } + ) + def test_advance_time_failure_invalid_value4(self): + response = self.client.post( + self.url, + data=json.dumps({"current_date": dict()}), + content_type="application/json", + ) + + self.assertEqual(response.status_code, status.BAD_REQUEST) + + @override_settings( + CACHES={ + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + } + } + ) + def test_advance_time_failure_less_than_actual(self): + response = self.client.post( + self.url, + data=json.dumps({"current_date": 5}), + content_type="application/json", + ) + + self.assertEqual(response.status_code, status.BAD_REQUEST) diff --git a/solution/services/backend/api/v1/time/views.py b/solution/services/backend/api/v1/time/views.py new file mode 100644 index 0000000..d940a6c --- /dev/null +++ b/solution/services/backend/api/v1/time/views.py @@ -0,0 +1,25 @@ +from http import HTTPStatus as status + +from django.core.cache import cache +from django.http import HttpRequest +from ninja import Router + +from api.v1 import schemas as global_schemas +from api.v1.time import schemas + +router = Router(tags=["time"]) + + +@router.post( + "/advance", + response={ + status.OK: schemas.CurrentDate, + status.BAD_REQUEST: global_schemas.BadRequestError, + }, +) +def advance_time( + request: HttpRequest, new_date: schemas.CurrentDate +) -> tuple[status, schemas.CurrentDate]: + cache.set("current_date", new_date.current_date) + + return status.OK, schemas.CurrentDate(current_date=new_date.current_date)