fix(plex): the rails' Restart comes from the one rollup; plain text decodes whole entity names only
Both Continue-watching rails built a show's card state inline; they now take it from rollup.show_state, so a show part watched with nothing to resume offers Play alone there too. A named reference counts only when its whole name is an HTML5 entity: html.unescape still decoded the legacy "¬" inside "¬ice;". Tests cover the grid's in-progress-but-not-resumable case through its SQL and both rails.
This commit is contained in:
@@ -165,6 +165,30 @@ def test_continue_watching_movies_and_shows(db, monkeypatch, override_dep):
|
||||
assert "m1" not in ids
|
||||
|
||||
|
||||
def test_a_continue_watching_show_says_whether_it_has_an_episode_to_resume(
|
||||
db, monkeypatch, override_dep
|
||||
):
|
||||
# Both in-progress rails (Discover's and Home's) take a show's card state from the one rollup:
|
||||
# a show part watched with nothing to resume offers Play alone, not Continue + Restart.
|
||||
from app.discover.queries import plex_in_progress
|
||||
|
||||
user = _seed(db)
|
||||
|
||||
def rails():
|
||||
d = _get(db, user, monkeypatch, override_dep, "/api/plex/discover?scope=both").json()
|
||||
home = {c["id"]: c for _, c in plex_in_progress(db, user.id, lang="en")}
|
||||
return {c["id"]: c for c in d["continue_watching"]}["sh1"], home["sh1"]
|
||||
|
||||
assert [c["resumable"] for c in rails()] == [True, True]
|
||||
ep1 = db.execute(select(PlexItem).where(PlexItem.rating_key == "sh1e1")).scalar_one()
|
||||
st = db.execute(
|
||||
select(PlexState).where(PlexState.user_id == user.id, PlexState.item_id == ep1.id)
|
||||
).scalar_one()
|
||||
st.status, st.position_seconds = "watched", 0
|
||||
db.commit()
|
||||
assert [(c["status"], c["resumable"]) for c in rails()] == [("in_progress", False)] * 2
|
||||
|
||||
|
||||
def test_continue_watching_null_status_in_hidden_out(db, monkeypatch, override_dep):
|
||||
# A started movie whose PlexState.status is NULL is still "in progress": `NULL NOT IN (...)` is NULL
|
||||
# (not TRUE), so a bare notin_ would wrongly drop it — the or_(is_(None), notin_) branch keeps it.
|
||||
|
||||
@@ -33,6 +33,8 @@ HU_SUMMARY = "<p>A műsorban minden párosnak stoppal kell eljutnia.</p>"
|
||||
("a < b and 1 <3 you", "a < b and 1 <3 you"),
|
||||
# Only a reference with its semicolon is one: an ampersand in prose stays as written.
|
||||
("AT¬ice, R© and H&M", "AT¬ice, R© and H&M"),
|
||||
# ...and only a whole entity name: a legacy one at its start ("¬", "&") is not.
|
||||
("AT¬ice; and &x;", "AT¬ice; and &x;"),
|
||||
("été ©", "été ©"),
|
||||
("Plain summary.", "Plain summary."),
|
||||
(" padded ", "padded"),
|
||||
|
||||
@@ -220,15 +220,18 @@ class TestRollup:
|
||||
for i in _get(db, user, monkeypatch, override_dep, "/api/plex/library").json()["items"]
|
||||
}
|
||||
assert cards["s1"]["resumable"] is True
|
||||
# e1 finished, e2 untouched: in progress, but nothing to resume
|
||||
e1 = db.execute(select(PlexItem).where(PlexItem.rating_key == "e1")).scalar_one()
|
||||
db.execute(
|
||||
delete(PlexState).where(PlexState.user_id == user.id, PlexState.position_seconds > 0)
|
||||
delete(PlexState).where(PlexState.user_id == user.id, PlexState.item_id == e1.id)
|
||||
)
|
||||
db.add(PlexState(user_id=user.id, item_id=e1.id, status="watched"))
|
||||
db.commit()
|
||||
cards = {
|
||||
i["id"]: i
|
||||
for i in _get(db, user, monkeypatch, override_dep, "/api/plex/library").json()["items"]
|
||||
}
|
||||
assert cards["s1"]["resumable"] is False
|
||||
assert (cards["s1"]["status"], cards["s1"]["resumable"]) == ("in_progress", False)
|
||||
|
||||
|
||||
def _fake_paginate(by_type):
|
||||
|
||||
Reference in New Issue
Block a user