"""Tests for file type detection.""" from __future__ import annotations from pathlib import Path import pytest from rp.detect import EXTENSION_MAP, _FILENAME_MAP, detect_type class TestExplicitType: """Priority 1: explicit_type always wins.""" def test_explicit_overrides_everything(self) -> None: assert detect_type(path="foo.py", content="...", explicit_type="json") == "json" def test_explicit_with_none_path_and_content(self) -> None: assert detect_type(explicit_type="rust") == "rust" def test_explicit_empty_string(self) -> None: # Empty string is falsy but not None, so it should still win. assert detect_type(explicit_type="") == "" class TestFilenameMap: """Priority 2: special filenames like Dockerfile.""" def test_dockerfile(self) -> None: assert detect_type(path="Dockerfile") == "docker" def test_dockerfile_with_path(self) -> None: assert detect_type(path="/some/dir/Dockerfile") == "docker" def test_makefile(self) -> None: assert detect_type(path="Makefile") == "make" def test_makefile_with_path(self) -> None: assert detect_type(path="src/Makefile") == "make" class TestExtensionMap: """Priority 3: file extension lookup.""" def test_python(self) -> None: assert detect_type(path="script.py") == "python" def test_python_case_insensitive(self) -> None: assert detect_type(path="SCRIPT.PY") == "python" def test_json_extension(self) -> None: assert detect_type(path="data.json") == "json" def test_markdown(self) -> None: assert detect_type(path="README.md") == "markdown" def test_rust(self) -> None: assert detect_type(path="main.rs") == "rust" def test_go(self) -> None: assert detect_type(path="main.go") == "go" def test_unknown_extension(self) -> None: assert detect_type(path="file.xyz") == "text" def test_no_extension(self) -> None: assert detect_type(path="Makefile") == "make" def test_double_extension(self) -> None: assert detect_type(path="archive.tar.gz") == "text" def test_hidden_file(self) -> None: assert detect_type(path=".bashrc") == "text" @pytest.mark.parametrize( ("suffix", "expected"), sorted(EXTENSION_MAP.items()), ) def test_all_known_extensions_detect(self, suffix: str, expected: str) -> None: assert detect_type(path=f"example{suffix}") == expected class TestContentJsonDetection: """Priority 4: detect JSON from content when path gives no clue.""" def test_json_object(self, sample_json: str) -> None: assert detect_type(content=sample_json) == "json" def test_json_array(self) -> None: assert detect_type(content="[1, 2, 3]") == "json" def test_json_with_whitespace(self) -> None: assert detect_type(content=' \n {"a": 1} \n ') == "json" def test_invalid_json_braces(self) -> None: assert detect_type(content="{invalid json}") == "text" def test_non_json_content(self) -> None: assert detect_type(content="hello world") == "text" def test_empty_content(self) -> None: assert detect_type(content="") == "text" def test_content_with_valid_path_takes_priority(self) -> None: assert detect_type(path="script.py", content='{"a": 1}') == "python" class TestFallback: """Priority 5: fallback to 'text'.""" def test_no_args(self) -> None: assert detect_type() == "text" def test_none_everything(self) -> None: assert detect_type(path=None, content=None, explicit_type=None) == "text" class TestExtensionMapCompleteness: """Verify EXTENSION_MAP entries are valid.""" def test_all_extensions_are_strings(self) -> None: for ext, lexer in EXTENSION_MAP.items(): assert isinstance(ext, str), f"Key {ext!r} is not str" assert isinstance(lexer, str), f"Value for {ext!r} is not str" def test_all_extensions_start_with_dot(self) -> None: for ext in EXTENSION_MAP: assert ext.startswith("."), f"Extension {ext!r} doesn't start with '.'" def test_all_filenames_in_filename_map(self) -> None: for name in _FILENAME_MAP: assert isinstance(name, str) def test_filename_map_matches_path_name_lookup(self, tmp_file) -> None: for name, expected in _FILENAME_MAP.items(): path = tmp_file("content", name=name) assert detect_type(path=str(path)) == expected def test_path_stringified_from_pathlib(tmp_file) -> None: path = tmp_file('print("hi")\n', suffix=".py") assert detect_type(path=str(Path(path))) == "python"