fix(playlists): a refused push spends none of the push allowance

The cooldown was checked before the list was found pushable and before its sync claim, so Watch later
or a list another sync held used up the push allowance. It now counts only a push that runs. The
docstring that called a YouTube mirror unpushable is corrected: its local edits sync back.
This commit is contained in:
2026-11-07 21:48:38 +01:00
parent 26ed8855c9
commit fc65b8ab83
2 changed files with 48 additions and 4 deletions
+42
View File
@@ -177,6 +177,48 @@ def test_plan_and_push_draw_on_one_allowance(db, as_user, make_user, monkeypatch
assert r.json()["detail"] == {"code": "playlist", "reason": "push_cooldown"}
def test_a_refused_push_spends_no_allowance(db, as_user, make_user, monkeypatch):
# The allowance counts pushes that run: Watch later (never pushable) and a list another sync
# holds are refused before any YouTube call, so they must not leave the next real press at 429.
from contextlib import contextmanager
from app.reader.models import Playlist
from app.routes import playlists as plroutes
user, pl = _pushable_list(db, make_user, monkeypatch, plroutes)
wl = Playlist(user_id=user.id, name="Watch later", kind="watch_later")
db.add(wl)
db.commit()
c = as_user(user)
over = plroutes.PUSH_ALLOWANCE + 1
assert {c.get(f"/api/playlists/{wl.id}/push-plan").status_code for _ in range(over)} == {400}
assert {c.post(f"/api/playlists/{wl.id}/push").status_code for _ in range(over)} == {400}
@contextmanager
def busy(_db, _id):
yield False
with monkeypatch.context() as m:
m.setattr(plroutes, "sync_claim", busy)
assert {c.post(f"/api/playlists/{pl.id}/push").status_code for _ in range(over)} == {409}
assert c.post(f"/api/playlists/{pl.id}/push").status_code == 200
def test_a_mirrored_youtube_list_is_pushable(db, as_user, make_user, monkeypatch):
# A mirror of the user's own YouTube list takes local edits (`dirty`) and syncs them back; only
# Watch later is refused.
from app.reader.models import Playlist
from app.routes import playlists as plroutes
user, _ = _pushable_list(db, make_user, monkeypatch, plroutes)
mirror = Playlist(
user_id=user.id, name="Mine", source="youtube", yt_playlist_id="PLx", dirty=True
)
db.add(mirror)
db.commit()
assert as_user(user).get(f"/api/playlists/{mirror.id}/push-plan").status_code == 200
def test_the_push_cooldown_is_per_user(db, as_user, make_user, monkeypatch):
from app.routes import playlists as plroutes