- e2e:修死选择器与蜜罐误命中、补断言、GA4/security-headers 用例诚实标注 skip 边界;新增 assert-helpers/fixtures/hydrated/primary-nav/touch-targets 等复用桩。 - 集成层:config/test/jest.integration.config.js + tests-integration/ 真库 一次性 SQLite 用例,teardown 守卫开发库指纹。 - 门禁工具链:jest.setup 归位到根、scripts/accessibility 全站 axe 节点计数、 check-brand-text-token/check-motion-constraints 机械守卫、stryker/lighthouse 配置收敛。
27 lines
1.4 KiB
TypeScript
27 lines
1.4 KiB
TypeScript
import { expect, type Locator } from '@playwright/test';
|
||
|
||
/**
|
||
* 等到 React 把 props/事件监听挂到目标元素上,再对它发起交互。
|
||
*
|
||
* 为什么需要:SSR HTML 一进入 DOM,元素就已经「可见」,但客户端组件的 onClick/onMouseEnter
|
||
* 要等 hydration 完成才存在。这段窗口内派发的指针事件被浏览器当作普通事件丢弃,hydration 后
|
||
* 也不会重放 —— 表现为 hover/click 调用成功、状态却永远不变,然后 expect 轮询到 15s timeout。
|
||
*
|
||
* 实测依据(next dev,本机 :3000):/contact 的 [data-testid="submit-button"] 在 first visible
|
||
* 之后 1735ms 才挂上 handler;早点击得到 0 条 [data-testid="error-message"],
|
||
* hydration 后同一动作得到 5 条。主导航「产品」按钮 first visible 时同样尚未 hydration。
|
||
*
|
||
* 探针取 React DOM 写在宿主元素上的 __reactProps$ 内部键:`toBeVisible()` 只能证明
|
||
* 「渲染出来了」,证明不了「能交互」,而这个键是唯一能把两者分开的信号。项目锁定 React 18.3
|
||
* (package.json),该前缀自 React 16 起稳定。
|
||
*/
|
||
export async function expectHydrated(target: Locator, timeout = 20000): Promise<void> {
|
||
await expect
|
||
.poll(
|
||
async () =>
|
||
target.evaluate((el) => Object.keys(el).some((key) => key.startsWith('__reactProps$'))),
|
||
{ timeout, message: '目标元素尚未完成 hydration' },
|
||
)
|
||
.toBe(true);
|
||
}
|