/** * Comprehensive Tests for MediaResolverPort * * Tests cover: * - Interface contract compliance * - ResolutionStrategies for all reference types * - resolveWithDefaults helper function * - isMediaResolverPort type guard * - Edge cases and error handling * - Business logic decisions */ import { MediaReference } from '@core/domain/media/MediaReference'; import { describe, expect, it } from 'vitest'; import { MediaResolverPort, ResolutionStrategies, resolveWithDefaults, isMediaResolverPort, } from './MediaResolverPort'; describe('MediaResolverPort - Comprehensive Tests', () => { describe('Interface Contract Compliance', () => { it('should define resolve method signature correctly', () => { // Verify the interface has the correct method signature const testInterface: MediaResolverPort = { resolve: async (ref: MediaReference): Promise => { return null; }, }; expect(testInterface).toBeDefined(); expect(typeof testInterface.resolve).toBe('function'); }); it('should accept MediaReference and return Promise', async () => { const mockResolver: MediaResolverPort = { resolve: async (ref: MediaReference): Promise => { // Verify ref is a MediaReference instance expect(ref).toBeInstanceOf(MediaReference); return '/test/path'; }, }; const ref = MediaReference.createSystemDefault('avatar'); const result = await mockResolver.resolve(ref); expect(result).toBe('/test/path'); }); }); describe('ResolutionStrategies - System Default', () => { it('should resolve system-default avatar without variant', () => { const ref = MediaReference.createSystemDefault('avatar'); const result = ResolutionStrategies.systemDefault(ref); expect(result).toBe('/media/default/neutral-default-avatar.png'); }); it('should resolve system-default avatar with male variant', () => { const ref = MediaReference.createSystemDefault('avatar', 'male'); const result = ResolutionStrategies.systemDefault(ref); expect(result).toBe('/media/default/male-default-avatar.png'); }); it('should resolve system-default avatar with female variant', () => { const ref = MediaReference.createSystemDefault('avatar', 'female'); const result = ResolutionStrategies.systemDefault(ref); expect(result).toBe('/media/default/female-default-avatar.png'); }); it('should resolve system-default avatar with neutral variant', () => { const ref = MediaReference.createSystemDefault('avatar', 'neutral'); const result = ResolutionStrategies.systemDefault(ref); expect(result).toBe('/media/default/neutral-default-avatar.png'); }); it('should resolve system-default logo', () => { const ref = MediaReference.createSystemDefault('logo'); const result = ResolutionStrategies.systemDefault(ref); expect(result).toBe('/media/default/logo.png'); }); it('should return null for non-system-default reference', () => { const ref = MediaReference.createGenerated('team-123'); const result = ResolutionStrategies.systemDefault(ref); expect(result).toBeNull(); }); }); describe('ResolutionStrategies - Generated', () => { it('should resolve generated reference for team', () => { const ref = MediaReference.createGenerated('team-123'); const result = ResolutionStrategies.generated(ref); expect(result).toBe('/media/teams/123/logo'); }); it('should resolve generated reference for league', () => { const ref = MediaReference.createGenerated('league-456'); const result = ResolutionStrategies.generated(ref); expect(result).toBe('/media/leagues/456/logo'); }); it('should resolve generated reference for driver', () => { const ref = MediaReference.createGenerated('driver-789'); const result = ResolutionStrategies.generated(ref); expect(result).toBe('/media/avatar/789'); }); it('should resolve generated reference for unknown type', () => { const ref = MediaReference.createGenerated('unknown-999'); const result = ResolutionStrategies.generated(ref); expect(result).toBe('/media/generated/unknown/999'); }); it('should return null for generated reference without generationRequestId', () => { // Create a reference with missing generationRequestId const ref = MediaReference.createGenerated('valid-id'); // Manually create an invalid reference const invalidRef = { type: 'generated' } as MediaReference; const result = ResolutionStrategies.generated(invalidRef); expect(result).toBeNull(); }); it('should return null for non-generated reference', () => { const ref = MediaReference.createSystemDefault('avatar'); const result = ResolutionStrategies.generated(ref); expect(result).toBeNull(); }); it('should handle generated reference with special characters in ID', () => { const ref = MediaReference.createGenerated('team-abc-123_XYZ'); const result = ResolutionStrategies.generated(ref); expect(result).toBe('/media/teams/abc-123_XYZ/logo'); }); it('should handle generated reference with multiple hyphens', () => { const ref = MediaReference.createGenerated('team-abc-def-123'); const result = ResolutionStrategies.generated(ref); expect(result).toBe('/media/teams/abc-def-123/logo'); }); }); describe('ResolutionStrategies - Uploaded', () => { it('should resolve uploaded reference', () => { const ref = MediaReference.createUploaded('media-456'); const result = ResolutionStrategies.uploaded(ref); expect(result).toBe('/media/uploaded/media-456'); }); it('should return null for uploaded reference without mediaId', () => { // Create a reference with missing mediaId const ref = MediaReference.createUploaded('valid-id'); // Manually create an invalid reference const invalidRef = { type: 'uploaded' } as MediaReference; const result = ResolutionStrategies.uploaded(invalidRef); expect(result).toBeNull(); }); it('should return null for non-uploaded reference', () => { const ref = MediaReference.createSystemDefault('avatar'); const result = ResolutionStrategies.uploaded(ref); expect(result).toBeNull(); }); it('should handle uploaded reference with special characters', () => { const ref = MediaReference.createUploaded('media-abc-123_XYZ'); const result = ResolutionStrategies.uploaded(ref); expect(result).toBe('/media/uploaded/media-abc-123_XYZ'); }); it('should handle uploaded reference with very long ID', () => { const longId = 'a'.repeat(1000); const ref = MediaReference.createUploaded(longId); const result = ResolutionStrategies.uploaded(ref); expect(result).toBe(`/media/uploaded/${longId}`); }); }); describe('ResolutionStrategies - None', () => { it('should return null for none reference', () => { const ref = MediaReference.createNone(); const result = ResolutionStrategies.none(ref); expect(result).toBeNull(); }); it('should return null for any reference passed to none strategy', () => { const ref = MediaReference.createSystemDefault('avatar'); const result = ResolutionStrategies.none(ref); expect(result).toBeNull(); }); }); describe('resolveWithDefaults - Integration Tests', () => { it('should resolve system-default reference using resolveWithDefaults', () => { const ref = MediaReference.createSystemDefault('avatar'); const result = resolveWithDefaults(ref); expect(result).toBe('/media/default/neutral-default-avatar.png'); }); it('should resolve system-default avatar with male variant using resolveWithDefaults', () => { const ref = MediaReference.createSystemDefault('avatar', 'male'); const result = resolveWithDefaults(ref); expect(result).toBe('/media/default/male-default-avatar.png'); }); it('should resolve system-default logo using resolveWithDefaults', () => { const ref = MediaReference.createSystemDefault('logo'); const result = resolveWithDefaults(ref); expect(result).toBe('/media/default/logo.png'); }); it('should resolve generated reference using resolveWithDefaults', () => { const ref = MediaReference.createGenerated('team-123'); const result = resolveWithDefaults(ref); expect(result).toBe('/media/teams/123/logo'); }); it('should resolve uploaded reference using resolveWithDefaults', () => { const ref = MediaReference.createUploaded('media-456'); const result = resolveWithDefaults(ref); expect(result).toBe('/media/uploaded/media-456'); }); it('should resolve none reference using resolveWithDefaults', () => { const ref = MediaReference.createNone(); const result = resolveWithDefaults(ref); expect(result).toBeNull(); }); it('should handle all reference types in sequence', () => { const refs = [ MediaReference.createSystemDefault('avatar'), MediaReference.createSystemDefault('avatar', 'male'), MediaReference.createSystemDefault('logo'), MediaReference.createGenerated('team-123'), MediaReference.createGenerated('league-456'), MediaReference.createGenerated('driver-789'), MediaReference.createUploaded('media-456'), MediaReference.createNone(), ]; const results = refs.map(ref => resolveWithDefaults(ref)); expect(results).toEqual([ '/media/default/neutral-default-avatar.png', '/media/default/male-default-avatar.png', '/media/default/logo.png', '/media/teams/123/logo', '/media/leagues/456/logo', '/media/avatar/789', '/media/uploaded/media-456', null, ]); }); }); describe('isMediaResolverPort Type Guard', () => { it('should return true for valid MediaResolverPort implementation', () => { const validResolver: MediaResolverPort = { resolve: async (ref: MediaReference): Promise => { return '/test/path'; }, }; expect(isMediaResolverPort(validResolver)).toBe(true); }); it('should return false for null', () => { expect(isMediaResolverPort(null)).toBe(false); }); it('should return false for undefined', () => { expect(isMediaResolverPort(undefined)).toBe(false); }); it('should return false for non-object', () => { expect(isMediaResolverPort('string')).toBe(false); expect(isMediaResolverPort(123)).toBe(false); expect(isMediaResolverPort(true)).toBe(false); }); it('should return false for object without resolve method', () => { const invalidResolver = { someOtherMethod: () => {}, }; expect(isMediaResolverPort(invalidResolver)).toBe(false); }); it('should return false for object with resolve property but not a function', () => { const invalidResolver = { resolve: 'not a function', }; expect(isMediaResolverPort(invalidResolver)).toBe(false); }); it('should return false for object with resolve as non-function property', () => { const invalidResolver = { resolve: 123, }; expect(isMediaResolverPort(invalidResolver)).toBe(false); }); it('should return true for object with resolve method and other properties', () => { const validResolver = { resolve: async (ref: MediaReference): Promise => { return '/test/path'; }, extraProperty: 'value', anotherMethod: () => {}, }; expect(isMediaResolverPort(validResolver)).toBe(true); }); }); describe('Business Logic Decisions', () => { it('should make correct decision for system-default avatar without variant', () => { const ref = MediaReference.createSystemDefault('avatar'); const result = resolveWithDefaults(ref); // Decision: Should use neutral default avatar expect(result).toBe('/media/default/neutral-default-avatar.png'); }); it('should make correct decision for system-default avatar with specific variant', () => { const ref = MediaReference.createSystemDefault('avatar', 'female'); const result = resolveWithDefaults(ref); // Decision: Should use the specified variant expect(result).toBe('/media/default/female-default-avatar.png'); }); it('should make correct decision for generated team reference', () => { const ref = MediaReference.createGenerated('team-123'); const result = resolveWithDefaults(ref); // Decision: Should resolve to team logo path expect(result).toBe('/media/teams/123/logo'); }); it('should make correct decision for generated league reference', () => { const ref = MediaReference.createGenerated('league-456'); const result = resolveWithDefaults(ref); // Decision: Should resolve to league logo path expect(result).toBe('/media/leagues/456/logo'); }); it('should make correct decision for generated driver reference', () => { const ref = MediaReference.createGenerated('driver-789'); const result = resolveWithDefaults(ref); // Decision: Should resolve to avatar path expect(result).toBe('/media/avatar/789'); }); it('should make correct decision for uploaded reference', () => { const ref = MediaReference.createUploaded('media-456'); const result = resolveWithDefaults(ref); // Decision: Should resolve to uploaded media path expect(result).toBe('/media/uploaded/media-456'); }); it('should make correct decision for none reference', () => { const ref = MediaReference.createNone(); const result = resolveWithDefaults(ref); // Decision: Should return null (no media) expect(result).toBeNull(); }); it('should make correct decision for unknown generated type', () => { const ref = MediaReference.createGenerated('unknown-999'); const result = resolveWithDefaults(ref); // Decision: Should fall back to generic generated path expect(result).toBe('/media/generated/unknown/999'); }); }); describe('Edge Cases and Error Handling', () => { it('should handle empty string IDs gracefully', () => { // MediaReference factory methods throw on empty strings // This tests that the strategies handle invalid refs gracefully const invalidRef = { type: 'generated' } as MediaReference; const result = ResolutionStrategies.generated(invalidRef); expect(result).toBeNull(); }); it('should handle references with missing properties', () => { const invalidRef = { type: 'uploaded' } as MediaReference; const result = ResolutionStrategies.uploaded(invalidRef); expect(result).toBeNull(); }); it('should handle very long IDs without performance issues', () => { const longId = 'a'.repeat(10000); const ref = MediaReference.createUploaded(longId); const result = resolveWithDefaults(ref); expect(result).toBe(`/media/uploaded/${longId}`); }); it('should handle Unicode characters in IDs', () => { const ref = MediaReference.createUploaded('media-日本語-123'); const result = resolveWithDefaults(ref); expect(result).toBe('/media/uploaded/media-日本語-123'); }); it('should handle special characters in generated IDs', () => { const ref = MediaReference.createGenerated('team-abc_def-123'); const result = resolveWithDefaults(ref); expect(result).toBe('/media/teams/abc_def-123/logo'); }); }); describe('Path Format Consistency', () => { it('should maintain consistent path format for system-default', () => { const ref = MediaReference.createSystemDefault('avatar'); const result = resolveWithDefaults(ref); // Should start with /media/default/ expect(result).toMatch(/^\/media\/default\//); }); it('should maintain consistent path format for generated team', () => { const ref = MediaReference.createGenerated('team-123'); const result = resolveWithDefaults(ref); // Should start with /media/teams/ expect(result).toMatch(/^\/media\/teams\//); }); it('should maintain consistent path format for generated league', () => { const ref = MediaReference.createGenerated('league-456'); const result = resolveWithDefaults(ref); // Should start with /media/leagues/ expect(result).toMatch(/^\/media\/leagues\//); }); it('should maintain consistent path format for generated driver', () => { const ref = MediaReference.createGenerated('driver-789'); const result = resolveWithDefaults(ref); // Should start with /media/avatar/ expect(result).toMatch(/^\/media\/avatar\//); }); it('should maintain consistent path format for uploaded', () => { const ref = MediaReference.createUploaded('media-456'); const result = resolveWithDefaults(ref); // Should start with /media/uploaded/ expect(result).toMatch(/^\/media\/uploaded\//); }); it('should maintain consistent path format for unknown generated type', () => { const ref = MediaReference.createGenerated('unknown-999'); const result = resolveWithDefaults(ref); // Should start with /media/generated/ expect(result).toMatch(/^\/media\/generated\//); }); }); });