history: flag rows whose slug no longer means the same anime
Provider switch (anidb -> hianime-first) left anidb-era rows whose slugs
200 on hianime as a DIFFERENT anime: /watch/jujutsu-kaisen-2552 is now
Burning Kabaddi (the trailing number is a hianime id), and the stored
anidb ep id doesn't even exist in that anime's list — the row rendered
as watched JJK but linked to the wrong show.
Client-side validation (no data migration): every history row's slug is
checked against GET /api/anime/{slug} once per slug; title mismatch (or
a dead slug) marks the entry stale. Stale rows:
- home: one card per stale anime above the hero + 'history ->' link
- history page: separate 'Moved or renamed on the source' section
Each card: title, 'find it ->' (search by stored title) and x (remove,
same endpoint as regular cards). Current rows are untouched: a hianime
slug whose details name matches the stored title passes.
Tests: API contract for a stale row (deletable while on the board);
live browser test (gated) with the real jujutsu-kaisen-2552 row:
remap card renders, card doesn't link to the wrong slug, find-it
lands on the title's search.
This commit is contained in:
1 parent
0f6bd0a52a
commit
379f591180
3 files changed
+141
-3
No files matched your search
@@ -450,3 +450,43 @@ async def _autoplay_blocked():
|
||||
timeout=120000, polling=250)
|
||||
assert not errors, errors
|
||||
await browser.close()
|
||||
|
||||
|
||||
def test_stale_history_remap_board():
|
||||
asyncio.run(_stale_history_remap_board())
|
||||
|
||||
|
||||
async def _stale_history_remap_board():
|
||||
# provider switch (anidb -> hianime) left rows whose anidb slug 200s on
|
||||
# hianime as a DIFFERENT anime (jujutsu-kaisen-2552 = Burning Kabaddi).
|
||||
# The history page must flag it for remap instead of linking to that show.
|
||||
jar = http.cookiejar.CookieJar()
|
||||
op = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
|
||||
op.open(urllib.request.Request(BASE + "/login",
|
||||
data=json.dumps({"username": "erin", "password": "erinpw12345"}).encode(),
|
||||
headers={"Content-Type": "application/json", "X-Aniweb": "1"}, method="POST"))
|
||||
op.open(urllib.request.Request(BASE + "/api/history",
|
||||
data=json.dumps({"title": "Jujutsu Kaisen", "slug_id": "jujutsu-kaisen-2552",
|
||||
"season_id": 2552, "ep_id": 35996, "lang": "jpn", "ep": 1,
|
||||
"pos": 42}).encode(),
|
||||
headers={"Content-Type": "application/json", "X-Aniweb": "1"}, method="POST"))
|
||||
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(args=LAUNCH_ARGS)
|
||||
page = await (await browser.new_context()).new_page()
|
||||
errors = []
|
||||
page.on("pageerror", lambda e: errors.append(str(e)))
|
||||
await _login(page, "erin", "erinpw12345")
|
||||
await page.goto(BASE + "/?history")
|
||||
await page.wait_for_function(
|
||||
"document.querySelector('a.card.remap')", timeout=60000, polling=POLL)
|
||||
stale = page.locator("a.card.remap", has_text="Jujutsu Kaisen")
|
||||
assert "not found" in await stale.inner_text()
|
||||
# the card must not link to the wrong-slug detail page; find-it goes
|
||||
# to the title's search instead
|
||||
assert not await stale.get_attribute("href")
|
||||
await stale.locator("button:has-text('find it')").click(force=True)
|
||||
await page.wait_for_function(
|
||||
"location.search.includes('q=')", timeout=15000, polling=POLL)
|
||||
assert not errors, errors
|
||||
await browser.close()
|
||||
Reference in new issue
Block a user