2026-05-18 07:27:06 +07:00
|
|
|
// @ts-nocheck
|
2026-05-18 07:29:01 +07:00
|
|
|
import { afterAll, beforeEach, describe, expect, it, mock } from 'bun:test';
|
2026-05-18 07:08:13 +07:00
|
|
|
|
|
|
|
|
// Mock db
|
|
|
|
|
const mockInsert = mock(() => ({
|
2026-05-18 07:29:01 +07:00
|
|
|
values: mock(() => Promise.resolve()),
|
2026-05-18 07:08:13 +07:00
|
|
|
}));
|
|
|
|
|
|
2026-05-18 07:29:01 +07:00
|
|
|
mock.module('../src/db/index', () => ({
|
2026-05-18 07:08:13 +07:00
|
|
|
db: {
|
2026-05-18 07:29:01 +07:00
|
|
|
insert: mockInsert,
|
2026-05-18 07:08:13 +07:00
|
|
|
},
|
2026-05-18 07:29:01 +07:00
|
|
|
files: {},
|
2026-05-18 07:08:13 +07:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Mock nanoid
|
2026-05-18 07:29:01 +07:00
|
|
|
mock.module('nanoid', () => ({
|
|
|
|
|
nanoid: () => 'mocked-nanoid-id',
|
2026-05-18 07:08:13 +07:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Mock telegram utils
|
2026-05-18 07:29:01 +07:00
|
|
|
mock.module('../src/utils/telegram', () => ({
|
|
|
|
|
forwardToStorage: mock(() =>
|
|
|
|
|
Promise.resolve({
|
|
|
|
|
telegramFileId: 'tg-file-id-123',
|
|
|
|
|
telegramFileUniqueId: 'tg-unique-id-abc',
|
|
|
|
|
storageMessageId: 98765,
|
|
|
|
|
}),
|
|
|
|
|
),
|
2026-05-18 07:08:13 +07:00
|
|
|
getBot: () => ({
|
2026-05-18 07:27:06 +07:00
|
|
|
telegram: {
|
2026-05-18 07:29:01 +07:00
|
|
|
getFile: mock(() =>
|
|
|
|
|
Promise.resolve({
|
|
|
|
|
file_id: 'tg-file-id-123',
|
|
|
|
|
file_size: 1000,
|
|
|
|
|
mime_type: 'image/jpeg',
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
}),
|
2026-05-18 07:08:13 +07:00
|
|
|
}));
|
|
|
|
|
|
2026-05-18 07:29:01 +07:00
|
|
|
describe('Upload Route Handler', () => {
|
|
|
|
|
let handleUpload: any;
|
2026-05-18 07:08:13 +07:00
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
|
mockInsert.mockClear();
|
2026-05-18 07:29:01 +07:00
|
|
|
const uploadRoute = await import('../src/routes/upload');
|
2026-05-18 07:08:13 +07:00
|
|
|
handleUpload = uploadRoute.handleUpload;
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-18 07:29:01 +07:00
|
|
|
it('should reject unsupported content types with 400 status', async () => {
|
|
|
|
|
const req = new Request('http://localhost:3000/api/upload', {
|
|
|
|
|
method: 'POST',
|
2026-05-18 07:08:13 +07:00
|
|
|
headers: {
|
2026-05-18 07:29:01 +07:00
|
|
|
'content-type': 'text/plain',
|
2026-05-18 07:08:13 +07:00
|
|
|
},
|
2026-05-18 07:29:01 +07:00
|
|
|
body: 'plain text data',
|
2026-05-18 07:08:13 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const res = await handleUpload(req);
|
|
|
|
|
expect(res.status).toBe(400);
|
|
|
|
|
const body = await res.json();
|
2026-05-18 07:29:01 +07:00
|
|
|
expect(body.error).toContain('Unsupported content type');
|
2026-05-18 07:08:13 +07:00
|
|
|
});
|
|
|
|
|
|
2026-05-18 07:29:01 +07:00
|
|
|
it('should process JSON upload (base64) successfully', async () => {
|
|
|
|
|
const req = new Request('http://localhost:3000/api/upload', {
|
|
|
|
|
method: 'POST',
|
2026-05-18 07:08:13 +07:00
|
|
|
headers: {
|
2026-05-18 07:29:01 +07:00
|
|
|
'content-type': 'application/json',
|
2026-05-18 07:08:13 +07:00
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
2026-05-18 07:29:01 +07:00
|
|
|
file: Buffer.from('hello world').toString('base64'),
|
|
|
|
|
fileName: 'test.txt',
|
|
|
|
|
}),
|
2026-05-18 07:08:13 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const res = await handleUpload(req);
|
|
|
|
|
expect(res.status).toBe(200);
|
|
|
|
|
const body = await res.json();
|
|
|
|
|
|
2026-05-18 07:29:01 +07:00
|
|
|
expect(body.public_id).toBe('mocked-nanoid-id');
|
|
|
|
|
expect(body.telegram_file_id).toBe('tg-file-id-123');
|
|
|
|
|
expect(body.telegram_file_unique_id).toBe('tg-unique-id-abc');
|
|
|
|
|
expect(body.file_name).toBe('test.txt');
|
|
|
|
|
expect(body.file_type).toBe('document');
|
2026-05-18 07:08:13 +07:00
|
|
|
});
|
|
|
|
|
|
2026-05-18 07:29:01 +07:00
|
|
|
it('should reject JSON upload without file key', async () => {
|
|
|
|
|
const req = new Request('http://localhost:3000/api/upload', {
|
|
|
|
|
method: 'POST',
|
2026-05-18 07:08:13 +07:00
|
|
|
headers: {
|
2026-05-18 07:29:01 +07:00
|
|
|
'content-type': 'application/json',
|
2026-05-18 07:08:13 +07:00
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
2026-05-18 07:29:01 +07:00
|
|
|
fileName: 'test.txt',
|
|
|
|
|
}),
|
2026-05-18 07:08:13 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const res = await handleUpload(req);
|
|
|
|
|
expect(res.status).toBe(400);
|
|
|
|
|
const body = await res.json();
|
2026-05-18 07:29:01 +07:00
|
|
|
expect(body.error).toContain('Invalid JSON');
|
2026-05-18 07:08:13 +07:00
|
|
|
});
|
|
|
|
|
|
2026-05-18 07:29:01 +07:00
|
|
|
it('should process multipart upload successfully', async () => {
|
2026-05-18 07:08:13 +07:00
|
|
|
const formData = new FormData();
|
2026-05-18 07:29:01 +07:00
|
|
|
const fileBlob = new Blob([Buffer.from('multipart hello')], { type: 'text/plain' });
|
|
|
|
|
formData.append('file', fileBlob, 'test_multi.txt');
|
2026-05-18 07:08:13 +07:00
|
|
|
|
2026-05-18 07:29:01 +07:00
|
|
|
const req = new Request('http://localhost:3000/api/upload', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
body: formData,
|
2026-05-18 07:08:13 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const res = await handleUpload(req);
|
|
|
|
|
expect(res.status).toBe(200);
|
|
|
|
|
const body = await res.json();
|
2026-05-18 07:29:01 +07:00
|
|
|
expect(body.public_id).toBe('mocked-nanoid-id');
|
|
|
|
|
expect(body.file_name).toBe('test_multi.txt');
|
2026-05-18 07:08:13 +07:00
|
|
|
});
|
2026-05-18 07:16:30 +07:00
|
|
|
|
|
|
|
|
afterAll(() => {
|
|
|
|
|
mock.restore();
|
|
|
|
|
});
|
2026-05-18 07:08:13 +07:00
|
|
|
});
|