@futdevpro/dynamo-e2e 1.18.14 → 1.18.16
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.
- package/CHANGELOG.md +28 -0
- package/README.md +47 -1
- package/bin/dye2e.js +13 -0
- package/build/_modules/generators/_collections/cli-runner.util.d.ts.map +1 -1
- package/build/_modules/generators/_collections/cli-runner.util.js +17 -0
- package/build/_modules/generators/_collections/cli-runner.util.js.map +1 -1
- package/build/_modules/runtime/_collections/notification-detector-page-script.const.d.ts +30 -0
- package/build/_modules/runtime/_collections/notification-detector-page-script.const.d.ts.map +1 -0
- package/build/_modules/runtime/_collections/notification-detector-page-script.const.js +169 -0
- package/build/_modules/runtime/_collections/notification-detector-page-script.const.js.map +1 -0
- package/build/_modules/runtime/_collections/notification-detector.util.d.ts +47 -0
- package/build/_modules/runtime/_collections/notification-detector.util.d.ts.map +1 -0
- package/build/_modules/runtime/_collections/notification-detector.util.js +165 -0
- package/build/_modules/runtime/_collections/notification-detector.util.js.map +1 -0
- package/build/_modules/runtime/_collections/notification-sweep.util.d.ts +65 -0
- package/build/_modules/runtime/_collections/notification-sweep.util.d.ts.map +1 -0
- package/build/_modules/runtime/_collections/notification-sweep.util.js +326 -0
- package/build/_modules/runtime/_collections/notification-sweep.util.js.map +1 -0
- package/build/_modules/runtime/_models/notification-report.interface.d.ts +54 -0
- package/build/_modules/runtime/_models/notification-report.interface.d.ts.map +1 -0
- package/build/_modules/runtime/_models/notification-report.interface.js +3 -0
- package/build/_modules/runtime/_models/notification-report.interface.js.map +1 -0
- package/build/_modules/runtime/_models/notification-sweep.interface.d.ts +67 -0
- package/build/_modules/runtime/_models/notification-sweep.interface.d.ts.map +1 -0
- package/build/_modules/runtime/_models/notification-sweep.interface.js +3 -0
- package/build/_modules/runtime/_models/notification-sweep.interface.js.map +1 -0
- package/build/_modules/runtime/index.d.ts +5 -0
- package/build/_modules/runtime/index.d.ts.map +1 -1
- package/build/_modules/runtime/index.js +5 -0
- package/build/_modules/runtime/index.js.map +1 -1
- package/build/index.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Browser } from '@playwright/test';
|
|
2
|
+
import { DyE2E_SweepOptions_Interface, DyE2E_SweepOutcome_Interface, DyE2E_SweepRow_Interface, DyE2E_SweepTarget_Interface } from '../_models/notification-sweep.interface';
|
|
3
|
+
/**
|
|
4
|
+
* Login-flow notification sweep (BFR-QA-002) — on top of `DyE2E_NotificationDetector_Util` (BFR-QA-001): opens the
|
|
5
|
+
* login page of every target, submits it with a WRONG password by default (so the ERROR branch is measured without
|
|
6
|
+
* a test account), and returns one matrix row per project: notifications · error/warning · visible banners ·
|
|
7
|
+
* raw-technical leaks · console errors. Framework-level defects (e.g. the raw `Http failure … 401` banner on the
|
|
8
|
+
* login of 5+ projects) only show when many projects are measured the same way.
|
|
9
|
+
*
|
|
10
|
+
* Two guards are CODE, not advice:
|
|
11
|
+
* - the probe e-mail must be on a reserved, undeliverable domain (`example.com`, `*.example`, `*.test`, `*.invalid`,
|
|
12
|
+
* `*.localhost`, `*.local`) or on a domain you declare your own (`ownDomains`) — `core-test-email-own-or-reserved-only`;
|
|
13
|
+
* - the form is submitted only on a test host (`test.*`, `*.test`, `localhost`, `127.0.0.1` …, or `allowSubmitHosts`)
|
|
14
|
+
* — anything else is loaded but NOT submitted, and the row says so.
|
|
15
|
+
* `real: true` uses the registered test account from `E2E_PERSISTENT_USER_EMAIL` / `_PASSWORD`; without them the row
|
|
16
|
+
* says it fell back to the probe. No account is ever created.
|
|
17
|
+
*/
|
|
18
|
+
export declare class DyE2E_NotificationSweep_Util {
|
|
19
|
+
/** The default probe e-mail — a reserved, undeliverable domain. */
|
|
20
|
+
static readonly defaultProbeEmail: string;
|
|
21
|
+
/** The default probe password (deliberately wrong). */
|
|
22
|
+
static readonly defaultProbePassword: string;
|
|
23
|
+
/** Login paths that differ from the FDP default `/landing/login` (measured). */
|
|
24
|
+
static readonly defaultLoginPaths: Record<string, string>;
|
|
25
|
+
/** The e-mail / user-name field. */
|
|
26
|
+
static readonly emailSelector: string;
|
|
27
|
+
/** The submit button. */
|
|
28
|
+
static readonly submitSelector: string;
|
|
29
|
+
/** Whether an e-mail may be used as a probe: reserved domain, or one of `ownDomains` (or a subdomain of it). */
|
|
30
|
+
static isAllowedProbeEmail(email: string, ownDomains?: string[]): boolean;
|
|
31
|
+
/** Whether the form of `url` may be submitted: a test host, or one of `allowHosts`. */
|
|
32
|
+
static isSubmitAllowed(url: string, allowHosts?: string[]): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Targets from a file: JSON (`[{ key, loginUrl }]` or `[{ key, baseUrl, loginPath? }]`), or the QA workspace's
|
|
35
|
+
* `TEST-TARGETS.md` table (`| **key** | \`https://test.…\` |` — only `https://test.` rows, PROD is never a target).
|
|
36
|
+
*/
|
|
37
|
+
static readTargets(file: string, loginPaths?: Record<string, string>): DyE2E_SweepTarget_Interface[];
|
|
38
|
+
/** Sweeps the targets one by one (a fresh context each) and returns the rows with their full reports. */
|
|
39
|
+
static sweep(browser: Browser, targets: DyE2E_SweepTarget_Interface[], options?: DyE2E_SweepOptions_Interface): Promise<DyE2E_SweepOutcome_Interface[]>;
|
|
40
|
+
/** The matrix of a sweep as text. */
|
|
41
|
+
static matrix(rows: DyE2E_SweepRow_Interface[]): string;
|
|
42
|
+
/**
|
|
43
|
+
* `dye2e notification-sweep` — flags: `--targets <md|json>` (required) · `--only a,b` · `--login-paths k=/p,…` ·
|
|
44
|
+
* `--no-submit` · `--real` · `--probe-email` · `--own-domains d,…` · `--allow-hosts h,…` · `--settle-ms` ·
|
|
45
|
+
* `--after-submit-ms` · `--json <out>` · `--fail-on-leak` · `--executable-path`.
|
|
46
|
+
* @returns the process exit code (2 = no targets / bad input, 1 = `--fail-on-leak` and a leak, 0 otherwise).
|
|
47
|
+
*/
|
|
48
|
+
static runCli(flags: Record<string, string>): Promise<number>;
|
|
49
|
+
/** One target: fresh context, detector, load, (guarded) submit, collect. */
|
|
50
|
+
private static sweepOne;
|
|
51
|
+
/**
|
|
52
|
+
* Records, then closes the MODAL dialogs (cdk overlay, `aria-modal="true"`, `alertdialog`) — measured 2026-09-24:
|
|
53
|
+
* - on 3 of 7 TEST sites a "This is NOT the production system" notice covered the login (every click hit it);
|
|
54
|
+
* - on one, the modal WAS the finding: "An unexpected error occurred: this.… is not a function" on page load —
|
|
55
|
+
* so every dialog is recorded (text + raw-technical-leak flag) BEFORE it is closed, never silently swept away.
|
|
56
|
+
* A non-modal `role="dialog"` (a cookie-consent bar) does not block the page and is left alone. Escape first, then
|
|
57
|
+
* the dialog's own action button; a modal that stays open stops the loop (named in the note).
|
|
58
|
+
*/
|
|
59
|
+
private static captureModalDialogs;
|
|
60
|
+
/** Fills the login form and submits it; a missing field is a note, not a crash. */
|
|
61
|
+
private static submitLogin;
|
|
62
|
+
/** CLI flags → sweep options. */
|
|
63
|
+
private static optionsFromFlags;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=notification-sweep.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-sweep.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/runtime/_collections/notification-sweep.util.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAA2C,MAAM,kBAAkB,CAAC;AAGpF,OAAO,EAGL,4BAA4B,EAC5B,4BAA4B,EAC5B,wBAAwB,EACxB,2BAA2B,EAC5B,MAAM,yCAAyC,CAAC;AAGjD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,4BAA4B;IAEvC,mEAAmE;IACnE,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAmC;IAE5E,uDAAuD;IACvD,MAAM,CAAC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAA6B;IAEzE,gFAAgF;IAChF,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAqC;IAE9F,oCAAoC;IACpC,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CACgE;IAErG,yBAAyB;IACzB,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CACqE;IAE3G,gHAAgH;IAChH,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,EAAO,GAAG,OAAO;IAa7E,uFAAuF;IACvF,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,EAAO,GAAG,OAAO;IAcvE;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,2BAA2B,EAAE;IAqCxG,yGAAyG;WAC5F,KAAK,CAChB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,2BAA2B,EAAE,EACtC,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,4BAA4B,EAAE,CAAC;IAgB1C,qCAAqC;IACrC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,wBAAwB,EAAE,GAAG,MAAM;IAgBvD;;;;;OAKG;WACU,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAgDnE,4EAA4E;mBACvD,QAAQ;IAkF7B;;;;;;;OAOG;mBACkB,mBAAmB;IAyCxC,mFAAmF;mBAC9D,WAAW;IAqBhC,iCAAiC;IACjC,OAAO,CAAC,MAAM,CAAC,gBAAgB;CAiBhC"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DyE2E_NotificationSweep_Util = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const test_1 = require("@playwright/test");
|
|
29
|
+
const notification_detector_util_1 = require("./notification-detector.util");
|
|
30
|
+
/**
|
|
31
|
+
* Login-flow notification sweep (BFR-QA-002) — on top of `DyE2E_NotificationDetector_Util` (BFR-QA-001): opens the
|
|
32
|
+
* login page of every target, submits it with a WRONG password by default (so the ERROR branch is measured without
|
|
33
|
+
* a test account), and returns one matrix row per project: notifications · error/warning · visible banners ·
|
|
34
|
+
* raw-technical leaks · console errors. Framework-level defects (e.g. the raw `Http failure … 401` banner on the
|
|
35
|
+
* login of 5+ projects) only show when many projects are measured the same way.
|
|
36
|
+
*
|
|
37
|
+
* Two guards are CODE, not advice:
|
|
38
|
+
* - the probe e-mail must be on a reserved, undeliverable domain (`example.com`, `*.example`, `*.test`, `*.invalid`,
|
|
39
|
+
* `*.localhost`, `*.local`) or on a domain you declare your own (`ownDomains`) — `core-test-email-own-or-reserved-only`;
|
|
40
|
+
* - the form is submitted only on a test host (`test.*`, `*.test`, `localhost`, `127.0.0.1` …, or `allowSubmitHosts`)
|
|
41
|
+
* — anything else is loaded but NOT submitted, and the row says so.
|
|
42
|
+
* `real: true` uses the registered test account from `E2E_PERSISTENT_USER_EMAIL` / `_PASSWORD`; without them the row
|
|
43
|
+
* says it fell back to the probe. No account is ever created.
|
|
44
|
+
*/
|
|
45
|
+
class DyE2E_NotificationSweep_Util {
|
|
46
|
+
/** The default probe e-mail — a reserved, undeliverable domain. */
|
|
47
|
+
static defaultProbeEmail = 'dye2e-sweep-probe@example.com';
|
|
48
|
+
/** The default probe password (deliberately wrong). */
|
|
49
|
+
static defaultProbePassword = 'Dye2e-Wrong-Password-1!';
|
|
50
|
+
/** Login paths that differ from the FDP default `/landing/login` (measured). */
|
|
51
|
+
static defaultLoginPaths = { 'fdp-token-service': '/login' };
|
|
52
|
+
/** The e-mail / user-name field. */
|
|
53
|
+
static emailSelector = 'input[type="email"], input[formcontrolname*="mail" i], input[name*="mail" i], input[type="text"]';
|
|
54
|
+
/** The submit button. */
|
|
55
|
+
static submitSelector = 'button[type="submit"], button:has-text("Login"), button:has-text("Log in"), button:has-text("Belépés")';
|
|
56
|
+
/** Whether an e-mail may be used as a probe: reserved domain, or one of `ownDomains` (or a subdomain of it). */
|
|
57
|
+
static isAllowedProbeEmail(email, ownDomains = []) {
|
|
58
|
+
const domain = (email.split('@')[1] ?? '').trim().toLowerCase();
|
|
59
|
+
if (!domain || !/^[a-z0-9.-]+$/.test(domain)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const reserved = ['example.com', 'example.net', 'example.org'].includes(domain)
|
|
63
|
+
|| ['.example', '.test', '.invalid', '.localhost', '.local'].some((tld) => domain.endsWith(tld));
|
|
64
|
+
return reserved || ownDomains.some((own) => domain === own.toLowerCase() || domain.endsWith('.' + own.toLowerCase()));
|
|
65
|
+
}
|
|
66
|
+
/** Whether the form of `url` may be submitted: a test host, or one of `allowHosts`. */
|
|
67
|
+
static isSubmitAllowed(url, allowHosts = []) {
|
|
68
|
+
let host;
|
|
69
|
+
try {
|
|
70
|
+
host = new URL(url).hostname.toLowerCase();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
return host.startsWith('test.') || ['localhost', '127.0.0.1', '[::1]'].includes(host)
|
|
76
|
+
|| ['.test', '.localhost'].some((tld) => host.endsWith(tld))
|
|
77
|
+
|| allowHosts.some((allowed) => host === allowed.toLowerCase());
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Targets from a file: JSON (`[{ key, loginUrl }]` or `[{ key, baseUrl, loginPath? }]`), or the QA workspace's
|
|
81
|
+
* `TEST-TARGETS.md` table (`| **key** | \`https://test.…\` |` — only `https://test.` rows, PROD is never a target).
|
|
82
|
+
*/
|
|
83
|
+
static readTargets(file, loginPaths = {}) {
|
|
84
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
85
|
+
const paths = { ...DyE2E_NotificationSweep_Util.defaultLoginPaths, ...loginPaths };
|
|
86
|
+
if (file.toLowerCase().endsWith('.json')) {
|
|
87
|
+
const parsed = JSON.parse(text);
|
|
88
|
+
if (!Array.isArray(parsed)) {
|
|
89
|
+
throw new Error(`notification-sweep: ${file} must be a JSON array of { key, loginUrl } / { key, baseUrl }`);
|
|
90
|
+
}
|
|
91
|
+
return parsed.map((entry, index) => {
|
|
92
|
+
const key = typeof entry.key === 'string' ? entry.key : '';
|
|
93
|
+
const base = typeof entry.baseUrl === 'string' ? entry.baseUrl.replace(/\/+$/, '') : '';
|
|
94
|
+
const loginUrl = typeof entry.loginUrl === 'string' ? entry.loginUrl
|
|
95
|
+
: base + (typeof entry.loginPath === 'string' ? entry.loginPath : paths[key] ?? '/landing/login');
|
|
96
|
+
if (!key || !/^https?:\/\//.test(loginUrl)) {
|
|
97
|
+
throw new Error(`notification-sweep: ${file} entry #${index} needs a "key" and a "loginUrl" or "baseUrl"`);
|
|
98
|
+
}
|
|
99
|
+
return { key: key, loginUrl: loginUrl };
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const targets = [];
|
|
103
|
+
const row = /^\|\s*\*\*([a-z0-9-]+)\*\*\s*\|\s*`(https:\/\/test\.[^`\s]+)`/gim;
|
|
104
|
+
let match = row.exec(text);
|
|
105
|
+
while (match) {
|
|
106
|
+
targets.push({ key: match[1], loginUrl: match[2].replace(/\/+$/, '') + (paths[match[1]] ?? '/landing/login') });
|
|
107
|
+
match = row.exec(text);
|
|
108
|
+
}
|
|
109
|
+
return targets;
|
|
110
|
+
}
|
|
111
|
+
/** Sweeps the targets one by one (a fresh context each) and returns the rows with their full reports. */
|
|
112
|
+
static async sweep(browser, targets, options = {}) {
|
|
113
|
+
const probeEmail = options.probeEmail ?? DyE2E_NotificationSweep_Util.defaultProbeEmail;
|
|
114
|
+
if (!DyE2E_NotificationSweep_Util.isAllowedProbeEmail(probeEmail, options.ownDomains)) {
|
|
115
|
+
throw new Error(`notification-sweep: the probe e-mail "${probeEmail}" is not on a reserved (example.com, *.test, `
|
|
116
|
+
+ '*.invalid …) or declared own domain (`ownDomains`) — a test must never write to a real, foreign address.');
|
|
117
|
+
}
|
|
118
|
+
const outcomes = [];
|
|
119
|
+
for (const target of targets) {
|
|
120
|
+
outcomes.push(await DyE2E_NotificationSweep_Util.sweepOne(browser, target, options, probeEmail));
|
|
121
|
+
}
|
|
122
|
+
return outcomes;
|
|
123
|
+
}
|
|
124
|
+
/** The matrix of a sweep as text. */
|
|
125
|
+
static matrix(rows) {
|
|
126
|
+
const lines = [
|
|
127
|
+
'=================== NOTIFICATION SWEEP ===================',
|
|
128
|
+
'project | mode | notif | err/warn | banner | dialog | leak | console | note',
|
|
129
|
+
];
|
|
130
|
+
rows.forEach((r) => {
|
|
131
|
+
lines.push(r.key.padEnd(20) + ' | ' + r.mode.padEnd(9) + ' | ' + String(r.notifications).padEnd(5) + ' | '
|
|
132
|
+
+ String(r.errorOrWarning).padEnd(8) + ' | ' + String(r.banners).padEnd(6) + ' | ' + String(r.dialogs).padEnd(6)
|
|
133
|
+
+ ' | ' + String(r.leaks).padEnd(4)
|
|
134
|
+
+ ' | ' + String(r.consoleErrors).padEnd(7) + ' | ' + r.note);
|
|
135
|
+
});
|
|
136
|
+
return lines.join('\n');
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* `dye2e notification-sweep` — flags: `--targets <md|json>` (required) · `--only a,b` · `--login-paths k=/p,…` ·
|
|
140
|
+
* `--no-submit` · `--real` · `--probe-email` · `--own-domains d,…` · `--allow-hosts h,…` · `--settle-ms` ·
|
|
141
|
+
* `--after-submit-ms` · `--json <out>` · `--fail-on-leak` · `--executable-path`.
|
|
142
|
+
* @returns the process exit code (2 = no targets / bad input, 1 = `--fail-on-leak` and a leak, 0 otherwise).
|
|
143
|
+
*/
|
|
144
|
+
static async runCli(flags) {
|
|
145
|
+
if (!flags.targets) {
|
|
146
|
+
process.stderr.write('[dye2e] error: --targets <TEST-TARGETS.md | targets.json> required\n');
|
|
147
|
+
return 2;
|
|
148
|
+
}
|
|
149
|
+
const list = (value) => (value ?? '').split(',').map((s) => s.trim()).filter(Boolean);
|
|
150
|
+
const loginPaths = {};
|
|
151
|
+
list(flags['login-paths']).forEach((pair) => {
|
|
152
|
+
const [key, loginPath] = pair.split('=');
|
|
153
|
+
loginPaths[key] = loginPath;
|
|
154
|
+
});
|
|
155
|
+
const only = list(flags.only);
|
|
156
|
+
const targets = DyE2E_NotificationSweep_Util.readTargets(flags.targets, loginPaths)
|
|
157
|
+
.filter((t) => !only.length || only.includes(t.key));
|
|
158
|
+
if (!targets.length) {
|
|
159
|
+
process.stderr.write(`[dye2e] error: no target in ${flags.targets}${only.length ? ' after --only' : ''}\n`);
|
|
160
|
+
return 2;
|
|
161
|
+
}
|
|
162
|
+
const executablePath = flags['executable-path'] || process.env.DYE2E_CHROMIUM_EXECUTABLE_PATH;
|
|
163
|
+
const browser = await test_1.chromium.launch(executablePath ? { executablePath: executablePath } : {});
|
|
164
|
+
let outcomes;
|
|
165
|
+
try {
|
|
166
|
+
outcomes = await DyE2E_NotificationSweep_Util.sweep(browser, targets, DyE2E_NotificationSweep_Util.optionsFromFlags(flags, list));
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
await browser.close();
|
|
170
|
+
}
|
|
171
|
+
outcomes.forEach((o) => {
|
|
172
|
+
process.stdout.write('\n### ' + o.row.key + ' -> ' + o.row.reachedUrl + (o.row.note ? ' [' + o.row.note + ']' : '')
|
|
173
|
+
+ '\n' + notification_detector_util_1.DyE2E_NotificationDetector_Util.summarize(o.report, o.row.key) + '\n');
|
|
174
|
+
});
|
|
175
|
+
const rows = outcomes.map((o) => o.row);
|
|
176
|
+
process.stdout.write('\n' + DyE2E_NotificationSweep_Util.matrix(rows) + '\n');
|
|
177
|
+
if (flags.json) {
|
|
178
|
+
fs.writeFileSync(flags.json, JSON.stringify({ generatedAt: new Date().toISOString(), outcomes: outcomes }, null, 2));
|
|
179
|
+
}
|
|
180
|
+
return flags['fail-on-leak'] && rows.some((r) => r.leaks > 0) ? 1 : 0;
|
|
181
|
+
}
|
|
182
|
+
/** One target: fresh context, detector, load, (guarded) submit, collect. */
|
|
183
|
+
static async sweepOne(browser, target, options, probeEmail) {
|
|
184
|
+
const context = await browser.newContext({ ignoreHTTPSErrors: true, viewport: { width: 1280, height: 900 } });
|
|
185
|
+
const notes = [];
|
|
186
|
+
const dialogs = [];
|
|
187
|
+
let mode = options.submit === false ? 'no-submit' : 'probe';
|
|
188
|
+
let submitted = false;
|
|
189
|
+
let page;
|
|
190
|
+
try {
|
|
191
|
+
if (options.prepareContext) {
|
|
192
|
+
await options.prepareContext(context);
|
|
193
|
+
}
|
|
194
|
+
await notification_detector_util_1.DyE2E_NotificationDetector_Util.attach(context);
|
|
195
|
+
page = await context.newPage();
|
|
196
|
+
await page.goto(target.loginUrl, { waitUntil: 'domcontentloaded', timeout: options.navigationTimeoutMs ?? 45_000 });
|
|
197
|
+
await page.waitForTimeout(options.settleMs ?? 5_000);
|
|
198
|
+
// a modal on load is RECORDED (it may be the finding itself), then closed so the form can be used
|
|
199
|
+
await DyE2E_NotificationSweep_Util.captureModalDialogs(page, 'load', notes, dialogs);
|
|
200
|
+
if (mode !== 'no-submit' && !DyE2E_NotificationSweep_Util.isSubmitAllowed(page.url(), options.allowSubmitHosts)) {
|
|
201
|
+
notes.push('submit-refused: ' + new URL(page.url()).hostname + ' is not a test host');
|
|
202
|
+
mode = 'no-submit';
|
|
203
|
+
}
|
|
204
|
+
if (mode !== 'no-submit') {
|
|
205
|
+
let email = probeEmail;
|
|
206
|
+
let password = options.probePassword ?? DyE2E_NotificationSweep_Util.defaultProbePassword;
|
|
207
|
+
if (options.real) {
|
|
208
|
+
if (process.env.E2E_PERSISTENT_USER_EMAIL && process.env.E2E_PERSISTENT_USER_PASSWORD) {
|
|
209
|
+
email = process.env.E2E_PERSISTENT_USER_EMAIL;
|
|
210
|
+
password = process.env.E2E_PERSISTENT_USER_PASSWORD;
|
|
211
|
+
mode = 'real';
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
notes.push('real requested, E2E_PERSISTENT_USER_EMAIL/_PASSWORD not set: wrong-password probe used');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
submitted = await DyE2E_NotificationSweep_Util.submitLogin(page, email, password, notes);
|
|
218
|
+
if (submitted) {
|
|
219
|
+
await page.waitForTimeout(options.afterSubmitMs ?? 9_000);
|
|
220
|
+
await DyE2E_NotificationSweep_Util.captureModalDialogs(page, 'after-submit', notes, dialogs);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
notes.push('flow-error: ' + (error instanceof Error ? error.message : String(error)).split('\n')[0].slice(0, 140));
|
|
226
|
+
}
|
|
227
|
+
const report = page
|
|
228
|
+
? await notification_detector_util_1.DyE2E_NotificationDetector_Util.collect(page)
|
|
229
|
+
: { notifications: [], visibleErrors: [], consoleErrors: [], pageErrors: [] };
|
|
230
|
+
const reachedUrl = page ? page.url() : target.loginUrl;
|
|
231
|
+
await context.close();
|
|
232
|
+
const leakingDialogs = dialogs.filter((d) => d.rawTechnicalLeak).length;
|
|
233
|
+
return {
|
|
234
|
+
report: report,
|
|
235
|
+
dialogs: dialogs,
|
|
236
|
+
row: {
|
|
237
|
+
key: target.key,
|
|
238
|
+
loginUrl: target.loginUrl,
|
|
239
|
+
reachedUrl: reachedUrl,
|
|
240
|
+
mode: mode,
|
|
241
|
+
submitted: submitted,
|
|
242
|
+
notifications: report.notifications.length,
|
|
243
|
+
errorOrWarning: report.notifications.filter((n) => n.type === 'error' || n.type === 'warning').length,
|
|
244
|
+
banners: report.visibleErrors.length,
|
|
245
|
+
dialogs: dialogs.length,
|
|
246
|
+
leaks: report.visibleErrors.filter((e) => e.rawTechnicalLeak).length
|
|
247
|
+
+ leakingDialogs,
|
|
248
|
+
consoleErrors: report.consoleErrors.filter((c) => c.type === 'error').length,
|
|
249
|
+
pageErrors: report.pageErrors.length,
|
|
250
|
+
note: notes.join(' · '),
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Records, then closes the MODAL dialogs (cdk overlay, `aria-modal="true"`, `alertdialog`) — measured 2026-09-24:
|
|
256
|
+
* - on 3 of 7 TEST sites a "This is NOT the production system" notice covered the login (every click hit it);
|
|
257
|
+
* - on one, the modal WAS the finding: "An unexpected error occurred: this.… is not a function" on page load —
|
|
258
|
+
* so every dialog is recorded (text + raw-technical-leak flag) BEFORE it is closed, never silently swept away.
|
|
259
|
+
* A non-modal `role="dialog"` (a cookie-consent bar) does not block the page and is left alone. Escape first, then
|
|
260
|
+
* the dialog's own action button; a modal that stays open stops the loop (named in the note).
|
|
261
|
+
*/
|
|
262
|
+
static async captureModalDialogs(page, phase, notes, dialogs) {
|
|
263
|
+
for (let round = 0; round < 3; round++) {
|
|
264
|
+
const dialog = page.locator('.cdk-overlay-container [role="dialog"]:visible, '
|
|
265
|
+
+ '.cdk-overlay-container mat-dialog-container:visible, [role="dialog"][aria-modal="true"]:visible, '
|
|
266
|
+
+ '[role="alertdialog"]:visible').first();
|
|
267
|
+
if (!await dialog.count()) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const fullText = ((await dialog.textContent()) ?? '').replace(/\s+/g, ' ').trim().slice(0, 300);
|
|
271
|
+
const text = fullText.slice(0, 70);
|
|
272
|
+
dialogs.push({
|
|
273
|
+
phase: phase,
|
|
274
|
+
text: fullText,
|
|
275
|
+
rawTechnicalLeak: notification_detector_util_1.DyE2E_NotificationDetector_Util.isRawTechnicalLeak(fullText),
|
|
276
|
+
});
|
|
277
|
+
await page.keyboard.press('Escape');
|
|
278
|
+
await page.waitForTimeout(300);
|
|
279
|
+
if (await dialog.isVisible()) {
|
|
280
|
+
const action = dialog.locator('mat-dialog-actions button, [mat-dialog-actions] button, button').last();
|
|
281
|
+
if (await action.count()) {
|
|
282
|
+
await action.click({ timeout: 3_000 }).catch(() => undefined);
|
|
283
|
+
await page.waitForTimeout(300);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const stillOpen = await dialog.isVisible();
|
|
287
|
+
notes.push(phase + ' dialog: "' + text + '"' + (stillOpen ? ' (it stayed open)' : ' (closed)'));
|
|
288
|
+
if (stillOpen) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/** Fills the login form and submits it; a missing field is a note, not a crash. */
|
|
294
|
+
static async submitLogin(page, email, password, notes) {
|
|
295
|
+
const passwordField = page.locator('input[type="password"]').first();
|
|
296
|
+
if (!await passwordField.count()) {
|
|
297
|
+
notes.push('submit-skip: no password field on the page');
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
await page.locator(DyE2E_NotificationSweep_Util.emailSelector).first().fill(email, { timeout: 8_000 });
|
|
301
|
+
await passwordField.fill(password, { timeout: 8_000 });
|
|
302
|
+
const button = page.locator(DyE2E_NotificationSweep_Util.submitSelector).first();
|
|
303
|
+
if (await button.count()) {
|
|
304
|
+
await button.click({ timeout: 8_000 });
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
await passwordField.press('Enter');
|
|
308
|
+
}
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
/** CLI flags → sweep options. */
|
|
312
|
+
static optionsFromFlags(flags, list) {
|
|
313
|
+
const number = (value) => (value && !Number.isNaN(Number(value)) ? Number(value) : undefined);
|
|
314
|
+
return {
|
|
315
|
+
submit: !flags['no-submit'],
|
|
316
|
+
real: !!flags.real,
|
|
317
|
+
probeEmail: flags['probe-email'],
|
|
318
|
+
ownDomains: list(flags['own-domains']),
|
|
319
|
+
allowSubmitHosts: list(flags['allow-hosts']),
|
|
320
|
+
settleMs: number(flags['settle-ms']),
|
|
321
|
+
afterSubmitMs: number(flags['after-submit-ms']),
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
exports.DyE2E_NotificationSweep_Util = DyE2E_NotificationSweep_Util;
|
|
326
|
+
//# sourceMappingURL=notification-sweep.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-sweep.util.js","sourceRoot":"","sources":["../../../../src/_modules/runtime/_collections/notification-sweep.util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Severity of a captured notification, read from the DyNX colour classes / snackbar panel class / mat-icon. */
|
|
2
|
+
export type DyE2E_NotificationType = 'error' | 'warning' | 'success' | 'info' | 'unknown';
|
|
3
|
+
/** Which UI surface produced the notification. */
|
|
4
|
+
export type DyE2E_NotificationKind = 'dynx-card' | 'notif-area' | 'snackbar' | 'role-alert';
|
|
5
|
+
/**
|
|
6
|
+
* One user-visible notification, recorded at the moment it APPEARED in the DOM (BFR-QA-001) —
|
|
7
|
+
* so it is in the report even if it auto-dismissed before collection.
|
|
8
|
+
*/
|
|
9
|
+
export interface DyE2E_Notification_Interface {
|
|
10
|
+
/** Unique per capture (`<document time origin>-<counter>`); an enriched re-read keeps the same id. */
|
|
11
|
+
id: string;
|
|
12
|
+
kind: DyE2E_NotificationKind;
|
|
13
|
+
type: DyE2E_NotificationType;
|
|
14
|
+
/** Title (DyNX `.text-slate-700`, snackbar label) — falls back to the whole text. */
|
|
15
|
+
title: string;
|
|
16
|
+
/** DyNX body text (`.text-slate-500`), empty when there is none. */
|
|
17
|
+
message: string;
|
|
18
|
+
/** `location.href` of the document the notification appeared in. */
|
|
19
|
+
url: string;
|
|
20
|
+
/** Wall-clock time of the appearance (epoch ms). */
|
|
21
|
+
at: number;
|
|
22
|
+
/** Milliseconds since that document started loading (`performance.now()`). */
|
|
23
|
+
sinceDocumentStartMs: number;
|
|
24
|
+
/** Whitespace-collapsed `outerHTML`, capped at 500 chars. */
|
|
25
|
+
html: string;
|
|
26
|
+
}
|
|
27
|
+
/** A visible, persistent (non-toast) error banner or inline error text at collection time. */
|
|
28
|
+
export interface DyE2E_VisibleError_Interface {
|
|
29
|
+
tag: string;
|
|
30
|
+
cls: string;
|
|
31
|
+
text: string;
|
|
32
|
+
/** The text leaks raw technical detail to the user (`Http failure response`, `/api/`, `[object Object]` …). */
|
|
33
|
+
rawTechnicalLeak: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** A `console.error` / `console.warn` message of the page. */
|
|
36
|
+
export interface DyE2E_ConsoleEntry_Interface {
|
|
37
|
+
type: string;
|
|
38
|
+
text: string;
|
|
39
|
+
url: string;
|
|
40
|
+
}
|
|
41
|
+
/** An uncaught page exception (`pageerror`). */
|
|
42
|
+
export interface DyE2E_PageError_Interface {
|
|
43
|
+
text: string;
|
|
44
|
+
url: string;
|
|
45
|
+
}
|
|
46
|
+
/** Everything the notification detector knows about one page. */
|
|
47
|
+
export interface DyE2E_NotificationReport_Interface {
|
|
48
|
+
/** In order of appearance, across every document the page navigated through. */
|
|
49
|
+
notifications: DyE2E_Notification_Interface[];
|
|
50
|
+
visibleErrors: DyE2E_VisibleError_Interface[];
|
|
51
|
+
consoleErrors: DyE2E_ConsoleEntry_Interface[];
|
|
52
|
+
pageErrors: DyE2E_PageError_Interface[];
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=notification-report.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-report.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/runtime/_models/notification-report.interface.ts"],"names":[],"mappings":"AAAA,gHAAgH;AAChH,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE1F,kDAAkD;AAClD,MAAM,MAAM,sBAAsB,GAAG,WAAW,GAAG,YAAY,GAAG,UAAU,GAAG,YAAY,CAAC;AAE5F;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IAC3C,sGAAsG;IACtG,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,sBAAsB,CAAC;IAC7B,IAAI,EAAE,sBAAsB,CAAC;IAC7B,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,oBAAoB,EAAE,MAAM,CAAC;IAC7B,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8FAA8F;AAC9F,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,+GAA+G;IAC/G,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,8DAA8D;AAC9D,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,gDAAgD;AAChD,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,iEAAiE;AACjE,MAAM,WAAW,kCAAkC;IACjD,gFAAgF;IAChF,aAAa,EAAE,4BAA4B,EAAE,CAAC;IAC9C,aAAa,EAAE,4BAA4B,EAAE,CAAC;IAC9C,aAAa,EAAE,4BAA4B,EAAE,CAAC;IAC9C,UAAU,EAAE,yBAAyB,EAAE,CAAC;CACzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-report.interface.js","sourceRoot":"","sources":["../../../../src/_modules/runtime/_models/notification-report.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { BrowserContext } from '@playwright/test';
|
|
2
|
+
import { DyE2E_NotificationReport_Interface } from './notification-report.interface';
|
|
3
|
+
/** One project of a notification sweep: a name and its login page. */
|
|
4
|
+
export interface DyE2E_SweepTarget_Interface {
|
|
5
|
+
key: string;
|
|
6
|
+
loginUrl: string;
|
|
7
|
+
}
|
|
8
|
+
/** How a target was driven. */
|
|
9
|
+
export type DyE2E_SweepMode = 'probe' | 'real' | 'no-submit';
|
|
10
|
+
/** One matrix row of a sweep (BFR-QA-002). */
|
|
11
|
+
export interface DyE2E_SweepRow_Interface {
|
|
12
|
+
key: string;
|
|
13
|
+
loginUrl: string;
|
|
14
|
+
/** Where the page ended up after the flow. */
|
|
15
|
+
reachedUrl: string;
|
|
16
|
+
mode: DyE2E_SweepMode;
|
|
17
|
+
/** The login form was really submitted. */
|
|
18
|
+
submitted: boolean;
|
|
19
|
+
notifications: number;
|
|
20
|
+
errorOrWarning: number;
|
|
21
|
+
banners: number;
|
|
22
|
+
/** Modal dialogs seen (on load or after the submit) — each recorded before it was closed. */
|
|
23
|
+
dialogs: number;
|
|
24
|
+
/** Banners AND dialogs that leak raw technical detail (`Http failure response`, `/api/`, `… is not a function`). */
|
|
25
|
+
leaks: number;
|
|
26
|
+
consoleErrors: number;
|
|
27
|
+
pageErrors: number;
|
|
28
|
+
/** Why something was skipped / refused / fell back (empty = the full flow ran). */
|
|
29
|
+
note: string;
|
|
30
|
+
}
|
|
31
|
+
/** A modal dialog the sweep met (and closed) — it may be the finding itself. */
|
|
32
|
+
export interface DyE2E_SweepDialog_Interface {
|
|
33
|
+
phase: 'load' | 'after-submit';
|
|
34
|
+
/** Whitespace-collapsed text, capped at 300 chars. */
|
|
35
|
+
text: string;
|
|
36
|
+
rawTechnicalLeak: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** A row plus the full detector report and the dialogs behind it. */
|
|
39
|
+
export interface DyE2E_SweepOutcome_Interface {
|
|
40
|
+
row: DyE2E_SweepRow_Interface;
|
|
41
|
+
report: DyE2E_NotificationReport_Interface;
|
|
42
|
+
dialogs: DyE2E_SweepDialog_Interface[];
|
|
43
|
+
}
|
|
44
|
+
/** Options of a sweep. */
|
|
45
|
+
export interface DyE2E_SweepOptions_Interface {
|
|
46
|
+
/** Submit the login form (default `true`); `false` = only load the page. */
|
|
47
|
+
submit?: boolean;
|
|
48
|
+
/** Use the registered test account from `E2E_PERSISTENT_USER_EMAIL` / `_PASSWORD` (default `false`). */
|
|
49
|
+
real?: boolean;
|
|
50
|
+
/** Probe e-mail (default `dye2e-sweep-probe@example.com`); must be on a reserved or an `ownDomains` domain. */
|
|
51
|
+
probeEmail?: string;
|
|
52
|
+
/** Probe password (default: a fixed wrong password). */
|
|
53
|
+
probePassword?: string;
|
|
54
|
+
/** Your own e-mail domains, allowed for `probeEmail` besides the reserved ones. */
|
|
55
|
+
ownDomains?: string[];
|
|
56
|
+
/** Hosts the form may be submitted to besides the test hosts (`test.*`, `*.test`, `localhost` …). */
|
|
57
|
+
allowSubmitHosts?: string[];
|
|
58
|
+
/** Wait after the page load before submitting (default 5000 ms). */
|
|
59
|
+
settleMs?: number;
|
|
60
|
+
/** Wait after the submit for the notifications (default 9000 ms). */
|
|
61
|
+
afterSubmitMs?: number;
|
|
62
|
+
/** Per-navigation timeout (default 45000 ms). */
|
|
63
|
+
navigationTimeoutMs?: number;
|
|
64
|
+
/** Called for every new context before the detector is attached (routing mocks, headers …). */
|
|
65
|
+
prepareContext?: (context: BrowserContext) => Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=notification-sweep.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-sweep.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/runtime/_models/notification-sweep.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,kCAAkC,EAAE,MAAM,iCAAiC,CAAC;AAErF,sEAAsE;AACtE,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,+BAA+B;AAC/B,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC;AAE7D,8CAA8C;AAC9C,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,eAAe,CAAC;IACtB,2CAA2C;IAC3C,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,OAAO,EAAE,MAAM,CAAC;IAChB,oHAAoH;IACpH,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;CACd;AAED,gFAAgF;AAChF,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,GAAG,cAAc,CAAC;IAC/B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,qEAAqE;AACrE,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,wBAAwB,CAAC;IAC9B,MAAM,EAAE,kCAAkC,CAAC;IAC3C,OAAO,EAAE,2BAA2B,EAAE,CAAC;CACxC;AAED,0BAA0B;AAC1B,MAAM,WAAW,4BAA4B;IAC3C,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wGAAwG;IACxG,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+GAA+G;IAC/G,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,qGAAqG;IACrG,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+FAA+F;IAC/F,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-sweep.interface.js","sourceRoot":"","sources":["../../../../src/_modules/runtime/_models/notification-sweep.interface.ts"],"names":[],"mappings":""}
|
|
@@ -13,9 +13,14 @@
|
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
15
|
export * from './_collections/assertion-helpers.util';
|
|
16
|
+
export * from './_collections/notification-detector-page-script.const';
|
|
17
|
+
export * from './_collections/notification-detector.util';
|
|
18
|
+
export * from './_collections/notification-sweep.util';
|
|
16
19
|
export * from './_collections/unique-generator.util';
|
|
17
20
|
export * from './_collections/wait-helpers.util';
|
|
18
21
|
export * from './_models/index';
|
|
22
|
+
export * from './_models/notification-report.interface';
|
|
23
|
+
export * from './_models/notification-sweep.interface';
|
|
19
24
|
export * from './_models/test-user.interface';
|
|
20
25
|
export * from './_services/dialog-page-object';
|
|
21
26
|
export * from './_services/field-page-object';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/_modules/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AACrD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,YAAY,CAAC;AAE3B,eAAO,MAAM,qBAAqB,EAAE,MAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/_modules/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,cAAc,uCAAuC,CAAC;AACtD,cAAc,wDAAwD,CAAC;AACvE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC;AACrD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,YAAY,CAAC;AAE3B,eAAO,MAAM,qBAAqB,EAAE,MAAwB,CAAC"}
|
|
@@ -30,9 +30,14 @@ exports.DYE2E_RUNTIME_VERSION = void 0;
|
|
|
30
30
|
* ```
|
|
31
31
|
*/
|
|
32
32
|
__exportStar(require("./_collections/assertion-helpers.util"), exports);
|
|
33
|
+
__exportStar(require("./_collections/notification-detector-page-script.const"), exports);
|
|
34
|
+
__exportStar(require("./_collections/notification-detector.util"), exports);
|
|
35
|
+
__exportStar(require("./_collections/notification-sweep.util"), exports);
|
|
33
36
|
__exportStar(require("./_collections/unique-generator.util"), exports);
|
|
34
37
|
__exportStar(require("./_collections/wait-helpers.util"), exports);
|
|
35
38
|
__exportStar(require("./_models/index"), exports);
|
|
39
|
+
__exportStar(require("./_models/notification-report.interface"), exports);
|
|
40
|
+
__exportStar(require("./_models/notification-sweep.interface"), exports);
|
|
36
41
|
__exportStar(require("./_models/test-user.interface"), exports);
|
|
37
42
|
__exportStar(require("./_services/dialog-page-object"), exports);
|
|
38
43
|
__exportStar(require("./_services/field-page-object"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/_modules/runtime/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;GAaG;AACH,wEAAsD;AACtD,uEAAqD;AACrD,mEAAiD;AACjD,kDAAgC;AAChC,gEAA8C;AAC9C,iEAA+C;AAC/C,gEAA8C;AAC9C,+DAA6C;AAC7C,iEAA+C;AAC/C,6DAA2C;AAC3C,qEAAmD;AACnD,8DAA4C;AAC5C,gEAA8C;AAC9C,mEAAiD;AACjD,6CAA2B;AAEd,QAAA,qBAAqB,GAAW,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/_modules/runtime/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;GAaG;AACH,wEAAsD;AACtD,yFAAuE;AACvE,4EAA0D;AAC1D,yEAAuD;AACvD,uEAAqD;AACrD,mEAAiD;AACjD,kDAAgC;AAChC,0EAAwD;AACxD,yEAAuD;AACvD,gEAA8C;AAC9C,iEAA+C;AAC/C,gEAA8C;AAC9C,+DAA6C;AAC7C,iEAA+C;AAC/C,6DAA2C;AAC3C,qEAAmD;AACnD,8DAA4C;AAC5C,gEAA8C;AAC9C,mEAAiD;AACjD,6CAA2B;AAEd,QAAA,qBAAqB,GAAW,eAAe,CAAC"}
|
package/build/index.js
CHANGED
|
@@ -24,5 +24,5 @@ __exportStar(require("./_modules/cwv/index"), exports);
|
|
|
24
24
|
__exportStar(require("./_modules/vqa/index"), exports);
|
|
25
25
|
__exportStar(require("./_modules/game/index"), exports);
|
|
26
26
|
/** Package-version stamp — npm-publish-time runtime-érték. */
|
|
27
|
-
exports.DYE2E_PACKAGE_VERSION = '01.18.
|
|
27
|
+
exports.DYE2E_PACKAGE_VERSION = '01.18.16';
|
|
28
28
|
//# sourceMappingURL=index.js.map
|