Pulse 移动端告警历史浏览器合格性验证指南:AlertHistoryMobileList 的 390×844 组件级 Playwright 测试

发布时间:2026/10/12 10:20:39
Pulse 移动端告警历史浏览器合格性验证指南:AlertHistoryMobileList 的 390×844 组件级 Playwright 测试 可观测性运维后端【免费下载链接】PulseReal-time monitoring dashboard for Proxmox VE, PBS, Docker, Kubernetes, TrueNAS and vSphere. Self-hosted, with smart alerts and AI patrols that catch silent failures.项目地址https://gitcode.com/gh_mirrors/pulse27/Pulse点击查看免费下载导读本文围绕 Pulse 前端仓库中的移动端告警历史Mobile Alert History浏览器合格性browser qualification测试展开说明如何用 Playwright 的 Chromium 与 WebKit 双引擎在 390×844 手机视口下对生产组件 AlertHistoryMobileList 及其调查抽屉进行自动化验收。读完本文你将掌握该合格性用例的启动方式、合成数据 fixture 的构造思路、焦点陷阱focus trap、Escape 关闭、焦点归还、横向溢出等关键断言背后的实现原理以及它相对于整机、读屏、持久化等验证类型的能力边界。一、为什么需要“组件级浏览器合格性”验证Pulse 的告警历史页面在同一份数据上提供了桌面表格与手机卡片两种呈现响应式容器 AlertHistoryTableSection 在md:hidden断点下渲染AlertHistoryMobileList在md及以上断点渲染表格。手机端没有 hover、没有宽屏的多列布局告警行的调查入口Timeline / Resource、实时读数、最后越界时间等上下文都必须压缩进一张卡片并在抽屉式对话框中完成焦点闭环。浏览器合格性测试正是针对这类“脱离桌面交互习惯”的移动交互而设它在真实浏览器引擎中渲染生产组件与生产 Tailwind CSS而非 mock 组件或测试样式从而验证tests/qualification/mobile-alert-history/README.md中列出的六项行为——Timeline/Resource 两种调查、Tab 焦点圈定、Escape 关闭、行消失后的焦点归还、页面溢出控制。二、前置条件与运行方式原文档给出的运行命令如下从仓库根目录执行# 在仓库根目录与 frontend-modern 分别安装依赖 npm ci npm --prefix frontend-modern ci # 执行移动告警历史浏览器合格性测试 pulse-heavy-run -- node tests/qualification/mobile-alert-history/run.mjs其中pulse-heavy-run是仓库文档统一约定的重型运行包装命令见 uuid-layout-diagnostic 对 “real local build/benchmark execution usepulse-heavy-run -- command” 的说明用于将真实浏览器执行与轻量校验区分开。运行器直接复用frontend-modern/node_modules中的 Vite 与playwright/test因此必须先完成两次npm ci。该用例依赖 Playwright 的Chromium与WebKit两个浏览器及其系统库缺少任一引擎或对应系统依赖时无法通过。三、运行器的生命周期与隔离策略测试入口 run.mjs 的核心隔离策略是“无后端、无凭据、无实时数据”Loopback-only Vite 服务器通过createServer以frontend-modern为根目录、vite.config.ts为配置文件启动绑定host: 127.0.0.1、port: 0临时端口。process.chdir(root)让 Tailwind 能从前端目录解析其配置。短暂端口port: 0交由系统分配临时端口避免与本地开发服务器冲突。确定性清理无论用例通过与否try/finally都保证先关闭全部浏览器、再server.close()不留孤儿进程与监听端口。由于服务器只对 loopback 开放且 fixture 不含任何网络请求整个运行过程不接触后端、凭据或生产数据可安全地在本地与 CI 中重复执行。四、合成数据 fixture一次可复现的手机会话页面源文件位于 frontend-modern/tests/browser/mobile-alert-history.htmlHTML 骨架与 mobile-alert-history.tsxSolidJS 渲染入口。fixture 的职责是合成状态、渲染生产组件构造一条alert-1告警resourceName: pve-production-01、rawAlertType: backup_failed、startTime: 2026-08-04T14:30:00.000Z放入“Today (August 4th)”分组构造对应的incident-1message 为Backup destination unavailable.含一个alert_fired事件预置到incidentTimelines与resourceIncidents将toggleIncidentTimeline、openResourceIncidentPanel等回调用最小实现 stub 化createSignal Set 操作明确不实现记事保存、过滤或网络加载通过Object.assign(window, { removeHistoryRows: ... })暴露window.removeHistoryRows()供测试在运行中清空分组模拟“刷新或过滤导致来源行消失”的场景最终render(() AlertHistoryMobileList state{fixture.state} /)挂载生产组件而不是测试替身。五、验证矩阵两个引擎 × 两种调查 × 行保留/移除run.mjs 对chromium与webkit两个引擎各执行一组遍历外层循环[Timeline, Resource]两种调查入口内层循环[false, true]两种行状态即每次运行共8 个组合。每个组合都新建一个 390×844、isMobile: true、hasTouch: true的移动上下文页面并收集pageerror以便最后断言无脚本异常。维度取值验证目的浏览器引擎Chromium / WebKit双引擎交叉验证 Web 标准行为的一致性调查类型Timeline / Resource两条调查链路各自可用行状态保留 / 移除焦点归还目标在行存在与消失两种情况下都正确视口390×844isMobile hasTouch逼近主流手机逻辑视口与触摸设备语义六、关键断言与源码实现一一对应1. 生产 Tailwind CSS 必须真实加载computed-style 守卫assert.equal( await dialog.evaluate( (el) getComputedStyle(el.closest([data-dialog-layer])).position, ), fixed, Production Tailwind styles must be loaded, );该断言直接针对 Dialog.tsx 中data-dialog-layer层的fixed inset-0 z-1000样式若 Tailwind 未按生产配置生成样式例如误用了未编译的源文件position不会是fixed测试立即失败从而防止在“没有生产样式”的空壳下假通过。2. 对话框语义与标题assert.match(await dialog.getAttribute(aria-label), /pve-production-01/);对应 MobileAlertHistoryInvestigationDialog.tsxdialogLabel()拼接为 “Incident timeline for pve-production-01” 或 “Resource incidents for pve-production-01”作为ariaLabel传给 Dialog。3. Tab 焦点圈定Tab containmentfor (let i 0; i 8; i) { await page.keyboard.press(Tab); assert.ok( await dialog.evaluate((el) el.contains(document.activeElement)), Tab must stay in dialog, ); }连按 8 次 Tab每次都必须落在对话框内部。其底层实现位于 useDialogState.ts组件在document上监听keydown当Tab且当前焦点在最后一个可聚焦元素或对话框外时preventDefault()并回到第一个元素ShiftTab对称处理。配合lockBodyScroll对 body 设置overflow: hidden与兄弟节点inert实现完整模态语义。4. Escape 关闭与焦点归还focus returnawait page.keyboard.press(Escape); await dialog.waitFor({ state: detached }); // 双重 requestAnimationFrame 等待状态提交 const target removeRow ? page.getByTestId(alert-history-mobile-list) : trigger; assert.ok(await target.evaluate((el) el document.activeElement), ...);Escape 关闭由useDialogState的 keydown 处理器统一完成。焦点归还则体现了两层设计Dialog 层关闭时若为最顶层对话框优先options.returnFocus?.()否则回退到打开前的previousFocususeDialogState.ts#L169-L183。AlertHistoryMobileList 层getInvestigationReturnFocusTarget 先按data-alert-history-row-key定位来源卡片再在卡片内找[data-alert-history-action${kind}]按钮若卡片已消失则回退到[data-testidalert-history-mobile-list]列表容器。closeInvestigation会在对话框关闭后执行双重requestAnimationFrame再补一次focus({ preventScroll: true })确保虚拟化列表滚动/重排后的最终焦点位置正确AlertHistoryMobileList.tsx#L98-L127。因此测试的两种期望恰好对应实现的两级回退行保留时焦点回到Timeline/Resource 触发按钮行被removeHistoryRows()移除后page.locator(article).count() 0焦点回到存活的列表容器data-testidalert-history-mobile-list本身带tabindex-1可接收程序化聚焦。5. 页面无横向溢出assert.ok( await page.evaluate( () document.documentElement.scrollWidth innerWidth 1, ), No horizontal overflow, );该断言把“卡片布局在 390px 宽度下是否横向撑破页面”作为硬性门槛防止出现超宽元素或min-w-0缺失导致的横向滚动条。6. 无脚本异常收集整个组合的pageerror事件最后assert.deepEqual(errors, [])将组件运行时的任何未捕获异常直接判为失败。七、被验证的移动交互细节从测试回看组件设计触控尺寸AlertHistoryItemActions.tsx 中 Timeline/Resource 按钮在touchSized时追加min-h-11保证手机上的点按目标高度单元测试同样断言两个按钮持有min-h-11。打开阈值告警的实时读数手机没有 hover因此“清除告警与最后一次越界”必须常驻卡片。AlertHistoryMobileList 用Show将descriptionCopy().detail与lastBreach一并渲染useRelativeTimeNow驱动的共享时钟会持续刷新实时读数。调查抽屉与虚拟化行隔离抽屉内部滚动区使用overflow-y-auto overscroll-contain见 MobileAlertHistoryInvestigationDialog.tsx配合layoutdrawer-right让调查内容滚动不干扰外层PlatformWindowedList的虚拟化行单元测试专门断言“Resource incidents”内容渲染在对话框而非卡片article内。桌面/手机布局同步matchMedia((min-width: 768px))监听器在视口切回桌面或 AI 聊天助手打开时自动收起调查抽屉同时保留共享的expandedIncidents/resourceIncidentPanel状态供切回手机时恢复AlertHistoryMobileList.tsx#L52-L83。八、能力边界这份证据证明什么、不证明什么原文档对此有明确限定这也是消费这份证据时必须遵守的边界覆盖范围它是component-browser evidence——真实浏览器渲染生产组件与生产样式但整条链路由 fixture 合成状态驱动。不覆盖整应用端到端、真实物理设备触控、屏幕阅读器ARIA 语义由单元与浏览器用例共同保证但无读屏实测、历史数据持久化、以及通知投递链路。fixture 回调不实现记事保存、过滤或网络操作。“回退守卫”是反向断言若把 AlertHistoryMobileList.tsx 的return action ?? list改成return action ?? null行消失时焦点将无处可落removeRow分支的焦点断言必然失败。原文档特别强调该 case 必须保留作为防回归的活体契约。九、与单元测试的分工同主题的单元测试 AlertHistoryMobileList.test.tsx 在 jsdom 环境下验证状态语义点击 Timeline 触发toggleIncidentTimeline调用、Escape 后按钮重新获得焦点、桌面↔手机布局切换时抽屉的打开/收起、Assist 交接后焦点归属 AI 聊天输入框等而run.mjs在真实引擎中验证浏览器行为与真实样式。两者互补前者快、覆盖面广后者慢、但证明“在真实手机上可能发生的交互语义”。十、小结tests/qualification/mobile-alert-history是一份“少而准”的组件级浏览器证据以合成数据 双引擎 390×844 移动视口为骨架把生产组件在生产样式下必须成立的行为两种调查、焦点圈定、Escape 关闭、焦点归还、无溢出、无异常固化为可重复执行的 Playwright 用例并用一条 computed-style 断言挡住“没有加载生产 Tailwind”的假通过。它明确把自己定位为证据而非交付物不冒充整机、读屏、持久化或通知投递验证但为移动告警历史的调查交互提供了可回归、可追溯的浏览器级底线。赞分享可观测性运维后端【免费下载链接】PulseReal-time monitoring dashboard for Proxmox VE, PBS, Docker, Kubernetes, TrueNAS and vSphere. Self-hosted, with smart alerts and AI patrols that catch silent failures.项目地址https://gitcode.com/gh_mirrors/pulse27/Pulse点击查看免费下载相关推荐Handlebars.js 浏览器测试指南基于 Playwright 与 Docker 的多浏览器验证方案Handlebars.js 浏览器测试指南基于 Playwright 与 Docker 的多浏览器验证方案 Handlebars.js 是语义化模板引擎项目前端IronClaw E2E 测试套件实战基于 Playwright 与 Reborn serve 的浏览器级端到端测试指南IronClaw E2E 测试套件实战基于 Playwright 与 Reborn serve 的浏览器级端到端测试指南 output_article Ir人工智能AI 应用交互助手AI AgentPenpot 前端测试体系实战指南CLJS 单元测试、Playwright 集成测试与浏览器实测验证Penpot 前端测试体系实战指南CLJS 单元测试、Playwright 集成测试与浏览器实测验证 Penpot 的前端 frontend/ 由 Clo前端设计系统图形学协同办公创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考