@nestia/e2e 8.1.0 → 9.0.0-dev.20251107

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,287 +1,287 @@
1
- /**
2
- * Type-safe comparator functions for Array.sort() operations with advanced
3
- * field access.
4
- *
5
- * GaffComparator provides a collection of specialized comparator functions
6
- * designed to work seamlessly with Array.sort() and testing frameworks like
7
- * TestValidator.sort(). Each comparator supports both single values and arrays
8
- * of values, enabling complex multi-field sorting scenarios with lexicographic
9
- * ordering.
10
- *
11
- * Key features:
12
- *
13
- * - Generic type safety for any object structure
14
- * - Support for single values or arrays of values per field
15
- * - Lexicographic comparison for multi-value scenarios
16
- * - Locale-aware string comparison
17
- * - Automatic type conversion for dates and numbers
18
- *
19
- * The comparators follow the standard JavaScript sort contract:
20
- *
21
- * - Return < 0 if first element should come before second
22
- * - Return > 0 if first element should come after second
23
- * - Return 0 if elements are equal
24
- *
25
- * @author Jeongho Nam - https://github.com/samchon
26
- * @example
27
- * ```typescript
28
- * // Basic usage with single fields
29
- * users.sort(GaffComparator.strings(user => user.name));
30
- * posts.sort(GaffComparator.dates(post => post.createdAt));
31
- * products.sort(GaffComparator.numbers(product => product.price));
32
- *
33
- * // Multi-field sorting with arrays
34
- * users.sort(GaffComparator.strings(user => [user.lastName, user.firstName]));
35
- * events.sort(GaffComparator.dates(event => [event.startDate, event.endDate]));
36
- *
37
- * // Integration with TestValidator's currying pattern
38
- * const validator = TestValidator.sort("user sorting",
39
- * (sortable) => api.getUsers({ sort: sortable })
40
- * )("name", "email")(
41
- * GaffComparator.strings(user => [user.name, user.email])
42
- * );
43
- * await validator("+"); // ascending
44
- * await validator("-"); // descending
45
- * ```;
46
- */
47
- export namespace GaffComparator {
48
- /**
49
- * Creates a comparator function for string-based sorting with locale-aware
50
- * comparison.
51
- *
52
- * Generates a comparator that extracts string values from objects and
53
- * performs lexicographic comparison using locale-sensitive string comparison.
54
- * Supports both single strings and arrays of strings for multi-field sorting
55
- * scenarios.
56
- *
57
- * When comparing arrays, performs lexicographic ordering: compares the first
58
- * elements, then the second elements if the first are equal, and so on. This
59
- * enables complex sorting like "sort by last name, then by first name".
60
- *
61
- * @example
62
- * ```typescript
63
- * interface User {
64
- * id: string;
65
- * firstName: string;
66
- * lastName: string;
67
- * email: string;
68
- * status: 'active' | 'inactive';
69
- * }
70
- *
71
- * const users: User[] = [
72
- * { id: '1', firstName: 'John', lastName: 'Doe', email: 'john@example.com', status: 'active' },
73
- * { id: '2', firstName: 'Jane', lastName: 'Doe', email: 'jane@example.com', status: 'inactive' },
74
- * { id: '3', firstName: 'Bob', lastName: 'Smith', email: 'bob@example.com', status: 'active' }
75
- * ];
76
- *
77
- * // Single field sorting
78
- * users.sort(GaffComparator.strings(user => user.lastName));
79
- * // Result: Doe, Doe, Smith
80
- *
81
- * // Multi-field sorting: last name, then first name
82
- * users.sort(GaffComparator.strings(user => [user.lastName, user.firstName]));
83
- * // Result: Doe Jane, Doe John, Smith Bob
84
- *
85
- * // Status-based sorting
86
- * users.sort(GaffComparator.strings(user => user.status));
87
- * // Result: active users first, then inactive
88
- *
89
- * // Complex multi-field: status, then last name, then first name
90
- * users.sort(GaffComparator.strings(user => [user.status, user.lastName, user.firstName]));
91
- *
92
- * // Integration with TestValidator sorting validation
93
- * const sortValidator = TestValidator.sort("user name sorting",
94
- * (sortFields) => userApi.getUsers({ sort: sortFields })
95
- * )("lastName", "firstName")(
96
- * GaffComparator.strings(user => [user.lastName, user.firstName])
97
- * );
98
- * await sortValidator("+"); // test ascending order
99
- * await sortValidator("-"); // test descending order
100
- * ```;
101
- *
102
- * @template T - The type of objects being compared
103
- * @param getter - Function that extracts string value(s) from input objects
104
- * @returns A comparator function suitable for Array.sort()
105
- */
106
- export const strings =
107
- <T>(getter: (input: T) => string | string[]) =>
108
- (x: T, y: T): number => {
109
- const a: string[] = wrap(getter(x));
110
- const b: string[] = wrap(getter(y));
111
-
112
- const idx: number = a.findIndex((v, i) => v !== b[i]);
113
- return idx !== -1 ? compare(a[idx], b[idx]) : 0;
114
- };
115
-
116
- /**
117
- * Creates a comparator function for date-based sorting with automatic string
118
- * parsing.
119
- *
120
- * Generates a comparator that extracts date values from objects,
121
- * automatically converting string representations to Date objects for
122
- * numerical comparison. Supports both single dates and arrays of dates for
123
- * complex temporal sorting.
124
- *
125
- * Date strings are parsed using the standard Date constructor, which supports
126
- * ISO 8601 format, RFC 2822 format, and other common date representations.
127
- * The comparison is performed on millisecond timestamps for precise
128
- * ordering.
129
- *
130
- * @example
131
- * ```typescript
132
- * interface Event {
133
- * id: string;
134
- * title: string;
135
- * startDate: string;
136
- * endDate: string;
137
- * createdAt: string;
138
- * updatedAt: string;
139
- * }
140
- *
141
- * const events: Event[] = [
142
- * {
143
- * id: '1',
144
- * title: 'Conference',
145
- * startDate: '2024-03-15T09:00:00Z',
146
- * endDate: '2024-03-15T17:00:00Z',
147
- * createdAt: '2024-01-10T10:00:00Z',
148
- * updatedAt: '2024-02-01T15:30:00Z'
149
- * },
150
- * {
151
- * id: '2',
152
- * title: 'Workshop',
153
- * startDate: '2024-03-10T14:00:00Z',
154
- * endDate: '2024-03-10T16:00:00Z',
155
- * createdAt: '2024-01-15T11:00:00Z',
156
- * updatedAt: '2024-01-20T09:15:00Z'
157
- * }
158
- * ];
159
- *
160
- * // Sort by start date (chronological order)
161
- * events.sort(GaffComparator.dates(event => event.startDate));
162
- *
163
- * // Sort by creation date (oldest first)
164
- * events.sort(GaffComparator.dates(event => event.createdAt));
165
- *
166
- * // Multi-field: start date, then end date
167
- * events.sort(GaffComparator.dates(event => [event.startDate, event.endDate]));
168
- *
169
- * // Sort by modification history: created date, then updated date
170
- * events.sort(GaffComparator.dates(event => [event.createdAt, event.updatedAt]));
171
- *
172
- * // Validate API date sorting with TestValidator
173
- * const dateValidator = TestValidator.sort("event chronological sorting",
174
- * (sortFields) => eventApi.getEvents({ sort: sortFields })
175
- * )("startDate")(
176
- * GaffComparator.dates(event => event.startDate)
177
- * );
178
- * await dateValidator("+", true); // ascending with trace logging
179
- *
180
- * // Test complex date-based sorting
181
- * const sortByEventSchedule = GaffComparator.dates(event => [
182
- * event.startDate,
183
- * event.endDate
184
- * ]);
185
- * ```;
186
- *
187
- * @template T - The type of objects being compared
188
- * @param getter - Function that extracts date string(s) from input objects
189
- * @returns A comparator function suitable for Array.sort()
190
- */
191
- export const dates =
192
- <T>(getter: (input: T) => string | string[]) =>
193
- (x: T, y: T): number => {
194
- const take = (v: T) =>
195
- wrap(getter(v)).map((str) => new Date(str).getTime());
196
- const a: number[] = take(x);
197
- const b: number[] = take(y);
198
-
199
- const idx: number = a.findIndex((v, i) => v !== b[i]);
200
- return idx !== -1 ? a[idx] - b[idx] : 0;
201
- };
202
-
203
- /**
204
- * Creates a comparator function for numerical sorting with multi-value
205
- * support.
206
- *
207
- * Generates a comparator that extracts numerical values from objects and
208
- * performs mathematical comparison. Supports both single numbers and arrays
209
- * of numbers for complex numerical sorting scenarios like sorting by price
210
- * then by rating.
211
- *
212
- * When comparing arrays, performs lexicographic numerical ordering: compares
213
- * the first numbers, then the second numbers if the first are equal, and so
214
- * on. This enables sophisticated sorting like "sort by price ascending, then
215
- * by rating descending".
216
- *
217
- * @example
218
- * ```typescript
219
- * interface Product {
220
- * id: string;
221
- * name: string;
222
- * price: number;
223
- * rating: number;
224
- * stock: number;
225
- * categoryId: number;
226
- * salesCount: number;
227
- * }
228
- *
229
- * const products: Product[] = [
230
- * { id: '1', name: 'Laptop', price: 999.99, rating: 4.5, stock: 15, categoryId: 1, salesCount: 150 },
231
- * { id: '2', name: 'Mouse', price: 29.99, rating: 4.2, stock: 50, categoryId: 1, salesCount: 300 },
232
- * { id: '3', name: 'Keyboard', price: 79.99, rating: 4.8, stock: 25, categoryId: 1, salesCount: 200 }
233
- * ];
234
- *
235
- * // Sort by price (ascending)
236
- * products.sort(GaffComparator.numbers(product => product.price));
237
- * // Result: Mouse ($29.99), Keyboard ($79.99), Laptop ($999.99)
238
- *
239
- * // Sort by rating (descending requires negation)
240
- * products.sort(GaffComparator.numbers(product => -product.rating));
241
- * // Result: Keyboard (4.8), Laptop (4.5), Mouse (4.2)
242
- *
243
- * // Multi-field: category, then price
244
- * products.sort(GaffComparator.numbers(product => [product.categoryId, product.price]));
245
- *
246
- * // Complex business logic: popularity (sales) then rating
247
- * products.sort(GaffComparator.numbers(product => [-product.salesCount, -product.rating]));
248
- * // Negative values for descending order
249
- *
250
- * // Sort by inventory priority: low stock first, then by sales
251
- * products.sort(GaffComparator.numbers(product => [product.stock, -product.salesCount]));
252
- *
253
- * // Validate API numerical sorting with TestValidator
254
- * const priceValidator = TestValidator.sort("product price sorting",
255
- * (sortFields) => productApi.getProducts({ sort: sortFields })
256
- * )("price")(
257
- * GaffComparator.numbers(product => product.price)
258
- * );
259
- * await priceValidator("+"); // test ascending order
260
- * await priceValidator("-"); // test descending order
261
- *
262
- * // Test multi-criteria sorting
263
- * const sortByBusinessValue = GaffComparator.numbers(product => [
264
- * -product.salesCount, // High sales first
265
- * -product.rating, // High rating first
266
- * product.price // Low price first (for tie-breaking)
267
- * ]);
268
- * ```;
269
- *
270
- * @template T - The type of objects being compared
271
- * @param closure - Function that extracts number value(s) from input objects
272
- * @returns A comparator function suitable for Array.sort()
273
- */
274
- export const numbers =
275
- <T>(closure: (input: T) => number | number[]) =>
276
- (x: T, y: T): number => {
277
- const a: number[] = wrap(closure(x));
278
- const b: number[] = wrap(closure(y));
279
-
280
- const idx: number = a.findIndex((v, i) => v !== b[i]);
281
- return idx !== -1 ? a[idx] - b[idx] : 0;
282
- };
283
-
284
- const compare = (x: string, y: string) => x.localeCompare(y);
285
-
286
- const wrap = <T>(elem: T | T[]): T[] => (Array.isArray(elem) ? elem : [elem]);
287
- }
1
+ /**
2
+ * Type-safe comparator functions for Array.sort() operations with advanced
3
+ * field access.
4
+ *
5
+ * GaffComparator provides a collection of specialized comparator functions
6
+ * designed to work seamlessly with Array.sort() and testing frameworks like
7
+ * TestValidator.sort(). Each comparator supports both single values and arrays
8
+ * of values, enabling complex multi-field sorting scenarios with lexicographic
9
+ * ordering.
10
+ *
11
+ * Key features:
12
+ *
13
+ * - Generic type safety for any object structure
14
+ * - Support for single values or arrays of values per field
15
+ * - Lexicographic comparison for multi-value scenarios
16
+ * - Locale-aware string comparison
17
+ * - Automatic type conversion for dates and numbers
18
+ *
19
+ * The comparators follow the standard JavaScript sort contract:
20
+ *
21
+ * - Return < 0 if first element should come before second
22
+ * - Return > 0 if first element should come after second
23
+ * - Return 0 if elements are equal
24
+ *
25
+ * @author Jeongho Nam - https://github.com/samchon
26
+ * @example
27
+ * ```typescript
28
+ * // Basic usage with single fields
29
+ * users.sort(GaffComparator.strings(user => user.name));
30
+ * posts.sort(GaffComparator.dates(post => post.createdAt));
31
+ * products.sort(GaffComparator.numbers(product => product.price));
32
+ *
33
+ * // Multi-field sorting with arrays
34
+ * users.sort(GaffComparator.strings(user => [user.lastName, user.firstName]));
35
+ * events.sort(GaffComparator.dates(event => [event.startDate, event.endDate]));
36
+ *
37
+ * // Integration with TestValidator's currying pattern
38
+ * const validator = TestValidator.sort("user sorting",
39
+ * (sortable) => api.getUsers({ sort: sortable })
40
+ * )("name", "email")(
41
+ * GaffComparator.strings(user => [user.name, user.email])
42
+ * );
43
+ * await validator("+"); // ascending
44
+ * await validator("-"); // descending
45
+ * ```;
46
+ */
47
+ export namespace GaffComparator {
48
+ /**
49
+ * Creates a comparator function for string-based sorting with locale-aware
50
+ * comparison.
51
+ *
52
+ * Generates a comparator that extracts string values from objects and
53
+ * performs lexicographic comparison using locale-sensitive string comparison.
54
+ * Supports both single strings and arrays of strings for multi-field sorting
55
+ * scenarios.
56
+ *
57
+ * When comparing arrays, performs lexicographic ordering: compares the first
58
+ * elements, then the second elements if the first are equal, and so on. This
59
+ * enables complex sorting like "sort by last name, then by first name".
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * interface User {
64
+ * id: string;
65
+ * firstName: string;
66
+ * lastName: string;
67
+ * email: string;
68
+ * status: 'active' | 'inactive';
69
+ * }
70
+ *
71
+ * const users: User[] = [
72
+ * { id: '1', firstName: 'John', lastName: 'Doe', email: 'john@example.com', status: 'active' },
73
+ * { id: '2', firstName: 'Jane', lastName: 'Doe', email: 'jane@example.com', status: 'inactive' },
74
+ * { id: '3', firstName: 'Bob', lastName: 'Smith', email: 'bob@example.com', status: 'active' }
75
+ * ];
76
+ *
77
+ * // Single field sorting
78
+ * users.sort(GaffComparator.strings(user => user.lastName));
79
+ * // Result: Doe, Doe, Smith
80
+ *
81
+ * // Multi-field sorting: last name, then first name
82
+ * users.sort(GaffComparator.strings(user => [user.lastName, user.firstName]));
83
+ * // Result: Doe Jane, Doe John, Smith Bob
84
+ *
85
+ * // Status-based sorting
86
+ * users.sort(GaffComparator.strings(user => user.status));
87
+ * // Result: active users first, then inactive
88
+ *
89
+ * // Complex multi-field: status, then last name, then first name
90
+ * users.sort(GaffComparator.strings(user => [user.status, user.lastName, user.firstName]));
91
+ *
92
+ * // Integration with TestValidator sorting validation
93
+ * const sortValidator = TestValidator.sort("user name sorting",
94
+ * (sortFields) => userApi.getUsers({ sort: sortFields })
95
+ * )("lastName", "firstName")(
96
+ * GaffComparator.strings(user => [user.lastName, user.firstName])
97
+ * );
98
+ * await sortValidator("+"); // test ascending order
99
+ * await sortValidator("-"); // test descending order
100
+ * ```;
101
+ *
102
+ * @template T - The type of objects being compared
103
+ * @param getter - Function that extracts string value(s) from input objects
104
+ * @returns A comparator function suitable for Array.sort()
105
+ */
106
+ export const strings =
107
+ <T>(getter: (input: T) => string | string[]) =>
108
+ (x: T, y: T): number => {
109
+ const a: string[] = wrap(getter(x));
110
+ const b: string[] = wrap(getter(y));
111
+
112
+ const idx: number = a.findIndex((v, i) => v !== b[i]);
113
+ return idx !== -1 ? compare(a[idx], b[idx]) : 0;
114
+ };
115
+
116
+ /**
117
+ * Creates a comparator function for date-based sorting with automatic string
118
+ * parsing.
119
+ *
120
+ * Generates a comparator that extracts date values from objects,
121
+ * automatically converting string representations to Date objects for
122
+ * numerical comparison. Supports both single dates and arrays of dates for
123
+ * complex temporal sorting.
124
+ *
125
+ * Date strings are parsed using the standard Date constructor, which supports
126
+ * ISO 8601 format, RFC 2822 format, and other common date representations.
127
+ * The comparison is performed on millisecond timestamps for precise
128
+ * ordering.
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * interface Event {
133
+ * id: string;
134
+ * title: string;
135
+ * startDate: string;
136
+ * endDate: string;
137
+ * createdAt: string;
138
+ * updatedAt: string;
139
+ * }
140
+ *
141
+ * const events: Event[] = [
142
+ * {
143
+ * id: '1',
144
+ * title: 'Conference',
145
+ * startDate: '2024-03-15T09:00:00Z',
146
+ * endDate: '2024-03-15T17:00:00Z',
147
+ * createdAt: '2024-01-10T10:00:00Z',
148
+ * updatedAt: '2024-02-01T15:30:00Z'
149
+ * },
150
+ * {
151
+ * id: '2',
152
+ * title: 'Workshop',
153
+ * startDate: '2024-03-10T14:00:00Z',
154
+ * endDate: '2024-03-10T16:00:00Z',
155
+ * createdAt: '2024-01-15T11:00:00Z',
156
+ * updatedAt: '2024-01-20T09:15:00Z'
157
+ * }
158
+ * ];
159
+ *
160
+ * // Sort by start date (chronological order)
161
+ * events.sort(GaffComparator.dates(event => event.startDate));
162
+ *
163
+ * // Sort by creation date (oldest first)
164
+ * events.sort(GaffComparator.dates(event => event.createdAt));
165
+ *
166
+ * // Multi-field: start date, then end date
167
+ * events.sort(GaffComparator.dates(event => [event.startDate, event.endDate]));
168
+ *
169
+ * // Sort by modification history: created date, then updated date
170
+ * events.sort(GaffComparator.dates(event => [event.createdAt, event.updatedAt]));
171
+ *
172
+ * // Validate API date sorting with TestValidator
173
+ * const dateValidator = TestValidator.sort("event chronological sorting",
174
+ * (sortFields) => eventApi.getEvents({ sort: sortFields })
175
+ * )("startDate")(
176
+ * GaffComparator.dates(event => event.startDate)
177
+ * );
178
+ * await dateValidator("+", true); // ascending with trace logging
179
+ *
180
+ * // Test complex date-based sorting
181
+ * const sortByEventSchedule = GaffComparator.dates(event => [
182
+ * event.startDate,
183
+ * event.endDate
184
+ * ]);
185
+ * ```;
186
+ *
187
+ * @template T - The type of objects being compared
188
+ * @param getter - Function that extracts date string(s) from input objects
189
+ * @returns A comparator function suitable for Array.sort()
190
+ */
191
+ export const dates =
192
+ <T>(getter: (input: T) => string | string[]) =>
193
+ (x: T, y: T): number => {
194
+ const take = (v: T) =>
195
+ wrap(getter(v)).map((str) => new Date(str).getTime());
196
+ const a: number[] = take(x);
197
+ const b: number[] = take(y);
198
+
199
+ const idx: number = a.findIndex((v, i) => v !== b[i]);
200
+ return idx !== -1 ? a[idx] - b[idx] : 0;
201
+ };
202
+
203
+ /**
204
+ * Creates a comparator function for numerical sorting with multi-value
205
+ * support.
206
+ *
207
+ * Generates a comparator that extracts numerical values from objects and
208
+ * performs mathematical comparison. Supports both single numbers and arrays
209
+ * of numbers for complex numerical sorting scenarios like sorting by price
210
+ * then by rating.
211
+ *
212
+ * When comparing arrays, performs lexicographic numerical ordering: compares
213
+ * the first numbers, then the second numbers if the first are equal, and so
214
+ * on. This enables sophisticated sorting like "sort by price ascending, then
215
+ * by rating descending".
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * interface Product {
220
+ * id: string;
221
+ * name: string;
222
+ * price: number;
223
+ * rating: number;
224
+ * stock: number;
225
+ * categoryId: number;
226
+ * salesCount: number;
227
+ * }
228
+ *
229
+ * const products: Product[] = [
230
+ * { id: '1', name: 'Laptop', price: 999.99, rating: 4.5, stock: 15, categoryId: 1, salesCount: 150 },
231
+ * { id: '2', name: 'Mouse', price: 29.99, rating: 4.2, stock: 50, categoryId: 1, salesCount: 300 },
232
+ * { id: '3', name: 'Keyboard', price: 79.99, rating: 4.8, stock: 25, categoryId: 1, salesCount: 200 }
233
+ * ];
234
+ *
235
+ * // Sort by price (ascending)
236
+ * products.sort(GaffComparator.numbers(product => product.price));
237
+ * // Result: Mouse ($29.99), Keyboard ($79.99), Laptop ($999.99)
238
+ *
239
+ * // Sort by rating (descending requires negation)
240
+ * products.sort(GaffComparator.numbers(product => -product.rating));
241
+ * // Result: Keyboard (4.8), Laptop (4.5), Mouse (4.2)
242
+ *
243
+ * // Multi-field: category, then price
244
+ * products.sort(GaffComparator.numbers(product => [product.categoryId, product.price]));
245
+ *
246
+ * // Complex business logic: popularity (sales) then rating
247
+ * products.sort(GaffComparator.numbers(product => [-product.salesCount, -product.rating]));
248
+ * // Negative values for descending order
249
+ *
250
+ * // Sort by inventory priority: low stock first, then by sales
251
+ * products.sort(GaffComparator.numbers(product => [product.stock, -product.salesCount]));
252
+ *
253
+ * // Validate API numerical sorting with TestValidator
254
+ * const priceValidator = TestValidator.sort("product price sorting",
255
+ * (sortFields) => productApi.getProducts({ sort: sortFields })
256
+ * )("price")(
257
+ * GaffComparator.numbers(product => product.price)
258
+ * );
259
+ * await priceValidator("+"); // test ascending order
260
+ * await priceValidator("-"); // test descending order
261
+ *
262
+ * // Test multi-criteria sorting
263
+ * const sortByBusinessValue = GaffComparator.numbers(product => [
264
+ * -product.salesCount, // High sales first
265
+ * -product.rating, // High rating first
266
+ * product.price // Low price first (for tie-breaking)
267
+ * ]);
268
+ * ```;
269
+ *
270
+ * @template T - The type of objects being compared
271
+ * @param closure - Function that extracts number value(s) from input objects
272
+ * @returns A comparator function suitable for Array.sort()
273
+ */
274
+ export const numbers =
275
+ <T>(closure: (input: T) => number | number[]) =>
276
+ (x: T, y: T): number => {
277
+ const a: number[] = wrap(closure(x));
278
+ const b: number[] = wrap(closure(y));
279
+
280
+ const idx: number = a.findIndex((v, i) => v !== b[i]);
281
+ return idx !== -1 ? a[idx] - b[idx] : 0;
282
+ };
283
+
284
+ const compare = (x: string, y: string) => x.localeCompare(y);
285
+
286
+ const wrap = <T>(elem: T | T[]): T[] => (Array.isArray(elem) ? elem : [elem]);
287
+ }