@flemist/test-variants 1.0.7 → 2.0.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.
Files changed (34) hide show
  1. package/dist/bundle/browser.js +437 -212
  2. package/dist/lib/index.cjs +10 -2
  3. package/dist/lib/index.d.ts +6 -2
  4. package/dist/lib/index.mjs +9 -2
  5. package/dist/lib/test-variants/argsToString.cjs +17 -0
  6. package/dist/lib/test-variants/argsToString.d.ts +2 -0
  7. package/dist/lib/test-variants/argsToString.mjs +13 -0
  8. package/dist/lib/test-variants/createTestVariants.cjs +71 -188
  9. package/dist/lib/test-variants/createTestVariants.d.ts +8 -30
  10. package/dist/lib/test-variants/createTestVariants.mjs +71 -188
  11. package/dist/lib/test-variants/createTestVariants.perf.cjs +32 -20
  12. package/dist/lib/test-variants/createTestVariants.perf.mjs +32 -20
  13. package/dist/lib/test-variants/prime.cjs +65 -0
  14. package/dist/lib/test-variants/prime.d.ts +3 -0
  15. package/dist/lib/test-variants/prime.mjs +59 -0
  16. package/dist/lib/test-variants/prime.perf.cjs +30 -0
  17. package/dist/lib/test-variants/prime.perf.d.ts +1 -0
  18. package/dist/lib/test-variants/prime.perf.mjs +28 -0
  19. package/dist/lib/test-variants/saveErrorVariants.cjs +97 -0
  20. package/dist/lib/test-variants/saveErrorVariants.d.ts +9 -0
  21. package/dist/lib/test-variants/saveErrorVariants.mjs +69 -0
  22. package/dist/lib/test-variants/testVariantsCreateTestRun.cjs +80 -0
  23. package/dist/lib/test-variants/testVariantsCreateTestRun.d.ts +22 -0
  24. package/dist/lib/test-variants/testVariantsCreateTestRun.mjs +76 -0
  25. package/dist/lib/test-variants/testVariantsIterable.cjs +67 -0
  26. package/dist/lib/test-variants/testVariantsIterable.d.ts +12 -0
  27. package/dist/lib/test-variants/testVariantsIterable.mjs +63 -0
  28. package/dist/lib/test-variants/testVariantsRun.cjs +235 -0
  29. package/dist/lib/test-variants/testVariantsRun.d.ts +33 -0
  30. package/dist/lib/test-variants/testVariantsRun.mjs +211 -0
  31. package/dist/lib/test-variants/types.cjs +2 -0
  32. package/dist/lib/test-variants/types.d.ts +18 -0
  33. package/dist/lib/test-variants/types.mjs +1 -0
  34. package/package.json +12 -9
