"""Path B per-second: pulling original FITs from the API instead of a website export. `download_fit` / `backfill_fits` are mocked at the `garth.download` boundary (network-dependent, upstream-deprecated — see ROADMAP test conventions). The FIT extractor is pure and tested directly. """ from __future__ import annotations import io import zipfile import pytest from openrun.ingest import garmin_api as g # A FIT header carries the literal b".FIT" at bytes 8..12; payload after is opaque here. FIT_BYTES = b"\x0e\x10\x00\x00\x20\x00\x00\x00.FITdata-goes-here" def _zip(*members: tuple[str, bytes]) -> bytes: buf = io.BytesIO() with zipfile.ZipFile(buf, "w") as zf: for name, data in members: zf.writestr(name, data) return buf.getvalue() # --- _extract_fit_bytes ---------------------------------------------------- def test_extract_from_zip(): assert g._extract_fit_bytes(_zip(("9.fit", FIT_BYTES))) == FIT_BYTES def test_extract_from_zip_extensionless_member_picks_largest(): blob = _zip(("small", b"x"), ("big", FIT_BYTES)) assert g._extract_fit_bytes(blob) == FIT_BYTES def test_extract_from_bare_fit(): assert g._extract_fit_bytes(FIT_BYTES) == FIT_BYTES @pytest.mark.parametrize("blob", [None, b"", b"not a fit at all"]) def test_extract_rejects_non_fit(blob): assert g._extract_fit_bytes(blob) is None # --- download_fit ---------------------------------------------------------- def _seed_activity(conn, aid: int, atype: str = "running") -> None: conn.execute( "INSERT INTO activities (activity_id, activity_type, start_time_gmt, raw, fetched_at) " "VALUES (?, ?, ?, ?, datetime('now'))", (aid, atype, "2026-05-01T10:00:00", "{}"), ) def test_download_fit_writes_and_links(tmp_conn, tmp_path, monkeypatch): _seed_activity(tmp_conn, 42) monkeypatch.setattr(g.garth, "download", lambda path: _zip(("42.fit", FIT_BYTES))) ok = g.download_fit(tmp_conn, 42, fit_dir=tmp_path) assert ok is True dest = tmp_path / "42.fit" assert dest.read_bytes() == FIT_BYTES row = tmp_conn.execute( "SELECT fit_path FROM activity_fit_files WHERE activity_id = 42" ).fetchone() assert row is not None and row[0].endswith("42.fit") def test_download_fit_skips_when_already_linked(tmp_conn, tmp_path, monkeypatch): _seed_activity(tmp_conn, 7) (tmp_path / "7.fit").write_bytes(FIT_BYTES) g.record_link(tmp_conn, 7, tmp_path / "7.fit") calls = [] monkeypatch.setattr(g.garth, "download", lambda path: calls.append(path) or b"") assert g.download_fit(tmp_conn, 7, fit_dir=tmp_path) is True assert calls == [] # no network call when on disk + linked def test_download_fit_force_redownloads(tmp_conn, tmp_path, monkeypatch): _seed_activity(tmp_conn, 7) (tmp_path / "7.fit").write_bytes(b"stale") g.record_link(tmp_conn, 7, tmp_path / "7.fit") monkeypatch.setattr(g.garth, "download", lambda path: _zip(("7.fit", FIT_BYTES))) assert g.download_fit(tmp_conn, 7, fit_dir=tmp_path, force=True) is True assert (tmp_path / "7.fit").read_bytes() == FIT_BYTES def test_download_fit_returns_false_on_empty_response(tmp_conn, tmp_path, monkeypatch): _seed_activity(tmp_conn, 99) monkeypatch.setattr(g.garth, "download", lambda path: None) assert g.download_fit(tmp_conn, 99, fit_dir=tmp_path) is False assert tmp_conn.execute( "SELECT 1 FROM activity_fit_files WHERE activity_id = 99" ).fetchone() is None # --- backfill_fits --------------------------------------------------------- def test_backfill_only_targets_unlinked(tmp_conn, tmp_path, monkeypatch): _seed_activity(tmp_conn, 1) _seed_activity(tmp_conn, 2) (tmp_path / "1.fit").write_bytes(FIT_BYTES) g.record_link(tmp_conn, 1, tmp_path / "1.fit") # 1 already has a FIT pulled = [] monkeypatch.setattr( g.garth, "download", lambda path: pulled.append(path) or _zip(("x.fit", FIT_BYTES)), ) got = g.backfill_fits(tmp_conn, fit_dir=tmp_path) assert got == 1 assert pulled == ["/download-service/files/activity/2"] def test_backfill_respects_type_filter(tmp_conn, tmp_path, monkeypatch): _seed_activity(tmp_conn, 10, atype="running") _seed_activity(tmp_conn, 11, atype="cycling") monkeypatch.setattr(g.garth, "download", lambda path: _zip(("x.fit", FIT_BYTES))) got = g.backfill_fits(tmp_conn, fit_dir=tmp_path, activity_type="running") assert got == 1 assert (tmp_path / "10.fit").exists() assert not (tmp_path / "11.fit").exists()