import { extractPlainTextFromHtml, getEmailSenderName, getEmailSenderEmail, getEmailDate, formatQuotedEmailDate, getInboxEmail, buildQuotedEmailHeader, buildQuotedEmailHeaderFromContact, buildQuotedEmailHeaderFromInbox, formatQuotedTextAsBlockquote, extractQuotedEmailText, truncatePreviewText, appendQuotedTextToMessage, } from '../quotedEmailHelper'; describe('quotedEmailHelper', () => { describe('extractPlainTextFromHtml', () => { it('returns empty string for null or undefined', () => { expect(extractPlainTextFromHtml(null)).toBe(''); expect(extractPlainTextFromHtml(undefined)).toBe(''); }); it('strips HTML tags and returns plain text', () => { const html = '

Hello world

'; const result = extractPlainTextFromHtml(html); expect(result).toBe('Hello world'); }); it('handles complex HTML structure', () => { const html = '

Line 1

Line 2

'; const result = extractPlainTextFromHtml(html); expect(result).toContain('Line 1'); expect(result).toContain('Line 2'); }); }); describe('getEmailSenderName', () => { it('returns sender name from lastEmail', () => { const lastEmail = { sender: { name: 'John Doe' } }; const result = getEmailSenderName(lastEmail, {}); expect(result).toBe('John Doe'); }); it('returns contact name if sender name not available', () => { const lastEmail = { sender: {} }; const contact = { name: 'Jane Smith' }; const result = getEmailSenderName(lastEmail, contact); expect(result).toBe('Jane Smith'); }); it('returns empty string if neither available', () => { const result = getEmailSenderName({}, {}); expect(result).toBe(''); }); it('trims whitespace from names', () => { const lastEmail = { sender: { name: ' John Doe ' } }; const result = getEmailSenderName(lastEmail, {}); expect(result).toBe('John Doe'); }); }); describe('getEmailSenderEmail', () => { it('returns sender email from lastEmail', () => { const lastEmail = { sender: { email: 'john@example.com' } }; const result = getEmailSenderEmail(lastEmail, {}); expect(result).toBe('john@example.com'); }); it('returns email from contentAttributes if sender email not available', () => { const lastEmail = { contentAttributes: { email: { from: ['jane@example.com'] }, }, }; const result = getEmailSenderEmail(lastEmail, {}); expect(result).toBe('jane@example.com'); }); it('returns contact email as fallback', () => { const lastEmail = {}; const contact = { email: 'contact@example.com' }; const result = getEmailSenderEmail(lastEmail, contact); expect(result).toBe('contact@example.com'); }); it('trims whitespace from emails', () => { const lastEmail = { sender: { email: ' john@example.com ' } }; const result = getEmailSenderEmail(lastEmail, {}); expect(result).toBe('john@example.com'); }); }); describe('getEmailDate', () => { it('returns parsed date from email metadata', () => { const lastEmail = { contentAttributes: { email: { date: '2024-01-15T10:30:00Z' }, }, }; const result = getEmailDate(lastEmail); expect(result).toBeInstanceOf(Date); }); it('returns date from created_at timestamp', () => { const lastEmail = { created_at: 1705318200 }; const result = getEmailDate(lastEmail); expect(result).toBeInstanceOf(Date); }); it('handles millisecond timestamps', () => { const lastEmail = { created_at: 1705318200000 }; const result = getEmailDate(lastEmail); expect(result).toBeInstanceOf(Date); }); it('returns null if no valid date found', () => { const result = getEmailDate({}); expect(result).toBeNull(); }); }); describe('formatQuotedEmailDate', () => { it('formats date correctly', () => { const date = new Date('2024-01-15T10:30:00Z'); const result = formatQuotedEmailDate(date); expect(result).toMatch(/Mon, Jan 15, 2024 at/); }); it('returns empty string for invalid date', () => { const result = formatQuotedEmailDate('invalid'); expect(result).toBe(''); }); }); describe('getInboxEmail', () => { it('returns email from contentAttributes.email.to', () => { const lastEmail = { contentAttributes: { email: { to: ['inbox@example.com'] }, }, }; const result = getInboxEmail(lastEmail, {}); expect(result).toBe('inbox@example.com'); }); it('returns inbox email as fallback', () => { const lastEmail = {}; const inbox = { email: 'support@example.com' }; const result = getInboxEmail(lastEmail, inbox); expect(result).toBe('support@example.com'); }); it('returns empty string if no email found', () => { expect(getInboxEmail({}, {})).toBe(''); }); it('trims whitespace from emails', () => { const lastEmail = { contentAttributes: { email: { to: [' inbox@example.com '] }, }, }; const result = getInboxEmail(lastEmail, {}); expect(result).toBe('inbox@example.com'); }); }); describe('buildQuotedEmailHeaderFromContact', () => { it('builds complete header with name and email', () => { const lastEmail = { sender: { name: 'John Doe', email: 'john@example.com' }, contentAttributes: { email: { date: '2024-01-15T10:30:00Z' }, }, }; const result = buildQuotedEmailHeaderFromContact(lastEmail, {}); expect(result).toContain('John Doe'); expect(result).toContain('john@example.com'); expect(result).toContain('wrote:'); }); it('builds header without name if not available', () => { const lastEmail = { sender: { email: 'john@example.com' }, contentAttributes: { email: { date: '2024-01-15T10:30:00Z' }, }, }; const result = buildQuotedEmailHeaderFromContact(lastEmail, {}); expect(result).toContain(''); expect(result).not.toContain('undefined'); }); it('returns empty string if missing required data', () => { expect(buildQuotedEmailHeaderFromContact(null, {})).toBe(''); expect(buildQuotedEmailHeaderFromContact({}, {})).toBe(''); }); }); describe('buildQuotedEmailHeaderFromInbox', () => { it('builds complete header with inbox name and email', () => { const lastEmail = { contentAttributes: { email: { date: '2024-01-15T10:30:00Z', to: ['support@example.com'], }, }, }; const inbox = { name: 'Support Team', email: 'support@example.com' }; const result = buildQuotedEmailHeaderFromInbox(lastEmail, inbox); expect(result).toContain('Support Team'); expect(result).toContain('support@example.com'); expect(result).toContain('wrote:'); }); it('builds header without name if not available', () => { const lastEmail = { contentAttributes: { email: { date: '2024-01-15T10:30:00Z', to: ['inbox@example.com'], }, }, }; const inbox = { email: 'inbox@example.com' }; const result = buildQuotedEmailHeaderFromInbox(lastEmail, inbox); expect(result).toContain(''); expect(result).not.toContain('undefined'); }); it('returns empty string if missing required data', () => { expect(buildQuotedEmailHeaderFromInbox(null, {})).toBe(''); expect(buildQuotedEmailHeaderFromInbox({}, {})).toBe(''); }); }); describe('buildQuotedEmailHeader', () => { it('uses inbox email for outgoing messages (message_type: 1)', () => { const lastEmail = { message_type: 1, contentAttributes: { email: { date: '2024-01-15T10:30:00Z', to: ['support@example.com'], }, }, }; const inbox = { name: 'Support', email: 'support@example.com' }; const contact = { name: 'John Doe', email: 'john@example.com' }; const result = buildQuotedEmailHeader(lastEmail, contact, inbox); expect(result).toContain('Support'); expect(result).toContain('support@example.com'); expect(result).not.toContain('John Doe'); }); it('uses contact email for incoming messages (message_type: 0)', () => { const lastEmail = { message_type: 0, sender: { name: 'Jane Smith', email: 'jane@example.com' }, contentAttributes: { email: { date: '2024-01-15T10:30:00Z' }, }, }; const inbox = { name: 'Support', email: 'support@example.com' }; const contact = { name: 'Jane Smith', email: 'jane@example.com' }; const result = buildQuotedEmailHeader(lastEmail, contact, inbox); expect(result).toContain('Jane Smith'); expect(result).toContain('jane@example.com'); expect(result).not.toContain('Support'); }); it('returns empty string if missing required data', () => { expect(buildQuotedEmailHeader(null, {}, {})).toBe(''); expect(buildQuotedEmailHeader({}, {}, {})).toBe(''); }); }); describe('formatQuotedTextAsBlockquote', () => { it('formats single line text', () => { const result = formatQuotedTextAsBlockquote('Hello world'); expect(result).toBe('> Hello world'); }); it('formats multi-line text', () => { const text = 'Line 1\nLine 2\nLine 3'; const result = formatQuotedTextAsBlockquote(text); expect(result).toBe('> Line 1\n> Line 2\n> Line 3'); }); it('includes header if provided', () => { const result = formatQuotedTextAsBlockquote('Hello', 'Header text'); expect(result).toContain('> Header text'); expect(result).toContain('>\n> Hello'); }); it('handles empty lines correctly', () => { const text = 'Line 1\n\nLine 3'; const result = formatQuotedTextAsBlockquote(text); expect(result).toBe('> Line 1\n>\n> Line 3'); }); it('returns empty string for empty input', () => { expect(formatQuotedTextAsBlockquote('')).toBe(''); expect(formatQuotedTextAsBlockquote('', '')).toBe(''); }); it('handles Windows line endings', () => { const text = 'Line 1\r\nLine 2'; const result = formatQuotedTextAsBlockquote(text); expect(result).toBe('> Line 1\n> Line 2'); }); }); describe('extractQuotedEmailText', () => { it('extracts text from textContent.reply', () => { const lastEmail = { contentAttributes: { email: { textContent: { reply: 'Reply text' } }, }, }; const result = extractQuotedEmailText(lastEmail); expect(result).toBe('Reply text'); }); it('falls back to textContent.full', () => { const lastEmail = { contentAttributes: { email: { textContent: { full: 'Full text' } }, }, }; const result = extractQuotedEmailText(lastEmail); expect(result).toBe('Full text'); }); it('extracts from htmlContent and converts to plain text', () => { const lastEmail = { contentAttributes: { email: { htmlContent: { reply: '

HTML reply

' } }, }, }; const result = extractQuotedEmailText(lastEmail); expect(result).toBe('HTML reply'); }); it('uses fallback content if structured content not available', () => { const lastEmail = { content: 'Fallback content' }; const result = extractQuotedEmailText(lastEmail); expect(result).toBe('Fallback content'); }); it('returns empty string for null or missing email', () => { expect(extractQuotedEmailText(null)).toBe(''); expect(extractQuotedEmailText({})).toBe(''); }); }); describe('truncatePreviewText', () => { it('returns full text if under max length', () => { const text = 'Short text'; const result = truncatePreviewText(text, 80); expect(result).toBe('Short text'); }); it('truncates text exceeding max length', () => { const text = 'A'.repeat(100); const result = truncatePreviewText(text, 80); expect(result).toHaveLength(80); expect(result).toContain('...'); }); it('collapses multiple spaces', () => { const text = 'Text with spaces'; const result = truncatePreviewText(text); expect(result).toBe('Text with spaces'); }); it('trims whitespace', () => { const text = ' Text with spaces '; const result = truncatePreviewText(text); expect(result).toBe('Text with spaces'); }); it('returns empty string for empty input', () => { expect(truncatePreviewText('')).toBe(''); expect(truncatePreviewText(' ')).toBe(''); }); it('uses default max length of 80', () => { const text = 'A'.repeat(100); const result = truncatePreviewText(text); expect(result).toHaveLength(80); }); }); describe('appendQuotedTextToMessage', () => { it('appends quoted text to message', () => { const message = 'My reply'; const quotedText = 'Original message'; const header = 'On date sender wrote:'; const result = appendQuotedTextToMessage(message, quotedText, header); expect(result).toContain('My reply'); expect(result).toContain('> On date sender wrote:'); expect(result).toContain('> Original message'); }); it('returns only quoted text if message is empty', () => { const result = appendQuotedTextToMessage('', 'Quoted', 'Header'); expect(result).toContain('> Header'); expect(result).toContain('> Quoted'); expect(result).not.toContain('\n\n\n'); }); it('returns message if no quoted text', () => { const result = appendQuotedTextToMessage('Message', '', ''); expect(result).toBe('Message'); }); it('handles proper spacing with double newline', () => { const result = appendQuotedTextToMessage('Message', 'Quoted', 'Header'); expect(result).toContain('Message\n\n>'); }); it('does not add extra newlines if message already ends with newlines', () => { const result = appendQuotedTextToMessage( 'Message\n\n', 'Quoted', 'Header' ); expect(result).not.toContain('\n\n\n'); }); it('adds single newline if message ends with one newline', () => { const result = appendQuotedTextToMessage('Message\n', 'Quoted', 'Header'); expect(result).toContain('Message\n\n>'); }); }); });