185 lines
6.2 KiB
Python
185 lines
6.2 KiB
Python
"""Unit tests for the TMDb normalizer (app/services/metadata/normalizer.py)
|
|||
|
|
— section 13. Uses hand-built payload fragments shaped like real TMDb
|
||
|
|
responses rather than calling the network."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from datetime import date
|
||
|
|
|
||
|
|
from app.services.metadata.normalizer import normalize_movie, normalize_person
|
||
|
|
|
||
|
|
FAKE_MOVIE = {
|
||
|
|
"id": 603,
|
||
|
|
"title": "The Matrix",
|
||
|
|
"original_title": "The Matrix",
|
||
|
|
"overview": "A computer hacker learns...",
|
||
|
|
"tagline": "Welcome to the Real World",
|
||
|
|
"status": "Released",
|
||
|
|
"original_language": "en",
|
||
|
|
"release_date": "1999-03-30",
|
||
|
|
"runtime": 136,
|
||
|
|
"budget": 63000000,
|
||
|
|
"revenue": 463517383,
|
||
|
|
"popularity": 45.5,
|
||
|
|
"vote_average": 8.2,
|
||
|
|
"vote_count": 24000,
|
||
|
|
"adult": False,
|
||
|
|
"imdb_id": "tt0133093",
|
||
|
|
"genres": [{"id": 28, "name": "Action"}, {"id": 878, "name": "Science Fiction"}],
|
||
|
|
"production_companies": [
|
||
|
|
{"id": 79, "name": "Village Roadshow Pictures", "origin_country": "US"}
|
||
|
|
],
|
||
|
|
"poster_path": "/poster.jpg",
|
||
|
|
"backdrop_path": "/backdrop.jpg",
|
||
|
|
"belongs_to_collection": {"id": 2344, "name": "The Matrix Collection"},
|
||
|
|
"credits": {
|
||
|
|
"cast": [
|
||
|
|
{
|
||
|
|
"id": 6384,
|
||
|
|
"name": "Keanu Reeves",
|
||
|
|
"character": "Neo",
|
||
|
|
"order": 0,
|
||
|
|
"profile_path": "/keanu.jpg",
|
||
|
|
"gender": 2,
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"crew": [
|
||
|
|
{
|
||
|
|
"id": 9339,
|
||
|
|
"name": "Lana Wachowski",
|
||
|
|
"department": "Directing",
|
||
|
|
"job": "Director",
|
||
|
|
"gender": 1,
|
||
|
|
}
|
||
|
|
],
|
||
|
|
},
|
||
|
|
"images": {
|
||
|
|
"posters": [
|
||
|
|
{"file_path": "/poster.jpg", "width": 2000, "height": 3000, "aspect_ratio": 0.667, "iso_639_1": "en", "vote_average": 8.1}
|
||
|
|
],
|
||
|
|
"backdrops": [],
|
||
|
|
"logos": [],
|
||
|
|
},
|
||
|
|
"videos": {
|
||
|
|
"results": [
|
||
|
|
{
|
||
|
|
"id": "abc123",
|
||
|
|
"type": "Trailer",
|
||
|
|
"site": "YouTube",
|
||
|
|
"key": "vKQi3bBA1y8",
|
||
|
|
"iso_639_1": "en",
|
||
|
|
"iso_3166_1": "US",
|
||
|
|
"official": True,
|
||
|
|
"published_at": "1999-03-01T00:00:00.000Z",
|
||
|
|
}
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"keywords": {"keywords": [{"id": 1, "name": "dystopia"}]},
|
||
|
|
"alternative_titles": {"titles": [{"title": "Matrix", "iso_3166_1": "US"}]},
|
||
|
|
"external_ids": {"imdb_id": "tt0133093"},
|
||
|
|
"recommendations": {"results": [{"id": 604}]},
|
||
|
|
}
|
||
|
|
|
||
|
|
FAKE_PERSON = {
|
||
|
|
"id": 6384,
|
||
|
|
"name": "Keanu Reeves",
|
||
|
|
"biography": "Keanu Charles Reeves is a Canadian actor.",
|
||
|
|
"birthday": "1964-09-02",
|
||
|
|
"deathday": None,
|
||
|
|
"place_of_birth": "Beirut, Lebanon",
|
||
|
|
"gender": 2,
|
||
|
|
"known_for_department": "Acting",
|
||
|
|
"popularity": 30.2,
|
||
|
|
"also_known_as": ["Keanu Charles Reeves"],
|
||
|
|
"profile_path": "/keanu.jpg",
|
||
|
|
"images": {"profiles": [{"file_path": "/keanu.jpg", "width": 1000, "height": 1500, "aspect_ratio": 0.667, "iso_639_1": None, "vote_average": 5.0}]},
|
||
|
|
"external_ids": {"imdb_id": "nm0000206"},
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def test_normalize_movie_maps_core_fields():
|
||
|
|
movie = normalize_movie(FAKE_MOVIE)
|
||
|
|
assert movie.external_id == "603"
|
||
|
|
assert movie.title == "The Matrix"
|
||
|
|
assert movie.status == "released"
|
||
|
|
assert movie.release_date == date(1999, 3, 30)
|
||
|
|
assert movie.runtime_minutes == 136
|
||
|
|
assert movie.budget == 63000000
|
||
|
|
assert movie.adult is False
|
||
|
|
|
||
|
|
|
||
|
|
def test_normalize_movie_maps_genres_and_keywords():
|
||
|
|
movie = normalize_movie(FAKE_MOVIE)
|
||
|
|
assert movie.genres == ["Action", "Science Fiction"]
|
||
|
|
assert movie.keywords == ["dystopia"]
|
||
|
|
assert movie.alternate_titles == ["Matrix"]
|
||
|
|
|
||
|
|
|
||
|
|
def test_normalize_movie_maps_cast_and_crew():
|
||
|
|
movie = normalize_movie(FAKE_MOVIE)
|
||
|
|
assert len(movie.cast) == 1
|
||
|
|
assert movie.cast[0].external_id == "6384"
|
||
|
|
assert movie.cast[0].department == "Acting"
|
||
|
|
assert movie.cast[0].character == "Neo"
|
||
|
|
assert movie.cast[0].gender == "male"
|
||
|
|
|
||
|
|
assert len(movie.crew) == 1
|
||
|
|
assert movie.crew[0].department == "Directing"
|
||
|
|
assert movie.crew[0].job == "Director"
|
||
|
|
assert movie.crew[0].gender == "female"
|
||
|
|
|
||
|
|
|
||
|
|
def test_normalize_movie_maps_artwork_and_videos():
|
||
|
|
movie = normalize_movie(FAKE_MOVIE)
|
||
|
|
poster_types = [a.artwork_type for a in movie.artwork]
|
||
|
|
assert poster_types.count("poster") >= 1
|
||
|
|
assert all(a.url.startswith("https://image.tmdb.org/t/p/original/") for a in movie.artwork)
|
||
|
|
|
||
|
|
assert len(movie.videos) == 1
|
||
|
|
assert movie.videos[0].url == "https://www.youtube.com/watch?v=vKQi3bBA1y8"
|
||
|
|
assert movie.videos[0].is_official is True
|
||
|
|
|
||
|
|
|
||
|
|
def test_normalize_movie_external_ids_never_include_tmdb_itself():
|
||
|
|
# TMDb's own id is handled separately by the ingestion pipeline via
|
||
|
|
# `normalized.external_id`, not folded into `external_ids` (section 3:
|
||
|
|
# Aurora doesn't conflate its own identity with provider identity).
|
||
|
|
movie = normalize_movie(FAKE_MOVIE)
|
||
|
|
assert "tmdb" not in movie.external_ids
|
||
|
|
assert movie.external_ids["imdb"] == "tt0133093"
|
||
|
|
|
||
|
|
|
||
|
|
def test_normalize_movie_maps_collection_and_recommendations():
|
||
|
|
movie = normalize_movie(FAKE_MOVIE)
|
||
|
|
assert movie.collection == ("2344", "The Matrix Collection")
|
||
|
|
assert movie.recommendation_external_ids == ["604"]
|
||
|
|
|
||
|
|
|
||
|
|
def test_normalize_movie_handles_missing_optional_sections():
|
||
|
|
minimal = {"id": 1, "title": "Minimal Movie"}
|
||
|
|
movie = normalize_movie(minimal)
|
||
|
|
assert movie.title == "Minimal Movie"
|
||
|
|
assert movie.genres == []
|
||
|
|
assert movie.cast == []
|
||
|
|
assert movie.artwork == []
|
||
|
|
assert movie.collection is None
|
||
|
|
|
||
|
|
|
||
|
|
def test_normalize_person_maps_core_fields():
|
||
|
|
person = normalize_person(FAKE_PERSON)
|
||
|
|
assert person.external_id == "6384"
|
||
|
|
assert person.name == "Keanu Reeves"
|
||
|
|
assert person.birthday == date(1964, 9, 2)
|
||
|
|
assert person.deathday is None
|
||
|
|
assert person.gender == "male"
|
||
|
|
assert person.external_ids["imdb"] == "nm0000206"
|
||
|
|
assert "Keanu Charles Reeves" in person.aliases
|
||
|
|
|
||
|
|
|
||
|
|
def test_normalize_person_profile_artwork_deduplicated():
|
||
|
|
person = normalize_person(FAKE_PERSON)
|
||
|
|
# profile_path duplicates an entry already in images.profiles; it must
|
||
|
|
# not be inserted twice.
|
||
|
|
paths = [a.provider_asset_id for a in person.artwork]
|
||
|
|
assert paths.count("/keanu.jpg") == 1
|