"""Unit tests for `jsonl_paths` — pure string transforms + light fs lookup.""" from __future__ import annotations import pytest from claude_code_api.paths import ( claude_home, encode_project_key, find_jsonl_by_session_id, projects_root, resolve_jsonl_path, session_dir, ) # ----- encode_project_key ----------------------------------------------------- @pytest.mark.parametrize( ("cwd", "expected"), [ # Observed in this repo: bare alnum + slashes + literal dashes. ( "/Users/h/projects/playgrounds/claude-code-sdk", "-Users-h-projects-playgrounds-claude-code-sdk", ), # Observed: dot-prefixed dir produces doubled dash, dash-containing # path segments survive unchanged. ( "/Users/h/.t3/worktrees/cars-system/t3code-9d8591ad", "-Users-h--t3-worktrees-cars-system-t3code-9d8591ad", ), # Trailing slash collapses to a trailing dash — claude would not # normally see this, but the encoder is deterministic. ("/Users/h/", "-Users-h-"), # Root. ("/", "-"), # Spaces, parentheses, other punct all become dashes. ("/tmp/My Project (v2)", "-tmp-My-Project--v2-"), ], ) def test_encode_known_paths(cwd: str, expected: str) -> None: assert encode_project_key(cwd) == expected def test_encode_rejects_relative() -> None: with pytest.raises(ValueError, match="absolute"): encode_project_key("relative/path") def test_encode_rejects_empty() -> None: with pytest.raises(ValueError, match="empty"): encode_project_key("") # ----- resolve_jsonl_path / session_dir -------------------------------------- def test_resolve_jsonl_path_under_fake_home(tmp_path): sid = "deadbeef-0000-4000-8000-000000000001" p = resolve_jsonl_path("/foo/bar", sid, home=tmp_path) assert p == tmp_path / ".claude" / "projects" / "-foo-bar" / f"{sid}.jsonl" def test_session_dir_matches_resolve_parent(tmp_path): sid = "deadbeef-0000-4000-8000-000000000002" assert resolve_jsonl_path("/a/b", sid, home=tmp_path).parent == session_dir( "/a/b", home=tmp_path ) def test_resolve_rejects_empty_session_id(tmp_path): with pytest.raises(ValueError, match="session_id"): resolve_jsonl_path("/foo", "", home=tmp_path) def test_claude_home_and_projects_root_honor_override(tmp_path): assert claude_home(tmp_path) == tmp_path / ".claude" assert projects_root(tmp_path) == tmp_path / ".claude" / "projects" # ----- find_jsonl_by_session_id --------------------------------------------- def test_find_returns_none_when_root_missing(tmp_path): # No `.claude/projects` under tmp_path. assert find_jsonl_by_session_id("nope", home=tmp_path) is None def test_find_locates_existing_session(tmp_path): sid = "abcdef00-1111-4000-8000-000000000000" p = resolve_jsonl_path("/some/cwd", sid, home=tmp_path) p.parent.mkdir(parents=True) p.write_text("{}\n") found = find_jsonl_by_session_id(sid, home=tmp_path) assert found == p def test_find_rejects_empty_session_id(tmp_path): with pytest.raises(ValueError, match="session_id"): find_jsonl_by_session_id("", home=tmp_path)