balda-js 0.0.1 → 0.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.
Files changed (65) hide show
  1. package/package.json +1 -6
  2. package/.husky/pre-commit +0 -19
  3. package/.nvmrc +0 -1
  4. package/docs/README.md +0 -135
  5. package/docs/blog/authors.yml +0 -6
  6. package/docs/blog/tags.yml +0 -4
  7. package/docs/cli.md +0 -109
  8. package/docs/docs/core-concepts/controllers.md +0 -393
  9. package/docs/docs/core-concepts/middleware.md +0 -302
  10. package/docs/docs/core-concepts/request-response.md +0 -486
  11. package/docs/docs/core-concepts/routing.md +0 -388
  12. package/docs/docs/core-concepts/server.md +0 -332
  13. package/docs/docs/cron/overview.md +0 -70
  14. package/docs/docs/examples/rest-api.md +0 -595
  15. package/docs/docs/getting-started/configuration.md +0 -168
  16. package/docs/docs/getting-started/installation.md +0 -125
  17. package/docs/docs/getting-started/quick-start.md +0 -273
  18. package/docs/docs/intro.md +0 -46
  19. package/docs/docs/plugins/cookie.md +0 -424
  20. package/docs/docs/plugins/cors.md +0 -295
  21. package/docs/docs/plugins/file.md +0 -382
  22. package/docs/docs/plugins/helmet.md +0 -388
  23. package/docs/docs/plugins/json.md +0 -338
  24. package/docs/docs/plugins/log.md +0 -592
  25. package/docs/docs/plugins/overview.md +0 -390
  26. package/docs/docs/plugins/rate-limiter.md +0 -347
  27. package/docs/docs/plugins/static.md +0 -352
  28. package/docs/docs/plugins/swagger.md +0 -411
  29. package/docs/docs/plugins/urlencoded.md +0 -76
  30. package/docs/docs/testing/examples.md +0 -384
  31. package/docs/docs/testing/mock-server.md +0 -311
  32. package/docs/docs/testing/overview.md +0 -76
  33. package/docs/docusaurus.config.ts +0 -144
  34. package/docs/intro.md +0 -78
  35. package/docs/package.json +0 -46
  36. package/docs/sidebars.ts +0 -72
  37. package/docs/static/.nojekyll +0 -0
  38. package/docs/static/img/docusaurus-social-card.jpg +0 -0
  39. package/docs/static/img/docusaurus.png +0 -0
  40. package/docs/static/img/favicon.ico +0 -0
  41. package/docs/static/img/logo.svg +0 -1
  42. package/docs/static/img/undraw_docusaurus_mountain.svg +0 -37
  43. package/docs/static/img/undraw_docusaurus_react.svg +0 -170
  44. package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
  45. package/docs/tsconfig.json +0 -8
  46. package/speed_test.sh +0 -3
  47. package/test/benchmark/index.ts +0 -17
  48. package/test/cli/cli.ts +0 -7
  49. package/test/commands/test.ts +0 -42
  50. package/test/controllers/file_upload.ts +0 -29
  51. package/test/controllers/urlencoded.ts +0 -13
  52. package/test/controllers/users.ts +0 -111
  53. package/test/cron/index.ts +0 -6
  54. package/test/cron/test_cron.ts +0 -8
  55. package/test/cron/test_cron_imported.ts +0 -8
  56. package/test/native_env.ts +0 -16
  57. package/test/resources/test.txt +0 -1
  58. package/test/server/index.ts +0 -3
  59. package/test/server/instance.ts +0 -63
  60. package/test/suite/upload.test.ts +0 -23
  61. package/test/suite/urlencoded.test.ts +0 -23
  62. package/test/suite/users.test.ts +0 -76
  63. package/todo.md +0 -9
  64. package/tsconfig.json +0 -24
  65. package/vitest.config.ts +0 -17
