@futdevpro/fdp-e2e-helpers 1.15.16 → 1.15.19
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/README.md +50 -0
- package/build/_models/interfaces/e2e-login-config.interface.d.ts +59 -0
- package/build/_models/interfaces/e2e-login-config.interface.js +3 -0
- package/build/_models/interfaces/e2e-login-result.interface.d.ts +21 -0
- package/build/_models/interfaces/e2e-login-result.interface.js +3 -0
- package/build/_services/e2e-login-helper.service.d.ts +83 -0
- package/build/_services/e2e-login-helper.service.js +165 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +3 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -39,6 +39,55 @@ user-management.md`).
|
|
|
39
39
|
- **Server env loader**: `global-env-settings.util.ts` THROWS if
|
|
40
40
|
`E2E_HARD_DELETE_KEY` is set on a production environment.
|
|
41
41
|
|
|
42
|
+
## `FDP_CWV_Collector_Util` — Core Web Vitals diagnostics
|
|
43
|
+
|
|
44
|
+
Scripted, synthetic Core Web Vitals (LCP / INP / CLS + attribution) measurement on
|
|
45
|
+
top of Playwright. The reusable Dynamo-level primitive behind the E2E "step-0" CWV
|
|
46
|
+
diagnostic. **Canonical guide:** `documentations/guidelines/development/cwv-diagnostics.md`.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { FDP_CWV_Collector_Util } from '@futdevpro/fdp-e2e-helpers';
|
|
50
|
+
|
|
51
|
+
// In an e2e spec (consumer supplies the web-vitals IIFE source as a string):
|
|
52
|
+
const result = await FDP_CWV_Collector_Util.collect(page, {
|
|
53
|
+
routes: [{ path: '/main/home', label: 'Home', interact: async p => { /* real click for INP */ } }],
|
|
54
|
+
webVitalsScript, // see resolve note below
|
|
55
|
+
componentPrefixes: ['s-', 'ad-', 'm1-', 'app-'], // attribution target → component-level
|
|
56
|
+
budgets: { lcpMs: 2500, inpMs: 200, cls: 0.1 }, // report-only (warn, not fail)
|
|
57
|
+
});
|
|
58
|
+
FDP_CWV_Collector_Util.writeResult(result, 'cwv-result.json');
|
|
59
|
+
// pipeline emits the [CDP_STEP_RESULT] marker AFTER playwright:
|
|
60
|
+
// node -e "require('@futdevpro/fdp-e2e-helpers').FDP_CWV_Collector_Util.emitMarkerFromFile('cwv-result.json')"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**API**: `collect` / `writeResult` / `emitMarkerFromFile` / `printStepResultMarker` /
|
|
64
|
+
`buildSummaryLine` + pure `rate` / `evaluateBudgets` / `summarizeWorst` / `buildRouteResult`.
|
|
65
|
+
|
|
66
|
+
**Why the consumer supplies `webVitalsScript` as a string** — this package deliberately
|
|
67
|
+
does NOT import `web-vitals` (keeps it dependency-light + no `require()` in shipped code).
|
|
68
|
+
The consuming e2e project reads the IIFE bundle and passes it in.
|
|
69
|
+
|
|
70
|
+
> ⚠ **web-vitals v4 `exports`-map gotcha (KÖTELEZŐ olvasni)**: the v4 package has a
|
|
71
|
+
> STRICT `exports` map — it does NOT export `./dist/*` subpaths NOR `./package.json`,
|
|
72
|
+
> so `require.resolve('web-vitals/dist/...')` AND `require.resolve('web-vitals/package.json')`
|
|
73
|
+
> both throw `ERR_PACKAGE_PATH_NOT_EXPORTED`. Resolve an ALLOWED entry point instead and
|
|
74
|
+
> walk to its `dist/`:
|
|
75
|
+
> ```ts
|
|
76
|
+
> const distDir = path.dirname(require.resolve('web-vitals/attribution'));
|
|
77
|
+
> const src = fs.readFileSync(path.join(distDir, 'web-vitals.attribution.iife.js'), 'utf-8');
|
|
78
|
+
> ```
|
|
79
|
+
|
|
80
|
+
> ⚠ **Playwright `addInitScript` + IIFE `var` gotcha**: the web-vitals IIFE does
|
|
81
|
+
> `var webVitals=...`, but `addInitScript` wraps the script in a function scope, so the
|
|
82
|
+
> top-level `var` never reaches `window`. The collector handles this internally by
|
|
83
|
+
> appending `;self.webVitals=self.webVitals||webVitals;` to the injected script.
|
|
84
|
+
|
|
85
|
+
**INP note**: synthetic/headless INP is best-effort (Event Timing API unreliable without
|
|
86
|
+
real user input) → often `undefined`. Trustworthy INP comes from the RUM phase. LCP/CLS/FCP/TTFB
|
|
87
|
+
are reliable.
|
|
88
|
+
|
|
89
|
+
`@playwright/test` is a **peer dependency** (the consuming e2e project already has it).
|
|
90
|
+
|
|
42
91
|
## Why stateless `*_Util` (not singleton service)
|
|
43
92
|
|
|
44
93
|
- Multi-worker parallel-test-safe — no shared instance state across Playwright
|
|
@@ -52,6 +101,7 @@ user-management.md`).
|
|
|
52
101
|
| Layer | Status |
|
|
53
102
|
|---|---|
|
|
54
103
|
| `E2E_HardDelete_Util` (account cascade) | ✅ v01.15.0 |
|
|
104
|
+
| `FDP_CWV_Collector_Util` (Core Web Vitals diag) | ✅ v01.15.14 — live-verified (organizer, 2026-06-01) |
|
|
55
105
|
| `E2E_UserManagerService` lift-up | ⏳ next PR |
|
|
56
106
|
| `E2E_ConfigService` lift-up | ⏳ later |
|
|
57
107
|
| `E2E_UiHelperService` lift-up | ⏳ later (Playwright dep boundary TBD) |
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E_LoginConfig_Interface — a `E2E_LoginHelperService.setConfig()` bemenete.
|
|
3
|
+
*
|
|
4
|
+
* Cel: a helper TARGET-AGNOSTIC. Egy konzument (Overseer, organizer, …) sajat
|
|
5
|
+
* `e2e-global-setup.ts`-jeben egyszer kitolti a configot az adott rendszer
|
|
6
|
+
* URL-jevel, route-javal, credentials-evel. A helper NEM ismeri a konzument.
|
|
7
|
+
*
|
|
8
|
+
* @see _services/e2e-login-helper.service.ts
|
|
9
|
+
*/
|
|
10
|
+
export interface E2E_LoginConfig_Interface {
|
|
11
|
+
/**
|
|
12
|
+
* Host-app base URL — `https://test.overseer.futdevpro.hu` szeru.
|
|
13
|
+
* NEM tartalmaz path-ot, csak host+protocol.
|
|
14
|
+
*/
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
/**
|
|
17
|
+
* Login route a baseUrl-en belul. Default: `'/'` (a guard-redirect a
|
|
18
|
+
* login-page-re iranyit). Pontos `/login` is megadhato ha a hostnak nincs
|
|
19
|
+
* guard-mehanikaja.
|
|
20
|
+
*/
|
|
21
|
+
loginRoute?: string;
|
|
22
|
+
/**
|
|
23
|
+
* A login utan elvart URL regex. Pl. `/test\.overseer/` → barmi a test
|
|
24
|
+
* overseer hoston (root dashboardra erkezve passol).
|
|
25
|
+
*/
|
|
26
|
+
postLoginUrlPattern: RegExp;
|
|
27
|
+
/**
|
|
28
|
+
* Persistent test-user credentials. `username` ES/VAGY `email` — a
|
|
29
|
+
* FDPNX_Acc_Login `usernameEmail` mezo barmelyiket elfogadja.
|
|
30
|
+
*/
|
|
31
|
+
persistentUser: {
|
|
32
|
+
email?: string;
|
|
33
|
+
username?: string;
|
|
34
|
+
password: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Selector-override-ok. Default a FDPNX_Acc_Login_Component Forms v2-es
|
|
38
|
+
* `data-testid`-jeit hasznalja.
|
|
39
|
+
*/
|
|
40
|
+
testIds?: {
|
|
41
|
+
/** username input `data-testid`. Default: `'login-username-text'` (Forms v2 TextField testId-pattern). */
|
|
42
|
+
username?: string;
|
|
43
|
+
/** password input `data-testid`. Default: `'login-password-password'`. */
|
|
44
|
+
password?: string;
|
|
45
|
+
/** submit button name (regex VAGY string). Default: `/Bejelentkezés|Login/`. */
|
|
46
|
+
submit?: string | RegExp;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Login-POST regex amit a helper `waitForResponse`-pel observal.
|
|
50
|
+
* Default: `/\/api\/auth\/login/`.
|
|
51
|
+
*/
|
|
52
|
+
loginApiPattern?: RegExp;
|
|
53
|
+
/**
|
|
54
|
+
* sessionStorage kulcs a token-snapshot kinyereshez. Default `'token'`.
|
|
55
|
+
* Wave-2-ben a FDP_Auth_StorageKey enum hozhatja.
|
|
56
|
+
*/
|
|
57
|
+
tokenStorageKey?: string;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=e2e-login-config.interface.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `E2E_LoginHelperService.loginWithPersistentUser()` visszateres-shape.
|
|
3
|
+
*
|
|
4
|
+
* `alreadyAuthenticated: true` eset:
|
|
5
|
+
* A login form NEM jelent meg a configurabilis varakozas alatt → a host
|
|
6
|
+
* eleve auth-elt sessiont talalt (pl. storageState reuse). A helper
|
|
7
|
+
* ezt NEM tekinti hibanak, csak jelzi.
|
|
8
|
+
*
|
|
9
|
+
* Sikeres login-flow eset:
|
|
10
|
+
* `loginApiStatus === 200`, `postLoginUrl` a postLoginUrlPattern-rel
|
|
11
|
+
* match-elt URL, `token` a sessionStorage kulcsanak erteke.
|
|
12
|
+
*
|
|
13
|
+
* @see _services/e2e-login-helper.service.ts
|
|
14
|
+
*/
|
|
15
|
+
export interface E2E_LoginResult_Interface {
|
|
16
|
+
alreadyAuthenticated?: boolean;
|
|
17
|
+
loginApiStatus?: number;
|
|
18
|
+
token?: string | null;
|
|
19
|
+
postLoginUrl?: string;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=e2e-login-result.interface.d.ts.map
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Page } from '@playwright/test';
|
|
2
|
+
import { DyNTS_SingletonService } from '@futdevpro/nts-dynamo';
|
|
3
|
+
import { E2E_LoginConfig_Interface } from '../_models/interfaces/e2e-login-config.interface';
|
|
4
|
+
import { E2E_LoginResult_Interface } from '../_models/interfaces/e2e-login-result.interface';
|
|
5
|
+
/**
|
|
6
|
+
* `E2E_LoginHelperService` — Playwright login flow helper a FDPNX_Acc_Login_Component
|
|
7
|
+
* (Forms v2) felulet ellen.
|
|
8
|
+
*
|
|
9
|
+
* Target-agnostic: NEM tartalmaz beegetett URL-t, route-ot, vagy creds-et —
|
|
10
|
+
* a konzument `setConfig()`-pel adja meg a host-app-specifikus ertekeket.
|
|
11
|
+
* Pattern: singleton, `DyNTS_SingletonService`-bol szarmaztatva (peerDep
|
|
12
|
+
* `@futdevpro/nts-dynamo`). Lasd `E2E_UserManagerService`-t azonos mintaval.
|
|
13
|
+
*
|
|
14
|
+
* Hasznalat (konzument oldalon):
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // e2e-global-setup.ts
|
|
17
|
+
* import { E2E_LoginHelperService } from '@futdevpro/fdp-e2e-helpers';
|
|
18
|
+
*
|
|
19
|
+
* E2E_LoginHelperService.getInstance().setConfig({
|
|
20
|
+
* baseUrl: process.env.E2E_BASE_URL!,
|
|
21
|
+
* loginRoute: '/',
|
|
22
|
+
* postLoginUrlPattern: /test\.overseer\.futdevpro\.hu/,
|
|
23
|
+
* persistentUser: {
|
|
24
|
+
* email: process.env.E2E_PERSISTENT_USER_EMAIL,
|
|
25
|
+
* password: process.env.E2E_PERSISTENT_USER_PASSWORD!,
|
|
26
|
+
* },
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // login-flow.spec.ts
|
|
30
|
+
* const login = E2E_LoginHelperService.getInstance();
|
|
31
|
+
* const result = await login.loginWithPersistentUser(page);
|
|
32
|
+
* expect(result.alreadyAuthenticated || result.loginApiStatus === 200).toBe(true);
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @see _specifications/fdp-login-forms-v2-rollout.md (F3)
|
|
36
|
+
*/
|
|
37
|
+
export declare class E2E_LoginHelperService extends DyNTS_SingletonService {
|
|
38
|
+
/** Singleton instance getter. */
|
|
39
|
+
static getInstance(): E2E_LoginHelperService;
|
|
40
|
+
/** Private constructor — singleton-enforcement. */
|
|
41
|
+
private constructor();
|
|
42
|
+
private config;
|
|
43
|
+
/**
|
|
44
|
+
* Target-config beallitas. A konzument cycle-elejen egyszer hivja
|
|
45
|
+
* (`e2e-global-setup.ts`). Tobbszori hivas felulirja a corabbi configot.
|
|
46
|
+
*/
|
|
47
|
+
setConfig(config: E2E_LoginConfig_Interface): void;
|
|
48
|
+
/** A jelenleg-aktiv config (testing + introspection). `null` ha nem volt setConfig. */
|
|
49
|
+
getConfig(): E2E_LoginConfig_Interface | null;
|
|
50
|
+
/**
|
|
51
|
+
* Persistent-user login a beallitott config alapjan.
|
|
52
|
+
*
|
|
53
|
+
* Skip-modok:
|
|
54
|
+
* - `config` nincs allitva → `DyFM_Error` dob.
|
|
55
|
+
* - A login form NEM lathato `opts.formVisibleTimeoutMs`-en belul →
|
|
56
|
+
* `{ alreadyAuthenticated: true }` (NEM hiba — `setupState reuse` scenario).
|
|
57
|
+
*
|
|
58
|
+
* Flow:
|
|
59
|
+
* 1. `page.goto(baseUrl + loginRoute)`
|
|
60
|
+
* 2. username + password fill
|
|
61
|
+
* 3. submit click
|
|
62
|
+
* 4. `waitForResponse(loginApiPattern)` → loginApiStatus
|
|
63
|
+
* 5. `waitForURL(postLoginUrlPattern)` → postLoginUrl
|
|
64
|
+
* 6. `extractToken(page)` → token
|
|
65
|
+
*/
|
|
66
|
+
loginWithPersistentUser(page: Page, opts?: {
|
|
67
|
+
/** Login form input megjeleneseig var-as. Default 5000ms. */
|
|
68
|
+
formVisibleTimeoutMs?: number;
|
|
69
|
+
/** Login POST response varakozas. Default 20000ms. */
|
|
70
|
+
loginRespTimeoutMs?: number;
|
|
71
|
+
/** Post-login URL-redirect varakozas. Default 20000ms. */
|
|
72
|
+
postLoginUrlTimeoutMs?: number;
|
|
73
|
+
}): Promise<E2E_LoginResult_Interface>;
|
|
74
|
+
/**
|
|
75
|
+
* Token snapshot `sessionStorage`-bol. Default kulcs `'token'` vagy a
|
|
76
|
+
* configban beallitott `tokenStorageKey`. Konfig-mentes is hasznalhato
|
|
77
|
+
* (storageKey explicit param-mal).
|
|
78
|
+
*/
|
|
79
|
+
extractToken(page: Page, storageKey?: string): Promise<string | null>;
|
|
80
|
+
/** Internal: throw if `setConfig()` nem volt meghivva. */
|
|
81
|
+
private requireConfig;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=e2e-login-helper.service.d.ts.map
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.E2E_LoginHelperService = void 0;
|
|
4
|
+
const fsm_dynamo_1 = require("@futdevpro/fsm-dynamo");
|
|
5
|
+
const nts_dynamo_1 = require("@futdevpro/nts-dynamo");
|
|
6
|
+
/**
|
|
7
|
+
* `E2E_LoginHelperService` — Playwright login flow helper a FDPNX_Acc_Login_Component
|
|
8
|
+
* (Forms v2) felulet ellen.
|
|
9
|
+
*
|
|
10
|
+
* Target-agnostic: NEM tartalmaz beegetett URL-t, route-ot, vagy creds-et —
|
|
11
|
+
* a konzument `setConfig()`-pel adja meg a host-app-specifikus ertekeket.
|
|
12
|
+
* Pattern: singleton, `DyNTS_SingletonService`-bol szarmaztatva (peerDep
|
|
13
|
+
* `@futdevpro/nts-dynamo`). Lasd `E2E_UserManagerService`-t azonos mintaval.
|
|
14
|
+
*
|
|
15
|
+
* Hasznalat (konzument oldalon):
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // e2e-global-setup.ts
|
|
18
|
+
* import { E2E_LoginHelperService } from '@futdevpro/fdp-e2e-helpers';
|
|
19
|
+
*
|
|
20
|
+
* E2E_LoginHelperService.getInstance().setConfig({
|
|
21
|
+
* baseUrl: process.env.E2E_BASE_URL!,
|
|
22
|
+
* loginRoute: '/',
|
|
23
|
+
* postLoginUrlPattern: /test\.overseer\.futdevpro\.hu/,
|
|
24
|
+
* persistentUser: {
|
|
25
|
+
* email: process.env.E2E_PERSISTENT_USER_EMAIL,
|
|
26
|
+
* password: process.env.E2E_PERSISTENT_USER_PASSWORD!,
|
|
27
|
+
* },
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // login-flow.spec.ts
|
|
31
|
+
* const login = E2E_LoginHelperService.getInstance();
|
|
32
|
+
* const result = await login.loginWithPersistentUser(page);
|
|
33
|
+
* expect(result.alreadyAuthenticated || result.loginApiStatus === 200).toBe(true);
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @see _specifications/fdp-login-forms-v2-rollout.md (F3)
|
|
37
|
+
*/
|
|
38
|
+
class E2E_LoginHelperService extends nts_dynamo_1.DyNTS_SingletonService {
|
|
39
|
+
/** Singleton instance getter. */
|
|
40
|
+
static getInstance() {
|
|
41
|
+
return E2E_LoginHelperService.getSingletonInstance();
|
|
42
|
+
}
|
|
43
|
+
/** Private constructor — singleton-enforcement. */
|
|
44
|
+
constructor() {
|
|
45
|
+
super();
|
|
46
|
+
}
|
|
47
|
+
config = null;
|
|
48
|
+
/**
|
|
49
|
+
* Target-config beallitas. A konzument cycle-elejen egyszer hivja
|
|
50
|
+
* (`e2e-global-setup.ts`). Tobbszori hivas felulirja a corabbi configot.
|
|
51
|
+
*/
|
|
52
|
+
setConfig(config) {
|
|
53
|
+
if (!config.baseUrl) {
|
|
54
|
+
throw new fsm_dynamo_1.DyFM_Error({
|
|
55
|
+
message: 'E2E_LoginHelperService.setConfig: baseUrl is required',
|
|
56
|
+
errorCode: 'FDP-E2E-LH-SC-001',
|
|
57
|
+
issuerService: 'E2E_LoginHelperService',
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (!config.persistentUser?.password) {
|
|
61
|
+
throw new fsm_dynamo_1.DyFM_Error({
|
|
62
|
+
message: 'E2E_LoginHelperService.setConfig: persistentUser.password is required',
|
|
63
|
+
errorCode: 'FDP-E2E-LH-SC-002',
|
|
64
|
+
issuerService: 'E2E_LoginHelperService',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (!config.persistentUser.email && !config.persistentUser.username) {
|
|
68
|
+
throw new fsm_dynamo_1.DyFM_Error({
|
|
69
|
+
message: 'E2E_LoginHelperService.setConfig: persistentUser.email or .username is required',
|
|
70
|
+
errorCode: 'FDP-E2E-LH-SC-003',
|
|
71
|
+
issuerService: 'E2E_LoginHelperService',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
this.config = config;
|
|
75
|
+
fsm_dynamo_1.DyFM_Log.info(`[E2E_LoginHelper] config set: baseUrl=${config.baseUrl}`);
|
|
76
|
+
}
|
|
77
|
+
/** A jelenleg-aktiv config (testing + introspection). `null` ha nem volt setConfig. */
|
|
78
|
+
getConfig() {
|
|
79
|
+
return this.config;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Persistent-user login a beallitott config alapjan.
|
|
83
|
+
*
|
|
84
|
+
* Skip-modok:
|
|
85
|
+
* - `config` nincs allitva → `DyFM_Error` dob.
|
|
86
|
+
* - A login form NEM lathato `opts.formVisibleTimeoutMs`-en belul →
|
|
87
|
+
* `{ alreadyAuthenticated: true }` (NEM hiba — `setupState reuse` scenario).
|
|
88
|
+
*
|
|
89
|
+
* Flow:
|
|
90
|
+
* 1. `page.goto(baseUrl + loginRoute)`
|
|
91
|
+
* 2. username + password fill
|
|
92
|
+
* 3. submit click
|
|
93
|
+
* 4. `waitForResponse(loginApiPattern)` → loginApiStatus
|
|
94
|
+
* 5. `waitForURL(postLoginUrlPattern)` → postLoginUrl
|
|
95
|
+
* 6. `extractToken(page)` → token
|
|
96
|
+
*/
|
|
97
|
+
async loginWithPersistentUser(page, opts = {}) {
|
|
98
|
+
const config = this.requireConfig();
|
|
99
|
+
const formVisibleTimeoutMs = opts.formVisibleTimeoutMs ?? 5_000;
|
|
100
|
+
const loginRespTimeoutMs = opts.loginRespTimeoutMs ?? 20_000;
|
|
101
|
+
const postLoginUrlTimeoutMs = opts.postLoginUrlTimeoutMs ?? 20_000;
|
|
102
|
+
const loginRoute = config.loginRoute ?? '/';
|
|
103
|
+
const usernameTestId = config.testIds?.username ?? 'login-username-text';
|
|
104
|
+
const passwordTestId = config.testIds?.password ?? 'login-password-password';
|
|
105
|
+
const submitName = config.testIds?.submit ?? /Bejelentkezés|Login/;
|
|
106
|
+
const loginApiPattern = config.loginApiPattern ?? /\/api\/auth\/login/;
|
|
107
|
+
const fullUrl = `${config.baseUrl.replace(/\/+$/, '')}${loginRoute}`;
|
|
108
|
+
await page.goto(fullUrl, { timeout: 20_000 });
|
|
109
|
+
// Alreadty-authenticated detection
|
|
110
|
+
const usernameLocator = page.locator(`[data-testid="${usernameTestId}"]`).first();
|
|
111
|
+
const visible = await usernameLocator
|
|
112
|
+
.isVisible({ timeout: formVisibleTimeoutMs })
|
|
113
|
+
.catch(() => false);
|
|
114
|
+
if (!visible) {
|
|
115
|
+
fsm_dynamo_1.DyFM_Log.info('[E2E_LoginHelper] login form not visible → already authenticated');
|
|
116
|
+
return { alreadyAuthenticated: true };
|
|
117
|
+
}
|
|
118
|
+
// Fill creds
|
|
119
|
+
const userValue = (config.persistentUser.email ?? config.persistentUser.username);
|
|
120
|
+
await usernameLocator.fill(userValue);
|
|
121
|
+
await page.locator(`[data-testid="${passwordTestId}"]`).first().fill(config.persistentUser.password);
|
|
122
|
+
// Wait response + click
|
|
123
|
+
const loginRespPromise = page.waitForResponse((resp) => loginApiPattern.test(resp.url()) && resp.request().method() === 'POST', { timeout: loginRespTimeoutMs });
|
|
124
|
+
const submitLocator = typeof submitName === 'string'
|
|
125
|
+
? page.locator(`button:has-text("${submitName}")`).first()
|
|
126
|
+
: page.getByRole('button', { name: submitName }).first();
|
|
127
|
+
await submitLocator.click();
|
|
128
|
+
const loginResp = await loginRespPromise;
|
|
129
|
+
const loginApiStatus = loginResp.status();
|
|
130
|
+
// Wait for post-login URL
|
|
131
|
+
await page.waitForURL(config.postLoginUrlPattern, { timeout: postLoginUrlTimeoutMs });
|
|
132
|
+
const postLoginUrl = page.url();
|
|
133
|
+
// Snapshot token
|
|
134
|
+
const token = await this.extractToken(page);
|
|
135
|
+
return {
|
|
136
|
+
alreadyAuthenticated: false,
|
|
137
|
+
loginApiStatus: loginApiStatus,
|
|
138
|
+
postLoginUrl: postLoginUrl,
|
|
139
|
+
token: token,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Token snapshot `sessionStorage`-bol. Default kulcs `'token'` vagy a
|
|
144
|
+
* configban beallitott `tokenStorageKey`. Konfig-mentes is hasznalhato
|
|
145
|
+
* (storageKey explicit param-mal).
|
|
146
|
+
*/
|
|
147
|
+
async extractToken(page, storageKey) {
|
|
148
|
+
const key = storageKey ?? this.config?.tokenStorageKey ?? 'token';
|
|
149
|
+
return page.evaluate((k) => sessionStorage.getItem(k), key);
|
|
150
|
+
}
|
|
151
|
+
/** Internal: throw if `setConfig()` nem volt meghivva. */
|
|
152
|
+
requireConfig() {
|
|
153
|
+
if (!this.config) {
|
|
154
|
+
throw new fsm_dynamo_1.DyFM_Error({
|
|
155
|
+
message: 'E2E_LoginHelperService: setConfig() must be called before login operations. '
|
|
156
|
+
+ 'Add it to your e2e-global-setup.ts.',
|
|
157
|
+
errorCode: 'FDP-E2E-LH-NCFG-001',
|
|
158
|
+
issuerService: 'E2E_LoginHelperService',
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return this.config;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.E2E_LoginHelperService = E2E_LoginHelperService;
|
|
165
|
+
//# sourceMappingURL=e2e-login-helper.service.js.map
|
package/build/index.d.ts
CHANGED
|
@@ -3,8 +3,11 @@ export * from './_collections/e2e-unique-generator.util';
|
|
|
3
3
|
export * from './_collections/fdp-cwv-collector.util';
|
|
4
4
|
export * from './_services/e2e-config.service';
|
|
5
5
|
export * from './_services/e2e-logger.service';
|
|
6
|
+
export * from './_services/e2e-login-helper.service';
|
|
6
7
|
export * from './_services/e2e-user-manager.service';
|
|
7
8
|
export * from './_models/interfaces/e2e-hard-delete-options.interface';
|
|
9
|
+
export * from './_models/interfaces/e2e-login-config.interface';
|
|
10
|
+
export * from './_models/interfaces/e2e-login-result.interface';
|
|
8
11
|
export * from './_models/interfaces/e2e-test-config.interface';
|
|
9
12
|
export * from './_models/interfaces/e2e-user.interface';
|
|
10
13
|
export * from './_models/interfaces/fdp-cwv-run-config.interface';
|
package/build/index.js
CHANGED
|
@@ -8,9 +8,12 @@ tslib_1.__exportStar(require("./_collections/fdp-cwv-collector.util"), exports);
|
|
|
8
8
|
// SERVICES
|
|
9
9
|
tslib_1.__exportStar(require("./_services/e2e-config.service"), exports);
|
|
10
10
|
tslib_1.__exportStar(require("./_services/e2e-logger.service"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./_services/e2e-login-helper.service"), exports);
|
|
11
12
|
tslib_1.__exportStar(require("./_services/e2e-user-manager.service"), exports);
|
|
12
13
|
// INTERFACES
|
|
13
14
|
tslib_1.__exportStar(require("./_models/interfaces/e2e-hard-delete-options.interface"), exports);
|
|
15
|
+
tslib_1.__exportStar(require("./_models/interfaces/e2e-login-config.interface"), exports);
|
|
16
|
+
tslib_1.__exportStar(require("./_models/interfaces/e2e-login-result.interface"), exports);
|
|
14
17
|
tslib_1.__exportStar(require("./_models/interfaces/e2e-test-config.interface"), exports);
|
|
15
18
|
tslib_1.__exportStar(require("./_models/interfaces/e2e-user.interface"), exports);
|
|
16
19
|
tslib_1.__exportStar(require("./_models/interfaces/fdp-cwv-run-config.interface"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@futdevpro/fdp-e2e-helpers",
|
|
3
|
-
"version": "01.15.
|
|
3
|
+
"version": "01.15.19",
|
|
4
4
|
"description": "Shared E2E test helpers for FDP-stack apps. First util: E2E_HardDelete_Util. Stateless utility-collection — NOT a framework.",
|
|
5
5
|
"DyBu_settings": {
|
|
6
6
|
"packageType": "shared-package",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"HOWTO.md"
|
|
71
71
|
],
|
|
72
72
|
"peerDependencies": {
|
|
73
|
-
"@futdevpro/fsm-dynamo": "1.15.
|
|
74
|
-
"@futdevpro/nts-dynamo": "1.15.
|
|
73
|
+
"@futdevpro/fsm-dynamo": "1.15.23",
|
|
74
|
+
"@futdevpro/nts-dynamo": "1.15.46",
|
|
75
75
|
"@playwright/test": ">=1.49.0"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
@@ -80,9 +80,9 @@
|
|
|
80
80
|
"tslib": "^2.6.2"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@futdevpro/dynamo-eslint": "1.15.
|
|
84
|
-
"@futdevpro/fsm-dynamo": "1.15.
|
|
85
|
-
"@futdevpro/nts-dynamo": "1.15.
|
|
83
|
+
"@futdevpro/dynamo-eslint": "1.15.12",
|
|
84
|
+
"@futdevpro/fsm-dynamo": "1.15.23",
|
|
85
|
+
"@futdevpro/nts-dynamo": "1.15.46",
|
|
86
86
|
"@playwright/test": "^1.49.0",
|
|
87
87
|
"@types/jasmine": "^5.1.5",
|
|
88
88
|
"@typescript-eslint/eslint-plugin": "^8.41.0",
|