From 27744421cd1efc985939f8470c58dcc50ae4b614 Mon Sep 17 00:00:00 2001 From: hideyukiMORI Date: Fri, 22 May 2026 20:59:04 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat(example):=20/examples/*=20=E3=83=91?= =?UTF-8?q?=E3=82=B9=E3=81=A7=20NENE2=20OpenAPI=20=E3=81=A8=E3=83=91?= =?UTF-8?q?=E3=83=AA=E3=83=86=E3=82=A3=E3=82=92=E6=8F=83=E3=81=88=E3=82=8B?= =?UTF-8?q?=20(#578)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit notes/tags/comments を /examples 配下にマウントし /examples/ping を追加。 Co-authored-by: Cursor --- src/example/app.py | 14 ++++-- tests/example/comment/test_comment_http.py | 50 +++++++++++----------- tests/example/note/test_list_notes.py | 28 ++++++------ tests/example/tag/test_tags.py | 32 +++++++------- tests/scripts/test_export_openapi.py | 3 +- 5 files changed, 68 insertions(+), 59 deletions(-) diff --git a/src/example/app.py b/src/example/app.py index 5faa31b..7c72769 100644 --- a/src/example/app.py +++ b/src/example/app.py @@ -165,6 +165,7 @@ def create_app(settings: AppSettings | None = None) -> FastAPI: note_repo, tag_repo, comment_repo, db_executor = _build_repositories(cfg) app.state.db_executor = db_executor + # OpenAPI parity with NENE2 PHP: /examples/notes, /examples/tags (nene2-js client paths). app.include_router( make_note_router( ListNotesUseCase(note_repo), @@ -172,7 +173,8 @@ def create_app(settings: AppSettings | None = None) -> FastAPI: CreateNoteUseCase(note_repo), UpdateNoteUseCase(note_repo), DeleteNoteUseCase(note_repo), - ) + ), + prefix="/examples", ) app.include_router( @@ -182,7 +184,8 @@ def create_app(settings: AppSettings | None = None) -> FastAPI: CreateTagUseCase(tag_repo), UpdateTagUseCase(tag_repo), DeleteTagUseCase(tag_repo), - ) + ), + prefix="/examples", ) app.include_router( @@ -192,9 +195,14 @@ def create_app(settings: AppSettings | None = None) -> FastAPI: CreateCommentUseCase(comment_repo, note_repo), UpdateCommentUseCase(comment_repo), DeleteCommentUseCase(comment_repo), - ) + ), + prefix="/examples", ) + @app.get("/examples/ping", tags=["system"], summary="Example ping") + async def example_ping() -> JSONResponse: + return JSONResponse({"message": "pong", "status": "ok"}) + db_health = DatabaseHealthCheck(db_executor) if db_executor else None @app.get("/health", tags=["system"], summary="Health check") diff --git a/tests/example/comment/test_comment_http.py b/tests/example/comment/test_comment_http.py index ade894c..e70ae2d 100644 --- a/tests/example/comment/test_comment_http.py +++ b/tests/example/comment/test_comment_http.py @@ -21,8 +21,8 @@ def _make_client() -> Generator[TestClient, None, None]: def test_list_comments_empty() -> None: with _make_client() as client: - note = client.post("/notes", json={"title": "Test Note", "body": "body"}).json() - response = client.get(f"/notes/{note['id']}/comments") + note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() + response = client.get(f"/examples/notes/{note['id']}/comments") assert response.status_code == 200 body = response.json() assert body["total"] == 0 @@ -31,41 +31,41 @@ def test_list_comments_empty() -> None: def test_create_and_list_comments() -> None: with _make_client() as client: - note = client.post("/notes", json={"title": "Test Note", "body": "body"}).json() + note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() note_id = note["id"] - create_response = client.post(f"/notes/{note_id}/comments", json={"body": "first comment"}) + create_response = client.post(f"/examples/notes/{note_id}/comments", json={"body": "first comment"}) assert create_response.status_code == 201 data = create_response.json() assert data["note_id"] == note_id assert data["body"] == "first comment" - list_response = client.get(f"/notes/{note_id}/comments") + list_response = client.get(f"/examples/notes/{note_id}/comments") assert list_response.json()["total"] == 1 def test_get_comment() -> None: with _make_client() as client: - note = client.post("/notes", json={"title": "Test Note", "body": "body"}).json() + note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() note_id = note["id"] - created = client.post(f"/notes/{note_id}/comments", json={"body": "get me"}).json() - response = client.get(f"/notes/{note_id}/comments/{created['id']}") + created = client.post(f"/examples/notes/{note_id}/comments", json={"body": "get me"}).json() + response = client.get(f"/examples/notes/{note_id}/comments/{created['id']}") assert response.status_code == 200 assert response.json()["body"] == "get me" def test_get_comment_not_found() -> None: with _make_client() as client: - note = client.post("/notes", json={"title": "Test Note", "body": "body"}).json() - response = client.get(f"/notes/{note['id']}/comments/9999") + note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() + response = client.get(f"/examples/notes/{note['id']}/comments/9999") assert response.status_code == 404 def test_update_comment() -> None: with _make_client() as client: - note = client.post("/notes", json={"title": "Test Note", "body": "body"}).json() + note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() note_id = note["id"] - created = client.post(f"/notes/{note_id}/comments", json={"body": "original"}).json() - url = f"/notes/{note_id}/comments/{created['id']}" + created = client.post(f"/examples/notes/{note_id}/comments", json={"body": "original"}).json() + url = f"/examples/notes/{note_id}/comments/{created['id']}" response = client.put(url, json={"body": "updated"}) assert response.status_code == 200 assert response.json()["body"] == "updated" @@ -73,40 +73,40 @@ def test_update_comment() -> None: def test_delete_comment() -> None: with _make_client() as client: - note = client.post("/notes", json={"title": "Test Note", "body": "body"}).json() + note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() note_id = note["id"] - created = client.post(f"/notes/{note_id}/comments", json={"body": "to delete"}).json() - delete_response = client.delete(f"/notes/{note_id}/comments/{created['id']}") + created = client.post(f"/examples/notes/{note_id}/comments", json={"body": "to delete"}).json() + delete_response = client.delete(f"/examples/notes/{note_id}/comments/{created['id']}") assert delete_response.status_code == 204 - get_response = client.get(f"/notes/{note_id}/comments/{created['id']}") + get_response = client.get(f"/examples/notes/{note_id}/comments/{created['id']}") assert get_response.status_code == 404 def test_create_comment_empty_body_returns_422() -> None: with _make_client() as client: - note = client.post("/notes", json={"title": "Test Note", "body": "body"}).json() - response = client.post(f"/notes/{note['id']}/comments", json={"body": " "}) + note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() + response = client.post(f"/examples/notes/{note['id']}/comments", json={"body": " "}) assert response.status_code == 422 def test_create_comment_for_nonexistent_note_returns_404() -> None: with _make_client() as client: - response = client.post("/notes/9999/comments", json={"body": "orphan"}) + response = client.post("/examples/notes/9999/comments", json={"body": "orphan"}) assert response.status_code == 404 def test_get_comment_from_wrong_note_returns_404() -> None: with _make_client() as client: - note1 = client.post("/notes", json={"title": "Note 1", "body": "b"}).json() - note2 = client.post("/notes", json={"title": "Note 2", "body": "b"}).json() + note1 = client.post("/examples/notes", json={"title": "Note 1", "body": "b"}).json() + note2 = client.post("/examples/notes", json={"title": "Note 2", "body": "b"}).json() comment = client.post( - f"/notes/{note1['id']}/comments", json={"body": "belongs to note1"} + f"/examples/notes/{note1['id']}/comments", json={"body": "belongs to note1"} ).json() - response = client.get(f"/notes/{note2['id']}/comments/{comment['id']}") + response = client.get(f"/examples/notes/{note2['id']}/comments/{comment['id']}") assert response.status_code == 404 def test_list_comments_for_nonexistent_note_returns_404() -> None: with _make_client() as client: - response = client.get("/notes/9999/comments") + response = client.get("/examples/notes/9999/comments") assert response.status_code == 404 diff --git a/tests/example/note/test_list_notes.py b/tests/example/note/test_list_notes.py index 66a8491..36a9c72 100644 --- a/tests/example/note/test_list_notes.py +++ b/tests/example/note/test_list_notes.py @@ -5,7 +5,7 @@ def test_list_notes_empty(client: TestClient) -> None: - r = client.get("/notes") + r = client.get("/examples/notes") assert r.status_code == 200 body = r.json() assert body["items"] == [] @@ -15,61 +15,61 @@ def test_list_notes_empty(client: TestClient) -> None: def test_create_and_get_note(client: TestClient) -> None: - r = client.post("/notes", json={"title": "Hello", "body": "World"}) + r = client.post("/examples/notes", json={"title": "Hello", "body": "World"}) assert r.status_code == 201 note_id = r.json()["id"] - r2 = client.get(f"/notes/{note_id}") + r2 = client.get(f"/examples/notes/{note_id}") assert r2.status_code == 200 assert r2.json()["title"] == "Hello" def test_create_note_empty_title_returns_422(client: TestClient) -> None: - r = client.post("/notes", json={"title": "", "body": "b"}) + r = client.post("/examples/notes", json={"title": "", "body": "b"}) assert r.status_code == 422 assert r.json()["errors"][0]["field"] == "title" def test_get_nonexistent_note_returns_404(client: TestClient) -> None: - r = client.get("/notes/9999") + r = client.get("/examples/notes/9999") assert r.status_code == 404 def test_update_note_returns_200(client: TestClient) -> None: - r = client.post("/notes", json={"title": "Old", "body": "Old body"}) + r = client.post("/examples/notes", json={"title": "Old", "body": "Old body"}) note_id = r.json()["id"] - r2 = client.put(f"/notes/{note_id}", json={"title": "New", "body": "New body"}) + r2 = client.put(f"/examples/notes/{note_id}", json={"title": "New", "body": "New body"}) assert r2.status_code == 200 assert r2.json()["title"] == "New" assert r2.json()["body"] == "New body" def test_update_nonexistent_note_returns_404(client: TestClient) -> None: - r = client.put("/notes/9999", json={"title": "T", "body": "B"}) + r = client.put("/examples/notes/9999", json={"title": "T", "body": "B"}) assert r.status_code == 404 def test_update_note_empty_title_returns_422(client: TestClient) -> None: - r = client.post("/notes", json={"title": "T", "body": "B"}) + r = client.post("/examples/notes", json={"title": "T", "body": "B"}) note_id = r.json()["id"] - r2 = client.put(f"/notes/{note_id}", json={"title": "", "body": "B"}) + r2 = client.put(f"/examples/notes/{note_id}", json={"title": "", "body": "B"}) assert r2.status_code == 422 def test_delete_note_returns_204(client: TestClient) -> None: - r = client.post("/notes", json={"title": "T", "body": "B"}) + r = client.post("/examples/notes", json={"title": "T", "body": "B"}) note_id = r.json()["id"] - r2 = client.delete(f"/notes/{note_id}") + r2 = client.delete(f"/examples/notes/{note_id}") assert r2.status_code == 204 - r3 = client.get(f"/notes/{note_id}") + r3 = client.get(f"/examples/notes/{note_id}") assert r3.status_code == 404 def test_delete_nonexistent_note_returns_404(client: TestClient) -> None: - r = client.delete("/notes/9999") + r = client.delete("/examples/notes/9999") assert r.status_code == 404 diff --git a/tests/example/tag/test_tags.py b/tests/example/tag/test_tags.py index 609ceee..1934a66 100644 --- a/tests/example/tag/test_tags.py +++ b/tests/example/tag/test_tags.py @@ -4,7 +4,7 @@ def test_list_tags_empty(client: TestClient) -> None: - r = client.get("/tags") + r = client.get("/examples/tags") assert r.status_code == 200 body = r.json() assert body["items"] == [] @@ -12,68 +12,68 @@ def test_list_tags_empty(client: TestClient) -> None: def test_create_and_get_tag(client: TestClient) -> None: - r = client.post("/tags", json={"name": "python"}) + r = client.post("/examples/tags", json={"name": "python"}) assert r.status_code == 201 tag_id = r.json()["id"] - r2 = client.get(f"/tags/{tag_id}") + r2 = client.get(f"/examples/tags/{tag_id}") assert r2.status_code == 200 assert r2.json()["name"] == "python" def test_create_tag_empty_name_returns_422(client: TestClient) -> None: - r = client.post("/tags", json={"name": ""}) + r = client.post("/examples/tags", json={"name": ""}) assert r.status_code == 422 assert r.json()["errors"][0]["field"] == "name" def test_get_nonexistent_tag_returns_404(client: TestClient) -> None: - r = client.get("/tags/9999") + r = client.get("/examples/tags/9999") assert r.status_code == 404 def test_update_tag_returns_200(client: TestClient) -> None: - r = client.post("/tags", json={"name": "old"}) + r = client.post("/examples/tags", json={"name": "old"}) tag_id = r.json()["id"] - r2 = client.put(f"/tags/{tag_id}", json={"name": "new"}) + r2 = client.put(f"/examples/tags/{tag_id}", json={"name": "new"}) assert r2.status_code == 200 assert r2.json()["name"] == "new" def test_update_nonexistent_tag_returns_404(client: TestClient) -> None: - r = client.put("/tags/9999", json={"name": "x"}) + r = client.put("/examples/tags/9999", json={"name": "x"}) assert r.status_code == 404 def test_update_tag_empty_name_returns_422(client: TestClient) -> None: - r = client.post("/tags", json={"name": "t"}) + r = client.post("/examples/tags", json={"name": "t"}) tag_id = r.json()["id"] - r2 = client.put(f"/tags/{tag_id}", json={"name": ""}) + r2 = client.put(f"/examples/tags/{tag_id}", json={"name": ""}) assert r2.status_code == 422 def test_delete_tag_returns_204(client: TestClient) -> None: - r = client.post("/tags", json={"name": "temp"}) + r = client.post("/examples/tags", json={"name": "temp"}) tag_id = r.json()["id"] - r2 = client.delete(f"/tags/{tag_id}") + r2 = client.delete(f"/examples/tags/{tag_id}") assert r2.status_code == 204 - r3 = client.get(f"/tags/{tag_id}") + r3 = client.get(f"/examples/tags/{tag_id}") assert r3.status_code == 404 def test_delete_nonexistent_tag_returns_404(client: TestClient) -> None: - r = client.delete("/tags/9999") + r = client.delete("/examples/tags/9999") assert r.status_code == 404 def test_list_tags_pagination(client: TestClient) -> None: for name in ["a", "b", "c"]: - client.post("/tags", json={"name": name}) + client.post("/examples/tags", json={"name": name}) - r = client.get("/tags?limit=2&offset=0") + r = client.get("/examples/tags?limit=2&offset=0") assert r.status_code == 200 body = r.json() assert len(body["items"]) == 2 diff --git a/tests/scripts/test_export_openapi.py b/tests/scripts/test_export_openapi.py index 2a46027..9be8fca 100644 --- a/tests/scripts/test_export_openapi.py +++ b/tests/scripts/test_export_openapi.py @@ -27,7 +27,8 @@ def test_main_yaml_is_valid_openapi( content = yaml.safe_load((tmp_path / "docs" / "openapi.yaml").read_text()) assert content["openapi"].startswith("3.") - assert "/notes" in content["paths"] + assert "/examples/notes" in content["paths"] + assert "/examples/ping" in content["paths"] def test_main_prints_output_path( From c3f155ea4677e7b480f5f9f3a6874cd1c5997367 Mon Sep 17 00:00:00 2001 From: hideyukiMORI Date: Fri, 22 May 2026 21:01:35 +0900 Subject: [PATCH 2/2] =?UTF-8?q?style(test):=20comment=20=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=81=AE=E8=A1=8C=E9=95=B7=E3=82=92=20ruff=20?= =?UTF-8?q?=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- tests/example/comment/test_comment_http.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/example/comment/test_comment_http.py b/tests/example/comment/test_comment_http.py index e70ae2d..2392c8c 100644 --- a/tests/example/comment/test_comment_http.py +++ b/tests/example/comment/test_comment_http.py @@ -33,7 +33,8 @@ def test_create_and_list_comments() -> None: with _make_client() as client: note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() note_id = note["id"] - create_response = client.post(f"/examples/notes/{note_id}/comments", json={"body": "first comment"}) + comments = f"/examples/notes/{note_id}/comments" + create_response = client.post(comments, json={"body": "first comment"}) assert create_response.status_code == 201 data = create_response.json() assert data["note_id"] == note_id @@ -64,7 +65,8 @@ def test_update_comment() -> None: with _make_client() as client: note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() note_id = note["id"] - created = client.post(f"/examples/notes/{note_id}/comments", json={"body": "original"}).json() + comments = f"/examples/notes/{note_id}/comments" + created = client.post(comments, json={"body": "original"}).json() url = f"/examples/notes/{note_id}/comments/{created['id']}" response = client.put(url, json={"body": "updated"}) assert response.status_code == 200 @@ -75,8 +77,9 @@ def test_delete_comment() -> None: with _make_client() as client: note = client.post("/examples/notes", json={"title": "Test Note", "body": "body"}).json() note_id = note["id"] - created = client.post(f"/examples/notes/{note_id}/comments", json={"body": "to delete"}).json() - delete_response = client.delete(f"/examples/notes/{note_id}/comments/{created['id']}") + comments = f"/examples/notes/{note_id}/comments" + created = client.post(comments, json={"body": "to delete"}).json() + delete_response = client.delete(f"{comments}/{created['id']}") assert delete_response.status_code == 204 get_response = client.get(f"/examples/notes/{note_id}/comments/{created['id']}") assert get_response.status_code == 404