#!/usr/bin/env python3 """A favorite whose site yt-dlp can't extract still gets its formats. Providers like rule34video hand the listing their formats; a favorite keeps none, and /api/resolve comes back empty for them. ensureFormats must then ask the providers again and take the item that is this video. backend/main.py & .venv/bin/python tests/smoke_favorite_formats.py """ import json import sys from playwright.sync_api import sync_playwright BASE = "http://127.0.0.1:5000/" SERVER = "https://a.fixture.test" FAV = {"key": "rule34video:4511669", "id": "rule34video:4511669", "url": "https://rule34video.com/video/4511669/sindel-cassie-sonya/", "title": "Sindel, Cassie, Sonya", "thumb": "", "channel": "Rule34video", "uploader": "Nyl", "duration": 510, "isLive": False, "favoriteDate": "2026-11-02T22:00:05.356Z"} STATUS = {"id": "a", "name": "a", "online": True, "channels": [ {"id": "rule34video", "name": "Rule34video", "description": "x", "options": []}]} FMT = [{"url": "https://rule34video.com/get_file/1/x/4511669_720p.mp4/", "height": 720, "ext": "mp4"}] asked = [] def videos(route): body = json.loads(route.request.post_data or "{}") asked.append(body) items = [{"id": "rule34video:1", "url": "https://rule34video.com/video/1/other/", "formats": []}, {"id": FAV["id"], "url": FAV["url"], "formats": FMT}] route.fulfill(status=200, content_type="application/json", body=json.dumps({"items": items})) def main(): failed = 0 with sync_playwright() as p: b = p.chromium.launch(args=["--no-sandbox", "--disable-gpu"]) page = b.new_page() page.route(f"{SERVER}/api/status", lambda r: r.fulfill( status=200, content_type="application/json", body=json.dumps(STATUS))) page.route("**/api/resolve", lambda r: r.fulfill( status=200, content_type="application/json", body='{"formats":[],"http_headers":{},"isLive":false,"url":null}')) page.route("**/api/videos", videos) page.goto(BASE, wait_until="domcontentloaded") page.evaluate("""([s, f]) => { localStorage.setItem('config', JSON.stringify({servers: [{[s]: {}}]})); localStorage.setItem('favorites', JSON.stringify([f])); }""", [SERVER, FAV]) page.goto(BASE, wait_until="load") meta = page.evaluate("""async (f) => { const v = Object.assign({}, f); const m = await App.videos.ensureFormats(v); return { m, attached: !!v.meta }; }""", FAV) ok = bool(meta["m"]) and meta["m"]["formats"] == FMT and meta["attached"] print(f" [{'PASS' if ok else 'FAIL'}] favorite gets the provider's formats {meta}") failed += 0 if ok else 1 ok = bool(asked) and asked[0]["channel"] == "rule34video" and asked[0]["server"] == SERVER print(f" [{'PASS' if ok else 'FAIL'}] asked the right channel and server {asked[:1]}") failed += 0 if ok else 1 saved = page.evaluate("""(item) => { localStorage.setItem('favorites', '[]'); App.favorites.toggle(Object.assign({}, item, { formats: [{ url: 'https://x/y.mp4', height: 720 }] })); return App.favorites.getAll()[0]; }""", FAV) ok = bool(saved) and bool(saved.get("meta")) and saved["meta"]["formats"][0]["url"] == "https://x/y.mp4" print(f" [{'PASS' if ok else 'FAIL'}] a saved favorite keeps its formats") failed += 0 if ok else 1 b.close() return 1 if failed else 0 if __name__ == "__main__": sys.exit(main())