여러 줄 주석이 설명보다 경위(예전·실측·지적)를 적고 있어 읽는 사람이 결론을 찾기 어려웠다. - ts·tsx·js·mjs·css·py 478개: 여러 줄 주석은 첫 문장 한 줄로, 과거형·날짜 문장은 삭제 - 주석 위치는 TypeScript 파서·파이썬 tokenize/ast 로 찾는다 — 문자열 안의 # · /* 는 건드리지 않는다 - eslint·ts·noqa·type: ignore 같은 지시 주석은 그대로 둔다 파이썬 275개 정리 전후 AST 동일, TS 298개 주석 뺀 토큰 동일(빈 JSX 주석 10곳만 차이). site·frontend·admin tsc, site vitest 105 passed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
70 lines
3.1 KiB
Python
70 lines
3.1 KiB
Python
"""캔버스 가이드가 일정을 함께 내려보내는가."""
|
|
import uuid
|
|
|
|
from sqlalchemy import text
|
|
|
|
from common.enums import PlaceCategory, SourceType
|
|
|
|
|
|
async def _seed_place(db_engine, owner_id, name="스테이,머뭄") -> str:
|
|
pid = uuid.uuid4()
|
|
async with db_engine.begin() as conn:
|
|
await conn.execute(
|
|
text("INSERT INTO places (place_id, owner_user_id, name, category, road_address, "
|
|
"region_code, latitude, longitude, status) "
|
|
"VALUES (:p, :o, :n, :c, :r, :rc, :lat, :lng, 1)"),
|
|
{"p": pid, "o": uuid.UUID(owner_id), "n": name, "c": PlaceCategory.LODGING.value,
|
|
"r": "전북특별자치도 군산시 절골길 18", "rc": "52군산시",
|
|
"lat": 35.98642, "lng": 126.70612},
|
|
)
|
|
return str(pid)
|
|
|
|
|
|
async def _seed_itinerary(db_engine, place_id, duration="1박 2일", course="원도심 코스"):
|
|
body = [{
|
|
"name": course, "duration": duration, "audience": "처음 온 손님", "why": "이유.",
|
|
"days": [{"label": "첫째 날", "startTime": "14:00",
|
|
"stops": [{"name": "군산근대역사박물관", "minutes": 90, "moveMinutes": 15,
|
|
"searchQuery": "군산근대역사박물관",
|
|
"latitude": 35.9985, "longitude": 126.7107}]}],
|
|
"source": {"name": "군산문화관광", "url": "https://www.gunsan.go.kr/tour/"},
|
|
}]
|
|
import json
|
|
async with db_engine.begin() as conn:
|
|
await conn.execute(
|
|
text("INSERT INTO place_itineraries (place_itinerary_id, place_id, duration, body, "
|
|
"generated_by, model, generated_at) "
|
|
"VALUES (:i, :p, :d, CAST(:b AS jsonb), :g, :m, now())"),
|
|
{"i": uuid.uuid4(), "p": uuid.UUID(place_id), "d": duration,
|
|
"b": json.dumps(body, ensure_ascii=False),
|
|
"g": SourceType.LLM.value, "m": "perplexity:sonar"},
|
|
)
|
|
|
|
|
|
async def test_guide_returns_stored_itineraries(client, db_engine, owner_id, monkeypatch):
|
|
"""검증: 저장된 일정이 있는 업장의 캔버스 가이드."""
|
|
# 생성·수집은 이 테스트의 관심이 아니다.
|
|
monkeypatch.setattr("services.llm.perplexity.is_configured", lambda: False)
|
|
|
|
pid = await _seed_place(db_engine, owner_id)
|
|
await _seed_itinerary(db_engine, pid)
|
|
|
|
body = (await client.get("/v1/local/guide", params={"place_id": pid})).json()
|
|
|
|
assert body["result"]["success"] is True
|
|
assert [i["name"] for i in body["itineraries"]] == ["원도심 코스"]
|
|
assert body["itineraries"][0]["duration"] == "1박 2일"
|
|
assert body["itineraries"][0]["days"][0]["stops"][0]["name"] == "군산근대역사박물관"
|
|
|
|
|
|
async def test_guide_without_itineraries_returns_empty_list(client, db_engine, owner_id, monkeypatch):
|
|
"""검증: 아직 생성되지 않은 업장."""
|
|
monkeypatch.setattr("services.llm.perplexity.is_configured", lambda: False)
|
|
|
|
pid = await _seed_place(db_engine, owner_id)
|
|
|
|
body = (await client.get("/v1/local/guide", params={"place_id": pid})).json()
|
|
|
|
assert body["result"]["success"] is True
|
|
assert body.get("itineraries", []) == []
|