|
1 | 1 | # Copyright 2024 The Meatie Authors. All rights reserved. |
2 | 2 | # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. |
3 | | -import json |
4 | 3 | from http import HTTPStatus |
5 | | -from http.server import BaseHTTPRequestHandler |
6 | | -from typing import Annotated, Any, Optional, Union |
| 4 | +from typing import Annotated, Union |
7 | 5 |
|
8 | 6 | import pytest |
9 | 7 | from aiohttp import ClientSession |
10 | 8 | from http_test import Handler, HTTPTestServer |
| 9 | +from http_test.handlers import echo_json_handler |
11 | 10 | from typing_extensions import Literal |
12 | 11 |
|
13 | | -from meatie import AsyncResponse, api_ref, endpoint |
| 12 | +from meatie import api_ref, endpoint |
14 | 13 | from meatie_aiohttp import Client |
15 | 14 |
|
16 | 15 | pydantic = pytest.importorskip("pydantic", minversion="2.0.0") |
17 | 16 |
|
18 | 17 |
|
19 | | -@pytest.mark.asyncio() |
20 | | -async def test_post_request_body_with_fmt(http_server: HTTPTestServer) -> None: |
21 | | - # GIVEN |
22 | | - class Request(pydantic.BaseModel): |
23 | | - data: Optional[dict[str, Any]] |
| 18 | +class Todo(pydantic.BaseModel): |
| 19 | + user_id: int = pydantic.Field(alias="userId") |
| 20 | + id: int |
| 21 | + title: str |
| 22 | + completed: bool |
24 | 23 |
|
25 | | - def handler(request: BaseHTTPRequestHandler) -> None: |
26 | | - content_length = request.headers.get("Content-Length", "0") |
27 | | - raw_body = request.rfile.read(int(content_length)) |
28 | | - body = json.loads(raw_body.decode("utf-8")) |
29 | 24 |
|
30 | | - if body.get("data") is not None: |
31 | | - request.send_response(HTTPStatus.BAD_REQUEST) |
32 | | - else: |
33 | | - request.send_response(HTTPStatus.OK) |
34 | | - request.end_headers() |
| 25 | +class Params: |
| 26 | + @staticmethod |
| 27 | + def todo(value: Todo) -> dict: |
| 28 | + return value.model_dump(by_alias=True) |
35 | 29 |
|
36 | | - http_server.handler = handler |
37 | 30 |
|
38 | | - def dump_body(model: pydantic.BaseModel) -> str: |
39 | | - return model.model_dump_json(by_alias=True, exclude_none=True) |
| 31 | +class JsonPlaceholderClient(Client): |
| 32 | + def __init__(self, base_url: str) -> None: |
| 33 | + super().__init__(ClientSession(base_url=base_url)) |
40 | 34 |
|
41 | | - class TestClient(Client): |
42 | | - @endpoint("/") |
43 | | - async def post_request(self, body: Annotated[Request, api_ref(fmt=dump_body)]) -> AsyncResponse: ... |
| 35 | + @endpoint("/todos") |
| 36 | + async def post_todo_as_dict( |
| 37 | + self, todo: Annotated[Todo, api_ref("body", fmt=lambda data: data.model_dump(by_alias=True))] |
| 38 | + ) -> Todo: ... |
| 39 | + |
| 40 | + |
| 41 | +@pytest.mark.asyncio() |
| 42 | +async def test_post_request_body_with_fmt_as_dict(http_server: HTTPTestServer) -> None: |
| 43 | + # GIVEN |
| 44 | + http_server.handler = echo_json_handler |
44 | 45 |
|
45 | 46 | # WHEN |
46 | | - async with TestClient(ClientSession(http_server.base_url)) as client: |
47 | | - response = await client.post_request(Request(data=None)) |
| 47 | + async with JsonPlaceholderClient(http_server.base_url) as client: |
| 48 | + todo = await client.post_todo_as_dict(Todo(userId=123, id=456, title="abc", completed=True)) |
48 | 49 |
|
49 | 50 | # THEN |
50 | | - assert response.status == HTTPStatus.OK |
| 51 | + assert todo.user_id == 123 |
51 | 52 |
|
52 | 53 |
|
53 | 54 | class TodoV1(pydantic.BaseModel): |
|
0 commit comments