@@ -0,0 +1,235 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var tslib = require('tslib');
6
+ var abortControllerFast = require('@flemist/abort-controller-fast');
7
+ var asyncUtils = require('@flemist/async-utils');
8
+ var timeLimits = require('@flemist/time-limits');
9
+ var garbageCollect_garbageCollect = require('../garbage-collect/garbageCollect.cjs');
10
+ var testVariants_saveErrorVariants = require('./saveErrorVariants.cjs');
11
+ var path = require('path');
12
+ require('fs');
13
+
14
+ function _interopNamespace(e) {
15
+ if (e && e.__esModule) return e;
16
+ var n = Object.create(null);
17
+ if (e) {
18
+ Object.keys(e).forEach(function (k) {
19
+ if (k !== 'default') {
20
+ var d = Object.getOwnPropertyDescriptor(e, k);
21
+ Object.defineProperty(n, k, d.get ? d : {
22
+ enumerable: true,
23
+ get: function () { return e[k]; }
24
+ });
25
+ }
26
+ });
27
+ }
28
+ n["default"] = e;
29
+ return Object.freeze(n);
30
+ }
31
+
32
+ var path__namespace = /*#__PURE__*/_interopNamespace(path);
33
+
34
+ function testVariantsRun(testRun, variants, options = {}) {
35
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
36
+ return tslib.__awaiter(this, void 0, void 0, function* () {
37
+ const saveErrorVariants = options.saveErrorVariants;
38
+ const retriesPerVariant = (_a = saveErrorVariants === null || saveErrorVariants === void 0 ? void 0 : saveErrorVariants.retriesPerVariant) !== null && _a !== void 0 ? _a : 1;
39
+ const sessionDate = new Date();
40
+ const errorVariantFilePath = saveErrorVariants
41
+ ? path__namespace.resolve(saveErrorVariants.dir, (_c = (_b = saveErrorVariants.getFilePath) === null || _b === void 0 ? void 0 : _b.call(saveErrorVariants, { sessionDate })) !== null && _c !== void 0 ? _c : testVariants_saveErrorVariants.generateErrorVariantFilePath({ sessionDate }))
42
+ : null;
43
+ // Replay phase: run previously saved error variants before normal iteration
44
+ if (saveErrorVariants) {
45
+ const files = yield testVariants_saveErrorVariants.readErrorVariantFiles(saveErrorVariants.dir);
46
+ for (const filePath of files) {
47
+ const args = yield testVariants_saveErrorVariants.parseErrorVariantFile(filePath, saveErrorVariants.jsonToArgs);
48
+ for (let retry = 0; retry < retriesPerVariant; retry++) {
49
+ const promiseOrResult = testRun(args, -1, null);
50
+ if (asyncUtils.isPromiseLike(promiseOrResult)) {
51
+ yield promiseOrResult;
52
+ }
53
+ }
54
+ }
55
+ }
56
+ const GC_Iterations = (_d = options.GC_Iterations) !== null && _d !== void 0 ? _d : 1000000;
57
+ const GC_IterationsAsync = (_e = options.GC_IterationsAsync) !== null && _e !== void 0 ? _e : 10000;
58
+ const GC_Interval = (_f = options.GC_Interval) !== null && _f !== void 0 ? _f : 1000;
59
+ const logInterval = (_g = options.logInterval) !== null && _g !== void 0 ? _g : 5000;
60
+ const logCompleted = (_h = options.logCompleted) !== null && _h !== void 0 ? _h : true;
61
+ const abortSignalExternal = options.abortSignal;
62
+ const findBestError = options.findBestError;
63
+ const parallel = options.parallel === true
64
+ ? Math.pow(2, 31)
65
+ : !options.parallel || options.parallel <= 0
66
+ ? 1
67
+ : options.parallel;
68
+ const seedsIterator = (_j = findBestError === null || findBestError === void 0 ? void 0 : findBestError.seeds[Symbol.iterator]()) !== null && _j !== void 0 ? _j : null;
69
+ let seedResult = seedsIterator === null || seedsIterator === void 0 ? void 0 : seedsIterator.next();
70
+ let bestError = null;
71
+ let index = -1;
72
+ let args = {};
73
+ let variantsIterator = variants[Symbol.iterator]();
74
+ function nextVariant() {
75
+ while (true) {
76
+ index++;
77
+ if (seedResult && seedResult.done) {
78
+ return false;
79
+ }
80
+ if (bestError == null || index < bestError.index) {
81
+ const result = variantsIterator.next();
82
+ if (!result.done) {
83
+ args = result.value;
84
+ return true;
85
+ }
86
+ }
87
+ if (!seedsIterator) {
88
+ return false;
89
+ }
90
+ seedResult = seedsIterator.next();
91
+ if (seedResult.done) {
92
+ return false;
93
+ }
94
+ index = -1;
95
+ variantsIterator = variants[Symbol.iterator]();
96
+ }
97
+ }
98
+ const abortControllerParallel = new abortControllerFast.AbortControllerFast();
99
+ const abortSignalParallel = asyncUtils.combineAbortSignals(abortSignalExternal, abortControllerParallel.signal);
100
+ const abortSignalAll = abortSignalParallel;
101
+ let debug = false;
102
+ let iterations = 0;
103
+ let iterationsAsync = 0;
104
+ let prevLogTime = Date.now();
105
+ let prevGC_Time = prevLogTime;
106
+ let prevGC_Iterations = iterations;
107
+ let prevGC_IterationsAsync = iterationsAsync;
108
+ const pool = parallel <= 1
109
+ ? null
110
+ : new timeLimits.Pool(parallel);
111
+ function onCompleted() {
112
+ if (logCompleted) {
113
+ console.log(`[test-variants] variants: ${index}, iterations: ${iterations}, async: ${iterationsAsync}`);
114
+ }
115
+ }
116
+ function next() {
117
+ return tslib.__awaiter(this, void 0, void 0, function* () {
118
+ while (!(abortSignalExternal === null || abortSignalExternal === void 0 ? void 0 : abortSignalExternal.aborted) && (debug || nextVariant())) {
119
+ const _index = index;
120
+ const _args = Object.assign(Object.assign({}, args), { seed: seedResult === null || seedResult === void 0 ? void 0 : seedResult.value });
121
+ const now = (logInterval || GC_Interval) && Date.now();
122
+ if (logInterval && now - prevLogTime >= logInterval) {
123
+ // the log is required to prevent the karma browserNoActivityTimeout
124
+ console.log(iterations);
125
+ prevLogTime = now;
126
+ }
127
+ if (GC_Iterations && iterations - prevGC_Iterations >= GC_Iterations
128
+ || GC_IterationsAsync && iterationsAsync - prevGC_IterationsAsync >= GC_IterationsAsync
129
+ || GC_Interval && now - prevGC_Time >= GC_Interval) {
130
+ prevGC_Iterations = iterations;
131
+ prevGC_IterationsAsync = iterationsAsync;
132
+ prevGC_Time = now;
133
+ yield garbageCollect_garbageCollect.garbageCollect(1);
134
+ }
135
+ if (abortSignalExternal === null || abortSignalExternal === void 0 ? void 0 : abortSignalExternal.aborted) {
136
+ continue;
137
+ }
138
+ if (!pool || abortSignalParallel.aborted) {
139
+ try {
140
+ let promiseOrIterations = testRun(_args, _index, abortSignalParallel);
141
+ if (asyncUtils.isPromiseLike(promiseOrIterations)) {
142
+ promiseOrIterations = yield promiseOrIterations;
143
+ }
144
+ if (!promiseOrIterations) {
145
+ debug = true;
146
+ abortControllerParallel.abort();
147
+ continue;
148
+ }
149
+ const { iterationsAsync: _iterationsAsync, iterationsSync: _iterationsSync } = promiseOrIterations;
150
+ iterationsAsync += _iterationsAsync;
151
+ iterations += _iterationsSync + _iterationsAsync;
152
+ }
153
+ catch (err) {
154
+ if (errorVariantFilePath) {
155
+ yield testVariants_saveErrorVariants.saveErrorVariantFile(_args, errorVariantFilePath, saveErrorVariants.argsToJson);
156
+ }
157
+ if (findBestError) {
158
+ bestError = {
159
+ error: err,
160
+ args: _args,
161
+ index: _index,
162
+ };
163
+ debug = false;
164
+ }
165
+ else {
166
+ throw err;
167
+ }
168
+ }
169
+ }
170
+ else {
171
+ if (!pool.hold(1)) {
172
+ yield pool.holdWait(1);
173
+ }
174
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
175
+ void (() => tslib.__awaiter(this, void 0, void 0, function* () {
176
+ try {
177
+ if (abortSignalParallel === null || abortSignalParallel === void 0 ? void 0 : abortSignalParallel.aborted) {
178
+ return;
179
+ }
180
+ let promiseOrIterations = testRun(_args, _index, abortSignalParallel);
181
+ if (asyncUtils.isPromiseLike(promiseOrIterations)) {
182
+ promiseOrIterations = yield promiseOrIterations;
183
+ }
184
+ if (!promiseOrIterations) {
185
+ debug = true;
186
+ abortControllerParallel.abort();
187
+ return;
188
+ }
189
+ const { iterationsAsync: _iterationsAsync, iterationsSync: _iterationsSync } = promiseOrIterations;
190
+ iterationsAsync += _iterationsAsync;
191
+ iterations += _iterationsSync + _iterationsAsync;
192
+ }
193
+ catch (err) {
194
+ if (errorVariantFilePath) {
195
+ yield testVariants_saveErrorVariants.saveErrorVariantFile(_args, errorVariantFilePath, saveErrorVariants.argsToJson);
196
+ }
197
+ if (findBestError) {
198
+ bestError = {
199
+ error: err,
200
+ args: _args,
201
+ index: _index,
202
+ };
203
+ debug = false;
204
+ }
205
+ else {
206
+ throw err;
207
+ }
208
+ }
209
+ finally {
210
+ void pool.release(1);
211
+ }
212
+ }))();
213
+ }
214
+ }
215
+ if (pool) {
216
+ yield pool.holdWait(parallel);
217
+ void pool.release(parallel);
218
+ }
219
+ if (abortSignalAll === null || abortSignalAll === void 0 ? void 0 : abortSignalAll.aborted) {
220
+ throw abortSignalAll.reason;
221
+ }
222
+ onCompleted();
223
+ yield garbageCollect_garbageCollect.garbageCollect(1);
224
+ return iterations;
225
+ });
226
+ }
227
+ const result = yield next();
228
+ return {
229
+ iterations: result,
230
+ bestError,
231
+ };
232
+ });
233
+ }
234
+
235
+ exports.testVariantsRun = testVariantsRun;
@@ -0,0 +1,33 @@
1
+ import { TestVariantsTestRun } from './testVariantsCreateTestRun';
2
+ import { type IAbortSignalFast } from '@flemist/abort-controller-fast';
3
+ import { Obj, type SaveErrorVariantsOptions } from "./types";
4
+ export declare type TestVariantsFindBestErrorOptions = {
5
+ seeds: Iterable<any>;
6
+ };
7
+ export declare type TestVariantsRunOptions<Args extends Obj = Obj, SavedArgs = Args> = {
8
+ /** Wait for garbage collection after iterations */
9
+ GC_Iterations?: null | number;
10
+ /** Same as GC_Iterations but only for async test variants, required for 10000 and more of Promise rejections */
11
+ GC_IterationsAsync?: null | number;
12
+ /** Wait for garbage collection after time interval, required to prevent the karma browserDisconnectTimeout */
13
+ GC_Interval?: null | number;
14
+ /** console log current iterations, required to prevent the karma browserNoActivityTimeout */
15
+ logInterval?: null | number;
16
+ /** console log iterations on test completed */
17
+ logCompleted?: null | boolean;
18
+ abortSignal?: null | IAbortSignalFast;
19
+ parallel?: null | number | boolean;
20
+ findBestError?: null | TestVariantsFindBestErrorOptions;
21
+ /** Save error-causing args to files and replay them before normal iteration */
22
+ saveErrorVariants?: null | SaveErrorVariantsOptions<Args, SavedArgs>;
23
+ };
24
+ export declare type TestVariantsBestError<Args extends Obj> = {
25
+ error: any;
26
+ args: Args;
27
+ index: number;
28
+ };
29
+ export declare type TestVariantsRunResult<Arg extends Obj> = {
30
+ iterations: number;
31
+ bestError: null | TestVariantsBestError<Arg>;
32
+ };
33
+ export declare function testVariantsRun<Args extends Obj, SavedArgs = Args>(testRun: TestVariantsTestRun<Args>, variants: Iterable<Args>, options?: TestVariantsRunOptions<Args, SavedArgs>): Promise<TestVariantsRunResult<Args>>;
@@ -0,0 +1,211 @@
1
+ import { __awaiter } from 'tslib';
2
+ import { AbortControllerFast } from '@flemist/abort-controller-fast';
3
+ import { isPromiseLike, combineAbortSignals } from '@flemist/async-utils';
4
+ import { Pool } from '@flemist/time-limits';
5
+ import { garbageCollect } from '../garbage-collect/garbageCollect.mjs';
6
+ import { generateErrorVariantFilePath, readErrorVariantFiles, parseErrorVariantFile, saveErrorVariantFile } from './saveErrorVariants.mjs';
7
+ import * as path from 'path';
8
+ import 'fs';
9
+
10
+ function testVariantsRun(testRun, variants, options = {}) {
11
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
12
+ return __awaiter(this, void 0, void 0, function* () {
13
+ const saveErrorVariants = options.saveErrorVariants;
14
+ const retriesPerVariant = (_a = saveErrorVariants === null || saveErrorVariants === void 0 ? void 0 : saveErrorVariants.retriesPerVariant) !== null && _a !== void 0 ? _a : 1;
15
+ const sessionDate = new Date();
16
+ const errorVariantFilePath = saveErrorVariants
17
+ ? path.resolve(saveErrorVariants.dir, (_c = (_b = saveErrorVariants.getFilePath) === null || _b === void 0 ? void 0 : _b.call(saveErrorVariants, { sessionDate })) !== null && _c !== void 0 ? _c : generateErrorVariantFilePath({ sessionDate }))
18
+ : null;
19
+ // Replay phase: run previously saved error variants before normal iteration
20
+ if (saveErrorVariants) {
21
+ const files = yield readErrorVariantFiles(saveErrorVariants.dir);
22
+ for (const filePath of files) {
23
+ const args = yield parseErrorVariantFile(filePath, saveErrorVariants.jsonToArgs);
24
+ for (let retry = 0; retry < retriesPerVariant; retry++) {
25
+ const promiseOrResult = testRun(args, -1, null);
26
+ if (isPromiseLike(promiseOrResult)) {
27
+ yield promiseOrResult;
28
+ }
29
+ }
30
+ }
31
+ }
32
+ const GC_Iterations = (_d = options.GC_Iterations) !== null && _d !== void 0 ? _d : 1000000;
33
+ const GC_IterationsAsync = (_e = options.GC_IterationsAsync) !== null && _e !== void 0 ? _e : 10000;
34
+ const GC_Interval = (_f = options.GC_Interval) !== null && _f !== void 0 ? _f : 1000;
35
+ const logInterval = (_g = options.logInterval) !== null && _g !== void 0 ? _g : 5000;
36
+ const logCompleted = (_h = options.logCompleted) !== null && _h !== void 0 ? _h : true;
37
+ const abortSignalExternal = options.abortSignal;
38
+ const findBestError = options.findBestError;
39
+ const parallel = options.parallel === true
40
+ ? Math.pow(2, 31)
41
+ : !options.parallel || options.parallel <= 0
42
+ ? 1
43
+ : options.parallel;
44
+ const seedsIterator = (_j = findBestError === null || findBestError === void 0 ? void 0 : findBestError.seeds[Symbol.iterator]()) !== null && _j !== void 0 ? _j : null;
45
+ let seedResult = seedsIterator === null || seedsIterator === void 0 ? void 0 : seedsIterator.next();
46
+ let bestError = null;
47
+ let index = -1;
48
+ let args = {};
49
+ let variantsIterator = variants[Symbol.iterator]();
50
+ function nextVariant() {
51
+ while (true) {
52
+ index++;
53
+ if (seedResult && seedResult.done) {
54
+ return false;
55
+ }
56
+ if (bestError == null || index < bestError.index) {
57
+ const result = variantsIterator.next();
58
+ if (!result.done) {
59
+ args = result.value;
60
+ return true;
61
+ }
62
+ }
63
+ if (!seedsIterator) {
64
+ return false;
65
+ }
66
+ seedResult = seedsIterator.next();
67
+ if (seedResult.done) {
68
+ return false;
69
+ }
70
+ index = -1;
71
+ variantsIterator = variants[Symbol.iterator]();
72
+ }
73
+ }
74
+ const abortControllerParallel = new AbortControllerFast();
75
+ const abortSignalParallel = combineAbortSignals(abortSignalExternal, abortControllerParallel.signal);
76
+ const abortSignalAll = abortSignalParallel;
77
+ let debug = false;
78
+ let iterations = 0;
79
+ let iterationsAsync = 0;
80
+ let prevLogTime = Date.now();
81
+ let prevGC_Time = prevLogTime;
82
+ let prevGC_Iterations = iterations;
83
+ let prevGC_IterationsAsync = iterationsAsync;
84
+ const pool = parallel <= 1
85
+ ? null
86
+ : new Pool(parallel);
87
+ function onCompleted() {
88
+ if (logCompleted) {
89
+ console.log(`[test-variants] variants: ${index}, iterations: ${iterations}, async: ${iterationsAsync}`);
90
+ }
91
+ }
92
+ function next() {
93
+ return __awaiter(this, void 0, void 0, function* () {
94
+ while (!(abortSignalExternal === null || abortSignalExternal === void 0 ? void 0 : abortSignalExternal.aborted) && (debug || nextVariant())) {
95
+ const _index = index;
96
+ const _args = Object.assign(Object.assign({}, args), { seed: seedResult === null || seedResult === void 0 ? void 0 : seedResult.value });
97
+ const now = (logInterval || GC_Interval) && Date.now();
98
+ if (logInterval && now - prevLogTime >= logInterval) {
99
+ // the log is required to prevent the karma browserNoActivityTimeout
100
+ console.log(iterations);
101
+ prevLogTime = now;
102
+ }
103
+ if (GC_Iterations && iterations - prevGC_Iterations >= GC_Iterations
104
+ || GC_IterationsAsync && iterationsAsync - prevGC_IterationsAsync >= GC_IterationsAsync
105
+ || GC_Interval && now - prevGC_Time >= GC_Interval) {
106
+ prevGC_Iterations = iterations;
107
+ prevGC_IterationsAsync = iterationsAsync;
108
+ prevGC_Time = now;
109
+ yield garbageCollect(1);
110
+ }
111
+ if (abortSignalExternal === null || abortSignalExternal === void 0 ? void 0 : abortSignalExternal.aborted) {
112
+ continue;
113
+ }
114
+ if (!pool || abortSignalParallel.aborted) {
115
+ try {
116
+ let promiseOrIterations = testRun(_args, _index, abortSignalParallel);
117
+ if (isPromiseLike(promiseOrIterations)) {
118
+ promiseOrIterations = yield promiseOrIterations;
119
+ }
120
+ if (!promiseOrIterations) {
121
+ debug = true;
122
+ abortControllerParallel.abort();
123
+ continue;
124
+ }
125
+ const { iterationsAsync: _iterationsAsync, iterationsSync: _iterationsSync } = promiseOrIterations;
126
+ iterationsAsync += _iterationsAsync;
127
+ iterations += _iterationsSync + _iterationsAsync;
128
+ }
129
+ catch (err) {
130
+ if (errorVariantFilePath) {
131
+ yield saveErrorVariantFile(_args, errorVariantFilePath, saveErrorVariants.argsToJson);
132
+ }
133
+ if (findBestError) {
134
+ bestError = {
135
+ error: err,
136
+ args: _args,
137
+ index: _index,
138
+ };
139
+ debug = false;
140
+ }
141
+ else {
142
+ throw err;
143
+ }
144
+ }
145
+ }
146
+ else {
147
+ if (!pool.hold(1)) {
148
+ yield pool.holdWait(1);
149
+ }
150
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
151
+ void (() => __awaiter(this, void 0, void 0, function* () {
152
+ try {
153
+ if (abortSignalParallel === null || abortSignalParallel === void 0 ? void 0 : abortSignalParallel.aborted) {
154
+ return;
155
+ }
156
+ let promiseOrIterations = testRun(_args, _index, abortSignalParallel);
157
+ if (isPromiseLike(promiseOrIterations)) {
158
+ promiseOrIterations = yield promiseOrIterations;
159
+ }
160
+ if (!promiseOrIterations) {
161
+ debug = true;
162
+ abortControllerParallel.abort();
163
+ return;
164
+ }
165
+ const { iterationsAsync: _iterationsAsync, iterationsSync: _iterationsSync } = promiseOrIterations;
166
+ iterationsAsync += _iterationsAsync;
167
+ iterations += _iterationsSync + _iterationsAsync;
168
+ }
169
+ catch (err) {
170
+ if (errorVariantFilePath) {
171
+ yield saveErrorVariantFile(_args, errorVariantFilePath, saveErrorVariants.argsToJson);
172
+ }
173
+ if (findBestError) {
174
+ bestError = {
175
+ error: err,
176
+ args: _args,
177
+ index: _index,
178
+ };
179
+ debug = false;
180
+ }
181
+ else {
182
+ throw err;
183
+ }
184
+ }
185
+ finally {
186
+ void pool.release(1);
187
+ }
188
+ }))();
189
+ }
190
+ }
191
+ if (pool) {
192
+ yield pool.holdWait(parallel);
193
+ void pool.release(parallel);
194
+ }
195
+ if (abortSignalAll === null || abortSignalAll === void 0 ? void 0 : abortSignalAll.aborted) {
196
+ throw abortSignalAll.reason;
197
+ }
198
+ onCompleted();
199
+ yield garbageCollect(1);
200
+ return iterations;
201
+ });
202
+ }
203
+ const result = yield next();
204
+ return {
205
+ iterations: result,
206
+ bestError,
207
+ };
208
+ });
209
+ }
210
+
211
+ export { testVariantsRun };
@@ -0,0 +1,2 @@
1
+ 'use strict';
2
+
@@ -0,0 +1,18 @@
1
+ export declare type Obj = Record<string, any>;
2
+ /** Options for generating error variant file path */
3
+ export declare type GenerateErrorVariantFilePathOptions = {
4
+ sessionDate: Date;
5
+ };
6
+ /** Options for saving and replaying error-causing parameter combinations */
7
+ export declare type SaveErrorVariantsOptions<Args, SavedArgs = Args> = {
8
+ /** Directory path for error variant JSON files */
9
+ dir: string;
10
+ /** Retry attempts per variant during replay phase (default: 1) */
11
+ retriesPerVariant?: null | number;
12
+ /** Custom file path generator; returns path relative to dir; null - use default path */
13
+ getFilePath?: null | ((options: GenerateErrorVariantFilePathOptions) => string | null);
14
+ /** Transform args before JSON serialization */
15
+ argsToJson?: null | ((args: Args) => string | SavedArgs);
16
+ /** Transform parsed JSON back to args */
17
+ jsonToArgs?: null | ((json: SavedArgs) => Args);
18
+ };
@@ -0,0 +1 @@
1
+
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@flemist/test-variants",
3
- "version": "1.0.7",
3
+ "version": "2.0.0",
4
4
  "description": "Runs a test function with all possible combinations of its parameters.",
