Task 4.7: Update template helpers to use key identifier
- Add series context helpers: prepare_series_context, get_series_by_key, filter_series_by_missing_episodes - Update module docstring with identifier convention documentation - Add unit tests for new series context helper functions - Update infrastructure.md with template helpers documentation - Mark Phase 4 (API Layer) as complete
This commit is contained in:
@@ -1,15 +1,19 @@
|
||||
"""
|
||||
Tests for template helper utilities.
|
||||
|
||||
This module tests the template helper functions.
|
||||
This module tests the template helper functions including series context
|
||||
preparation using `key` as the primary identifier.
|
||||
"""
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from src.server.utils.template_helpers import (
|
||||
filter_series_by_missing_episodes,
|
||||
get_base_context,
|
||||
get_series_by_key,
|
||||
list_available_templates,
|
||||
prepare_series_context,
|
||||
validate_template_exists,
|
||||
)
|
||||
|
||||
@@ -84,3 +88,156 @@ class TestTemplateHelpers:
|
||||
"""Test that all required templates exist."""
|
||||
assert validate_template_exists(template_name), \
|
||||
f"Required template {template_name} does not exist"
|
||||
|
||||
|
||||
class TestSeriesContextHelpers:
|
||||
"""Test series context helper functions.
|
||||
|
||||
These tests verify that series helpers use `key` as the primary
|
||||
identifier following the project's identifier convention.
|
||||
"""
|
||||
|
||||
def test_prepare_series_context_uses_key(self):
|
||||
"""Test that prepare_series_context uses key as primary identifier."""
|
||||
series_data = [
|
||||
{
|
||||
"key": "attack-on-titan",
|
||||
"name": "Attack on Titan",
|
||||
"folder": "Attack on Titan (2013)",
|
||||
},
|
||||
{
|
||||
"key": "one-piece",
|
||||
"name": "One Piece",
|
||||
"folder": "One Piece (1999)",
|
||||
},
|
||||
]
|
||||
prepared = prepare_series_context(series_data)
|
||||
|
||||
assert len(prepared) == 2
|
||||
# Verify key is present and used
|
||||
assert prepared[0]["key"] in ("attack-on-titan", "one-piece")
|
||||
assert all("key" in item for item in prepared)
|
||||
assert all("folder" in item for item in prepared)
|
||||
|
||||
def test_prepare_series_context_sorts_by_name(self):
|
||||
"""Test that series are sorted by name by default."""
|
||||
series_data = [
|
||||
{"key": "z-series", "name": "Zebra Anime", "folder": "z"},
|
||||
{"key": "a-series", "name": "Alpha Anime", "folder": "a"},
|
||||
]
|
||||
prepared = prepare_series_context(series_data, sort_by="name")
|
||||
|
||||
assert prepared[0]["name"] == "Alpha Anime"
|
||||
assert prepared[1]["name"] == "Zebra Anime"
|
||||
|
||||
def test_prepare_series_context_sorts_by_key(self):
|
||||
"""Test that series can be sorted by key."""
|
||||
series_data = [
|
||||
{"key": "z-series", "name": "Zebra", "folder": "z"},
|
||||
{"key": "a-series", "name": "Alpha", "folder": "a"},
|
||||
]
|
||||
prepared = prepare_series_context(series_data, sort_by="key")
|
||||
|
||||
assert prepared[0]["key"] == "a-series"
|
||||
assert prepared[1]["key"] == "z-series"
|
||||
|
||||
def test_prepare_series_context_empty_list(self):
|
||||
"""Test prepare_series_context with empty list."""
|
||||
prepared = prepare_series_context([])
|
||||
assert prepared == []
|
||||
|
||||
def test_prepare_series_context_skips_missing_key(self):
|
||||
"""Test that items without key are skipped with warning."""
|
||||
series_data = [
|
||||
{"key": "valid-series", "name": "Valid", "folder": "valid"},
|
||||
{"name": "No Key", "folder": "nokey"}, # Missing key
|
||||
]
|
||||
prepared = prepare_series_context(series_data)
|
||||
|
||||
assert len(prepared) == 1
|
||||
assert prepared[0]["key"] == "valid-series"
|
||||
|
||||
def test_prepare_series_context_preserves_extra_fields(self):
|
||||
"""Test that extra fields are preserved."""
|
||||
series_data = [
|
||||
{
|
||||
"key": "test",
|
||||
"name": "Test",
|
||||
"folder": "test",
|
||||
"missing_episodes": {"1": [1, 2]},
|
||||
"site": "aniworld.to",
|
||||
}
|
||||
]
|
||||
prepared = prepare_series_context(series_data)
|
||||
|
||||
assert prepared[0]["missing_episodes"] == {"1": [1, 2]}
|
||||
assert prepared[0]["site"] == "aniworld.to"
|
||||
|
||||
def test_get_series_by_key_found(self):
|
||||
"""Test finding a series by key."""
|
||||
series_data = [
|
||||
{"key": "attack-on-titan", "name": "Attack on Titan"},
|
||||
{"key": "one-piece", "name": "One Piece"},
|
||||
]
|
||||
result = get_series_by_key(series_data, "attack-on-titan")
|
||||
|
||||
assert result is not None
|
||||
assert result["name"] == "Attack on Titan"
|
||||
|
||||
def test_get_series_by_key_not_found(self):
|
||||
"""Test that None is returned when key not found."""
|
||||
series_data = [
|
||||
{"key": "attack-on-titan", "name": "Attack on Titan"},
|
||||
]
|
||||
result = get_series_by_key(series_data, "non-existent")
|
||||
|
||||
assert result is None
|
||||
|
||||
def test_get_series_by_key_empty_list(self):
|
||||
"""Test get_series_by_key with empty list."""
|
||||
result = get_series_by_key([], "any-key")
|
||||
assert result is None
|
||||
|
||||
def test_filter_series_by_missing_episodes(self):
|
||||
"""Test filtering series with missing episodes."""
|
||||
series_data = [
|
||||
{
|
||||
"key": "has-missing",
|
||||
"name": "Has Missing",
|
||||
"missing_episodes": {"1": [1, 2, 3]},
|
||||
},
|
||||
{
|
||||
"key": "no-missing",
|
||||
"name": "No Missing",
|
||||
"missing_episodes": {},
|
||||
},
|
||||
{
|
||||
"key": "empty-seasons",
|
||||
"name": "Empty Seasons",
|
||||
"missing_episodes": {"1": [], "2": []},
|
||||
},
|
||||
]
|
||||
filtered = filter_series_by_missing_episodes(series_data)
|
||||
|
||||
assert len(filtered) == 1
|
||||
assert filtered[0]["key"] == "has-missing"
|
||||
|
||||
def test_filter_series_by_missing_episodes_empty(self):
|
||||
"""Test filter with empty list."""
|
||||
filtered = filter_series_by_missing_episodes([])
|
||||
assert filtered == []
|
||||
|
||||
def test_filter_preserves_key_identifier(self):
|
||||
"""Test that filter preserves key as identifier."""
|
||||
series_data = [
|
||||
{
|
||||
"key": "test-series",
|
||||
"folder": "Test Series (2020)",
|
||||
"name": "Test",
|
||||
"missing_episodes": {"1": [1]},
|
||||
}
|
||||
]
|
||||
filtered = filter_series_by_missing_episodes(series_data)
|
||||
|
||||
assert filtered[0]["key"] == "test-series"
|
||||
assert filtered[0]["folder"] == "Test Series (2020)"
|
||||
|
||||
Reference in New Issue
Block a user