"""Owner email action links over HTTP (§9.1-9.2, idempotency per §15).""" import re from datetime import UTC, datetime, timedelta from gogo.domain import BookingStatus from tests.test_proposal_lifecycle import create def extract_links(text: str) -> dict[str, str]: """Pull action URLs out of the plain-text proposal email.""" links = {} resolve = re.search(r"RIJEŠENO[^\n]*\n\s+(http\S+)", text) confirm = re.search(r"POTVRDI[^\n]*\n\s+(http\S+)", text) reject = re.search(r"ODBIJ[^\n]*\n\s+(http\S+)", text) if resolve: links["resolve"] = resolve.group(1) if confirm: links["confirm"] = confirm.group(1) if reject: links["reject"] = reject.group(1) return links async def test_resolve_link_closes_request_no_sms(session, tenant, emails, sms, gogo_client): req, _ = await create(session, tenant) await session.commit() links = extract_links(emails[0].text) resp = await gogo_client.get(links["resolve"]) assert resp.status_code == 200 assert "Označeno kao riješeno" in resp.text await session.refresh(req) assert req.status == BookingStatus.resolved_by_owner.value assert sms == [] # idempotent: second click shows friendly "already handled" page resp2 = await gogo_client.get(links["resolve"]) assert resp2.status_code == 200 assert "već obrađen" in resp2.text async def test_confirm_link_sends_sms(session, tenant, emails, sms, gogo_client): req, _ = await create(session, tenant) await session.commit() links = extract_links(emails[0].text) resp = await gogo_client.get(links["confirm"]) assert resp.status_code == 200 assert "Termin potvrđen" in resp.text await session.refresh(req) assert req.status == BookingStatus.confirmed.value assert len(sms) == 1 assert "Potvrđen termin" in sms[0][1] async def test_reject_link_shows_editable_form_then_sends( session, tenant, emails, sms, gogo_client ): req, _ = await create(session, tenant) await session.commit() links = extract_links(emails[0].text) # GET shows the form with the default template prefilled — nothing sent yet resp = await gogo_client.get(links["reject"]) assert resp.status_code == 200 assert "