name: Test on: push: branches: [main] pull_request: # 仓库启用 merge queue 后,"合并后的结果"会在落地前先跑一遍测试(需在仓库设置里开启) merge_group: # star 刷新走 PR 时由机器人显式 dispatch(GITHUB_TOKEN 建的 PR 不会触发 pull_request 工作流) workflow_dispatch: permissions: contents: read jobs: test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v4 with: node-version: "20" - name: Smoke tests run: npm test # issue #51:设置必须在插件升级后存活。这份验证跑真实插件代码 + 真机形状的宿主替身, # 「包目录被整体替换」这一步冒烟测试覆盖不到,单独跑一遍。 - name: Settings survive plugin upgrade (#51) run: node scripts/verify-settings-survive-upgrade.cjs # issue #92:外部词库送来的内容不能被当成「用户改动」冻进存储 / 镜像, # 否则 README 承诺的「把包从外部词库删掉即可回到设置页管理」不成立。 - name: External bank ownership (#92) run: node scripts/verify-external-bank-ownership.cjs # (SSE 推送)+ (If-Match):被修的是「两个调用方之间的时序」,纯函数测不到。 # 这条用真 HTTP + 真 SSE 长连接跑完整时间线(两个标签页、保存后推送、手改文件推送、断线重连)。 - name: Push-based reload + If-Match conflict control run: node scripts/verify-push-and-conflict.cjs # 设置页抽成模块级工厂后,它能脱离 apply 单独实例化 / 渲染 / 卸载。 # 这份验证同时守住「不再退回闭包捕获」——否则抽取会被无声改回去。 - name: Settings page is independently testable run: node scripts/verify-settings-page.cjs # 鲸尾摇速分档:连续映射(tok/s ÷ 16,上限 6 次/秒)在小黑盒反馈里被说成「直接起飞了… # 都看不清尾巴」。这条把「离散档位 + 上限压到 4」钉住,并逐点确认不带该键时等于改动前的行为。 - name: Whale-tail speed tiers run: node scripts/verify-whale-tail-tiers.cjs # appearance.fontSize 的 0 = 跟随宿主:客户端半边一直放行它,服务端半边曾把它夹成下限 8, # 于是选 0 → 保存 → 刷新回退 8px,且全程无报错(issue #129)。这条按「两半口径逐点一致 # + 真 HTTP 往返 + 直接读落盘文件」钉住。 - name: appearance.fontSize = 0 survives a save run: node scripts/verify-appearance-zero.cjs # 选句引擎:反重复(洗牌袋)+ 条件选词(when / rarity), # 外加「设置页行语法双向可逆」与 node 半边的校验 / 比较键。 # 这些错了肉眼看不出来(少抽一句、条件句在错的时候出现、保存一次丢条件),单独钉住。 - name: Phrase selection engine (anti-repeat + conditions) run: node scripts/verify-phrase-selection.cjs # 依赖真实 DOM 的部分(弹幕挂载、状态行锁宽、标签页标题所有权、每回合容器的内存泄漏) # 纯函数测不到,单独一档。GitHub 的 ubuntu 镜像自带 Google Chrome,运行器按 # /usr/bin/google-chrome 自动挑(也可 --browser= 指定)。 browser: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 # 运行器用 Node 内置的全局 WebSocket 连 CDP(Node 22+ 才有);主 test 档仍跑 Node 20, # 顺带覆盖较老的宿主运行时。 - name: Setup Node uses: actions/setup-node@v4 with: node-version: "22" - name: Danmaku / layout / settings-save / pending / title pages run: node scripts/run-danmaku-mount-test.cjs && node scripts/run-danmaku-mount-test.cjs --page=label && node scripts/run-danmaku-mount-test.cjs --page=settings && node scripts/run-danmaku-mount-test.cjs --page=pending && node scripts/run-danmaku-mount-test.cjs --page=title # 对外注册接口:一个真的第三方站在宿主上下文上接入,词库清空后状态行只可能 # 显示第三方内容 —— 这条证明「不改本插件源码就能接进来」不是纸面约定。 # 对外注册接口:一个真的第三方站在宿主上下文上接入,词库清空后状态行只可能 # 显示第三方内容 —— 这条证明「不改本插件源码就能接进来」不是纸面约定。 - name: Third-party registration API run: node scripts/run-danmaku-mount-test.cjs --page=external # 外观(字体/发光/动画/活动指示)与 弹幕增强(悬停冻结、点击复制、按相位分色、 # 自己发一条):类名、::before、指针交互都只有真浏览器 + 真 CSS 才成立。 - name: Appearance themes + danmaku extras run: node scripts/run-danmaku-mount-test.cjs --page=appearance # 含 issue #87 的泄漏场景:连续 8 个回合后每回合的临时容器必须回落到开跑前的规模 - name: 0.1.7 status line + turn-container leak (#87) run: node scripts/run-turn-process-test.cjs # issue #141:别的插件/皮肤的「除我之外全隐藏」会把挂在 runningContent 里的状态行 # 一起 display:none。这条规则是级联的结果 —— 读源码看不出「谁赢」,只有真浏览器量 # computed display 才有结论。它同时钉住行根的公开白名单标记 # (data-dsh-status-rotator-line / .dsh-status-rotator-line)与「标记不是自愈机制」。 - name: Coexistence with dsh-claude-style's wait line (#141) run: node scripts/run-issue-141-coexist-test.cjs # issue #144:核心词库为空时,「文案」页的自动落点撞上**未启用**的词库包 —— # 打字确实写盘成功,但运行时只合并 enabledPacks,状态栏永远不显示,且全程静默。 # 这条跑真实 lib/client.js + 真 DOM:自动落点、PUT 落进哪个包、重读后目标是否保持、 # 未启用提示与下拉标记;另有一个「一个包都没启用」的场景要求它不许静默。 - name: Auto edit-target must not pick a disabled pack (#144) run: node scripts/run-issue-144-disabled-pack-test.cjs # issue #151:把投稿界面搬进设置页 —— 本地按机器人**同口径**预校验,一键开好预填的 Issue。 # 这条跑真实 lib/client.js + 真 DOM 的完整交互(空→写→校验→勾选→出正文→复制/打开), # 并钉住"投稿草稿不进配置、一次盘都不写"。正文能否被机器人解析由 smoke-test 那边验 # (那边能 require scripts/phrase-bot.cjs)。 - name: In-settings phrase submission (#151) run: node scripts/run-issue-151-submit-test.cjs # issue #166:常驻 2 秒兜底轮询 rescanAll 每拍两次全树遍历 + 逐元素读几何。 # 这条用计数证据量「静态页面里全树重扫的次数」:关闭 / 默认间隔时 2.6 秒内应为 0 #(旧实现每 2 秒必然 2 次),并把新配置项 rescanIntervalMs 与三条事件驱动兜底 #(MutationObserver 接管 / ResizeObserver 截断 / 服务晚就绪的限次重试)一起钉住。 - name: Fallback rescan interval + event-driven fallbacks (#166) run: node scripts/run-issue-166-rescan-test.cjs