from pathlib import Path import re ROOT = Path(__file__).resolve().parents[2] MATCH_API = ROOT / "uniapp" / "src" / "api" / "match.ts" MATCH_DETAIL = ROOT / "uniapp" / "src" / "pages" / "match_detail" / "match_detail.vue" MATCH_LIVE_POPUP = ROOT / "uniapp" / "src" / "components" / "match-live-popup" / "match-live-popup.vue" def read_text(path: Path) -> str: return path.read_text(encoding="utf-8") def main() -> None: assert MATCH_LIVE_POPUP.exists(), f"missing popup component: {MATCH_LIVE_POPUP}" detail_source = read_text(MATCH_DETAIL) popup_source = read_text(MATCH_LIVE_POPUP) api_source = read_text(MATCH_API) assert 'v-if="liveList.length"' in detail_source, "match detail should render live_list block with v-if" assert 'v-else-if="thirdPartyLiveUrl"' in detail_source, "match detail should keep thirdPartyLiveUrl fallback with v-else-if" assert "MatchLivePopup" in detail_source, "match detail should use MatchLivePopup" assert "fetch_status" in detail_source, "match detail should reference fetch_status" assert "last_fetch_at" in detail_source, "match detail should reference last_fetch_at" assert "update_time" in detail_source, "match detail should reference update_time" assert "default_play_url" in popup_source, "popup should prefer default_play_url" assert "stream_options" in popup_source, "popup should support stream_options" assert "/pages/webview/webview?url=" in popup_source, "selected stream should route through existing webview page" field_names = [ "play_url_m3u8", "play_url_hd_m3u8", "play_url_flv", "play_url_hd_flv", ] for field_name in field_names: assert field_name in popup_source, f"popup should cover {field_name}" assert field_name in api_source, f"match live types should cover {field_name}" assert re.search(r"const\s+defaultPlayUrl\s*=\s*normalizeUrl\(props\.line\?\.default_play_url\)", popup_source), \ "popup should explicitly prefer props.line?.default_play_url" assert re.search(r"defaultPlayUrl.*?resetSelected", popup_source, re.S), \ "popup selection reset should prefer default_play_url" assert re.search(r"fetch_status.*last_fetch_at", popup_source, re.S) or "update_time" in popup_source, \ "popup metadata should use fetch_status and last_fetch_at/update_time" assert re.search(r"normalized === '0'.*待抓取", popup_source, re.S), \ "popup should map fetch_status 0 to pending label" assert re.search(r"normalized === '1'.*已抓取", popup_source, re.S), \ "popup should map fetch_status 1 to success label" assert re.search(r"normalized === '2'.*抓取失败", popup_source, re.S), \ "popup should map fetch_status 2 to failure label" assert re.search(r"normalized === '0'.*待抓取", detail_source, re.S), \ "page should map fetch_status 0 to pending label" assert re.search(r"normalized === '1'.*已抓取", detail_source, re.S), \ "page should map fetch_status 1 to success label" assert re.search(r"normalized === '2'.*抓取失败", detail_source, re.S), \ "page should map fetch_status 2 to failure label" assert "/match/detail" in api_source, "match detail API path should stay on /match/detail" if __name__ == "__main__": main()