"""Unit tests for the bulk-session slug-redirect dependency (CCM-4380).""" import uuid from typing import cast from unittest.mock import AsyncMock, MagicMock from fastapi import HTTPException from fastapi.requests import Request from pytest_mock.plugin import MockerFixture import pytest from product_staging.api.dependencies import ( BulkSessionSlugRedirect, resolve_bulk_session_slug, ) from product_staging.logic import bulk_session as bulk_session_logic SLUG = "32387-2026-05-25-13-45-35" def _request(path: str, query: str = "") -> Request: request = MagicMock() request.url.path = path request.url.query = query return cast(Request, request) async def test_resolve_returns_uuid_unchanged() -> None: """A UUID path param is returned as-is, with no slug lookup or redirect.""" bulk_session_id = uuid.uuid4() result = await resolve_bulk_session_slug( request=_request(f"/bulk-session/{bulk_session_id}"), bulk_session_id=bulk_session_id, identity_uuid=uuid.uuid4(), profiles=[("SettingsProfile", 1)], ) assert result == bulk_session_id async def test_resolve_slug_raises_redirect_with_relative_location( mocker: MockerFixture, ) -> None: """A slug is resolved, authorized, and a relative 307 Location is raised (query kept).""" resolved_id = str(uuid.uuid4()) identity_uuid = uuid.uuid4() profiles = [("SettingsProfile", 1)] mock_resolve = mocker.patch.object( bulk_session_logic, "get_bulk_session_id_by_slug", new=AsyncMock(return_value=resolved_id), ) mock_authz = mocker.patch.object( bulk_session_logic, "assert_authorization", return_value=None ) with pytest.raises(BulkSessionSlugRedirect) as exc_info: await resolve_bulk_session_slug( request=_request(f"/bulk-session/{SLUG}/assets", query="filename=a.jpg"), bulk_session_id=SLUG, identity_uuid=identity_uuid, profiles=profiles, ) assert ( exc_info.value.location == f"/bulk-session/{resolved_id}/assets?filename=a.jpg" ) mock_resolve.assert_awaited_once_with(SLUG) mock_authz.assert_called_once_with( bulk_session_id=uuid.UUID(resolved_id), identity_uuid=identity_uuid, profiles=profiles, ) async def test_resolve_slug_not_found_raises_404(mocker: MockerFixture) -> None: """A slug that resolves to no session raises a 404 (no redirect).""" mocker.patch.object( bulk_session_logic, "get_bulk_session_id_by_slug", new=AsyncMock(return_value=None), ) with pytest.raises(HTTPException) as exc_info: await resolve_bulk_session_slug( request=_request(f"/bulk-session/{SLUG}/assets"), bulk_session_id=SLUG, identity_uuid=uuid.uuid4(), profiles=[("SettingsProfile", 1)], ) assert exc_info.value.status_code == 404