agenda/tests/test_add_new_conference.py

160 lines
4.8 KiB
Python

"""Tests for agenda.add_new_conference."""
from datetime import date, datetime
import typing
import lxml.html # type: ignore[import-untyped]
import pytest
import yaml
from agenda import add_new_conference
def test_parse_osm_url_mlat_mlon() -> None:
"""OpenStreetMap URLs with mlat/mlon should parse."""
result = add_new_conference.parse_osm_url(
"https://www.openstreetmap.org/?mlat=51.5&mlon=-0.12"
)
assert result == (51.5, -0.12)
def test_extract_google_maps_latlon_at_pattern() -> None:
"""Google Maps @lat,lon URLs should parse."""
result = add_new_conference.extract_google_maps_latlon(
"https://www.google.com/maps/place/Venue/@51.5242464,-0.0997024,17z/"
)
assert result == (51.5242464, -0.0997024)
def test_insert_sorted_allows_same_url_different_year_without_year_component() -> None:
"""The same non-year-specific URL can be reused for a different year."""
conferences: list[dict[str, typing.Any]] = [
{
"name": "OldConf",
"start": date(2025, 6, 1),
"url": "https://example.com/conf",
}
]
new_conf: dict[str, typing.Any] = {
"name": "NewConf",
"start": date(2026, 6, 1),
"url": "https://example.com/conf",
}
updated = add_new_conference.insert_sorted(conferences, new_conf)
assert len(updated) == 2
assert updated[1]["name"] == "NewConf"
def test_validate_country_normalises_name() -> None:
"""Country names should be normalised to alpha-2 codes."""
conf: dict[str, typing.Any] = {"country": "United Kingdom"}
add_new_conference.validate_country(conf)
assert conf["country"] == "gb"
def test_normalise_end_field_defaults_single_day_date() -> None:
"""Non-Geomob conferences should default end to the start date."""
conf: dict[str, typing.Any] = {
"name": "PyCon",
"start": date(2026, 4, 10),
}
add_new_conference.normalise_end_field(conf, "plain text")
assert conf["end"] == date(2026, 4, 10)
def test_normalise_end_field_sets_geomob_end_time() -> None:
"""Geomob conferences should default to a 22:00 end time."""
conf: dict[str, typing.Any] = {
"name": "Geomob London",
"start": date(2026, 1, 28),
"url": "https://thegeomob.com/post/jan-28th-2026-geomoblon-details",
}
add_new_conference.normalise_end_field(conf, "see you there")
assert conf["end"] == datetime(2026, 1, 28, 22, 0)
def test_detect_page_coordinates_uses_first_supported_link() -> None:
"""Page coordinate detection should inspect anchor hrefs."""
root = lxml.html.fromstring(
(
"<html><body>"
'<a href="https://example.com">Example</a>'
'<a href="https://www.openstreetmap.org/?mlat=51.5&mlon=-0.12">Map</a>'
"</body></html>"
)
)
assert add_new_conference.detect_page_coordinates(root) == (51.5, -0.12)
def test_add_new_conference_updates_yaml(
tmp_path: typing.Any, monkeypatch: pytest.MonkeyPatch
) -> None:
"""The end-to-end import flow should append a generated conference."""
yaml_path = tmp_path / "conferences.yaml"
yaml_path.write_text(
yaml.dump(
[
{
"name": "ExistingConf",
"start": date(2026, 4, 1),
"end": date(2026, 4, 2),
"url": "https://example.com/existing",
}
],
sort_keys=False,
)
)
root = lxml.html.fromstring(
(
"<html><body>"
'<a href="https://www.openstreetmap.org/?mlat=40.0&mlon=-74.0">Map</a>'
"</body></html>"
)
)
monkeypatch.setattr(add_new_conference, "fetch_webpage", lambda url: root)
monkeypatch.setattr(
add_new_conference,
"webpage_to_text",
lambda parsed: "Conference details",
)
monkeypatch.setattr(
add_new_conference,
"get_from_open_ai",
lambda prompt: {
"yaml": yaml.dump(
{
"name": "NewConf",
"topic": "Tech",
"location": "New York",
"country": "United States",
"start": date(2026, 5, 3),
"url": "https://example.com/newconf",
},
sort_keys=False,
)
},
)
added = add_new_conference.add_new_conference(
"https://example.com/newconf", str(yaml_path)
)
assert added is True
written = yaml.safe_load(yaml_path.read_text())
assert len(written) == 2
assert written[1]["name"] == "NewConf"
assert written[1]["country"] == "us"
assert written[1]["end"] == date(2026, 5, 3)
assert written[1]["latitude"] == 40.0
assert written[1]["longitude"] == -74.0