"""캔버스 가이드가 일정을 함께 내려보내는가. ★ 예전에는 일부러 뺐다 — "캔버스에 그릴 자리가 아직 없다"(get_guide docstring). 자리를 만들었으므로(ItineraryTickets 의 폴백) 이제 실어 보낸다. 빼 두면 캔버스와 발행본이 다른 목록을 보이고, 그건 이 함수 자신이 경계한 상황이다. """ 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): """검증: 저장된 일정이 있는 업장의 캔버스 가이드. 기대결과: itineraries 가 실려 온다 — 캔버스가 발행본과 같은 목록을 본다.""" # 생성·수집은 이 테스트의 관심이 아니다. 유료 호출과 잡 등록을 막는다. 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): """검증: 아직 생성되지 않은 업장. 기대결과: 빈 배열 — 캔버스는 PasteHint 를 띄운다(에러가 아니다).""" 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", []) == []