@flemist/test-variants 3.0.3 → 5.0.1

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 (118) hide show
  1. package/README.md +287 -49
  2. package/build/browser/index.cjs +1 -0
  3. package/build/browser/index.d.ts +1 -0
  4. package/build/browser/index.mjs +4 -0
  5. package/build/common/-test/freezeProps.d.ts +2 -0
  6. package/build/common/garbage-collect/garbageCollect.d.ts +5 -0
  7. package/build/common/helpers/log.d.ts +5 -0
  8. package/build/common/index.cjs +1 -0
  9. package/build/common/index.d.ts +2 -0
  10. package/build/common/index.mjs +4 -0
  11. package/build/common/test-variants/-test/caches.d.ts +1 -0
  12. package/build/common/test-variants/-test/constants.d.ts +8 -0
  13. package/build/common/test-variants/-test/estimations/estimateCallCount.d.ts +4 -0
  14. package/build/common/test-variants/-test/estimations/estimateModeChanges.d.ts +4 -0
  15. package/build/common/test-variants/-test/generators/findBestError.d.ts +4 -0
  16. package/build/common/test-variants/-test/generators/primitives.d.ts +16 -0
  17. package/build/common/test-variants/-test/generators/run.d.ts +9 -0
  18. package/build/common/test-variants/-test/generators/template.d.ts +3 -0
  19. package/build/common/test-variants/-test/generators/testFunc.d.ts +3 -0
  20. package/build/common/test-variants/-test/helpers/CallController.d.ts +28 -0
  21. package/build/common/test-variants/-test/helpers/ErrorVariantController.d.ts +17 -0
  22. package/build/common/test-variants/-test/helpers/TestError.d.ts +2 -0
  23. package/build/common/test-variants/-test/helpers/deepEqualJsonLikeWithoutSeed.d.ts +1 -0
  24. package/build/common/test-variants/-test/helpers/deepFreezeJsonLike.d.ts +1 -0
  25. package/build/common/test-variants/-test/helpers/forEachVariant.d.ts +4 -0
  26. package/build/common/test-variants/-test/helpers/getMaxAttemptsPerVariant.d.ts +2 -0
  27. package/build/common/test-variants/-test/helpers/getParallelLimit.d.ts +7 -0
  28. package/build/common/test-variants/-test/helpers/getVariantArgs.d.ts +12 -0
  29. package/build/common/test-variants/-test/helpers/runWithTimeController.d.ts +7 -0
  30. package/build/common/test-variants/-test/invariants/CallCountInvariant.d.ts +18 -0
  31. package/build/common/test-variants/-test/invariants/CallOptionsInvariant.d.ts +32 -0
  32. package/build/common/test-variants/-test/invariants/ErrorBehaviorInvariant.d.ts +32 -0
  33. package/build/common/test-variants/-test/invariants/FindBestErrorInvariant.d.ts +37 -0
  34. package/build/common/test-variants/-test/invariants/IterationsInvariant.d.ts +21 -0
  35. package/build/common/test-variants/-test/invariants/LimitTimeInvariant.d.ts +26 -0
  36. package/build/common/test-variants/-test/invariants/LogInvariant.d.ts +126 -0
  37. package/build/common/test-variants/-test/invariants/OnErrorInvariant.d.ts +38 -0
  38. package/build/common/test-variants/-test/invariants/OnModeChangeInvariant.d.ts +32 -0
  39. package/build/common/test-variants/-test/invariants/ParallelInvariant.d.ts +25 -0
  40. package/build/common/test-variants/-test/log.d.ts +3 -0
  41. package/build/common/test-variants/-test/types.d.ts +34 -0
  42. package/build/common/test-variants/-test/variants.d.ts +3 -0
  43. package/build/common/test-variants/createTestRun.d.ts +3 -0
  44. package/build/common/test-variants/createTestVariants.d.ts +4 -0
  45. package/build/common/test-variants/iterator/createVariantsIterator.d.ts +4 -0
  46. package/build/common/test-variants/iterator/helpers/findValueIndex.d.ts +2 -0
  47. package/build/common/test-variants/iterator/helpers/mode.d.ts +3 -0
  48. package/build/common/test-variants/iterator/helpers/template.d.ts +7 -0
  49. package/build/common/test-variants/iterator/types.d.ts +106 -0
  50. package/build/common/test-variants/iterator/variant-navigation/-test/helpers/caches.d.ts +1 -0
  51. package/build/common/test-variants/iterator/variant-navigation/-test/helpers/check.d.ts +2 -0
  52. package/build/common/test-variants/iterator/variant-navigation/-test/helpers/create.d.ts +3 -0
  53. package/build/common/test-variants/iterator/variant-navigation/-test/helpers/format.d.ts +6 -0
  54. package/build/common/test-variants/iterator/variant-navigation/-test/helpers/parse.d.ts +8 -0
  55. package/build/common/test-variants/iterator/variant-navigation/-test/helpers/variants.d.ts +12 -0
  56. package/build/common/test-variants/iterator/variant-navigation/variantNavigation.d.ts +28 -0
  57. package/build/common/test-variants/log/format.d.ts +7 -0
  58. package/build/common/test-variants/log/getMemoryUsage.d.ts +2 -0
  59. package/build/common/test-variants/log/logOptions.d.ts +8 -0
  60. package/build/common/test-variants/run/AbortErrorSilent.d.ts +3 -0
  61. package/build/common/test-variants/run/RunContext.d.ts +21 -0
  62. package/build/common/test-variants/run/createRunResult.d.ts +6 -0
  63. package/build/common/test-variants/run/createRunState.d.ts +23 -0
  64. package/build/common/test-variants/run/errorHandlers.d.ts +20 -0
  65. package/build/common/test-variants/run/gcManager.d.ts +6 -0
  66. package/build/common/test-variants/run/resolveRunOptions.d.ts +23 -0
  67. package/build/common/test-variants/run/runIterationLoop.d.ts +9 -0
  68. package/build/common/test-variants/run/runLogger.d.ts +9 -0
  69. package/build/common/test-variants/run/types.d.ts +57 -0
  70. package/build/common/test-variants/testVariantsRun.d.ts +6 -0
  71. package/build/common/test-variants/types.d.ts +187 -0
  72. package/build/createTestVariants-BE_TQ9u5.mjs +1018 -0
  73. package/build/createTestVariants-Cmx68kHs.js +4 -0
  74. package/build/node/index.cjs +1 -0
  75. package/build/node/index.d.ts +8 -0
  76. package/build/node/index.mjs +107 -0
  77. package/build/node/test-variants/createSaveErrorVariantsStore.d.ts +5 -0
  78. package/{dist/lib → build/node}/test-variants/saveErrorVariants.d.ts +4 -3
  79. package/package.json +109 -68
  80. package/dist/bundle/browser.js +0 -669
  81. package/dist/lib/garbage-collect/garbageCollect.cjs +0 -30
  82. package/dist/lib/garbage-collect/garbageCollect.d.ts +0 -2
  83. package/dist/lib/garbage-collect/garbageCollect.mjs +0 -26
  84. package/dist/lib/index.cjs +0 -23
  85. package/dist/lib/index.d.ts +0 -7
  86. package/dist/lib/index.mjs +0 -13
  87. package/dist/lib/test-variants/argsToString.cjs +0 -17
  88. package/dist/lib/test-variants/argsToString.d.ts +0 -2
  89. package/dist/lib/test-variants/argsToString.mjs +0 -13
  90. package/dist/lib/test-variants/createTestVariants.cjs +0 -91
  91. package/dist/lib/test-variants/createTestVariants.d.ts +0 -8
  92. package/dist/lib/test-variants/createTestVariants.mjs +0 -87
  93. package/dist/lib/test-variants/createTestVariants.perf.cjs +0 -44
  94. package/dist/lib/test-variants/createTestVariants.perf.d.ts +0 -1
  95. package/dist/lib/test-variants/createTestVariants.perf.mjs +0 -42
  96. package/dist/lib/test-variants/prime.cjs +0 -65
  97. package/dist/lib/test-variants/prime.d.ts +0 -3
  98. package/dist/lib/test-variants/prime.mjs +0 -59
  99. package/dist/lib/test-variants/prime.perf.cjs +0 -30
  100. package/dist/lib/test-variants/prime.perf.d.ts +0 -1
  101. package/dist/lib/test-variants/prime.perf.mjs +0 -28
  102. package/dist/lib/test-variants/saveErrorVariants.cjs +0 -97
  103. package/dist/lib/test-variants/saveErrorVariants.mjs +0 -69
  104. package/dist/lib/test-variants/testVariantsCreateTestRun.cjs +0 -80
  105. package/dist/lib/test-variants/testVariantsCreateTestRun.d.ts +0 -22
  106. package/dist/lib/test-variants/testVariantsCreateTestRun.mjs +0 -76
  107. package/dist/lib/test-variants/testVariantsIterable.cjs +0 -70
  108. package/dist/lib/test-variants/testVariantsIterable.d.ts +0 -15
  109. package/dist/lib/test-variants/testVariantsIterable.mjs +0 -66
  110. package/dist/lib/test-variants/testVariantsIterator.cjs +0 -429
  111. package/dist/lib/test-variants/testVariantsIterator.d.ts +0 -67
  112. package/dist/lib/test-variants/testVariantsIterator.mjs +0 -425
  113. package/dist/lib/test-variants/testVariantsRun.cjs +0 -289
  114. package/dist/lib/test-variants/testVariantsRun.d.ts +0 -50
  115. package/dist/lib/test-variants/testVariantsRun.mjs +0 -265
  116. package/dist/lib/test-variants/types.cjs +0 -2
  117. package/dist/lib/test-variants/types.d.ts +0 -20
  118. package/dist/lib/test-variants/types.mjs +0 -1
