108 lines
3.1 KiB
Python
108 lines
3.1 KiB
Python
|
|
"""§4.2: apply_official_exercise_media_rules — Lifecycle, Sichtbarkeit, Copyright."""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import os
|
||
|
|
from unittest.mock import MagicMock
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from fastapi import HTTPException
|
||
|
|
|
||
|
|
os.environ.setdefault("SKIP_DB_MIGRATE", "1")
|
||
|
|
|
||
|
|
from routers.exercises import apply_official_exercise_media_rules
|
||
|
|
|
||
|
|
|
||
|
|
def _row(
|
||
|
|
aid: int,
|
||
|
|
*,
|
||
|
|
vis: str = "private",
|
||
|
|
lifecycle: str = "active",
|
||
|
|
copyright_notice: str | None = "",
|
||
|
|
name: str = "f.bin",
|
||
|
|
) -> dict:
|
||
|
|
return {
|
||
|
|
"id": aid,
|
||
|
|
"visibility": vis,
|
||
|
|
"club_id": 1,
|
||
|
|
"lifecycle_state": lifecycle,
|
||
|
|
"copyright_notice": copyright_notice,
|
||
|
|
"original_filename": name,
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def test_non_official_visibility_noop() -> None:
|
||
|
|
cur = MagicMock()
|
||
|
|
apply_official_exercise_media_rules(
|
||
|
|
cur,
|
||
|
|
1,
|
||
|
|
"private",
|
||
|
|
promote_attached_media=False,
|
||
|
|
default_official_media_copyright=None,
|
||
|
|
)
|
||
|
|
cur.execute.assert_not_called()
|
||
|
|
|
||
|
|
|
||
|
|
def test_lifecycle_not_active_422() -> None:
|
||
|
|
cur = MagicMock()
|
||
|
|
cur.fetchall.return_value = [_row(1, lifecycle="trash_soft", copyright_notice="abc")]
|
||
|
|
with pytest.raises(HTTPException) as ei:
|
||
|
|
apply_official_exercise_media_rules(
|
||
|
|
cur,
|
||
|
|
1,
|
||
|
|
"official",
|
||
|
|
promote_attached_media=False,
|
||
|
|
default_official_media_copyright=None,
|
||
|
|
)
|
||
|
|
assert ei.value.status_code == 422
|
||
|
|
assert ei.value.detail["code"] == "OFFICIAL_MEDIA_LIFECYCLE"
|
||
|
|
|
||
|
|
|
||
|
|
def test_visibility_promotion_confirm_422() -> None:
|
||
|
|
cur = MagicMock()
|
||
|
|
cur.fetchall.return_value = [_row(1, vis="club", copyright_notice="halten")]
|
||
|
|
with pytest.raises(HTTPException) as ei:
|
||
|
|
apply_official_exercise_media_rules(
|
||
|
|
cur,
|
||
|
|
1,
|
||
|
|
"official",
|
||
|
|
promote_attached_media=False,
|
||
|
|
default_official_media_copyright=None,
|
||
|
|
)
|
||
|
|
assert ei.value.status_code == 422
|
||
|
|
assert ei.value.detail["code"] == "OFFICIAL_MEDIA_CONFIRM_REQUIRED"
|
||
|
|
assert ei.value.detail["assets_need_visibility_promotion"]
|
||
|
|
|
||
|
|
|
||
|
|
def test_copyright_required_422() -> None:
|
||
|
|
cur = MagicMock()
|
||
|
|
cur.fetchall.return_value = [_row(1, vis="official", copyright_notice="")]
|
||
|
|
with pytest.raises(HTTPException) as ei:
|
||
|
|
apply_official_exercise_media_rules(
|
||
|
|
cur,
|
||
|
|
1,
|
||
|
|
"official",
|
||
|
|
promote_attached_media=True,
|
||
|
|
default_official_media_copyright=None,
|
||
|
|
)
|
||
|
|
assert ei.value.status_code == 422
|
||
|
|
assert ei.value.detail["code"] == "OFFICIAL_MEDIA_CONFIRM_REQUIRED"
|
||
|
|
assert ei.value.detail["assets_missing_copyright"]
|
||
|
|
|
||
|
|
|
||
|
|
def test_promote_and_fill_copyright_updates() -> None:
|
||
|
|
cur = MagicMock()
|
||
|
|
cur.fetchall.return_value = [_row(1, vis="private", copyright_notice=" ")]
|
||
|
|
apply_official_exercise_media_rules(
|
||
|
|
cur,
|
||
|
|
42,
|
||
|
|
"official",
|
||
|
|
promote_attached_media=True,
|
||
|
|
default_official_media_copyright="© Test Holding",
|
||
|
|
)
|
||
|
|
assert cur.execute.call_count == 3
|
||
|
|
sql1 = cur.execute.call_args_list[1][0][0]
|
||
|
|
sql2 = cur.execute.call_args_list[2][0][0]
|
||
|
|
assert "visibility = 'official'" in sql1
|
||
|
|
assert "copyright_notice" in sql2
|
||
|
|
|