@capillarytech/cap-ui-utils 3.2.0-beta.2 → 3.2.0-beta.4
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/e2e/README.md
CHANGED
|
@@ -64,9 +64,18 @@ import { waitForApi } from '@capillarytech/cap-ui-utils/e2e/playwright/waits';
|
|
|
64
64
|
- **`playwright/logCollector`** — per-test POST to `http://127.0.0.1:4000/logger`
|
|
65
65
|
with the exact WDIO payload (`status` / `time` / `validataionMessage` / `total`,
|
|
66
66
|
keyed runId → suite → test). Non-fatal on any failure; honours `skipLogCollector`.
|
|
67
|
+
- **`playwright/apiFailureLogger`** — logs every same-origin API response outside
|
|
68
|
+
2xx (response + request headers) and network-level request failures, with the
|
|
69
|
+
same wording as the WDIO CDP interceptor (`API <url> errored with status: ...`,
|
|
70
|
+
`Following request headers were sent for failed request`). Auto-attached by
|
|
71
|
+
`doLogin()`; also exported standalone as `attachApiFailureLogger(page, {baseUrl})`.
|
|
67
72
|
- **`playwright/config`** — `createPlaywrightConfig()` wires the reporter, selects the
|
|
68
73
|
suite via `SUITE` → `@<suite>` grep (mirrors `wdio --suite`), and sets pod-friendly
|
|
69
|
-
defaults (headless chromium, trace/screenshot on failure, retries).
|
|
74
|
+
defaults (headless chromium, trace/screenshot on failure, retries). Workers are
|
|
75
|
+
resolvable PER SUITE: `workersBySuite: { smoke: 2, sanity: 1, regression: 1 }`
|
|
76
|
+
(smoke is parallel-safe; sanity/regression builders are stateful on a shared org).
|
|
77
|
+
Default parallelism matches the WDIO module configs (`maxInstances: MAX_INSTANCES || 2`).
|
|
78
|
+
Precedence: `PW_WORKERS_<SUITE>` > `workersBySuite` > `PW_WORKERS` > `MAX_INSTANCES` > `workers` > 2.
|
|
70
79
|
- **`playwright/login`** — Playwright port of `pages/common/login.page` (intouch V2/V1).
|
|
71
80
|
- **`playwright/waits`** — network-driven wait helpers (no fixed sleeps).
|
|
72
81
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Failed-API logger — Playwright port of the WDIO base-conf network interceptor
|
|
4
|
+
* (test/wdio.conf.ts `Network.responseReceived` block): every SAME-ORIGIN API
|
|
5
|
+
* response outside 2xx is logged with its response + request headers, and
|
|
6
|
+
* network-level request failures (refused/aborted/DNS) are logged too.
|
|
7
|
+
*
|
|
8
|
+
* The lines go to stdout, which supervisor.py captures and ships to Apitester —
|
|
9
|
+
* and they use the SAME wording as the WDIO interceptor so existing debugging
|
|
10
|
+
* habits and log greps keep working:
|
|
11
|
+
*
|
|
12
|
+
* API <url> errored with status: <status> with following response headers:
|
|
13
|
+
* { ...response headers... }
|
|
14
|
+
* Following request headers were sent for failed request { ...request headers... }
|
|
15
|
+
*
|
|
16
|
+
* Auto-attached by doLogin() for every consumer (mirrors WDIO's always-on base
|
|
17
|
+
* conf). Idempotent per page. Logging must never fail the run.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const attached = new WeakSet();
|
|
21
|
+
|
|
22
|
+
function attachApiFailureLogger(page, opts = {}) {
|
|
23
|
+
if (!page || typeof page.on !== "function" || attached.has(page)) return;
|
|
24
|
+
attached.add(page);
|
|
25
|
+
|
|
26
|
+
// Same-origin filter — WDIO used cons['url'] (the intouch base URL).
|
|
27
|
+
const base = String(opts.baseUrl || process.env.INTOUCH_URL || "");
|
|
28
|
+
|
|
29
|
+
page.on("response", (response) => {
|
|
30
|
+
Promise.resolve()
|
|
31
|
+
.then(async () => {
|
|
32
|
+
const url = response.url();
|
|
33
|
+
if (base && !url.startsWith(base)) return;
|
|
34
|
+
const status = response.status();
|
|
35
|
+
if (status >= 200 && status <= 299) return;
|
|
36
|
+
const respHeaders = await response.allHeaders().catch(() => response.headers());
|
|
37
|
+
console.log(`API ${url} errored with status: ${status} with following response headers:`);
|
|
38
|
+
console.log(respHeaders);
|
|
39
|
+
console.log("Following request headers were sent for failed request", response.request().headers());
|
|
40
|
+
})
|
|
41
|
+
.catch(() => { /* logging must never fail the run */ });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
page.on("requestfailed", (request) => {
|
|
45
|
+
try {
|
|
46
|
+
const url = request.url();
|
|
47
|
+
if (base && !url.startsWith(base)) return;
|
|
48
|
+
const failure = request.failure();
|
|
49
|
+
console.log(`API ${url} FAILED at network level: ${(failure && failure.errorText) || "unknown"} (method ${request.method()})`);
|
|
50
|
+
console.log("Following request headers were sent for failed request", request.headers());
|
|
51
|
+
} catch (e) { /* ignore */ }
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
console.log("----DONE SETTING UP NETWORK INTERCEPTOR TO LOG FAILED APIS----");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = { attachApiFailureLogger };
|
|
58
|
+
module.exports.default = { attachApiFailureLogger };
|
package/e2e/playwright/config.js
CHANGED
|
@@ -22,6 +22,30 @@ function num(v, dflt) {
|
|
|
22
22
|
return Number.isFinite(n) ? n : dflt;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Per-suite worker resolution — parallelism DEFAULT matches the WDIO module
|
|
27
|
+
* configs: `maxInstances: Number(process.env.MAX_INSTANCES) || 2` (2 browser
|
|
28
|
+
* instances is the pod-proven ceiling — 3 pushed the container over its 4Gi
|
|
29
|
+
* limit). Additionally declarable PER SUITE, which WDIO couldn't do: stateful
|
|
30
|
+
* sanity/regression builders on a shared org can be pinned serial while smoke
|
|
31
|
+
* stays parallel. Precedence:
|
|
32
|
+
* 1. env PW_WORKERS_<SUITE> (ops override for one suite, no code change)
|
|
33
|
+
* 2. overrides.workersBySuite (the module's checked-in per-suite intent,
|
|
34
|
+
* e.g. { smoke: 2, sanity: 1, regression: 1 })
|
|
35
|
+
* 3. env PW_WORKERS (global override — deliberately BELOW
|
|
36
|
+
* workersBySuite so it can't parallelize a suite the module marked serial)
|
|
37
|
+
* 4. env MAX_INSTANCES (the WDIO-era knob, honoured for continuity)
|
|
38
|
+
* 5. overrides.workers, then 2 (== WDIO maxInstances default)
|
|
39
|
+
*/
|
|
40
|
+
function resolveWorkers(overrides, suite) {
|
|
41
|
+
const suiteEnv = suite ? process.env["PW_WORKERS_" + suite.toUpperCase()] : undefined;
|
|
42
|
+
const bySuite = overrides.workersBySuite || {};
|
|
43
|
+
const fromCode = bySuite[suite] !== undefined ? bySuite[suite]
|
|
44
|
+
: num(process.env.PW_WORKERS,
|
|
45
|
+
num(process.env.MAX_INSTANCES, overrides.workers !== undefined ? overrides.workers : 2));
|
|
46
|
+
return num(suiteEnv, fromCode);
|
|
47
|
+
}
|
|
48
|
+
|
|
25
49
|
function createPlaywrightConfig(overrides = {}) {
|
|
26
50
|
const suite = process.env.SUITE || process.env.suite || "";
|
|
27
51
|
const reporterPath = require.resolve("./reporter");
|
|
@@ -32,7 +56,7 @@ function createPlaywrightConfig(overrides = {}) {
|
|
|
32
56
|
fullyParallel: overrides.fullyParallel !== undefined ? overrides.fullyParallel : true,
|
|
33
57
|
forbidOnly: !!process.env.CI,
|
|
34
58
|
retries: num(process.env.PW_RETRIES, overrides.retries !== undefined ? overrides.retries : 1),
|
|
35
|
-
workers:
|
|
59
|
+
workers: resolveWorkers(overrides, suite),
|
|
36
60
|
timeout: num(process.env.PW_TIMEOUT, overrides.timeout || 90000),
|
|
37
61
|
expect: { timeout: num(process.env.PW_EXPECT_TIMEOUT, 15000) },
|
|
38
62
|
// Only the migrated suite runs — same behaviour as `wdio --suite <suite>`.
|
package/e2e/playwright/index.js
CHANGED
|
@@ -10,6 +10,7 @@ const config_1 = require("./config");
|
|
|
10
10
|
const login_1 = require("./login");
|
|
11
11
|
const waits_1 = require("./waits");
|
|
12
12
|
const logCollector_1 = require("./logCollector");
|
|
13
|
+
const apiFailureLogger_1 = require("./apiFailureLogger");
|
|
13
14
|
|
|
14
15
|
exports.createPlaywrightConfig = config_1.createPlaywrightConfig;
|
|
15
16
|
exports.doLogin = login_1.doLogin;
|
|
@@ -17,4 +18,5 @@ exports.waitForApi = waits_1.waitForApi;
|
|
|
17
18
|
exports.clickAndWaitForApi = waits_1.clickAndWaitForApi;
|
|
18
19
|
exports.waitForApiIdle = waits_1.waitForApiIdle;
|
|
19
20
|
exports.collectLogs = logCollector_1.collectLogs;
|
|
21
|
+
exports.attachApiFailureLogger = apiFailureLogger_1.attachApiFailureLogger;
|
|
20
22
|
exports.reporterPath = require.resolve("./reporter");
|
package/e2e/playwright/login.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* import { doLogin } from '@capillarytech/cap-ui-utils/e2e/playwright/login';
|
|
11
11
|
* await doLogin(page, { url, username, password });
|
|
12
12
|
*/
|
|
13
|
+
const { attachApiFailureLogger } = require("./apiFailureLogger");
|
|
14
|
+
|
|
13
15
|
const MAX_LOGIN_ATTEMPTS = 3;
|
|
14
16
|
|
|
15
17
|
function sel(page) {
|
|
@@ -28,6 +30,9 @@ function sel(page) {
|
|
|
28
30
|
|
|
29
31
|
async function doLogin(page, opts, attempt = 0) {
|
|
30
32
|
const { url, username, password } = opts;
|
|
33
|
+
// WDIO's base conf always logged failed same-origin API calls (CDP interceptor);
|
|
34
|
+
// wire the PW equivalent here so every consumer inherits it. Idempotent per page.
|
|
35
|
+
attachApiFailureLogger(page, { baseUrl: url });
|
|
31
36
|
const s = sel(page);
|
|
32
37
|
try {
|
|
33
38
|
await page.goto(url, { waitUntil: "domcontentloaded" });
|