@nestia/e2e 14.0.1 → 14.0.3

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.
@@ -6,8 +6,8 @@ exports.RandomGenerator = void 0;
6
6
  *
7
7
  * RandomGenerator provides a collection of functions for generating random data
8
8
  * including strings, names, content, dates, and array sampling. All functions
9
- * are designed to be deterministic within a single execution but produce varied
10
- * output across different runs, making them ideal for testing scenarios.
9
+ * draw from `Math.random()`, so they are not seeded and produce varied output
10
+ * across executions, which suits testing scenarios that need arbitrary data.
11
11
  *
12
12
  * The namespace includes specialized generators for:
13
13
  *
@@ -16,21 +16,33 @@ exports.RandomGenerator = void 0;
16
16
  * - Date ranges and time-based data
17
17
  * - Array sampling and element selection
18
18
  *
19
+ * Processing cost: Text construction scales with generated characters, sparse
20
+ * sampling with selected positions, and fixed-size draws use constant work. The
21
+ * namespace retains only fixed character tables; each generator owns its
22
+ * invocation-local result.
23
+ *
19
24
  * @author Jeongho Nam - https://github.com/samchon
20
25
  * @example
21
- * ```typescript
22
26
  * // Generate test user data
23
27
  * const testUser = {
24
28
  * id: RandomGenerator.alphaNumeric(8),
25
29
  * name: RandomGenerator.name(),
26
- * bio: RandomGenerator.paragraph({ sentences: 3, wordMin: 5, wordMax: 10 }),
30
+ * bio: RandomGenerator.paragraph({
31
+ * sentences: 3,
32
+ * wordMin: 5,
33
+ * wordMax: 10,
34
+ * }),
27
35
  * phone: RandomGenerator.mobile(),
28
- * createdAt: RandomGenerator.date(new Date(), 1000 * 60 * 60 * 24 * 30) // 30 days
36
+ * createdAt: RandomGenerator.date(new Date(), 1000 * 60 * 60 * 24 * 30), // 30 days
29
37
  * };
30
38
  *
31
39
  * // Sample data for testing
32
40
  * const testSample = RandomGenerator.sample(allUsers, 5);
33
- * ```;
41
+ *
42
+ * @evidence contracts/common.md#principled-implementation The private integer helper partitions Math.random output into equally sized bins for finite ordered integer bounds, and generators compose text, dates and selections from those draws. Math.random is approximately uniform and not cryptographically secure; exact probability guarantees do not follow from its finite precision.
43
+ * @evidence contracts/common.md#clear-and-simple-design Small generators build on each other (`name` on `paragraph`, `content` on `paragraph`, both on `alphabets`), so one integer helper decides the randomness.
44
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The data are drawn, not taken from a fixed list of test values.
45
+ * @evidence contracts/common.md#meaningful-documentation The namespace prose says the functions are not seeded and lists the kinds of data, with an example.
34
46
  */
35
47
  var RandomGenerator;
