Files
shelfmark/tests/config/test_hardcover_sync_settings.py
T
splitsec2 9d5b47d17b feat(hardcover): retries, error counting and a back-off for requests nothing matches (#1534)
A synced request whose download failed, was interrupted by a restart, or was cancelled by the stall timer goes back to pending after AUTO_DOWNLOAD_RETRY_DAYS (7 by default, 0 turns it off), a few per pass, oldest first. Only what never arrived is retried, the failed release is remembered, and a request is given up on after three failed retries. Downloads cancelled by a person and rejected requests are never retried.

Errors count as errors: a search that failed in one source no longer reads as no match, a throttled Hardcover lookup is an error and not a skip, and a request that blows up doesn't abort the pass. Both summaries carry the error count.

A request for the same Hardcover book and format is skipped when the history already has a finished or running download for it. A request that finds nothing is searched once a day after three no-match passes, then every two days, up to AUTO_DOWNLOAD_BACKOFF_MAX_DAYS (3 by default, 0 turns it off).
2026-10-23 00:58:42 -06:00

89 lines
2.8 KiB
Python

"""Tests for the Hardcover Sync settings tab registration and action buttons."""
import shelfmark.config.hardcover_sync_settings # noqa: F401 - registers the tab
from shelfmark.core import settings_registry
def _field_map():
tab = settings_registry.get_settings_tab("hardcover_sync")
assert tab is not None
return {field.key: field for field in tab.fields if hasattr(field, "key")}
def test_tab_is_registered():
tab = settings_registry.get_settings_tab("hardcover_sync")
assert tab is not None
assert tab.display_name == "Hardcover Sync"
def test_everything_is_off_by_default():
fields = _field_map()
assert fields["HARDCOVER_SYNC_ENABLED"].default is False
assert fields["AUTO_DOWNLOAD_ENABLED"].default is False
def test_schedule_and_content_type_defaults():
fields = _field_map()
assert fields["HARDCOVER_SYNC_INTERVAL"].default == 6
assert fields["HARDCOVER_SYNC_INTERVAL"].min_value == 1
assert fields["HARDCOVER_SYNC_INTERVAL_UNIT"].default == "hours"
assert fields["HARDCOVER_SYNC_CONTENT_TYPE"].default == "audiobook"
assert fields["HARDCOVER_SYNC_STATUSES"].default == "1"
assert fields["AUTO_DOWNLOAD_SOURCE_PRIORITY"].default == []
def test_failed_downloads_are_retried_after_a_week_and_it_can_be_turned_off():
field = _field_map()["AUTO_DOWNLOAD_RETRY_DAYS"]
assert field.default == 7
assert field.min_value == 0 # 0 is the off switch
def test_shelf_options_come_from_hardcover_statuses():
options = _field_map()["HARDCOVER_SYNC_STATUSES"].options()
assert {"value": "1", "label": "Want to Read"} in options
def test_action_buttons_are_registered():
fields = _field_map()
assert fields["sync_now"].callback is not None
def test_sync_now_reports_busy_when_a_run_is_active(monkeypatch):
monkeypatch.setattr("shelfmark.core.hardcover_scheduler.trigger_async", lambda **_: False)
result = settings_registry.execute_action("hardcover_sync", "sync_now")
assert result["success"] is False
assert "already running" in result["message"]
def test_sync_now_starts_a_forced_run(monkeypatch):
seen = []
def _trigger(**kwargs):
seen.append(kwargs)
return True
monkeypatch.setattr("shelfmark.core.hardcover_scheduler.trigger_async", _trigger)
result = settings_registry.execute_action("hardcover_sync", "sync_now")
assert result["success"] is True
assert seen == [{"force": True}]
def test_request_as_offers_both_and_ebook_sources_have_their_own_priority_list():
fields = _field_map()
options = fields["HARDCOVER_SYNC_CONTENT_TYPE"].options
values = {o["value"] for o in (options() if callable(options) else options)}
assert values == {"audiobook", "ebook", "both"}
assert "AUTO_DOWNLOAD_EBOOK_SOURCE_PRIORITY" in fields
assert fields["AUTO_DOWNLOAD_EBOOK_SOURCE_PRIORITY"].default == []