te.js 2.0.1 → 2.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/package.json +13 -2
- package/.cursor/plans/ai_native_framework_features_5bb1a20a.plan.md +0 -234
- package/.cursor/plans/auto_error_fix_agent_e68979c5.plan.md +0 -356
- package/.cursor/plans/tejas_framework_test_suite_5e3c6fad.plan.md +0 -168
- package/.prettierignore +0 -31
- package/.prettierrc +0 -5
- package/example/API_OVERVIEW.md +0 -77
- package/example/README.md +0 -155
- package/example/index.js +0 -29
- package/example/middlewares/auth.js +0 -9
- package/example/middlewares/global.midair.js +0 -6
- package/example/openapi.json +0 -390
- package/example/package.json +0 -23
- package/example/services/cache.service.js +0 -25
- package/example/services/user.service.js +0 -42
- package/example/start-redis.js +0 -2
- package/example/targets/cache.target.js +0 -35
- package/example/targets/index.target.js +0 -16
- package/example/targets/users.target.js +0 -60
- package/example/tejas.config.json +0 -22
- package/tests/auto-docs/handler-analyzer.test.js +0 -44
- package/tests/auto-docs/openapi-generator.test.js +0 -103
- package/tests/auto-docs/parse.test.js +0 -63
- package/tests/auto-docs/source-resolver.test.js +0 -58
- package/tests/helpers/index.js +0 -37
- package/tests/helpers/mock-http.js +0 -342
- package/tests/helpers/test-utils.js +0 -446
- package/tests/setup.test.js +0 -148
- package/vitest.config.js +0 -54
|
@@ -1,446 +0,0 @@
|
|
|
1
|
-
import { vi } from 'vitest';
|
|
2
|
-
import { createMockRequest, createMockResponse, createMockPair } from './mock-http.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Create an Ammo instance with mocked request/response
|
|
6
|
-
* @param {Object} options - Request options
|
|
7
|
-
* @returns {Promise<Object>} Object containing ammo, req, and res
|
|
8
|
-
*/
|
|
9
|
-
export async function createTestAmmo(options = {}) {
|
|
10
|
-
const { req, res } = createMockPair(options);
|
|
11
|
-
|
|
12
|
-
// Dynamically import Ammo to avoid module initialization issues
|
|
13
|
-
const { default: Ammo } = await import('../../server/ammo.js');
|
|
14
|
-
const ammo = new Ammo(req, res);
|
|
15
|
-
|
|
16
|
-
return { ammo, req, res };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Create an enhanced Ammo instance (with enhance() already called)
|
|
21
|
-
* @param {Object} options - Request options
|
|
22
|
-
* @returns {Promise<Object>} Object containing ammo, req, and res
|
|
23
|
-
*/
|
|
24
|
-
export async function createEnhancedAmmo(options = {}) {
|
|
25
|
-
const { ammo, req, res } = await createTestAmmo(options);
|
|
26
|
-
|
|
27
|
-
// Mock the body parser to avoid actual body parsing
|
|
28
|
-
const mockPayload = options.body || {};
|
|
29
|
-
ammo.payload = mockPayload;
|
|
30
|
-
ammo.method = options.method || 'GET';
|
|
31
|
-
ammo.headers = req.headers;
|
|
32
|
-
ammo.ip = req.socket?.remoteAddress || '127.0.0.1';
|
|
33
|
-
ammo.path = options.url || '/';
|
|
34
|
-
ammo.endpoint = options.url || '/';
|
|
35
|
-
ammo.protocol = options.protocol || 'http';
|
|
36
|
-
ammo.hostname = req.headers?.host || 'localhost';
|
|
37
|
-
ammo.fullURL = `${ammo.protocol}://${ammo.hostname}${ammo.path}`;
|
|
38
|
-
|
|
39
|
-
// Set HTTP method flags
|
|
40
|
-
ammo.GET = ammo.method === 'GET';
|
|
41
|
-
ammo.POST = ammo.method === 'POST';
|
|
42
|
-
ammo.PUT = ammo.method === 'PUT';
|
|
43
|
-
ammo.DELETE = ammo.method === 'DELETE';
|
|
44
|
-
ammo.PATCH = ammo.method === 'PATCH';
|
|
45
|
-
ammo.HEAD = ammo.method === 'HEAD';
|
|
46
|
-
ammo.OPTIONS = ammo.method === 'OPTIONS';
|
|
47
|
-
|
|
48
|
-
return { ammo, req, res };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Create a fresh TargetRegistry for testing
|
|
53
|
-
* @returns {Object} Fresh registry instance
|
|
54
|
-
*/
|
|
55
|
-
export function createTestRegistry() {
|
|
56
|
-
// Create a new registry instance (bypasses singleton)
|
|
57
|
-
return {
|
|
58
|
-
targets: [],
|
|
59
|
-
globalMiddlewares: [],
|
|
60
|
-
addGlobalMiddleware(...middlewares) {
|
|
61
|
-
const validMiddlewares = middlewares.filter(
|
|
62
|
-
(m) => typeof m === 'function'
|
|
63
|
-
);
|
|
64
|
-
this.globalMiddlewares = this.globalMiddlewares.concat(validMiddlewares);
|
|
65
|
-
},
|
|
66
|
-
register(targets) {
|
|
67
|
-
if (Array.isArray(targets)) {
|
|
68
|
-
this.targets = this.targets.concat(targets);
|
|
69
|
-
} else {
|
|
70
|
-
this.targets.push(targets);
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
aim(endpoint) {
|
|
74
|
-
const standardizedEndpoint = endpoint.endsWith('/') && endpoint !== '/'
|
|
75
|
-
? endpoint.slice(0, -1)
|
|
76
|
-
: endpoint;
|
|
77
|
-
|
|
78
|
-
// Exact match
|
|
79
|
-
const exactMatch = this.targets.find(
|
|
80
|
-
(target) => target.getPath() === standardizedEndpoint
|
|
81
|
-
);
|
|
82
|
-
if (exactMatch) {
|
|
83
|
-
return { target: exactMatch, params: {} };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Parameterized route matching
|
|
87
|
-
for (const target of this.targets) {
|
|
88
|
-
const params = this.matchParameterizedRoute(
|
|
89
|
-
target.getPath(),
|
|
90
|
-
standardizedEndpoint
|
|
91
|
-
);
|
|
92
|
-
if (params !== null) {
|
|
93
|
-
return { target, params };
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return null;
|
|
98
|
-
},
|
|
99
|
-
matchParameterizedRoute(pattern, url) {
|
|
100
|
-
if (pattern === '/' && url === '/') return {};
|
|
101
|
-
|
|
102
|
-
const patternSegments = pattern.split('/').filter((s) => s.length > 0);
|
|
103
|
-
const urlSegments = url.split('/').filter((s) => s.length > 0);
|
|
104
|
-
|
|
105
|
-
if (patternSegments.length !== urlSegments.length) return null;
|
|
106
|
-
if (patternSegments.length === 0 && urlSegments.length === 0) return {};
|
|
107
|
-
|
|
108
|
-
const params = {};
|
|
109
|
-
for (let i = 0; i < patternSegments.length; i++) {
|
|
110
|
-
const patternSegment = patternSegments[i];
|
|
111
|
-
const urlSegment = urlSegments[i];
|
|
112
|
-
|
|
113
|
-
if (patternSegment.startsWith(':')) {
|
|
114
|
-
params[patternSegment.slice(1)] = urlSegment;
|
|
115
|
-
} else if (patternSegment !== urlSegment) {
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return params;
|
|
121
|
-
},
|
|
122
|
-
getAllEndpoints(grouped) {
|
|
123
|
-
if (grouped) {
|
|
124
|
-
return this.targets.reduce((acc, target) => {
|
|
125
|
-
const group = target.getPath().split('/')[1];
|
|
126
|
-
if (!acc[group]) acc[group] = [];
|
|
127
|
-
acc[group].push(target.getPath());
|
|
128
|
-
return acc;
|
|
129
|
-
}, {});
|
|
130
|
-
}
|
|
131
|
-
return this.targets.map((target) => target.getPath());
|
|
132
|
-
},
|
|
133
|
-
reset() {
|
|
134
|
-
this.targets = [];
|
|
135
|
-
this.globalMiddlewares = [];
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Create a mock endpoint for testing
|
|
142
|
-
* @param {Object} options - Endpoint options
|
|
143
|
-
* @returns {Object} Mock endpoint object
|
|
144
|
-
*/
|
|
145
|
-
export function createMockEndpoint(options = {}) {
|
|
146
|
-
const path = options.path || '/test';
|
|
147
|
-
const handler = options.handler || vi.fn();
|
|
148
|
-
const middlewares = options.middlewares || [];
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
getPath: () => path,
|
|
152
|
-
getHandler: () => handler,
|
|
153
|
-
getMiddlewares: () => middlewares,
|
|
154
|
-
setPath: vi.fn().mockReturnThis(),
|
|
155
|
-
setHandler: vi.fn().mockReturnThis(),
|
|
156
|
-
setMiddlewares: vi.fn().mockReturnThis(),
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Create a mock middleware function
|
|
162
|
-
* @param {Object} options - Middleware options
|
|
163
|
-
* @returns {Function} Mock middleware
|
|
164
|
-
*/
|
|
165
|
-
export function createMockMiddleware(options = {}) {
|
|
166
|
-
const {
|
|
167
|
-
name = 'mockMiddleware',
|
|
168
|
-
callNext = true,
|
|
169
|
-
delay = 0,
|
|
170
|
-
throwError = null,
|
|
171
|
-
modifyAmmo = null,
|
|
172
|
-
} = options;
|
|
173
|
-
|
|
174
|
-
const middleware = vi.fn(async (ammo, next) => {
|
|
175
|
-
if (delay > 0) {
|
|
176
|
-
await sleep(delay);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (throwError) {
|
|
180
|
-
throw throwError;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (modifyAmmo && typeof modifyAmmo === 'function') {
|
|
184
|
-
modifyAmmo(ammo);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (callNext && next) {
|
|
188
|
-
await next();
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
// Add name for debugging
|
|
193
|
-
Object.defineProperty(middleware, 'name', { value: name });
|
|
194
|
-
|
|
195
|
-
return middleware;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Create a middleware that uses Express-style signature (req, res, next)
|
|
200
|
-
* @param {Object} options - Middleware options
|
|
201
|
-
* @returns {Function} Mock Express-style middleware
|
|
202
|
-
*/
|
|
203
|
-
export function createExpressStyleMiddleware(options = {}) {
|
|
204
|
-
const {
|
|
205
|
-
name = 'expressMiddleware',
|
|
206
|
-
callNext = true,
|
|
207
|
-
delay = 0,
|
|
208
|
-
throwError = null,
|
|
209
|
-
} = options;
|
|
210
|
-
|
|
211
|
-
const middleware = vi.fn(async (req, res, next) => {
|
|
212
|
-
if (delay > 0) {
|
|
213
|
-
await sleep(delay);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (throwError) {
|
|
217
|
-
throw throwError;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (callNext && next) {
|
|
221
|
-
await next();
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
Object.defineProperty(middleware, 'name', { value: name });
|
|
226
|
-
|
|
227
|
-
return middleware;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Sleep utility for async tests
|
|
232
|
-
* @param {number} ms - Milliseconds to sleep
|
|
233
|
-
* @returns {Promise<void>}
|
|
234
|
-
*/
|
|
235
|
-
export function sleep(ms) {
|
|
236
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Wait for a condition to be true
|
|
241
|
-
* @param {Function} condition - Function returning boolean
|
|
242
|
-
* @param {Object} options - Wait options
|
|
243
|
-
* @returns {Promise<void>}
|
|
244
|
-
*/
|
|
245
|
-
export async function waitFor(condition, options = {}) {
|
|
246
|
-
const { timeout = 5000, interval = 50 } = options;
|
|
247
|
-
const startTime = Date.now();
|
|
248
|
-
|
|
249
|
-
while (Date.now() - startTime < timeout) {
|
|
250
|
-
if (await condition()) {
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
await sleep(interval);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
throw new Error(`waitFor: Condition not met within ${timeout}ms`);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Create a mock database connection for testing
|
|
261
|
-
* @param {string} type - Database type (mongodb, redis)
|
|
262
|
-
* @returns {Object} Mock database connection
|
|
263
|
-
*/
|
|
264
|
-
export function createMockDbConnection(type = 'mongodb') {
|
|
265
|
-
const mockConnection = {
|
|
266
|
-
type,
|
|
267
|
-
isConnected: true,
|
|
268
|
-
close: vi.fn().mockResolvedValue(undefined),
|
|
269
|
-
query: vi.fn().mockResolvedValue([]),
|
|
270
|
-
insert: vi.fn().mockResolvedValue({ insertedId: 'mock-id' }),
|
|
271
|
-
update: vi.fn().mockResolvedValue({ modifiedCount: 1 }),
|
|
272
|
-
delete: vi.fn().mockResolvedValue({ deletedCount: 1 }),
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
if (type === 'mongodb') {
|
|
276
|
-
mockConnection.collection = vi.fn(() => ({
|
|
277
|
-
find: vi.fn().mockReturnValue({
|
|
278
|
-
toArray: vi.fn().mockResolvedValue([]),
|
|
279
|
-
}),
|
|
280
|
-
findOne: vi.fn().mockResolvedValue(null),
|
|
281
|
-
insertOne: vi.fn().mockResolvedValue({ insertedId: 'mock-id' }),
|
|
282
|
-
updateOne: vi.fn().mockResolvedValue({ modifiedCount: 1 }),
|
|
283
|
-
deleteOne: vi.fn().mockResolvedValue({ deletedCount: 1 }),
|
|
284
|
-
}));
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (type === 'redis') {
|
|
288
|
-
mockConnection.get = vi.fn().mockResolvedValue(null);
|
|
289
|
-
mockConnection.set = vi.fn().mockResolvedValue('OK');
|
|
290
|
-
mockConnection.del = vi.fn().mockResolvedValue(1);
|
|
291
|
-
mockConnection.exists = vi.fn().mockResolvedValue(0);
|
|
292
|
-
mockConnection.expire = vi.fn().mockResolvedValue(1);
|
|
293
|
-
mockConnection.ttl = vi.fn().mockResolvedValue(-1);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
return mockConnection;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Create a mock file object for upload tests
|
|
301
|
-
* @param {Object} options - File options
|
|
302
|
-
* @returns {Object} Mock file object
|
|
303
|
-
*/
|
|
304
|
-
export function createMockFile(options = {}) {
|
|
305
|
-
return {
|
|
306
|
-
fieldName: options.fieldName || 'file',
|
|
307
|
-
originalFilename: options.filename || 'test.txt',
|
|
308
|
-
filepath: options.filepath || '/tmp/upload_test.txt',
|
|
309
|
-
mimetype: options.mimetype || 'text/plain',
|
|
310
|
-
size: options.size || 1024,
|
|
311
|
-
newFilename: options.newFilename || 'upload_test.txt',
|
|
312
|
-
hash: options.hash || null,
|
|
313
|
-
lastModifiedDate: options.lastModifiedDate || new Date(),
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Create a mock storage for rate limiting tests
|
|
319
|
-
* @returns {Object} Mock storage object
|
|
320
|
-
*/
|
|
321
|
-
export function createMockStorage() {
|
|
322
|
-
const store = new Map();
|
|
323
|
-
|
|
324
|
-
return {
|
|
325
|
-
get: vi.fn((key) => store.get(key)),
|
|
326
|
-
set: vi.fn((key, value, ttl) => {
|
|
327
|
-
store.set(key, value);
|
|
328
|
-
return true;
|
|
329
|
-
}),
|
|
330
|
-
increment: vi.fn((key, amount = 1) => {
|
|
331
|
-
const current = store.get(key) || 0;
|
|
332
|
-
const newValue = current + amount;
|
|
333
|
-
store.set(key, newValue);
|
|
334
|
-
return newValue;
|
|
335
|
-
}),
|
|
336
|
-
decrement: vi.fn((key, amount = 1) => {
|
|
337
|
-
const current = store.get(key) || 0;
|
|
338
|
-
const newValue = Math.max(0, current - amount);
|
|
339
|
-
store.set(key, newValue);
|
|
340
|
-
return newValue;
|
|
341
|
-
}),
|
|
342
|
-
delete: vi.fn((key) => store.delete(key)),
|
|
343
|
-
has: vi.fn((key) => store.has(key)),
|
|
344
|
-
clear: vi.fn(() => store.clear()),
|
|
345
|
-
_store: store, // Expose for testing
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* Assert response has expected status and optional body
|
|
351
|
-
* @param {Object} res - Mock response object
|
|
352
|
-
* @param {number} expectedStatus - Expected status code
|
|
353
|
-
* @param {any} expectedBody - Optional expected body (string or object)
|
|
354
|
-
*/
|
|
355
|
-
export function assertResponse(res, expectedStatus, expectedBody) {
|
|
356
|
-
if (expectedStatus !== undefined) {
|
|
357
|
-
if (res.statusCode !== expectedStatus) {
|
|
358
|
-
throw new Error(
|
|
359
|
-
`Expected status ${expectedStatus}, got ${res.statusCode}. Body: ${res.getBody()}`
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (expectedBody !== undefined) {
|
|
365
|
-
const body = res.getBody();
|
|
366
|
-
if (typeof expectedBody === 'object') {
|
|
367
|
-
const jsonBody = res.getJsonBody();
|
|
368
|
-
if (JSON.stringify(jsonBody) !== JSON.stringify(expectedBody)) {
|
|
369
|
-
throw new Error(
|
|
370
|
-
`Body mismatch. Expected: ${JSON.stringify(expectedBody)}, Got: ${JSON.stringify(jsonBody)}`
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
|
-
} else if (body !== expectedBody) {
|
|
374
|
-
throw new Error(`Body mismatch. Expected: ${expectedBody}, Got: ${body}`);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Mock console methods for cleaner test output
|
|
381
|
-
* @returns {Object} Object with restore function
|
|
382
|
-
*/
|
|
383
|
-
export function mockConsole() {
|
|
384
|
-
const originalConsole = {
|
|
385
|
-
log: console.log,
|
|
386
|
-
error: console.error,
|
|
387
|
-
warn: console.warn,
|
|
388
|
-
info: console.info,
|
|
389
|
-
};
|
|
390
|
-
|
|
391
|
-
console.log = vi.fn();
|
|
392
|
-
console.error = vi.fn();
|
|
393
|
-
console.warn = vi.fn();
|
|
394
|
-
console.info = vi.fn();
|
|
395
|
-
|
|
396
|
-
return {
|
|
397
|
-
restore: () => {
|
|
398
|
-
console.log = originalConsole.log;
|
|
399
|
-
console.error = originalConsole.error;
|
|
400
|
-
console.warn = originalConsole.warn;
|
|
401
|
-
console.info = originalConsole.info;
|
|
402
|
-
},
|
|
403
|
-
mocks: {
|
|
404
|
-
log: console.log,
|
|
405
|
-
error: console.error,
|
|
406
|
-
warn: console.warn,
|
|
407
|
-
info: console.info,
|
|
408
|
-
},
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Capture all response data for assertion
|
|
414
|
-
* @param {Object} res - Mock response object
|
|
415
|
-
* @returns {Object} Captured response data
|
|
416
|
-
*/
|
|
417
|
-
export function captureResponse(res) {
|
|
418
|
-
return {
|
|
419
|
-
statusCode: res.statusCode,
|
|
420
|
-
statusMessage: res.statusMessage,
|
|
421
|
-
headers: { ...res.headers },
|
|
422
|
-
body: res.getBody(),
|
|
423
|
-
jsonBody: res.getJsonBody(),
|
|
424
|
-
headersSent: res.headersSent,
|
|
425
|
-
finished: res.finished,
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
export default {
|
|
430
|
-
createTestAmmo,
|
|
431
|
-
createEnhancedAmmo,
|
|
432
|
-
createTestRegistry,
|
|
433
|
-
createMockEndpoint,
|
|
434
|
-
createMockMiddleware,
|
|
435
|
-
createExpressStyleMiddleware,
|
|
436
|
-
sleep,
|
|
437
|
-
waitFor,
|
|
438
|
-
createMockDbConnection,
|
|
439
|
-
createMockFile,
|
|
440
|
-
createMockStorage,
|
|
441
|
-
assertResponse,
|
|
442
|
-
mockConsole,
|
|
443
|
-
captureResponse,
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
|
package/tests/setup.test.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Smoke test to verify Vitest setup and test helpers work correctly
|
|
3
|
-
*/
|
|
4
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
5
|
-
import {
|
|
6
|
-
createMockRequest,
|
|
7
|
-
createMockResponse,
|
|
8
|
-
createMockPair,
|
|
9
|
-
createJsonRequest,
|
|
10
|
-
} from './helpers/mock-http.js';
|
|
11
|
-
import { createMockStorage, sleep } from './helpers/test-utils.js';
|
|
12
|
-
|
|
13
|
-
describe('Test Infrastructure Setup', () => {
|
|
14
|
-
describe('Vitest Configuration', () => {
|
|
15
|
-
it('should have vitest globals available', () => {
|
|
16
|
-
expect(describe).toBeDefined();
|
|
17
|
-
expect(it).toBeDefined();
|
|
18
|
-
expect(expect).toBeDefined();
|
|
19
|
-
expect(vi).toBeDefined();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should support async/await', async () => {
|
|
23
|
-
const result = await Promise.resolve(42);
|
|
24
|
-
expect(result).toBe(42);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('should support vi.fn() mocking', () => {
|
|
28
|
-
const mockFn = vi.fn(() => 'mocked');
|
|
29
|
-
expect(mockFn()).toBe('mocked');
|
|
30
|
-
expect(mockFn).toHaveBeenCalledTimes(1);
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe('Mock HTTP Request', () => {
|
|
35
|
-
it('should create a mock request with defaults', () => {
|
|
36
|
-
const req = createMockRequest();
|
|
37
|
-
|
|
38
|
-
expect(req.method).toBe('GET');
|
|
39
|
-
expect(req.url).toBe('/');
|
|
40
|
-
expect(req.headers).toBeDefined();
|
|
41
|
-
expect(req.socket).toBeDefined();
|
|
42
|
-
expect(req.socket.remoteAddress).toBe('127.0.0.1');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should create a mock request with custom options', () => {
|
|
46
|
-
const req = createMockRequest({
|
|
47
|
-
method: 'POST',
|
|
48
|
-
url: '/api/users',
|
|
49
|
-
headers: { 'content-type': 'application/json' },
|
|
50
|
-
ip: '192.168.1.1',
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
expect(req.method).toBe('POST');
|
|
54
|
-
expect(req.url).toBe('/api/users');
|
|
55
|
-
expect(req.headers['content-type']).toBe('application/json');
|
|
56
|
-
expect(req.socket.remoteAddress).toBe('192.168.1.1');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('should create a JSON request with proper headers', () => {
|
|
60
|
-
const req = createJsonRequest({ method: 'POST', url: '/api/data' });
|
|
61
|
-
|
|
62
|
-
expect(req.headers['content-type']).toBe('application/json');
|
|
63
|
-
expect(req.headers['accept']).toBe('application/json');
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
describe('Mock HTTP Response', () => {
|
|
68
|
-
it('should create a mock response with defaults', () => {
|
|
69
|
-
const res = createMockResponse();
|
|
70
|
-
|
|
71
|
-
expect(res.statusCode).toBe(200);
|
|
72
|
-
expect(res.headers).toEqual({});
|
|
73
|
-
expect(res.headersSent).toBe(false);
|
|
74
|
-
expect(res.finished).toBe(false);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should support writeHead', () => {
|
|
78
|
-
const res = createMockResponse();
|
|
79
|
-
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
80
|
-
|
|
81
|
-
expect(res.statusCode).toBe(201);
|
|
82
|
-
expect(res.headers['content-type']).toBe('application/json');
|
|
83
|
-
expect(res.headersSent).toBe(true);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should support write and end', () => {
|
|
87
|
-
const res = createMockResponse();
|
|
88
|
-
res.write('Hello');
|
|
89
|
-
res.write(' World');
|
|
90
|
-
res.end();
|
|
91
|
-
|
|
92
|
-
expect(res.getBody()).toBe('Hello World');
|
|
93
|
-
expect(res.finished).toBe(true);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should parse JSON body', () => {
|
|
97
|
-
const res = createMockResponse();
|
|
98
|
-
res.write(JSON.stringify({ message: 'success' }));
|
|
99
|
-
res.end();
|
|
100
|
-
|
|
101
|
-
expect(res.getJsonBody()).toEqual({ message: 'success' });
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe('Mock Request/Response Pair', () => {
|
|
106
|
-
it('should create paired req/res objects', () => {
|
|
107
|
-
const { req, res } = createMockPair({ method: 'DELETE', url: '/item/1' });
|
|
108
|
-
|
|
109
|
-
expect(req.method).toBe('DELETE');
|
|
110
|
-
expect(req.url).toBe('/item/1');
|
|
111
|
-
expect(res).toBeDefined();
|
|
112
|
-
expect(res.statusCode).toBe(200);
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
describe('Mock Storage', () => {
|
|
117
|
-
it('should support basic operations', () => {
|
|
118
|
-
const storage = createMockStorage();
|
|
119
|
-
|
|
120
|
-
storage.set('key1', 'value1');
|
|
121
|
-
expect(storage.get('key1')).toBe('value1');
|
|
122
|
-
|
|
123
|
-
storage.delete('key1');
|
|
124
|
-
expect(storage.get('key1')).toBeUndefined();
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should support increment/decrement', () => {
|
|
128
|
-
const storage = createMockStorage();
|
|
129
|
-
|
|
130
|
-
storage.set('counter', 0);
|
|
131
|
-
expect(storage.increment('counter')).toBe(1);
|
|
132
|
-
expect(storage.increment('counter', 5)).toBe(6);
|
|
133
|
-
expect(storage.decrement('counter', 2)).toBe(4);
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
describe('Utility Functions', () => {
|
|
138
|
-
it('should support sleep', async () => {
|
|
139
|
-
const start = Date.now();
|
|
140
|
-
await sleep(50);
|
|
141
|
-
const elapsed = Date.now() - start;
|
|
142
|
-
|
|
143
|
-
expect(elapsed).toBeGreaterThanOrEqual(45);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
|
package/vitest.config.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
// Use ESM modules
|
|
6
|
-
environment: 'node',
|
|
7
|
-
|
|
8
|
-
// Test file patterns
|
|
9
|
-
include: ['tests/**/*.test.js'],
|
|
10
|
-
|
|
11
|
-
// Global test timeout (ms)
|
|
12
|
-
testTimeout: 10000,
|
|
13
|
-
|
|
14
|
-
// Enable globals (describe, it, expect, etc.)
|
|
15
|
-
globals: true,
|
|
16
|
-
|
|
17
|
-
// Coverage configuration
|
|
18
|
-
coverage: {
|
|
19
|
-
provider: 'v8',
|
|
20
|
-
reporter: ['text', 'json', 'html'],
|
|
21
|
-
include: [
|
|
22
|
-
'server/**/*.js',
|
|
23
|
-
'database/**/*.js',
|
|
24
|
-
'rate-limit/**/*.js',
|
|
25
|
-
'utils/**/*.js',
|
|
26
|
-
],
|
|
27
|
-
exclude: [
|
|
28
|
-
'node_modules/**',
|
|
29
|
-
'tests/**',
|
|
30
|
-
'example/**',
|
|
31
|
-
'docs/**',
|
|
32
|
-
],
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
// Reporter options
|
|
36
|
-
reporters: ['verbose'],
|
|
37
|
-
|
|
38
|
-
// Isolation mode - each test file runs in its own context
|
|
39
|
-
isolate: true,
|
|
40
|
-
|
|
41
|
-
// Retry failed tests
|
|
42
|
-
retry: 0,
|
|
43
|
-
|
|
44
|
-
// Setup files to run before tests
|
|
45
|
-
setupFiles: [],
|
|
46
|
-
|
|
47
|
-
// Dependencies to inline (necessary for some ESM modules)
|
|
48
|
-
deps: {
|
|
49
|
-
interopDefault: true,
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
|