aboutsummaryrefslogtreecommitdiff
path: root/claude-templates/.ai/scripts/tests/test_inbox_send.py
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-15 16:56:39 -0500
committerCraig Jennings <c@cjennings.net>2026-05-15 16:56:39 -0500
commitc1d4e3c4a42abd01bc7ef83b1d6ae036ee32ef1d (patch)
tree3e6dcc682cbf2311409e7f71d83a7d4088392068 /claude-templates/.ai/scripts/tests/test_inbox_send.py
parent2b471da4bab014a2e096f63edc7aac235fc40fdd (diff)
parent69c5e4ace81586c05dea6a9a3afd54dafa61a73b (diff)
downloadrulesets-c1d4e3c4a42abd01bc7ef83b1d6ae036ee32ef1d.tar.gz
rulesets-c1d4e3c4a42abd01bc7ef83b1d6ae036ee32ef1d.zip
Merge commit '69c5e4ace81586c05dea6a9a3afd54dafa61a73b' as 'claude-templates'
Diffstat (limited to 'claude-templates/.ai/scripts/tests/test_inbox_send.py')
-rw-r--r--claude-templates/.ai/scripts/tests/test_inbox_send.py329
1 files changed, 329 insertions, 0 deletions
diff --git a/claude-templates/.ai/scripts/tests/test_inbox_send.py b/claude-templates/.ai/scripts/tests/test_inbox_send.py
new file mode 100644
index 0000000..597a7e9
--- /dev/null
+++ b/claude-templates/.ai/scripts/tests/test_inbox_send.py
@@ -0,0 +1,329 @@
+"""Tests for inbox-send.py — universal cross-project inbox messaging tool.
+
+The script:
+- discovers .ai projects with an inbox/ subdirectory under known roots,
+- writes a text message as a dated .org file in the target's inbox/, or
+- copies a file into the target's inbox/ with a dated, source-tagged name.
+
+All discovery is roots-driven (env var INBOX_SEND_ROOTS overrides the
+defaults) so tests can sandbox everything inside tmp_path.
+"""
+
+import subprocess
+from pathlib import Path
+
+import pytest
+
+SCRIPT = Path(__file__).parent.parent / "inbox-send.py"
+
+
+@pytest.fixture
+def project_root(tmp_path):
+ """Build a fake project under tmp_path/projects/<name>/ with .ai/ + top-level inbox/."""
+ def _make(name: str, has_inbox: bool = True) -> Path:
+ proj = tmp_path / "projects" / name
+ proj.mkdir(parents=True, exist_ok=True)
+ (proj / ".ai").mkdir(exist_ok=True)
+ if has_inbox:
+ (proj / "inbox").mkdir(exist_ok=True)
+ return proj
+ return _make
+
+
+@pytest.fixture
+def run_script(tmp_path):
+ """Invoke inbox-send with sandboxed roots via INBOX_SEND_ROOTS env var."""
+ def _run(args, cwd=None, roots=None, expect_failure=False):
+ env = {}
+ # Preserve PATH and a few essentials for python3 to launch.
+ import os as _os
+ env["PATH"] = _os.environ.get("PATH", "")
+ env["HOME"] = _os.environ.get("HOME", "/tmp")
+ if roots:
+ env["INBOX_SEND_ROOTS"] = ":".join(str(r) for r in roots)
+ cmd = ["python3", str(SCRIPT)] + args
+ result = subprocess.run(
+ cmd,
+ capture_output=True,
+ text=True,
+ cwd=cwd or tmp_path,
+ env=env,
+ check=not expect_failure,
+ )
+ return result
+ return _run
+
+
+# ----------------------------------------------------------------------
+# Discovery (--list)
+# ----------------------------------------------------------------------
+
+class TestInboxSendDiscovery:
+ """Discovering available .ai projects under the configured roots."""
+
+ def test_inbox_send_list_detects_projects_with_ai_inbox(self, project_root, run_script, tmp_path):
+ """Normal: --list shows projects that have .ai/inbox/."""
+ project_root("foo")
+ project_root("bar")
+ result = run_script(["--list"], roots=[tmp_path / "projects"])
+ assert "foo" in result.stdout
+ assert "bar" in result.stdout
+
+ def test_inbox_send_list_skips_projects_without_inbox(self, project_root, run_script, tmp_path):
+ """Boundary: project with .ai/ but no inbox/ is not surfaced."""
+ project_root("withinbox", has_inbox=True)
+ project_root("noinbox", has_inbox=False)
+ result = run_script(["--list"], roots=[tmp_path / "projects"])
+ assert "withinbox" in result.stdout
+ assert "noinbox" not in result.stdout
+
+ def test_inbox_send_list_skips_current_project(self, project_root, run_script, tmp_path):
+ """Normal: --list excludes the project the user is currently in."""
+ cwd_project = project_root("current")
+ project_root("other")
+ result = run_script(["--list"], cwd=cwd_project, roots=[tmp_path / "projects"])
+ assert "other" in result.stdout
+ assert "current" not in result.stdout
+
+ def test_inbox_send_list_empty_when_no_projects(self, run_script, tmp_path):
+ """Boundary: no projects under roots → friendly informational message."""
+ (tmp_path / "projects").mkdir()
+ result = run_script(["--list"], roots=[tmp_path / "projects"])
+ assert result.returncode == 0
+ assert "No projects" in result.stdout
+
+ def test_inbox_send_list_handles_missing_root(self, run_script, tmp_path):
+ """Boundary: configured root doesn't exist → skip silently."""
+ result = run_script(["--list"], roots=[tmp_path / "does-not-exist"])
+ assert result.returncode == 0
+
+
+# ----------------------------------------------------------------------
+# Slug derivation from text and from filenames
+# ----------------------------------------------------------------------
+
+def _slug_from(inbox_files, source_name):
+ """Helper: extract the slug from a deposited file's basename."""
+ assert len(inbox_files) == 1
+ name = inbox_files[0].stem
+ marker = f"from-{source_name}-"
+ return name.split(marker, 1)[1]
+
+
+class TestInboxSendNaming:
+ """Slug derivation from --text (and override via --name)."""
+
+ def test_inbox_send_text_slug_hyphenated_lowercase(self, project_root, run_script, tmp_path):
+ """Normal: 'ATM cash reminder' → slug 'atm-cash-reminder'."""
+ project_root("target")
+ cwd = project_root("source")
+ run_script(
+ ["target", "--text", "ATM cash reminder"],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ assert _slug_from(files, "source") == "atm-cash-reminder"
+
+ def test_inbox_send_text_slug_truncated_at_word_boundary(self, project_root, run_script, tmp_path):
+ """Normal: long text truncated under 40 chars at the nearest word boundary."""
+ project_root("target")
+ cwd = project_root("source")
+ long_text = (
+ "Please review the SOFWeek prep doc and confirm the AirBnB kitchen details"
+ )
+ run_script(
+ ["target", "--text", long_text],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ slug = _slug_from(files, "source")
+ assert slug.startswith("please-review-the-sofweek")
+ assert len(slug) <= 40
+ # Truncation should land on a word boundary (last char is a letter/digit, not mid-word).
+ assert "-" not in slug[-1]
+
+ def test_inbox_send_text_slug_strips_punctuation(self, project_root, run_script, tmp_path):
+ """Normal: punctuation stripped, lowercased."""
+ project_root("target")
+ cwd = project_root("source")
+ run_script(
+ ["target", "--text", "Hey! What's the plan? See you @ 5PM."],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ slug = _slug_from(files, "source")
+ for ch in "!?'@.":
+ assert ch not in slug
+ assert slug == slug.lower()
+
+ def test_inbox_send_name_override_overrides_slug(self, project_root, run_script, tmp_path):
+ """Normal: --name wins over derived slug."""
+ project_root("target")
+ cwd = project_root("source")
+ run_script(
+ ["target", "--text", "ok", "--name", "pre-call-ack"],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ assert _slug_from(files, "source") == "pre-call-ack"
+
+
+# ----------------------------------------------------------------------
+# --text mode end-to-end
+# ----------------------------------------------------------------------
+
+class TestInboxSendText:
+ """--text mode writes a .org file with the message body."""
+
+ def test_inbox_send_text_writes_org_file_with_message(self, project_root, run_script, tmp_path):
+ """Normal: produces a .org file whose body contains the message."""
+ project_root("target")
+ cwd = project_root("source")
+ run_script(
+ ["target", "--text", "Remember the ATM run"],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ assert len(files) == 1
+ assert files[0].suffix == ".org"
+ body = files[0].read_text()
+ assert "Remember the ATM run" in body
+
+ def test_inbox_send_text_filename_includes_source_project_name(self, project_root, run_script, tmp_path):
+ """Normal: filename includes 'from-<source>-' so the target knows where it came from."""
+ project_root("target")
+ cwd = project_root("emacs")
+ run_script(
+ ["target", "--text", "hello"],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ assert "from-emacs-" in files[0].name
+
+
+# ----------------------------------------------------------------------
+# --file mode end-to-end
+# ----------------------------------------------------------------------
+
+class TestInboxSendFile:
+ """--file mode copies the source file into the target inbox."""
+
+ def test_inbox_send_file_copies_text_file(self, project_root, run_script, tmp_path):
+ """Normal: copies a text file to the target inbox, preserving content."""
+ project_root("target")
+ cwd = project_root("source")
+ src = tmp_path / "doc.org"
+ src.write_text("file content")
+ run_script(
+ ["target", "--file", str(src)],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ assert len(files) == 1
+ assert files[0].read_text() == "file content"
+
+ def test_inbox_send_file_preserves_extension(self, project_root, run_script, tmp_path):
+ """Normal: extension carried from source file."""
+ project_root("target")
+ cwd = project_root("source")
+ src = tmp_path / "image.png"
+ src.write_bytes(b"\x89PNG\r\n...")
+ run_script(
+ ["target", "--file", str(src)],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ assert files[0].suffix == ".png"
+
+ def test_inbox_send_file_slug_from_source_basename(self, project_root, run_script, tmp_path):
+ """Normal: filename slug derived from the source file's basename when --name omitted."""
+ project_root("target")
+ cwd = project_root("source")
+ src = tmp_path / "branching-strategy-notes.md"
+ src.write_text("notes")
+ run_script(
+ ["target", "--file", str(src)],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ assert "branching-strategy-notes" in files[0].name
+
+ def test_inbox_send_file_name_override(self, project_root, run_script, tmp_path):
+ """Normal: --name overrides the basename-derived slug; extension preserved."""
+ project_root("target")
+ cwd = project_root("source")
+ src = tmp_path / "random.pdf"
+ src.write_bytes(b"%PDF-1.4...")
+ run_script(
+ ["target", "--file", str(src), "--name", "branching-strategy"],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ )
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ assert "branching-strategy" in files[0].name
+ assert files[0].suffix == ".pdf"
+
+
+# ----------------------------------------------------------------------
+# Errors and refusal cases
+# ----------------------------------------------------------------------
+
+class TestInboxSendErrors:
+ """Refusal cases — surface clearly, exit non-zero, leave filesystem untouched."""
+
+ def test_inbox_send_refuses_unknown_target(self, project_root, run_script, tmp_path):
+ """Error: target project not found in discovery → refuse."""
+ cwd = project_root("source")
+ result = run_script(
+ ["nonexistent", "--text", "hi"],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ expect_failure=True,
+ )
+ assert result.returncode != 0
+
+ def test_inbox_send_refuses_no_text_and_no_file(self, project_root, run_script, tmp_path):
+ """Error: must provide one of --text / --file."""
+ project_root("target")
+ cwd = project_root("source")
+ result = run_script(
+ ["target"],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ expect_failure=True,
+ )
+ assert result.returncode != 0
+
+ def test_inbox_send_refuses_both_text_and_file(self, project_root, run_script, tmp_path):
+ """Error: --text and --file are mutually exclusive."""
+ project_root("target")
+ cwd = project_root("source")
+ src = tmp_path / "doc.org"
+ src.write_text("x")
+ result = run_script(
+ ["target", "--text", "hi", "--file", str(src)],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ expect_failure=True,
+ )
+ assert result.returncode != 0
+
+ def test_inbox_send_refuses_missing_source_file(self, project_root, run_script, tmp_path):
+ """Error: --file path doesn't exist → refuse."""
+ project_root("target")
+ cwd = project_root("source")
+ result = run_script(
+ ["target", "--file", str(tmp_path / "definitely-missing.org")],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ expect_failure=True,
+ )
+ assert result.returncode != 0
+
+ def test_inbox_send_refuses_empty_text(self, project_root, run_script, tmp_path):
+ """Error: empty --text refused; nothing written to target inbox."""
+ project_root("target")
+ cwd = project_root("source")
+ result = run_script(
+ ["target", "--text", " "],
+ cwd=cwd, roots=[tmp_path / "projects"],
+ expect_failure=True,
+ )
+ assert result.returncode != 0
+ files = list((tmp_path / "projects" / "target" / "inbox").iterdir())
+ assert files == []