@@ -1,425 +0,0 @@
1
- /** Find last index of value in array; uses custom equals or strict equality */
2
- function findLastIndex(values, value, equals) {
3
- if (equals) {
4
- for (let i = values.length - 1; i >= 0; i--) {
5
- if (equals(values[i], value)) {
6
- return i;
7
- }
8
- }
9
- return -1;
10
- }
11
- for (let i = values.length - 1; i >= 0; i--) {
12
- if (values[i] === value) {
13
- return i;
14
- }
15
- }
16
- return -1;
17
- }
18
- /** Calculate template values for given key index */
19
- function calcTemplateValues(templates, args, keyIndex) {
20
- const template = templates[keyIndex];
21
- if (typeof template === 'function') {
22
- return template(args);
23
- }
24
- return template;
25
- }
26
- /** Reset iterator state for new cycle */
27
- function resetIteratorState(state, templates, keysCount) {
28
- state.index = -1;
29
- state.repeatIndex = 0;
30
- for (let i = 0; i < keysCount; i++) {
31
- state.indexes[i] = -1;
32
- state.argValues[i] = [];
33
- }
34
- if (keysCount > 0) {
35
- state.argValues[0] = calcTemplateValues(templates, state.args, 0);
36
- }
37
- }
38
- /** Get effective max index for an arg (considering argLimit) */
39
- function getMaxIndex(state, keyIndex) {
40
- const valuesLen = state.argValues[keyIndex].length;
41
- const argLimit = state.argLimits[keyIndex];
42
- if (argLimit == null) {
43
- return valuesLen;
44
- }
45
- return argLimit < valuesLen ? argLimit : valuesLen;
46
- }
47
- /** Advance to next variant in cartesian product; returns true if successful */
48
- function advanceVariant(state, templates, keys, keysCount) {
49
- var _a;
50
- for (let keyIndex = keysCount - 1; keyIndex >= 0; keyIndex--) {
51
- const valueIndex = state.indexes[keyIndex] + 1;
52
- const maxIndex = getMaxIndex(state, keyIndex);
53
- if (valueIndex < maxIndex) {
54
- const key = keys[keyIndex];
55
- const value = state.argValues[keyIndex][valueIndex];
56
- state.indexes[keyIndex] = valueIndex;
57
- state.args[key] = value;
58
- for (keyIndex++; keyIndex < keysCount; keyIndex++) {
59
- const keyVariants = calcTemplateValues(templates, state.args, keyIndex);
60
- const keyMaxIndex = (_a = state.argLimits[keyIndex]) !== null && _a !== void 0 ? _a : keyVariants.length;
61
- if (keyVariants.length === 0 || keyMaxIndex <= 0) {
62
- break;
63
- }
64
- state.indexes[keyIndex] = 0;
65
- state.argValues[keyIndex] = keyVariants;
66
- const key = keys[keyIndex];
67
- const value = keyVariants[0];
68
- state.args[key] = value;
69
- }
70
- if (keyIndex >= keysCount) {
71
- return true;
72
- }
73
- }
74
- }
75
- return false;
76
- }
77
- /** Validate saved args keys match iterator's arg names (ignoring "seed" key) */
78
- function validateArgsKeys(savedArgs, keysSet, keysCount) {
79
- const savedKeys = Object.keys(savedArgs).filter(k => k !== 'seed');
80
- if (savedKeys.length !== keysCount) {
81
- return false;
82
- }
83
- for (const key of savedKeys) {
84
- if (!keysSet.has(key)) {
85
- return false;
86
- }
87
- }
88
- return true;
89
- }
90
- /** For static templates, verify arg value exists in template values */
91
- function validateStaticArgsValues(savedArgs, templates, keys, keysCount, equals) {
92
- for (let i = 0; i < keysCount; i++) {
93
- const template = templates[i];
94
- if (typeof template !== 'function') {
95
- const value = savedArgs[keys[i]];
96
- if (findLastIndex(template, value, equals) < 0) {
97
- return false;
98
- }
99
- }
100
- }
101
- return true;
102
- }
103
- /** Check if current position >= pending args position; returns false if current < pending or all args skipped */
104
- function isPositionReached(state, pendingArgs, keys, keysCount, equals) {
105
- let anyCompared = false;
106
- for (let i = 0; i < keysCount; i++) {
107
- const currentValueIndex = state.indexes[i];
108
- const pendingValue = pendingArgs[keys[i]];
109
- const pendingValueIndex = findLastIndex(state.argValues[i], pendingValue, equals);
110
- // Dynamic template value not found - skip this arg from comparison
111
- if (pendingValueIndex < 0) {
112
- continue;
113
- }
114
- anyCompared = true;
115
- if (currentValueIndex < pendingValueIndex) {
116
- return false;
117
- }
118
- if (currentValueIndex > pendingValueIndex) {
119
- return true;
120
- }
121
- }
122
- // All compared args are equal - position reached; or all args skipped - keep pending
123
- return anyCompared;
124
- }
125
- /** Calculate indexes for given args; returns null if any value not found */
126
- function calcArgsIndexes(limitArgs, templates, keys, keysCount, equals) {
127
- const indexes = [];
128
- for (let i = 0; i < keysCount; i++) {
129
- const key = keys[i];
130
- const value = limitArgs[key];
131
- // Use limitArgs for dynamic template calculation
132
- const values = calcTemplateValues(templates, limitArgs, i);
133
- const valueIndex = findLastIndex(values, value, equals);
134
- if (valueIndex < 0) {
135
- return null;
136
- }
137
- indexes.push(valueIndex);
138
- }
139
- return indexes;
140
- }
141
- /** Compare two index arrays lexicographically; returns -1 if a < b, 0 if equal, 1 if a > b */
142
- function compareLexicographic(a, b) {
143
- var _a, _b;
144
- const len = Math.max(a.length, b.length);
145
- for (let i = 0; i < len; i++) {
146
- const ai = (_a = a[i]) !== null && _a !== void 0 ? _a : 0;
147
- const bi = (_b = b[i]) !== null && _b !== void 0 ? _b : 0;
148
- if (ai < bi) {
149
- return -1;
150
- }
151
- if (ai > bi) {
152
- return 1;
153
- }
154
- }
155
- return 0;
156
- }
157
- /** Update per-arg limits from args values using lexicographic comparison; returns true if updated */
158
- function updateArgLimits(state, limitArgs, oldLimitArgs, templates, keys, keysCount, equals, limitArgOnError) {
159
- if (!limitArgOnError) {
160
- return false;
161
- }
162
- // Calculate indexes for new limit args
163
- const newIndexes = calcArgsIndexes(limitArgs, templates, keys, keysCount, equals);
164
- if (!newIndexes) {
165
- return false; // Value not found, can't apply limit
166
- }
167
- // If we have existing limit, compare lexicographically
168
- if (oldLimitArgs) {
169
- const currentIndexes = calcArgsIndexes(oldLimitArgs, templates, keys, keysCount, equals);
170
- if (currentIndexes) {
171
- const cmp = compareLexicographic(newIndexes, currentIndexes);
172
- if (cmp >= 0) {
173
- // New is larger or equal - reject entirely
174
- return false;
175
- }
176
- }
177
- }
178
- // New is smaller (or first limit) - replace all argLimits
179
- for (let i = 0; i < keysCount; i++) {
180
- const valueIndex = newIndexes[i];
181
- // Check callback if provided
182
- if (typeof limitArgOnError === 'function') {
183
- const key = keys[i];
184
- const values = calcTemplateValues(templates, limitArgs, i);
185
- const shouldLimit = limitArgOnError({
186
- name: key,
187
- valueIndex,
188
- values,
189
- maxValueIndex: state.argLimits[i],
190
- });
191
- if (!shouldLimit) {
192
- state.argLimits[i] = null;
193
- continue;
194
- }
195
- }
196
- // Set argLimit: index 0 can't be limited further, store null
197
- state.argLimits[i] = valueIndex > 0 ? valueIndex : null;
198
- }
199
- // Filter out pending limits that are now excluded by argLimits
200
- state.pendingLimits = state.pendingLimits.filter(pending => {
201
- for (let i = 0; i < keysCount; i++) {
202
- const value = pending.args[keys[i]];
203
- const values = calcTemplateValues(templates, pending.args, i);
204
- const valueIndex = findLastIndex(values, value, equals);
205
- const argLimit = state.argLimits[i];
206
- if (argLimit != null && valueIndex >= argLimit) {
207
- return false; // Pending position is excluded by argLimits
208
- }
209
- }
210
- return true; // Keep
211
- });
212
- return true;
213
- }
214
- /** Process pending limits; returns true if any limit was applied */
215
- function processPendingLimits(state, templates, keys, keysCount, equals, limitArgOnError) {
216
- var _a, _b;
217
- let applied = false;
218
- for (let i = state.pendingLimits.length - 1; i >= 0; i--) {
219
- const pending = state.pendingLimits[i];
220
- if (isPositionReached(state, pending.args, keys, keysCount, equals)) {
221
- // Current position >= pending position: apply limit
222
- if (state.count == null || state.index < state.count) {
223
- const oldLimitArgs = (_b = (_a = state.limit) === null || _a === void 0 ? void 0 : _a.args) !== null && _b !== void 0 ? _b : null;
224
- state.count = state.index;
225
- state.limit = typeof pending.error !== 'undefined'
226
- ? { args: pending.args, error: pending.error }
227
- : { args: pending.args };
228
- updateArgLimits(state, pending.args, oldLimitArgs, templates, keys, keysCount, equals, limitArgOnError);
229
- applied = true;
230
- }
231
- // Remove from pending
232
- state.pendingLimits.splice(i, 1);
233
- }
234
- }
235
- return applied;
236
- }
237
- /** Creates test variants iterator with limiting capabilities */
238
- function testVariantsIterator(options) {
239
- const { argsTemplates, getSeed, repeatsPerVariant: _repeatsPerVariant, equals, limitArgOnError } = options;
240
- const repeatsPerVariant = _repeatsPerVariant !== null && _repeatsPerVariant !== void 0 ? _repeatsPerVariant : 1;
241
- const keys = Object.keys(argsTemplates);
242
- const templates = Object.values(argsTemplates);
243
- const keysCount = keys.length;
244
- const keysSet = new Set(keys);
245
- // Initialize state
246
- const indexes = [];
247
- const argValues = [];
248
- const argLimits = [];
249
- for (let i = 0; i < keysCount; i++) {
250
- indexes[i] = -1;
251
- argValues[i] = [];
252
- argLimits[i] = null;
253
- }
254
- const state = {
255
- args: {},
256
- indexes,
257
- argValues,
258
- argLimits,
259
- index: -1,
260
- cycleIndex: -1,
261
- repeatIndex: 0,
262
- count: null,
263
- limit: null,
264
- started: false,
265
- currentArgs: null,
266
- pendingLimits: [],
267
- };
268
- const iterator = {
269
- get index() {
270
- return state.index;
271
- },
272
- get cycleIndex() {
273
- return state.cycleIndex;
274
- },
275
- get count() {
276
- return state.count;
277
- },
278
- get limit() {
279
- return state.limit;
280
- },
281
- addLimit(_options) {
282
- var _a, _b, _c, _d, _e, _f;
283
- const hasArgs = typeof (_options === null || _options === void 0 ? void 0 : _options.args) !== 'undefined' && _options.args !== null;
284
- const hasIndex = (_options === null || _options === void 0 ? void 0 : _options.index) != null;
285
- // addLimit() or addLimit({error}) - uses current args and index
286
- if (!hasArgs && !hasIndex) {
287
- if (state.index < 0) {
288
- throw new Error('[testVariantsIterator] addLimit() requires at least one next() call');
289
- }
290
- if (state.count == null || state.index < state.count) {
291
- const oldLimitArgs = (_b = (_a = state.limit) === null || _a === void 0 ? void 0 : _a.args) !== null && _b !== void 0 ? _b : null;
292
- state.count = state.index;
293
- state.limit = typeof (_options === null || _options === void 0 ? void 0 : _options.error) !== 'undefined'
294
- ? { args: state.currentArgs, error: _options.error }
295
- : { args: state.currentArgs };
296
- updateArgLimits(state, state.args, oldLimitArgs, templates, keys, keysCount, equals, limitArgOnError);
297
- }
298
- return;
299
- }
300
- // addLimit({index}) - only index limiting, no args
301
- if (hasIndex && !hasArgs) {
302
- if (state.count == null || _options.index < state.count) {
303
- state.count = _options.index;
304
- }
305
- return;
306
- }
307
- // addLimit({args}) or addLimit({args, error}) - pending limit + immediate per-arg limits
308
- if (hasArgs && !hasIndex) {
309
- // Validate args keys match iterator's arg names
310
- if (!validateArgsKeys(_options.args, keysSet, keysCount)) {
311
- return; // Discard - unreproducible (templates changed)
312
- }
313
- // For static templates, verify arg value exists
314
- if (!validateStaticArgsValues(_options.args, templates, keys, keysCount, equals)) {
315
- return; // Discard - unreproducible (value not in template)
316
- }
317
- // Apply per-arg limits immediately (if limitArgOnError enabled)
318
- const oldLimitArgs = (_d = (_c = state.limit) === null || _c === void 0 ? void 0 : _c.args) !== null && _d !== void 0 ? _d : null;
319
- const updated = updateArgLimits(state, _options.args, oldLimitArgs, templates, keys, keysCount, equals, limitArgOnError);
320
- if (updated) {
321
- // argLimits updated - this is the new best, update state.limit for future comparisons
322
- state.limit = typeof _options.error !== 'undefined'
323
- ? { args: _options.args, error: _options.error }
324
- : { args: _options.args };
325
- // Pending limit at this position is now filtered by argLimits, don't add
326
- }
327
- else if (!limitArgOnError) {
328
- // No argLimits filtering - add pending limit for position-based stopping
329
- const pending = typeof _options.error !== 'undefined'
330
- ? { args: _options.args, error: _options.error }
331
- : { args: _options.args };
332
- state.pendingLimits.push(pending);
333
- }
334
- // If limitArgOnError and not updated (lexicographically larger), discard entirely
335
- return;
336
- }
337
- // addLimit({args, index}) or addLimit({args, index, error}) - immediate index + pending args
338
- if (hasArgs && hasIndex) {
339
- // Check if this is earliest (before potentially updating count)
340
- const isEarliest = state.count == null || _options.index < state.count;
341
- // Always apply index limit
342
- if (isEarliest) {
343
- state.count = _options.index;
344
- }
345
- // Validate args for limit property update
346
- if (!validateArgsKeys(_options.args, keysSet, keysCount)) {
347
- return; // Skip per-arg limits and limit property update
348
- }
349
- if (!validateStaticArgsValues(_options.args, templates, keys, keysCount, equals)) {
350
- return; // Skip per-arg limits and limit property update
351
- }
352
- // Update limit if this is earliest
353
- if (isEarliest) {
354
- const oldLimitArgs = (_f = (_e = state.limit) === null || _e === void 0 ? void 0 : _e.args) !== null && _f !== void 0 ? _f : null;
355
- state.limit = typeof _options.error !== 'undefined'
356
- ? { args: _options.args, error: _options.error }
357
- : { args: _options.args };
358
- updateArgLimits(state, _options.args, oldLimitArgs, templates, keys, keysCount, equals, limitArgOnError);
359
- }
360
- }
361
- },
362
- start() {
363
- state.cycleIndex++;
364
- resetIteratorState(state, templates, keysCount);
365
- state.started = true;
366
- },
367
- next() {
368
- if (!state.started) {
369
- throw new Error('[testVariantsIterator] start() must be called before next()');
370
- }
371
- // Try next repeat for current variant
372
- if (state.index >= 0 && state.repeatIndex + 1 < repeatsPerVariant) {
373
- // Check if current variant is still within limit
374
- if (state.count == null || state.index < state.count) {
375
- state.repeatIndex++;
376
- if (getSeed) {
377
- const seed = getSeed({
378
- variantIndex: state.index,
379
- cycleIndex: state.cycleIndex,
380
- repeatIndex: state.repeatIndex,
381
- });
382
- state.currentArgs = Object.assign(Object.assign({}, state.args), { seed });
383
- }
384
- else {
385
- state.currentArgs = Object.assign({}, state.args);
386
- }
387
- return state.currentArgs;
388
- }
389
- }
390
- // Move to next variant
391
- state.repeatIndex = 0;
392
- if (!advanceVariant(state, templates, keys, keysCount)) {
393
- // First complete cycle sets count to total variant count
394
- if (state.count == null) {
395
- state.count = state.index + 1;
396
- }
397
- return null;
398
- }
399
- state.index++;
400
- // Process pending limits at new position
401
- if (state.pendingLimits.length > 0) {
402
- processPendingLimits(state, templates, keys, keysCount, equals, limitArgOnError);
403
- }
404
- // Check count limit (may have been updated by pending limit)
405
- if (state.count != null && state.index >= state.count) {
406
- return null;
407
- }
408
- if (getSeed) {
409
- const seed = getSeed({
410
- variantIndex: state.index,
411
- cycleIndex: state.cycleIndex,
412
- repeatIndex: state.repeatIndex,
413
- });
414
- state.currentArgs = Object.assign(Object.assign({}, state.args), { seed });
415
- }
416
- else {
417
- state.currentArgs = Object.assign({}, state.args);
418
- }
419
- return state.currentArgs;
420
- },
421
- };
422
- return iterator;
423
- }
424
-
425
- export { testVariantsIterator };