@futdevpro/dynamo-e2e 1.18.39 → 1.18.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +9 -2
  3. package/build/_modules/visual-gate/_collections/visual-gate-defaults.const.d.ts +10 -0
  4. package/build/_modules/visual-gate/_collections/visual-gate-defaults.const.d.ts.map +1 -1
  5. package/build/_modules/visual-gate/_collections/visual-gate-defaults.const.js +21 -0
  6. package/build/_modules/visual-gate/_collections/visual-gate-defaults.const.js.map +1 -1
  7. package/build/_modules/visual-gate/_collections/visual-gate-look.util.d.ts +51 -0
  8. package/build/_modules/visual-gate/_collections/visual-gate-look.util.d.ts.map +1 -0
  9. package/build/_modules/visual-gate/_collections/visual-gate-look.util.js +241 -0
  10. package/build/_modules/visual-gate/_collections/visual-gate-look.util.js.map +1 -0
  11. package/build/_modules/visual-gate/_collections/visual-gate.util.d.ts +25 -17
  12. package/build/_modules/visual-gate/_collections/visual-gate.util.d.ts.map +1 -1
  13. package/build/_modules/visual-gate/_collections/visual-gate.util.js +66 -10
  14. package/build/_modules/visual-gate/_collections/visual-gate.util.js.map +1 -1
  15. package/build/_modules/visual-gate/_models/visual-gate-finding.interface.d.ts +7 -2
  16. package/build/_modules/visual-gate/_models/visual-gate-finding.interface.d.ts.map +1 -1
  17. package/build/_modules/visual-gate/_models/visual-gate-look-options.interface.d.ts +33 -0
  18. package/build/_modules/visual-gate/_models/visual-gate-look-options.interface.d.ts.map +1 -0
  19. package/build/_modules/visual-gate/_models/visual-gate-look-options.interface.js +3 -0
  20. package/build/_modules/visual-gate/_models/visual-gate-look-options.interface.js.map +1 -0
  21. package/build/_modules/visual-gate/_models/visual-gate-options.interface.d.ts +32 -0
  22. package/build/_modules/visual-gate/_models/visual-gate-options.interface.d.ts.map +1 -0
  23. package/build/_modules/visual-gate/_models/visual-gate-options.interface.js +3 -0
  24. package/build/_modules/visual-gate/_models/visual-gate-options.interface.js.map +1 -0
  25. package/build/_modules/visual-gate/_models/visual-gate-page.interface.d.ts +5 -0
  26. package/build/_modules/visual-gate/_models/visual-gate-page.interface.d.ts.map +1 -1
  27. package/build/_modules/visual-gate/index.d.ts +5 -1
  28. package/build/_modules/visual-gate/index.d.ts.map +1 -1
  29. package/build/_modules/visual-gate/index.js +5 -1
  30. package/build/_modules/visual-gate/index.js.map +1 -1
  31. package/build/index.js +1 -1
  32. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,33 @@
3
3
  Minden release a `dynamo-e2e-foundation` HYPERPLAN MP-N ütemezést követi.
4
4
  Verzióformátum: `MM.mm.p` (két-számjegyes major-minor, Dynamo-konvenció).
5
5
 
