@pasosdejesus/m 0.24.0 → 0.26.0
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/dist/CHANGELOG.md +75 -1
- package/dist/base-model/baseline.generated.d.ts +48 -0
- package/dist/base-model/baseline.generated.d.ts.map +1 -0
- package/dist/base-model/baseline.generated.js +930 -0
- package/dist/base-model/baseline.generated.js.map +1 -0
- package/dist/base-model/check.d.ts +6 -0
- package/dist/base-model/check.d.ts.map +1 -0
- package/dist/base-model/check.js +195 -0
- package/dist/base-model/check.js.map +1 -0
- package/dist/base-model/generate.d.ts +42 -0
- package/dist/base-model/generate.d.ts.map +1 -0
- package/dist/base-model/generate.js +241 -0
- package/dist/base-model/generate.js.map +1 -0
- package/dist/base-model/guidelines.d.ts +13 -0
- package/dist/base-model/guidelines.d.ts.map +1 -0
- package/dist/base-model/guidelines.js +61 -0
- package/dist/base-model/guidelines.js.map +1 -0
- package/dist/base-model/index.d.ts +22 -0
- package/dist/base-model/index.d.ts.map +1 -0
- package/dist/base-model/index.js +26 -0
- package/dist/base-model/index.js.map +1 -0
- package/dist/base-model/parse-structure.d.ts +4 -0
- package/dist/base-model/parse-structure.d.ts.map +1 -0
- package/dist/base-model/parse-structure.js +170 -0
- package/dist/base-model/parse-structure.js.map +1 -0
- package/dist/base-model/queries.d.ts +34 -0
- package/dist/base-model/queries.d.ts.map +1 -0
- package/dist/base-model/queries.js +118 -0
- package/dist/base-model/queries.js.map +1 -0
- package/dist/base-model/references/learn-tg.d.ts +21 -0
- package/dist/base-model/references/learn-tg.d.ts.map +1 -0
- package/dist/base-model/references/learn-tg.js +65 -0
- package/dist/base-model/references/learn-tg.js.map +1 -0
- package/dist/base-model/references/msip.d.ts +29 -0
- package/dist/base-model/references/msip.d.ts.map +1 -0
- package/dist/base-model/references/msip.js +33 -0
- package/dist/base-model/references/msip.js.map +1 -0
- package/dist/base-model/types.d.ts +207 -0
- package/dist/base-model/types.d.ts.map +1 -0
- package/dist/base-model/types.js +10 -0
- package/dist/base-model/types.js.map +1 -0
- package/dist/base-model/version.d.ts +19 -0
- package/dist/base-model/version.d.ts.map +1 -0
- package/dist/base-model/version.js +26 -0
- package/dist/base-model/version.js.map +1 -0
- package/dist/base-model/wallet-link.d.ts +69 -0
- package/dist/base-model/wallet-link.d.ts.map +1 -0
- package/dist/base-model/wallet-link.js +220 -0
- package/dist/base-model/wallet-link.js.map +1 -0
- package/dist/base-model/wallet-link.test.d.ts +2 -0
- package/dist/base-model/wallet-link.test.d.ts.map +1 -0
- package/dist/base-model/wallet-link.test.js +147 -0
- package/dist/base-model/wallet-link.test.js.map +1 -0
- package/dist/e2e/full-wallet.d.ts +19 -0
- package/dist/e2e/full-wallet.d.ts.map +1 -1
- package/dist/e2e/full-wallet.js +12 -4
- package/dist/e2e/full-wallet.js.map +1 -1
- package/dist/e2e/full-wallet.test.js +26 -0
- package/dist/e2e/full-wallet.test.js.map +1 -1
- package/dist/e2e/in-app-wallet.d.ts +23 -0
- package/dist/e2e/in-app-wallet.d.ts.map +1 -0
- package/dist/e2e/in-app-wallet.js +40 -0
- package/dist/e2e/in-app-wallet.js.map +1 -0
- package/dist/e2e/in-app-wallet.test.d.ts +2 -0
- package/dist/e2e/in-app-wallet.test.d.ts.map +1 -0
- package/dist/e2e/in-app-wallet.test.js +52 -0
- package/dist/e2e/in-app-wallet.test.js.map +1 -0
- package/dist/e2e/index.d.ts +5 -1
- package/dist/e2e/index.d.ts.map +1 -1
- package/dist/e2e/index.js +2 -0
- package/dist/e2e/index.js.map +1 -1
- package/dist/e2e/warmup.d.ts +38 -0
- package/dist/e2e/warmup.d.ts.map +1 -0
- package/dist/e2e/warmup.js +84 -0
- package/dist/e2e/warmup.js.map +1 -0
- package/dist/e2e/warmup.test.d.ts +2 -0
- package/dist/e2e/warmup.test.d.ts.map +1 -0
- package/dist/e2e/warmup.test.js +67 -0
- package/dist/e2e/warmup.test.js.map +1 -0
- package/dist/i18n/locales/cli.d.ts.map +1 -1
- package/dist/i18n/locales/cli.js +10 -0
- package/dist/i18n/locales/cli.js.map +1 -1
- package/dist/m.js +19 -1
- package/dist/m.js.map +1 -1
- package/dist/tasks/base-model.d.ts +4 -0
- package/dist/tasks/base-model.d.ts.map +1 -0
- package/dist/tasks/base-model.js +260 -0
- package/dist/tasks/base-model.js.map +1 -0
- package/dist/tasks/db.d.ts.map +1 -1
- package/dist/tasks/db.js +27 -0
- package/dist/tasks/db.js.map +1 -1
- package/dist/tasks/e2e-summary.d.ts +13 -0
- package/dist/tasks/e2e-summary.d.ts.map +1 -0
- package/dist/tasks/e2e-summary.js +117 -0
- package/dist/tasks/e2e-summary.js.map +1 -0
- package/dist/tasks/e2e.d.ts +29 -0
- package/dist/tasks/e2e.d.ts.map +1 -1
- package/dist/tasks/e2e.js +130 -36
- package/dist/tasks/e2e.js.map +1 -1
- package/dist/tasks/e2e.test.d.ts +2 -0
- package/dist/tasks/e2e.test.d.ts.map +1 -0
- package/dist/tasks/e2e.test.js +108 -0
- package/dist/tasks/e2e.test.js.map +1 -0
- package/dist/tasks/warmup.d.ts +4 -0
- package/dist/tasks/warmup.d.ts.map +1 -0
- package/dist/tasks/warmup.js +67 -0
- package/dist/tasks/warmup.js.map +1 -0
- package/dist/tasks/warmup.test.d.ts +2 -0
- package/dist/tasks/warmup.test.d.ts.map +1 -0
- package/dist/tasks/warmup.test.js +40 -0
- package/dist/tasks/warmup.test.js.map +1 -0
- package/dist/templates/apps/nextjs/package.json.hbs +1 -1
- package/dist/test-utils/console.d.ts +37 -0
- package/dist/test-utils/console.d.ts.map +1 -0
- package/dist/test-utils/console.js +52 -0
- package/dist/test-utils/console.js.map +1 -0
- package/dist/test-utils/console.test.d.ts +2 -0
- package/dist/test-utils/console.test.d.ts.map +1 -0
- package/dist/test-utils/console.test.js +57 -0
- package/dist/test-utils/console.test.js.map +1 -0
- package/dist/test-utils/index.d.ts +1 -0
- package/dist/test-utils/index.d.ts.map +1 -1
- package/dist/test-utils/index.js +1 -0
- package/dist/test-utils/index.js.map +1 -1
- package/dist/test-utils/kysely-mocks.d.ts +163 -33
- package/dist/test-utils/kysely-mocks.d.ts.map +1 -1
- package/dist/test-utils/kysely-mocks.js +147 -18
- package/dist/test-utils/kysely-mocks.js.map +1 -1
- package/dist/test-utils/kysely-mocks.test.d.ts +2 -0
- package/dist/test-utils/kysely-mocks.test.d.ts.map +1 -0
- package/dist/test-utils/kysely-mocks.test.js +94 -0
- package/dist/test-utils/kysely-mocks.test.js.map +1 -0
- package/dist/wallet/next/components/InAppWalletSetup.d.ts +11 -0
- package/dist/wallet/next/components/InAppWalletSetup.d.ts.map +1 -0
- package/dist/wallet/next/components/InAppWalletSetup.js +55 -0
- package/dist/wallet/next/components/InAppWalletSetup.js.map +1 -0
- package/dist/wallet/next/components/InAppWalletUnlock.d.ts +9 -0
- package/dist/wallet/next/components/InAppWalletUnlock.d.ts.map +1 -0
- package/dist/wallet/next/components/InAppWalletUnlock.js +29 -0
- package/dist/wallet/next/components/InAppWalletUnlock.js.map +1 -0
- package/dist/wallet/next/components.test.d.ts +2 -0
- package/dist/wallet/next/components.test.d.ts.map +1 -0
- package/dist/wallet/next/components.test.js +122 -0
- package/dist/wallet/next/components.test.js.map +1 -0
- package/dist/wallet/next/i18n.d.ts +63 -0
- package/dist/wallet/next/i18n.d.ts.map +1 -0
- package/dist/wallet/next/i18n.js +64 -0
- package/dist/wallet/next/i18n.js.map +1 -0
- package/dist/wallet/next/index.d.ts +7 -0
- package/dist/wallet/next/index.d.ts.map +1 -0
- package/dist/wallet/next/index.js +12 -0
- package/dist/wallet/next/index.js.map +1 -0
- package/dist/wallet/next/namespaces.d.ts +17 -0
- package/dist/wallet/next/namespaces.d.ts.map +1 -0
- package/dist/wallet/next/namespaces.js +17 -0
- package/dist/wallet/next/namespaces.js.map +1 -0
- package/dist/wallet/next/useInAppWallet.d.ts +55 -0
- package/dist/wallet/next/useInAppWallet.d.ts.map +1 -0
- package/dist/wallet/next/useInAppWallet.js +261 -0
- package/dist/wallet/next/useInAppWallet.js.map +1 -0
- package/dist/wallet/next/useInAppWallet.test.d.ts +2 -0
- package/dist/wallet/next/useInAppWallet.test.d.ts.map +1 -0
- package/dist/wallet/next/useInAppWallet.test.js +261 -0
- package/dist/wallet/next/useInAppWallet.test.js.map +1 -0
- package/package.json +9 -1
- package/src/e2e/README.md +58 -0
- package/src/tasks/README.md +1 -0
- package/src/test-utils/README.md +28 -0
- package/src/wallet/README.md +25 -2
package/dist/tasks/e2e.d.ts
CHANGED
|
@@ -1,2 +1,31 @@
|
|
|
1
|
+
/** Stable, machine-readable prefix consumed by `test:e2e:summary` (P4). */
|
|
2
|
+
export declare const RESULT_PREFIX = "[e2e-result] ";
|
|
3
|
+
export type E2eResult = 'ok' | 'fail' | 'skip';
|
|
4
|
+
/** One spec result line; `<file>` is the spec file name (e.g. `donate.spec.mjs`). */
|
|
5
|
+
export declare function resultLine(file: string, result: E2eResult): string;
|
|
6
|
+
/**
|
|
7
|
+
* Classifies a spec by exit code, and marks a successful spec that printed `[SKIP]`
|
|
8
|
+
* as skipped. A non-zero exit always wins (a spec that failed is not a skip).
|
|
9
|
+
*/
|
|
10
|
+
export declare function classifyResult(status: number | null, output: string): E2eResult;
|
|
11
|
+
export interface RetryPlan {
|
|
12
|
+
retries: number;
|
|
13
|
+
retryDelayMs: number;
|
|
14
|
+
specDelayMs: number;
|
|
15
|
+
/** Injectable sleep (tests). */
|
|
16
|
+
sleep?: (ms: number) => Promise<void>;
|
|
17
|
+
onRetry?: (attempt: number, failedFiles: string[]) => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Runs every spec once, then re-runs each failed spec on its own up to `retries`
|
|
21
|
+
* times. Returns the final per-spec result and the attempt count. Extracted from
|
|
22
|
+
* `runE2e` so the retry policy is unit-testable without spawning processes.
|
|
23
|
+
*/
|
|
24
|
+
export declare function runSpecsWithRetry<S extends {
|
|
25
|
+
file: string;
|
|
26
|
+
}>(specs: S[], runOne: (spec: S, attempt: number) => Promise<E2eResult>, plan: RetryPlan): Promise<{
|
|
27
|
+
results: Map<string, E2eResult>;
|
|
28
|
+
attempts: Map<string, number>;
|
|
29
|
+
}>;
|
|
1
30
|
export declare function runE2e(testPattern?: string, args?: string[]): Promise<void>;
|
|
2
31
|
//# sourceMappingURL=e2e.d.ts.map
|
package/dist/tasks/e2e.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e2e.d.ts","sourceRoot":"","sources":["../../src/tasks/e2e.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"e2e.d.ts","sourceRoot":"","sources":["../../src/tasks/e2e.ts"],"names":[],"mappings":"AAiDA,2EAA2E;AAC3E,eAAO,MAAM,aAAa,kBAAkB,CAAA;AAC5C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAA;AAE9C,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,MAAM,CAElE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAG/E;AA+BD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,gCAAgC;IAChC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CAC3D;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAChE,KAAK,EAAE,CAAC,EAAE,EACV,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,EACxD,IAAI,EAAE,SAAS,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CA4B7E;AAED,wBAAsB,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,iBAoHrE"}
|
package/dist/tasks/e2e.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
// test:e2e — Run E2E tests with Puppeteer + SIWE on OpenBSD/adJ
|
|
2
|
-
|
|
2
|
+
//
|
|
3
|
+
// P3 (m/REQ/49): `--retry <N>` re-runs each failed spec on its own, and every
|
|
4
|
+
// spec/attempt emits one stable machine-readable line (`[e2e-result] <file> <r>`)
|
|
5
|
+
// that `test:e2e:summary` (P4) consumes. The full stream is also saved to
|
|
6
|
+
// `E2E_LOG_DIR` (default /tmp).
|
|
7
|
+
import { spawn } from 'child_process';
|
|
3
8
|
import * as fs from 'fs';
|
|
4
9
|
import * as path from 'path';
|
|
5
10
|
import { globSync } from 'glob';
|
|
@@ -16,9 +21,13 @@ const t = createTranslator(detectLocale(), {
|
|
|
16
21
|
'e2e.no_specs': 'No spec files found in {{0}} matching: {{1}}',
|
|
17
22
|
'e2e.found': 'Found {{0}} spec(s)',
|
|
18
23
|
'e2e.running': '▶ {{0}}',
|
|
24
|
+
'e2e.retry_attempt': '▶ {{0}} (attempt {{1}})',
|
|
25
|
+
'e2e.retry_start': 'Retrying {{0}} spec(s) — attempt {{1}}/{{2}}',
|
|
19
26
|
'e2e.failed': ' ✗ {{0}} failed (exit {{1}})',
|
|
20
27
|
'e2e.all_passed': 'All {{0}} spec(s) passed.',
|
|
21
28
|
'e2e.partial': '{{0}}/{{1}} spec(s) failed.',
|
|
29
|
+
'e2e.still_failing': 'Still failing after {{0}} retry(ies): {{1}}',
|
|
30
|
+
'e2e.log_saved': 'Log saved to {{0}}',
|
|
22
31
|
},
|
|
23
32
|
es: {
|
|
24
33
|
'e2e.no_dir': 'No se encontró directorio e2e/. Esperado: e2e/specs/ o e2e/smoke/',
|
|
@@ -27,11 +36,34 @@ const t = createTranslator(detectLocale(), {
|
|
|
27
36
|
'e2e.no_specs': 'No se encontraron archivos spec en {{0}} coincidiendo con: {{1}}',
|
|
28
37
|
'e2e.found': '{{0}} spec(s) encontrado(s)',
|
|
29
38
|
'e2e.running': '▶ {{0}}',
|
|
39
|
+
'e2e.retry_attempt': '▶ {{0}} (intento {{1}})',
|
|
40
|
+
'e2e.retry_start': 'Reintentando {{0}} spec(s) — intento {{1}}/{{2}}',
|
|
30
41
|
'e2e.failed': ' ✗ {{0}} falló (exit {{1}})',
|
|
31
42
|
'e2e.all_passed': 'Todos los {{0}} spec(s) pasaron.',
|
|
32
43
|
'e2e.partial': '{{0}}/{{1}} spec(s) fallaron.',
|
|
44
|
+
'e2e.still_failing': 'Siguen fallando tras {{0}} reintento(s): {{1}}',
|
|
45
|
+
'e2e.log_saved': 'Log guardado en {{0}}',
|
|
33
46
|
},
|
|
34
47
|
}, commonCli);
|
|
48
|
+
/** Stable, machine-readable prefix consumed by `test:e2e:summary` (P4). */
|
|
49
|
+
export const RESULT_PREFIX = '[e2e-result] ';
|
|
50
|
+
/** One spec result line; `<file>` is the spec file name (e.g. `donate.spec.mjs`). */
|
|
51
|
+
export function resultLine(file, result) {
|
|
52
|
+
return `${RESULT_PREFIX}${file} ${result}`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Classifies a spec by exit code, and marks a successful spec that printed `[SKIP]`
|
|
56
|
+
* as skipped. A non-zero exit always wins (a spec that failed is not a skip).
|
|
57
|
+
*/
|
|
58
|
+
export function classifyResult(status, output) {
|
|
59
|
+
if (status !== 0)
|
|
60
|
+
return 'fail';
|
|
61
|
+
return /\[SKIP\]/.test(output) ? 'skip' : 'ok';
|
|
62
|
+
}
|
|
63
|
+
function getFlag(args, name) {
|
|
64
|
+
const idx = args.indexOf(name);
|
|
65
|
+
return idx >= 0 && idx + 1 < args.length ? args[idx + 1] : null;
|
|
66
|
+
}
|
|
35
67
|
function findSpecs(subDir, pattern, e2eDir) {
|
|
36
68
|
const specDir = path.join(e2eDir, subDir);
|
|
37
69
|
if (!fs.existsSync(specDir))
|
|
@@ -39,6 +71,57 @@ function findSpecs(subDir, pattern, e2eDir) {
|
|
|
39
71
|
const files = globSync(pattern, { cwd: specDir });
|
|
40
72
|
return files.map(f => ({ file: f, dir: specDir }));
|
|
41
73
|
}
|
|
74
|
+
/** Runs one spec, streaming and capturing its output. */
|
|
75
|
+
function runSpec(specPath, env) {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
const child = spawn(process.execPath, [specPath], { cwd: process.cwd(), env });
|
|
78
|
+
let output = '';
|
|
79
|
+
const onData = (chunk) => {
|
|
80
|
+
const text = chunk.toString();
|
|
81
|
+
output += text;
|
|
82
|
+
process.stdout.write(text);
|
|
83
|
+
};
|
|
84
|
+
child.stdout.on('data', onData);
|
|
85
|
+
child.stderr.on('data', onData);
|
|
86
|
+
child.on('error', reject);
|
|
87
|
+
child.on('close', (code) => resolve({ status: code ?? 1, output }));
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Runs every spec once, then re-runs each failed spec on its own up to `retries`
|
|
92
|
+
* times. Returns the final per-spec result and the attempt count. Extracted from
|
|
93
|
+
* `runE2e` so the retry policy is unit-testable without spawning processes.
|
|
94
|
+
*/
|
|
95
|
+
export async function runSpecsWithRetry(specs, runOne, plan) {
|
|
96
|
+
const sleep = plan.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
97
|
+
const results = new Map();
|
|
98
|
+
const attempts = new Map();
|
|
99
|
+
for (let i = 0; i < specs.length; i++) {
|
|
100
|
+
const spec = specs[i];
|
|
101
|
+
results.set(spec.file, await runOne(spec, 1));
|
|
102
|
+
attempts.set(spec.file, 1);
|
|
103
|
+
if (plan.specDelayMs > 0 && i < specs.length - 1)
|
|
104
|
+
await sleep(plan.specDelayMs);
|
|
105
|
+
}
|
|
106
|
+
let failed = specs.filter((s) => results.get(s.file) === 'fail');
|
|
107
|
+
for (let attempt = 1; attempt <= plan.retries && failed.length > 0; attempt++) {
|
|
108
|
+
plan.onRetry?.(attempt, failed.map((s) => s.file));
|
|
109
|
+
if (plan.retryDelayMs > 0)
|
|
110
|
+
await sleep(plan.retryDelayMs);
|
|
111
|
+
const still = [];
|
|
112
|
+
for (const spec of failed) {
|
|
113
|
+
const result = await runOne(spec, attempt + 1);
|
|
114
|
+
results.set(spec.file, result);
|
|
115
|
+
attempts.set(spec.file, attempt + 1);
|
|
116
|
+
if (result === 'fail')
|
|
117
|
+
still.push(spec);
|
|
118
|
+
if (plan.specDelayMs > 0)
|
|
119
|
+
await sleep(plan.specDelayMs);
|
|
120
|
+
}
|
|
121
|
+
failed = still;
|
|
122
|
+
}
|
|
123
|
+
return { results, attempts };
|
|
124
|
+
}
|
|
42
125
|
export async function runE2e(testPattern, args = []) {
|
|
43
126
|
const cwd = process.cwd();
|
|
44
127
|
// If testPattern looks like a flag, move it to args
|
|
@@ -48,6 +131,9 @@ export async function runE2e(testPattern, args = []) {
|
|
|
48
131
|
}
|
|
49
132
|
const smokeOnly = args.includes('--smoke');
|
|
50
133
|
const grepFilter = args.includes('--grep') ? args[args.indexOf('--grep') + 1] : null;
|
|
134
|
+
const retries = Math.max(0, parseInt(getFlag(args, '--retry') ?? process.env.E2E_RETRIES ?? '0', 10) || 0);
|
|
135
|
+
const retryDelay = Math.max(0, parseInt(getFlag(args, '--retry-delay') ?? '15000', 10) || 0);
|
|
136
|
+
const logDir = process.env.E2E_LOG_DIR || '/tmp';
|
|
51
137
|
// 1. Detect e2e directory
|
|
52
138
|
const e2eDir = path.join(cwd, 'e2e');
|
|
53
139
|
if (!fs.existsSync(e2eDir)) {
|
|
@@ -66,7 +152,6 @@ export async function runE2e(testPattern, args = []) {
|
|
|
66
152
|
}
|
|
67
153
|
// 3. Find specs — search in both specs/ and smoke/ when no flag specified
|
|
68
154
|
let specFiles = [];
|
|
69
|
-
// If pattern doesn't contain glob chars and isn't a full filename, wrap with *...*
|
|
70
155
|
let pattern = testPattern || '**/*.spec.mjs';
|
|
71
156
|
if (testPattern && !testPattern.includes('*') && !testPattern.endsWith('.spec.mjs')) {
|
|
72
157
|
pattern = `*${testPattern}*.spec.mjs`;
|
|
@@ -75,7 +160,6 @@ export async function runE2e(testPattern, args = []) {
|
|
|
75
160
|
specFiles = findSpecs('smoke', pattern, e2eDir);
|
|
76
161
|
}
|
|
77
162
|
else {
|
|
78
|
-
// Try specs/ first, then smoke/
|
|
79
163
|
specFiles = findSpecs('specs', pattern, e2eDir);
|
|
80
164
|
if (specFiles.length === 0) {
|
|
81
165
|
specFiles = findSpecs('smoke', pattern, e2eDir);
|
|
@@ -84,7 +168,6 @@ export async function runE2e(testPattern, args = []) {
|
|
|
84
168
|
}
|
|
85
169
|
}
|
|
86
170
|
}
|
|
87
|
-
// Apply grep filter
|
|
88
171
|
if (grepFilter && specFiles.length > 0) {
|
|
89
172
|
specFiles = specFiles.filter(s => s.file.includes(grepFilter));
|
|
90
173
|
}
|
|
@@ -94,43 +177,54 @@ export async function runE2e(testPattern, args = []) {
|
|
|
94
177
|
process.exit(0);
|
|
95
178
|
}
|
|
96
179
|
info(t("e2e.found", String(specFiles.length)));
|
|
97
|
-
// 4.
|
|
98
|
-
|
|
180
|
+
// 4. Log file (best effort) for `test:e2e:summary`.
|
|
181
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
182
|
+
const logFile = path.join(logDir, `e2e-${stamp}.log`);
|
|
183
|
+
let log = null;
|
|
184
|
+
try {
|
|
185
|
+
log = fs.createWriteStream(logFile);
|
|
186
|
+
info(t("e2e.log_saved", logFile));
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
log = null;
|
|
190
|
+
}
|
|
99
191
|
const specDelay = parseInt(process.env.E2E_SPEC_DELAY_MS || '1500', 10);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
192
|
+
// Every spec RUN (including retries) gets a fresh WALLET_INDEX so a retry does
|
|
193
|
+
// not hammer the site's per-wallet rate limit.
|
|
194
|
+
let walletRun = 0;
|
|
195
|
+
const runOne = async (spec, attempt) => {
|
|
196
|
+
const specPath = path.join(spec.dir, spec.file);
|
|
197
|
+
const rel = path.relative(e2eDir, specPath);
|
|
198
|
+
const env = { ...process.env, WALLET_INDEX: String(walletRun++) };
|
|
105
199
|
if (chromePath)
|
|
106
200
|
env.CHROME_PATH = chromePath;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (failures === 0) {
|
|
128
|
-
success(
|
|
201
|
+
info('\n' + (attempt > 1 ? t("e2e.retry_attempt", rel, String(attempt)) : t("e2e.running", rel)));
|
|
202
|
+
const { status, output } = await runSpec(specPath, env);
|
|
203
|
+
const result = classifyResult(status, output);
|
|
204
|
+
const line = resultLine(spec.file, result);
|
|
205
|
+
console.log(line);
|
|
206
|
+
if (result === 'fail')
|
|
207
|
+
problem(t("e2e.failed", spec.file, String(status)));
|
|
208
|
+
log?.write(`▶ ${rel}\n${output}\n${line}\n`);
|
|
209
|
+
return result;
|
|
210
|
+
};
|
|
211
|
+
// 5. Run pass 1 and the retries.
|
|
212
|
+
const { results } = await runSpecsWithRetry(specFiles, runOne, {
|
|
213
|
+
retries,
|
|
214
|
+
retryDelayMs: retryDelay,
|
|
215
|
+
specDelayMs: specDelay,
|
|
216
|
+
onRetry: (attempt, files) => info('\n' + t("e2e.retry_start", String(files.length), String(attempt), String(retries))),
|
|
217
|
+
});
|
|
218
|
+
log?.end();
|
|
219
|
+
// 7. Summary. A spec is green only by exit code.
|
|
220
|
+
const failures = specFiles.filter((s) => results.get(s.file) === 'fail');
|
|
221
|
+
if (failures.length === 0) {
|
|
222
|
+
success('\n' + t("e2e.all_passed", String(specFiles.length)));
|
|
129
223
|
}
|
|
130
224
|
else {
|
|
131
|
-
problem(
|
|
225
|
+
problem('\n' + t("e2e.partial", String(failures.length), String(specFiles.length)));
|
|
226
|
+
problem(t("e2e.still_failing", String(retries), failures.map((s) => s.file).join(', ')));
|
|
132
227
|
}
|
|
133
|
-
|
|
134
|
-
process.exit(failures > 0 ? 1 : 0);
|
|
228
|
+
process.exit(failures.length > 0 ? 1 : 0);
|
|
135
229
|
}
|
|
136
230
|
//# sourceMappingURL=e2e.js.map
|
package/dist/tasks/e2e.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e2e.js","sourceRoot":"","sources":["../../src/tasks/e2e.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"e2e.js","sourceRoot":"","sources":["../../src/tasks/e2e.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e.test.d.ts","sourceRoot":"","sources":["../../src/tasks/e2e.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { classifyResult, resultLine, runSpecsWithRetry } from './e2e.js';
|
|
3
|
+
import { parseE2eLog, renderE2eSummary } from './e2e-summary.js';
|
|
4
|
+
// P3/P4 (m/REQ/49): the runner emits a stable `[e2e-result] <file> <r>` line and
|
|
5
|
+
// `test:e2e:summary` consumes it (last attempt wins).
|
|
6
|
+
describe('classifyResult / resultLine', () => {
|
|
7
|
+
it('reports fail by exit code (even if it also printed [SKIP])', () => {
|
|
8
|
+
expect(classifyResult(1, 'anything')).toBe('fail');
|
|
9
|
+
expect(classifyResult(2, '[SKIP] x')).toBe('fail');
|
|
10
|
+
});
|
|
11
|
+
it('reports skip for a green spec that printed [SKIP]', () => {
|
|
12
|
+
expect(classifyResult(0, 'ran\n[SKIP] needs Chrome')).toBe('skip');
|
|
13
|
+
});
|
|
14
|
+
it('reports ok for a plain green spec', () => {
|
|
15
|
+
expect(classifyResult(0, '[OK] fine')).toBe('ok');
|
|
16
|
+
});
|
|
17
|
+
it('formats the machine-readable line', () => {
|
|
18
|
+
expect(resultLine('donate.spec.mjs', 'ok')).toBe('[e2e-result] donate.spec.mjs ok');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
describe('parseE2eLog', () => {
|
|
22
|
+
it('reads the machine format and keeps the last result per spec', () => {
|
|
23
|
+
const log = [
|
|
24
|
+
'▶ specs/a.spec.mjs',
|
|
25
|
+
'[e2e-result] a.spec.mjs fail',
|
|
26
|
+
'▶ specs/b.spec.mjs',
|
|
27
|
+
'[e2e-result] b.spec.mjs ok',
|
|
28
|
+
'[e2e-retry] ▶ specs/a.spec.mjs (intento 1)',
|
|
29
|
+
'[e2e-result] a.spec.mjs ok',
|
|
30
|
+
].join('\n');
|
|
31
|
+
const status = parseE2eLog(log);
|
|
32
|
+
expect(status.get('a.spec.mjs')).toBe('ok');
|
|
33
|
+
expect(status.get('b.spec.mjs')).toBe('ok');
|
|
34
|
+
});
|
|
35
|
+
it('falls back to the human format when there are no [e2e-result] lines', () => {
|
|
36
|
+
const log = [
|
|
37
|
+
'▶ specs/a.spec.mjs',
|
|
38
|
+
'[OK] fine',
|
|
39
|
+
'✅ 0 failures',
|
|
40
|
+
'▶ specs/b.spec.mjs',
|
|
41
|
+
'❌ 1 failures',
|
|
42
|
+
'▶ specs/c.spec.mjs',
|
|
43
|
+
'started and never finished',
|
|
44
|
+
].join('\n');
|
|
45
|
+
const status = parseE2eLog(log);
|
|
46
|
+
expect(status.get('a.spec.mjs')).toBe('ok');
|
|
47
|
+
expect(status.get('b.spec.mjs')).toBe('fail');
|
|
48
|
+
expect(status.get('c.spec.mjs')).toBe('?');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('renderE2eSummary', () => {
|
|
52
|
+
it('marks the specs whose state differs between runs', () => {
|
|
53
|
+
const site = parseE2eLog('[e2e-result] a.spec.mjs fail\n[e2e-result] b.spec.mjs ok');
|
|
54
|
+
const local = parseE2eLog('[e2e-result] a.spec.mjs ok\n[e2e-result] b.spec.mjs ok');
|
|
55
|
+
const out = renderE2eSummary([
|
|
56
|
+
{ file: '/tmp/site.log', status: site },
|
|
57
|
+
{ file: '/tmp/local.log', status: local },
|
|
58
|
+
]);
|
|
59
|
+
expect(out).toContain('a.spec.mjs');
|
|
60
|
+
expect(out).toContain('<-- difiere');
|
|
61
|
+
expect(out).toContain('1 con estado distinto');
|
|
62
|
+
// b didn't differ, so its row must not carry the marker.
|
|
63
|
+
const bLine = out.split('\n').find((l) => l.startsWith('b.spec.mjs')) ?? '';
|
|
64
|
+
expect(bLine).not.toContain('<-- difiere');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('runSpecsWithRetry (P3)', () => {
|
|
68
|
+
it('retries a failing spec until it passes', async () => {
|
|
69
|
+
const calls = [];
|
|
70
|
+
const runOne = async (spec, attempt) => {
|
|
71
|
+
calls.push(`${spec.file}#${attempt}`);
|
|
72
|
+
return attempt >= 2 ? 'ok' : 'fail';
|
|
73
|
+
};
|
|
74
|
+
const { results, attempts } = await runSpecsWithRetry([{ file: 'a.spec.mjs' }], runOne, {
|
|
75
|
+
retries: 2, retryDelayMs: 0, specDelayMs: 0,
|
|
76
|
+
});
|
|
77
|
+
expect(results.get('a.spec.mjs')).toBe('ok');
|
|
78
|
+
expect(attempts.get('a.spec.mjs')).toBe(2);
|
|
79
|
+
expect(calls).toEqual(['a.spec.mjs#1', 'a.spec.mjs#2']);
|
|
80
|
+
});
|
|
81
|
+
it('stops after N retries and reports fail', async () => {
|
|
82
|
+
let n = 0;
|
|
83
|
+
const runOne = async () => { n += 1; return 'fail'; };
|
|
84
|
+
const { results, attempts } = await runSpecsWithRetry([{ file: 'a.spec.mjs' }], runOne, {
|
|
85
|
+
retries: 2, retryDelayMs: 0, specDelayMs: 0,
|
|
86
|
+
});
|
|
87
|
+
expect(results.get('a.spec.mjs')).toBe('fail');
|
|
88
|
+
expect(attempts.get('a.spec.mjs')).toBe(3); // 1 + 2 retries
|
|
89
|
+
expect(n).toBe(3);
|
|
90
|
+
});
|
|
91
|
+
it('does not retry when retries=0', async () => {
|
|
92
|
+
let n = 0;
|
|
93
|
+
const runOne = async () => { n += 1; return 'fail'; };
|
|
94
|
+
const { attempts } = await runSpecsWithRetry([{ file: 'a.spec.mjs' }], runOne, {
|
|
95
|
+
retries: 0, retryDelayMs: 0, specDelayMs: 0,
|
|
96
|
+
});
|
|
97
|
+
expect(attempts.get('a.spec.mjs')).toBe(1);
|
|
98
|
+
expect(n).toBe(1);
|
|
99
|
+
});
|
|
100
|
+
it('leaves a green spec untouched', async () => {
|
|
101
|
+
const runOne = async () => 'ok';
|
|
102
|
+
const { attempts } = await runSpecsWithRetry([{ file: 'a.spec.mjs' }], runOne, {
|
|
103
|
+
retries: 3, retryDelayMs: 0, specDelayMs: 0,
|
|
104
|
+
});
|
|
105
|
+
expect(attempts.get('a.spec.mjs')).toBe(1);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=e2e.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e.test.js","sourceRoot":"","sources":["../../src/tasks/e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Reads the route list from `e2e/warmup-paths.json` or `package.json:e2e.warmupPaths`. */
|
|
2
|
+
export declare function resolveWarmupPaths(cwd: string): string[] | null;
|
|
3
|
+
export declare function runWarmup(args: string[]): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=warmup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warmup.d.ts","sourceRoot":"","sources":["../../src/tasks/warmup.ts"],"names":[],"mappings":"AAqBA,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAsB/D;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB7D"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// warmup — calienta un sitio (Next.js compila rutas bajo demanda) (m/REQ/49 P5).
|
|
2
|
+
//
|
|
3
|
+
// La lista de rutas vive en el consumidor: `e2e/warmup-paths.json` o
|
|
4
|
+
// `package.json:e2e.warmupPaths`. El sitio base sale de `SITE_URL`.
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { warmup } from '../e2e/warmup.js';
|
|
8
|
+
import { problem, info, success } from '../util/colors.js';
|
|
9
|
+
import { createTranslator } from '../i18n/createTranslator.js';
|
|
10
|
+
import { detectLocale } from '../util/locale.js';
|
|
11
|
+
import commonCli from '../i18n/common-cli.js';
|
|
12
|
+
const t = createTranslator(detectLocale(), {
|
|
13
|
+
en: {
|
|
14
|
+
'warmup.no_paths': 'No warmup paths found. Create e2e/warmup-paths.json or set package.json:e2e.warmupPaths.',
|
|
15
|
+
},
|
|
16
|
+
es: {
|
|
17
|
+
'warmup.no_paths': 'No se encontraron rutas de warmup. Crea e2e/warmup-paths.json o define package.json:e2e.warmupPaths.',
|
|
18
|
+
},
|
|
19
|
+
}, commonCli);
|
|
20
|
+
/** Reads the route list from `e2e/warmup-paths.json` or `package.json:e2e.warmupPaths`. */
|
|
21
|
+
export function resolveWarmupPaths(cwd) {
|
|
22
|
+
const jsonPath = path.join(cwd, 'e2e', 'warmup-paths.json');
|
|
23
|
+
if (fs.existsSync(jsonPath)) {
|
|
24
|
+
try {
|
|
25
|
+
const data = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
|
|
26
|
+
const paths = Array.isArray(data) ? data : data?.paths;
|
|
27
|
+
if (Array.isArray(paths))
|
|
28
|
+
return paths.filter((p) => typeof p === 'string');
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
35
|
+
if (fs.existsSync(pkgPath)) {
|
|
36
|
+
try {
|
|
37
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
38
|
+
const paths = pkg?.e2e?.warmupPaths;
|
|
39
|
+
if (Array.isArray(paths))
|
|
40
|
+
return paths.filter((p) => typeof p === 'string');
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
export async function runWarmup(args) {
|
|
49
|
+
const cwd = process.cwd();
|
|
50
|
+
const filter = args.find((a) => !a.startsWith('--'));
|
|
51
|
+
const sequential = args.includes('--sequential');
|
|
52
|
+
const paths = resolveWarmupPaths(cwd);
|
|
53
|
+
if (!paths || paths.length === 0) {
|
|
54
|
+
problem(t('warmup.no_paths'));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
const baseUrl = process.env.SITE_URL || 'http://localhost:4000';
|
|
58
|
+
info(`SITE_URL=${baseUrl}${sequential ? ' (secuencial)' : ''}`);
|
|
59
|
+
const outcome = await warmup(baseUrl, {
|
|
60
|
+
paths,
|
|
61
|
+
filter,
|
|
62
|
+
mode: sequential ? 'sequential' : 'two-pass',
|
|
63
|
+
});
|
|
64
|
+
success(`Warmup: ${outcome.results.length} ruta(s), ${outcome.slow.length} lenta(s), ${outcome.errors} error(es).`);
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=warmup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warmup.js","sourceRoot":"","sources":["../../src/tasks/warmup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warmup.test.d.ts","sourceRoot":"","sources":["../../src/tasks/warmup.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { resolveWarmupPaths } from './warmup.js';
|
|
6
|
+
// P5 (m/REQ/49): the route list lives in the consumer.
|
|
7
|
+
let dirs = [];
|
|
8
|
+
function tmpProject() {
|
|
9
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'm-warmup-'));
|
|
10
|
+
dirs.push(dir);
|
|
11
|
+
return dir;
|
|
12
|
+
}
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
for (const dir of dirs)
|
|
15
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
16
|
+
dirs = [];
|
|
17
|
+
});
|
|
18
|
+
describe('resolveWarmupPaths (P5)', () => {
|
|
19
|
+
it('reads e2e/warmup-paths.json (array form)', () => {
|
|
20
|
+
const dir = tmpProject();
|
|
21
|
+
fs.mkdirSync(path.join(dir, 'e2e'), { recursive: true });
|
|
22
|
+
fs.writeFileSync(path.join(dir, 'e2e', 'warmup-paths.json'), JSON.stringify(['/en', '/api/a']));
|
|
23
|
+
expect(resolveWarmupPaths(dir)).toEqual(['/en', '/api/a']);
|
|
24
|
+
});
|
|
25
|
+
it('reads e2e/warmup-paths.json (object form) and drops non-strings', () => {
|
|
26
|
+
const dir = tmpProject();
|
|
27
|
+
fs.mkdirSync(path.join(dir, 'e2e'), { recursive: true });
|
|
28
|
+
fs.writeFileSync(path.join(dir, 'e2e', 'warmup-paths.json'), JSON.stringify({ paths: ['/en', 1, '/api/a'] }));
|
|
29
|
+
expect(resolveWarmupPaths(dir)).toEqual(['/en', '/api/a']);
|
|
30
|
+
});
|
|
31
|
+
it('falls back to package.json:e2e.warmupPaths', () => {
|
|
32
|
+
const dir = tmpProject();
|
|
33
|
+
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ e2e: { warmupPaths: ['/x'] } }));
|
|
34
|
+
expect(resolveWarmupPaths(dir)).toEqual(['/x']);
|
|
35
|
+
});
|
|
36
|
+
it('returns null when nothing is configured', () => {
|
|
37
|
+
expect(resolveWarmupPaths(tmpProject())).toBeNull();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=warmup.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warmup.test.js","sourceRoot":"","sources":["../../src/tasks/warmup.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Console noise silencing for tests
|
|
3
|
+
*
|
|
4
|
+
* "Y todo lo que hagáis, hacedlo de corazón, como para el Señor y no para los hombres" (Colosenses 3:23)
|
|
5
|
+
*
|
|
6
|
+
* P5/U2 of `m/REQ/49`: many consumers wrap `console` to hide expected noise
|
|
7
|
+
* (retry attempts, aborted navigations, warnings from a mocked dependency).
|
|
8
|
+
* This graduates the pattern from learn.tg's `vitest.setup.ts` (`NOISY_PATTERNS`)
|
|
9
|
+
* so consumers can drop their local wrapper.
|
|
10
|
+
*/
|
|
11
|
+
/** Console methods wrapped by `silenceConsole`. */
|
|
12
|
+
export type SilencedConsoleMethod = 'log' | 'warn' | 'error' | 'info' | 'debug';
|
|
13
|
+
export interface SilenceConsoleOpts {
|
|
14
|
+
/** Methods to wrap (default `log`, `warn`, `error`). */
|
|
15
|
+
methods?: SilencedConsoleMethod[];
|
|
16
|
+
/** Console object to wrap (default `globalThis.console`; injectable for tests). */
|
|
17
|
+
console?: Console;
|
|
18
|
+
}
|
|
19
|
+
export interface SilenceConsoleHandle {
|
|
20
|
+
/** Restores the original methods. */
|
|
21
|
+
restore: () => void;
|
|
22
|
+
/** The argument lists that were suppressed (useful for assertions). */
|
|
23
|
+
suppressed: unknown[][];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Wraps the console methods so a call whose args contain any of `patterns`
|
|
27
|
+
* (substring match on string args) is suppressed; the rest passes through to the
|
|
28
|
+
* original method.
|
|
29
|
+
*
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const silence = silenceConsole(['[retry]', 'AbortError'])
|
|
32
|
+
* // ... exercise the code ...
|
|
33
|
+
* silence.restore()
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function silenceConsole(patterns: string[], opts?: SilenceConsoleOpts): SilenceConsoleHandle;
|
|
37
|
+
//# sourceMappingURL=console.d.ts.map
|