"""Tests for main handlers with /stream as base.""" import json from unittest.mock import MagicMock, patch import pytest from flask.testing import FlaskClient from owsrequest.utils.fixture_plugin import RequestEngine from owsresponse import response from pytest_mock import MockerFixture from assets.constants import error from assets.logic import ownership, stream_info OA_HEADERS = {"Orchard-User-Id": "oa:12345"} ALW_HEADERS = { "Orchard-User-Id": "alw:12345", "Grass-Account-Id": "234234", "Grass-Account-Type": "vendor", } @pytest.fixture def get_hls_streaming_link_successful_response() -> dict[str, str]: """Mock successful HLS streaming link response.""" return {"status_code:": "200"} @pytest.mark.parametrize("headers", [OA_HEADERS, ALW_HEADERS, {}]) def test_get_hls_streaming_link_correction_mode_false( fixture_client: FlaskClient, headers: dict[str, str], get_hls_streaming_link_successful_response: dict[str, str], mocker: MockerFixture, ) -> None: """Test route that gets HLS streaming link.""" check_track_ownership_mock = mocker.patch.object( ownership, "check_track_ownership", return_value=response.Response() ) get_track_wowza_stream_url_with_correction_assets_mock = mocker.patch.object( stream_info, "get_track_wowza_stream_url_with_correction_assets", return_value=get_hls_streaming_link_successful_response, ) track_id = "1" data = {} full_ip_address = None is_correction_mode = False if not headers: data = {"Orchard-User-Id": "alw:321"} headers["Content-Type"] = "application/json" if "Orchard-User-Id" in headers: full_user_id = headers["Orchard-User-Id"] else: full_user_id = data["Orchard-User-Id"] if "X-Forwarded-For" in headers: full_ip_address = headers["X-Forwarded-For"] request_url = "/stream/track/{track_id}/hls".format(track_id=track_id) result = fixture_client.get(request_url, data=json.dumps(data), headers=headers) assert get_track_wowza_stream_url_with_correction_assets_mock.call_count == 1 get_track_wowza_stream_url_with_correction_assets_mock.assert_called_with( track_id, full_user_id, full_ip_address, None, is_correction_mode, None, None ) assert result.status_code == 200 assert result.headers.get("Correlation-Id") assert ( json.loads(result.data.decode("utf-8")) == get_hls_streaming_link_successful_response ) if headers == ALW_HEADERS: assert check_track_ownership_mock.called @pytest.mark.parametrize("headers", [OA_HEADERS, ALW_HEADERS, {}]) def test_get_hls_streaming_link_correction_mode_true( fixture_client: FlaskClient, headers: dict[str, str], get_hls_streaming_link_successful_response: dict[str, str], mocker: MockerFixture, ) -> None: """Test route that gets HLS streaming link.""" check_track_ownership_mock = mocker.patch.object( ownership, "check_track_ownership", return_value=response.Response() ) get_track_wowza_stream_url_with_correction_assets_mock = mocker.patch.object( stream_info, "get_track_wowza_stream_url_with_correction_assets", return_value=get_hls_streaming_link_successful_response, ) track_id = "1" data = {} full_ip_address = None is_correction_mode = True if not headers: data = {"Orchard-User-Id": "alw:321"} headers["Content-Type"] = "application/json" if "Orchard-User-Id" in headers: full_user_id = headers["Orchard-User-Id"] else: full_user_id = data["Orchard-User-Id"] if "X-Forwarded-For" in headers: full_ip_address = headers["X-Forwarded-For"] request_url = "/stream/track/{track_id}/hls?is_correction=True".format( track_id=track_id ) result = fixture_client.get(request_url, data=json.dumps(data), headers=headers) assert get_track_wowza_stream_url_with_correction_assets_mock.call_count == 1 get_track_wowza_stream_url_with_correction_assets_mock.assert_called_with( track_id, full_user_id, full_ip_address, None, is_correction_mode, None, None ) assert result.status_code == 200 assert result.headers.get("Correlation-Id") assert ( json.loads(result.data.decode("utf-8")) == get_hls_streaming_link_successful_response ) if headers == ALW_HEADERS: assert check_track_ownership_mock.called @patch("assets.handlers.ownership") def test_get_hls_streaming_link_for_profile_access_denied( mock_ownership: MagicMock, fixture_client: FlaskClient, request_engine: RequestEngine, ) -> None: """Test getting an hls streaming link for profiles.""" request_engine["ows-features"].add_spec("GET", "/features") profile_headers = { "Orchard-Profile-Type": "ContentProfile", "Orchard-Profile-Id": 1, "Orchard-Identity-Id": "abc-def", "Orchard-Profile-UUID": "ghi-jkl", "Referer": "http://localhost/", } request_url = "/stream/track/1/hls?is_correction=True" result = fixture_client.get(request_url, headers=profile_headers) assert result.status_code == 401 assert result.get_json()["message"] == "No explicit access policy found" profile_headers["Orchard-Roles"] = "review_digital_audio" mock_ownership.check_profile_track_access.return_value = False result = fixture_client.get(request_url, headers=profile_headers) assert result.status_code == 403 assert result.get_json()["message"] == "User lacks ownership" @patch("assets.handlers.ownership") @patch("assets.handlers.stream_info") def test_get_hls_streaming_link_for_profile_success( mock_stream: MagicMock, mock_ownership: MagicMock, fixture_client: FlaskClient, request_engine: RequestEngine, ) -> None: """Test getting an hls streaming link for profiles.""" request_engine["ows-features"].add_spec("GET", "/features") profile_headers = { "Orchard-Profile-Type": "ContentProfile", "Orchard-Profile-Id": 1, "Orchard-Identity-Id": "abc-def", "Orchard-Profile-UUID": "ghi-jkl", "Orchard-Roles": "review_digital_audio", "Referer": "http://localhost/", } request_url = "/stream/track/1/hls?is_correction=True" mock_ownership.check_profile_track_access.return_value = True mock_stream.get_track_wowza_stream_url_with_correction_assets.return_value = {} result = fixture_client.get(request_url, headers=profile_headers) assert result.status_code == 200 mock_stream.get_track_wowza_stream_url_with_correction_assets.assert_called_with( "1", None, None, "http://localhost/", True, "ContentProfile", "ghi-jkl" ) @pytest.mark.parametrize( "headers, status, error_code", [ (OA_HEADERS, 400, error.ERROR_CODE_HEADER_VALIDATION), (ALW_HEADERS, 400, error.ERROR_CODE_HEADER_VALIDATION), ({}, 401, error.ERROR_CODE_AUTHORIZATION), ], ) def test_get_hls_streaming_link_failure( fixture_client: FlaskClient, headers: dict[str, str], status: int, error_code: str ) -> None: """Test route fails when there is invalid Orchard-User-Id in header.""" track_id = "1" request_url = f"/stream/track/{track_id}/hls" headers = headers.copy() if headers: headers["Orchard-User-Id"] = "invalid_id" else: headers["Content-Type"] = "application/json" result = fixture_client.get(request_url, headers=headers) assert result.status_code == status response_message = json.loads(result.data.decode()) assert response_message["code"] == error_code def test_get_hls_streaming_link_with_invalid_ownership( monkeypatch: pytest.MonkeyPatch, fixture_client: FlaskClient ) -> None: """Test route that gets HLS streaming link.""" headers = ALW_HEADERS.copy() headers["Content-Type"] = "application/json" monkeypatch.setattr( ownership, "check_track_ownership", value=MagicMock( return_value=response.create_error_response( code="not_owned", message="not_owned", status=403 ) ), ) track_id = "1" request_url = f"/stream/track/{track_id}/hls" result = fixture_client.get(request_url, headers=headers) assert result.status_code == 403 assert result.headers.get("Correlation-Id")