Files
ai-kefu-jc/tests/test_invite_static.py
T
2026-09-29 14:15:12 +08:00

70 lines
2.9 KiB
Python

"""邀请卡静态回归网:不变量"未展示 ⇒ 零占位、零拦截"。
背景(2026-09-01 bug):点 X 写入 permanent 后刷新,startInviteTimer 在
storage 守卫早退 ⇒ showInvite 永不执行 ⇒ invitePanel 引用恒为 null ⇒
hideInvite 提前返回 ⇒ .invite-panel 停留"display:block + opacity:0"的
隐形占位态,.invite-container(z-index:99998、无 pointer-events:none)
拦截页面右下角所有点击。修复 = 出厂即折叠(A)+ 容器点击穿透(C)。
"""
import re
from pathlib import Path
STATIC = Path(__file__).resolve().parent.parent / "static"
def _read(rel):
return (STATIC / rel).read_text(encoding="utf-8")
def _extract_function(src, name):
"""花括号计数提取函数源码(与 test_theme_static.py 同款)。"""
start = src.index("function " + name + "(")
i = src.index("{", start)
depth = 0
for j in range(i, len(src)):
if src[j] == "{":
depth += 1
elif src[j] == "}":
depth -= 1
if depth == 0:
return src[start:j + 1]
raise AssertionError("unbalanced braces in " + name)
def test_invite_panel_ships_hidden():
"""A:面板出厂即带 hide —— 任何绕过 showInvite 的路径都零占位。"""
src = _read("widget.js")
assert '<div class="invite-panel hide">' in src, \
"invite 模板必须出厂带 hide(未展示 ⇒ 无布局占位)"
def test_invite_container_click_through():
"""C:容器 pointer-events:none —— 卡片未展示时整棵子树点击穿透。"""
m = re.search(r"\.invite-container \{[^}]*\}", _read("widget.js"))
assert m, "widget.js 缺 .invite-container 规则"
assert "pointer-events:none" in m.group(0), \
".invite-container 必须 pointer-events:none(防隐形拦截点击)"
def test_show_invite_reflow_between_unhide_and_show():
"""入场动画:remove(hide) 与 add(show) 之间必须强制回流。
出厂带 hide 后,若 remove 与 add 同帧执行,display:none→block 与
opacity 变化合并进同一次样式重算,0.3s 淡入退化为瞬现。
"""
fn = _extract_function(_read("widget.js"), "showInvite")
for token in ('remove("hide")', "offsetWidth", 'add("show")'):
assert token in fn, f"showInvite 缺 {token}"
assert fn.index('remove("hide")') < fn.index("offsetWidth") < fn.index('add("show")'), \
"showInvite 须 remove(hide) → offsetWidth 回流 → add(show) 顺序执行"
def test_autoinvite_specialcase_removed_and_guard_kept():
"""A 落地后 !autoInvite 预折叠特判删除;startInviteTimer 的配置守卫保留。"""
src = _read("widget.js")
assert "disabledInvitePanel" not in src, \
"!autoInvite 预折叠特判应删除(出厂 hide 统一覆盖该不变量)"
fn = _extract_function(src, "startInviteTimer")
assert "if (!autoInvite) return;" in fn, \
"startInviteTimer 必须保留 data-auto-invite=false 永不自动弹的守卫"