@futdevpro/fdp-e2e-helpers
v1.15.41
Published
Shared E2E test helpers for FDP-stack apps. First util: E2E_HardDelete_Util. Stateless utility-collection — NOT a framework.
Readme
@futdevpro/fdp-e2e-helpers
Shared E2E test helpers for FDP-stack apps. Stateless utility-collection — NOT a framework.
Scope
This package extracts cross-project E2E helper utilities that wire into existing
@futdevpro/fdp-templates + @futdevpro/fdp-templates-nts server-side endpoints.
The server-half (e.g. validateE2EKey, hardDeleteUserBySystem,
hardDeleteUserDataCollection) is already shipped; this package fills the
client-half so individual project e2e/ folders don't reinvent the wheel.
First util: E2E_HardDelete_Util
Calls the FDP auth-service cascading hard-delete endpoint:
import { E2E_HardDelete_Util } from '@futdevpro/fdp-e2e-helpers';
await E2E_HardDelete_Util.deleteAccount({
authServiceUrl: 'http://localhost:48005',
accountId: '<account-id>',
e2eKey: process.env.E2E_HARD_DELETE_KEY!,
timeoutMs: 30000, // optional, default 30s
});The endpoint hit is DELETE /auth-api/auth-redirect/e2e/user/hard-delete —
server-side this triggers cascading delete across all registered services
(spec REQ-USER-004 in LIVE-projects/fdp-e2e-full/__specifications/sections/
user-management.md).
Production safety (defense-in-depth)
- Client-side guard: hostnames containing
productionor word-boundedprodthrowFDP-E2E-HD-PROD-GUARDBEFORE any HTTP call. - Server-side guard: the FDPNTS endpoint enforces
env in {local, test}and validates theX-E2E-Keyheader againstE2E_HARD_DELETE_KEYenv. - Server env loader:
global-env-settings.util.tsTHROWS ifE2E_HARD_DELETE_KEYis set on a production environment.
FDP_CWV_Collector_Util — Core Web Vitals diagnostics
Scripted, synthetic Core Web Vitals (LCP / INP / CLS + attribution) measurement on
top of Playwright. The reusable Dynamo-level primitive behind the E2E "step-0" CWV
diagnostic. Canonical guide: documentations/guidelines/development/cwv-diagnostics.md.
import { FDP_CWV_Collector_Util } from '@futdevpro/fdp-e2e-helpers';
// In an e2e spec (consumer supplies the web-vitals IIFE source as a string):
const result = await FDP_CWV_Collector_Util.collect(page, {
routes: [{ path: '/main/home', label: 'Home', interact: async p => { /* real click for INP */ } }],
webVitalsScript, // see resolve note below
componentPrefixes: ['s-', 'ad-', 'm1-', 'app-'], // attribution target → component-level
budgets: { lcpMs: 2500, inpMs: 200, cls: 0.1 }, // report-only (warn, not fail)
});
FDP_CWV_Collector_Util.writeResult(result, 'cwv-result.json');
// pipeline emits the [CDP_STEP_RESULT] marker AFTER playwright:
// node -e "require('@futdevpro/fdp-e2e-helpers').FDP_CWV_Collector_Util.emitMarkerFromFile('cwv-result.json')"API: collect / writeResult / emitMarkerFromFile / printStepResultMarker /
buildSummaryLine + pure rate / evaluateBudgets / summarizeWorst / buildRouteResult.
Why the consumer supplies webVitalsScript as a string — this package deliberately
does NOT import web-vitals (keeps it dependency-light + no require() in shipped code).
The consuming e2e project reads the IIFE bundle and passes it in.
⚠ web-vitals v4
exports-map gotcha (KÖTELEZŐ olvasni): the v4 package has a STRICTexportsmap — it does NOT export./dist/*subpaths NOR./package.json, sorequire.resolve('web-vitals/dist/...')ANDrequire.resolve('web-vitals/package.json')both throwERR_PACKAGE_PATH_NOT_EXPORTED. Resolve an ALLOWED entry point instead and walk to itsdist/:const distDir = path.dirname(require.resolve('web-vitals/attribution')); const src = fs.readFileSync(path.join(distDir, 'web-vitals.attribution.iife.js'), 'utf-8');
⚠ Playwright
addInitScript+ IIFEvargotcha: the web-vitals IIFE doesvar webVitals=..., butaddInitScriptwraps the script in a function scope, so the top-levelvarnever reacheswindow. The collector handles this internally by appending;self.webVitals=self.webVitals||webVitals;to the injected script.
INP note: synthetic/headless INP is best-effort (Event Timing API unreliable without
real user input) → often undefined. Trustworthy INP comes from the RUM phase. LCP/CLS/FCP/TTFB
are reliable.
@playwright/test is a peer dependency (the consuming e2e project already has it).
Why stateless *_Util (not singleton service)
- Multi-worker parallel-test-safe — no shared instance state across Playwright workers.
- Pure function call signature, no setup/teardown.
- Singletons (e.g.
E2E_UserManagerService) come later when stateful cleanup tracking is needed.
Status
| Layer | Status |
|---|---|
| E2E_HardDelete_Util (account cascade) | ✅ v01.15.0 |
| FDP_CWV_Collector_Util (Core Web Vitals diag) | ✅ v01.15.14 — live-verified (organizer, 2026-06-01) |
| E2E_UserManagerService lift-up | ⏳ next PR |
| E2E_ConfigService lift-up | ⏳ later |
| E2E_UiHelperService lift-up | ⏳ later (Playwright dep boundary TBD) |
See _specifications/BACKLOG.md for the full roadmap.
