@nestia/e2e 8.0.5-dev.20250904 → 8.0.5

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.
@@ -1,490 +1,490 @@
1
- /**
2
- * Comprehensive random data generation utilities for testing and development.
3
- *
4
- * RandomGenerator provides a collection of functions for generating random data
5
- * including strings, names, content, dates, and array sampling. All functions
6
- * are designed to be deterministic within a single execution but produce varied
7
- * output across different runs, making them ideal for testing scenarios.
8
- *
9
- * The namespace includes specialized generators for:
10
- *
11
- * - Text content (alphabets, alphanumeric, names, paragraphs)
12
- * - Phone numbers and contact information
13
- * - Date ranges and time-based data
14
- * - Array sampling and element selection
15
- *
16
- * @author Jeongho Nam - https://github.com/samchon
17
- * @example
18
- * ```typescript
19
- * // Generate test user data
20
- * const testUser = {
21
- * id: RandomGenerator.alphaNumeric(8),
22
- * name: RandomGenerator.name(),
23
- * bio: RandomGenerator.paragraph({ sentences: 3, wordMin: 5, wordMax: 10 }),
24
- * phone: RandomGenerator.mobile(),
25
- * createdAt: RandomGenerator.date(new Date(), 1000 * 60 * 60 * 24 * 30) // 30 days
26
- * };
27
- *
28
- * // Sample data for testing
29
- * const testSample = RandomGenerator.sample(allUsers, 5);
30
- * ```;
31
- */
32
- export namespace RandomGenerator {
33
- /** Character set containing lowercase alphabetical characters a-z */
34
- const CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
35
-
36
- /**
37
- * Character set containing digits (0-9) and lowercase alphabetical characters
38
- * (a-z)
39
- */
40
- const LETTERS: string = "0123456789" + CHARACTERS;
41
-
42
- /**
43
- * Generates a random string containing only lowercase alphabetical
44
- * characters.
45
- *
46
- * Creates a string of specified length using only characters a-z. Each
47
- * character is independently randomly selected, so the same character may
48
- * appear multiple times. Useful for generating random identifiers, test
49
- * names, or placeholder text.
50
- *
51
- * @example
52
- * ```typescript
53
- * RandomGenerator.alphabets(5); // e.g. "kxqpw"
54
- * RandomGenerator.alphabets(3); // e.g. "mzr"
55
- * RandomGenerator.alphabets(10); // e.g. "qwertasdfg"
56
- *
57
- * // Generate random CSS class names
58
- * const className = `test-${RandomGenerator.alphabets(6)}`;
59
- *
60
- * // Create random variable names for testing
61
- * const varName = RandomGenerator.alphabets(8);
62
- * ```
63
- *
64
- * @param length - The desired length of the generated alphabetic string
65
- * @returns A string containing only lowercase letters of the specified length
66
- */
67
- export const alphabets = (length: number): string =>
68
- new Array(length)
69
- .fill("")
70
- .map(() => CHARACTERS[randint(0, CHARACTERS.length - 1)])
71
- .join("");
72
-
73
- /**
74
- * Generates a random alphanumeric string containing digits and lowercase
75
- * letters.
76
- *
77
- * Creates a string of specified length using characters from 0-9 and a-z.
78
- * Each position is independently randomly selected from the combined
79
- * character set. Ideal for generating random IDs, tokens, passwords, or
80
- * unique identifiers that need both numeric and alphabetic characters.
81
- *
82
- * @example
83
- * ```typescript
84
- * RandomGenerator.alphaNumeric(8); // e.g. "a1b2c3d4"
85
- * RandomGenerator.alphaNumeric(12); // e.g. "x9y8z7w6v5u4"
86
- *
87
- * // Generate random API keys
88
- * const apiKey = RandomGenerator.alphaNumeric(32);
89
- *
90
- * // Create session tokens
91
- * const sessionId = `sess_${RandomGenerator.alphaNumeric(16)}`;
92
- *
93
- * // Generate test database IDs
94
- * const testId = RandomGenerator.alphaNumeric(10);
95
- * ```
96
- *
97
- * @param length - The desired length of the generated alphanumeric string
98
- * @returns A string containing digits and lowercase letters of the specified
99
- * length
100
- */
101
- export const alphaNumeric = (length: number): string =>
102
- new Array(length)
103
- .fill("")
104
- .map(() => LETTERS[randint(0, LETTERS.length - 1)])
105
- .join("");
106
-
107
- /**
108
- * Generates a random name-like string with realistic length variation.
109
- *
110
- * Creates a name by generating a paragraph with 2-3 words (randomly chosen).
111
- * The resulting string resembles typical human names in structure and length.
112
- * Each word is between 3-7 characters by default, creating realistic-looking
113
- * names.
114
- *
115
- * @example
116
- * ```typescript
117
- * RandomGenerator.name(); // e.g. "lorem ipsum" (2-3 words)
118
- * RandomGenerator.name(1); // e.g. "dolor" (single word)
119
- * RandomGenerator.name(3); // e.g. "sit amet consectetur" (3 words)
120
- *
121
- * // Generate test user names
122
- * const users = Array.from({ length: 10 }, () => ({
123
- * id: RandomGenerator.alphaNumeric(8),
124
- * name: RandomGenerator.name(),
125
- * email: `${RandomGenerator.name(1)}@test.com`
126
- * }));
127
- *
128
- * // Create random author names for blog posts
129
- * const authorName = RandomGenerator.name();
130
- * ```
131
- *
132
- * @param length - Number of words in the name (default: random between 2-3)
133
- * @returns A space-separated string of random words (each 3-7 chars by
134
- * default)
135
- */
136
- export const name = (length: number = randint(2, 3)): string =>
137
- paragraph({
138
- sentences: length,
139
- });
140
-
141
- /**
142
- * Generates a random paragraph with configurable sentence structure.
143
- *
144
- * Creates a paragraph consisting of a specified number of "sentences"
145
- * (words). Each sentence is a random alphabetic string, and sentences are
146
- * joined with spaces. Accepts an optional configuration object for fine-tuned
147
- * control over the paragraph structure.
148
- *
149
- * @example
150
- * ```typescript
151
- * // Generate with defaults (random 2-5 words, 3-7 characters each)
152
- * RandomGenerator.paragraph(); // e.g. "lorem ipsum dolor"
153
- *
154
- * // Specific number of sentences
155
- * RandomGenerator.paragraph({ sentences: 5 }); // "lorem ipsum dolor sit amet"
156
- *
157
- * // Custom word length ranges
158
- * RandomGenerator.paragraph({ sentences: 4, wordMin: 2, wordMax: 5 });
159
- * // "ab cd ef gh"
160
- *
161
- * // Generate product descriptions
162
- * const description = RandomGenerator.paragraph({
163
- * sentences: 8,
164
- * wordMin: 4,
165
- * wordMax: 8
166
- * });
167
- *
168
- * // Create test content for forms
169
- * const placeholder = RandomGenerator.paragraph({
170
- * sentences: 3,
171
- * wordMin: 5,
172
- * wordMax: 10
173
- * });
174
- * ```;
175
- *
176
- * @param props - Optional configuration object with sentences count and word
177
- * length ranges
178
- * @returns A string containing the generated paragraph
179
- */
180
- export const paragraph = (
181
- props?: Partial<{
182
- sentences: number;
183
- wordMin: number;
184
- wordMax: number;
185
- }>,
186
- ) =>
187
- new Array(props?.sentences ?? randint(2, 5))
188
- .fill("")
189
- .map(() => alphabets(randint(props?.wordMin ?? 3, props?.wordMax ?? 7)))
190
- .join(" ");
191
-
192
- /**
193
- * Generates random multi-paragraph content with customizable structure.
194
- *
195
- * Creates content consisting of multiple paragraphs separated by double
196
- * newlines. Accepts an optional configuration object to control content
197
- * structure including paragraph count, sentences per paragraph, and word
198
- * character lengths. Ideal for generating realistic-looking text content for
199
- * testing.
200
- *
201
- * @example
202
- * ```typescript
203
- * // Generate with all defaults
204
- * const article = RandomGenerator.content();
205
- *
206
- * // Specific structure: 5 paragraphs, 15-25 sentences each, 4-8 char words
207
- * const longContent = RandomGenerator.content({
208
- * paragraphs: 5,
209
- * sentenceMin: 15,
210
- * sentenceMax: 25,
211
- * wordMin: 4,
212
- * wordMax: 8
213
- * });
214
- *
215
- * // Short content with brief sentences
216
- * const shortContent = RandomGenerator.content({
217
- * paragraphs: 2,
218
- * sentenceMin: 5,
219
- * sentenceMax: 8,
220
- * wordMin: 2,
221
- * wordMax: 4
222
- * });
223
- *
224
- * // Generate blog post content
225
- * const blogPost = {
226
- * title: RandomGenerator.name(3),
227
- * content: RandomGenerator.content({
228
- * paragraphs: 4,
229
- * sentenceMin: 10,
230
- * sentenceMax: 20,
231
- * wordMin: 3,
232
- * wordMax: 7
233
- * }),
234
- * summary: RandomGenerator.paragraph({ sentences: 2 })
235
- * };
236
- *
237
- * // Create test data for CMS
238
- * const pages = Array.from({ length: 10 }, () => ({
239
- * id: RandomGenerator.alphaNumeric(8),
240
- * content: RandomGenerator.content({
241
- * paragraphs: randint(2, 6),
242
- * sentenceMin: 8,
243
- * sentenceMax: 15
244
- * })
245
- * }));
246
- * ```;
247
- *
248
- * @param props - Optional configuration object with paragraph, sentence, and
249
- * word parameters
250
- * @returns A string containing the generated multi-paragraph content
251
- */
252
- export const content = (
253
- props?: Partial<{
254
- paragraphs: number;
255
- sentenceMin: number;
256
- sentenceMax: number;
257
- wordMin: number;
258
- wordMax: number;
259
- }>,
260
- ) =>
261
- new Array(props?.paragraphs ?? randint(3, 8))
262
- .fill("")
263
- .map(() =>
264
- paragraph({
265
- sentences: randint(
266
- props?.sentenceMin ?? 10,
267
- props?.sentenceMax ?? 40,
268
- ),
269
- wordMin: props?.wordMin ?? 1,
270
- wordMax: props?.wordMax ?? 7,
271
- }),
272
- )
273
- .join("\n\n");
274
-
275
- /**
276
- * Extracts a random substring from the provided content string.
277
- *
278
- * Selects two random positions within the content and returns the substring
279
- * between them. The starting position is always before the ending position.
280
- * Automatically trims whitespace from the beginning and end of the result.
281
- * Useful for creating excerpts, search terms, or partial content samples.
282
- *
283
- * @example
284
- * ```typescript
285
- * const text = "The quick brown fox jumps over the lazy dog";
286
- *
287
- * RandomGenerator.substring(text); // e.g. "quick brown fox"
288
- * RandomGenerator.substring(text); // e.g. "jumps over"
289
- * RandomGenerator.substring(text); // e.g. "fox jumps over the lazy"
290
- *
291
- * // Generate search terms from content
292
- * const searchQuery = RandomGenerator.substring(articleContent);
293
- *
294
- * // Create excerpts for previews
295
- * const excerpt = RandomGenerator.substring(fullBlogPost);
296
- *
297
- * // Generate partial matches for testing search functionality
298
- * const partialMatch = RandomGenerator.substring(productDescription);
299
- *
300
- * // Create random selections for highlight testing
301
- * const selectedText = RandomGenerator.substring(documentContent);
302
- * ```;
303
- *
304
- * @param content - The source string to extract a substring from
305
- * @returns A trimmed substring of the original content
306
- */
307
- export const substring = (content: string): string => {
308
- const first: number = randint(0, content.length - 1);
309
- const last: number = randint(first + 1, content.length);
310
-
311
- return content.substring(first, last).trim();
312
- };
313
-
314
- /**
315
- * Generates a random mobile phone number with customizable prefix.
316
- *
317
- * Creates a mobile phone number in the format: [prefix][3-4 digits][4
318
- * digits]. The middle section is 3 digits if the random number is less than
319
- * 1000, otherwise 4 digits. The last section is always 4 digits, zero-padded
320
- * if necessary. Commonly used for generating Korean mobile phone numbers or
321
- * similar formats.
322
- *
323
- * @example
324
- * ```typescript
325
- * RandomGenerator.mobile(); // e.g. "0103341234" or "01012345678"
326
- * RandomGenerator.mobile("011"); // e.g. "0119876543" or "01112345678"
327
- * RandomGenerator.mobile("+82"); // e.g. "+823341234" or "+8212345678"
328
- *
329
- * // Generate test user phone numbers
330
- * const testUsers = Array.from({ length: 100 }, () => ({
331
- * name: RandomGenerator.name(),
332
- * phone: RandomGenerator.mobile(),
333
- * altPhone: RandomGenerator.mobile("011")
334
- * }));
335
- *
336
- * // Create international phone numbers
337
- * const internationalPhone = RandomGenerator.mobile("+821");
338
- *
339
- * // Generate contact list for testing
340
- * const contacts = ["010", "011", "016", "017", "018", "019"].map(prefix => ({
341
- * carrier: prefix,
342
- * number: RandomGenerator.mobile(prefix)
343
- * }));
344
- * ```;
345
- *
346
- * @param prefix - The prefix string for the phone number (default: "010")
347
- * @returns A formatted mobile phone number string
348
- */
349
- export const mobile = (prefix: string = "010"): string =>
350
- [
351
- prefix,
352
- (() => {
353
- const value = randint(0, 9999);
354
- return value.toString().padStart(value < 1_000 ? 3 : 4, "0");
355
- })(),
356
- randint(0, 9999).toString().padStart(4, "0"),
357
- ].join("");
358
-
359
- /**
360
- * Generates a random date within a specified range from a starting point.
361
- *
362
- * Returns a random date between the start date and start date + range. The
363
- * range represents the maximum number of milliseconds to add to the starting
364
- * date. Useful for generating timestamps, creation dates, or scheduling test
365
- * data.
366
- *
367
- * @example
368
- * ```typescript
369
- * const now = new Date();
370
- * const oneDay = 24 * 60 * 60 * 1000;
371
- * const oneMonth = 30 * oneDay;
372
- *
373
- * // Random date within the next 30 days
374
- * const futureDate = RandomGenerator.date(now, oneMonth);
375
- *
376
- * // Random date within the past week
377
- * const pastWeek = new Date(now.getTime() - 7 * oneDay);
378
- * const recentDate = RandomGenerator.date(pastWeek, 7 * oneDay);
379
- *
380
- * // Generate random creation dates for test data
381
- * const startOfYear = new Date(2024, 0, 1);
382
- * const endOfYear = new Date(2024, 11, 31).getTime() - startOfYear.getTime();
383
- * const randomCreationDate = RandomGenerator.date(startOfYear, endOfYear);
384
- *
385
- * // Create test events with random timestamps
386
- * const events = Array.from({ length: 50 }, () => ({
387
- * id: RandomGenerator.alphaNumeric(8),
388
- * title: RandomGenerator.name(2),
389
- * createdAt: RandomGenerator.date(new Date(), oneMonth),
390
- * scheduledFor: RandomGenerator.date(new Date(), oneMonth * 3)
391
- * }));
392
- * ```;
393
- *
394
- * @param from - The starting date for the random range
395
- * @param range - The range in milliseconds from the starting date
396
- * @returns A random date within the specified range
397
- */
398
- export const date = (from: Date, range: number): Date =>
399
- new Date(from.getTime() + randint(0, range));
400
-
401
- /**
402
- * Randomly samples a specified number of unique elements from an array.
403
- *
404
- * Selects random elements from the input array without replacement, ensuring
405
- * all returned elements are unique. The sample size is automatically capped
406
- * at the array length to prevent errors. Uses a Set-based approach to
407
- * guarantee uniqueness of selected indices. Ideal for creating test datasets
408
- * or selecting random subsets for validation.
409
- *
410
- * @example
411
- * ```typescript
412
- * const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
413
- *
414
- * RandomGenerator.sample(numbers, 3); // e.g. [2, 7, 9]
415
- * RandomGenerator.sample(numbers, 5); // e.g. [1, 4, 6, 8, 10]
416
- * RandomGenerator.sample(numbers, 15); // returns all 10 elements (capped at array length)
417
- *
418
- * // Sample users for testing
419
- * const allUsers = await getUsersFromDatabase();
420
- * const testUsers = RandomGenerator.sample(allUsers, 10);
421
- *
422
- * // Create random product selections
423
- * const featuredProducts = RandomGenerator.sample(allProducts, 5);
424
- *
425
- * // Generate test data subsets
426
- * const validationSet = RandomGenerator.sample(trainingData, 100);
427
- *
428
- * // Random A/B testing groups
429
- * const groupA = RandomGenerator.sample(allParticipants, 50);
430
- * const remaining = allParticipants.filter(p => !groupA.includes(p));
431
- * const groupB = RandomGenerator.sample(remaining, 50);
432
- * ```;
433
- *
434
- * @param array - The source array to sample from
435
- * @param count - The number of elements to sample
436
- * @returns An array containing the randomly selected elements
437
- */
438
- export const sample = <T>(array: T[], count: number): T[] => {
439
- count = Math.min(count, array.length);
440
- const indexes: Set<number> = new Set();
441
- while (indexes.size < count) indexes.add(randint(0, array.length - 1));
442
- return Array.from(indexes).map((index) => array[index]);
443
- };
444
-
445
- /**
446
- * Randomly selects a single element from an array.
447
- *
448
- * Chooses one element at random from the provided array using uniform
449
- * distribution. Each element has an equal probability of being selected. This
450
- * is a convenience function equivalent to sampling with a count of 1, but
451
- * returns the element directly rather than an array containing one element.
452
- *
453
- * @example
454
- * ```typescript
455
- * const colors = ['red', 'blue', 'green', 'yellow', 'purple'];
456
- * const fruits = ['apple', 'banana', 'orange', 'grape', 'kiwi'];
457
- *
458
- * RandomGenerator.pick(colors); // e.g. "blue"
459
- * RandomGenerator.pick(fruits); // e.g. "apple"
460
- *
461
- * // Select random configuration options
462
- * const randomTheme = RandomGenerator.pick(['light', 'dark', 'auto']);
463
- * const randomLocale = RandomGenerator.pick(['en', 'ko', 'ja', 'zh']);
464
- *
465
- * // Choose random test scenarios
466
- * const testScenario = RandomGenerator.pick([
467
- * 'happy_path',
468
- * 'edge_case',
469
- * 'error_condition',
470
- * 'boundary_test'
471
- * ]);
472
- *
473
- * // Random user role assignment
474
- * const userRole = RandomGenerator.pick(['admin', 'user', 'moderator']);
475
- *
476
- * // Select random API endpoints for testing
477
- * const endpoints = ['/users', '/posts', '/comments', '/categories'];
478
- * const randomEndpoint = RandomGenerator.pick(endpoints);
479
- * ```;
480
- *
481
- * @param array - The source array to pick an element from
482
- * @returns A randomly selected element from the array
483
- */
484
- export const pick = <T>(array: readonly T[]): T =>
485
- array[randint(0, array.length - 1)];
486
- }
487
-
488
- /** @internal */
489
- const randint = (min: number, max: number): number =>
490
- Math.floor(Math.random() * (max - min + 1)) + min;
1
+ /**
2
+ * Comprehensive random data generation utilities for testing and development.
3
+ *
4
+ * RandomGenerator provides a collection of functions for generating random data
5
+ * including strings, names, content, dates, and array sampling. All functions
6
+ * are designed to be deterministic within a single execution but produce varied
7
+ * output across different runs, making them ideal for testing scenarios.
8
+ *
9
+ * The namespace includes specialized generators for:
10
+ *
11
+ * - Text content (alphabets, alphanumeric, names, paragraphs)
12
+ * - Phone numbers and contact information
13
+ * - Date ranges and time-based data
14
+ * - Array sampling and element selection
15
+ *
16
+ * @author Jeongho Nam - https://github.com/samchon
17
+ * @example
18
+ * ```typescript
19
+ * // Generate test user data
20
+ * const testUser = {
21
+ * id: RandomGenerator.alphaNumeric(8),
22
+ * name: RandomGenerator.name(),
23
+ * bio: RandomGenerator.paragraph({ sentences: 3, wordMin: 5, wordMax: 10 }),
24
+ * phone: RandomGenerator.mobile(),
25
+ * createdAt: RandomGenerator.date(new Date(), 1000 * 60 * 60 * 24 * 30) // 30 days
26
+ * };
27
+ *
28
+ * // Sample data for testing
29
+ * const testSample = RandomGenerator.sample(allUsers, 5);
30
+ * ```;
31
+ */
32
+ export namespace RandomGenerator {
33
+ /** Character set containing lowercase alphabetical characters a-z */
34
+ const CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
35
+
36
+ /**
37
+ * Character set containing digits (0-9) and lowercase alphabetical characters
38
+ * (a-z)
39
+ */
40
+ const LETTERS: string = "0123456789" + CHARACTERS;
41
+
42
+ /**
43
+ * Generates a random string containing only lowercase alphabetical
44
+ * characters.
45
+ *
46
+ * Creates a string of specified length using only characters a-z. Each
47
+ * character is independently randomly selected, so the same character may
48
+ * appear multiple times. Useful for generating random identifiers, test
49
+ * names, or placeholder text.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * RandomGenerator.alphabets(5); // e.g. "kxqpw"
54
+ * RandomGenerator.alphabets(3); // e.g. "mzr"
55
+ * RandomGenerator.alphabets(10); // e.g. "qwertasdfg"
56
+ *
57
+ * // Generate random CSS class names
58
+ * const className = `test-${RandomGenerator.alphabets(6)}`;
59
+ *
60
+ * // Create random variable names for testing
61
+ * const varName = RandomGenerator.alphabets(8);
62
+ * ```
63
+ *
64
+ * @param length - The desired length of the generated alphabetic string
65
+ * @returns A string containing only lowercase letters of the specified length
66
+ */
67
+ export const alphabets = (length: number): string =>
68
+ new Array(length)
69
+ .fill("")
70
+ .map(() => CHARACTERS[randint(0, CHARACTERS.length - 1)])
71
+ .join("");
72
+
73
+ /**
74
+ * Generates a random alphanumeric string containing digits and lowercase
75
+ * letters.
76
+ *
77
+ * Creates a string of specified length using characters from 0-9 and a-z.
78
+ * Each position is independently randomly selected from the combined
79
+ * character set. Ideal for generating random IDs, tokens, passwords, or
80
+ * unique identifiers that need both numeric and alphabetic characters.
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * RandomGenerator.alphaNumeric(8); // e.g. "a1b2c3d4"
85
+ * RandomGenerator.alphaNumeric(12); // e.g. "x9y8z7w6v5u4"
86
+ *
87
+ * // Generate random API keys
88
+ * const apiKey = RandomGenerator.alphaNumeric(32);
89
+ *
90
+ * // Create session tokens
91
+ * const sessionId = `sess_${RandomGenerator.alphaNumeric(16)}`;
92
+ *
93
+ * // Generate test database IDs
94
+ * const testId = RandomGenerator.alphaNumeric(10);
95
+ * ```
96
+ *
97
+ * @param length - The desired length of the generated alphanumeric string
98
+ * @returns A string containing digits and lowercase letters of the specified
99
+ * length
100
+ */
101
+ export const alphaNumeric = (length: number): string =>
102
+ new Array(length)
103
+ .fill("")
104
+ .map(() => LETTERS[randint(0, LETTERS.length - 1)])
105
+ .join("");
106
+
107
+ /**
108
+ * Generates a random name-like string with realistic length variation.
109
+ *
110
+ * Creates a name by generating a paragraph with 2-3 words (randomly chosen).
111
+ * The resulting string resembles typical human names in structure and length.
112
+ * Each word is between 3-7 characters by default, creating realistic-looking
113
+ * names.
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * RandomGenerator.name(); // e.g. "lorem ipsum" (2-3 words)
118
+ * RandomGenerator.name(1); // e.g. "dolor" (single word)
119
+ * RandomGenerator.name(3); // e.g. "sit amet consectetur" (3 words)
120
+ *
121
+ * // Generate test user names
122
+ * const users = Array.from({ length: 10 }, () => ({
123
+ * id: RandomGenerator.alphaNumeric(8),
124
+ * name: RandomGenerator.name(),
125
+ * email: `${RandomGenerator.name(1)}@test.com`
126
+ * }));
127
+ *
128
+ * // Create random author names for blog posts
129
+ * const authorName = RandomGenerator.name();
130
+ * ```
131
+ *
132
+ * @param length - Number of words in the name (default: random between 2-3)
133
+ * @returns A space-separated string of random words (each 3-7 chars by
134
+ * default)
135
+ */
136
+ export const name = (length: number = randint(2, 3)): string =>
137
+ paragraph({
138
+ sentences: length,
139
+ });
140
+
141
+ /**
142
+ * Generates a random paragraph with configurable sentence structure.
143
+ *
144
+ * Creates a paragraph consisting of a specified number of "sentences"
145
+ * (words). Each sentence is a random alphabetic string, and sentences are
146
+ * joined with spaces. Accepts an optional configuration object for fine-tuned
147
+ * control over the paragraph structure.
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * // Generate with defaults (random 2-5 words, 3-7 characters each)
152
+ * RandomGenerator.paragraph(); // e.g. "lorem ipsum dolor"
153
+ *
154
+ * // Specific number of sentences
155
+ * RandomGenerator.paragraph({ sentences: 5 }); // "lorem ipsum dolor sit amet"
156
+ *
157
+ * // Custom word length ranges
158
+ * RandomGenerator.paragraph({ sentences: 4, wordMin: 2, wordMax: 5 });
159
+ * // "ab cd ef gh"
160
+ *
161
+ * // Generate product descriptions
162
+ * const description = RandomGenerator.paragraph({
163
+ * sentences: 8,
164
+ * wordMin: 4,
165
+ * wordMax: 8
166
+ * });
167
+ *
168
+ * // Create test content for forms
169
+ * const placeholder = RandomGenerator.paragraph({
170
+ * sentences: 3,
171
+ * wordMin: 5,
172
+ * wordMax: 10
173
+ * });
174
+ * ```;
175
+ *
176
+ * @param props - Optional configuration object with sentences count and word
177
+ * length ranges
178
+ * @returns A string containing the generated paragraph
179
+ */
180
+ export const paragraph = (
181
+ props?: Partial<{
182
+ sentences: number;
183
+ wordMin: number;
184
+ wordMax: number;
185
+ }>,
186
+ ) =>
187
+ new Array(props?.sentences ?? randint(2, 5))
188
+ .fill("")
189
+ .map(() => alphabets(randint(props?.wordMin ?? 3, props?.wordMax ?? 7)))
190
+ .join(" ");
191
+
192
+ /**
193
+ * Generates random multi-paragraph content with customizable structure.
194
+ *
195
+ * Creates content consisting of multiple paragraphs separated by double
196
+ * newlines. Accepts an optional configuration object to control content
197
+ * structure including paragraph count, sentences per paragraph, and word
198
+ * character lengths. Ideal for generating realistic-looking text content for
199
+ * testing.
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * // Generate with all defaults
204
+ * const article = RandomGenerator.content();
205
+ *
206
+ * // Specific structure: 5 paragraphs, 15-25 sentences each, 4-8 char words
207
+ * const longContent = RandomGenerator.content({
208
+ * paragraphs: 5,
209
+ * sentenceMin: 15,
210
+ * sentenceMax: 25,
211
+ * wordMin: 4,
212
+ * wordMax: 8
213
+ * });
214
+ *
215
+ * // Short content with brief sentences
216
+ * const shortContent = RandomGenerator.content({
217
+ * paragraphs: 2,
218
+ * sentenceMin: 5,
219
+ * sentenceMax: 8,
220
+ * wordMin: 2,
221
+ * wordMax: 4
222
+ * });
223
+ *
224
+ * // Generate blog post content
225
+ * const blogPost = {
226
+ * title: RandomGenerator.name(3),
227
+ * content: RandomGenerator.content({
228
+ * paragraphs: 4,
229
+ * sentenceMin: 10,
230
+ * sentenceMax: 20,
231
+ * wordMin: 3,
232
+ * wordMax: 7
233
+ * }),
234
+ * summary: RandomGenerator.paragraph({ sentences: 2 })
235
+ * };
236
+ *
237
+ * // Create test data for CMS
238
+ * const pages = Array.from({ length: 10 }, () => ({
239
+ * id: RandomGenerator.alphaNumeric(8),
240
+ * content: RandomGenerator.content({
241
+ * paragraphs: randint(2, 6),
242
+ * sentenceMin: 8,
243
+ * sentenceMax: 15
244
+ * })
245
+ * }));
246
+ * ```;
247
+ *
248
+ * @param props - Optional configuration object with paragraph, sentence, and
249
+ * word parameters
250
+ * @returns A string containing the generated multi-paragraph content
251
+ */
252
+ export const content = (
253
+ props?: Partial<{
254
+ paragraphs: number;
255
+ sentenceMin: number;
256
+ sentenceMax: number;
257
+ wordMin: number;
258
+ wordMax: number;
259
+ }>,
260
+ ) =>
261
+ new Array(props?.paragraphs ?? randint(3, 8))
262
+ .fill("")
263
+ .map(() =>
264
+ paragraph({
265
+ sentences: randint(
266
+ props?.sentenceMin ?? 10,
267
+ props?.sentenceMax ?? 40,
268
+ ),
269
+ wordMin: props?.wordMin ?? 1,
270
+ wordMax: props?.wordMax ?? 7,
271
+ }),
272
+ )
273
+ .join("\n\n");
274
+
275
+ /**
276
+ * Extracts a random substring from the provided content string.
277
+ *
278
+ * Selects two random positions within the content and returns the substring
279
+ * between them. The starting position is always before the ending position.
280
+ * Automatically trims whitespace from the beginning and end of the result.
281
+ * Useful for creating excerpts, search terms, or partial content samples.
282
+ *
283
+ * @example
284
+ * ```typescript
285
+ * const text = "The quick brown fox jumps over the lazy dog";
286
+ *
287
+ * RandomGenerator.substring(text); // e.g. "quick brown fox"
288
+ * RandomGenerator.substring(text); // e.g. "jumps over"
289
+ * RandomGenerator.substring(text); // e.g. "fox jumps over the lazy"
290
+ *
291
+ * // Generate search terms from content
292
+ * const searchQuery = RandomGenerator.substring(articleContent);
293
+ *
294
+ * // Create excerpts for previews
295
+ * const excerpt = RandomGenerator.substring(fullBlogPost);
296
+ *
297
+ * // Generate partial matches for testing search functionality
298
+ * const partialMatch = RandomGenerator.substring(productDescription);
299
+ *
300
+ * // Create random selections for highlight testing
301
+ * const selectedText = RandomGenerator.substring(documentContent);
302
+ * ```;
303
+ *
304
+ * @param content - The source string to extract a substring from
305
+ * @returns A trimmed substring of the original content
306
+ */
307
+ export const substring = (content: string): string => {
308
+ const first: number = randint(0, content.length - 1);
309
+ const last: number = randint(first + 1, content.length);
310
+
311
+ return content.substring(first, last).trim();
312
+ };
313
+
314
+ /**
315
+ * Generates a random mobile phone number with customizable prefix.
316
+ *
317
+ * Creates a mobile phone number in the format: [prefix][3-4 digits][4
318
+ * digits]. The middle section is 3 digits if the random number is less than
319
+ * 1000, otherwise 4 digits. The last section is always 4 digits, zero-padded
320
+ * if necessary. Commonly used for generating Korean mobile phone numbers or
321
+ * similar formats.
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * RandomGenerator.mobile(); // e.g. "0103341234" or "01012345678"
326
+ * RandomGenerator.mobile("011"); // e.g. "0119876543" or "01112345678"
327
+ * RandomGenerator.mobile("+82"); // e.g. "+823341234" or "+8212345678"
328
+ *
329
+ * // Generate test user phone numbers
330
+ * const testUsers = Array.from({ length: 100 }, () => ({
331
+ * name: RandomGenerator.name(),
332
+ * phone: RandomGenerator.mobile(),
333
+ * altPhone: RandomGenerator.mobile("011")
334
+ * }));
335
+ *
336
+ * // Create international phone numbers
337
+ * const internationalPhone = RandomGenerator.mobile("+821");
338
+ *
339
+ * // Generate contact list for testing
340
+ * const contacts = ["010", "011", "016", "017", "018", "019"].map(prefix => ({
341
+ * carrier: prefix,
342
+ * number: RandomGenerator.mobile(prefix)
343
+ * }));
344
+ * ```;
345
+ *
346
+ * @param prefix - The prefix string for the phone number (default: "010")
347
+ * @returns A formatted mobile phone number string
348
+ */
349
+ export const mobile = (prefix: string = "010"): string =>
350
+ [
351
+ prefix,
352
+ (() => {
353
+ const value = randint(0, 9999);
354
+ return value.toString().padStart(value < 1_000 ? 3 : 4, "0");
355
+ })(),
356
+ randint(0, 9999).toString().padStart(4, "0"),
357
+ ].join("");
358
+
359
+ /**
360
+ * Generates a random date within a specified range from a starting point.
361
+ *
362
+ * Returns a random date between the start date and start date + range. The
363
+ * range represents the maximum number of milliseconds to add to the starting
364
+ * date. Useful for generating timestamps, creation dates, or scheduling test
365
+ * data.
366
+ *
367
+ * @example
368
+ * ```typescript
369
+ * const now = new Date();
370
+ * const oneDay = 24 * 60 * 60 * 1000;
371
+ * const oneMonth = 30 * oneDay;
372
+ *
373
+ * // Random date within the next 30 days
374
+ * const futureDate = RandomGenerator.date(now, oneMonth);
375
+ *
376
+ * // Random date within the past week
377
+ * const pastWeek = new Date(now.getTime() - 7 * oneDay);
378
+ * const recentDate = RandomGenerator.date(pastWeek, 7 * oneDay);
379
+ *
380
+ * // Generate random creation dates for test data
381
+ * const startOfYear = new Date(2024, 0, 1);
382
+ * const endOfYear = new Date(2024, 11, 31).getTime() - startOfYear.getTime();
383
+ * const randomCreationDate = RandomGenerator.date(startOfYear, endOfYear);
384
+ *
385
+ * // Create test events with random timestamps
386
+ * const events = Array.from({ length: 50 }, () => ({
387
+ * id: RandomGenerator.alphaNumeric(8),
388
+ * title: RandomGenerator.name(2),
389
+ * createdAt: RandomGenerator.date(new Date(), oneMonth),
390
+ * scheduledFor: RandomGenerator.date(new Date(), oneMonth * 3)
391
+ * }));
392
+ * ```;
393
+ *
394
+ * @param from - The starting date for the random range
395
+ * @param range - The range in milliseconds from the starting date
396
+ * @returns A random date within the specified range
397
+ */
398
+ export const date = (from: Date, range: number): Date =>
399
+ new Date(from.getTime() + randint(0, range));
400
+
401
+ /**
402
+ * Randomly samples a specified number of unique elements from an array.
403
+ *
404
+ * Selects random elements from the input array without replacement, ensuring
405
+ * all returned elements are unique. The sample size is automatically capped
406
+ * at the array length to prevent errors. Uses a Set-based approach to
407
+ * guarantee uniqueness of selected indices. Ideal for creating test datasets
408
+ * or selecting random subsets for validation.
409
+ *
410
+ * @example
411
+ * ```typescript
412
+ * const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
413
+ *
414
+ * RandomGenerator.sample(numbers, 3); // e.g. [2, 7, 9]
415
+ * RandomGenerator.sample(numbers, 5); // e.g. [1, 4, 6, 8, 10]
416
+ * RandomGenerator.sample(numbers, 15); // returns all 10 elements (capped at array length)
417
+ *
418
+ * // Sample users for testing
419
+ * const allUsers = await getUsersFromDatabase();
420
+ * const testUsers = RandomGenerator.sample(allUsers, 10);
421
+ *
422
+ * // Create random product selections
423
+ * const featuredProducts = RandomGenerator.sample(allProducts, 5);
424
+ *
425
+ * // Generate test data subsets
426
+ * const validationSet = RandomGenerator.sample(trainingData, 100);
427
+ *
428
+ * // Random A/B testing groups
429
+ * const groupA = RandomGenerator.sample(allParticipants, 50);
430
+ * const remaining = allParticipants.filter(p => !groupA.includes(p));
431
+ * const groupB = RandomGenerator.sample(remaining, 50);
432
+ * ```;
433
+ *
434
+ * @param array - The source array to sample from
435
+ * @param count - The number of elements to sample
436
+ * @returns An array containing the randomly selected elements
437
+ */
438
+ export const sample = <T>(array: T[], count: number): T[] => {
439
+ count = Math.min(count, array.length);
440
+ const indexes: Set<number> = new Set();
441
+ while (indexes.size < count) indexes.add(randint(0, array.length - 1));
442
+ return Array.from(indexes).map((index) => array[index]);
443
+ };
444
+
445
+ /**
446
+ * Randomly selects a single element from an array.
447
+ *
448
+ * Chooses one element at random from the provided array using uniform
449
+ * distribution. Each element has an equal probability of being selected. This
450
+ * is a convenience function equivalent to sampling with a count of 1, but
451
+ * returns the element directly rather than an array containing one element.
452
+ *
453
+ * @example
454
+ * ```typescript
455
+ * const colors = ['red', 'blue', 'green', 'yellow', 'purple'];
456
+ * const fruits = ['apple', 'banana', 'orange', 'grape', 'kiwi'];
457
+ *
458
+ * RandomGenerator.pick(colors); // e.g. "blue"
459
+ * RandomGenerator.pick(fruits); // e.g. "apple"
460
+ *
461
+ * // Select random configuration options
462
+ * const randomTheme = RandomGenerator.pick(['light', 'dark', 'auto']);
463
+ * const randomLocale = RandomGenerator.pick(['en', 'ko', 'ja', 'zh']);
464
+ *
465
+ * // Choose random test scenarios
466
+ * const testScenario = RandomGenerator.pick([
467
+ * 'happy_path',
468
+ * 'edge_case',
469
+ * 'error_condition',
470
+ * 'boundary_test'
471
+ * ]);
472
+ *
473
+ * // Random user role assignment
474
+ * const userRole = RandomGenerator.pick(['admin', 'user', 'moderator']);
475
+ *
476
+ * // Select random API endpoints for testing
477
+ * const endpoints = ['/users', '/posts', '/comments', '/categories'];
478
+ * const randomEndpoint = RandomGenerator.pick(endpoints);
479
+ * ```;
480
+ *
481
+ * @param array - The source array to pick an element from
482
+ * @returns A randomly selected element from the array
483
+ */
484
+ export const pick = <T>(array: readonly T[]): T =>
485
+ array[randint(0, array.length - 1)];
486
+ }
487
+
488
+ /** @internal */
489
+ const randint = (min: number, max: number): number =>
490
+ Math.floor(Math.random() * (max - min + 1)) + min;