test: guard v1.3.28 website launch (#3410)

Co-authored-by: zhifu gao <[email protected]>
This commit is contained in:
zhifu gao
2026-07-24 16:20:54 +08:00
committed by GitHub
co-authored by zhifu gao
parent 689cc945b4
commit ddea8873fb
2 changed files with 217 additions and 0 deletions
+74
View File
@@ -4,6 +4,7 @@
from __future__ import annotations
import argparse
from html.parser import HTMLParser
import re
import sys
import time
@@ -19,6 +20,7 @@ class PageContract:
required: tuple[str, ...]
forbidden: tuple[str, ...] = ()
visible_required: tuple[str, ...] = ()
required_links: tuple[str, ...] = ()
@dataclass(frozen=True)
@@ -212,6 +214,52 @@ PAGE_CONTRACTS: dict[str, PageContract] = {
),
forbidden=("funasr==1.3.26", "runtime-llamacpp-v0.1.1"),
),
f"{BASE_URL}/blog/funasr-v1-3-28-realtime-websocket-subtitles.html": PageContract(
required=(
"funasr==1.3.28",
"funasr-realtime-server",
"VAD",
"runtime-llamacpp-v0.1.9",
"https://github.com/modelscope/FunASR/releases/tag/v1.3.28",
"/donors.html",
),
visible_required=(
"精确合并源码通过 118 项聚焦回归测试",
"实时 WebSocket 文件还独立通过 60 项测试",
"覆盖 STOP 最终解码",
"SenseVoice 用户通过同一次包升级获得字幕对齐修复",
),
required_links=(
"https://github.com/modelscope/FunASR",
"https://github.com/FunAudioLLM/Fun-ASR",
"https://github.com/FunAudioLLM/SenseVoice",
"https://github.com/modelscope/FunClip",
),
forbidden=("funasr==1.3.27", "runtime-llamacpp-v0.1.1"),
),
f"{BASE_URL}/en/blog/funasr-v1-3-28-realtime-websocket-subtitles.html": PageContract(
required=(
"funasr==1.3.28",
"funasr-realtime-server",
"VAD",
"runtime-llamacpp-v0.1.9",
"https://github.com/modelscope/FunASR/releases/tag/v1.3.28",
"/en/donors.html",
),
visible_required=(
"The exact merged source passed 118 focused regression tests",
"The realtime WebSocket file also passed all 60 tests independently",
"including STOP final decode",
"SenseVoice users receive the subtitle alignment fix",
),
required_links=(
"https://github.com/modelscope/FunASR",
"https://github.com/FunAudioLLM/Fun-ASR",
"https://github.com/FunAudioLLM/SenseVoice",
"https://github.com/modelscope/FunClip",
),
forbidden=("funasr==1.3.27", "runtime-llamacpp-v0.1.1"),
),
}
@@ -235,6 +283,27 @@ def extract_visible_text(html: str) -> str:
return re.sub(r"\s+", " ", body).strip()
class _LinkCollector(HTMLParser):
def __init__(self) -> None:
super().__init__()
self.links: set[str] = set()
def handle_starttag(
self, tag: str, attrs: list[tuple[str, str | None]]
) -> None:
if tag.lower() != "a":
return
for name, value in attrs:
if name.lower() == "href" and value is not None:
self.links.add(value)
def extract_links(html: str) -> set[str]:
parser = _LinkCollector()
parser.feed(html)
return parser.links
def validate_pages(pages: dict[str, str]) -> list[str]:
failures: list[str] = []
for url, contract in PAGE_CONTRACTS.items():
@@ -250,6 +319,11 @@ def validate_pages(pages: dict[str, str]) -> list[str]:
for needle in contract.visible_required:
if needle not in visible_text:
failures.append(f"{url}: visible text missing `{needle}`")
if contract.required_links:
links = extract_links(text)
for target in contract.required_links:
if target not in links:
failures.append(f"{url}: missing link `{target}`")
for needle in contract.forbidden:
if needle in text:
failures.append(f"{url}: forbidden `{needle}`")
+143
View File
@@ -147,6 +147,38 @@ def test_website_contract_accepts_current_public_copy():
https://github.com/modelscope/FunClip
<a href="/en/donors.html">Thanks</a>
""",
"https://www.funasr.com/blog/funasr-v1-3-28-realtime-websocket-subtitles.html": """
funasr==1.3.28
funasr-realtime-server
VAD STOP SenseVoice
精确合并源码通过 118 项聚焦回归测试
实时 WebSocket 文件还独立通过 60 项测试
覆盖 STOP 最终解码
SenseVoice 用户通过同一次包升级获得字幕对齐修复
runtime-llamacpp-v0.1.9
https://github.com/modelscope/FunASR/releases/tag/v1.3.28
<a href="https://github.com/modelscope/FunASR">FunASR</a>
<a href="https://github.com/FunAudioLLM/Fun-ASR">Fun-ASR</a>
<a href="https://github.com/FunAudioLLM/SenseVoice">SenseVoice</a>
<a href="https://github.com/modelscope/FunClip">FunClip</a>
<a href="/donors.html">功德榜</a>
""",
"https://www.funasr.com/en/blog/funasr-v1-3-28-realtime-websocket-subtitles.html": """
funasr==1.3.28
funasr-realtime-server
VAD STOP SenseVoice
The exact merged source passed 118 focused regression tests.
The realtime WebSocket file also passed all 60 tests independently
including STOP final decode
SenseVoice users receive the subtitle alignment fix
runtime-llamacpp-v0.1.9
https://github.com/modelscope/FunASR/releases/tag/v1.3.28
<a href="https://github.com/modelscope/FunASR">FunASR</a>
<a href="https://github.com/FunAudioLLM/Fun-ASR">Fun-ASR</a>
<a href="https://github.com/FunAudioLLM/SenseVoice">SenseVoice</a>
<a href="https://github.com/modelscope/FunClip">FunClip</a>
<a href="/en/donors.html">Thanks</a>
""",
}
assert checker.validate_pages(pages) == []
@@ -187,6 +219,117 @@ def test_website_contract_includes_v1327_launch_articles():
)
def test_website_contract_includes_v1328_launch_articles():
checker = _load_module()
assert (
"https://www.funasr.com/blog/funasr-v1-3-28-realtime-websocket-subtitles.html"
in checker.PAGE_CONTRACTS
)
assert (
"https://www.funasr.com/en/blog/funasr-v1-3-28-realtime-websocket-subtitles.html"
in checker.PAGE_CONTRACTS
)
def test_v1328_contract_rejects_language_swapped_body():
checker = _load_module()
url = "https://www.funasr.com/blog/funasr-v1-3-28-realtime-websocket-subtitles.html"
pages = {
url: """
<body>
funasr==1.3.28 funasr-realtime-server VAD STOP SenseVoice
The exact merged source passed 118 focused regression tests.
The realtime WebSocket file also passed all 60 tests independently.
runtime-llamacpp-v0.1.9
https://github.com/modelscope/FunASR/releases/tag/v1.3.28
<a href="https://github.com/modelscope/FunASR">FunASR</a>
<a href="https://github.com/FunAudioLLM/Fun-ASR">Fun-ASR</a>
<a href="https://github.com/FunAudioLLM/SenseVoice">SenseVoice</a>
<a href="https://github.com/modelscope/FunClip">FunClip</a>
<a href="/donors.html">Thanks</a>
</body>
"""
}
failures = checker.validate_pages(pages)
assert any(
url in failure
and "visible text missing `精确合并源码通过 118 项聚焦回归测试`" in failure
for failure in failures
)
def test_v1328_contract_rejects_css_test_count_and_indirect_repo_link():
checker = _load_module()
url = "https://www.funasr.com/en/blog/funasr-v1-3-28-realtime-websocket-subtitles.html"
pages = {
url: """
<style>.proof { font-weight: 600; }</style>
<body>
funasr==1.3.28 funasr-realtime-server VAD STOP SenseVoice
The exact merged source passed 118 focused regression tests.
runtime-llamacpp-v0.1.9
<a href="https://github.com/modelscope/FunASR/releases/tag/v1.3.28">Release</a>
<a href="https://github.com/FunAudioLLM/Fun-ASR">Fun-ASR</a>
<a href="https://github.com/FunAudioLLM/SenseVoice">SenseVoice</a>
<a href="https://github.com/modelscope/FunClip">FunClip</a>
<a href="/en/donors.html">Thanks</a>
</body>
"""
}
failures = checker.validate_pages(pages)
assert any(
url in failure
and "visible text missing `The realtime WebSocket file also passed all 60 tests independently`"
in failure
for failure in failures
)
assert any(
url in failure
and "missing link `https://github.com/modelscope/FunASR`" in failure
for failure in failures
)
def test_v1328_contract_requires_visible_stop_and_sensevoice_copy():
checker = _load_module()
url = "https://www.funasr.com/en/blog/funasr-v1-3-28-realtime-websocket-subtitles.html"
pages = {
url: """
<head><meta name="keywords" content="STOP"></head>
<body>
funasr==1.3.28 funasr-realtime-server VAD
The exact merged source passed 118 focused regression tests.
The realtime WebSocket file also passed all 60 tests independently.
runtime-llamacpp-v0.1.9
https://github.com/modelscope/FunASR/releases/tag/v1.3.28
<a href="https://github.com/modelscope/FunASR">FunASR</a>
<a href="https://github.com/FunAudioLLM/Fun-ASR">Fun-ASR</a>
<a href="https://github.com/FunAudioLLM/SenseVoice">Repository</a>
<a href="https://github.com/modelscope/FunClip">FunClip</a>
<a href="/en/donors.html">Thanks</a>
</body>
"""
}
failures = checker.validate_pages(pages)
assert any(
url in failure and "visible text missing `including STOP final decode`" in failure
for failure in failures
)
assert any(
url in failure
and "visible text missing `SenseVoice users receive the subtitle alignment fix`"
in failure
for failure in failures
)
def test_static_asset_contract_rejects_non_png_payloads():
checker = _load_module()
banner_url = "https://www.funasr.com/img/banner.4f436d19.png"