@nestia/e2e 7.0.3 → 7.1.1-dev.20250714

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