@nestia/e2e 8.0.0 → 8.0.1-dev.20250831

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,488 +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 default)
134
- */
135
- export const name = (length: number = randint(2, 3)): string =>
136
- paragraph({
137
- sentences: length,
138
- });
139
-
140
- /**
141
- * Generates a random paragraph with configurable sentence structure.
142
- *
143
- * Creates a paragraph consisting of a specified number of "sentences"
144
- * (words). Each sentence is a random alphabetic string, and sentences are
145
- * joined with spaces. Accepts an optional configuration object for fine-tuned
146
- * control over the paragraph structure.
147
- *
148
- * @example
149
- * ```typescript
150
- * // Generate with defaults (random 2-5 words, 3-7 characters each)
151
- * RandomGenerator.paragraph(); // e.g. "lorem ipsum dolor"
152
- *
153
- * // Specific number of sentences
154
- * RandomGenerator.paragraph({ sentences: 5 }); // "lorem ipsum dolor sit amet"
155
- *
156
- * // Custom word length ranges
157
- * RandomGenerator.paragraph({ sentences: 4, wordMin: 2, wordMax: 5 });
158
- * // "ab cd ef gh"
159
- *
160
- * // Generate product descriptions
161
- * const description = RandomGenerator.paragraph({
162
- * sentences: 8,
163
- * wordMin: 4,
164
- * wordMax: 8
165
- * });
166
- *
167
- * // Create test content for forms
168
- * const placeholder = RandomGenerator.paragraph({
169
- * sentences: 3,
170
- * wordMin: 5,
171
- * wordMax: 10
172
- * });
173
- * ```;
174
- *
175
- * @param props - Optional configuration object with sentences count and word
176
- * length ranges
177
- * @returns A string containing the generated paragraph
178
- */
179
- export const paragraph = (
180
- props?: Partial<{
181
- sentences: number;
182
- wordMin: number;
183
- wordMax: number;
184
- }>,
185
- ) =>
186
- new Array(props?.sentences ?? randint(2, 5))
187
- .fill("")
188
- .map(() => alphabets(randint(props?.wordMin ?? 3, props?.wordMax ?? 7)))
189
- .join(" ");
190
-
191
- /**
192
- * Generates random multi-paragraph content with customizable structure.
193
- *
194
- * Creates content consisting of multiple paragraphs separated by double
195
- * newlines. Accepts an optional configuration object to control content
196
- * structure including paragraph count, sentences per paragraph, and word
197
- * character lengths. Ideal for generating realistic-looking text content for
198
- * testing.
199
- *
200
- * @example
201
- * ```typescript
202
- * // Generate with all defaults
203
- * const article = RandomGenerator.content();
204
- *
205
- * // Specific structure: 5 paragraphs, 15-25 sentences each, 4-8 char words
206
- * const longContent = RandomGenerator.content({
207
- * paragraphs: 5,
208
- * sentenceMin: 15,
209
- * sentenceMax: 25,
210
- * wordMin: 4,
211
- * wordMax: 8
212
- * });
213
- *
214
- * // Short content with brief sentences
215
- * const shortContent = RandomGenerator.content({
216
- * paragraphs: 2,
217
- * sentenceMin: 5,
218
- * sentenceMax: 8,
219
- * wordMin: 2,
220
- * wordMax: 4
221
- * });
222
- *
223
- * // Generate blog post content
224
- * const blogPost = {
225
- * title: RandomGenerator.name(3),
226
- * content: RandomGenerator.content({
227
- * paragraphs: 4,
228
- * sentenceMin: 10,
229
- * sentenceMax: 20,
230
- * wordMin: 3,
231
- * wordMax: 7
232
- * }),
233
- * summary: RandomGenerator.paragraph({ sentences: 2 })
234
- * };
235
- *
236
- * // Create test data for CMS
237
- * const pages = Array.from({ length: 10 }, () => ({
238
- * id: RandomGenerator.alphaNumeric(8),
239
- * content: RandomGenerator.content({
240
- * paragraphs: randint(2, 6),
241
- * sentenceMin: 8,
242
- * sentenceMax: 15
243
- * })
244
- * }));
245
- * ```;
246
- *
247
- * @param props - Optional configuration object with paragraph, sentence, and
248
- * word parameters
249
- * @returns A string containing the generated multi-paragraph content
250
- */
251
- export const content = (
252
- props?: Partial<{
253
- paragraphs: number;
254
- sentenceMin: number;
255
- sentenceMax: number;
256
- wordMin: number;
257
- wordMax: number;
258
- }>,
259
- ) =>
260
- new Array(props?.paragraphs ?? randint(3, 8))
261
- .fill("")
262
- .map(() =>
263
- paragraph({
264
- sentences: randint(
265
- props?.sentenceMin ?? 10,
266
- props?.sentenceMax ?? 40,
267
- ),
268
- wordMin: props?.wordMin ?? 1,
269
- wordMax: props?.wordMax ?? 7,
270
- }),
271
- )
272
- .join("\n\n");
273
-
274
- /**
275
- * Extracts a random substring from the provided content string.
276
- *
277
- * Selects two random positions within the content and returns the substring
278
- * between them. The starting position is always before the ending position.
279
- * Automatically trims whitespace from the beginning and end of the result.
280
- * Useful for creating excerpts, search terms, or partial content samples.
281
- *
282
- * @example
283
- * ```typescript
284
- * const text = "The quick brown fox jumps over the lazy dog";
285
- *
286
- * RandomGenerator.substring(text); // e.g. "quick brown fox"
287
- * RandomGenerator.substring(text); // e.g. "jumps over"
288
- * RandomGenerator.substring(text); // e.g. "fox jumps over the lazy"
289
- *
290
- * // Generate search terms from content
291
- * const searchQuery = RandomGenerator.substring(articleContent);
292
- *
293
- * // Create excerpts for previews
294
- * const excerpt = RandomGenerator.substring(fullBlogPost);
295
- *
296
- * // Generate partial matches for testing search functionality
297
- * const partialMatch = RandomGenerator.substring(productDescription);
298
- *
299
- * // Create random selections for highlight testing
300
- * const selectedText = RandomGenerator.substring(documentContent);
301
- * ```;
302
- *
303
- * @param content - The source string to extract a substring from
304
- * @returns A trimmed substring of the original content
305
- */
306
- export const substring = (content: string): string => {
307
- const first: number = randint(0, content.length - 1);
308
- const last: number = randint(first + 1, content.length);
309
-
310
- return content.substring(first, last).trim();
311
- };
312
-
313
- /**
314
- * Generates a random mobile phone number with customizable prefix.
315
- *
316
- * Creates a mobile phone number in the format: [prefix][3-4 digits][4
317
- * digits]. The middle section is 3 digits if the random number is less than
318
- * 1000, otherwise 4 digits. The last section is always 4 digits, zero-padded
319
- * if necessary. Commonly used for generating Korean mobile phone numbers or
320
- * similar formats.
321
- *
322
- * @example
323
- * ```typescript
324
- * RandomGenerator.mobile(); // e.g. "0103341234" or "01012345678"
325
- * RandomGenerator.mobile("011"); // e.g. "0119876543" or "01112345678"
326
- * RandomGenerator.mobile("+82"); // e.g. "+823341234" or "+8212345678"
327
- *
328
- * // Generate test user phone numbers
329
- * const testUsers = Array.from({ length: 100 }, () => ({
330
- * name: RandomGenerator.name(),
331
- * phone: RandomGenerator.mobile(),
332
- * altPhone: RandomGenerator.mobile("011")
333
- * }));
334
- *
335
- * // Create international phone numbers
336
- * const internationalPhone = RandomGenerator.mobile("+821");
337
- *
338
- * // Generate contact list for testing
339
- * const contacts = ["010", "011", "016", "017", "018", "019"].map(prefix => ({
340
- * carrier: prefix,
341
- * number: RandomGenerator.mobile(prefix)
342
- * }));
343
- * ```;
344
- *
345
- * @param prefix - The prefix string for the phone number (default: "010")
346
- * @returns A formatted mobile phone number string
347
- */
348
- export const mobile = (prefix: string = "010"): string =>
349
- [
350
- prefix,
351
- (() => {
352
- const value = randint(0, 9999);
353
- return value.toString().padStart(value < 1_000 ? 3 : 4, "0");
354
- })(),
355
- randint(0, 9999).toString().padStart(4, "0"),
356
- ].join("");
357
-
358
- /**
359
- * Generates a random date within a specified range from a starting point.
360
- *
361
- * Returns a random date between the start date and start date + range. The
362
- * range represents the maximum number of milliseconds to add to the starting
363
- * date. Useful for generating timestamps, creation dates, or scheduling test
364
- * data.
365
- *
366
- * @example
367
- * ```typescript
368
- * const now = new Date();
369
- * const oneDay = 24 * 60 * 60 * 1000;
370
- * const oneMonth = 30 * oneDay;
371
- *
372
- * // Random date within the next 30 days
373
- * const futureDate = RandomGenerator.date(now, oneMonth);
374
- *
375
- * // Random date within the past week
376
- * const pastWeek = new Date(now.getTime() - 7 * oneDay);
377
- * const recentDate = RandomGenerator.date(pastWeek, 7 * oneDay);
378
- *
379
- * // Generate random creation dates for test data
380
- * const startOfYear = new Date(2024, 0, 1);
381
- * const endOfYear = new Date(2024, 11, 31).getTime() - startOfYear.getTime();
382
- * const randomCreationDate = RandomGenerator.date(startOfYear, endOfYear);
383
- *
384
- * // Create test events with random timestamps
385
- * const events = Array.from({ length: 50 }, () => ({
386
- * id: RandomGenerator.alphaNumeric(8),
387
- * title: RandomGenerator.name(2),
388
- * createdAt: RandomGenerator.date(new Date(), oneMonth),
389
- * scheduledFor: RandomGenerator.date(new Date(), oneMonth * 3)
390
- * }));
391
- * ```;
392
- *
393
- * @param from - The starting date for the random range
394
- * @param range - The range in milliseconds from the starting date
395
- * @returns A random date within the specified range
396
- */
397
- export const date = (from: Date, range: number): Date =>
398
- new Date(from.getTime() + randint(0, range));
399
-
400
- /**
401
- * Randomly samples a specified number of unique elements from an array.
402
- *
403
- * Selects random elements from the input array without replacement, ensuring
404
- * all returned elements are unique. The sample size is automatically capped
405
- * at the array length to prevent errors. Uses a Set-based approach to
406
- * guarantee uniqueness of selected indices. Ideal for creating test datasets
407
- * or selecting random subsets for validation.
408
- *
409
- * @example
410
- * ```typescript
411
- * const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
412
- *
413
- * RandomGenerator.sample(numbers, 3); // e.g. [2, 7, 9]
414
- * RandomGenerator.sample(numbers, 5); // e.g. [1, 4, 6, 8, 10]
415
- * RandomGenerator.sample(numbers, 15); // returns all 10 elements (capped at array length)
416
- *
417
- * // Sample users for testing
418
- * const allUsers = await getUsersFromDatabase();
419
- * const testUsers = RandomGenerator.sample(allUsers, 10);
420
- *
421
- * // Create random product selections
422
- * const featuredProducts = RandomGenerator.sample(allProducts, 5);
423
- *
424
- * // Generate test data subsets
425
- * const validationSet = RandomGenerator.sample(trainingData, 100);
426
- *
427
- * // Random A/B testing groups
428
- * const groupA = RandomGenerator.sample(allParticipants, 50);
429
- * const remaining = allParticipants.filter(p => !groupA.includes(p));
430
- * const groupB = RandomGenerator.sample(remaining, 50);
431
- * ```;
432
- *
433
- * @param array - The source array to sample from
434
- * @param count - The number of elements to sample
435
- * @returns An array containing the randomly selected elements
436
- */
437
- export const sample = <T>(array: T[], count: number): T[] => {
438
- count = Math.min(count, array.length);
439
- const indexes: Set<number> = new Set();
440
- while (indexes.size < count) indexes.add(randint(0, array.length - 1));
441
- return Array.from(indexes).map((index) => array[index]);
442
- };
443
-
444
- /**
445
- * Randomly selects a single element from an array.
446
- *
447
- * Chooses one element at random from the provided array using uniform
448
- * distribution. Each element has an equal probability of being selected. This
449
- * is a convenience function equivalent to sampling with a count of 1, but
450
- * returns the element directly rather than an array containing one element.
451
- *
452
- * @example
453
- * ```typescript
454
- * const colors = ['red', 'blue', 'green', 'yellow', 'purple'];
455
- * const fruits = ['apple', 'banana', 'orange', 'grape', 'kiwi'];
456
- *
457
- * RandomGenerator.pick(colors); // e.g. "blue"
458
- * RandomGenerator.pick(fruits); // e.g. "apple"
459
- *
460
- * // Select random configuration options
461
- * const randomTheme = RandomGenerator.pick(['light', 'dark', 'auto']);
462
- * const randomLocale = RandomGenerator.pick(['en', 'ko', 'ja', 'zh']);
463
- *
464
- * // Choose random test scenarios
465
- * const testScenario = RandomGenerator.pick([
466
- * 'happy_path',
467
- * 'edge_case',
468
- * 'error_condition',
469
- * 'boundary_test'
470
- * ]);
471
- *
472
- * // Random user role assignment
473
- * const userRole = RandomGenerator.pick(['admin', 'user', 'moderator']);
474
- *
475
- * // Select random API endpoints for testing
476
- * const endpoints = ['/users', '/posts', '/comments', '/categories'];
477
- * const randomEndpoint = RandomGenerator.pick(endpoints);
478
- * ```;
479
- *
480
- * @param array - The source array to pick an element from
481
- * @returns A randomly selected element from the array
482
- */
483
- export const pick = <T>(array: T[]): T => array[randint(0, array.length - 1)];
484
- }
485
-
486
- /** @internal */
487
- const randint = (min: number, max: number): number =>
488
- 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;