@nestia/e2e 14.0.1 → 14.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ArrayUtil.d.ts +152 -70
- package/lib/ArrayUtil.js +168 -74
- package/lib/ArrayUtil.js.map +1 -1
- package/lib/DynamicExecutor.d.ts +139 -11
- package/lib/DynamicExecutor.js +98 -10
- package/lib/DynamicExecutor.js.map +1 -1
- package/lib/GaffComparator.d.ts +176 -73
- package/lib/GaffComparator.js +189 -76
- package/lib/GaffComparator.js.map +1 -1
- package/lib/MapUtil.d.ts +37 -6
- package/lib/MapUtil.js +37 -6
- package/lib/MapUtil.js.map +1 -1
- package/lib/RandomGenerator.d.ts +157 -84
- package/lib/RandomGenerator.js +173 -89
- package/lib/RandomGenerator.js.map +1 -1
- package/lib/TestValidator.d.ts +248 -74
- package/lib/TestValidator.js +252 -89
- package/lib/TestValidator.js.map +1 -1
- package/lib/internal/json_equal_to.d.ts +21 -0
- package/lib/internal/json_equal_to.js +26 -6
- package/lib/internal/json_equal_to.js.map +1 -1
- package/package.json +3 -2
- package/src/ArrayUtil.ts +172 -76
- package/src/DynamicExecutor.ts +158 -15
- package/src/GaffComparator.ts +187 -77
- package/src/MapUtil.ts +37 -6
- package/src/RandomGenerator.ts +172 -89
- package/src/TestValidator.ts +276 -98
- package/src/internal/json_equal_to.ts +25 -4
package/lib/GaffComparator.d.ts
CHANGED
|
@@ -22,27 +22,40 @@
|
|
|
22
22
|
* - Return > 0 if first element should come after second
|
|
23
23
|
* - Return 0 if elements are equal
|
|
24
24
|
*
|
|
25
|
+
* Processing cost: Each comparison extracts both key lists and visits their
|
|
26
|
+
* common prefix until the first difference; date keys additionally parse all
|
|
27
|
+
* supplied strings once per comparison. No sort or repeated scan is performed
|
|
28
|
+
* inside a comparison.
|
|
29
|
+
*
|
|
25
30
|
* @author Jeongho Nam - https://github.com/samchon
|
|
26
31
|
* @example
|
|
27
|
-
* ```typescript
|
|
28
32
|
* // 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));
|
|
33
|
+
* users.sort(GaffComparator.strings((user) => user.name));
|
|
34
|
+
* posts.sort(GaffComparator.dates((post) => post.createdAt));
|
|
35
|
+
* products.sort(GaffComparator.numbers((product) => product.price));
|
|
32
36
|
*
|
|
33
37
|
* // Multi-field sorting with arrays
|
|
34
|
-
* users.sort(
|
|
35
|
-
*
|
|
38
|
+
* users.sort(
|
|
39
|
+
* GaffComparator.strings((user) => [user.lastName, user.firstName]),
|
|
40
|
+
* );
|
|
41
|
+
* events.sort(
|
|
42
|
+
* GaffComparator.dates((event) => [event.startDate, event.endDate]),
|
|
43
|
+
* );
|
|
36
44
|
*
|
|
37
45
|
* // Integration with TestValidator's currying pattern
|
|
38
|
-
* const validator = TestValidator.sort("user sorting",
|
|
39
|
-
*
|
|
40
|
-
* )(
|
|
41
|
-
*
|
|
42
|
-
*
|
|
46
|
+
* const validator = TestValidator.sort("user sorting", (sortable) =>
|
|
47
|
+
* api.getUsers({ sort: sortable }),
|
|
48
|
+
* )(
|
|
49
|
+
* "name",
|
|
50
|
+
* "email",
|
|
51
|
+
* )(GaffComparator.strings((user) => [user.name, user.email]));
|
|
43
52
|
* await validator("+"); // ascending
|
|
44
53
|
* await validator("-"); // descending
|
|
45
|
-
*
|
|
54
|
+
*
|
|
55
|
+
* @evidence contracts/common.md#principled-implementation Each comparator maps both operands to arrays of comparable values and decides by the first position where they differ, then by array length, which is a lexicographic order that satisfies the sort contract for well-defined values; it is used to check server-side sorting from the client.
|
|
56
|
+
* @evidence contracts/common.md#clear-and-simple-design Three comparators share scalar-to-array wrapping. Strings compare each key by collation; dates and numbers use a shared strict mismatch search over their numeric keys.
|
|
57
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The ordering rule is generic in the getter, with no field, entity, or locale special case.
|
|
58
|
+
* @evidence contracts/common.md#meaningful-documentation The namespace prose lists the features and the sort contract with an example.
|
|
46
59
|
*/
|
|
47
60
|
export declare namespace GaffComparator {
|
|
48
61
|
/**
|
|
@@ -56,52 +69,89 @@ export declare namespace GaffComparator {
|
|
|
56
69
|
*
|
|
57
70
|
* When comparing arrays, performs lexicographic ordering: compares the first
|
|
58
71
|
* 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".
|
|
72
|
+
* enables complex sorting like "sort by last name, then by first name". Keys
|
|
73
|
+
* that compare equal under the runtime's collation, including different
|
|
74
|
+
* canonically equivalent Unicode spellings, continue to the next key. If the
|
|
75
|
+
* whole common prefix compares equal, the shorter key list sorts first.
|
|
76
|
+
*
|
|
77
|
+
* Processing cost: Both getters run once and a bounded loop visits only
|
|
78
|
+
* common keys until the first collation difference. Work depends on examined
|
|
79
|
+
* keys and string comparison cost; scalar wrapping adds constant space.
|
|
60
80
|
*
|
|
61
81
|
* @example
|
|
62
|
-
* ```typescript
|
|
63
82
|
* interface User {
|
|
64
83
|
* id: string;
|
|
65
84
|
* firstName: string;
|
|
66
85
|
* lastName: string;
|
|
67
86
|
* email: string;
|
|
68
|
-
* status:
|
|
87
|
+
* status: "active" | "inactive";
|
|
69
88
|
* }
|
|
70
89
|
*
|
|
71
90
|
* const users: User[] = [
|
|
72
|
-
* {
|
|
73
|
-
*
|
|
74
|
-
*
|
|
91
|
+
* {
|
|
92
|
+
* id: "1",
|
|
93
|
+
* firstName: "John",
|
|
94
|
+
* lastName: "Doe",
|
|
95
|
+
* email: "john@example.com",
|
|
96
|
+
* status: "active",
|
|
97
|
+
* },
|
|
98
|
+
* {
|
|
99
|
+
* id: "2",
|
|
100
|
+
* firstName: "Jane",
|
|
101
|
+
* lastName: "Doe",
|
|
102
|
+
* email: "jane@example.com",
|
|
103
|
+
* status: "inactive",
|
|
104
|
+
* },
|
|
105
|
+
* {
|
|
106
|
+
* id: "3",
|
|
107
|
+
* firstName: "Bob",
|
|
108
|
+
* lastName: "Smith",
|
|
109
|
+
* email: "bob@example.com",
|
|
110
|
+
* status: "active",
|
|
111
|
+
* },
|
|
75
112
|
* ];
|
|
76
113
|
*
|
|
77
114
|
* // Single field sorting
|
|
78
|
-
* users.sort(GaffComparator.strings(user => user.lastName));
|
|
115
|
+
* users.sort(GaffComparator.strings((user) => user.lastName));
|
|
79
116
|
* // Result: Doe, Doe, Smith
|
|
80
117
|
*
|
|
81
118
|
* // Multi-field sorting: last name, then first name
|
|
82
|
-
* users.sort(
|
|
119
|
+
* users.sort(
|
|
120
|
+
* GaffComparator.strings((user) => [user.lastName, user.firstName]),
|
|
121
|
+
* );
|
|
83
122
|
* // Result: Doe Jane, Doe John, Smith Bob
|
|
84
123
|
*
|
|
85
124
|
* // Status-based sorting
|
|
86
|
-
* users.sort(GaffComparator.strings(user => user.status));
|
|
125
|
+
* users.sort(GaffComparator.strings((user) => user.status));
|
|
87
126
|
* // Result: active users first, then inactive
|
|
88
127
|
*
|
|
89
128
|
* // Complex multi-field: status, then last name, then first name
|
|
90
|
-
* users.sort(
|
|
129
|
+
* users.sort(
|
|
130
|
+
* GaffComparator.strings((user) => [
|
|
131
|
+
* user.status,
|
|
132
|
+
* user.lastName,
|
|
133
|
+
* user.firstName,
|
|
134
|
+
* ]),
|
|
135
|
+
* );
|
|
91
136
|
*
|
|
92
137
|
* // Integration with TestValidator sorting validation
|
|
93
|
-
* const sortValidator = TestValidator.sort(
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
138
|
+
* const sortValidator = TestValidator.sort(
|
|
139
|
+
* "user name sorting",
|
|
140
|
+
* (sortFields) => userApi.getUsers({ sort: sortFields }),
|
|
141
|
+
* )(
|
|
142
|
+
* "lastName",
|
|
143
|
+
* "firstName",
|
|
144
|
+
* )(GaffComparator.strings((user) => [user.lastName, user.firstName]));
|
|
98
145
|
* await sortValidator("+"); // test ascending order
|
|
99
146
|
* await sortValidator("-"); // test descending order
|
|
100
|
-
* ```;
|
|
101
147
|
*
|
|
102
148
|
* @template T - The type of objects being compared
|
|
103
149
|
* @param getter - Function that extracts string value(s) from input objects
|
|
104
150
|
* @returns A comparator function suitable for Array.sort()
|
|
151
|
+
* @evidence contracts/common.md#principled-implementation Each common key position is compared once with localeCompare; a nonzero result decides the order, while collation-equal spellings continue to later keys. Only an entirely equal common prefix falls through to array length, establishing lexicographic order under the runtime's actual collation without assuming strict string equality.
|
|
152
|
+
* @evidence contracts/common.md#clear-and-simple-design Shared wrapping accepts scalar or array keys; one bounded loop returns the first nonzero collation result or the length difference.
|
|
153
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The comparison is the platform's locale collation, not a hand-written ordering.
|
|
154
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the locale sensitivity, the multi-value rule, and the arguments, with examples.
|
|
105
155
|
*/
|
|
106
156
|
const strings: <T>(getter: (input: T) => string | string[]) => (x: T, y: T) => number;
|
|
107
157
|
/**
|
|
@@ -118,8 +168,11 @@ export declare namespace GaffComparator {
|
|
|
118
168
|
* The comparison is performed on millisecond timestamps for precise
|
|
119
169
|
* ordering.
|
|
120
170
|
*
|
|
171
|
+
* Processing cost: Both getters run once, each returned string is parsed
|
|
172
|
+
* once, and the bounded mismatch search visits at most the common key count.
|
|
173
|
+
* Numeric key arrays require space proportional to the two lists.
|
|
174
|
+
*
|
|
121
175
|
* @example
|
|
122
|
-
* ```typescript
|
|
123
176
|
* interface Event {
|
|
124
177
|
* id: string;
|
|
125
178
|
* title: string;
|
|
@@ -131,53 +184,59 @@ export declare namespace GaffComparator {
|
|
|
131
184
|
*
|
|
132
185
|
* const events: Event[] = [
|
|
133
186
|
* {
|
|
134
|
-
* id:
|
|
135
|
-
* title:
|
|
136
|
-
* startDate:
|
|
137
|
-
* endDate:
|
|
138
|
-
* createdAt:
|
|
139
|
-
* updatedAt:
|
|
187
|
+
* id: "1",
|
|
188
|
+
* title: "Conference",
|
|
189
|
+
* startDate: "2024-03-15T09:00:00Z",
|
|
190
|
+
* endDate: "2024-03-15T17:00:00Z",
|
|
191
|
+
* createdAt: "2024-01-10T10:00:00Z",
|
|
192
|
+
* updatedAt: "2024-02-01T15:30:00Z",
|
|
140
193
|
* },
|
|
141
194
|
* {
|
|
142
|
-
* id:
|
|
143
|
-
* title:
|
|
144
|
-
* startDate:
|
|
145
|
-
* endDate:
|
|
146
|
-
* createdAt:
|
|
147
|
-
* updatedAt:
|
|
148
|
-
* }
|
|
195
|
+
* id: "2",
|
|
196
|
+
* title: "Workshop",
|
|
197
|
+
* startDate: "2024-03-10T14:00:00Z",
|
|
198
|
+
* endDate: "2024-03-10T16:00:00Z",
|
|
199
|
+
* createdAt: "2024-01-15T11:00:00Z",
|
|
200
|
+
* updatedAt: "2024-01-20T09:15:00Z",
|
|
201
|
+
* },
|
|
149
202
|
* ];
|
|
150
203
|
*
|
|
151
204
|
* // Sort by start date (chronological order)
|
|
152
|
-
* events.sort(GaffComparator.dates(event => event.startDate));
|
|
205
|
+
* events.sort(GaffComparator.dates((event) => event.startDate));
|
|
153
206
|
*
|
|
154
207
|
* // Sort by creation date (oldest first)
|
|
155
|
-
* events.sort(GaffComparator.dates(event => event.createdAt));
|
|
208
|
+
* events.sort(GaffComparator.dates((event) => event.createdAt));
|
|
156
209
|
*
|
|
157
210
|
* // Multi-field: start date, then end date
|
|
158
|
-
* events.sort(
|
|
211
|
+
* events.sort(
|
|
212
|
+
* GaffComparator.dates((event) => [event.startDate, event.endDate]),
|
|
213
|
+
* );
|
|
159
214
|
*
|
|
160
215
|
* // Sort by modification history: created date, then updated date
|
|
161
|
-
* events.sort(
|
|
216
|
+
* events.sort(
|
|
217
|
+
* GaffComparator.dates((event) => [event.createdAt, event.updatedAt]),
|
|
218
|
+
* );
|
|
162
219
|
*
|
|
163
220
|
* // Validate API date sorting with TestValidator
|
|
164
|
-
* const dateValidator = TestValidator.sort(
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* );
|
|
221
|
+
* const dateValidator = TestValidator.sort(
|
|
222
|
+
* "event chronological sorting",
|
|
223
|
+
* (sortFields) => eventApi.getEvents({ sort: sortFields }),
|
|
224
|
+
* )("startDate")(GaffComparator.dates((event) => event.startDate));
|
|
169
225
|
* await dateValidator("+", true); // ascending with trace logging
|
|
170
226
|
*
|
|
171
227
|
* // Test complex date-based sorting
|
|
172
|
-
* const sortByEventSchedule = GaffComparator.dates(event => [
|
|
228
|
+
* const sortByEventSchedule = GaffComparator.dates((event) => [
|
|
173
229
|
* event.startDate,
|
|
174
|
-
* event.endDate
|
|
230
|
+
* event.endDate,
|
|
175
231
|
* ]);
|
|
176
|
-
* ```;
|
|
177
232
|
*
|
|
178
233
|
* @template T - The type of objects being compared
|
|
179
234
|
* @param getter - Function that extracts date string(s) from input objects
|
|
180
235
|
* @returns A comparator function suitable for Array.sort()
|
|
236
|
+
* @evidence contracts/common.md#principled-implementation Each value is parsed by the `Date` constructor and compared by its millisecond timestamp, so ISO 8601 and the other formats the constructor accepts order correctly; a string the constructor cannot parse yields NaN, and the comparator then returns NaN, which a sort treats as equality, a limit the caller must respect by giving valid dates.
|
|
237
|
+
* @evidence contracts/common.md#clear-and-simple-design It uses the shared `wrap` and `mismatch`, and adds only the parsing.
|
|
238
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Parsing is the standard constructor with no format special cases.
|
|
239
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the accepted formats and the millisecond comparison, with examples.
|
|
181
240
|
*/
|
|
182
241
|
const dates: <T>(getter: (input: T) => string | string[]) => (x: T, y: T) => number;
|
|
183
242
|
/**
|
|
@@ -194,8 +253,11 @@ export declare namespace GaffComparator {
|
|
|
194
253
|
* on. This enables sophisticated sorting like "sort by price ascending, then
|
|
195
254
|
* by rating descending".
|
|
196
255
|
*
|
|
256
|
+
* Processing cost: Both getters run once and mismatch visits only the common
|
|
257
|
+
* prefix until the first unequal key. Existing key arrays are reused, and
|
|
258
|
+
* scalar wrapping takes constant auxiliary space.
|
|
259
|
+
*
|
|
197
260
|
* @example
|
|
198
|
-
* ```typescript
|
|
199
261
|
* interface Product {
|
|
200
262
|
* id: string;
|
|
201
263
|
* name: string;
|
|
@@ -207,49 +269,90 @@ export declare namespace GaffComparator {
|
|
|
207
269
|
* }
|
|
208
270
|
*
|
|
209
271
|
* const products: Product[] = [
|
|
210
|
-
* {
|
|
211
|
-
*
|
|
212
|
-
*
|
|
272
|
+
* {
|
|
273
|
+
* id: "1",
|
|
274
|
+
* name: "Laptop",
|
|
275
|
+
* price: 999.99,
|
|
276
|
+
* rating: 4.5,
|
|
277
|
+
* stock: 15,
|
|
278
|
+
* categoryId: 1,
|
|
279
|
+
* salesCount: 150,
|
|
280
|
+
* },
|
|
281
|
+
* {
|
|
282
|
+
* id: "2",
|
|
283
|
+
* name: "Mouse",
|
|
284
|
+
* price: 29.99,
|
|
285
|
+
* rating: 4.2,
|
|
286
|
+
* stock: 50,
|
|
287
|
+
* categoryId: 1,
|
|
288
|
+
* salesCount: 300,
|
|
289
|
+
* },
|
|
290
|
+
* {
|
|
291
|
+
* id: "3",
|
|
292
|
+
* name: "Keyboard",
|
|
293
|
+
* price: 79.99,
|
|
294
|
+
* rating: 4.8,
|
|
295
|
+
* stock: 25,
|
|
296
|
+
* categoryId: 1,
|
|
297
|
+
* salesCount: 200,
|
|
298
|
+
* },
|
|
213
299
|
* ];
|
|
214
300
|
*
|
|
215
301
|
* // Sort by price (ascending)
|
|
216
|
-
* products.sort(GaffComparator.numbers(product => product.price));
|
|
302
|
+
* products.sort(GaffComparator.numbers((product) => product.price));
|
|
217
303
|
* // Result: Mouse ($29.99), Keyboard ($79.99), Laptop ($999.99)
|
|
218
304
|
*
|
|
219
305
|
* // Sort by rating (descending requires negation)
|
|
220
|
-
* products.sort(GaffComparator.numbers(product => -product.rating));
|
|
306
|
+
* products.sort(GaffComparator.numbers((product) => -product.rating));
|
|
221
307
|
* // Result: Keyboard (4.8), Laptop (4.5), Mouse (4.2)
|
|
222
308
|
*
|
|
223
309
|
* // Multi-field: category, then price
|
|
224
|
-
* products.sort(
|
|
310
|
+
* products.sort(
|
|
311
|
+
* GaffComparator.numbers((product) => [
|
|
312
|
+
* product.categoryId,
|
|
313
|
+
* product.price,
|
|
314
|
+
* ]),
|
|
315
|
+
* );
|
|
225
316
|
*
|
|
226
317
|
* // Complex business logic: popularity (sales) then rating
|
|
227
|
-
* products.sort(
|
|
318
|
+
* products.sort(
|
|
319
|
+
* GaffComparator.numbers((product) => [
|
|
320
|
+
* -product.salesCount,
|
|
321
|
+
* -product.rating,
|
|
322
|
+
* ]),
|
|
323
|
+
* );
|
|
228
324
|
* // Negative values for descending order
|
|
229
325
|
*
|
|
230
326
|
* // Sort by inventory priority: low stock first, then by sales
|
|
231
|
-
* products.sort(
|
|
327
|
+
* products.sort(
|
|
328
|
+
* GaffComparator.numbers((product) => [
|
|
329
|
+
* product.stock,
|
|
330
|
+
* -product.salesCount,
|
|
331
|
+
* ]),
|
|
332
|
+
* );
|
|
232
333
|
*
|
|
233
334
|
* // Validate API numerical sorting with TestValidator
|
|
234
|
-
* const priceValidator = TestValidator.sort(
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
* );
|
|
335
|
+
* const priceValidator = TestValidator.sort(
|
|
336
|
+
* "product price sorting",
|
|
337
|
+
* (sortFields) => productApi.getProducts({ sort: sortFields }),
|
|
338
|
+
* )("price")(GaffComparator.numbers((product) => product.price));
|
|
239
339
|
* await priceValidator("+"); // test ascending order
|
|
240
340
|
* await priceValidator("-"); // test descending order
|
|
241
341
|
*
|
|
242
342
|
* // Test multi-criteria sorting
|
|
243
|
-
* const sortByBusinessValue = GaffComparator.numbers(product => [
|
|
244
|
-
* -product.salesCount,
|
|
245
|
-
* -product.rating,
|
|
246
|
-
* product.price
|
|
343
|
+
* const sortByBusinessValue = GaffComparator.numbers((product) => [
|
|
344
|
+
* -product.salesCount, // High sales first
|
|
345
|
+
* -product.rating, // High rating first
|
|
346
|
+
* product.price, // Low price first (for tie-breaking)
|
|
247
347
|
* ]);
|
|
248
|
-
* ```;
|
|
249
348
|
*
|
|
250
349
|
* @template T - The type of objects being compared
|
|
251
350
|
* @param closure - Function that extracts number value(s) from input objects
|
|
252
351
|
* @returns A comparator function suitable for Array.sort()
|
|
352
|
+
* @evidence contracts/common.md#principled-implementation The sign of subtraction at the first differing position orders finite numeric values, and a shorter equal prefix sorts first. Subtraction can round or overflow, so the result's magnitude is not an exact-distance guarantee; callers must supply ordered numeric values rather than NaN.
|
|
353
|
+
* @evidence contracts/common.md#clear-and-simple-design It uses the shared `wrap` and `mismatch`, and adds only the subtraction.
|
|
354
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The comparison is the arithmetic difference, with no rounding or thresholds.
|
|
355
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the multi-value rule and the arguments, with examples.
|
|
253
356
|
*/
|
|
254
357
|
const numbers: <T>(closure: (input: T) => number | number[]) => (x: T, y: T) => number;
|
|
255
358
|
}
|