diff --git a/components/email/__tests__/recipient-popover.test.tsx b/components/email/__tests__/recipient-popover.test.tsx new file mode 100644 index 000000000..9a5306720 --- /dev/null +++ b/components/email/__tests__/recipient-popover.test.tsx @@ -0,0 +1,39 @@ +import { fireEvent, render, screen } from '@testing-library/react'; +import { afterEach, describe, expect, it } from 'vitest'; +import React from 'react'; +import { RecipientPopover } from '../recipient-popover'; +import { useContactStore } from '@/stores/contact-store'; +import type { ContactCard } from '@/lib/jmap/types'; + +// A saved contact without a name made the popover show only the address, +// even though the message header named the sender. + +const address = 'wordpress@example.org'; + +function setContacts(contacts: ContactCard[]) { + useContactStore.setState({ contacts }); +} + +function openPopover() { + render(); + fireEvent.click(screen.getByRole('button', { name: 'WordPress' })); +} + +describe('RecipientPopover', () => { + afterEach(() => setContacts([])); + + it('shows the header name and the address when a matching contact has no name', () => { + setContacts([{ id: 'c1', emails: { e1: { address } } } as unknown as ContactCard]); + openPopover(); + const header = screen.getAllByText('WordPress'); + expect(header.length).toBe(2); + expect(screen.getByText(address)).toBeTruthy(); + }); + + it('prefers the contact name over the header name', () => { + setContacts([{ id: 'c1', name: { full: 'WP Blog' }, emails: { e1: { address } } } as unknown as ContactCard]); + openPopover(); + expect(screen.getByText('WP Blog')).toBeTruthy(); + expect(screen.getByText(address)).toBeTruthy(); + }); +}); diff --git a/components/email/recipient-popover.tsx b/components/email/recipient-popover.tsx index 09c53bb8f..929aa84c2 100644 --- a/components/email/recipient-popover.tsx +++ b/components/email/recipient-popover.tsx @@ -37,8 +37,13 @@ export function RecipientPopover({ name, email, displayLabel, onViewContact, cla ); }); - const contactName = contact ? getContactDisplayName(contact) : name; const emails = contact?.emails ? Object.values(contact.emails) : []; + // A contact without a name falls back to its address; prefer the name from + // the message header in that case. + const contactDisplayName = contact ? getContactDisplayName(contact) : ''; + const contactHasName = !!contactDisplayName && + !emails.some((e) => e.address.toLowerCase() === contactDisplayName.toLowerCase()); + const contactName = (contactHasName ? contactDisplayName : name) || contactDisplayName; const phones = contact?.phones ? Object.values(contact.phones) : []; const orgs = contact?.organizations ? Object.values(contact.organizations) : []; @@ -160,7 +165,7 @@ export function RecipientPopover({ name, email, displayLabel, onViewContact, cla
{contactName || shownEmail}
- {contactName && contactName !== email && ( + {contactName && contactName.toLowerCase() !== email.toLowerCase() && (
{shownEmail}