@futdevpro/dynamo-e2e

中文文档
1.18.49发布于 2026/11/15MITTypeScriptESM + CJS近 30 天下载 3044

End-to-end testing engine for the Dynamo + FDP ecosystem — auto-generated form-coverage tests, viewport audit matrix, CWV diagnostics. Settings-POJO-first.

原始使用文档
文档目录8 节
  1. What
  2. Status
  3. Install
  4. Quick start
  5. Sub-exports
  6. Playwright preset — CI timeouts and the failure budget
  7. Live notification detector ( /runtime )
  8. Login-flow notification sweep ( /runtime + CLI)

@futdevpro/dynamo-e2e

npm coverage specs hyperplan

End-to-end testing engine for the Dynamo + FDP ecosystem.

What

A Dynamo bedrock-package that turns Forms v2 Settings POJOs into Playwright test suites — auto-generated, typed, overridable, diffable.

Three layers in one package:

  1. Form-coverage — every field-type has a pre-curated positive + negative input matrix; the generator emits ~20-50 tests per form from a single Settings POJO.
  2. Viewport matrix (Wave-2) — auto-fan-out tests over 7 standard viewports + overflow/touch-target a11y detection.
  3. Core Web Vitals diagnostics (Wave-3) — synthetic LCP / CLS / INP / TTFB measurement + percentile aggregation + attribution.

Status

Wave-1..4 + MP-10/MP-11 (2026-06-10) — Layer A contracts, Layer B generators (form-suite + viewport-suite + CWV-suite), Layer C runtime fixtures + page-objects, Overseer CICD pipeline registered, 75%+ test coverage gate active (statements 97.84%, branches 87.13%, functions 98.55%, lines 97.84%). 104 specs, 0 failures.

Plan-net: __documentations/plans/dynamo-e2e-foundation/HYPERPLAN.md (11 MPs, 4900+ LOC planning).

Install

pnpm add -D @futdevpro/dynamo-e2e @playwright/test

@futdevpro/fsm-dynamo is a peer-dep — bring your own (or no Settings POJO source if you only use the runtime presets).

Quick start

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`

Sub-exports

  • @futdevpro/dynamo-e2e/contracts — POJO types
  • @futdevpro/dynamo-e2e/generators — Node-only emission engine
  • @futdevpro/dynamo-e2e/runtime — Playwright fixtures + page-objects (Wave-4) + the live notification detector (DyE2E_NotificationDetector_Util, see below)
  • @futdevpro/dynamo-e2e/presets — pre-built suites + DyE2E_getPlaywrightConfig / DyE2E_getGlobalSetup playwright-config factory (fleet e2e-config SSOT)
  • @futdevpro/dynamo-e2e/game — capability-gated deterministic game seam, failure artifacts and bidirectional journey-catalog validation
  • @futdevpro/dynamo-e2e/cwv — Core Web Vitals (Wave-3)
  • @futdevpro/dynamo-e2e/ui-check — scripted, per-error-class UI detectors that return VERDICTS (a control that does nothing, two-level scrolling, a checkbox that does not toggle); a growing default list, coded waivers, a safety guard for pressing controls. Catalog + proofs: __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 — the visual regression gate: closes the TEST warning and the cookie bar through the app (DyE2E_BlockingOverlays_Util.prepareStorageState, once per language), then checks each key page in HU + EN at 1440 + 390 (DyE2E_VisualGate_Util.cases): red when an overlay still covers it, it shows (almost) nothing, it is wider than the screen, or it differs from the committed baseline (toHaveScreenshot). The look (DyE2E_VisualGateLook_Util, BFR-FUTDEVPRO-081): the "not found" screen, an empty content area, green / cyan / blue instead of the neutral grey, a text off the screen, a raw icon word, a placeholder; with a referenceUrl, the heading and paragraph sizes of production on the pages marked isOnReference. With testInfo, the screenshots (TEST and production) go into the report.
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 preset — CI timeouts and the failure budget

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)
});

⚠️ A call-site { timeout } overrides the config. expect(x).toBeVisible({ timeout: 15_000 }) ignores the preset's expect.timeout (and its ciTimeoutFactor). Scale those values with DyE2E_ciTimeout(15_000) — unchanged locally, × E2E_CI_TIMEOUT_FACTOR (or 3) under CI. Measured: a shared CI runner was 2.3–4.7× slower than a local machine, and a smoke suite with hard-coded call-site timeouts stayed red for months while its config "looked right".

Live notification detector (/runtime)

Records every user-visible notification — DyNX dynamo-notification-card / dynamo-notifications-area, mat-snackbar (red- / yellow- / blue- / green-snackbar), [role=alert] — at the moment it APPEARS, so a toast that auto-dismissed before the end of the test is still in the report. It also snapshots the visible error banners (with a rawTechnicalLeak flag for texts like Http failure response, /api/, [object Object]) and collects the page's console errors/warnings and uncaught pageerrors.

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'));

Captures survive a full-page navigation (they are reported to Node through a Playwright binding). The page-side code is plain JavaScript, so no __name shim is needed under tsx / esbuild. collect() throws on a context without attach() — an empty report would otherwise read as "no notifications".

Login-flow notification sweep (/runtime + CLI)

Built on the detector: opens the login page of many projects, submits it with a WRONG password (so the ERROR branch is measured without a test account) and prints one matrix row per project — notifications · error/warning · banners · modal dialogs · raw-technical leaks · console errors. Framework-level defects show up only when many projects are measured the same way.

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)));

Guards in code, not in docs: the probe address must be on a reserved domain (example.com, *.test, *.invalid …) or on one you declare with ownDomains — anything else throws before a page is opened; the form is submitted only on a test host (test.*, *.test, localhost …, or allowSubmitHosts) — anything else is loaded but NOT submitted, and the row says so. real: true / --real uses E2E_PERSISTENT_USER_EMAIL / _PASSWORD; without them the row says it fell back to the probe. Modal dialogs (a "not the production system" notice, an error dialog) are RECORDED — text + leak flag — before they are closed; a non-modal cookie bar is left alone.

Detailed game-preset contract: __documentations/game-preset.md.

版本与发布记录

@futdevpro/dynamo-e2e 共发布 57 个版本,首次发布于 2026/06/10;过去 12 个月发布了 57 个版本。

版本发布日期距今
1.18.49latest2026/11/15今天
1.18.482026/11/15今天
1.18.472026/11/132 天前
1.18.462026/11/132 天前
1.18.452026/11/123 天前
1.18.432026/11/124 天前

关于 @futdevpro/dynamo-e2e 的常见问题

@futdevpro/dynamo-e2e 是什么?

End-to-end testing engine for the Dynamo + FDP ecosystem — auto-generated form-coverage tests, viewport audit matrix, CWV diagnostics. Settings-POJO-first.

如何安装 @futdevpro/dynamo-e2e?

在项目目录运行 npm install @futdevpro/dynamo-e2e,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 dye2e,可以用 npx dye2e 直接运行。

@futdevpro/dynamo-e2e 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@futdevpro/dynamo-e2e 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@futdevpro/dynamo-e2e 可以商用吗?

@futdevpro/dynamo-e2e 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@futdevpro/dynamo-e2e 的下载量有多少?

根据 npm 官方下载统计,@futdevpro/dynamo-e2e 在 2026/10/16 – 2026/11/14 这 30 天内被下载 3,044 次,日均约 101 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@futdevpro/dynamo-e2e 还在维护吗?

最新版本 1.18.49 发布于 2026/11/15(今天);至今共发布 57 个版本,其中过去 12 个月发布了 57 个;首次发布于 2026/06/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。