import { Media } from './Media'; import { MediaUrl } from '../value-objects/MediaUrl'; describe('Media', () => { describe('create', () => { it('creates a new media with required properties', () => { const media = Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: 'user-1', }); expect(media.id).toBe('media-1'); expect(media.filename).toBe('avatar.png'); expect(media.originalName).toBe('avatar.png'); expect(media.mimeType).toBe('image/png'); expect(media.size).toBe(123); expect(media.url).toBeInstanceOf(MediaUrl); expect(media.url.value).toBe('https://example.com/avatar.png'); expect(media.type).toBe('image'); expect(media.uploadedBy).toBe('user-1'); expect(media.uploadedAt).toBeInstanceOf(Date); expect(media.metadata).toBeUndefined(); }); it('creates media with metadata', () => { const media = Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: 'user-1', metadata: { width: 100, height: 100 }, }); expect(media.metadata).toEqual({ width: 100, height: 100 }); }); it('throws error when filename is missing', () => { expect(() => Media.create({ id: 'media-1', filename: '', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: 'user-1', }) ).toThrow('Filename is required'); }); it('throws error when url is missing', () => { expect(() => Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: '', type: 'image', uploadedBy: 'user-1', }) ).toThrow('URL is required'); }); it('throws error when uploadedBy is missing', () => { expect(() => Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: '', }) ).toThrow('Uploaded by is required'); }); it('throws error when url is invalid', () => { expect(() => Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'invalid-url', type: 'image', uploadedBy: 'user-1', }) ).toThrow(); }); }); describe('reconstitute', () => { it('reconstitutes a media from props', () => { const uploadedAt = new Date('2024-01-01T00:00:00.000Z'); const media = Media.reconstitute({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: 'user-1', uploadedAt, }); expect(media.id).toBe('media-1'); expect(media.filename).toBe('avatar.png'); expect(media.originalName).toBe('avatar.png'); expect(media.mimeType).toBe('image/png'); expect(media.size).toBe(123); expect(media.url.value).toBe('https://example.com/avatar.png'); expect(media.type).toBe('image'); expect(media.uploadedBy).toBe('user-1'); expect(media.uploadedAt).toEqual(uploadedAt); expect(media.metadata).toBeUndefined(); }); it('reconstitutes a media with metadata', () => { const media = Media.reconstitute({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: 'user-1', uploadedAt: new Date(), metadata: { width: 100, height: 100 }, }); expect(media.metadata).toEqual({ width: 100, height: 100 }); }); it('reconstitutes a video media', () => { const media = Media.reconstitute({ id: 'media-1', filename: 'video.mp4', originalName: 'video.mp4', mimeType: 'video/mp4', size: 1024, url: 'https://example.com/video.mp4', type: 'video', uploadedBy: 'user-1', uploadedAt: new Date(), }); expect(media.type).toBe('video'); }); it('reconstitutes a document media', () => { const media = Media.reconstitute({ id: 'media-1', filename: 'document.pdf', originalName: 'document.pdf', mimeType: 'application/pdf', size: 2048, url: 'https://example.com/document.pdf', type: 'document', uploadedBy: 'user-1', uploadedAt: new Date(), }); expect(media.type).toBe('document'); }); }); describe('toProps', () => { it('returns correct props for a new media', () => { const media = Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: 'user-1', }); const props = media.toProps(); expect(props.id).toBe('media-1'); expect(props.filename).toBe('avatar.png'); expect(props.originalName).toBe('avatar.png'); expect(props.mimeType).toBe('image/png'); expect(props.size).toBe(123); expect(props.url).toBe('https://example.com/avatar.png'); expect(props.type).toBe('image'); expect(props.uploadedBy).toBe('user-1'); expect(props.uploadedAt).toBeInstanceOf(Date); expect(props.metadata).toBeUndefined(); }); it('returns correct props for a media with metadata', () => { const media = Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: 'user-1', metadata: { width: 100, height: 100 }, }); const props = media.toProps(); expect(props.metadata).toEqual({ width: 100, height: 100 }); }); it('returns correct props for a reconstituted media', () => { const uploadedAt = new Date('2024-01-01T00:00:00.000Z'); const media = Media.reconstitute({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: 'user-1', uploadedAt, metadata: { width: 100, height: 100 }, }); const props = media.toProps(); expect(props.id).toBe('media-1'); expect(props.filename).toBe('avatar.png'); expect(props.originalName).toBe('avatar.png'); expect(props.mimeType).toBe('image/png'); expect(props.size).toBe(123); expect(props.url).toBe('https://example.com/avatar.png'); expect(props.type).toBe('image'); expect(props.uploadedBy).toBe('user-1'); expect(props.uploadedAt).toEqual(uploadedAt); expect(props.metadata).toEqual({ width: 100, height: 100 }); }); }); describe('value object validation', () => { it('validates url as MediaUrl value object', () => { const media = Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'https://example.com/avatar.png', type: 'image', uploadedBy: 'user-1', }); expect(media.url).toBeInstanceOf(MediaUrl); expect(media.url.value).toBe('https://example.com/avatar.png'); }); it('accepts data URI for url', () => { const media = Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: 'data:image/png;base64,abc', type: 'image', uploadedBy: 'user-1', }); expect(media.url.value).toBe('data:image/png;base64,abc'); }); it('accepts root-relative path for url', () => { const media = Media.create({ id: 'media-1', filename: 'avatar.png', originalName: 'avatar.png', mimeType: 'image/png', size: 123, url: '/images/avatar.png', type: 'image', uploadedBy: 'user-1', }); expect(media.url.value).toBe('/images/avatar.png'); }); }); });