poku 4.3.2 → 4.3.3-canary.2648bb03
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 +2 -2
- package/lib/modules/_shared.cjs +82 -14
- package/lib/modules/_shared.d.cts +9 -0
- package/lib/modules/_shared.d.ts +9 -0
- package/lib/modules/_shared.js +82 -14
- package/lib/modules/index.cjs +1 -0
- package/lib/modules/index.d.cts +9 -2
- package/lib/modules/index.d.ts +9 -2
- package/lib/modules/index.js +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -168,7 +168,7 @@ deno run npm:poku
|
|
|
168
168
|
<td>🌐 Run package.json scripts and files in background</td>
|
|
169
169
|
</tr>
|
|
170
170
|
<tr>
|
|
171
|
-
<td><a href="https://poku.io/docs/documentation/
|
|
171
|
+
<td><a href="https://poku.io/docs/documentation/plugins/official/containers">docker</a></td>
|
|
172
172
|
<td>🐳 Build, start, compose, stop, remove, and test containers</td>
|
|
173
173
|
</tr>
|
|
174
174
|
<tr>
|
|
@@ -197,7 +197,7 @@ deno run npm:poku
|
|
|
197
197
|
|
|
198
198
|
<table>
|
|
199
199
|
<tr>
|
|
200
|
-
<td><a href="https://poku.io/docs/documentation/
|
|
200
|
+
<td><a href="https://poku.io/docs/documentation/plugins/official/coverage">coverage</a></td>
|
|
201
201
|
<td>☔️ Enable coverage collection using a coverage plugin</td>
|
|
202
202
|
</tr>
|
|
203
203
|
<tr>
|
package/lib/modules/_shared.cjs
CHANGED
|
@@ -243,6 +243,20 @@ ${preIdentation} ${format(`${options?.expected ?? "Expected"}:`).dim()}`
|
|
|
243
243
|
const indent = getIndent();
|
|
244
244
|
log$1(`${indent}${format(`\u25CF ${message}`).cyan().bold()}`);
|
|
245
245
|
},
|
|
246
|
+
onRetryStart({ attempt, total }) {
|
|
247
|
+
const indent = indentation.test.repeat(
|
|
248
|
+
indentation.describeDepth + indentation.itDepth
|
|
249
|
+
);
|
|
250
|
+
log$1(`${indent}${format(`\u21BB Retry ${attempt}/${total}`).dim()}`);
|
|
251
|
+
},
|
|
252
|
+
onRetryEnd({ attempt, success }) {
|
|
253
|
+
if (success && attempt > 1) {
|
|
254
|
+
const indent = indentation.test.repeat(
|
|
255
|
+
indentation.describeDepth + indentation.itDepth
|
|
256
|
+
);
|
|
257
|
+
log$1(`${indent}${format("\u2714 Retry succeeded").success().dim()}`);
|
|
258
|
+
}
|
|
259
|
+
},
|
|
246
260
|
onFileResult({ status, path, duration, output }) {
|
|
247
261
|
process$1.stdout.write(`
|
|
248
262
|
`), status ? (log$1(
|
|
@@ -264,15 +278,14 @@ ${preIdentation} ${format(`${options?.expected ?? "Expected"}:`).dim()}`
|
|
|
264
278
|
`${format(String(errors.length)).fail().bold()} ${format("test file(s) failed:").bold()}
|
|
265
279
|
`
|
|
266
280
|
);
|
|
267
|
-
for (const i in errors)
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
index > 0 && process$1.stdout.write(`
|
|
281
|
+
for (const i in errors) {
|
|
282
|
+
const { file, output } = errors[i], index = +i;
|
|
283
|
+
index > 0 && process$1.stdout.write(`
|
|
271
284
|
`), log$1(
|
|
272
|
-
|
|
273
|
-
|
|
285
|
+
`${format(`${index + 1})`).dim().bold()} ${format(file).underline()}`
|
|
286
|
+
), output && log$1(`
|
|
274
287
|
${output}`);
|
|
275
|
-
|
|
288
|
+
}
|
|
276
289
|
}
|
|
277
290
|
},
|
|
278
291
|
onExit({ results: results2, timespan: timespan2 }) {
|
|
@@ -356,6 +369,10 @@ ${message}
|
|
|
356
369
|
},
|
|
357
370
|
onTodoModifier() {
|
|
358
371
|
},
|
|
372
|
+
onRetryStart() {
|
|
373
|
+
},
|
|
374
|
+
onRetryEnd() {
|
|
375
|
+
},
|
|
359
376
|
onFileResult({ status, path, output }) {
|
|
360
377
|
log$1(`${status ? BADGE_PASS : BADGE_FAIL} ${path.relative}`), status || (countFails++, errors.push({
|
|
361
378
|
file: path.relative,
|
|
@@ -378,6 +395,10 @@ ${message}
|
|
|
378
395
|
},
|
|
379
396
|
onSkipFile() {
|
|
380
397
|
},
|
|
398
|
+
onRetryStart() {
|
|
399
|
+
},
|
|
400
|
+
onRetryEnd() {
|
|
401
|
+
},
|
|
381
402
|
onFileResult({ path, status, output }) {
|
|
382
403
|
process$1.stdout.write(status ? DOT_PASS : DOT_FAIL), status || errors.push({
|
|
383
404
|
file: path.relative,
|
|
@@ -401,6 +422,10 @@ ${message}
|
|
|
401
422
|
},
|
|
402
423
|
onSkipFile() {
|
|
403
424
|
},
|
|
425
|
+
onRetryStart() {
|
|
426
|
+
},
|
|
427
|
+
onRetryEnd() {
|
|
428
|
+
},
|
|
404
429
|
onFileResult({ status, output }) {
|
|
405
430
|
status || (countFails++, output && log$1(output));
|
|
406
431
|
},
|
|
@@ -425,7 +450,7 @@ const states = getSharedState("states", {
|
|
|
425
450
|
}), errorHoist = getSharedState("errorHoist", {
|
|
426
451
|
depth: 0,
|
|
427
452
|
failed: !1
|
|
428
|
-
}), VERSION = "4.3.
|
|
453
|
+
}), VERSION = "4.3.3-canary.2648bb03", deepOptions = getSharedState("deepOptions", []), GLOBAL = getSharedState("GLOBAL", {
|
|
429
454
|
cwd: cwd$1,
|
|
430
455
|
configs: {
|
|
431
456
|
filter: void 0,
|
|
@@ -679,11 +704,14 @@ const poku = (async (targetPaths, configs) => {
|
|
|
679
704
|
for (const plugin2 of plugins)
|
|
680
705
|
plugin2.teardown && await plugin2.teardown(pluginContext);
|
|
681
706
|
if (GLOBAL.configs.noExit) return code;
|
|
707
|
+
}), retryContext = getSharedState("retryContext", {
|
|
708
|
+
stack: null
|
|
682
709
|
}), assertProcessor = () => {
|
|
683
710
|
const { reporter: reporter2 } = GLOBAL, handleSuccess = ({ message }) => {
|
|
684
711
|
typeof message == "string" && reporter2.onAssertionSuccess({ message });
|
|
685
712
|
}, handleError = (error, options) => {
|
|
686
|
-
|
|
713
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
714
|
+
throw ctx ? ctx.failed = !0 : process$1.exitCode = 1, error instanceof nodeAssert.AssertionError && reporter2.onAssertionFailure({ assertOptions: options, error }), error;
|
|
687
715
|
};
|
|
688
716
|
return { processAssert: (cb, options) => {
|
|
689
717
|
try {
|
|
@@ -854,7 +882,8 @@ const poku = (async (targetPaths, configs) => {
|
|
|
854
882
|
const insideDescribe = errorHoist.depth > 0;
|
|
855
883
|
let onError;
|
|
856
884
|
insideDescribe ? errorHoist.failed = !1 : (onError = (error) => {
|
|
857
|
-
|
|
885
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
886
|
+
ctx ? ctx.failed = !0 : (process$1.exitCode = 1, success = !1, error instanceof nodeAssert.AssertionError || console.error(error));
|
|
858
887
|
}, process$1.once("uncaughtException", onError), process$1.once("unhandledRejection", onError)), start = process$1.hrtime();
|
|
859
888
|
try {
|
|
860
889
|
const hooks = getScopeHook();
|
|
@@ -866,9 +895,15 @@ const poku = (async (targetPaths, configs) => {
|
|
|
866
895
|
resultCb instanceof Promise && await resultCb;
|
|
867
896
|
}
|
|
868
897
|
} catch (error) {
|
|
869
|
-
|
|
898
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
899
|
+
ctx ? ctx.failed = !0 : (process$1.exitCode = 1, success = !1, error instanceof nodeAssert.AssertionError || console.error(error));
|
|
870
900
|
} finally {
|
|
871
|
-
end = process$1.hrtime(start), onError
|
|
901
|
+
if (end = process$1.hrtime(start), onError)
|
|
902
|
+
process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError);
|
|
903
|
+
else if (errorHoist.failed) {
|
|
904
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
905
|
+
ctx ? ctx.failed = !0 : success = !1, errorHoist.failed = !1;
|
|
906
|
+
}
|
|
872
907
|
}
|
|
873
908
|
if (typeof each.after.cb == "function") {
|
|
874
909
|
const afterResult = each.after.cb();
|
|
@@ -907,7 +942,10 @@ const poku = (async (targetPaths, configs) => {
|
|
|
907
942
|
} catch (error) {
|
|
908
943
|
onError(error);
|
|
909
944
|
} finally {
|
|
910
|
-
end = process$1.hrtime(start), process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError), errorHoist.depth--, process$1.exitCode !== initialExitCode && (success = !1)
|
|
945
|
+
if (end = process$1.hrtime(start), process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError), errorHoist.depth--, process$1.exitCode !== initialExitCode && (success = !1), !success) {
|
|
946
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
947
|
+
ctx && (ctx.failed = !0);
|
|
948
|
+
}
|
|
911
949
|
}
|
|
912
950
|
if (!title) return;
|
|
913
951
|
const duration = end[0] * 1e3 + end[1] / 1e6;
|
|
@@ -985,7 +1023,36 @@ const poku = (async (targetPaths, configs) => {
|
|
|
985
1023
|
each.after.status = !0;
|
|
986
1024
|
}, reset: () => {
|
|
987
1025
|
each.after.cb = void 0;
|
|
988
|
-
} })
|
|
1026
|
+
} });
|
|
1027
|
+
async function retry(config, callback) {
|
|
1028
|
+
const attempts = typeof config == "number" ? config : config.attempts, delay = typeof config == "number" ? 0 : config.delay ?? 0;
|
|
1029
|
+
retryContext.stack || (retryContext.stack = []);
|
|
1030
|
+
const stack = retryContext.stack;
|
|
1031
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
1032
|
+
const context = {
|
|
1033
|
+
attempts,
|
|
1034
|
+
currentAttempt: attempt,
|
|
1035
|
+
delay,
|
|
1036
|
+
failed: !1
|
|
1037
|
+
};
|
|
1038
|
+
stack.push(context), GLOBAL.reporter.onRetryStart?.({ attempt, total: attempts });
|
|
1039
|
+
try {
|
|
1040
|
+
const result = callback();
|
|
1041
|
+
if (result instanceof Promise && await result, !context.failed) {
|
|
1042
|
+
stack.pop(), GLOBAL.reporter.onRetryEnd?.({
|
|
1043
|
+
attempt,
|
|
1044
|
+
total: attempts,
|
|
1045
|
+
success: !0
|
|
1046
|
+
}), stack.length === 0 && (retryContext.stack = null);
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
} catch {
|
|
1050
|
+
}
|
|
1051
|
+
stack.pop(), GLOBAL.reporter.onRetryEnd?.({ attempt, total: attempts, success: !1 }), attempt < attempts && delay > 0 && await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1052
|
+
}
|
|
1053
|
+
stack.length === 0 && (retryContext.stack = null), process.exitCode = 1;
|
|
1054
|
+
}
|
|
1055
|
+
const regex = {
|
|
989
1056
|
sequentialSpaces: /\s+/
|
|
990
1057
|
}, setPortsAndPIDs = (portOrPID) => Array.isArray(portOrPID) ? portOrPID : [portOrPID].map((p) => Number(p)).filter((p) => !Number.isNaN(p)), populateRange = (startsAt, endsAt) => {
|
|
991
1058
|
const first = Number(startsAt), last = Number(endsAt);
|
|
@@ -1206,6 +1273,7 @@ exports.onSigint = onSigint;
|
|
|
1206
1273
|
exports.parserOutput = parserOutput;
|
|
1207
1274
|
exports.poku = poku;
|
|
1208
1275
|
exports.reporter = reporter;
|
|
1276
|
+
exports.retry = retry;
|
|
1209
1277
|
exports.runner = runner;
|
|
1210
1278
|
exports.skip = skip;
|
|
1211
1279
|
exports.sleep = sleep;
|
|
@@ -151,6 +151,15 @@ type ReporterPlugin = (configs?: Configs) => {
|
|
|
151
151
|
onTodoModifier: (options: {
|
|
152
152
|
message: string;
|
|
153
153
|
}) => void;
|
|
154
|
+
onRetryStart: (options: {
|
|
155
|
+
attempt: number;
|
|
156
|
+
total: number;
|
|
157
|
+
}) => void;
|
|
158
|
+
onRetryEnd: (options: {
|
|
159
|
+
attempt: number;
|
|
160
|
+
total: number;
|
|
161
|
+
success: boolean;
|
|
162
|
+
}) => void;
|
|
154
163
|
onFileStart: (options: {
|
|
155
164
|
path: Path;
|
|
156
165
|
}) => void;
|
package/lib/modules/_shared.d.ts
CHANGED
|
@@ -151,6 +151,15 @@ type ReporterPlugin = (configs?: Configs) => {
|
|
|
151
151
|
onTodoModifier: (options: {
|
|
152
152
|
message: string;
|
|
153
153
|
}) => void;
|
|
154
|
+
onRetryStart: (options: {
|
|
155
|
+
attempt: number;
|
|
156
|
+
total: number;
|
|
157
|
+
}) => void;
|
|
158
|
+
onRetryEnd: (options: {
|
|
159
|
+
attempt: number;
|
|
160
|
+
total: number;
|
|
161
|
+
success: boolean;
|
|
162
|
+
}) => void;
|
|
154
163
|
onFileStart: (options: {
|
|
155
164
|
path: Path;
|
|
156
165
|
}) => void;
|
package/lib/modules/_shared.js
CHANGED
|
@@ -237,6 +237,20 @@ ${preIdentation} ${format(`${options?.expected ?? "Expected"}:`).dim()}`
|
|
|
237
237
|
const indent = getIndent();
|
|
238
238
|
log$1(`${indent}${format(`\u25CF ${message}`).cyan().bold()}`);
|
|
239
239
|
},
|
|
240
|
+
onRetryStart({ attempt, total }) {
|
|
241
|
+
const indent = indentation.test.repeat(
|
|
242
|
+
indentation.describeDepth + indentation.itDepth
|
|
243
|
+
);
|
|
244
|
+
log$1(`${indent}${format(`\u21BB Retry ${attempt}/${total}`).dim()}`);
|
|
245
|
+
},
|
|
246
|
+
onRetryEnd({ attempt, success }) {
|
|
247
|
+
if (success && attempt > 1) {
|
|
248
|
+
const indent = indentation.test.repeat(
|
|
249
|
+
indentation.describeDepth + indentation.itDepth
|
|
250
|
+
);
|
|
251
|
+
log$1(`${indent}${format("\u2714 Retry succeeded").success().dim()}`);
|
|
252
|
+
}
|
|
253
|
+
},
|
|
240
254
|
onFileResult({ status, path, duration, output }) {
|
|
241
255
|
stdout.write(`
|
|
242
256
|
`), status ? (log$1(
|
|
@@ -258,15 +272,14 @@ ${preIdentation} ${format(`${options?.expected ?? "Expected"}:`).dim()}`
|
|
|
258
272
|
`${format(String(errors.length)).fail().bold()} ${format("test file(s) failed:").bold()}
|
|
259
273
|
`
|
|
260
274
|
);
|
|
261
|
-
for (const i in errors)
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
index > 0 && stdout.write(`
|
|
275
|
+
for (const i in errors) {
|
|
276
|
+
const { file, output } = errors[i], index = +i;
|
|
277
|
+
index > 0 && stdout.write(`
|
|
265
278
|
`), log$1(
|
|
266
|
-
|
|
267
|
-
|
|
279
|
+
`${format(`${index + 1})`).dim().bold()} ${format(file).underline()}`
|
|
280
|
+
), output && log$1(`
|
|
268
281
|
${output}`);
|
|
269
|
-
|
|
282
|
+
}
|
|
270
283
|
}
|
|
271
284
|
},
|
|
272
285
|
onExit({ results: results2, timespan: timespan2 }) {
|
|
@@ -350,6 +363,10 @@ ${message}
|
|
|
350
363
|
},
|
|
351
364
|
onTodoModifier() {
|
|
352
365
|
},
|
|
366
|
+
onRetryStart() {
|
|
367
|
+
},
|
|
368
|
+
onRetryEnd() {
|
|
369
|
+
},
|
|
353
370
|
onFileResult({ status, path, output }) {
|
|
354
371
|
log$1(`${status ? BADGE_PASS : BADGE_FAIL} ${path.relative}`), status || (countFails++, errors.push({
|
|
355
372
|
file: path.relative,
|
|
@@ -372,6 +389,10 @@ ${message}
|
|
|
372
389
|
},
|
|
373
390
|
onSkipFile() {
|
|
374
391
|
},
|
|
392
|
+
onRetryStart() {
|
|
393
|
+
},
|
|
394
|
+
onRetryEnd() {
|
|
395
|
+
},
|
|
375
396
|
onFileResult({ path, status, output }) {
|
|
376
397
|
stdout.write(status ? DOT_PASS : DOT_FAIL), status || errors.push({
|
|
377
398
|
file: path.relative,
|
|
@@ -395,6 +416,10 @@ ${message}
|
|
|
395
416
|
},
|
|
396
417
|
onSkipFile() {
|
|
397
418
|
},
|
|
419
|
+
onRetryStart() {
|
|
420
|
+
},
|
|
421
|
+
onRetryEnd() {
|
|
422
|
+
},
|
|
398
423
|
onFileResult({ status, output }) {
|
|
399
424
|
status || (countFails++, output && log$1(output));
|
|
400
425
|
},
|
|
@@ -419,7 +444,7 @@ const states = getSharedState("states", {
|
|
|
419
444
|
}), errorHoist = getSharedState("errorHoist", {
|
|
420
445
|
depth: 0,
|
|
421
446
|
failed: !1
|
|
422
|
-
}), VERSION = "4.3.
|
|
447
|
+
}), VERSION = "4.3.3-canary.2648bb03", deepOptions = getSharedState("deepOptions", []), GLOBAL = getSharedState("GLOBAL", {
|
|
423
448
|
cwd: cwd$1,
|
|
424
449
|
configs: {
|
|
425
450
|
filter: void 0,
|
|
@@ -687,11 +712,14 @@ const poku = (async (targetPaths, configs) => {
|
|
|
687
712
|
for (const plugin2 of plugins)
|
|
688
713
|
plugin2.teardown && await plugin2.teardown(pluginContext);
|
|
689
714
|
if (GLOBAL.configs.noExit) return code;
|
|
715
|
+
}), retryContext = getSharedState("retryContext", {
|
|
716
|
+
stack: null
|
|
690
717
|
}), assertProcessor = () => {
|
|
691
718
|
const { reporter: reporter2 } = GLOBAL, handleSuccess = ({ message }) => {
|
|
692
719
|
typeof message == "string" && reporter2.onAssertionSuccess({ message });
|
|
693
720
|
}, handleError = (error, options) => {
|
|
694
|
-
|
|
721
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
722
|
+
throw ctx ? ctx.failed = !0 : process$1.exitCode = 1, error instanceof AssertionError && reporter2.onAssertionFailure({ assertOptions: options, error }), error;
|
|
695
723
|
};
|
|
696
724
|
return { processAssert: (cb, options) => {
|
|
697
725
|
try {
|
|
@@ -862,7 +890,8 @@ const poku = (async (targetPaths, configs) => {
|
|
|
862
890
|
const insideDescribe = errorHoist.depth > 0;
|
|
863
891
|
let onError;
|
|
864
892
|
insideDescribe ? errorHoist.failed = !1 : (onError = (error) => {
|
|
865
|
-
|
|
893
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
894
|
+
ctx ? ctx.failed = !0 : (process$1.exitCode = 1, success = !1, error instanceof AssertionError || console.error(error));
|
|
866
895
|
}, process$1.once("uncaughtException", onError), process$1.once("unhandledRejection", onError)), start = process$1.hrtime();
|
|
867
896
|
try {
|
|
868
897
|
const hooks = getScopeHook();
|
|
@@ -874,9 +903,15 @@ const poku = (async (targetPaths, configs) => {
|
|
|
874
903
|
resultCb instanceof Promise && await resultCb;
|
|
875
904
|
}
|
|
876
905
|
} catch (error) {
|
|
877
|
-
|
|
906
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
907
|
+
ctx ? ctx.failed = !0 : (process$1.exitCode = 1, success = !1, error instanceof AssertionError || console.error(error));
|
|
878
908
|
} finally {
|
|
879
|
-
end = process$1.hrtime(start), onError
|
|
909
|
+
if (end = process$1.hrtime(start), onError)
|
|
910
|
+
process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError);
|
|
911
|
+
else if (errorHoist.failed) {
|
|
912
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
913
|
+
ctx ? ctx.failed = !0 : success = !1, errorHoist.failed = !1;
|
|
914
|
+
}
|
|
880
915
|
}
|
|
881
916
|
if (typeof each.after.cb == "function") {
|
|
882
917
|
const afterResult = each.after.cb();
|
|
@@ -915,7 +950,10 @@ const poku = (async (targetPaths, configs) => {
|
|
|
915
950
|
} catch (error) {
|
|
916
951
|
onError(error);
|
|
917
952
|
} finally {
|
|
918
|
-
end = process$1.hrtime(start), process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError), errorHoist.depth--, process$1.exitCode !== initialExitCode && (success = !1)
|
|
953
|
+
if (end = process$1.hrtime(start), process$1.removeListener("uncaughtException", onError), process$1.removeListener("unhandledRejection", onError), errorHoist.depth--, process$1.exitCode !== initialExitCode && (success = !1), !success) {
|
|
954
|
+
const ctx = retryContext.stack?.[retryContext.stack.length - 1];
|
|
955
|
+
ctx && (ctx.failed = !0);
|
|
956
|
+
}
|
|
919
957
|
}
|
|
920
958
|
if (!title) return;
|
|
921
959
|
const duration = end[0] * 1e3 + end[1] / 1e6;
|
|
@@ -993,7 +1031,36 @@ const poku = (async (targetPaths, configs) => {
|
|
|
993
1031
|
each.after.status = !0;
|
|
994
1032
|
}, reset: () => {
|
|
995
1033
|
each.after.cb = void 0;
|
|
996
|
-
} })
|
|
1034
|
+
} });
|
|
1035
|
+
async function retry(config, callback) {
|
|
1036
|
+
const attempts = typeof config == "number" ? config : config.attempts, delay = typeof config == "number" ? 0 : config.delay ?? 0;
|
|
1037
|
+
retryContext.stack || (retryContext.stack = []);
|
|
1038
|
+
const stack = retryContext.stack;
|
|
1039
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
1040
|
+
const context = {
|
|
1041
|
+
attempts,
|
|
1042
|
+
currentAttempt: attempt,
|
|
1043
|
+
delay,
|
|
1044
|
+
failed: !1
|
|
1045
|
+
};
|
|
1046
|
+
stack.push(context), GLOBAL.reporter.onRetryStart?.({ attempt, total: attempts });
|
|
1047
|
+
try {
|
|
1048
|
+
const result = callback();
|
|
1049
|
+
if (result instanceof Promise && await result, !context.failed) {
|
|
1050
|
+
stack.pop(), GLOBAL.reporter.onRetryEnd?.({
|
|
1051
|
+
attempt,
|
|
1052
|
+
total: attempts,
|
|
1053
|
+
success: !0
|
|
1054
|
+
}), stack.length === 0 && (retryContext.stack = null);
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
} catch {
|
|
1058
|
+
}
|
|
1059
|
+
stack.pop(), GLOBAL.reporter.onRetryEnd?.({ attempt, total: attempts, success: !1 }), attempt < attempts && delay > 0 && await new Promise((resolve2) => setTimeout(resolve2, delay));
|
|
1060
|
+
}
|
|
1061
|
+
stack.length === 0 && (retryContext.stack = null), process.exitCode = 1;
|
|
1062
|
+
}
|
|
1063
|
+
const regex = {
|
|
997
1064
|
sequentialSpaces: /\s+/
|
|
998
1065
|
}, setPortsAndPIDs = (portOrPID) => Array.isArray(portOrPID) ? portOrPID : [portOrPID].map((p) => Number(p)).filter((p) => !Number.isNaN(p)), populateRange = (startsAt, endsAt) => {
|
|
999
1066
|
const first = Number(startsAt), last = Number(endsAt);
|
|
@@ -1228,6 +1295,7 @@ export {
|
|
|
1228
1295
|
poku,
|
|
1229
1296
|
reporter,
|
|
1230
1297
|
results,
|
|
1298
|
+
retry,
|
|
1231
1299
|
runner,
|
|
1232
1300
|
skip,
|
|
1233
1301
|
sleep,
|
package/lib/modules/index.cjs
CHANGED
|
@@ -14,6 +14,7 @@ exports.kill = _shared.kill;
|
|
|
14
14
|
exports.listFiles = _shared.listFiles;
|
|
15
15
|
exports.log = _shared.log;
|
|
16
16
|
exports.poku = _shared.poku;
|
|
17
|
+
exports.retry = _shared.retry;
|
|
17
18
|
exports.skip = _shared.skip;
|
|
18
19
|
exports.sleep = _shared.sleep;
|
|
19
20
|
exports.startScript = _shared.startScript;
|
package/lib/modules/index.d.cts
CHANGED
|
@@ -131,6 +131,13 @@ declare const beforeEach: (callback: () => unknown, options?: EachOptions) => Co
|
|
|
131
131
|
*/
|
|
132
132
|
declare const afterEach: (callback: () => unknown) => Control;
|
|
133
133
|
|
|
134
|
+
type RetryConfig = {
|
|
135
|
+
attempts: number;
|
|
136
|
+
delay?: number;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
declare function retry(config: number | RetryConfig, callback: () => unknown | Promise<unknown>): Promise<void>;
|
|
140
|
+
|
|
134
141
|
type Runner = 'npm' | 'bun' | 'deno' | 'yarn' | 'pnpm';
|
|
135
142
|
|
|
136
143
|
type BackgroundProcessOptions = {
|
|
@@ -250,5 +257,5 @@ declare const listFiles: (targetDir: string, configs?: Configs) => Promise<strin
|
|
|
250
257
|
/** 🐷 Auxiliary function to define the `poku` configurations */
|
|
251
258
|
declare const defineConfig: (options: ConfigFile) => ConfigFile;
|
|
252
259
|
|
|
253
|
-
export { Code, ConfigFile, Configs as ListFilesConfigs, afterEach, assert, beforeEach, defineConfig, describe, envFile, exit, getPIDs, it, kill, listFiles, log, skip, sleep, startScript, startService, strict, test, waitForExpectedResult, waitForPort };
|
|
254
|
-
export type { StartScriptOptions, StartServiceOptions, WaitForExpectedResultOptions, WaitForPortOptions };
|
|
260
|
+
export { Code, ConfigFile, Configs as ListFilesConfigs, afterEach, assert, beforeEach, defineConfig, describe, envFile, exit, getPIDs, it, kill, listFiles, log, retry, skip, sleep, startScript, startService, strict, test, waitForExpectedResult, waitForPort };
|
|
261
|
+
export type { RetryConfig, StartScriptOptions, StartServiceOptions, WaitForExpectedResultOptions, WaitForPortOptions };
|
package/lib/modules/index.d.ts
CHANGED
|
@@ -131,6 +131,13 @@ declare const beforeEach: (callback: () => unknown, options?: EachOptions) => Co
|
|
|
131
131
|
*/
|
|
132
132
|
declare const afterEach: (callback: () => unknown) => Control;
|
|
133
133
|
|
|
134
|
+
type RetryConfig = {
|
|
135
|
+
attempts: number;
|
|
136
|
+
delay?: number;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
declare function retry(config: number | RetryConfig, callback: () => unknown | Promise<unknown>): Promise<void>;
|
|
140
|
+
|
|
134
141
|
type Runner = 'npm' | 'bun' | 'deno' | 'yarn' | 'pnpm';
|
|
135
142
|
|
|
136
143
|
type BackgroundProcessOptions = {
|
|
@@ -250,5 +257,5 @@ declare const listFiles: (targetDir: string, configs?: Configs) => Promise<strin
|
|
|
250
257
|
/** 🐷 Auxiliary function to define the `poku` configurations */
|
|
251
258
|
declare const defineConfig: (options: ConfigFile) => ConfigFile;
|
|
252
259
|
|
|
253
|
-
export { Code, ConfigFile, Configs as ListFilesConfigs, afterEach, assert, beforeEach, defineConfig, describe, envFile, exit, getPIDs, it, kill, listFiles, log, skip, sleep, startScript, startService, strict, test, waitForExpectedResult, waitForPort };
|
|
254
|
-
export type { StartScriptOptions, StartServiceOptions, WaitForExpectedResultOptions, WaitForPortOptions };
|
|
260
|
+
export { Code, ConfigFile, Configs as ListFilesConfigs, afterEach, assert, beforeEach, defineConfig, describe, envFile, exit, getPIDs, it, kill, listFiles, log, retry, skip, sleep, startScript, startService, strict, test, waitForExpectedResult, waitForPort };
|
|
261
|
+
export type { RetryConfig, StartScriptOptions, StartServiceOptions, WaitForExpectedResultOptions, WaitForPortOptions };
|
package/lib/modules/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterEach$1, assert, beforeEach$1, describe, envFile, exit, getPIDs, it, kill, listFiles, log, poku, skip, sleep, startScript, startService, strict, test, VERSION, waitForExpectedResult, waitForPort } from "./_shared.js";
|
|
1
|
+
import { afterEach$1, assert, beforeEach$1, describe, envFile, exit, getPIDs, it, kill, listFiles, log, poku, retry, skip, sleep, startScript, startService, strict, test, VERSION, waitForExpectedResult, waitForPort } from "./_shared.js";
|
|
2
2
|
import "node:path";
|
|
3
3
|
import "node:process";
|
|
4
4
|
import "node:os";
|
|
@@ -22,6 +22,7 @@ export {
|
|
|
22
22
|
listFiles,
|
|
23
23
|
log,
|
|
24
24
|
poku,
|
|
25
|
+
retry,
|
|
25
26
|
skip,
|
|
26
27
|
sleep,
|
|
27
28
|
startScript,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poku",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.3-canary.2648bb03",
|
|
4
4
|
"description": "🐷 Poku makes testing easy for Node.js, Bun, Deno, and you at the same time.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"build": "bash scripts/build.sh",
|
|
53
53
|
"lint": "bash scripts/lint.sh",
|
|
54
54
|
"lint:fix": "bash scripts/lint-fix.sh",
|
|
55
|
-
"
|
|
55
|
+
"typecheck": "bash scripts/typecheck.sh",
|
|
56
56
|
"update": "bash scripts/update.sh",
|
|
57
57
|
"benchmark": "npm --prefix benchmark start"
|
|
58
58
|
},
|