6
+ ## [01.18.40] — 2026-11-04 — `/visual-gate`: the look — neutral grey, text, production font sizes (BFR-FUTDEVPRO-081)
7
+
8
+ - **Why** (owner, 2026-11-02 21:43: "we are going backwards while we prepare for the release"; futdevpro
9
+ `BFR-FUTDEVPRO-081`): four defects the user saw reached the futdevpro TEST with no test failing — blue / green frames
10
+ instead of the neutral grey, a page "not found", tiles fallen apart, an admin list in one line. futdevpro's own gate
11
+ (`e2e/tests/ui-check/visual-regression-gate-feature.spec.ts`, 20 red on TEST 839, green on the fixed build) is now a
12
+ shared, parameterised tool: one call per product, its key pages, its content area, its reference URL, its waivers.
13
+ - **`DyE2E_VisualGateLook_Util`** (`DyE2E_VisualGate_Util.inspect` runs it): ① `not-found` (the product's "not found"
14
+ screen, `notFoundSelector`) and `content-empty` (the content area missing or lower than 150 px, `contentSelector`);
15
+ ③ `loud-color` — a box of the content area with a saturated (> 0.35) frame, background or gradient in the green …
16
+ blue range (80–260°), in any colour space (Tailwind 4 reports `oklch`: judged by its rendered sRGB pixel); red and
17
+ amber carry meaning and stay; buttons, fields, icons, Material and media are the shared
18
+ components and are skipped (`neutralSkipSelector`), a product's own decoration can be allowed
19
+ (`gradientAllowSelector`); ⑤ `text-off-screen` (a visible text beyond the screen edge even when an `overflow:
20
+ hidden` parent hides the scroll; a honeypot far off the screen is not), ⑥ `raw-icon-word` (a `mat-icon` showing
21
+ its ligature word), ⑦ `placeholder-text` ("coming soon", "hamarosan", "lorem ipsum", `TODO`, `TBD`). Every check can
22
+ be turned off or tuned; the defaults are futdevpro's measured values.
23
+ - **④ the production font sizes**: `assertPage(page, gateCase, { referenceUrl })` opens the page marked
24
+ `isOnReference` on production (read only, same screen size and language) and fails when a heading or paragraph size
25
+ of production is gone (`compareFontSizes`; a new size only on TEST is not a finding).
26
+ - **The report**: with `testInfo`, the full-page screenshot of the page (and of the reference) is attached before the
27
+ verdict, so a human sees it even when the case is red. `isScreenshotComparisonSkipped` turns the pixel comparison
28
+ off (a baseline taken on a developer machine renders the fonts differently; futdevpro's choice).
29
+ - Compatible: without the new options a 01.18.39 call checks the same, plus the neutral look and the text on the whole
30
+ page.
31
+ - 6 specs (4 on a real Chromium, fixture pages with each defect beside its fixed twin), 4 mutants killed; 626 / 0.
32
+
6
33
  ## [01.18.39] — 2026-11-02 — `/visual-gate`: the visual regression gate, first slice (R1-72 d)
7
34
 
8
35
  - **Why** (owner, 2026-11-02 21:39: the credit service's login "badly out of shape", "a review tool is needed";
package/README.md CHANGED
@@ -87,7 +87,11 @@ DyE2E_UICheckRunner_Util.assertClean(report); // throws with every finding's mea
87
87
  - `@futdevpro/dynamo-e2e/visual-gate` — the visual regression gate: closes the TEST warning and the cookie bar through
88
88
  the app (`DyE2E_BlockingOverlays_Util.prepareStorageState`, once per language), then checks each key page in
89
89
  HU + EN at 1440 + 390 (`DyE2E_VisualGate_Util.cases`): red when an overlay still covers it, it shows (almost)
90
- nothing, it is wider than the screen, or it differs from the committed baseline (`toHaveScreenshot`).
90
+ nothing, it is wider than the screen, or it differs from the committed baseline (`toHaveScreenshot`). The look
91
+ (`DyE2E_VisualGateLook_Util`, BFR-FUTDEVPRO-081): the "not found" screen, an empty content area, green / cyan / blue
92
+ instead of the neutral grey, a text off the screen, a raw icon word, a placeholder; with a `referenceUrl`, the
93
+ heading and paragraph sizes of production on the pages marked `isOnReference`. With `testInfo`, the screenshots
94
+ (TEST and production) go into the report.
91
95
 
92
96
  ```ts
93
97
  import { DyE2E_BlockingOverlays_Util, DyE2E_VisualGate_Util } from '@futdevpro/dynamo-e2e/visual-gate';
@@ -102,7 +106,10 @@ for (const gateCase of DyE2E_VisualGate_Util.cases({ pages: [ { name: 'login', p
102
106
  const page = await context.newPage();
103
107
 
104
108
  await page.goto(BASE_URL + gateCase.page.path);
105
- await DyE2E_VisualGate_Util.assertPage(page, gateCase); // layout first, then the screenshot comparison
109
+ await DyE2E_VisualGate_Util.assertPage(page, gateCase, {
110
+ contentSelector: 'main', notFoundSelector: 'app-a-block-message-screen',
111
+ referenceUrl: 'https://example.hu', testInfo: test.info(),
112
+ }); // layout + look first, then the production font sizes, then the screenshot comparison
106
113
  });
107
114
  }
108
115
  ```
@@ -9,5 +9,15 @@ export declare const DyE2E_VisualGateDefaults_Const: {
9
9
  overflowTolerancePx: number;
10
10
  maxDiffPixelRatio: number;
11
11
  overlayTimeoutMs: number;
12
+ contentSelector: string;
13
+ minContentHeightPx: number;
14
+ neutralSkipSelector: string;
15
+ loudHueFrom: number;
16
+ loudHueTo: number;
17
+ loudMinSaturation: number;
18
+ loudMinAlpha: number;
19
+ placeholderPattern: string;
20
+ fontSizeTags: string[];
21
+ maxFindingsPerCheck: number;
12
22
  };
13
23
  //# sourceMappingURL=visual-gate-defaults.const.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"visual-gate-defaults.const.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate-defaults.const.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kCAAkC,EAAE,MAAM,2CAA2C,CAAC;AAC/F,OAAO,EAAE,kCAAkC,EAAE,MAAM,2CAA2C,CAAC;AAE/F,wEAAwE;AACxE,eAAO,MAAM,8BAA8B,EAAE;IAC3C,SAAS,EAAE,kCAAkC,EAAE,CAAC;IAChD,SAAS,EAAE,kCAAkC,EAAE,CAAC;IAChD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;CAuB1B,CAAC"}
1
+ {"version":3,"file":"visual-gate-defaults.const.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate-defaults.const.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kCAAkC,EAAE,MAAM,2CAA2C,CAAC;AAC/F,OAAO,EAAE,kCAAkC,EAAE,MAAM,2CAA2C,CAAC;AAE/F,wEAAwE;AACxE,eAAO,MAAM,8BAA8B,EAAE;IAC3C,SAAS,EAAE,kCAAkC,EAAE,CAAC;IAChD,SAAS,EAAE,kCAAkC,EAAE,CAAC;IAChD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CA4C7B,CAAC"}
@@ -24,5 +24,26 @@ exports.DyE2E_VisualGateDefaults_Const = {
24
24
  * renders behind the app's language map or a 4 s fail-open, so a slow runner needs well over 4 s.
25
25
  */
26
26
  overlayTimeoutMs: 15_000,
27
+ /** The content area when the product names none: the whole page. */
28
+ contentSelector: 'body',
29
+ /** A content area lower than this is empty (futdevpro's gate, BFR-FUTDEVPRO-081). */
30
+ minContentHeightPx: 150,
31
+ /**
32
+ * The shared components (their colours are the shared design's): buttons, fields, icons, Material, the notification
33
+ * area, media (futdevpro's gate, BFR-FUTDEVPRO-081).
34
+ */
35
+ neutralSkipSelector: 'button, dynamo-button-new, input, select, textarea, mat-icon, [class*="mat-"], '
36
+ + '[class*="mdc-"], dynamo-notifications-area, img, svg, video, canvas',
37
+ /** Green (80°) … blue (260°): the systems are neutral grey; red (an error) and amber (a to-do) carry meaning. */
38
+ loudHueFrom: 80,
39
+ loudHueTo: 260,
40
+ loudMinSaturation: 0.35,
41
+ loudMinAlpha: 0.15,
42
+ /** A finished page shows none of these (owner, 2026-11-02 22:27: "placeholders … as closed, finished items"). */
43
+ placeholderPattern: '(coming soon|hamarosan|lorem ipsum|\\bTODO\\b|\\bTBD\\b)',
44
+ /** The tags whose font sizes are compared with the reference. */
45
+ fontSizeTags: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'],
46
+ /** At most this many findings of one check are listed (the rest is the same defect). */
47
+ maxFindingsPerCheck: 12,
27
48
  };
28
49
  //# sourceMappingURL=visual-gate-defaults.const.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"visual-gate-defaults.const.js","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate-defaults.const.ts"],"names":[],"mappings":";;;AAGA,wEAAwE;AAC3D,QAAA,8BAA8B,GAQvC;IACF,SAAS,EAAE;QACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QAC7C,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;KAC5C;IACD,SAAS,EAAE;QACT,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAC/B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;KAChC;IACD,4GAA4G;IAC5G,oBAAoB,EAAE,EAAE;IACxB,+DAA+D;IAC/D,sBAAsB,EAAE,CAAC;IACzB,yGAAyG;IACzG,mBAAmB,EAAE,CAAC;IACtB,uGAAuG;IACvG,iBAAiB,EAAE,IAAI;IACvB;;;OAGG;IACH,gBAAgB,EAAE,MAAM;CACzB,CAAC"}
1
+ {"version":3,"file":"visual-gate-defaults.const.js","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate-defaults.const.ts"],"names":[],"mappings":";;;AAGA,wEAAwE;AAC3D,QAAA,8BAA8B,GAkBvC;IACF,SAAS,EAAE;QACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QAC7C,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;KAC5C;IACD,SAAS,EAAE;QACT,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAC/B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;KAChC;IACD,4GAA4G;IAC5G,oBAAoB,EAAE,EAAE;IACxB,+DAA+D;IAC/D,sBAAsB,EAAE,CAAC;IACzB,yGAAyG;IACzG,mBAAmB,EAAE,CAAC;IACtB,uGAAuG;IACvG,iBAAiB,EAAE,IAAI;IACvB;;;OAGG;IACH,gBAAgB,EAAE,MAAM;IACxB,oEAAoE;IACpE,eAAe,EAAE,MAAM;IACvB,qFAAqF;IACrF,kBAAkB,EAAE,GAAG;IACvB;;;OAGG;IACH,mBAAmB,EAAE,iFAAiF;UAClG,qEAAqE;IACzE,iHAAiH;IACjH,WAAW,EAAE,EAAE;IACf,SAAS,EAAE,GAAG;IACd,iBAAiB,EAAE,IAAI;IACvB,YAAY,EAAE,IAAI;IAClB,iHAAiH;IACjH,kBAAkB,EAAE,0DAA0D;IAC9E,iEAAiE;IACjE,YAAY,EAAE,CAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAE;IACzD,wFAAwF;IACxF,mBAAmB,EAAE,EAAE;CACxB,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { Page } from '@playwright/test';
2
+ import { DyE2E_VisualGateFinding_Interface } from '../_models/visual-gate-finding.interface';
3
+ import { DyE2E_VisualGateLookOptions_Interface } from '../_models/visual-gate-look-options.interface';
4
+ /** The font sizes per tag (`h1` … `p`), sorted and distinct, as computed (`16px`). */
5
+ export type DyE2E_VisualGateFontSizes_Type = Record<string, string[]>;
6
+ /**
7
+ * The look checks of the visual gate (BFR-FUTDEVPRO-081, owner 2026-11-02 21:43: "we are going backwards while we
8
+ * prepare for the release"): four defects reached the futdevpro TEST that no functional test noticed — blue / green
9
+ * frames instead of the neutral grey, a page "not found", tiles fallen apart, an admin list in one line.
10
+ *
11
+ * @description Ported from futdevpro's own gate (`e2e/tests/ui-check/visual-regression-gate-feature.spec.ts`, 20 red
12
+ * on TEST 839, green on the fixed build), parameterised: the content area, the "not found" screen, the shared
13
+ * components skipped and the loud hue range are options with futdevpro's values as defaults. Every check is a
14
+ * browser-side script (DOM APIs only), so it measures the rendered page, not the source.
15
+ */
16
+ export declare class DyE2E_VisualGateLook_Util {
17
+ /**
18
+ * ① the content area: `{ isNotFound, isContentMissing, contentHeight }`. Argument: `{ contentSelector,
19
+ * notFoundSelector }`.
20
+ */
21
+ static readonly contentScript: string;
22
+ /**
23
+ * ③ the neutral look: the boxes of the content area with a saturated frame, background or gradient in the loud
24
+ * hue range. Argument: the resolved look options. Returns `<tag.class> frame|background|gradient <colour>` lines.
25
+ */
26
+ static readonly loudColorsScript: string;
27
+ /**
28
+ * ⑤ ⑥ ⑦ on the whole page: a visible text off the screen, an icon showing its ligature word, a placeholder text.
29
+ * Argument: `{ placeholderPattern, maxFindings }`. Returns `{ kind, message }` findings.
30
+ */
31
+ static readonly textProblemsScript: string;
32
+ /** ④ the font sizes of the headings and paragraphs of the content area. Argument: `{ contentSelector, tags }`. */
33
+ static readonly fontSizesScript: string;
34
+ /** The options with every default filled in. */
35
+ static resolve(options?: DyE2E_VisualGateLookOptions_Interface): Required<DyE2E_VisualGateLookOptions_Interface>;
36
+ /**
37
+ * The look checks of one page: ① the "not found" screen and the content area (when the product names them),
38
+ * ③ the neutral look, ⑤ ⑥ ⑦ the text.
39
+ *
40
+ * @returns the findings; empty when the page looks as it should
41
+ */
42
+ static inspect(page: Page, options?: DyE2E_VisualGateLookOptions_Interface): Promise<DyE2E_VisualGateFinding_Interface[]>;
43
+ /** ④ the font sizes of the headings and paragraphs in the content area (after the fonts are loaded). */
44
+ static measureFontSizes(page: Page, contentSelector?: string): Promise<DyE2E_VisualGateFontSizes_Type>;
45
+ /**
46
+ * ④ judges the font sizes against the reference: a size the reference uses for a tag, missing here, is a finding
47
+ * ("the old font size dropped"). A size only here is not (a new heading may have its own).
48
+ */
49
+ static compareFontSizes(ours: DyE2E_VisualGateFontSizes_Type, reference: DyE2E_VisualGateFontSizes_Type): DyE2E_VisualGateFinding_Interface[];
50
+ }
51
+ //# sourceMappingURL=visual-gate-look.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-gate-look.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate-look.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,OAAO,EAAE,iCAAiC,EAAE,MAAM,0CAA0C,CAAC;AAC7F,OAAO,EAAE,qCAAqC,EAAE,MAAM,+CAA+C,CAAC;AAGtG,sFAAsF;AACtF,MAAM,MAAM,8BAA8B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAEtE;;;;;;;;;GASG;AACH,qBAAa,yBAAyB;IAEpC;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAQlC;IAEH;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAuErC;IAEH;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAuCvC;IAEH,kHAAkH;IAClH,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAUpC;IAEH,gDAAgD;IAChD,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,qCAA0C,GAAG,QAAQ,CAAC,qCAAqC,CAAC;IAkBpH;;;;;OAKG;WACU,OAAO,CAClB,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,qCAA0C,GAClD,OAAO,CAAC,iCAAiC,EAAE,CAAC;IAqC/C,wGAAwG;WAC3F,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC;IAS5G;;;OAGG;IACH,MAAM,CAAC,gBAAgB,CACrB,IAAI,EAAE,8BAA8B,EACpC,SAAS,EAAE,8BAA8B,GACxC,iCAAiC,EAAE;CAiBvC"}
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DyE2E_VisualGateLook_Util = void 0;
4
+ const visual_gate_defaults_const_1 = require("./visual-gate-defaults.const");
5
+ /**
6
+ * The look checks of the visual gate (BFR-FUTDEVPRO-081, owner 2026-11-02 21:43: "we are going backwards while we
7
+ * prepare for the release"): four defects reached the futdevpro TEST that no functional test noticed — blue / green
8
+ * frames instead of the neutral grey, a page "not found", tiles fallen apart, an admin list in one line.
9
+ *
10
+ * @description Ported from futdevpro's own gate (`e2e/tests/ui-check/visual-regression-gate-feature.spec.ts`, 20 red
11
+ * on TEST 839, green on the fixed build), parameterised: the content area, the "not found" screen, the shared
12
+ * components skipped and the loud hue range are options with futdevpro's values as defaults. Every check is a
13
+ * browser-side script (DOM APIs only), so it measures the rendered page, not the source.
14
+ */
15
+ class DyE2E_VisualGateLook_Util {
16
+ /**
17
+ * ① the content area: `{ isNotFound, isContentMissing, contentHeight }`. Argument: `{ contentSelector,
18
+ * notFoundSelector }`.
19
+ */
20
+ static contentScript = `(set) => {
21
+ const notFound = set.notFoundSelector ? document.querySelector(set.notFoundSelector) : null;
22
+ const content = document.querySelector(set.contentSelector);
23
+ return {
24
+ isNotFound: !!notFound && notFound.getBoundingClientRect().height > 0,
25
+ isContentMissing: !content,
26
+ contentHeight: content ? Math.round(content.getBoundingClientRect().height) : 0,
27
+ };
28
+ }`;
29
+ /**
30
+ * ③ the neutral look: the boxes of the content area with a saturated frame, background or gradient in the loud
31
+ * hue range. Argument: the resolved look options. Returns `<tag.class> frame|background|gradient <colour>` lines.
32
+ */
33
+ static loudColorsScript = `(set) => {
34
+ const root = document.querySelector(set.contentSelector);
35
+ const canvas = document.createElement('canvas');
36
+ canvas.width = 1;
37
+ canvas.height = 1;
38
+ const ctx = canvas.getContext('2d', { willReadFrequently: true });
39
+ // rgb() / rgba() directly; any other colour space (Tailwind 4 reports oklch) by its rendered sRGB pixel
40
+ const toRgba = (color) => {
41
+ const match = color.match(/^rgba?\\(([^)]+)\\)$/);
42
+ if (match) {
43
+ const parts = match[1].split(/[ ,/]+/).filter(Boolean).map(Number);
44
+ return [ parts[0], parts[1], parts[2], parts.length > 3 ? parts[3] : 1 ];
45
+ }
46
+ if (!ctx) { return null; }
47
+ ctx.clearRect(0, 0, 1, 1);
48
+ ctx.fillStyle = 'rgba(0, 0, 0, 0)';
49
+ ctx.fillStyle = color;
50
+ ctx.fillRect(0, 0, 1, 1);
51
+ const pixel = ctx.getImageData(0, 0, 1, 1).data;
52
+ return [ pixel[0], pixel[1], pixel[2], pixel[3] / 255 ];
53
+ };
54
+ const parse = (color) => {
55
+ const rgba = toRgba(color);
56
+ if (!rgba) { return null; }
57
+ const r = rgba[0] / 255;
58
+ const g = rgba[1] / 255;
59
+ const b = rgba[2] / 255;
60
+ const a = rgba[3];
61
+ const max = Math.max(r, g, b);
62
+ const min = Math.min(r, g, b);
63
+ const l = (max + min) / 2;
64
+ const d = max - min;
65
+ const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
66
+ let h = 0;
67
+ if (d !== 0) {
68
+ h = max === r ? 60 * (((g - b) / d) % 6) : max === g ? 60 * ((b - r) / d + 2) : 60 * ((r - g) / d + 4);
69
+ }
70
+ return { h: (h + 360) % 360, s: s, a: a };
71
+ };
72
+ const isLoud = (color) => {
73
+ const c = parse(color);
74
+ return !!c && c.a > set.loudMinAlpha && c.s > set.loudMinSaturation && c.h >= set.loudHueFrom
75
+ && c.h <= set.loudHueTo;
76
+ };
77
+ const found = [];
78
+ if (!root) { return found; }
79
+ for (const el of [ root ].concat(Array.from(root.querySelectorAll('*')))) {
80
+ if (el.closest(set.neutralSkipSelector)) { continue; }
81
+ const style = getComputedStyle(el);
82
+ const rect = el.getBoundingClientRect();
83
+ if (rect.width < 4 || rect.height < 4 || style.visibility === 'hidden' || style.display === 'none') {
84
+ continue;
85
+ }
86
+ const cls = typeof el.className === 'string' ? el.className.trim().split(/\\s+/).slice(0, 2).join('.') : '';
87
+ const name = el.tagName.toLowerCase() + (cls ? '.' + cls : '');
88
+ if (parseFloat(style.borderTopWidth) > 0 && style.borderTopStyle !== 'none' && isLoud(style.borderTopColor)) {
89
+ found.push(name + ' frame ' + style.borderTopColor);
90
+ }
91
+ if (isLoud(style.backgroundColor)) {
92
+ found.push(name + ' background ' + style.backgroundColor);
93
+ }
94
+ const isGradientAllowed = !!set.gradientAllowSelector && !!el.closest(set.gradientAllowSelector);
95
+ if (style.backgroundImage && style.backgroundImage !== 'none' && !isGradientAllowed) {
96
+ const colors = style.backgroundImage.match(/(?:rgba?|hsla?|oklch|oklab|lab|lch|color)\\([^)]+\\)/g) || [];
97
+ const loud = colors.find((color) => isLoud(color));
98
+ if (loud) {
99
+ found.push(name + ' gradient ' + loud);
100
+ }
101
+ }
102
+ }
103
+ return Array.from(new Set(found)).slice(0, set.maxFindings);
104
+ }`;
105
+ /**
106
+ * ⑤ ⑥ ⑦ on the whole page: a visible text off the screen, an icon showing its ligature word, a placeholder text.
107
+ * Argument: `{ placeholderPattern, maxFindings }`. Returns `{ kind, message }` findings.
108
+ */
109
+ static textProblemsScript = `(set) => {
110
+ const found = [];
111
+ const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
112
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
113
+ const text = String(node.textContent).trim();
114
+ const parent = node.parentElement;
115
+ if (!text || !parent || parent.closest('mat-icon, [aria-hidden="true"], .cdk-visually-hidden')
116
+ || !parent.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true })) {
117
+ continue;
118
+ }
119
+ const range = document.createRange();
120
+ range.selectNodeContents(node);
121
+ // a honeypot field stands far off the screen on purpose (-10000 px)
122
+ const out = Array.from(range.getClientRects()).find((rect) => rect.width > 0 && rect.left > -5000
123
+ && (rect.left < -1 || rect.right > window.innerWidth + 1));
124
+ if (out) {
125
+ found.push({ kind: 'text-off-screen', message: '"' + text.slice(0, 40) + '" <' + parent.tagName.toLowerCase()
126
+ + '> [' + Math.round(out.left) + ' … ' + Math.round(out.right) + ' px] on a ' + window.innerWidth
127
+ + ' px screen' });
128
+ }
129
+ }
130
+ for (const icon of Array.from(document.querySelectorAll('mat-icon'))) {
131
+ const word = String(icon.textContent).trim();
132
+ if (word.length < 3 || icon.querySelector('svg') || !icon.checkVisibility()) { continue; }
133
+ const range = document.createRange();
134
+ range.selectNodeContents(icon);
135
+ if (range.getBoundingClientRect().width > 2 * parseFloat(getComputedStyle(icon).fontSize)) {
136
+ found.push({ kind: 'raw-icon-word', message: 'the icon shows its word: "' + word + '"' });
137
+ }
138
+ }
139
+ if (set.placeholderPattern) {
140
+ const pattern = new RegExp('[^\\\\n]{0,30}' + set.placeholderPattern + '[^\\\\n]{0,30}', 'gi');
141
+ for (const line of document.body.innerText.match(pattern) || []) {
142
+ found.push({ kind: 'placeholder-text', message: 'visible placeholder: "' + line.trim() + '"' });
143
+ }
144
+ }
145
+ const seen = new Set();
146
+ return found.filter((finding) => !seen.has(finding.message) && seen.add(finding.message))
147
+ .slice(0, set.maxFindings);
148
+ }`;
149
+ /** ④ the font sizes of the headings and paragraphs of the content area. Argument: `{ contentSelector, tags }`. */
150
+ static fontSizesScript = `(set) => {
151
+ const root = document.querySelector(set.contentSelector);
152
+ const out = {};
153
+ for (const tag of set.tags) {
154
+ const sizes = Array.from(root ? root.querySelectorAll(tag) : [])
155
+ .filter((el) => el.getBoundingClientRect().height > 0)
156
+ .map((el) => getComputedStyle(el).fontSize);
157
+ out[tag] = Array.from(new Set(sizes)).sort();
158
+ }
159
+ return out;
160
+ }`;
161
+ /** The options with every default filled in. */
162
+ static resolve(options = {}) {
163
+ return {
164
+ contentSelector: options.contentSelector ?? visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.contentSelector,
165
+ notFoundSelector: options.notFoundSelector ?? '',
166
+ minContentHeightPx: options.minContentHeightPx ?? visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.minContentHeightPx,
167
+ neutralSkipSelector: options.neutralSkipSelector ?? visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.neutralSkipSelector,
168
+ gradientAllowSelector: options.gradientAllowSelector ?? '',
169
+ loudHueFrom: options.loudHueFrom ?? visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.loudHueFrom,
170
+ loudHueTo: options.loudHueTo ?? visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.loudHueTo,
171
+ loudMinSaturation: options.loudMinSaturation ?? visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.loudMinSaturation,
172
+ loudMinAlpha: options.loudMinAlpha ?? visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.loudMinAlpha,
173
+ placeholderPattern: options.placeholderPattern === undefined
174
+ ? visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.placeholderPattern : options.placeholderPattern,
175
+ isNeutralLookSkipped: options.isNeutralLookSkipped ?? false,
176
+ isTextCheckSkipped: options.isTextCheckSkipped ?? false,
177
+ };
178
+ }
179
+ /**
180
+ * The look checks of one page: ① the "not found" screen and the content area (when the product names them),
181
+ * ③ the neutral look, ⑤ ⑥ ⑦ the text.
182
+ *
183
+ * @returns the findings; empty when the page looks as it should
184
+ */
185
+ static async inspect(page, options = {}) {
186
+ const set = this.resolve(options);
187
+ const maxFindings = visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.maxFindingsPerCheck;
188
+ const findings = [];
189
+ const content = await page.evaluate(`(${this.contentScript})(${JSON.stringify(set)})`);
190
+ if (content.isNotFound) {
191
+ findings.push({ kind: 'not-found', message: `the "not found" screen is shown (${set.notFoundSelector})` });
192
+ }
193
+ if (options.contentSelector && content.isContentMissing) {
194
+ findings.push({ kind: 'content-empty', message: `the content area is missing (${set.contentSelector})` });
195
+ }
196
+ else if (options.contentSelector && content.contentHeight < set.minContentHeightPx) {
197
+ findings.push({
198
+ kind: 'content-empty',
199
+ message: `the content area is ${content.contentHeight} px high (at least ${set.minContentHeightPx})`,
200
+ });
201
+ }
202
+ if (!set.isNeutralLookSkipped) {
203
+ const loud = await page.evaluate(`(${this.loudColorsScript})(${JSON.stringify({ ...set, maxFindings: maxFindings })})`);
204
+ findings.push(...loud.map((line) => ({
205
+ kind: 'loud-color', message: `${line} instead of the neutral grey`,
206
+ })));
207
+ }
208
+ if (!set.isTextCheckSkipped) {
209
+ findings.push(...await page.evaluate(`(${this.textProblemsScript})(${JSON.stringify({ placeholderPattern: set.placeholderPattern, maxFindings: maxFindings })})`));
210
+ }
211
+ return findings;
212
+ }
213
+ /** ④ the font sizes of the headings and paragraphs in the content area (after the fonts are loaded). */
214
+ static async measureFontSizes(page, contentSelector) {
215
+ await page.evaluate('document.fonts ? document.fonts.ready.then(() => true) : true');
216
+ return page.evaluate(`(${this.fontSizesScript})(${JSON.stringify({
217
+ contentSelector: contentSelector ?? visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.contentSelector,
218
+ tags: visual_gate_defaults_const_1.DyE2E_VisualGateDefaults_Const.fontSizeTags,
219
+ })})`);
220
+ }
221
+ /**
222
+ * ④ judges the font sizes against the reference: a size the reference uses for a tag, missing here, is a finding
223
+ * ("the old font size dropped"). A size only here is not (a new heading may have its own).
224
+ */
225
+ static compareFontSizes(ours, reference) {
226
+ const findings = [];
227
+ for (const tag of Object.keys(reference)) {
228
+ const own = ours[tag] ?? [];
229
+ const missing = reference[tag].filter((size) => !own.includes(size));
230
+ if (missing.length) {
231
+ findings.push({
232
+ kind: 'font-size-differs',
233
+ message: `<${tag}> on the reference ${reference[tag].join(', ')}, here ${own.join(', ') || 'none'}`,
234
+ });
235
+ }
236
+ }
237
+ return findings;
238
+ }
239
+ }
240
+ exports.DyE2E_VisualGateLook_Util = DyE2E_VisualGateLook_Util;
241
+ //# sourceMappingURL=visual-gate-look.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-gate-look.util.js","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate-look.util.ts"],"names":[],"mappings":"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"}
@@ -3,16 +3,19 @@ import { DyE2E_VisualGateCase_Interface } from '../_models/visual-gate-case.inte
3
3
  import { DyE2E_VisualGateFinding_Interface } from '../_models/visual-gate-finding.interface';
4
4
  import { DyE2E_VisualGateLanguage_Interface } from '../_models/visual-gate-language.interface';
5
5
  import { DyE2E_VisualGateLayout_Interface } from '../_models/visual-gate-layout.interface';
6
+ import { DyE2E_VisualGateOptions_Interface } from '../_models/visual-gate-options.interface';
6
7
  import { DyE2E_VisualGatePage_Interface } from '../_models/visual-gate-page.interface';
7
8
  import { DyE2E_VisualGateViewport_Interface } from '../_models/visual-gate-viewport.interface';
8
9
  /**
9
10
  * The visual regression gate (R1-72 d; owner, 2026-11-02 21:39: the credit login "badly out of shape", "a review tool
10
11
  * is needed"): the key pages, HU + EN, 1440 + 390, red in the CI when a page falls apart or disappears.
11
12
  *
12
- * @description Two checks per page, the cheap and certain one first: (1) a layout check in the browser — the TEST
13
- * warning or the cookie bar still covers the page, the page shows (almost) nothing, or it is wider than the screen;
14
- * (2) a screenshot comparison against the product's committed baseline (Playwright `toHaveScreenshot`; the first run,
15
- * or `--update-snapshots`, writes it).
13
+ * @description The cheap and certain checks first: (1) a layout check in the browser — the TEST warning or the
14
+ * cookie bar still covers the page, the page shows (almost) nothing, or it is wider than the screen; (2) the look
15
+ * (BFR-FUTDEVPRO-081, `DyE2E_VisualGateLook_Util`) — the "not found" screen, an empty content area, green / cyan /
16
+ * blue instead of the neutral grey, a text off the screen, a raw icon word, a placeholder; (3) with a `referenceUrl`,
17
+ * the heading and paragraph sizes of production; then (4) a screenshot comparison against the product's committed
18
+ * baseline (Playwright `toHaveScreenshot`; the first run, or `--update-snapshots`, writes it; it can be skipped).
16
19
  *
17
20
  * ```ts
18
21
  * import { DyE2E_BlockingOverlays_Util, DyE2E_VisualGate_Util } from '@futdevpro/dynamo-e2e/visual-gate';
@@ -27,7 +30,9 @@ import { DyE2E_VisualGateViewport_Interface } from '../_models/visual-gate-viewp
27
30
  * const page = await context.newPage();
28
31
  *
29
32
  * await page.goto(BASE_URL + gateCase.page.path);
30
- * await DyE2E_VisualGate_Util.assertPage(page, gateCase);
33
+ * await DyE2E_VisualGate_Util.assertPage(page, gateCase, {
34
+ * contentSelector: 'main', referenceUrl: 'https://example.hu', testInfo: test.info(),
35
+ * });
31
36
  * });
32
37
  * }
33
38
  * ```
@@ -57,20 +62,23 @@ export declare class DyE2E_VisualGate_Util {
57
62
  minVisibleElementCount?: number;
58
63
  overflowTolerancePx?: number;
59
64
  }): DyE2E_VisualGateFinding_Interface[];
60
- /** The cheap checks of one page: overlays still covering it + the layout. */
61
- static inspect(page: Page, limits?: {
62
- minVisibleTextLength?: number;
63
- minVisibleElementCount?: number;
64
- overflowTolerancePx?: number;
65
+ /** The cheap checks of one page: overlays still covering it, the layout and the look. */
66
+ static inspect(page: Page, options?: DyE2E_VisualGateOptions_Interface): Promise<DyE2E_VisualGateFinding_Interface[]>;
67
+ /**
68
+ * ④ the same page on the reference deployment (production, read only), at the same screen size and in the same
69
+ * language: its heading and paragraph sizes must be here too.
70
+ *
71
+ * @returns the `font-size-differs` findings; with `testInfo`, the reference's full-page screenshot is attached
72
+ */
73
+ static compareWithReference(page: Page, gateCase: DyE2E_VisualGateCase_Interface, options: DyE2E_VisualGateOptions_Interface & {
74
+ referenceUrl: string;
65
75
  }): Promise<DyE2E_VisualGateFinding_Interface[]>;
66
76
  /**
67
- * The gate for one case, inside a Playwright test: the cheap checks first (a finding fails the test with its
68
- * reason), then the screenshot comparison against the baseline `<case id>.png`.
77
+ * The gate for one case, inside a Playwright test: the cheap checks first, then (with a `referenceUrl`, on a page
78
+ * marked `isOnReference`) the font sizes of the reference — every finding fails the test with its reason —, then
79
+ * the screenshot comparison against the baseline `<case id>.png` (unless skipped). With `testInfo`, a full-page
80
+ * screenshot of the page goes into the report first, so a human sees it even when the case is red.
69
81
  */
70
- static assertPage(page: Page, gateCase: DyE2E_VisualGateCase_Interface, options?: {
71
- maxDiffPixelRatio?: number;
72
- minVisibleTextLength?: number;
73
- overflowTolerancePx?: number;
74
- }): Promise<void>;
82
+ static assertPage(page: Page, gateCase: DyE2E_VisualGateCase_Interface, options?: DyE2E_VisualGateOptions_Interface): Promise<void>;
75
83
  }
76
84
  //# sourceMappingURL=visual-gate.util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"visual-gate.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,8BAA8B,EAAE,MAAM,uCAAuC,CAAC;AACvF,OAAO,EAAE,iCAAiC,EAAE,MAAM,0CAA0C,CAAC;AAC7F,OAAO,EAAE,kCAAkC,EAAE,MAAM,2CAA2C,CAAC;AAC/F,OAAO,EAAE,gCAAgC,EAAE,MAAM,yCAAyC,CAAC;AAC3F,OAAO,EAAE,8BAA8B,EAAE,MAAM,uCAAuC,CAAC;AACvF,OAAO,EAAE,kCAAkC,EAAE,MAAM,2CAA2C,CAAC;AAI/F;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,qBAAqB;IAEhC,iHAAiH;IACjH,MAAM,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAoCxC;IAEH;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;QAChB,KAAK,EAAE,8BAA8B,EAAE,CAAC;QACxC,SAAS,CAAC,EAAE,kCAAkC,EAAE,CAAC;QACjD,SAAS,CAAC,EAAE,kCAAkC,EAAE,CAAC;KAClD,GAAG,8BAA8B,EAAE;IAoBpC,iEAAiE;WACpD,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,gCAAgC,CAAC;IAMjF;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAChB,MAAM,EAAE,gCAAgC,EACxC,MAAM,GAAE;QAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAAO,GAC5G,iCAAiC,EAAE;IAwBtC,6EAA6E;WAChE,OAAO,CAClB,IAAI,EAAE,IAAI,EACV,MAAM,GAAE;QAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAAO,GAC5G,OAAO,CAAC,iCAAiC,EAAE,CAAC;IAS/C;;;OAGG;WACU,UAAU,CACrB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,8BAA8B,EACxC,OAAO,GAAE;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAAO,GACxG,OAAO,CAAC,IAAI,CAAC;CAgBjB"}
1
+ {"version":3,"file":"visual-gate.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4C,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAElF,OAAO,EAAE,8BAA8B,EAAE,MAAM,uCAAuC,CAAC;AACvF,OAAO,EAAE,iCAAiC,EAAE,MAAM,0CAA0C,CAAC;AAC7F,OAAO,EAAE,kCAAkC,EAAE,MAAM,2CAA2C,CAAC;AAC/F,OAAO,EAAE,gCAAgC,EAAE,MAAM,yCAAyC,CAAC;AAC3F,OAAO,EAAE,iCAAiC,EAAE,MAAM,0CAA0C,CAAC;AAC7F,OAAO,EAAE,8BAA8B,EAAE,MAAM,uCAAuC,CAAC;AACvF,OAAO,EAAE,kCAAkC,EAAE,MAAM,2CAA2C,CAAC;AAK/F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,qBAAqB;IAEhC,iHAAiH;IACjH,MAAM,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAoCxC;IAEH;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;QAChB,KAAK,EAAE,8BAA8B,EAAE,CAAC;QACxC,SAAS,CAAC,EAAE,kCAAkC,EAAE,CAAC;QACjD,SAAS,CAAC,EAAE,kCAAkC,EAAE,CAAC;KAClD,GAAG,8BAA8B,EAAE;IAoBpC,iEAAiE;WACpD,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,gCAAgC,CAAC;IAMjF;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAChB,MAAM,EAAE,gCAAgC,EACxC,MAAM,GAAE;QAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAAO,GAC5G,iCAAiC,EAAE;IAwBtC,yFAAyF;WAC5E,OAAO,CAClB,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,iCAAsC,GAC9C,OAAO,CAAC,iCAAiC,EAAE,CAAC;IAY/C;;;;;OAKG;WACU,oBAAoB,CAC/B,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,8BAA8B,EACxC,OAAO,EAAE,iCAAiC,GAAG;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,GACpE,OAAO,CAAC,iCAAiC,EAAE,CAAC;IAuC/C;;;;;OAKG;WACU,UAAU,CACrB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,8BAA8B,EACxC,OAAO,GAAE,iCAAsC,GAC9C,OAAO,CAAC,IAAI,CAAC;CA6BjB"}
@@ -4,14 +4,17 @@ exports.DyE2E_VisualGate_Util = void 0;
4
4
  const test_1 = require("@playwright/test");
5
5
  const blocking_overlays_util_1 = require("./blocking-overlays.util");
6
6
  const visual_gate_defaults_const_1 = require("./visual-gate-defaults.const");
7
+ const visual_gate_look_util_1 = require("./visual-gate-look.util");
7
8
  /**
8
9
  * The visual regression gate (R1-72 d; owner, 2026-11-02 21:39: the credit login "badly out of shape", "a review tool
9
10
  * is needed"): the key pages, HU + EN, 1440 + 390, red in the CI when a page falls apart or disappears.
10
11
  *
11
- * @description Two checks per page, the cheap and certain one first: (1) a layout check in the browser — the TEST
12
- * warning or the cookie bar still covers the page, the page shows (almost) nothing, or it is wider than the screen;
13
- * (2) a screenshot comparison against the product's committed baseline (Playwright `toHaveScreenshot`; the first run,
14
- * or `--update-snapshots`, writes it).
12
+ * @description The cheap and certain checks first: (1) a layout check in the browser — the TEST warning or the
13
+ * cookie bar still covers the page, the page shows (almost) nothing, or it is wider than the screen; (2) the look
14
+ * (BFR-FUTDEVPRO-081, `DyE2E_VisualGateLook_Util`) — the "not found" screen, an empty content area, green / cyan /
15
+ * blue instead of the neutral grey, a text off the screen, a raw icon word, a placeholder; (3) with a `referenceUrl`,
16
+ * the heading and paragraph sizes of production; then (4) a screenshot comparison against the product's committed
17
+ * baseline (Playwright `toHaveScreenshot`; the first run, or `--update-snapshots`, writes it; it can be skipped).
15
18
  *
16
19
  * ```ts
17
20
  * import { DyE2E_BlockingOverlays_Util, DyE2E_VisualGate_Util } from '@futdevpro/dynamo-e2e/visual-gate';
@@ -26,7 +29,9 @@ const visual_gate_defaults_const_1 = require("./visual-gate-defaults.const");
26
29
  * const page = await context.newPage();
27
30
  *
28
31
  * await page.goto(BASE_URL + gateCase.page.path);
29
- * await DyE2E_VisualGate_Util.assertPage(page, gateCase);
32
+ * await DyE2E_VisualGate_Util.assertPage(page, gateCase, {
33
+ * contentSelector: 'main', referenceUrl: 'https://example.hu', testInfo: test.info(),
34
+ * });
30
35
  * });
31
36
  * }
32
37
  * ```
@@ -122,24 +127,75 @@ class DyE2E_VisualGate_Util {
122
127
  }
123
128
  return findings;
124
129
  }
125
- /** The cheap checks of one page: overlays still covering it + the layout. */
126
- static async inspect(page, limits = {}) {
130
+ /** The cheap checks of one page: overlays still covering it, the layout and the look. */
131
+ static async inspect(page, options = {}) {
127
132
  const findings = (await blocking_overlays_util_1.DyE2E_BlockingOverlays_Util.findVisible(page))
128
133
  .map((name) => ({
129
134
  kind: 'blocking-overlay', message: `${name} covers the page (close it first: DyE2E_BlockingOverlays_Util)`,
130
135
  }));
131
- return findings.concat(this.checkLayout(await this.measureLayout(page), limits));
136
+ return findings.concat(this.checkLayout(await this.measureLayout(page), options), await visual_gate_look_util_1.DyE2E_VisualGateLook_Util.inspect(page, options));
132
137
  }
133
138
  /**
134
- * The gate for one case, inside a Playwright test: the cheap checks first (a finding fails the test with its
135
- * reason), then the screenshot comparison against the baseline `<case id>.png`.
139
+ * ④ the same page on the reference deployment (production, read only), at the same screen size and in the same
140
+ * language: its heading and paragraph sizes must be here too.
141
+ *
142
+ * @returns the `font-size-differs` findings; with `testInfo`, the reference's full-page screenshot is attached
143
+ */
144
+ static async compareWithReference(page, gateCase, options) {
145
+ const browser = page.context().browser();
146
+ if (!browser) {
147
+ throw new Error('[dynamo-e2e visual-gate] the reference needs a browser (not a persistent context)');
148
+ }
149
+ const context = await browser.newContext({
150
+ ignoreHTTPSErrors: true,
151
+ locale: gateCase.language.locale,
152
+ viewport: { width: gateCase.viewport.width, height: gateCase.viewport.height },
153
+ storageState: options.referenceStorageState,
154
+ });
155
+ try {
156
+ const reference = await context.newPage();
157
+ await reference.goto(options.referenceUrl.replace(/\/$/u, '') + gateCase.page.path, { waitUntil: 'domcontentloaded', timeout: 45_000 });
158
+ if (!options.referenceStorageState) {
159
+ await blocking_overlays_util_1.DyE2E_BlockingOverlays_Util.acknowledge(reference);
160
+ }
161
+ await reference.waitForLoadState('networkidle', { timeout: 20_000 }).catch(() => undefined);
162
+ const theirs = await visual_gate_look_util_1.DyE2E_VisualGateLook_Util.measureFontSizes(reference, options.contentSelector);
163
+ if (options.testInfo) {
164
+ await options.testInfo.attach(`reference-${gateCase.id}.png`, {
165
+ body: await reference.screenshot({ fullPage: true }), contentType: 'image/png',
166
+ });
167
+ }
168
+ return visual_gate_look_util_1.DyE2E_VisualGateLook_Util.compareFontSizes(await visual_gate_look_util_1.DyE2E_VisualGateLook_Util.measureFontSizes(page, options.contentSelector), theirs);
169
+ }
170
+ finally {
171
+ await context.close();
172
+ }
173
+ }
174
+ /**
175
+ * The gate for one case, inside a Playwright test: the cheap checks first, then (with a `referenceUrl`, on a page
176
+ * marked `isOnReference`) the font sizes of the reference — every finding fails the test with its reason —, then
177
+ * the screenshot comparison against the baseline `<case id>.png` (unless skipped). With `testInfo`, a full-page
178
+ * screenshot of the page goes into the report first, so a human sees it even when the case is red.
136
179
  */
137
180
  static async assertPage(page, gateCase, options = {}) {
181
+ if (options.testInfo) {
182
+ await options.testInfo.attach(`test-${gateCase.id}.png`, {
183
+ body: await page.screenshot({ fullPage: true }), contentType: 'image/png',
184
+ });
185
+ }
138
186
  const findings = await this.inspect(page, options);
187
+ if (options.referenceUrl && gateCase.page.isOnReference) {
188
+ findings.push(...await this.compareWithReference(page, gateCase, {
189
+ ...options, referenceUrl: options.referenceUrl,
190
+ }));
191
+ }
139
192
  if (findings.length) {
140
193
  throw new Error(`[dynamo-e2e visual-gate] ${gateCase.id} (${page.url()}):\n`
141
194
  + findings.map((finding) => `- ${finding.kind}: ${finding.message}`).join('\n'));
142
195
  }
196
+ if (options.isScreenshotComparisonSkipped) {
197
+ return;
198
+ }
143
199
  await (0, test_1.expect)(page).toHaveScreenshot(gateCase.snapshotName, {
144
200
  fullPage: true,
145
201
  animations: 'disabled',
@@ -1 +1 @@
1
- {"version":3,"file":"visual-gate.util.js","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate.util.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"visual-gate.util.js","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_collections/visual-gate.util.ts"],"names":[],"mappings":"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"}
@@ -3,9 +3,14 @@ export interface DyE2E_VisualGateFinding_Interface {
3
3
  /**
4
4
  * `blocking-overlay`: the TEST warning or the cookie bar covers the page (the screenshot would show them);
5
5
  * `page-empty`: the page shows (almost) nothing — it disappeared; `horizontal-overflow`: the page is wider than the
6
- * screen — it fell apart.
6
+ * screen — it fell apart; `not-found`: the product's "not found" screen is shown; `content-empty`: the content area
7
+ * is missing or (almost) empty; `loud-color`: a box of the content area has a saturated green / cyan / blue frame,
8
+ * background or gradient instead of the systems' neutral grey; `font-size-differs`: a heading or paragraph size of
9
+ * the reference (production) is gone; `text-off-screen`: a visible text sticks out of the screen; `raw-icon-word`:
10
+ * an icon shows its ligature word instead of the sign; `placeholder-text`: "coming soon", "lorem ipsum", `TODO` …
11
+ * is visible.
7
12
  */
8
- kind: 'blocking-overlay' | 'page-empty' | 'horizontal-overflow';
13
+ kind: 'blocking-overlay' | 'page-empty' | 'horizontal-overflow' | 'not-found' | 'content-empty' | 'loud-color' | 'font-size-differs' | 'text-off-screen' | 'raw-icon-word' | 'placeholder-text';
9
14
  message: string;
10
15
  }
11
16
  //# sourceMappingURL=visual-gate-finding.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"visual-gate-finding.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_models/visual-gate-finding.interface.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,MAAM,WAAW,iCAAiC;IAChD;;;;OAIG;IACH,IAAI,EAAE,kBAAkB,GAAG,YAAY,GAAG,qBAAqB,CAAC;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"visual-gate-finding.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_models/visual-gate-finding.interface.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,MAAM,WAAW,iCAAiC;IAChD;;;;;;;;;OASG;IACH,IAAI,EAAE,kBAAkB,GAAG,YAAY,GAAG,qBAAqB,GAAG,WAAW,GAAG,eAAe,GAAG,YAAY,GAC1G,mBAAmB,GAAG,iBAAiB,GAAG,eAAe,GAAG,kBAAkB,CAAC;IACnF,OAAO,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * How the visual gate judges the look of a page (BFR-FUTDEVPRO-081); every field has a default
3
+ * (`DyE2E_VisualGateDefaults_Const`).
4
+ */
5
+ export interface DyE2E_VisualGateLookOptions_Interface {
6
+ /**
7
+ * The content area of the product (without the header, the footer, the cookie bar and the TEST ribbon): the
8
+ * neutral-look check and the font sizes are measured in it. Default `body`. When it is given, a missing or (almost)
9
+ * empty content area is a `content-empty` finding.
10
+ */
11
+ contentSelector?: string;
12
+ /** The product's "not found" screen (a component or test id): visible ⇒ `not-found`. No default. */
13
+ notFoundSelector?: string;
14
+ /** A content area lower than this is empty, px (with `contentSelector` only). */
15
+ minContentHeightPx?: number;
16
+ /** The shared components skipped by the neutral-look check (buttons, fields, icons, Material, media). */
17
+ neutralSkipSelector?: string;
18
+ /** Boxes whose gradient is part of the design (a product's own decoration): their gradient is not judged. */
19
+ gradientAllowSelector?: string;
20
+ /** The hue range that is loud, degrees: green (80) … blue (260); red (error) and amber (to do) carry meaning. */
21
+ loudHueFrom?: number;
22
+ loudHueTo?: number;
23
+ /** A colour at least this saturated (HSL, 0–1) and this opaque (0–1) is loud. */
24
+ loudMinSaturation?: number;
25
+ loudMinAlpha?: number;
26
+ /** The placeholder words, a case-insensitive regular expression source; `null` turns the check off. */
27
+ placeholderPattern?: string | null;
28
+ /** Turns off the neutral-look check (a product whose design is not the neutral grey). */
29
+ isNeutralLookSkipped?: boolean;
30
+ /** Turns off the text checks (text off the screen, a raw icon word, a placeholder). */
31
+ isTextCheckSkipped?: boolean;
32
+ }
33
+ //# sourceMappingURL=visual-gate-look-options.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-gate-look-options.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_models/visual-gate-look-options.interface.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,qCAAqC;IACpD;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oGAAoG;IACpG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yGAAyG;IACzG,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,6GAA6G;IAC7G,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iHAAiH;IACjH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,yFAAyF;IACzF,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=visual-gate-look-options.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-gate-look-options.interface.js","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_models/visual-gate-look-options.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import { TestInfo } from '@playwright/test';
2
+ import { DyE2E_BlockingOverlaysState_Type } from '../_collections/blocking-overlays.util';
3
+ import { DyE2E_VisualGateLookOptions_Interface } from './visual-gate-look-options.interface';
4
+ /** The options of `DyE2E_VisualGate_Util.inspect` / `assertPage`; every field has a default. */
5
+ export interface DyE2E_VisualGateOptions_Interface extends DyE2E_VisualGateLookOptions_Interface {
6
+ /** Fewer visible characters than this ⇒ `page-empty`. */
7
+ minVisibleTextLength?: number;
8
+ /** Fewer visible elements than this ⇒ `page-empty`. */
9
+ minVisibleElementCount?: number;
10
+ /** A document at most this much wider than the viewport is not a sideways scroll, px. */
11
+ overflowTolerancePx?: number;
12
+ /** The share of differing pixels the screenshot comparison tolerates. */
13
+ maxDiffPixelRatio?: number;
14
+ /**
15
+ * No pixel comparison against a baseline (a product whose baseline cannot come from the CI's own container: a
16
+ * baseline taken on a developer machine renders the fonts differently — futdevpro's choice, BFR-FUTDEVPRO-081).
17
+ */
18
+ isScreenshotComparisonSkipped?: boolean;
19
+ /**
20
+ * The reference deployment (production, read only: `https://futdevpro.hu`): on the pages marked `isOnReference`
21
+ * the heading and paragraph sizes must be the reference's (④). Unset ⇒ no comparison.
22
+ */
23
+ referenceUrl?: string;
24
+ /**
25
+ * The state to open the reference with (`DyE2E_BlockingOverlays_Util.prepareStorageState` on the reference, once
26
+ * per language). Unset ⇒ the cookie bar of the reference is closed on every case (slower).
27
+ */
28
+ referenceStorageState?: DyE2E_BlockingOverlaysState_Type;
29
+ /** The Playwright test info: a full-page screenshot of the page (and of the reference) goes into the report. */
30
+ testInfo?: TestInfo;
31
+ }
32
+ //# sourceMappingURL=visual-gate-options.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-gate-options.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_models/visual-gate-options.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,gCAAgC,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,EAAE,qCAAqC,EAAE,MAAM,sCAAsC,CAAC;AAE7F,gGAAgG;AAChG,MAAM,WAAW,iCAAkC,SAAQ,qCAAqC;IAC9F,yDAAyD;IACzD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,uDAAuD;IACvD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,yFAAyF;IACzF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,gCAAgC,CAAC;IACzD,gHAAgH;IAChH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=visual-gate-options.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-gate-options.interface.js","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_models/visual-gate-options.interface.ts"],"names":[],"mappings":""}
@@ -6,5 +6,10 @@ export interface DyE2E_VisualGatePage_Interface {
6
6
  path: string;
7
7
  /** Selectors of changing parts (a date, a version number) that the screenshot comparison masks. */
8
8
  mask?: string[];
9
+ /**
10
+ * The page is on the reference deployment (production) with the same content: its heading and paragraph sizes
11
+ * are compared there (`referenceUrl` of `assertPage`). A page that is new, or changed on purpose, leaves it unset.
12
+ */
13
+ isOnReference?: boolean;
9
14
  }
10
15
  //# sourceMappingURL=visual-gate-page.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"visual-gate-page.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_models/visual-gate-page.interface.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,WAAW,8BAA8B;IAC7C,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,mGAAmG;IACnG,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB"}
1
+ {"version":3,"file":"visual-gate-page.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/visual-gate/_models/visual-gate-page.interface.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,WAAW,8BAA8B;IAC7C,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,mGAAmG;IACnG,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB"}
@@ -1,15 +1,19 @@
1
1
  /**
2
2
  * `@futdevpro/dynamo-e2e/visual-gate` — the visual regression gate (R1-72 d): close the TEST warning and the cookie
3
3
  * bar, then check the key pages (HU + EN, 1440 + 390) — red when a page falls apart, disappears or changes.
4
- * The `/vqa` layer collects evidence for a reviewer, `/ui-check` presses controls; this layer judges the look.
4
+ * The `/vqa` layer collects evidence for a reviewer, `/ui-check` presses controls; this layer judges the look: the
5
+ * neutral grey, the text, and the font sizes of production (BFR-FUTDEVPRO-081).
5
6
  */
6
7
  export * from './_collections/blocking-overlays.util';
7
8
  export * from './_collections/visual-gate-defaults.const';
9
+ export * from './_collections/visual-gate-look.util';
8
10
  export * from './_collections/visual-gate.util';
9
11
  export * from './_models/visual-gate-case.interface';
10
12
  export * from './_models/visual-gate-finding.interface';
11
13
  export * from './_models/visual-gate-language.interface';
12
14
  export * from './_models/visual-gate-layout.interface';
15
+ export * from './_models/visual-gate-look-options.interface';
16
+ export * from './_models/visual-gate-options.interface';
13
17
  export * from './_models/visual-gate-page.interface';
14
18
  export * from './_models/visual-gate-viewport.interface';
15
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/_modules/visual-gate/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AACzD,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC;AACrD,cAAc,0CAA0C,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/_modules/visual-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,sCAAsC,CAAC;AACrD,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AACzD,cAAc,wCAAwC,CAAC;AACvD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,yCAAyC,CAAC;AACxD,cAAc,sCAAsC,CAAC;AACrD,cAAc,0CAA0C,CAAC"}
@@ -17,15 +17,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  /**
18
18
  * `@futdevpro/dynamo-e2e/visual-gate` — the visual regression gate (R1-72 d): close the TEST warning and the cookie
19
19
  * bar, then check the key pages (HU + EN, 1440 + 390) — red when a page falls apart, disappears or changes.
20
- * The `/vqa` layer collects evidence for a reviewer, `/ui-check` presses controls; this layer judges the look.
20
+ * The `/vqa` layer collects evidence for a reviewer, `/ui-check` presses controls; this layer judges the look: the
21
+ * neutral grey, the text, and the font sizes of production (BFR-FUTDEVPRO-081).
21
22
  */
22
23
  __exportStar(require("./_collections/blocking-overlays.util"), exports);
23
24
  __exportStar(require("./_collections/visual-gate-defaults.const"), exports);
25
+ __exportStar(require("./_collections/visual-gate-look.util"), exports);
24
26
  __exportStar(require("./_collections/visual-gate.util"), exports);
25
27
  __exportStar(require("./_models/visual-gate-case.interface"), exports);
26
28
  __exportStar(require("./_models/visual-gate-finding.interface"), exports);
27
29
  __exportStar(require("./_models/visual-gate-language.interface"), exports);
28
30
  __exportStar(require("./_models/visual-gate-layout.interface"), exports);
31
+ __exportStar(require("./_models/visual-gate-look-options.interface"), exports);
32
+ __exportStar(require("./_models/visual-gate-options.interface"), exports);
29
33
  __exportStar(require("./_models/visual-gate-page.interface"), exports);
30
34
  __exportStar(require("./_models/visual-gate-viewport.interface"), exports);
31
35
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/_modules/visual-gate/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;;GAIG;AACH,wEAAsD;AACtD,4EAA0D;AAC1D,kEAAgD;AAChD,uEAAqD;AACrD,0EAAwD;AACxD,2EAAyD;AACzD,yEAAuD;AACvD,uEAAqD;AACrD,2EAAyD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/_modules/visual-gate/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;;;GAKG;AACH,wEAAsD;AACtD,4EAA0D;AAC1D,uEAAqD;AACrD,kEAAgD;AAChD,uEAAqD;AACrD,0EAAwD;AACxD,2EAAyD;AACzD,yEAAuD;AACvD,+EAA6D;AAC7D,0EAAwD;AACxD,uEAAqD;AACrD,2EAAyD"}
package/build/index.js CHANGED
@@ -26,5 +26,5 @@ __exportStar(require("./_modules/game/index"), exports);
26
26
  __exportStar(require("./_modules/ui-check/index"), exports);
27
27
  __exportStar(require("./_modules/coverage/index"), exports);
28
28
  /** Package-version stamp — npm-publish-time runtime-érték. */
29
- exports.DYE2E_PACKAGE_VERSION = '01.18.39';
29
+ exports.DYE2E_PACKAGE_VERSION = '01.18.40';
30
30
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@futdevpro/dynamo-e2e",
3
- "version": "01.18.39",
3
+ "version": "01.18.40",
4
4
  "description": "End-to-end testing engine for the Dynamo + FDP ecosystem — auto-generated form-coverage tests, viewport audit matrix, CWV diagnostics. Settings-POJO-first.",
5
5
  "DyBu_settings": {
6
6
  "packageType": "core-package",