import os import sys import pytest from app.assets.services.file_utils import is_visible, list_files_recursively class TestIsVisible: def test_visible_file(self): assert is_visible("file.txt") is True def test_hidden_file(self): assert is_visible(".hidden") is False def test_hidden_directory(self): assert is_visible(".git") is False def test_visible_directory(self): assert is_visible("src") is True def test_dotdot_is_hidden(self): assert is_visible("..") is False def test_dot_is_hidden(self): assert is_visible(".") is False class TestListFilesRecursively: def test_skips_hidden_files(self, tmp_path): (tmp_path / "visible.txt").write_text("a") (tmp_path / ".hidden").write_text("b") result = list_files_recursively(str(tmp_path)) assert len(result) == 1 assert result[0].endswith("visible.txt") def test_skips_hidden_directories(self, tmp_path): hidden_dir = tmp_path / ".hidden_dir" hidden_dir.mkdir() (hidden_dir / "file.txt").write_text("a") visible_dir = tmp_path / "visible_dir" visible_dir.mkdir() (visible_dir / "file.txt").write_text("b") result = list_files_recursively(str(tmp_path)) assert len(result) == 1 assert "visible_dir" in result[0] assert ".hidden_dir" not in result[0] def test_empty_directory(self, tmp_path): result = list_files_recursively(str(tmp_path)) assert result == [] def test_nonexistent_directory(self, tmp_path): result = list_files_recursively(str(tmp_path / "nonexistent")) assert result == [] @pytest.mark.skipif(sys.platform == "win32", reason="symlinks need privileges on Windows") def test_follows_symlinked_directories(self, tmp_path): target = tmp_path / "real_dir" target.mkdir() (target / "model.safetensors").write_text("data") root = tmp_path / "root" root.mkdir() (root / "link").symlink_to(target) result = list_files_recursively(str(root)) assert len(result) == 1 assert result[0].endswith("model.safetensors") assert "link" in result[0] @pytest.mark.skipif(sys.platform == "win32", reason="symlinks need privileges on Windows") def test_follows_symlinked_files(self, tmp_path): real_file = tmp_path / "real.txt" real_file.write_text("content") root = tmp_path / "root" root.mkdir() (root / "link.txt").symlink_to(real_file) result = list_files_recursively(str(root)) assert len(result) == 1 assert result[0].endswith("link.txt") @pytest.mark.skipif(sys.platform == "win32", reason="symlinks need privileges on Windows") def test_circular_symlinks_do_not_loop(self, tmp_path): dir_a = tmp_path / "a" dir_a.mkdir() (dir_a / "file.txt").write_text("a") # a/b -> a (circular) (dir_a / "b").symlink_to(dir_a) result = list_files_recursively(str(dir_a)) assert len(result) == 1 assert result[0].endswith("file.txt") @pytest.mark.skipif(sys.platform == "win32", reason="symlinks need privileges on Windows") def test_mutual_circular_symlinks(self, tmp_path): dir_a = tmp_path / "a" dir_b = tmp_path / "b" dir_a.mkdir() dir_b.mkdir() (dir_a / "file_a.txt").write_text("a") (dir_b / "file_b.txt").write_text("b") # a/link_b -> b and b/link_a -> a (dir_a / "link_b").symlink_to(dir_b) (dir_b / "link_a").symlink_to(dir_a) result = list_files_recursively(str(dir_a)) basenames = sorted(os.path.basename(p) for p in result) assert "file_a.txt" in basenames assert "file_b.txt" in basenames