@@ -1,384 +0,0 @@
1
- # Testing Examples
2
-
3
- This guide provides practical examples of testing with Balda.js MockServer, covering common scenarios and patterns.
4
-
5
- ## Basic API Testing
6
-
7
- ### Simple GET Request
8
- ```typescript
9
- import { describe, it, expect } from "vitest";
10
- import { mockServer } from "test/server/instance";
11
-
12
- describe("Basic API Tests", () => {
13
- it("GET /users returns user list", async () => {
14
- const res = await mockServer.get("/users");
15
-
16
- expect(res.statusCode()).toBe(200);
17
- expect(Array.isArray(res.body())).toBe(true);
18
- expect(res.body().length).toBeGreaterThan(0);
19
- });
20
- });
21
- ```
22
-
23
- ### GET with Query Parameters
24
- ```typescript
25
- it("GET /users with pagination", async () => {
26
- const res = await mockServer.get("/users", {
27
- query: { page: "1", limit: "5" }
28
- });
29
-
30
- expect(res.statusCode()).toBe(200);
31
- expect(res.body().length).toBeLessThanOrEqual(5);
32
- });
33
- ```
34
-
35
- ### GET with Headers
36
- ```typescript
37
- it("GET /protected with authorization", async () => {
38
- const res = await mockServer.get("/protected", {
39
- headers: { "Authorization": "Bearer token123" }
40
- });
41
-
42
- expect(res.statusCode()).toBe(200);
43
- });
44
- ```
45
-
46
- ## POST Request Testing
47
-
48
- ### JSON Body
49
- ```typescript
50
- it("POST /users creates new user", async () => {
51
- const newUser = {
52
- name: "John Doe",
53
- email: "john@example.com",
54
- age: 30
55
- };
56
-
57
- const res = await mockServer.post("/users", { body: newUser });
58
-
59
- expect(res.statusCode()).toBe(201);
60
- expect(res.assertBodyDeepEqual(newUser));
61
- });
62
- ```
63
-
64
- ### Form Data (URL Encoded)
65
- ```typescript
66
- it("POST /users with form data", async () => {
67
- const res = await mockServer.post("/users", {
68
- urlencoded: {
69
- name: "Jane Doe",
70
- email: "jane@example.com",
71
- age: "25"
72
- }
73
- });
74
-
75
- expect(res.statusCode()).toBe(201);
76
- expect(res.assertBodySubset({ name: "Jane Doe" }));
77
- });
78
- ```
79
-
80
- ### File Upload
81
- ```typescript
82
- it("POST /upload handles file upload", async () => {
83
- const formData = new FormData();
84
- const fileContent = new Uint8Array([1, 2, 3, 4, 5]);
85
- formData.append("file", new Blob([fileContent]), "test.txt");
86
-
87
- const res = await mockServer.post("/upload", { formData });
88
-
89
- expect(res.statusCode()).toBe(200);
90
- expect(res.body()).toEqual({
91
- originalName: "test.txt",
92
- filename: "file",
93
- size: 5,
94
- mimetype: "application/octet-stream"
95
- });
96
- });
97
- ```
98
-
99
- ## Error Handling Examples
100
-
101
- ### 404 Not Found
102
- ```typescript
103
- it("GET /users/999 returns 404", async () => {
104
- const res = await mockServer.get("/users/999");
105
-
106
- expect(res.statusCode()).toBe(404);
107
- expect(res.assertBodyDeepEqual({ error: "User not found" }));
108
- });
109
- ```
110
-
111
- ### 409 Conflict
112
- ```typescript
113
- it("POST /users returns 409 for existing user", async () => {
114
- const existingUser = {
115
- id: 1,
116
- name: "John Doe",
117
- email: "john.doe@example.com",
118
- age: 20
119
- };
120
-
121
- const res = await mockServer.post("/users", { body: existingUser });
122
-
123
- expect(res.statusCode()).toBe(409);
124
- expect(res.assertBodyDeepEqual({ error: "User already exists" }));
125
- });
126
- ```
127
-
128
- ### Server Error
129
- ```typescript
130
- it("GET /users with shouldFail=true returns 500", async () => {
131
- const res = await mockServer.get("/users", {
132
- query: { shouldFail: "true" }
133
- });
134
-
135
- expect(res.statusCode()).toBe(500);
136
- });
137
- ```
138
-
139
- ## CRUD Operations Testing
140
-
141
- ### Complete CRUD Test Suite
142
- ```typescript
143
- describe("User CRUD Operations", () => {
144
- it("creates a new user", async () => {
145
- const newUser = { id: 3, name: "New User", email: "new@example.com", age: 30 };
146
-
147
- const res = await mockServer.post("/users", { body: newUser });
148
-
149
- expect(res.statusCode()).toBe(201);
150
- expect(res.assertBodyDeepEqual(newUser));
151
- });
152
-
153
- it("reads a specific user", async () => {
154
- const res = await mockServer.get("/users/1");
155
-
156
- expect(res.statusCode()).toBe(200);
157
- expect(res.assertBodySubset({ id: 1 }));
158
- });
159
-
160
- it("updates a user", async () => {
161
- const res = await mockServer.patch("/users/1", {
162
- body: { name: "Updated Name" }
163
- });
164
-
165
- expect(res.statusCode()).toBe(200);
166
- expect(res.assertBodySubset({ id: 1, name: "Updated Name" }));
167
- });
168
-
169
- it("deletes a user", async () => {
170
- const res = await mockServer.delete("/users/1");
171
-
172
- expect(res.statusCode()).toBe(204);
173
- });
174
- });
175
- ```
176
-
177
- ## Authentication Testing
178
-
179
- ### Protected Routes
180
- ```typescript
181
- describe("Authentication", () => {
182
- it("accesses protected route with valid token", async () => {
183
- const res = await mockServer.get("/protected", {
184
- headers: { "Authorization": "Bearer valid-token" }
185
- });
186
-
187
- expect(res.statusCode()).toBe(200);
188
- });
189
-
190
- it("rejects access without token", async () => {
191
- const res = await mockServer.get("/protected");
192
-
193
- expect(res.statusCode()).toBe(401);
194
- });
195
-
196
- it("rejects access with invalid token", async () => {
197
- const res = await mockServer.get("/protected", {
198
- headers: { "Authorization": "Bearer invalid-token" }
199
- });
200
-
201
- expect(res.statusCode()).toBe(401);
202
- });
203
- });
204
- ```
205
-
206
- ## Cookie Testing
207
-
208
- ### Setting and Reading Cookies
209
- ```typescript
210
- describe("Cookie Handling", () => {
211
- it("sets session cookie on login", async () => {
212
- const res = await mockServer.post("/login", {
213
- body: { username: "user", password: "pass" }
214
- });
215
-
216
- expect(res.statusCode()).toBe(200);
217
- expect(res.headers()["set-cookie"]).toContain("sessionId");
218
- });
219
-
220
- it("uses existing session cookie", async () => {
221
- const res = await mockServer.get("/profile", {
222
- cookies: { sessionId: "valid-session" }
223
- });
224
-
225
- expect(res.statusCode()).toBe(200);
226
- });
227
- });
228
- ```
229
-
230
- ## Advanced Testing Patterns
231
-
232
- ### Testing with Custom Headers
233
- ```typescript
234
- it("handles custom headers", async () => {
235
- const res = await mockServer.get("/api/data", {
236
- headers: {
237
- "X-API-Key": "secret-key",
238
- "X-Client-Version": "1.0.0",
239
- "Content-Type": "application/json"
240
- }
241
- });
242
-
243
- expect(res.statusCode()).toBe(200);
244
- });
245
- ```
246
-
247
- ### Testing with IP Address
248
- ```typescript
249
- it("handles IP-based logic", async () => {
250
- const res = await mockServer.get("/location", {
251
- ip: "192.168.1.100"
252
- });
253
-
254
- expect(res.statusCode()).toBe(200);
255
- expect(res.body()).toHaveProperty("ip", "192.168.1.100");
256
- });
257
- ```
258
-
259
- ### Testing Query Parameters
260
- ```typescript
261
- it("handles complex query parameters", async () => {
262
- const res = await mockServer.get("/search", {
263
- query: {
264
- q: "search term",
265
- category: "technology",
266
- sort: "date",
267
- order: "desc",
268
- page: "1",
269
- limit: "20"
270
- }
271
- });
272
-
273
- expect(res.statusCode()).toBe(200);
274
- expect(res.body()).toHaveProperty("results");
275
- });
276
- ```
277
-
278
- ## Testing Middleware
279
-
280
- ### Rate Limiting
281
- ```typescript
282
- describe("Rate Limiting", () => {
283
- it("allows requests within limit", async () => {
284
- const res = await mockServer.get("/api/limited");
285
- expect(res.statusCode()).toBe(200);
286
- });
287
-
288
- it("blocks requests over limit", async () => {
289
- // Simulate multiple requests
290
- for (let i = 0; i < 10; i++) {
291
- await mockServer.get("/api/limited");
292
- }
293
-
294
- const res = await mockServer.get("/api/limited");
295
- expect(res.statusCode()).toBe(429);
296
- });
297
- });
298
- ```
299
-
300
- ### CORS Testing
301
- ```typescript
302
- describe("CORS", () => {
303
- it("handles preflight OPTIONS request", async () => {
304
- const res = await mockServer.request("OPTIONS", "/api/data", {
305
- headers: {
306
- "Origin": "https://example.com",
307
- "Access-Control-Request-Method": "POST"
308
- }
309
- });
310
-
311
- expect(res.statusCode()).toBe(200);
312
- expect(res.headers()["access-control-allow-origin"]).toBe("*");
313
- });
314
- });
315
- ```
316
-
317
- ## Performance Testing
318
-
319
- ### Load Testing with MockServer
320
- ```typescript
321
- describe("Performance", () => {
322
- it("handles multiple concurrent requests", async () => {
323
- const promises = Array.from({ length: 100 }, () =>
324
- mockServer.get("/api/data")
325
- );
326
-
327
- const results = await Promise.all(promises);
328
-
329
- results.forEach(res => {
330
- expect(res.statusCode()).toBe(200);
331
- });
332
- });
333
- });
334
- ```
335
-
336
- ## Best Practices
337
-
338
- ### Test Organization
339
- ```typescript
340
- describe("User API", () => {
341
- describe("GET /users", () => {
342
- it("returns all users", async () => {
343
- // Test implementation
344
- });
345
-
346
- it("supports pagination", async () => {
347
- // Test implementation
348
- });
349
- });
350
-
351
- describe("POST /users", () => {
352
- it("creates new user", async () => {
353
- // Test implementation
354
- });
355
-
356
- it("validates required fields", async () => {
357
- // Test implementation
358
- });
359
- });
360
- });
361
- ```
362
-
363
- ### Type Safety
364
- ```typescript
365
- interface User {
366
- id: number;
367
- name: string;
368
- email: string;
369
- age: number;
370
- }
371
-
372
- describe("Type-safe testing", () => {
373
- it("returns properly typed user data", async () => {
374
- const res = await mockServer.get<User[]>("/users");
375
- const users = res.body() as User[];
376
-
377
- expect(users[0]).toHaveProperty("id");
378
- expect(users[0]).toHaveProperty("name");
379
- expect(users[0]).toHaveProperty("email");
380
- });
381
- });
382
- ```
383
-
384
- These examples demonstrate the flexibility and power of MockServer for comprehensive API testing in Balda.js applications.
@@ -1,311 +0,0 @@
1
- # MockServer Testing
2
-
3
- The MockServer is Balda.js's powerful testing utility that allows you to test HTTP endpoints without starting a real server. This enables fast, isolated testing of your controllers and middleware.
4
-
5
- ## Overview
6
-
7
- MockServer simulates HTTP requests by:
8
- - Executing the complete middleware chain
9
- - Running route handlers with mocked request/response objects
10
- - Providing realistic testing environment without network overhead
11
- - Supporting all HTTP methods and content types
12
-
13
- ## Basic Usage
14
-
15
- ```typescript
16
- import { describe, it, expect } from "vitest";
17
- import { mockServer } from "test/server/instance";
18
-
19
- describe("API Tests", () => {
20
- it("GET /users returns all users", async () => {
21
- const res = await mockServer.get("/users");
22
- expect(res.statusCode()).toBe(200);
23
- expect(Array.isArray(res.body())).toBe(true);
24
- });
25
- });
26
- ```
27
-
28
- ## HTTP Methods
29
-
30
- MockServer provides methods for all HTTP verbs:
31
-
32
- ### GET Requests
33
- ```typescript
34
- // Simple GET request
35
- const res = await mockServer.get("/users");
36
-
37
- // GET with query parameters
38
- const res = await mockServer.get("/users", {
39
- query: { page: "1", limit: "10" }
40
- });
41
-
42
- // GET with headers
43
- const res = await mockServer.get("/users", {
44
- headers: { "Authorization": "Bearer token123" }
45
- });
46
- ```
47
-
48
- ### POST Requests
49
- ```typescript
50
- // POST with JSON body
51
- const res = await mockServer.post("/users", {
52
- body: { name: "John", email: "john@example.com" }
53
- });
54
-
55
- // POST with form data
56
- const res = await mockServer.post("/users", {
57
- urlencoded: { name: "John", email: "john@example.com" }
58
- });
59
-
60
- // POST with file upload
61
- const formData = new FormData();
62
- formData.append("file", new Blob(["content"]), "test.txt");
63
- const res = await mockServer.post("/upload", { formData });
64
- ```
65
-
66
- ### Other HTTP Methods
67
- ```typescript
68
- // PUT request
69
- const res = await mockServer.put("/users/1", {
70
- body: { name: "Updated Name" }
71
- });
72
-
73
- // PATCH request
74
- const res = await mockServer.patch("/users/1", {
75
- body: { name: "Patched Name" }
76
- });
77
-
78
- // DELETE request
79
- const res = await mockServer.delete("/users/1");
80
- ```
81
-
82
- ## Request Options
83
-
84
- MockServer supports comprehensive request configuration:
85
-
86
- ```typescript
87
- interface MockServerOptions {
88
- headers?: Record<string, string>;
89
- query?: Record<string, string>;
90
- cookies?: Record<string, string>;
91
- ip?: string;
92
- body?: any;
93
- formData?: FormData;
94
- urlencoded?: Record<string, string>;
95
- }
96
- ```
97
-
98
- ### Headers
99
- ```typescript
100
- const res = await mockServer.get("/protected", {
101
- headers: {
102
- "Authorization": "Bearer token123",
103
- "Content-Type": "application/json"
104
- }
105
- });
106
- ```
107
-
108
- ### Query Parameters
109
- ```typescript
110
- const res = await mockServer.get("/search", {
111
- query: {
112
- q: "search term",
113
- page: "1",
114
- limit: "20"
115
- }
116
- });
117
- ```
118
-
119
- ### Cookies
120
- ```typescript
121
- const res = await mockServer.get("/profile", {
122
- cookies: {
123
- sessionId: "abc123",
124
- userId: "456"
125
- }
126
- });
127
- ```
128
-
129
- ### IP Address
130
- ```typescript
131
- const res = await mockServer.get("/location", {
132
- ip: "192.168.1.1"
133
- });
134
- ```
135
-
136
- ## Response Assertions
137
-
138
- MockResponse provides powerful assertion methods:
139
-
140
- ### Status Code Assertions
141
- ```typescript
142
- const res = await mockServer.get("/users");
143
- expect(res.statusCode()).toBe(200);
144
- expect(res.assertStatus(200)); // Alternative syntax
145
- ```
146
-
147
- ### Body Assertions
148
- ```typescript
149
- // Exact body match
150
- expect(res.assertBodyDeepEqual({ id: 1, name: "John" }));
151
-
152
- // Partial body match
153
- expect(res.assertBodySubset({ name: "John" }));
154
-
155
- // Get body content
156
- const body = res.body();
157
- expect(body.name).toBe("John");
158
- ```
159
-
160
- ### Complete Example
161
- ```typescript
162
- describe("User API", () => {
163
- it("creates a new user", async () => {
164
- const newUser = {
165
- name: "Jane Doe",
166
- email: "jane@example.com",
167
- age: 25
168
- };
169
-
170
- const res = await mockServer.post("/users", { body: newUser });
171
-
172
- expect(res.assertStatus(201));
173
- expect(res.assertBodyDeepEqual(newUser));
174
- });
175
-
176
- it("returns 404 for non-existent user", async () => {
177
- const res = await mockServer.get("/users/999");
178
-
179
- expect(res.assertStatus(404));
180
- expect(res.assertBodyDeepEqual({ error: "User not found" }));
181
- });
182
- });
183
- ```
184
-
185
- ## File Upload Testing
186
-
187
- MockServer supports file upload testing with FormData:
188
-
189
- ```typescript
190
- describe("File Upload", () => {
191
- it("uploads a file successfully", async () => {
192
- const formData = new FormData();
193
- const fileContent = new Uint8Array([1, 2, 3, 4, 5]);
194
- formData.append("file", new Blob([fileContent]), "test.txt");
195
-
196
- const res = await mockServer.post("/upload", { formData });
197
-
198
- expect(res.assertStatus(200));
199
- expect(res.body()).toEqual({
200
- originalName: "test.txt",
201
- filename: "file",
202
- size: 5,
203
- mimetype: "application/octet-stream"
204
- });
205
- });
206
- });
207
- ```
208
-
209
- ## Error Handling
210
-
211
- MockServer properly handles and reports errors:
212
-
213
- ```typescript
214
- describe("Error Handling", () => {
215
- it("handles server errors gracefully", async () => {
216
- const res = await mockServer.get("/users", {
217
- query: { shouldFail: "true" }
218
- });
219
-
220
- expect(res.assertStatus(500));
221
- expect(res.body()).toHaveProperty("error");
222
- });
223
- });
224
- ```
225
-
226
- ## Best Practices
227
-
228
- ### 1. Test Isolation
229
- ```typescript
230
- describe("User Management", () => {
231
- // Each test should be independent
232
- it("creates user", async () => {
233
- // Test implementation
234
- });
235
-
236
- it("updates user", async () => {
237
- // Test implementation - doesn't depend on previous test
238
- });
239
- });
240
- ```
241
-
242
- ### 2. Descriptive Test Names
243
- ```typescript
244
- // Good
245
- it("POST /users returns 409 when user already exists", async () => {
246
- // Test implementation
247
- });
248
-
249
- // Avoid
250
- it("test user creation", async () => {
251
- // Test implementation
252
- });
253
- ```
254
-
255
- ### 3. Use TypeScript
256
- ```typescript
257
- interface UserResponse {
258
- id: number;
259
- name: string;
260
- email: string;
261
- }
262
-
263
- const res = await mockServer.get<UserResponse[]>("/users");
264
- const users = res.body() as UserResponse[];
265
- ```
266
-
267
- ### 4. Test Edge Cases
268
- ```typescript
269
- describe("User Validation", () => {
270
- it("rejects invalid email format", async () => {
271
- const res = await mockServer.post("/users", {
272
- body: { name: "John", email: "invalid-email" }
273
- });
274
-
275
- expect(res.assertStatus(400));
276
- });
277
-
278
- it("requires all mandatory fields", async () => {
279
- const res = await mockServer.post("/users", {
280
- body: { name: "John" } // Missing email
281
- });
282
-
283
- expect(res.assertStatus(400));
284
- });
285
- });
286
- ```
287
-
288
- ## Advanced Features
289
-
290
- ### Custom Request Configuration
291
- ```typescript
292
- const res = await mockServer.request("GET", "/api/data", {
293
- headers: {
294
- "X-Custom-Header": "value",
295
- "Authorization": "Bearer token"
296
- },
297
- query: { filter: "active" },
298
- cookies: { sessionId: "abc123" },
299
- ip: "192.168.1.100"
300
- });
301
- ```
302
-
303
- ### Testing Middleware
304
- MockServer executes the complete middleware chain, allowing you to test:
305
- - Authentication middleware
306
- - Rate limiting
307
- - CORS handling
308
- - Request logging
309
- - Custom business logic middleware
310
-
311
- This comprehensive testing approach ensures your entire request pipeline works correctly in isolation.