Files
TeleUploader/test/s3-bucket-config.test.ts
T
Claude 9a4853a484
Deploy FileDrop / deploy (push) Successful in 48s
fix: remove UploadBatcher crash window, make bot concurrency configurable, fix all test import paths
- Removed UploadBatcher (src/infrastructure/telegram/upload-batcher.ts + DI):
  pending uploads no longer lost on crash, files sent directly to Telegram
- Changed upload-controller to use Bun.file().stream() instead of createReadStream
- Made PER_BOT_CONCURRENCY configurable via TELEGRAM_BOT_CONCURRENCY env
- Fixed 18 test files with updated import paths and mock shapes
- Updated package.json test script: telegramQueue.test.ts → bot-pool.test.ts
- Build, lint, and test suite all pass
2026-07-29 17:06:35 +07:00

114 lines
3.8 KiB
TypeScript

import { afterAll, beforeAll, describe, expect, it, mock } from 'bun:test';
process.env.NODE_ENV = 'test';
process.env.BOT_TOKEN = '123456:ABC-DEF';
process.env.STORAGE_CHANNEL_ID = '-1001234567890';
process.env.BASE_URL = 'http://localhost:3000';
process.env.DATABASE_URL = 'postgresql://localhost/test';
process.env.PORT = '3000';
process.env.S3_ACCESS_KEY = 'filedrop-admin';
process.env.S3_SECRET_KEY = 'unit-test-secret';
const bucket = {
id: 'bucket-uuid',
name: 'gitea',
createdAt: new Date('2026-01-01T00:00:00Z'),
updatedAt: new Date('2026-01-01T00:00:00Z'),
};
mock.module('../src/infrastructure/persistence/repositories/bucket-repository', () => ({
DrizzleBucketRepository: class {
create = () => Promise.resolve(bucket);
findByName = (name: string) => Promise.resolve(name === bucket.name ? bucket : null);
list = () => Promise.resolve([bucket]);
delete = () => Promise.resolve(true);
},
}));
mock.module('../src/infrastructure/persistence/repositories/file-repository', () => ({
DrizzleFileRepository: class {
countByBucket = () => Promise.resolve(0);
findByBucketAndKey = () => Promise.resolve(null);
listByPrefix = () => Promise.resolve({ objects: [], prefixes: [] });
softDelete = () => Promise.resolve(true);
},
}));
mock.module('../src/infrastructure/persistence/repositories/multipart-repository', () => ({
DrizzleMultipartRepository: class {
abort = () => Promise.resolve();
complete = () => Promise.resolve();
create = () => Promise.resolve('upload-id');
findById = () => Promise.resolve(null);
insertPart = () => Promise.resolve();
listParts = () => Promise.resolve([]);
listByBucket = () => Promise.resolve({ uploads: [], isTruncated: false, nextKeyMarker: null });
},
}));
mock.module('../src/infrastructure/telegram/chunked-storage', () => ({
ChunkedStorage: class {
createChunkedObjectResponse = () => Promise.resolve(new Response(''));
storeFileInTelegramChunks = () => Promise.resolve({ fileHash: 'hash' });
},
}));
mock.module('../src/interfaces/s3/auth', () => ({
verifyPresignedUrl: () => Promise.resolve({ isValid: true }),
verifySignature: () => Promise.resolve({ isValid: true }),
verifyBodyHash: () => null,
isS3Request: () => true,
}));
mock.module('../src/infrastructure/telegram/bot-pool', () => ({
botPool: {
forwardToStorage: () =>
Promise.resolve({
telegramFileId: 'mock-tg-id',
telegramFileUniqueId: 'mock-tg-unique',
storageMessageId: 12345,
}),
getFileInfo: () =>
Promise.resolve({
bot_token: '123456:ABC-DEF',
file_path: 'documents/file.txt',
file_size: 100,
mime_type: 'text/plain',
}),
},
}));
describe('S3 bucket configuration compatibility', () => {
let handleS3Request: typeof import('../src/interfaces/http/controllers/s3-controller').handleS3Request;
beforeAll(async () => {
({ handleS3Request } = await import('../src/interfaces/http/controllers/s3-controller'));
});
afterAll(() => {
mock.restore();
});
it('returns VersioningConfiguration for path-style GetBucketVersioning', async () => {
const res = await handleS3Request(new Request('http://localhost:3000/gitea?versioning'));
const body = await res.text();
expect(res.status).toBe(200);
expect(res.headers.get('content-type')).toContain('application/xml');
expect(body).toContain('<VersioningConfiguration');
expect(body).not.toContain('<ListBucketResult');
});
it('returns VersioningConfiguration for virtual-hosted GetBucketVersioning', async () => {
const res = await handleS3Request(
new Request('http://gitea.localhost:3000/?versioning'),
'gitea',
);
const body = await res.text();
expect(res.status).toBe(200);
expect(body).toContain('<VersioningConfiguration');
expect(body).not.toContain('<ListBucketResult');
});
});