"""Unit tests for jobs.py template rendering and safety.""" from media_library_viewer_api.jobs import JOB_TEMPLATES, JobTemplate class TestJobTemplate: def test_render_basic(self): template = JobTemplate( name="Test", description="A test job", command_template="echo {path}", ) result = template.render({"path": "/media/file.mkv"}) assert result == "echo /media/file.mkv" def test_render_quotes_spaces(self): template = JobTemplate( name="Test", description="A test job", command_template="du -sh {path}", ) result = template.render({"path": "/media/My Movie (2024)/file.mkv"}) # shlex.quote wraps in single quotes assert "'" in result or "\\" in result assert "My Movie (2024)" in result def test_render_quotes_special_chars(self): template = JobTemplate( name="Test", description="A test job", command_template="stat {path}", ) result = template.render({"path": "/media/file;rm -rf /"}) # Injection attempt should be safely quoted assert "rm -rf" in result # it's there but quoted assert result.startswith("stat ") # Should not be executable as separate command assert ";" not in result or "'" in result class TestBuiltinTemplates: def test_all_templates_exist(self): assert "disk_usage" in JOB_TEMPLATES assert "ffprobe" in JOB_TEMPLATES assert "dry_run_find_empty_dirs" in JOB_TEMPLATES def test_all_templates_renderable(self): for key, template in JOB_TEMPLATES.items(): result = template.render({"path": "/test/path"}) assert "/test/path" in result or "'/test/path'" in result def test_no_destructive_in_phase1(self): for key, template in JOB_TEMPLATES.items(): assert template.destructive is False, f"Template {key} is marked destructive"