// Unit tests for transcript fetcher import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals'; import fetch from 'node-fetch'; import { fetchTranscriptContent, isValidTranscriptUrl, extractSessionIdFromTranscript } from '../../lib/transcriptFetcher'; // Mock node-fetch const mockFetch = fetch as jest.MockedFunction; describe('Transcript Fetcher', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('fetchTranscriptContent', () => { it('should successfully fetch transcript content', async () => { const mockResponse = { ok: true, text: jest.fn().mockResolvedValue('Session transcript content'), }; mockFetch.mockResolvedValue(mockResponse as any); const result = await fetchTranscriptContent('https://example.com/transcript'); expect(result.success).toBe(true); expect(result.content).toBe('Session transcript content'); expect(result.error).toBeUndefined(); expect(mockFetch).toHaveBeenCalledWith('https://example.com/transcript', { method: 'GET', headers: { 'User-Agent': 'LiveDash-Transcript-Fetcher/1.0', }, signal: expect.any(AbortSignal), }); }); it('should handle authentication with username and password', async () => { const mockResponse = { ok: true, text: jest.fn().mockResolvedValue('Authenticated transcript'), }; mockFetch.mockResolvedValue(mockResponse as any); const result = await fetchTranscriptContent( 'https://example.com/transcript', 'user123', 'pass456' ); expect(result.success).toBe(true); expect(result.content).toBe('Authenticated transcript'); const expectedAuth = 'Basic ' + Buffer.from('user123:pass456').toString('base64'); expect(mockFetch).toHaveBeenCalledWith('https://example.com/transcript', { method: 'GET', headers: { 'User-Agent': 'LiveDash-Transcript-Fetcher/1.0', 'Authorization': expectedAuth, }, signal: expect.any(AbortSignal), }); }); it('should handle HTTP errors', async () => { const mockResponse = { ok: false, status: 404, statusText: 'Not Found', }; mockFetch.mockResolvedValue(mockResponse as any); const result = await fetchTranscriptContent('https://example.com/transcript'); expect(result.success).toBe(false); expect(result.error).toBe('HTTP 404: Not Found'); expect(result.content).toBeUndefined(); }); it('should handle empty transcript content', async () => { const mockResponse = { ok: true, text: jest.fn().mockResolvedValue(' '), }; mockFetch.mockResolvedValue(mockResponse as any); const result = await fetchTranscriptContent('https://example.com/transcript'); expect(result.success).toBe(false); expect(result.error).toBe('Empty transcript content'); expect(result.content).toBeUndefined(); }); it('should handle network errors', async () => { mockFetch.mockRejectedValue(new Error('ENOTFOUND example.com')); const result = await fetchTranscriptContent('https://example.com/transcript'); expect(result.success).toBe(false); expect(result.error).toBe('Domain not found'); expect(result.content).toBeUndefined(); }); it('should handle connection refused errors', async () => { mockFetch.mockRejectedValue(new Error('ECONNREFUSED')); const result = await fetchTranscriptContent('https://example.com/transcript'); expect(result.success).toBe(false); expect(result.error).toBe('Connection refused'); expect(result.content).toBeUndefined(); }); it('should handle timeout errors', async () => { mockFetch.mockRejectedValue(new Error('Request timeout')); const result = await fetchTranscriptContent('https://example.com/transcript'); expect(result.success).toBe(false); expect(result.error).toBe('Request timeout'); expect(result.content).toBeUndefined(); }); it('should handle empty URL', async () => { const result = await fetchTranscriptContent(''); expect(result.success).toBe(false); expect(result.error).toBe('No transcript URL provided'); expect(result.content).toBeUndefined(); expect(mockFetch).not.toHaveBeenCalled(); }); it('should trim whitespace from content', async () => { const mockResponse = { ok: true, text: jest.fn().mockResolvedValue(' \n Session content \n '), }; mockFetch.mockResolvedValue(mockResponse as any); const result = await fetchTranscriptContent('https://example.com/transcript'); expect(result.success).toBe(true); expect(result.content).toBe('Session content'); }); }); describe('isValidTranscriptUrl', () => { it('should validate HTTP URLs', () => { expect(isValidTranscriptUrl('http://example.com/transcript')).toBe(true); }); it('should validate HTTPS URLs', () => { expect(isValidTranscriptUrl('https://example.com/transcript')).toBe(true); }); it('should reject invalid URLs', () => { expect(isValidTranscriptUrl('not-a-url')).toBe(false); expect(isValidTranscriptUrl('ftp://example.com')).toBe(false); expect(isValidTranscriptUrl('')).toBe(false); expect(isValidTranscriptUrl(null as any)).toBe(false); expect(isValidTranscriptUrl(undefined as any)).toBe(false); }); it('should handle malformed URLs', () => { expect(isValidTranscriptUrl('http://')).toBe(false); expect(isValidTranscriptUrl('https://')).toBe(false); expect(isValidTranscriptUrl('://example.com')).toBe(false); }); }); describe('extractSessionIdFromTranscript', () => { it('should extract session ID from session_id pattern', () => { const content = 'session_id: abc123def456\nOther content...'; const result = extractSessionIdFromTranscript(content); expect(result).toBe('abc123def456'); }); it('should extract session ID from sessionId pattern', () => { const content = 'sessionId: xyz789\nTranscript data...'; const result = extractSessionIdFromTranscript(content); expect(result).toBe('xyz789'); }); it('should extract session ID from id pattern', () => { const content = 'id: session-12345678\nChat log...'; const result = extractSessionIdFromTranscript(content); expect(result).toBe('session-12345678'); }); it('should extract session ID from first line', () => { const content = 'abc123def456\nUser: Hello\nBot: Hi there'; const result = extractSessionIdFromTranscript(content); expect(result).toBe('abc123def456'); }); it('should return null for content without session ID', () => { const content = 'User: Hello\nBot: Hi there\nUser: How are you?'; const result = extractSessionIdFromTranscript(content); expect(result).toBe(null); }); it('should return null for empty content', () => { expect(extractSessionIdFromTranscript('')).toBe(null); expect(extractSessionIdFromTranscript(null as any)).toBe(null); expect(extractSessionIdFromTranscript(undefined as any)).toBe(null); }); it('should handle case-insensitive patterns', () => { const content = 'SESSION_ID: ABC123\nContent...'; const result = extractSessionIdFromTranscript(content); expect(result).toBe('ABC123'); }); it('should extract the first matching pattern', () => { const content = 'session_id: first123\nid: second456\nMore content...'; const result = extractSessionIdFromTranscript(content); expect(result).toBe('first123'); }); }); });