5
5
  "main": "dist/lib/index.cjs",
6
6
  "module": "dist/lib/index.mjs",
7
7
  "types": "dist/lib/index.d.ts",
8
8
  "engines": {
9
- "node": ">=10.4.0",
9
+ "node": ">=11.14.0",
10
10
  "pnpm": ">=7.1.6"
11
11
  },
12
12
  "repository": {
@@ -33,7 +33,7 @@
33
33
  "access": "public"
34
34
  },
35
35
  "scripts": {
36
- "_prepublishOnly": "pnpm run audit && pnpm run lint && pnpm run build && pnpm run test:mocha:ci && pnpm run test:karma",
36
+ "_prepublishOnly": "pnpm run audit && pnpm run lint && pnpm run build && pnpm run test:mocha:ci && pnpm run test:karma && npm login",
37
37
  "audit": "pnpm audit --prod",
38
38
  "lint": "eslint ./**/*.{js,cjs,mjs,ts,tsx}",
39
39
  "lint:fix": "eslint --fix ./**/*.{js,cjs,mjs,ts,tsx}",
@@ -47,17 +47,20 @@
47
47
  "test:mocha:watch": "mocha --watch ./src/**/*.test.*",
48
48
  "test:karma": "rimraf tmp/coverage/karma && karma start --single-run --log-level debug",
49
49
  "test:mocha:ci": "rimraf tmp/coverage/mocha && nyc --all mocha ./{src,dist/lib}/**/*.test.*",
50
- "coveralls": "pnpm run coverage:check && nyc report --reporter=text-lcov --temp-dir \"tmp/coverage/merge/\" | coveralls"
50
+ "coveralls": "pnpm run coverage:check && nyc report --reporter=text-lcov --temp-dir \"tmp/coverage/merge/\" | coveralls",
51
+ "mcp:tools": "mcp-project-tools"
51
52
  },
