From 76c0c5fcddf826b1321b605a5dd5154e9e267b4c Mon Sep 17 00:00:00 2001 From: moha Date: Fri, 24 Apr 2026 03:31:48 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E3=83=89=E3=82=AD=E3=83=A5?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E4=B8=80=E8=A6=A7API=E3=81=AB?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E5=90=8D=E6=A4=9C=E7=B4=A2?= =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=AB=E3=82=BF=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/routers/documents.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/backend/routers/documents.py b/backend/routers/documents.py index d7f9afa..b210221 100644 --- a/backend/routers/documents.py +++ b/backend/routers/documents.py @@ -132,19 +132,28 @@ async def upload_document( async def list_documents( offset: int = 0, limit: int = 20, + search: str = "", db: AsyncSession = Depends(get_db), ): - """登録済み文書一覧を取得する(ページネーション対応)""" + """登録済み文書一覧を取得する(ページネーション・検索対応)""" if limit > 100: limit = 100 if offset < 0: offset = 0 - total_result = await db.execute(select(func.count(Document.id))) + base_query = select(Document) + count_query = select(func.count(Document.id)) + + if search.strip(): + pattern = f"%{search.strip()}%" + base_query = base_query.where(Document.filename.ilike(pattern)) + count_query = count_query.where(Document.filename.ilike(pattern)) + + total_result = await db.execute(count_query) total = int(total_result.scalar_one()) result = await db.execute( - select(Document) + base_query .order_by(Document.uploaded_at.desc()) .offset(offset) .limit(limit) From c51dbefa334cab8f1fc50991a77b01c1939ea662 Mon Sep 17 00:00:00 2001 From: moha Date: Fri, 24 Apr 2026 03:31:58 +0900 Subject: [PATCH 2/2] =?UTF-8?q?test:=20=E3=83=95=E3=82=A1=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E5=90=8D=E6=A4=9C=E7=B4=A2=E3=83=95=E3=82=A3=E3=83=AB?= =?UTF-8?q?=E3=82=BF=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/tests/test_documents_router.py | 42 ++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/backend/tests/test_documents_router.py b/backend/tests/test_documents_router.py index c107148..2076b5d 100644 --- a/backend/tests/test_documents_router.py +++ b/backend/tests/test_documents_router.py @@ -287,6 +287,48 @@ def test_list_negative_offset_clamped_to_zero(self): data = response.json() assert data["offset"] == 0 + def test_list_with_search_parameter(self): + """searchパラメータ付きでリクエストが正常に処理される""" + app, _ = create_test_app() + client = TestClient(app) + + response = client.get("/api/documents?search=report") + assert response.status_code == 200 + data = response.json() + assert "items" in data + assert "total" in data + + def test_list_with_empty_search(self): + """空のsearchパラメータでも正常動作する""" + app, _ = create_test_app() + client = TestClient(app) + + response = client.get("/api/documents?search=") + assert response.status_code == 200 + data = response.json() + assert "items" in data + + def test_list_with_search_and_pagination(self): + """searchとページネーションパラメータの併用が正常動作する""" + app, _ = create_test_app() + client = TestClient(app) + + response = client.get("/api/documents?search=test&offset=0&limit=5") + assert response.status_code == 200 + data = response.json() + assert data["offset"] == 0 + assert data["limit"] == 5 + + def test_list_with_whitespace_search(self): + """空白のみのsearchパラメータは通常の一覧と同等に動作する""" + app, _ = create_test_app() + client = TestClient(app) + + response = client.get("/api/documents?search=%20%20") + assert response.status_code == 200 + data = response.json() + assert "items" in data + def create_stats_test_app(stats_tuple, type_rows): """統計テスト用アプリケーション生成"""