Título com Vídeo
Texto curto da matéria.
""" Testes unitários do classificador de mídia e gate estrutural DOM. Valida schema de 2 campos, navegação estrutural na DOM (Zero-Regex) e montagem do payload compacto. """ from __future__ import annotations import json import sys import urllib.error from pathlib import Path import pytest from bs4 import BeautifulSoup # Adiciona o diretório raiz ao sys.path para import dos scripts sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent)) from scripts.extract_article_contents import ( MEDIA_CLASSIFIER_PROMPT, MEDIA_CLASSIFIER_SCHEMA, MediaCandidateInfo, MediaClassification, build_compact_payload, classify_media_content, detect_candidate_media, validate_classifier_response, ) # ============================================================================== # 1. Testes de Validação do Contrato Estruturado (validate_classifier_response) # ============================================================================== def test_validate_classifier_response_text_valid() -> None: data = {"content_type": "text", "media_type": None} result = validate_classifier_response(data) assert result == MediaClassification(content_type="text", media_type=None) def test_validate_classifier_response_text_with_media_type_invalid() -> None: data = {"content_type": "text", "media_type": "image"} assert validate_classifier_response(data) is None def test_validate_classifier_response_media_valid() -> None: for m_type in ("video", "image", "images", "embed", "mixed"): data = {"content_type": "media", "media_type": m_type} result = validate_classifier_response(data) assert result == MediaClassification(content_type="media", media_type=m_type) def test_validate_classifier_response_media_with_null_invalid() -> None: data = {"content_type": "media", "media_type": None} assert validate_classifier_response(data) is None def test_validate_classifier_response_unknown_values() -> None: assert validate_classifier_response({"content_type": "audio", "media_type": None}) is None assert validate_classifier_response({"content_type": "media", "media_type": "podcast"}) is None def test_validate_classifier_response_missing_or_extra_fields() -> None: assert validate_classifier_response({"content_type": "text"}) is None assert validate_classifier_response({"content_type": "text", "media_type": None, "extra": 123}) is None assert validate_classifier_response("not_a_dict") is None # ============================================================================== # 2. Testes do Gate Estrutural DOM (detect_candidate_media) # ============================================================================== def test_detect_candidate_media_video() -> None: html = """
Texto curto da matéria.
Apenas texto e áudio.
Galeria completa do evento.
Veja o post acima.
Texto jornalístico longo sem mídia interna no corpo.
Segundo parágrafo informativo.
Parágrafo do artigo.
Primeiro parágrafo com acentuação: ação, notícia & análise.
Segundo parágrafo com texto em espanhol: ¿Cómo estás? Fútbol y pasión.
" not in payload
assert " Primeiro parágrafo de notícia densa. Segundo parágrafo detalhando o acontecimento político e econômico. Terceiro parágrafo com as conclusões e declarações oficiais.Editorial Textual Pura