"""Tests for broadcast.py: project fingerprinting + discovery. Plain python3 script. The pure-ish helpers are driven against tmp project trees; discovery is exercised with SEARCH_ROOTS monkeypatched to the tree, and the cwd-based helpers with monkeypatch.chdir. """ from __future__ import annotations import importlib.util from pathlib import Path import pytest SCRIPT = Path(__file__).resolve().parents[1] / "broadcast.py" @pytest.fixture(scope="module") def bcast(): spec = importlib.util.spec_from_file_location("broadcast", SCRIPT) assert spec and spec.loader module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module def _make_project(root: Path, name: str, with_inbox: bool = True, with_protocols: bool = True) -> Path: p = root / name (p / ".ai").mkdir(parents=True) if with_protocols: (p / ".ai" / "protocols.org").write_text("#+TITLE: protocols\n") if with_inbox: (p / "inbox").mkdir() return p # --- is_broadcastable --- def test_is_broadcastable_true_with_protocols_and_inbox(bcast, tmp_path): assert bcast.is_broadcastable(_make_project(tmp_path, "proj")) is True def test_is_broadcastable_false_without_inbox(bcast, tmp_path): p = _make_project(tmp_path, "proj", with_inbox=False) assert bcast.is_broadcastable(p) is False def test_is_broadcastable_false_without_protocols(bcast, tmp_path): p = _make_project(tmp_path, "proj", with_protocols=False) assert bcast.is_broadcastable(p) is False def test_is_broadcastable_false_on_plain_dir(bcast, tmp_path): assert bcast.is_broadcastable(tmp_path) is False # --- discover (SEARCH_ROOTS monkeypatched onto the tmp tree) --- def test_discover_finds_broadcastable_subprojects(bcast, tmp_path, monkeypatch): root = tmp_path / "code" root.mkdir() _make_project(root, "alpha") _make_project(root, "beta") _make_project(root, "no-inbox", with_inbox=False) # not broadcastable monkeypatch.setattr(bcast, "SEARCH_ROOTS", [root]) assert [p.name for p in bcast.discover()] == ["alpha", "beta"] def test_discover_handles_root_that_is_itself_a_project(bcast, tmp_path, monkeypatch): root = _make_project(tmp_path, ".emacs.d") monkeypatch.setattr(bcast, "SEARCH_ROOTS", [root]) assert [p.name for p in bcast.discover()] == [".emacs.d"] def test_discover_dedups_by_basename_across_roots(bcast, tmp_path, monkeypatch): root1 = tmp_path / "code" root1.mkdir() root2 = tmp_path / "projects" root2.mkdir() _make_project(root1, "dup") _make_project(root2, "dup") monkeypatch.setattr(bcast, "SEARCH_ROOTS", [root1, root2]) assert [p.name for p in bcast.discover()] == ["dup"] def test_discover_skips_missing_roots(bcast, tmp_path, monkeypatch): monkeypatch.setattr(bcast, "SEARCH_ROOTS", [tmp_path / "does-not-exist"]) assert bcast.discover() == [] # --- sender_project / inbox_send_path (cwd-based) --- def test_sender_project_returns_basename_inside_an_ai_project(bcast, tmp_path, monkeypatch): p = _make_project(tmp_path, "myproj") monkeypatch.chdir(p) assert bcast.sender_project() == "myproj" def test_sender_project_none_outside_an_ai_project(bcast, tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) assert bcast.sender_project() is None def test_inbox_send_path_found_in_project(bcast, tmp_path, monkeypatch): p = _make_project(tmp_path, "myproj") (p / ".ai" / "scripts").mkdir() helper = p / ".ai" / "scripts" / "inbox-send.py" helper.write_text("# stub\n") monkeypatch.chdir(p) assert bcast.inbox_send_path() == helper def test_inbox_send_path_raises_when_missing(bcast, tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) with pytest.raises(SystemExit): bcast.inbox_send_path()