36
48
  (function (RandomGenerator) {
@@ -50,10 +62,12 @@ var RandomGenerator;
50
62
  * appear multiple times. Useful for generating random identifiers, test
51
63
  * names, or placeholder text.
52
64
  *
65
+ * Processing cost: Constructing L characters costs O(L) time and
66
+ * intermediate/result space.
67
+ *
53
68
  * @example
54
- * ```typescript
55
- * RandomGenerator.alphabets(5); // e.g. "kxqpw"
56
- * RandomGenerator.alphabets(3); // e.g. "mzr"
69
+ * RandomGenerator.alphabets(5); // e.g. "kxqpw"
70
+ * RandomGenerator.alphabets(3); // e.g. "mzr"
57
71
  * RandomGenerator.alphabets(10); // e.g. "qwertasdfg"
58
72
  *
59
73
  * // Generate random CSS class names
@@ -61,10 +75,13 @@ var RandomGenerator;
61
75
  *
62
76
  * // Create random variable names for testing
63
77
  * const varName = RandomGenerator.alphabets(8);
64
- * ```
65
78
  *
66
79
  * @param length - The desired length of the generated alphabetic string
67
80
  * @returns A string containing only lowercase letters of the specified length
81
+ * @evidence contracts/common.md#principled-implementation Each requested character maps a Math.random draw to one of 26 lowercase letters. Repeats are possible, and distribution inherits Math.random rather than guaranteeing exact uniformity.
82
+ * @evidence contracts/common.md#clear-and-simple-design One expression over the shared integer helper.
83
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The characters are drawn, not enumerated from a list of known values.
84
+ * @evidence contracts/common.md#meaningful-documentation The comment states the character set, the independence of the draws, and examples.
68
85
  */
69
86
  RandomGenerator.alphabets = (length) => new Array(length)
70
87
  .fill("")
@@ -79,9 +96,11 @@ var RandomGenerator;
79
96
  * character set. Ideal for generating random IDs, tokens, passwords, or
80
97
  * unique identifiers that need both numeric and alphabetic characters.
81
98
  *
99
+ * Processing cost: Constructing L characters costs O(L) time and
100
+ * intermediate/result space.
101
+ *
82
102
  * @example
83
- * ```typescript
84
- * RandomGenerator.alphaNumeric(8); // e.g. "a1b2c3d4"
103
+ * RandomGenerator.alphaNumeric(8); // e.g. "a1b2c3d4"
85
104
  * RandomGenerator.alphaNumeric(12); // e.g. "x9y8z7w6v5u4"
86
105
  *
87
106
  * // Generate random API keys
@@ -92,11 +111,14 @@ var RandomGenerator;
92
111
  *
93
112
  * // Generate test database IDs
94
113
  * const testId = RandomGenerator.alphaNumeric(10);
95
- * ```
96
114
  *
97
115
  * @param length - The desired length of the generated alphanumeric string
98
116
  * @returns A string containing digits and lowercase letters of the specified
99
117
  * length
118
+ * @evidence contracts/common.md#principled-implementation Each character maps a Math.random draw to one of ten digits and 26 lowercase letters. Repeated characters are allowed and exact uniformity is not guaranteed.
119
+ * @evidence contracts/common.md#clear-and-simple-design One expression over the shared integer helper.
120
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The characters are drawn, not enumerated from a list of known values.
121
+ * @evidence contracts/common.md#meaningful-documentation The comment states the character set and gives examples.
100
122
  */
101
123
  RandomGenerator.alphaNumeric = (length) => new Array(length)
102
124
  .fill("")
@@ -110,26 +132,31 @@ var RandomGenerator;
110
132
  * Each word is between 3-7 characters by default, creating realistic-looking
111
133
  * names.
112
134
  *
135
+ * Processing cost: The delegated paragraph work scales with the requested
136
+ * word count and total generated characters.
137
+ *
113
138
  * @example
114
- * ```typescript
115
- * RandomGenerator.name(); // e.g. "lorem ipsum" (2-3 words)
116
- * RandomGenerator.name(1); // e.g. "dolor" (single word)
117
- * RandomGenerator.name(3); // e.g. "sit amet consectetur" (3 words)
139
+ * RandomGenerator.name(); // e.g. "lorem ipsum" (2-3 words)
140
+ * RandomGenerator.name(1); // e.g. "dolor" (single word)
141
+ * RandomGenerator.name(3); // e.g. "sit amet consectetur" (3 words)
118
142
  *
119
143
  * // Generate test user names
120
144
  * const users = Array.from({ length: 10 }, () => ({
121
- * id: RandomGenerator.alphaNumeric(8),
122
- * name: RandomGenerator.name(),
123
- * email: `${RandomGenerator.name(1)}@test.com`
145
+ * id: RandomGenerator.alphaNumeric(8),
146
+ * name: RandomGenerator.name(),
147
+ * email: `${RandomGenerator.name(1)}@test.com`,
124
148
  * }));
125
149
  *
126
150
  * // Create random author names for blog posts
127
151
  * const authorName = RandomGenerator.name();
128
- * ```
129
152
  *
130
153
  * @param length - Number of words in the name (default: random between 2-3)
131
154
  * @returns A space-separated string of random words (each 3-7 chars by
132
155
  * default)
156
+ * @evidence contracts/common.md#principled-implementation A name is a short paragraph of two or three lowercase words by default, so it reads as a person or entity name without an external name list.
157
+ * @evidence contracts/common.md#clear-and-simple-design A one-line delegation to `paragraph` with the sentence count as the word count.
158
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The words are drawn letters, not a fixed list of names.
159
+ * @evidence contracts/common.md#meaningful-documentation The comment states the default length and gives examples.
133
160
  */
134
161
  RandomGenerator.name = (length = randint(2, 3)) => RandomGenerator.paragraph({
135
162
  sentences: length,
@@ -142,13 +169,16 @@ var RandomGenerator;
142
169
  * joined with spaces. Accepts an optional configuration object for fine-tuned
143
170
  * control over the paragraph structure.
144
171
  *
172
+ * Processing cost: Each requested word is generated once; time and temporary
173
+ * space scale with the total generated character count and the number of
174
+ * words.
175
+ *
145
176
  * @example
146
- * ```typescript
147
177
  * // Generate with defaults (random 2-5 words, 3-7 characters each)
148
- * RandomGenerator.paragraph(); // e.g. "lorem ipsum dolor"
178
+ * RandomGenerator.paragraph(); // e.g. "lorem ipsum dolor"
149
179
  *
150
180
  * // Specific number of sentences
151
- * RandomGenerator.paragraph({ sentences: 5 }); // "lorem ipsum dolor sit amet"
181
+ * RandomGenerator.paragraph({ sentences: 5 }); // "lorem ipsum dolor sit amet"
152
182
  *
153
183
  * // Custom word length ranges
154
184
  * RandomGenerator.paragraph({ sentences: 4, wordMin: 2, wordMax: 5 });
@@ -158,20 +188,23 @@ var RandomGenerator;
158
188
  * const description = RandomGenerator.paragraph({
159
189
  * sentences: 8,
160
190
  * wordMin: 4,
161
- * wordMax: 8
191
+ * wordMax: 8,
162
192
  * });
163
193
  *
164
194
  * // Create test content for forms
165
195
  * const placeholder = RandomGenerator.paragraph({
166
196
  * sentences: 3,
167
197
  * wordMin: 5,
168
- * wordMax: 10
198
+ * wordMax: 10,
169
199
  * });
170
- * ```;
171
200
  *
172
201
  * @param props - Optional configuration object with sentences count and word
173
202
  * length ranges
174
203
  * @returns A string containing the generated paragraph
204
+ * @evidence contracts/common.md#principled-implementation A paragraph is a number of words joined by spaces, each word a random lowercase string of a length between the minimum and maximum, with the defaults of two to five words of three to seven letters.
205
+ * @evidence contracts/common.md#clear-and-simple-design One expression over `alphabets`, with three optional numbers.
206
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The words are drawn letters, not a fixed text.
207
+ * @evidence contracts/common.md#meaningful-documentation The comment states the parameters and their defaults, with examples.
175
208
  */
176
209
  RandomGenerator.paragraph = (props) => { var _a; return new Array((_a = props === null || props === void 0 ? void 0 : props.sentences) !== null && _a !== void 0 ? _a : randint(2, 5))
177
210
  .fill("")
@@ -186,8 +219,10 @@ var RandomGenerator;
186
219
  * character lengths. Ideal for generating realistic-looking text content for
187
220
  * testing.
188
221
  *
222
+ * Processing cost: Every paragraph is generated once; time and temporary
223
+ * space scale with the total output characters and paragraph/word counts.
224
+ *
189
225
  * @example
190
- * ```typescript
191
226
  * // Generate with all defaults
192
227
  * const article = RandomGenerator.content();
193
228
  *
@@ -197,7 +232,7 @@ var RandomGenerator;
197
232
  * sentenceMin: 15,
198
233
  * sentenceMax: 25,
199
234
  * wordMin: 4,
200
- * wordMax: 8
235
+ * wordMax: 8,
201
236
  * });
202
237
  *
203
238
  * // Short content with brief sentences
@@ -206,7 +241,7 @@ var RandomGenerator;
206
241
  * sentenceMin: 5,
207
242
  * sentenceMax: 8,
208
243
  * wordMin: 2,
209
- * wordMax: 4
244
+ * wordMax: 4,
210
245
  * });
211
246
  *
212
247
  * // Generate blog post content
@@ -217,9 +252,9 @@ var RandomGenerator;
217
252
  * sentenceMin: 10,
218
253
  * sentenceMax: 20,
219
254
  * wordMin: 3,
220
- * wordMax: 7
255
+ * wordMax: 7,
221
256
  * }),
222
- * summary: RandomGenerator.paragraph({ sentences: 2 })
257
+ * summary: RandomGenerator.paragraph({ sentences: 2 }),
223
258
  * };
224
259
  *
225
260
  * // Create test data for CMS
@@ -228,14 +263,17 @@ var RandomGenerator;
228
263
  * content: RandomGenerator.content({
229
264
  * paragraphs: randint(2, 6),
230
265
  * sentenceMin: 8,
231
- * sentenceMax: 15
232
- * })
266
+ * sentenceMax: 15,
267
+ * }),
233
268
  * }));
234
- * ```;
235
269
  *
236
270
  * @param props - Optional configuration object with paragraph, sentence, and
237
271
  * word parameters
238
272
  * @returns A string containing the generated multi-paragraph content
273
+ * @evidence contracts/common.md#principled-implementation The content has three to eight paragraphs by default, each containing ten to forty space-separated words of one to seven lowercase letters, joined by blank lines. The legacy sentence-named options count words, not grammatical sentences.
274
+ * @evidence contracts/common.md#clear-and-simple-design One expression over `paragraph`, with five optional numbers.
275
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The text is drawn, not a fixed corpus.
276
+ * @evidence contracts/common.md#meaningful-documentation The comment states the parameters and their defaults, with examples.
239
277
  */
240
278
  RandomGenerator.content = (props) => { var _a; return new Array((_a = props === null || props === void 0 ? void 0 : props.paragraphs) !== null && _a !== void 0 ? _a : randint(3, 8))
241
279
  .fill("")
@@ -253,13 +291,15 @@ var RandomGenerator;
253
291
  * Automatically trims whitespace from the beginning and end of the result.
254
292
  * Useful for creating excerpts, search terms, or partial content samples.
255
293
  *
294
+ * Processing cost: Two draws choose the slice bounds; substring and trimming
295
+ * cost at most O(N) in the input length.
296
+ *
256
297
  * @example
257
- * ```typescript
258
298
  * const text = "The quick brown fox jumps over the lazy dog";
259
299
  *
260
- * RandomGenerator.substring(text); // e.g. "quick brown fox"
261
- * RandomGenerator.substring(text); // e.g. "jumps over"
262
- * RandomGenerator.substring(text); // e.g. "fox jumps over the lazy"
300
+ * RandomGenerator.substring(text); // e.g. "quick brown fox"
301
+ * RandomGenerator.substring(text); // e.g. "jumps over"
302
+ * RandomGenerator.substring(text); // e.g. "fox jumps over the lazy"
263
303
  *
264
304
  * // Generate search terms from content
265
305
  * const searchQuery = RandomGenerator.substring(articleContent);
@@ -272,10 +312,13 @@ var RandomGenerator;
272
312
  *
273
313
  * // Create random selections for highlight testing
274
314
  * const selectedText = RandomGenerator.substring(documentContent);
275
- * ```;
276
315
  *
277
316
  * @param content - The source string to extract a substring from
278
317
  * @returns A trimmed substring of the original content
318
+ * @evidence contracts/common.md#principled-implementation For nonempty input, the first index is a valid position and the last is strictly later up to the length. Trimming can empty a whitespace slice. Empty input also returns an empty string; substring clamps its drawn bounds to the empty input.
319
+ * @evidence contracts/common.md#clear-and-simple-design Two draws and one slice.
320
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The slice bounds are drawn, not fixed.
321
+ * @evidence contracts/common.md#meaningful-documentation The comment states that the slice is random and trimmed, with examples.
279
322
  */
280
323
  RandomGenerator.substring = (content) => {
281
324
  const first = randint(0, content.length - 1);
@@ -291,31 +334,39 @@ var RandomGenerator;
291
334
  * if necessary. Commonly used for generating Korean mobile phone numbers or
292
335
  * similar formats.
293
336
  *
337
+ * Processing cost: Two bounded integer draws and fixed-width decimal
338
+ * formatting use constant work; joining the caller prefix costs O(P) output
339
+ * time and space for P prefix characters.
340
+ *
294
341
  * @example
295
- * ```typescript
296
- * RandomGenerator.mobile(); // e.g. "0103341234" or "01012345678"
297
- * RandomGenerator.mobile("011"); // e.g. "0119876543" or "01112345678"
298
- * RandomGenerator.mobile("+82"); // e.g. "+823341234" or "+8212345678"
342
+ * RandomGenerator.mobile(); // e.g. "0103341234" or "01012345678"
343
+ * RandomGenerator.mobile("011"); // e.g. "0119876543" or "01112345678"
344
+ * RandomGenerator.mobile("+82"); // e.g. "+823341234" or "+8212345678"
299
345
  *
300
346
  * // Generate test user phone numbers
301
347
  * const testUsers = Array.from({ length: 100 }, () => ({
302
348
  * name: RandomGenerator.name(),
303
349
  * phone: RandomGenerator.mobile(),
304
- * altPhone: RandomGenerator.mobile("011")
350
+ * altPhone: RandomGenerator.mobile("011"),
305
351
  * }));
306
352
  *
307
353
  * // Create international phone numbers
308
354
  * const internationalPhone = RandomGenerator.mobile("+821");
309
355
  *
310
356
  * // Generate contact list for testing
311
- * const contacts = ["010", "011", "016", "017", "018", "019"].map(prefix => ({
312
- * carrier: prefix,
313
- * number: RandomGenerator.mobile(prefix)
314
- * }));
315
- * ```;
357
+ * const contacts = ["010", "011", "016", "017", "018", "019"].map(
358
+ * (prefix) => ({
359
+ * carrier: prefix,
360
+ * number: RandomGenerator.mobile(prefix),
361
+ * }),
362
+ * );
316
363
  *
317
364
  * @param prefix - The prefix string for the phone number (default: "010")
318
365
  * @returns A formatted mobile phone number string
366
+ * @evidence contracts/common.md#principled-implementation A mobile number is the prefix, a middle group of three digits when the drawn value is below 1,000 and four digits otherwise, and a four-digit group, all zero-padded, which matches the 010-XXX-XXXX and 010-XXXX-XXXX Korean formats the default prefix implies.
367
+ * @evidence contracts/common.md#clear-and-simple-design One expression with two draws.
368
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The prefix is a parameter whose default is the documented Korean one, and the digits are drawn.
369
+ * @evidence contracts/common.md#meaningful-documentation The comment states the format, the default prefix, and examples.
319
370
  */
320
371
  RandomGenerator.mobile = (prefix = "010") => [
321
372
  prefix,
@@ -333,8 +384,10 @@ var RandomGenerator;
333
384
  * date. Useful for generating timestamps, creation dates, or scheduling test
334
385
  * data.
335
386
  *
387
+ * Processing cost: One integer draw and one Date construction use constant
388
+ * work.
389
+ *
336
390
  * @example
337
- * ```typescript
338
391
  * const now = new Date();
339
392
  * const oneDay = 24 * 60 * 60 * 1000;
340
393
  * const oneMonth = 30 * oneDay;
@@ -348,38 +401,50 @@ var RandomGenerator;
348
401
  *
349
402
  * // Generate random creation dates for test data
350
403
  * const startOfYear = new Date(2024, 0, 1);
351
- * const endOfYear = new Date(2024, 11, 31).getTime() - startOfYear.getTime();
352
- * const randomCreationDate = RandomGenerator.date(startOfYear, endOfYear);
404
+ * const endOfYear =
405
+ * new Date(2024, 11, 31).getTime() - startOfYear.getTime();
406
+ * const randomCreationDate = RandomGenerator.date(
407
+ * startOfYear,
408
+ * endOfYear,
409
+ * );
353
410
  *
354
411
  * // Create test events with random timestamps
355
412
  * const events = Array.from({ length: 50 }, () => ({
356
413
  * id: RandomGenerator.alphaNumeric(8),
357
414
  * title: RandomGenerator.name(2),
358
415
  * createdAt: RandomGenerator.date(new Date(), oneMonth),
359
- * scheduledFor: RandomGenerator.date(new Date(), oneMonth * 3)
416
+ * scheduledFor: RandomGenerator.date(new Date(), oneMonth * 3),
360
417
  * }));
361
- * ```;
362
418
  *
363
419
  * @param from - The starting date for the random range
364
420
  * @param range - The range in milliseconds from the starting date
365
421
  * @returns A random date within the specified range
422
+ * @evidence contracts/common.md#principled-implementation For a valid start date and finite nonnegative integer range whose endpoint is Date-representable, the result adds an integer offset from zero through range. Unsupported invalid dates or bounds are not validated and can produce an Invalid Date or an out-of-range result.
423
+ * @evidence contracts/common.md#clear-and-simple-design One expression over the shared integer helper.
424
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The offset is drawn, not fixed.
425
+ * @evidence contracts/common.md#meaningful-documentation The comment states the interval and the unit of the range, with examples.
366
426
  */
367
427
  RandomGenerator.date = (from, range) => new Date(from.getTime() + randint(0, range));
368
428
  /**
369
- * Randomly samples a specified number of unique elements from an array.
429
+ * Randomly samples a specified number of positions from an array.
430
+ *
431
+ * Selects input positions without replacement. Equal values at different
432
+ * positions remain separate candidates and can both appear in the result. The
433
+ * sample size is automatically capped at the array length to prevent errors.
434
+ * Uses a partial Fisher-Yates shuffle over a sparse index map, so every draw
435
+ * is final and the cost grows with the sample size, not with the array
436
+ * length. Ideal for creating test datasets or selecting random subsets for
437
+ * validation.
370
438
  *
371
- * Selects random elements from the input array without replacement, ensuring
372
- * all returned elements are unique. The sample size is automatically capped
373
- * at the array length to prevent errors. Uses a Set-based approach to
374
- * guarantee uniqueness of selected indices. Ideal for creating test datasets
375
- * or selecting random subsets for validation.
439
+ * Processing cost: For K selected positions, sparse partial Fisher-Yates uses
440
+ * K map lookups/updates and K output entries: expected O(K) time and O(K)
441
+ * space, without copying the N-element input.
376
442
  *
377
443
  * @example
378
- * ```typescript
379
444
  * const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
380
445
  *
381
- * RandomGenerator.sample(numbers, 3); // e.g. [2, 7, 9]
382
- * RandomGenerator.sample(numbers, 5); // e.g. [1, 4, 6, 8, 10]
446
+ * RandomGenerator.sample(numbers, 3); // e.g. [2, 7, 9]
447
+ * RandomGenerator.sample(numbers, 5); // e.g. [1, 4, 6, 8, 10]
383
448
  * RandomGenerator.sample(numbers, 15); // returns all 10 elements (capped at array length)
384
449
  *
385
450
  * // Sample users for testing
@@ -394,61 +459,80 @@ var RandomGenerator;
394
459
  *
395
460
  * // Random A/B testing groups
396
461
  * const groupA = RandomGenerator.sample(allParticipants, 50);
397
- * const remaining = allParticipants.filter(p => !groupA.includes(p));
462
+ * const remaining = allParticipants.filter((p) => !groupA.includes(p));
398
463
  * const groupB = RandomGenerator.sample(remaining, 50);
399
- * ```;
400
464
  *
401
465
  * @param array - The source array to sample from
402
466
  * @param count - The number of elements to sample
403
467
  * @returns An array containing the randomly selected elements
468
+ * @evidence contracts/common.md#principled-implementation A partial Fisher-Yates shuffle over a sparse map of moved positions draws each result element from the not-yet-chosen positions uniformly, so the sample is without replacement, approximately uniform under Math.random, and its cost grows with the sample size; the count is capped at the array length, a positive fractional count rounds upward through the loop condition, and a count that is zero, negative, or NaN yields an empty array.
469
+ * @evidence contracts/common.md#clear-and-simple-design One loop with one map, and no rejection of repeated draws.
470
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The array is not mutated or copied, and no element is favored or excluded.
471
+ * @evidence contracts/common.md#meaningful-documentation The comment states without-replacement sampling, the cap, and the algorithm, with examples.
404
472
  */
405
473
  RandomGenerator.sample = (array, count) => {
474
+ var _a, _b;
406
475
  count = Math.min(count, array.length);
407
- const indexes = new Set();
408
- while (indexes.size < count)
409
- indexes.add(randint(0, array.length - 1));
410
- return Array.from(indexes).map((i) => array[i]);
476
+ // `moved` holds the positions whose element differs from the identity, so
477
+ // the shuffle needs no copy of the array
478
+ const moved = new Map();
479
+ const output = [];
480
+ for (let i = 0; i < count; ++i) {
481
+ const j = randint(i, array.length - 1);
482
+ output.push(array[(_a = moved.get(j)) !== null && _a !== void 0 ? _a : j]);
483
+ moved.set(j, (_b = moved.get(i)) !== null && _b !== void 0 ? _b : i);
484
+ }
485
+ return output;
411
486
  };
412
487
  /**
413
488
  * Randomly selects a single element from an array.
414
489
  *
415
- * Chooses one element at random from the provided array using uniform
416
- * distribution. Each element has an equal probability of being selected. This
417
- * is a convenience function equivalent to sampling with a count of 1, but
418
- * returns the element directly rather than an array containing one element.
490
+ * Chooses one element at random from the provided array using approximately
491
+ * uniform distribution inherited from Math.random. This is a convenience
492
+ * function equivalent to sampling with a count of 1, but returns the element
493
+ * directly rather than an array containing one element.
494
+ *
495
+ * Processing cost: One bounded draw and one indexed lookup use constant work.
419
496
  *
420
497
  * @example
421
- * ```typescript
422
- * const colors = ['red', 'blue', 'green', 'yellow', 'purple'];
423
- * const fruits = ['apple', 'banana', 'orange', 'grape', 'kiwi'];
498
+ * const colors = ["red", "blue", "green", "yellow", "purple"];
499
+ * const fruits = ["apple", "banana", "orange", "grape", "kiwi"];
424
500
  *
425
- * RandomGenerator.pick(colors); // e.g. "blue"
426
- * RandomGenerator.pick(fruits); // e.g. "apple"
501
+ * RandomGenerator.pick(colors); // e.g. "blue"
502
+ * RandomGenerator.pick(fruits); // e.g. "apple"
427
503
  *
428
504
  * // Select random configuration options
429
- * const randomTheme = RandomGenerator.pick(['light', 'dark', 'auto']);
430
- * const randomLocale = RandomGenerator.pick(['en', 'ko', 'ja', 'zh']);
505
+ * const randomTheme = RandomGenerator.pick(["light", "dark", "auto"]);
506
+ * const randomLocale = RandomGenerator.pick(["en", "ko", "ja", "zh"]);
431
507
  *
432
508
  * // Choose random test scenarios
433
509
  * const testScenario = RandomGenerator.pick([
434
- * 'happy_path',
435
- * 'edge_case',
436
- * 'error_condition',
437
- * 'boundary_test'
510
+ * "happy_path",
511
+ * "edge_case",
512
+ * "error_condition",
513
+ * "boundary_test",
438
514
  * ]);
439
515
  *
440
516
  * // Random user role assignment
441
- * const userRole = RandomGenerator.pick(['admin', 'user', 'moderator']);
517
+ * const userRole = RandomGenerator.pick(["admin", "user", "moderator"]);
442
518
  *
443
519
  * // Select random API endpoints for testing
444
- * const endpoints = ['/users', '/posts', '/comments', '/categories'];
520
+ * const endpoints = ["/users", "/posts", "/comments", "/categories"];
445
521
  * const randomEndpoint = RandomGenerator.pick(endpoints);
446
- * ```;
447
522
  *
448
523
  * @param array - The source array to pick an element from
449
524
  * @returns A randomly selected element from the array
525
+ * @throws RangeError when the array is empty
526
+ * @evidence contracts/common.md#principled-implementation One index maps a Math.random draw to a valid position, giving approximately uniform selection; an empty array has no element to return, so it raises a `RangeError` instead of returning `undefined` under the element type.
527
+ * @evidence contracts/common.md#clear-and-simple-design One guard and one draw.
528
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The guard states the contract for the empty array and no default element is invented.
529
+ * @evidence contracts/common.md#meaningful-documentation The comment states the approximately uniform selection, the relation to sampling one element, and the `RangeError` for an empty array, with examples.
450
530
  */
451
- RandomGenerator.pick = (array) => array[randint(0, array.length - 1)];
531
+ RandomGenerator.pick = (array) => {
532
+ if (array.length === 0)
533
+ throw new RangeError("RandomGenerator.pick(): the array is empty.");
534
+ return array[randint(0, array.length - 1)];
535
+ };
452
536
  })(RandomGenerator || (exports.RandomGenerator = RandomGenerator = {}));
453
537
  /** @internal */
454
538
  const randint = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
@@ -1 +1 @@
1
- {"version":3,"file":"RandomGenerator.js","sourceRoot":"","sources":["../src/RandomGenerator.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,IAAiB,eAAe,CAsc/B;AAtcD,WAAiB,eAAe;IAC9B,qEAAqE;IACrE,MAAM,UAAU,GAAG,4BAA4B,CAAC;IAEhD;;;OAGG;IACH,MAAM,OAAO,GAAW,YAAY,GAAG,UAAU,CAAC;IAElD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,yBAAS,GAAG,CAAC,MAAc,EAAU,EAAE,CAClD,IAAI,KAAK,CAAC,MAAM,CAAC;SACd,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;SACxD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACU,4BAAY,GAAG,CAAC,MAAc,EAAU,EAAE,CACrD,IAAI,KAAK,CAAC,MAAM,CAAC;SACd,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACU,oBAAI,GAAG,CAAC,MAAM,GAAW,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAU,EAAE,CAC7D,yBAAS,CAAC;QACR,SAAS,EAAE,MAAM;KAClB,CAAC,CAAC;IAEL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;IACU,yBAAS,GAAG,CACvB,KAIE,EACF,EAAE,kBACF,IAAI,KAAK,OAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,SAAS,mCAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACzC,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,GAAG,EAAE,sBAAC,yBAAS,CAAC,OAAO,OAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,CAAC,QAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,CAAC,CAAC,CAAC,GAAA,CAAC;SACvE,IAAI,CAAC,GAAG,CAAC,GAAA,CAAC;IAEf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2DG;IACU,uBAAO,GAAG,CACrB,KAME,EACF,EAAE,kBACF,IAAI,KAAK,OAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,UAAU,mCAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SAC1C,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,GAAG,EAAE,8BACR,yBAAS,CAAC;QACR,SAAS,EAAE,OAAO,OAChB,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,WAAW,mCAAI,EAAE,QACxB,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,WAAW,mCAAI,EAAE,CACzB;QACD,OAAO,QAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,CAAC;QAC5B,OAAO,QAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,CAAC;KAC7B,CAAC,GAAA,CACH;SACA,IAAI,CAAC,MAAM,CAAC,GAAA,CAAC;IAElB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACU,yBAAS,GAAG,CAAC,OAAe,EAAU,EAAE;QACnD,MAAM,KAAK,GAAW,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,GAAW,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,OAAO,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,CAAC,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACU,sBAAM,GAAG,CAAC,MAAM,GAAW,KAAK,EAAU,EAAE,CACvD;QACE,MAAM;QACN,CAAC,GAAG,EAAE;YACJ,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YAC/B,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,KAAK,GAAG,IAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC/D,CAAC,CAAC,EAAE;QACJ,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;KAC7C,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;IACU,oBAAI,GAAG,CAAC,IAAU,EAAE,KAAa,EAAQ,EAAE,CACtD,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;IACU,sBAAM,GAAG,CAAI,KAAU,EAAE,KAAa,EAAO,EAAE;QAC1D,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,OAAO,GAAgB,IAAI,GAAG,EAAE,CAAC;QACvC,OAAO,OAAO,CAAC,IAAI,GAAG,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACvE,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;IACnD,CAAC,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;IACU,oBAAI,GAAG,CAAI,KAAmB,EAAK,EAAE,CAChD,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAE,CAAC;AACzC,CAAC,EAtcgB,eAAe,aAAf,eAAe,GAAf,eAAe,QAsc/B;AAED,gBAAgB;AAChB,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,GAAW,EAAU,EAAE,CACnD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC"}
1
+ {"version":3,"file":"RandomGenerator.js","sourceRoot":"","sources":["../src/RandomGenerator.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,IAAiB,eAAe,CA6gB/B;AA7gBD,WAAiB,eAAe;IAC9B,qEAAqE;IACrE,MAAM,UAAU,GAAG,4BAA4B,CAAC;IAEhD;;;OAGG;IACH,MAAM,OAAO,GAAW,YAAY,GAAG,UAAU,CAAC;IAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACU,yBAAS,GAAG,CAAC,MAAc,EAAU,EAAE,CAClD,IAAI,KAAK,CAAC,MAAM,CAAC;SACd,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;SACxD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACU,4BAAY,GAAG,CAAC,MAAc,EAAU,EAAE,CACrD,IAAI,KAAK,CAAC,MAAM,CAAC;SACd,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACU,oBAAI,GAAG,CAAC,MAAM,GAAW,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAU,EAAE,CAC7D,yBAAS,CAAC;QACR,SAAS,EAAE,MAAM;KAClB,CAAC,CAAC;IAEL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4CG;IACU,yBAAS,GAAG,CACvB,KAIE,EACF,EAAE,kBACF,IAAI,KAAK,OAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,SAAS,mCAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACzC,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,GAAG,EAAE,sBAAC,yBAAS,CAAC,OAAO,OAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,CAAC,QAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,CAAC,CAAC,CAAC,GAAA,CAAC;SACvE,IAAI,CAAC,GAAG,CAAC,GAAA,CAAC;IAEf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgEG;IACU,uBAAO,GAAG,CACrB,KAME,EACF,EAAE,kBACF,IAAI,KAAK,OAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,UAAU,mCAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SAC1C,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,GAAG,EAAE,8BACR,yBAAS,CAAC;QACR,SAAS,EAAE,OAAO,OAChB,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,WAAW,mCAAI,EAAE,QACxB,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,WAAW,mCAAI,EAAE,CACzB;QACD,OAAO,QAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,CAAC;QAC5B,OAAO,QAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,CAAC;KAC7B,CAAC,GAAA,CACH;SACA,IAAI,CAAC,MAAM,CAAC,GAAA,CAAC;IAElB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;IACU,yBAAS,GAAG,CAAC,OAAe,EAAU,EAAE;QACnD,MAAM,KAAK,GAAW,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,GAAW,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,OAAO,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,CAAC,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0CG;IACU,sBAAM,GAAG,CAAC,MAAM,GAAW,KAAK,EAAU,EAAE,CACvD;QACE,MAAM;QACN,CAAC,GAAG,EAAE;YACJ,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YAC/B,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,KAAK,GAAG,IAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC/D,CAAC,CAAC,EAAE;QACJ,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;KAC7C,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+CG;IACU,oBAAI,GAAG,CAAC,IAAU,EAAE,KAAa,EAAQ,EAAE,CACtD,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4CG;IACU,sBAAM,GAAG,CAAI,KAAU,EAAE,KAAa,EAAO,EAAE;;QAC1D,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACtC,0EAA0E;QAC1E,yCAAyC;QACzC,MAAM,KAAK,GAAwB,IAAI,GAAG,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAQ,EAAE,CAAC;QACvB,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;YACvC,MAAM,CAAC,GAAW,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,KAAK,OAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,mCAAI,CAAC,CAAE,CAAC,CAAC;YACvC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,mCAAI,CAAC,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;IACU,oBAAI,GAAG,CAAI,KAAmB,EAAK,EAAE;QAChD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YACpB,MAAM,IAAI,UAAU,CAAC,6CAA6C,CAAC,CAAC;QACtE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAE,CAAC;IAC9C,CAAC,CAAC;AACJ,CAAC,EA7gBgB,eAAe,aAAf,eAAe,GAAf,eAAe,QA6gB/B;AAED,gBAAgB;AAChB,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,GAAW,EAAU,EAAE,CACnD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC"}