@uploadista/server 0.0.18-beta.16 → 0.0.18-beta.2

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,351 +0,0 @@
1
- /**
2
- * Tests for HTTP Health Check Handlers
3
- *
4
- * Covers:
5
- * - Liveness probe endpoint (/health)
6
- * - Readiness probe endpoint (/ready)
7
- * - Component details endpoint (/health/components)
8
- * - Response format negotiation (JSON/plain text)
9
- * - HTTP status codes
10
- */
11
-
12
- import { it } from "@effect/vitest";
13
- import type {
14
- HealthResponse as HealthResponseBody,
15
- HealthStatus,
16
- } from "@uploadista/core/types";
17
- import { Effect } from "effect";
18
- import { describe, expect } from "vitest";
19
- import {
20
- handleHealthComponents,
21
- handleHealthLiveness,
22
- handleHealthReadiness,
23
- } from "../../../src/core/http-handlers/health-http-handlers";
24
- import type {
25
- HealthComponentsRequest,
26
- HealthReadyRequest,
27
- HealthRequest,
28
- } from "../../../src/core/routes";
29
-
30
- describe("HTTP Health Check Handlers", () => {
31
- describe("Liveness Probe (/health)", () => {
32
- it.effect("should return 200 OK for liveness check", () =>
33
- Effect.gen(function* () {
34
- const request: HealthRequest = {
35
- type: "health",
36
- acceptHeader: "application/json",
37
- };
38
-
39
- const response = yield* handleHealthLiveness(request);
40
-
41
- expect(response.status).toBe(200);
42
- expect(response.type).toBe("health");
43
- }),
44
- );
45
-
46
- it.effect("should return healthy status in JSON format", () =>
47
- Effect.gen(function* () {
48
- const request: HealthRequest = {
49
- type: "health",
50
- acceptHeader: "application/json",
51
- };
52
-
53
- const response = yield* handleHealthLiveness(request);
54
-
55
- expect(response.headers["Content-Type"]).toBe("application/json");
56
- const body = response.body as HealthResponseBody;
57
- expect(body.status).toBe("healthy");
58
- expect(body.timestamp).toBeDefined();
59
- }),
60
- );
61
-
62
- it.effect("should include uptime in response", () =>
63
- Effect.gen(function* () {
64
- const request: HealthRequest = {
65
- type: "health",
66
- acceptHeader: "application/json",
67
- };
68
-
69
- const response = yield* handleHealthLiveness(request);
70
- const body = response.body as HealthResponseBody;
71
-
72
- expect(body.uptime).toBeDefined();
73
- expect(typeof body.uptime).toBe("number");
74
- expect(body.uptime).toBeGreaterThanOrEqual(0);
75
- }),
76
- );
77
-
78
- it.effect("should return plain text 'OK' when Accept: text/plain", () =>
79
- Effect.gen(function* () {
80
- const request: HealthRequest = {
81
- type: "health",
82
- acceptHeader: "text/plain",
83
- };
84
-
85
- const response = yield* handleHealthLiveness(request);
86
-
87
- expect(response.headers["Content-Type"]).toBe("text/plain");
88
- expect(response.body).toBe("OK");
89
- }),
90
- );
91
-
92
- it.effect("should include version when configured", () =>
93
- Effect.gen(function* () {
94
- const request: HealthRequest = {
95
- type: "health",
96
- acceptHeader: "application/json",
97
- };
98
- const config = { version: "1.2.3" };
99
-
100
- const response = yield* handleHealthLiveness(request, config);
101
- const body = response.body as HealthResponseBody;
102
-
103
- expect(body.version).toBe("1.2.3");
104
- }),
105
- );
106
-
107
- it.effect("should return timestamp in ISO 8601 format", () =>
108
- Effect.gen(function* () {
109
- const request: HealthRequest = {
110
- type: "health",
111
- acceptHeader: "application/json",
112
- };
113
-
114
- const response = yield* handleHealthLiveness(request);
115
- const body = response.body as HealthResponseBody;
116
-
117
- // Verify timestamp is valid ISO 8601
118
- const parsedDate = new Date(body.timestamp);
119
- expect(parsedDate.toISOString()).toBe(body.timestamp);
120
- }),
121
- );
122
- });
123
-
124
- describe("Readiness Probe (/ready)", () => {
125
- it.effect("should return 200 OK when all dependencies healthy", () =>
126
- Effect.gen(function* () {
127
- const request: HealthReadyRequest = {
128
- type: "health-ready",
129
- acceptHeader: "application/json",
130
- };
131
-
132
- const response = yield* handleHealthReadiness(request);
133
-
134
- expect(response.status).toBe(200);
135
- expect(response.type).toBe("health-ready");
136
- }),
137
- );
138
-
139
- it.effect("should include component status in response", () =>
140
- Effect.gen(function* () {
141
- const request: HealthReadyRequest = {
142
- type: "health-ready",
143
- acceptHeader: "application/json",
144
- };
145
-
146
- const response = yield* handleHealthReadiness(request);
147
- const body = response.body as HealthResponseBody;
148
-
149
- expect(body.components).toBeDefined();
150
- }),
151
- );
152
-
153
- it.effect("should return plain text when Accept: text/plain", () =>
154
- Effect.gen(function* () {
155
- const request: HealthReadyRequest = {
156
- type: "health-ready",
157
- acceptHeader: "text/plain",
158
- };
159
-
160
- const response = yield* handleHealthReadiness(request);
161
-
162
- expect(response.headers["Content-Type"]).toBe("text/plain");
163
- expect(typeof response.body).toBe("string");
164
- }),
165
- );
166
-
167
- it.effect("should respect checkStorage config option", () =>
168
- Effect.gen(function* () {
169
- const request: HealthReadyRequest = {
170
- type: "health-ready",
171
- acceptHeader: "application/json",
172
- };
173
- const config = { checkStorage: true };
174
-
175
- const response = yield* handleHealthReadiness(request, config);
176
- const body = response.body as HealthResponseBody;
177
-
178
- // Storage should be checked when enabled
179
- expect(body.components?.storage).toBeDefined();
180
- }),
181
- );
182
-
183
- it.effect("should skip storage check when disabled", () =>
184
- Effect.gen(function* () {
185
- const request: HealthReadyRequest = {
186
- type: "health-ready",
187
- acceptHeader: "application/json",
188
- };
189
- const config = { checkStorage: false };
190
-
191
- const response = yield* handleHealthReadiness(request, config);
192
- const body = response.body as HealthResponseBody;
193
-
194
- // Storage should not be present when disabled
195
- expect(body.components?.storage).toBeUndefined();
196
- }),
197
- );
198
- });
199
-
200
- describe("Component Details (/health/components)", () => {
201
- it.effect("should always return 200 OK (for debugging)", () =>
202
- Effect.gen(function* () {
203
- const request: HealthComponentsRequest = {
204
- type: "health-components",
205
- acceptHeader: "application/json",
206
- };
207
-
208
- const response = yield* handleHealthComponents(request);
209
-
210
- // Components endpoint always returns 200 for debugging
211
- expect(response.status).toBe(200);
212
- expect(response.type).toBe("health-components");
213
- }),
214
- );
215
-
216
- it.effect("should include detailed component status", () =>
217
- Effect.gen(function* () {
218
- const request: HealthComponentsRequest = {
219
- type: "health-components",
220
- acceptHeader: "application/json",
221
- };
222
-
223
- const response = yield* handleHealthComponents(request);
224
- const body = response.body as HealthResponseBody;
225
-
226
- expect(body.components).toBeDefined();
227
- }),
228
- );
229
-
230
- it.effect("should include timestamp and uptime", () =>
231
- Effect.gen(function* () {
232
- const request: HealthComponentsRequest = {
233
- type: "health-components",
234
- acceptHeader: "application/json",
235
- };
236
-
237
- const response = yield* handleHealthComponents(request);
238
- const body = response.body as HealthResponseBody;
239
-
240
- expect(body.timestamp).toBeDefined();
241
- expect(body.uptime).toBeDefined();
242
- }),
243
- );
244
-
245
- it.effect("should return plain text when Accept: text/plain", () =>
246
- Effect.gen(function* () {
247
- const request: HealthComponentsRequest = {
248
- type: "health-components",
249
- acceptHeader: "text/plain",
250
- };
251
-
252
- const response = yield* handleHealthComponents(request);
253
-
254
- expect(response.headers["Content-Type"]).toBe("text/plain");
255
- expect(typeof response.body).toBe("string");
256
- }),
257
- );
258
- });
259
-
260
- describe("Response Format Negotiation", () => {
261
- it.effect("should default to JSON when no Accept header", () =>
262
- Effect.gen(function* () {
263
- const request: HealthRequest = {
264
- type: "health",
265
- acceptHeader: null,
266
- };
267
-
268
- const response = yield* handleHealthLiveness(request);
269
-
270
- expect(response.headers["Content-Type"]).toBe("application/json");
271
- }),
272
- );
273
-
274
- it.effect("should return JSON for application/json Accept header", () =>
275
- Effect.gen(function* () {
276
- const request: HealthRequest = {
277
- type: "health",
278
- acceptHeader: "application/json",
279
- };
280
-
281
- const response = yield* handleHealthLiveness(request);
282
-
283
- expect(response.headers["Content-Type"]).toBe("application/json");
284
- expect(typeof response.body).toBe("object");
285
- }),
286
- );
287
-
288
- it.effect("should return plain text for text/plain Accept header", () =>
289
- Effect.gen(function* () {
290
- const request: HealthRequest = {
291
- type: "health",
292
- acceptHeader: "text/plain",
293
- };
294
-
295
- const response = yield* handleHealthLiveness(request);
296
-
297
- expect(response.headers["Content-Type"]).toBe("text/plain");
298
- expect(typeof response.body).toBe("string");
299
- }),
300
- );
301
-
302
- it.effect("should handle Accept header with multiple types", () =>
303
- Effect.gen(function* () {
304
- const request: HealthRequest = {
305
- type: "health",
306
- acceptHeader: "text/plain, application/json",
307
- };
308
-
309
- const response = yield* handleHealthLiveness(request);
310
-
311
- // text/plain takes precedence when listed first
312
- expect(response.headers["Content-Type"]).toBe("text/plain");
313
- }),
314
- );
315
- });
316
-
317
- describe("Health Status Values", () => {
318
- it.effect("should return 'healthy' status for liveness", () =>
319
- Effect.gen(function* () {
320
- const request: HealthRequest = {
321
- type: "health",
322
- acceptHeader: "application/json",
323
- };
324
-
325
- const response = yield* handleHealthLiveness(request);
326
- const body = response.body as HealthResponseBody;
327
-
328
- expect(body.status).toBe("healthy");
329
- }),
330
- );
331
-
332
- it.effect("should return valid HealthStatus values", () =>
333
- Effect.gen(function* () {
334
- const request: HealthReadyRequest = {
335
- type: "health-ready",
336
- acceptHeader: "application/json",
337
- };
338
-
339
- const response = yield* handleHealthReadiness(request);
340
- const body = response.body as HealthResponseBody;
341
-
342
- const validStatuses: HealthStatus[] = [
343
- "healthy",
344
- "degraded",
345
- "unhealthy",
346
- ];
347
- expect(validStatuses).toContain(body.status);
348
- }),
349
- );
350
- });
351
- });