From ecaed9f70edd0677f72f08024b46019ca2dacad3 Mon Sep 17 00:00:00 2001 From: samadpls Date: Tue, 28 Jan 2025 02:32:31 +0500 Subject: [PATCH] Add PUT and DELETE endpoint decorators with tests Signed-off-by: samadpls --- core/cat/mad_hatter/decorators/endpoint.py | 58 +++++++++++++++++++ core/tests/mocks/mock_plugin/mock_endpoint.py | 10 +++- core/tests/routes/test_custom_endpoints.py | 15 +++++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/core/cat/mad_hatter/decorators/endpoint.py b/core/cat/mad_hatter/decorators/endpoint.py index 8960ad19d..972bced24 100644 --- a/core/cat/mad_hatter/decorators/endpoint.py +++ b/core/cat/mad_hatter/decorators/endpoint.py @@ -191,6 +191,64 @@ def my_post_endpoint(item: Item): **kwargs, ) + def put( + cls, + path, + prefix=default_prefix, + response_model=None, + tags=default_tags, + **kwargs, + ) -> Callable: + """ + Define a custom API endpoint for PUT operation, parameters are the same as FastAPI path operation. + Examples: + .. code-block:: python + from cat.mad_hatter.decorators import endpoint + from pydantic import BaseModel + + class Item(BaseModel): + name: str + description: str + + @endpoint.put(path="/hello") + def my_put_endpoint(item: Item): + return {"Hello": item.name, "Description": item.description} + """ + return cls.endpoint( + path=path, + methods={"PUT"}, + prefix=prefix, + response_model=response_model, + tags=tags, + **kwargs, + ) + + def delete( + cls, + path, + prefix=default_prefix, + response_model=None, + tags=default_tags, + **kwargs, + ) -> Callable: + """ + Define a custom API endpoint for DELETE operation, parameters are the same as FastAPI path operation. + Examples: + .. code-block:: python + from cat.mad_hatter.decorators import endpoint + + @endpoint.delete(path="/hello/{item_id}") + def my_delete_endpoint(item_id: int): + return {"message": f"Deleted item {item_id}"} + """ + return cls.endpoint( + path=path, + methods={"DELETE"}, + prefix=prefix, + response_model=response_model, + tags=tags, + **kwargs, + ) endpoint = None diff --git a/core/tests/mocks/mock_plugin/mock_endpoint.py b/core/tests/mocks/mock_plugin/mock_endpoint.py index 7f4b49fe7..715ed5fa4 100644 --- a/core/tests/mocks/mock_plugin/mock_endpoint.py +++ b/core/tests/mocks/mock_plugin/mock_endpoint.py @@ -21,4 +21,12 @@ def test_get(stray=check_permissions(AuthResource.PLUGINS, AuthPermission.LIST)) @endpoint.post(path="/crud", prefix="/tests", tags=["Tests"]) def test_post(item: Item) -> str: - return {"name": item.name, "description": item.description} \ No newline at end of file + return {"name": item.name, "description": item.description} + +@endpoint.put(path="/crud", prefix="/tests", tags=["Tests"]) +def test_put(item: Item) -> str: + return {"name": item.name, "description": item.description} + +@endpoint.delete(path="/crud/{item_id}", prefix="/tests", tags=["Tests"]) +def test_delete(item_id: int): + return {"result": "ok", "deleted_id": item_id} \ No newline at end of file diff --git a/core/tests/routes/test_custom_endpoints.py b/core/tests/routes/test_custom_endpoints.py index e1e0b8d64..a334696c2 100644 --- a/core/tests/routes/test_custom_endpoints.py +++ b/core/tests/routes/test_custom_endpoints.py @@ -31,6 +31,21 @@ def test_custom_endpoint_post(client, just_installed_plugin): assert response.json()["name"] == "the cat" assert response.json()["description"] == "it's magic" +def test_custom_endpoint_put(client, just_installed_plugin): + payload = {"name": "the cat", "description": "it's magic"} + response = client.put("/tests/crud", json=payload) + + assert response.status_code == 200 + assert response.json()["name"] == "the cat" + assert response.json()["description"] == "it's magic" + +def test_custom_endpoint_delete(client, just_installed_plugin): + response = client.delete("/tests/crud/123") + + assert response.status_code == 200 + assert response.json()["result"] == "ok" + assert response.json()["deleted_id"] == 123 + @pytest.mark.parametrize("switch_type", ["deactivation", "uninstall"]) def test_custom_endpoints_on_plugin_deactivation_or_uninstall(