/
/
/
1"""Tests for the translatable browse/recommendation label check."""
2
3import ast
4
5from scripts.check_translatable_labels import (
6 PROVIDERS_PATH,
7 _is_hardcoded_label,
8 _is_shipped_provider_file,
9 _resolve_python_files,
10 find_violations,
11)
12
13
14def _first_call(source: str) -> ast.Call:
15 """Return the first ``ast.Call`` node in a source snippet."""
16 return next(node for node in ast.walk(ast.parse(source)) if isinstance(node, ast.Call))
17
18
19def test_flags_literal_name_without_translation_key() -> None:
20 """A folder built with a literal ``name`` and no ``translation_key`` is flagged."""
21 assert _is_hardcoded_label(_first_call('BrowseFolder(item_id="x", name="Top Charts")'))
22 assert _is_hardcoded_label(_first_call('RecommendationFolder(name="For You")'))
23
24
25def test_allows_literal_name_with_translation_key() -> None:
26 """A literal name paired with a ``translation_key`` is acceptable."""
27 call = _first_call('BrowseFolder(name="Top Charts", translation_key="top_charts")')
28 assert not _is_hardcoded_label(call)
29
30
31def test_ignores_dynamic_names() -> None:
32 """A name built from data (variable, attribute, f-string) is real content, not a label."""
33 assert not _is_hardcoded_label(_first_call("BrowseFolder(name=artist.name)"))
34 assert not _is_hardcoded_label(_first_call("BrowseFolder(name=folder_title)"))
35 assert not _is_hardcoded_label(_first_call('BrowseFolder(name=f"Radio: {title}")'))
36
37
38def test_ignores_other_constructors() -> None:
39 """Constructors that are not browse/recommendation folders are not checked here."""
40 assert not _is_hardcoded_label(_first_call('Album(name="Greatest Hits")'))
41
42
43def test_real_tree_is_clean() -> None:
44 """No shipped provider hardcodes a browse/recommendation folder label."""
45 assert find_violations() == []
46
47
48def test_is_shipped_provider_file_skips_templates() -> None:
49 """Template/test providers and out-of-tree paths are not shipped provider files."""
50 assert _is_shipped_provider_file(PROVIDERS_PATH / "spotify" / "__init__.py")
51 assert not _is_shipped_provider_file(PROVIDERS_PATH / "_demo_music_provider" / "__init__.py")
52 assert not _is_shipped_provider_file(PROVIDERS_PATH / "test" / "__init__.py")
53
54
55def test_resolve_python_files_skips_template_folder() -> None:
56 """Resolving a template provider folder yields no files to scan."""
57 assert _resolve_python_files([str(PROVIDERS_PATH / "_demo_music_provider")]) == []
58
59
60def test_explicit_empty_paths_scans_nothing() -> None:
61 """An explicit empty path list scans nothing (no fallback to a full scan)."""
62 assert find_violations([]) == []
63