소스 검색

Add InternalGateway.update (#13)

Casper van der Wel 2 년 전
부모
커밋
38d073cfdd
3개의 변경된 파일49개의 추가작업 그리고 1개의 파일을 삭제
  1. 1 1
      CHANGES.md
  2. 12 0
      clean_python/base/infrastructure/internal_gateway.py
  3. 36 0
      tests/test_internal_gateway.py

+ 1 - 1
CHANGES.md

@@ -4,7 +4,7 @@
 0.4.3 (unreleased)
 ------------------
 
-- Nothing changed yet.
+- Added `InternalGateway.update`.
 
 
 0.4.2 (2023-09-04)

+ 12 - 0
clean_python/base/infrastructure/internal_gateway.py

@@ -10,6 +10,7 @@ from clean_python.base.application.manage import Manage
 from clean_python.base.domain import BadRequest
 from clean_python.base.domain import DoesNotExist
 from clean_python.base.domain import Filter
+from clean_python.base.domain import Json
 from clean_python.base.domain import PageOptions
 from clean_python.base.domain import RootEntity
 from clean_python.base.domain import ValueObject
@@ -60,3 +61,14 @@ class InternalGateway(Generic[E, T]):
 
     async def exists(self, filters: List[Filter]) -> bool:
         return await self.manage.exists(filters)
+
+    async def update(self, values: Json) -> T:
+        values = values.copy()
+        id_ = values.pop("id", None)
+        if id_ is None:
+            raise DoesNotExist("item", id_)
+        try:
+            updated = await self.manage.update(id_, values)
+        except BadRequest as e:
+            raise ValueError(e)
+        return self._map(updated)

+ 36 - 0
tests/test_internal_gateway.py

@@ -3,9 +3,13 @@ from typing import cast
 import pytest
 from pydantic import Field
 
+from clean_python import Conflict
+from clean_python import DoesNotExist
 from clean_python import Filter
+from clean_python import Id
 from clean_python import InMemoryGateway
 from clean_python import InternalGateway
+from clean_python import Json
 from clean_python import Manage
 from clean_python import Repository
 from clean_python import RootEntity
@@ -26,6 +30,11 @@ class ManageUser(Manage[User]):
     def __init__(self):
         self.repo = UserRepository(gateway=InMemoryGateway([]))
 
+    async def update(self, id: Id, values: Json) -> User:
+        if values.get("name") == "conflict":
+            raise Conflict()
+        return await self.repo.update(id, values)
+
 
 # domain - this module
 class UserObj(ValueObject):
@@ -120,3 +129,30 @@ async def test_exists_2(internal_gateway_with_record: UserGateway):
         await internal_gateway_with_record.exists([Filter(field="id", values=[1])])
         is False
     )
+
+
+async def test_update(internal_gateway_with_record):
+    updated = await internal_gateway_with_record.update({"id": 12, "name": "bar"})
+
+    assert updated == UserObj(id=12, name="bar")
+
+
+@pytest.mark.parametrize(
+    "values", [{"id": 12, "name": "bar"}, {"id": None, "name": "bar"}, {"name": "bar"}]
+)
+async def test_update_does_not_exist(internal_gateway, values):
+    with pytest.raises(DoesNotExist):
+        assert await internal_gateway.update(values)
+
+
+async def test_update_bad_request(internal_gateway_with_record):
+    # a 'bad request' should be reraised as a ValueError; errors in gateways
+    # are an internal affair.
+    with pytest.raises(ValueError):
+        assert await internal_gateway_with_record.update({"id": 12, "name": ""})
+
+
+async def test_update_conflict(internal_gateway_with_record):
+    # a 'conflict' should bubble through the internal gateway
+    with pytest.raises(Conflict):
+        assert await internal_gateway_with_record.update({"id": 12, "name": "conflict"})