99 lines
3.8 KiB
Python
99 lines
3.8 KiB
Python
|
|
"""Tests for chapter cover Celery enqueue deduplication gate."""
|
||
|
|
|
||
|
|
from unittest.mock import MagicMock, patch
|
||
|
|
|
||
|
|
from app.tasks.chapter_cover_enqueue import (
|
||
|
|
_enqueue_dedup_key,
|
||
|
|
try_enqueue_generate_chapter_cover,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def _eligible_pipeline_chapter():
|
||
|
|
ch = MagicMock()
|
||
|
|
ch.cover_asset_id = None
|
||
|
|
ch.canonical_markdown = "some body"
|
||
|
|
ch.images = []
|
||
|
|
return ch
|
||
|
|
|
||
|
|
|
||
|
|
@patch("app.tasks.chapter_cover_tasks.generate_chapter_cover")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue.redis.from_url")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue._load_chapter_for_enqueue_sync")
|
||
|
|
def test_try_enqueue_false_when_chapter_missing(mock_load, mock_redis, mock_gen_task):
|
||
|
|
mock_load.return_value = None
|
||
|
|
assert try_enqueue_generate_chapter_cover("missing-id", "pipeline") is False
|
||
|
|
mock_gen_task.delay.assert_not_called()
|
||
|
|
mock_redis.assert_not_called()
|
||
|
|
|
||
|
|
|
||
|
|
@patch("app.tasks.chapter_cover_tasks.generate_chapter_cover")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue.redis.from_url")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue._load_chapter_for_enqueue_sync")
|
||
|
|
def test_try_enqueue_false_when_cover_asset_exists(
|
||
|
|
mock_load, mock_redis, mock_gen_task
|
||
|
|
):
|
||
|
|
ch = _eligible_pipeline_chapter()
|
||
|
|
ch.cover_asset_id = "asset-1"
|
||
|
|
mock_load.return_value = ch
|
||
|
|
assert try_enqueue_generate_chapter_cover("ch-1", "pipeline") is False
|
||
|
|
mock_gen_task.delay.assert_not_called()
|
||
|
|
mock_redis.assert_not_called()
|
||
|
|
|
||
|
|
|
||
|
|
@patch("app.tasks.chapter_cover_tasks.generate_chapter_cover")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue.redis.from_url")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue._load_chapter_for_enqueue_sync")
|
||
|
|
def test_try_enqueue_false_when_redis_nx_not_acquired(
|
||
|
|
mock_load, mock_redis, mock_gen_task
|
||
|
|
):
|
||
|
|
mock_load.return_value = _eligible_pipeline_chapter()
|
||
|
|
r = MagicMock()
|
||
|
|
r.set.return_value = False
|
||
|
|
mock_redis.return_value = r
|
||
|
|
assert try_enqueue_generate_chapter_cover("ch-1", "pipeline") is False
|
||
|
|
mock_gen_task.delay.assert_not_called()
|
||
|
|
r.set.assert_called_once()
|
||
|
|
|
||
|
|
|
||
|
|
@patch("app.tasks.chapter_cover_tasks.generate_chapter_cover")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue.redis.from_url")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue._load_chapter_for_enqueue_sync")
|
||
|
|
def test_try_enqueue_true_when_eligible_and_nx_ok(mock_load, mock_redis, mock_gen_task):
|
||
|
|
mock_load.return_value = _eligible_pipeline_chapter()
|
||
|
|
r = MagicMock()
|
||
|
|
r.set.return_value = True
|
||
|
|
mock_redis.return_value = r
|
||
|
|
mock_gen_task.delay = MagicMock()
|
||
|
|
assert try_enqueue_generate_chapter_cover("ch-1", "pipeline") is True
|
||
|
|
mock_gen_task.delay.assert_called_once_with("ch-1")
|
||
|
|
r.set.assert_called_once()
|
||
|
|
|
||
|
|
|
||
|
|
@patch("app.tasks.chapter_cover_tasks.generate_chapter_cover")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue.redis.from_url")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue._load_chapter_for_enqueue_sync")
|
||
|
|
def test_try_enqueue_deletes_dedup_key_when_delay_fails(
|
||
|
|
mock_load, mock_redis, mock_gen_task
|
||
|
|
):
|
||
|
|
mock_load.return_value = _eligible_pipeline_chapter()
|
||
|
|
r = MagicMock()
|
||
|
|
r.set.return_value = True
|
||
|
|
mock_redis.return_value = r
|
||
|
|
mock_gen_task.delay = MagicMock(side_effect=RuntimeError("broker down"))
|
||
|
|
assert try_enqueue_generate_chapter_cover("ch-1", "pipeline") is False
|
||
|
|
mock_gen_task.delay.assert_called_once_with("ch-1")
|
||
|
|
r.delete.assert_called_once_with(_enqueue_dedup_key("ch-1"))
|
||
|
|
|
||
|
|
|
||
|
|
@patch("app.tasks.chapter_cover_tasks.generate_chapter_cover")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue.redis.from_url")
|
||
|
|
@patch("app.tasks.chapter_cover_enqueue._load_chapter_for_enqueue_sync")
|
||
|
|
def test_try_enqueue_http_skips_empty_category(mock_load, mock_redis, mock_gen_task):
|
||
|
|
ch = _eligible_pipeline_chapter()
|
||
|
|
ch.category = None
|
||
|
|
ch.status = "completed"
|
||
|
|
mock_load.return_value = ch
|
||
|
|
assert try_enqueue_generate_chapter_cover("ch-1", "http") is False
|
||
|
|
mock_gen_task.delay.assert_not_called()
|
||
|
|
mock_redis.assert_not_called()
|