import logging import time from fastapi import FastAPI from fastapi.testclient import TestClient from _shared.access_log import ( AccessLogMiddleware, BufferLogHandler, router as logs_router, install, _BUFFER, ) def _reset_buffer(): _BUFFER.clear() def test_access_middleware_records_request(): _reset_buffer() app = FastAPI() app.add_middleware(AccessLogMiddleware) @app.get("/api/lotto/recommend") def recommend(): return {"ok": True} client = TestClient(app) client.get("/api/lotto/recommend") items = [x for x in _BUFFER if x["source"] == "access"] assert len(items) == 1 assert items[0]["method"] == "GET" assert items[0]["path"] == "/api/lotto/recommend" assert items[0]["status"] == 200 assert items[0]["ms"] >= 0 def test_access_middleware_skips_health(): _reset_buffer() app = FastAPI() app.add_middleware(AccessLogMiddleware) @app.get("/health") def health(): return {"ok": True} client = TestClient(app) client.get("/health") items = [x for x in _BUFFER if x["source"] == "access"] assert items == [] def test_access_middleware_skips_options(): _reset_buffer() app = FastAPI() app.add_middleware(AccessLogMiddleware) @app.get("/api/lotto/recommend") def recommend(): return {"ok": True} client = TestClient(app) client.options("/api/lotto/recommend") items = [x for x in _BUFFER if x["source"] == "access"] assert items == [] def test_buffer_log_handler_captures_logger_info(): _reset_buffer() root = logging.getLogger("") handler = BufferLogHandler() root.addHandler(handler) try: lg = logging.getLogger("lotto.test") lg.setLevel(logging.INFO) lg.info("뉴스 스크래핑 완료: 국내 12건") finally: root.removeHandler(handler) items = [x for x in _BUFFER if x["source"] == "log"] assert len(items) == 1 assert items[0]["message"] == "뉴스 스크래핑 완료: 국내 12건" assert items[0]["level"] == "info" assert items[0]["logger"] == "lotto.test" def test_logs_recent_endpoint_returns_recent_items(): _reset_buffer() app = FastAPI() install(app) @app.get("/api/lotto/recommend") def recommend(): return {"ok": True} client = TestClient(app) client.get("/api/lotto/recommend") client.get("/api/lotto/recommend") client.get("/health") # 제외되어야 함 resp = client.get("/logs/recent") assert resp.status_code == 200 logs = resp.json()["logs"] access_items = [x for x in logs if x["source"] == "access"] assert len(access_items) == 2 def test_logs_recent_with_since_filter(): _reset_buffer() app = FastAPI() install(app) @app.get("/api/lotto/recommend") def recommend(): return {"ok": True} client = TestClient(app) client.get("/api/lotto/recommend") time.sleep(0.01) cursor_resp = client.get("/logs/recent") cursor_ts = cursor_resp.json()["logs"][-1]["ts"] client.get("/api/lotto/recommend") resp = client.get(f"/logs/recent?since={cursor_ts}") items = [x for x in resp.json()["logs"] if x["source"] == "access"] assert len(items) == 1