radoslav-orlov: with no Spotify auth, enrichment runs on the no-creds Spotify Free source (prefer-free is on by default) and IS working — pending drains, the modal shows RUNNING — but the dashboard header tooltip said 'Not Authenticated / Connect Spotify in Settings'. Two causes: - get_stats() only set using_free for the rate-limit / spent-budget bridges, not the plain no-auth-default-free case. The loop already computes the right signal (free_serving = _free_active(), True here) but it was a local var. Cache it on self each iteration and report it as using_free (no auth API call in the 2s status loop). - The dashboard's Spotify updater checked notAuthenticated BEFORE bridgingFree, so even with using_free it showed Not Authenticated. notAuthenticated now excludes the bridging-free case; the LastFM/Genius/Tidal/Qobuz updaters (no free path) are unchanged. 5 seam tests for get_stats free/auth reporting; 67 enrichment/free tests pass.
68 lines
2.7 KiB
Python
68 lines
2.7 KiB
Python
"""Issue #887: the Spotify enrichment worker's get_stats() must report
|
|
``using_free`` when it's enriching via the no-creds Spotify Free source — even
|
|
with no official auth — so the dashboard shows "Running (Spotify Free)" instead
|
|
of a misleading "Not Authenticated".
|
|
|
|
Builds the worker via __new__ (bypassing the real SpotifyClient()) and stubs the
|
|
db-querying helpers, so the get_stats() free/auth logic is tested in isolation.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import types
|
|
|
|
from core.spotify_worker import SpotifyWorker
|
|
|
|
|
|
def _worker(*, serving_via_free, sp=None, rate_limited=False, budget_free=False):
|
|
w = SpotifyWorker.__new__(SpotifyWorker)
|
|
w.running = True
|
|
w.paused = False
|
|
w.thread = types.SimpleNamespace(is_alive=lambda: True)
|
|
w.current_item = None
|
|
w.stats = {'pending': 0, 'processed': 0}
|
|
w._serving_via_free = serving_via_free
|
|
w.client = types.SimpleNamespace(
|
|
sp=sp,
|
|
is_rate_limited=lambda: rate_limited,
|
|
get_rate_limit_info=lambda: None,
|
|
get_post_ban_cooldown_remaining=lambda: 0,
|
|
is_spotify_metadata_available=lambda: True,
|
|
_budget_exhausted_use_free=budget_free,
|
|
)
|
|
# db-backed helpers stubbed — we only exercise the auth/free reporting.
|
|
w._count_pending_items = lambda: 100
|
|
w._get_progress_breakdown = lambda: {}
|
|
w._get_daily_budget_info = lambda: {'exhausted': False}
|
|
return w
|
|
|
|
|
|
def test_no_auth_but_serving_via_free_reports_using_free():
|
|
# #887: no official auth (sp is None), worker enriching via Spotify Free.
|
|
stats = _worker(serving_via_free=True, sp=None).get_stats()
|
|
assert stats['authenticated'] is False # no official auth
|
|
assert stats['using_free'] is True # ...but Free is carrying it
|
|
|
|
|
|
def test_no_auth_and_not_serving_free_is_not_using_free():
|
|
# Genuinely can't enrich (no auth, free not active) -> Not Authenticated stands.
|
|
stats = _worker(serving_via_free=False, sp=None).get_stats()
|
|
assert stats['authenticated'] is False
|
|
assert stats['using_free'] is False
|
|
|
|
|
|
def test_rate_limit_bridge_still_reports_using_free():
|
|
# Pre-existing bridge path must still work (cache False, but rate-limited).
|
|
stats = _worker(serving_via_free=False, sp=object(), rate_limited=True).get_stats()
|
|
assert stats['using_free'] is True
|
|
|
|
|
|
def test_budget_bridge_still_reports_using_free():
|
|
stats = _worker(serving_via_free=False, sp=object(), budget_free=True).get_stats()
|
|
assert stats['using_free'] is True
|
|
|
|
|
|
def test_authed_and_not_on_free_reports_authenticated_not_free():
|
|
stats = _worker(serving_via_free=False, sp=object()).get_stats()
|
|
assert stats['authenticated'] is True
|
|
assert stats['using_free'] is False
|