Move the MIME/type-to-extension maps and derivation helpers out of
session-manager.ts into a dedicated attachment-naming module — keeps
session-manager focused on session lifecycle and gives the helpers
a natural home for unit tests alongside the existing attachment-safety
module.
Two small fixes alongside the extraction:
- extForMime now guards `typeof mime !== 'string'` before .split, so a
buggy bridge passing `mimeType: { ... }` (object) no longer crashes
the inbound write loop.
- deriveAttachmentName computes Date.now() once per call instead of
twice, and tightens the explicit-name check to a string-and-truthy
guard so non-string values fall through to derivation.
Adds attachment-naming.test.ts with 11 cases covering MIME normalization
(case + parameters), Telegram type fallback, the non-string defensive
guard, and the bare-timestamp fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
72 lines
3.0 KiB
TypeScript
72 lines
3.0 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
|
|
import { deriveAttachmentName, extForMime } from './attachment-naming.js';
|
|
|
|
describe('extForMime', () => {
|
|
it('returns empty for undefined / non-string / empty', () => {
|
|
expect(extForMime(undefined)).toBe('');
|
|
expect(extForMime('')).toBe('');
|
|
expect(extForMime({})).toBe('');
|
|
expect(extForMime(null)).toBe('');
|
|
expect(extForMime(42)).toBe('');
|
|
});
|
|
|
|
it('maps common MIME types to canonical extensions', () => {
|
|
expect(extForMime('image/jpeg')).toBe('jpg');
|
|
expect(extForMime('application/pdf')).toBe('pdf');
|
|
expect(extForMime('audio/ogg')).toBe('ogg');
|
|
});
|
|
|
|
it('strips parameters and is case-insensitive', () => {
|
|
expect(extForMime('image/JPEG; foo=bar')).toBe('jpg');
|
|
expect(extForMime(' Application/PDF ')).toBe('pdf');
|
|
expect(extForMime('text/plain; charset=utf-8')).toBe('txt');
|
|
});
|
|
|
|
it('returns empty for unknown MIMEs', () => {
|
|
expect(extForMime('application/octet-stream')).toBe('');
|
|
expect(extForMime('application/x-totally-made-up')).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('deriveAttachmentName', () => {
|
|
it('returns explicit name when set, no derivation', () => {
|
|
expect(deriveAttachmentName({ name: 'photo.jpg', mimeType: 'application/pdf' })).toBe('photo.jpg');
|
|
});
|
|
|
|
it('ignores empty / non-string explicit name and falls through to derivation', () => {
|
|
const out = deriveAttachmentName({ name: '', mimeType: 'application/pdf' });
|
|
expect(out).toMatch(/^attachment-\d+\.pdf$/);
|
|
|
|
const out2 = deriveAttachmentName({ name: 42, mimeType: 'application/pdf' });
|
|
expect(out2).toMatch(/^attachment-\d+\.pdf$/);
|
|
});
|
|
|
|
it('derives extension from mimeType when no name', () => {
|
|
expect(deriveAttachmentName({ mimeType: 'application/pdf' })).toMatch(/^attachment-\d+\.pdf$/);
|
|
expect(deriveAttachmentName({ mimeType: 'image/jpeg' })).toMatch(/^attachment-\d+\.jpg$/);
|
|
});
|
|
|
|
it('falls back to att.type when mimeType is missing (Telegram photos/stickers)', () => {
|
|
expect(deriveAttachmentName({ type: 'photo' })).toMatch(/^attachment-\d+\.jpg$/);
|
|
expect(deriveAttachmentName({ type: 'sticker' })).toMatch(/^attachment-\d+\.webp$/);
|
|
expect(deriveAttachmentName({ type: 'voice' })).toMatch(/^attachment-\d+\.ogg$/);
|
|
expect(deriveAttachmentName({ type: 'animation' })).toMatch(/^attachment-\d+\.mp4$/);
|
|
});
|
|
|
|
it('case-insensitive att.type lookup', () => {
|
|
expect(deriveAttachmentName({ type: 'PHOTO' })).toMatch(/^attachment-\d+\.jpg$/);
|
|
});
|
|
|
|
it('returns bare timestamp when nothing matches', () => {
|
|
expect(deriveAttachmentName({})).toMatch(/^attachment-\d+$/);
|
|
expect(deriveAttachmentName({ mimeType: 'application/octet-stream' })).toMatch(/^attachment-\d+$/);
|
|
expect(deriveAttachmentName({ type: 'mystery-class' })).toMatch(/^attachment-\d+$/);
|
|
});
|
|
|
|
it('does not crash on non-string mimeType (defensive against buggy bridges)', () => {
|
|
expect(() => deriveAttachmentName({ mimeType: { foo: 'bar' } })).not.toThrow();
|
|
expect(deriveAttachmentName({ mimeType: { foo: 'bar' } })).toMatch(/^attachment-\d+$/);
|
|
});
|
|
});
|