@futdevpro/ dynam- e2e (英语)
Dynamo+FDP生态系统的端到端测试引擎.
什麽
将表格 v2 设置 POJOs 变成 Playwright 的 Dynamo 基岩包 测试套房—— 自动生成, (中文(简体) ), 类型, (中文(简体) ), 压倒一切, (中文(简体) ), 可调试。 。 。 .
一组三层:
- 表格覆盖 ——每个字段类型都有一个预测正+负 输入矩阵; 生成器从单一个形式发出~20-50个测试 设置 POJO .
- 视图端口矩阵 (华维-2) ——7个标准以上的自动脱产测试 取景口+溢出/触地-目标a11y检测.
- 核心网络生命特征诊断 (行) 合成LCP / CLS / INP / TTFB 测量 + 百分位聚合 + 归属.
状态
波-1.4.4 + MP-10/MP-11 (2026-06-10)-A层合同 B层 发电机(窗体-套装+取景口-套装+CWV-套装), C层运行时间 已登记的CCD管道监督员, 75分测试 覆盖门 活动( 报表) 97.84% (简体中文),分支 87.13%, (中文(简体) ), 函数 98.55%线条 97.84% (简体中文)104个规格,0个失败.
计划网: __documentations/plans/dynamo-e2e-foundation/HYPERPLAN.md
(11名议员,4900+当地办事处规划).
安装
pnpm add -D @futdevpro/dynamo-e2e @playwright/test
@futdevpro/fsm-dynamo 是同位素 – 带来自己的( 或者没有设置)
POJO 源码, 如果您只使用运行时间预设的话 .
快开始
import { DyFM_TextFieldNew_Settings } from '@futdevpro/fsm-dynamo/ngx-models';
import { DyE2E_FormSuite_Generator } from '@futdevpro/dynamo-e2e/generators';
const settings = new DyFM_FormNew_Settings({
key: 'login',
fields: [
new DyFM_TextFieldNew_Settings({ key: 'email', /* ... */ }),
],
});
const specSource = DyE2E_FormSuite_Generator.emit({
formSettings: settings,
formRoute: '/login',
formSelector: 'dynamo-form-new',
});
// → write specSource to `e2e/tests/generated/login-form.spec.ts`
分出口
@futdevpro/dynamo-e2e/contracts- POJO类型@futdevpro/dynamo-e2e/generators——节点排放发动机@futdevpro/dynamo-e2e/runtime— Playwright 固定装置 + 页面对象 (Wave-4) + 实时通知探测器 (单位:千美元)DyE2E_NotificationDetector_Util,见下文)@futdevpro/dynamo-e2e/presets预建套房+DyE2E_getPlaywrightConfig编号 :DyE2E_getGlobalSetup剧作家-配置工厂(fleet e2e-config SSOT)@futdevpro/dynamo-e2e/game——能力定型游戏接缝,故障文物和双向出行目录验证@futdevpro/dynamo-e2e/cwv- 核心网络生命(Wave-3)@futdevpro/dynamo-e2e/ui-check– 脚本,每error级UI检测器,返回VERDICTS(一个可以实现的控制) 无所事事,双层滚动,一个不切换的复选框; 越来越多的默认列表, 编码放弃, 一个安全警卫 用于按下控件。 目录 + 证明:__documentations/UI-CHECK-DETECTORS.md
import { DyE2E_UICheckRunner_Util } from '@futdevpro/dynamo-e2e/ui-check';
const report = await DyE2E_UICheckRunner_Util.run(page, { url: page.url(), accountKind: 'anonymous' });
DyE2E_UICheckRunner_Util.assertClean(report); // throws with every finding's measurement
@futdevpro/dynamo-e2e/visual-gate——视觉回归门:关闭TEST警告和cookie栏通过 应用程序( e)DyE2E_BlockingOverlays_Util.prepareStorageState),然后检查每个密钥页 HU + EN 时为 1440 + 390 (DyE2E_VisualGate_Util.cases:当一个覆被仍被覆盖时,红色会显示(几乎) 没有,它比屏幕大,或者它与承诺的基准不同(toHaveScreenshot) (中文(简体) ). 外观 (单位:千美元)DyE2E_VisualGateLook_Util, BFR-FUTDEVPRO-081):"未找到"的屏幕,一个空的内容区域,绿色/青色/蓝色 而不是中性的灰色, 屏幕上的文本, 原始图标词, 占位符; 带有referenceUrl,则 标出页数的标题和段落大小isOnReference与testInfo,截图 (科技和生产)列入报告.
import { DyE2E_BlockingOverlays_Util, DyE2E_VisualGate_Util } from '@futdevpro/dynamo-e2e/visual-gate';
for (const gateCase of DyE2E_VisualGate_Util.cases({ pages: [ { name: 'login', path: '/login' } ] })) {
test(`| visual: ${gateCase.id}`, async ({ browser }) => {
const { storageState } = await DyE2E_BlockingOverlays_Util.prepareStorageState({
browser, baseUrl: BASE_URL, locale: gateCase.language.locale,
});
const context = await browser.newContext({ storageState, locale: gateCase.language.locale,
viewport: { width: gateCase.viewport.width, height: gateCase.viewport.height } });
const page = await context.newPage();
await page.goto(BASE_URL + gateCase.page.path);
await DyE2E_VisualGate_Util.assertPage(page, gateCase, {
contentSelector: 'main', notFoundSelector: 'app-a-block-message-screen',
referenceUrl: 'https://example.hu', testInfo: test.info(),
}); // layout + look first, then the production font sizes, then the screenshot comparison
});
}
Playwright 预设—— CI 超时和失败预算
import { DyE2E_getPlaywrightConfig, DyE2E_ciTimeout } from '@futdevpro/dynamo-e2e/presets';
export default DyE2E_getPlaywrightConfig({
defaultBaseUrl: 'https://test.example.hu',
ciTimeoutFactor: 3, // CI only: timeout / expectTimeout / actionTimeout / navigationTimeout × 3 (default 1)
maxFailuresInCi: 1, // CI only: stop after the first failure (default: unset = unchanged)
});
⚠️ 电话站
{ timeout }覆盖配置 .expect(x).toBeVisible({ timeout: 15_000 })忽略预设expect.timeout联合国ciTimeoutFactor) (中文(简体) ). 缩放这些值为DyE2E_ciTimeout(15_000)当地不变, ×E2E_CI_TIMEOUT_FACTOR(或3个)CI测量:共用CI跑车比本地机器慢2.3-4.7×, 而一个带有硬码呼叫站点超时的烟雾套房却被红了好几个月,而它的配置"看起来是正确的".
实时通知探测器( R)/runtime(中文(简体) )
记录每个用户可见的通知——DyNX dynamo-notification-card 编号 : dynamo-notifications-area垫口巴
(单位:千美元)red- 编号 : yellow- 编号 : blue- 编号 : green-snackbar, (中文(简体) ), [role=alert] - 此时此刻,它欢迎,所以敬酒
测试结束前自动解职仍在报告内。 它也会快照可见的错误横幅( 有
rawTechnicalLeak 文本的旗帜 Http failure response, (中文(简体) ), /api/, (中文(简体) ), [object Object])并收集页面
console 错误/警告和未发现 pageerror编号.
import { DyE2E_NotificationDetector_Util } from '@futdevpro/dynamo-e2e/runtime';
await DyE2E_NotificationDetector_Util.attach(context); // before the first navigation
// ... the flow ...
const report = await DyE2E_NotificationDetector_Util.collect(page);
expect(report.notifications.filter((n) => n.type === 'error')).toEqual([]);
console.log(DyE2E_NotificationDetector_Util.summarize(report, 'login'));
捕捉在一整页的导航中幸存下来(通过Playwright绑定向Node报告). 页面侧码
是普通 Java 脚本,所以没有 __name shim是需要根据 tsx / 兴起. collect() 丢入不包含的上下文
attach() ——空报告否则会被理解为"没有通知".
登录流程通知扫描( I)/runtime +CLI) 组合键
建于探测器上: 打开许多工程的登录页, 以 WRONG 密码提交( 所以是 EROR 分支) 在没有测试账户的情况下进行测量),并打印每个项目的一个矩阵行——通知 ——错误/警告 ——横幅 —— 模式对话框 : 原始技术泄漏 : 控制台出错 。 框架层面的缺陷仅在许多项目出现时才会出现 同样的测量方法.
dye2e notification-sweep --targets TEST-TARGETS.md --json sweep.json # or a JSON [{ key, loginUrl | baseUrl }]
dye2e notification-sweep --targets targets.json --only a,b --fail-on-leak # exit 1 on a raw technical leak
const outcomes = await DyE2E_NotificationSweep_Util.sweep(browser, targets, { settleMs: 5000 });
console.log(DyE2E_NotificationSweep_Util.matrix(outcomes.map((o) => o.row)));
编码中的警卫,而不是文件中的警卫:探测器地址必须在保留域上(example.com, (中文(简体) ), *.test, (中文(简体) ), *.invalid . ) (中文(简体) )
或用一个你宣布 ownDomains – 在打开一页前投出其它任何内容; 表格只提交于
测试主机( e)test.*, (中文(简体) ), *.test, (中文(简体) ), localhost ...,或者说 allowSubmitHosts——其他东西被装入,但没有提交,
和行说. real: true 编号 : --real 用途 E2E_PERSISTENT_USER_EMAIL 编号 : _PASSWORD没有他们,排说
它掉回了探测器。 Modal对话框(一个"不是生产系统"的通知,一个错误对话框)被记录——
文本 + 漏出旗—— 在关闭前; 非模式 cookie 栏被留下.
详细的游戏预设合同 : __documentations/game-preset.md。 。 。 .