52
53
  "devDependencies": {
54
+ "@anthropic-ai/claude-code": "^2.0.76",
53
55
  "@babel/core": "7.18.5",
54
56
  "@babel/plugin-syntax-dynamic-import": "7.8.3",
55
57
  "@babel/plugin-transform-classes": "7.18.4",
56
58
  "@babel/plugin-transform-runtime": "7.18.5",
57
59
  "@babel/preset-env": "7.18.2",
58
- "@babel/runtime-corejs3": "7.18.3",
60
+ "@babel/runtime-corejs3": "7.28.3",
59
61
  "@flemist/copy-glob-flat": "0.0.5",
60
62
  "@flemist/karma-custom-launcher": "0.0.0",
63
+ "@flemist/mcp-project-tools": "3.0.19",
61
64
  "@flemist/test-utils": "1.0.2",
62
65
  "@rollup/plugin-alias": "3.1.9",
63
66
  "@rollup/plugin-babel": "5.3.1",
@@ -67,7 +70,7 @@
67
70
  "@rollup/plugin-multi-entry": "4.1.0",
68
71
  "@rollup/plugin-node-resolve": "13.3.0",
69
72
  "@rollup/plugin-replace": "4.0.0",
70
- "@rollup/plugin-typescript": "11.1.5",
73
+ "@rollup/plugin-typescript": "12.1.4",
71
74
  "@rollup/pluginutils": "4.2.1",
72
75
  "@types/assert": "1.5.6",
73
76
  "@types/mocha": "9.1.1",
@@ -85,9 +88,9 @@
85
88
  "karma-safari-launcher": "1.0.0",
86
89
  "mocha": "9.2.2",
87
90
  "nyc": "15.1.0",
88
- "rdtsc": "3.0.4",
91
+ "rdtsc": "5.0.7",
89
92
  "rimraf": "3.0.2",
90
- "rollup": "2.75.7",
93
+ "rollup": "2.79.2",
91
94
  "rollup-plugin-delete": "2.0.0",
92
95
  "rollup-plugin-istanbul": "3.0.0",
93
96
  "rollup-plugin-multi-input": "1.3.1",
@@ -101,6 +104,6 @@
101
104
  "@flemist/abort-controller-fast": "^1.0.0",
102
105
  "@flemist/async-utils": "^1.0.0",
103
106
  "@flemist/time-limits": "^1.0.1",
104
- "tslib": "^2.4.0"
107
+ "tslib": "2.5.3"
105
108
  }
106
109
  }