- routes: GET / teruskan headers ke shouldHandleS3; OPTIONS jawab
204 CORS generik bila bukan S3, handleS3Direct bila S3; komentar
bypass rate-limit S3 dipertahankan (registry abort pada 429)
- auth-controller: readLoginBody via LoginBodySchema; handleMe sederhanakan
(getAuthSession sudah cek bearer); import AuthSession dari dto
- swagger: pindah src/routes -> src/interfaces/http/swagger; tambah path
auth, /api/v1, /{bucket}, /{bucket}/{key}; version dari config.appVersion
- index: unref ketiga setInterval agar tak menahan process
- env: PORT fail-fast via PositiveIntSchema (default 4000 bila tak diset);
log config turun ke debug
- metrics: dokumentasikan uploadThroughput/queueSize/botUtilization
- test baru test/s3-routing.test.ts (GET / S3 vs home, OPTIONS 204 CORS)
74 lines
2.8 KiB
TypeScript
74 lines
2.8 KiB
TypeScript
import { describe, expect, it } from 'bun:test';
|
|
import { handleSwaggerHtml, handleSwaggerJson } from '../src/interfaces/http/swagger';
|
|
|
|
describe('Swagger Documentation Endpoints', () => {
|
|
it('returns OpenAPI specification JSON', async () => {
|
|
const res = await handleSwaggerJson();
|
|
|
|
expect(res.status).toBe(200);
|
|
expect(res.headers.get('content-type')).toContain('application/json');
|
|
|
|
const body = (await res.json()) as {
|
|
openapi: string;
|
|
info: { title: string };
|
|
paths: Record<string, { get?: object; post?: object }>;
|
|
};
|
|
expect(body.openapi).toBe('3.0.0');
|
|
expect(body.info.title).toBe('FileDrop API');
|
|
expect(body.paths).toHaveProperty('/health');
|
|
expect(body.paths).toHaveProperty('/api/upload');
|
|
expect(body.paths).toHaveProperty('/f/{public_id}');
|
|
expect(body.paths).toHaveProperty('/file/{public_id}/info');
|
|
|
|
const uploadPath = body.paths['/api/upload'] as any;
|
|
const downloadPath = body.paths['/f/{public_id}'] as any;
|
|
|
|
expect(uploadPath.post.requestBody.content).toHaveProperty('multipart/form-data');
|
|
expect(uploadPath.post.requestBody.content).toHaveProperty('application/json');
|
|
|
|
// Verify 429 response documented
|
|
const uploadResponses = uploadPath.post.responses;
|
|
expect(uploadResponses).toHaveProperty('429');
|
|
|
|
// Verify download is 302 redirect to Telegram CDN
|
|
const downloadResponses = downloadPath.get.responses;
|
|
expect(downloadResponses).toHaveProperty('302');
|
|
expect(downloadResponses['302'].description).toContain('Redirect');
|
|
});
|
|
|
|
it('documents auth, web API, and S3 endpoints with the app version', async () => {
|
|
const res = await handleSwaggerJson();
|
|
const body = (await res.json()) as {
|
|
info: { version: string };
|
|
paths: Record<string, object>;
|
|
};
|
|
|
|
expect(body.paths).toHaveProperty('/api/v1/auth/login');
|
|
expect(body.paths).toHaveProperty('/api/v1/auth/logout');
|
|
expect(body.paths).toHaveProperty('/api/v1/auth/me');
|
|
expect(body.paths).toHaveProperty('/api/v1/{path}');
|
|
expect(body.paths).toHaveProperty('/{bucket}');
|
|
expect(body.paths).toHaveProperty('/{bucket}/{key}');
|
|
expect(typeof body.info.version).toBe('string');
|
|
expect(body.info.version.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('returns Swagger UI HTML page', async () => {
|
|
const res = await handleSwaggerHtml();
|
|
|
|
expect(res.status).toBe(200);
|
|
expect(res.headers.get('content-type')).toContain('text/html');
|
|
|
|
const html = await res.text();
|
|
expect(html).toContain('<!DOCTYPE html>');
|
|
expect(html).toContain('swagger-ui');
|
|
expect(html).toContain('/swagger.json');
|
|
expect(html).toContain('swagger-ui-bundle.js');
|
|
});
|
|
|
|
it('should not expose CORS * header', async () => {
|
|
const res = await handleSwaggerJson();
|
|
expect(res.headers.get('access-control-allow-origin')).toBeNull();
|
|
});
|
|
});
|