Files
iptv-manager-service/tests/routers/test_playlist.py
Stefano a42d4c30a6
All checks were successful
AWS Deploy on Push / build (push) Successful in 5m18s
Started (incomplete) implementation of stream verification scheduler and endpoints
2025-06-17 17:12:39 -05:00

262 lines
9.1 KiB
Python

import uuid
from datetime import datetime, timezone
from unittest.mock import MagicMock, patch
import pytest
from fastapi import status
from sqlalchemy.orm import Session
from app.auth.dependencies import get_current_user
# Import the router we're testing
from app.routers.playlist import (
ProcessStatus,
ValidationProcessResponse,
ValidationResultResponse,
router,
validation_processes,
)
from app.utils.database import get_db
# Import mocks and fixtures
from tests.utils.auth_test_fixtures import (
admin_user_client,
db_session,
non_admin_user_client,
)
from tests.utils.db_mocks import MockChannelDB
# --- Test Fixtures ---
@pytest.fixture
def mock_stream_manager():
with patch("app.routers.playlist.StreamManager") as mock:
yield mock
# --- Test Cases For Stream Validation ---
def test_start_stream_validation_success(
db_session: Session, admin_user_client, mock_stream_manager
):
"""Test starting a stream validation process"""
mock_instance = mock_stream_manager.return_value
mock_instance.validate_and_select_stream.return_value = "http://valid.stream.url"
response = admin_user_client.post(
"/playlist/validate-streams", json={"channel_id": "test-channel"}
)
assert response.status_code == status.HTTP_202_ACCEPTED
data = response.json()
assert "process_id" in data
assert data["status"] == ProcessStatus.PENDING
assert data["message"] == "Validation process started"
# Verify process was added to tracking
process_id = data["process_id"]
assert process_id in validation_processes
# In test environment, background tasks run synchronously so status may be COMPLETED
assert validation_processes[process_id]["status"] in [
ProcessStatus.PENDING,
ProcessStatus.COMPLETED,
]
assert validation_processes[process_id]["channel_id"] == "test-channel"
def test_get_validation_status_pending(db_session: Session, admin_user_client):
"""Test checking status of pending validation"""
process_id = str(uuid.uuid4())
validation_processes[process_id] = {
"status": ProcessStatus.PENDING,
"channel_id": "test-channel",
}
response = admin_user_client.get(f"/playlist/validate-streams/{process_id}")
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["process_id"] == process_id
assert data["status"] == ProcessStatus.PENDING
assert data["working_streams"] is None
assert data["error"] is None
def test_get_validation_status_completed(db_session: Session, admin_user_client):
"""Test checking status of completed validation"""
process_id = str(uuid.uuid4())
validation_processes[process_id] = {
"status": ProcessStatus.COMPLETED,
"channel_id": "test-channel",
"result": {
"working_streams": [
{"channel_id": "test-channel", "stream_url": "http://valid.stream.url"}
]
},
}
response = admin_user_client.get(f"/playlist/validate-streams/{process_id}")
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["process_id"] == process_id
assert data["status"] == ProcessStatus.COMPLETED
assert len(data["working_streams"]) == 1
assert data["working_streams"][0]["channel_id"] == "test-channel"
assert data["working_streams"][0]["stream_url"] == "http://valid.stream.url"
assert data["error"] is None
def test_get_validation_status_completed_with_error(
db_session: Session, admin_user_client
):
"""Test checking status of completed validation with error"""
process_id = str(uuid.uuid4())
validation_processes[process_id] = {
"status": ProcessStatus.COMPLETED,
"channel_id": "test-channel",
"error": "No working streams found for channel test-channel",
}
response = admin_user_client.get(f"/playlist/validate-streams/{process_id}")
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["process_id"] == process_id
assert data["status"] == ProcessStatus.COMPLETED
assert data["working_streams"] is None
assert data["error"] == "No working streams found for channel test-channel"
def test_get_validation_status_failed(db_session: Session, admin_user_client):
"""Test checking status of failed validation"""
process_id = str(uuid.uuid4())
validation_processes[process_id] = {
"status": ProcessStatus.FAILED,
"channel_id": "test-channel",
"error": "Validation error occurred",
}
response = admin_user_client.get(f"/playlist/validate-streams/{process_id}")
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["process_id"] == process_id
assert data["status"] == ProcessStatus.FAILED
assert data["working_streams"] is None
assert data["error"] == "Validation error occurred"
def test_get_validation_status_not_found(db_session: Session, admin_user_client):
"""Test checking status of non-existent process"""
random_uuid = str(uuid.uuid4())
response = admin_user_client.get(f"/playlist/validate-streams/{random_uuid}")
assert response.status_code == status.HTTP_404_NOT_FOUND
assert "Process not found" in response.json()["detail"]
def test_run_stream_validation_success(mock_stream_manager, db_session):
"""Test the background validation task success case"""
process_id = str(uuid.uuid4())
validation_processes[process_id] = {
"status": ProcessStatus.PENDING,
"channel_id": "test-channel",
}
mock_instance = mock_stream_manager.return_value
mock_instance.validate_and_select_stream.return_value = "http://valid.stream.url"
from app.routers.playlist import run_stream_validation
run_stream_validation(process_id, "test-channel", db_session)
assert validation_processes[process_id]["status"] == ProcessStatus.COMPLETED
assert len(validation_processes[process_id]["result"]["working_streams"]) == 1
assert (
validation_processes[process_id]["result"]["working_streams"][0].channel_id
== "test-channel"
)
assert (
validation_processes[process_id]["result"]["working_streams"][0].stream_url
== "http://valid.stream.url"
)
def test_run_stream_validation_failure(mock_stream_manager, db_session):
"""Test the background validation task failure case"""
process_id = str(uuid.uuid4())
validation_processes[process_id] = {
"status": ProcessStatus.PENDING,
"channel_id": "test-channel",
}
mock_instance = mock_stream_manager.return_value
mock_instance.validate_and_select_stream.return_value = None
from app.routers.playlist import run_stream_validation
run_stream_validation(process_id, "test-channel", db_session)
assert validation_processes[process_id]["status"] == ProcessStatus.COMPLETED
assert "error" in validation_processes[process_id]
assert "No working streams found" in validation_processes[process_id]["error"]
def test_run_stream_validation_exception(mock_stream_manager, db_session):
"""Test the background validation task exception case"""
process_id = str(uuid.uuid4())
validation_processes[process_id] = {
"status": ProcessStatus.PENDING,
"channel_id": "test-channel",
}
mock_instance = mock_stream_manager.return_value
mock_instance.validate_and_select_stream.side_effect = Exception("Test error")
from app.routers.playlist import run_stream_validation
run_stream_validation(process_id, "test-channel", db_session)
assert validation_processes[process_id]["status"] == ProcessStatus.FAILED
assert "error" in validation_processes[process_id]
assert "Test error" in validation_processes[process_id]["error"]
def test_start_stream_validation_no_channel_id(
db_session: Session, admin_user_client, mock_stream_manager
):
"""Test starting validation without channel_id"""
response = admin_user_client.post("/playlist/validate-streams", json={})
assert response.status_code == status.HTTP_202_ACCEPTED
data = response.json()
assert "process_id" in data
assert data["status"] == ProcessStatus.PENDING
# Verify process was added to tracking
process_id = data["process_id"]
assert process_id in validation_processes
assert validation_processes[process_id]["status"] in [
ProcessStatus.PENDING,
ProcessStatus.COMPLETED,
]
assert validation_processes[process_id]["channel_id"] is None
assert "not yet implemented" in validation_processes[process_id].get("error", "")
def test_run_stream_validation_no_channel_id(mock_stream_manager, db_session):
"""Test background validation without channel_id"""
process_id = str(uuid.uuid4())
validation_processes[process_id] = {"status": ProcessStatus.PENDING}
from app.routers.playlist import run_stream_validation
run_stream_validation(process_id, None, db_session)
assert validation_processes[process_id]["status"] == ProcessStatus.COMPLETED
assert "error" in validation_processes[process_id]
assert "not yet implemented" in validation_processes[process_id]["error"]