import { jest } from '@jest/globals' import type { ILogger } from '../../Utils/logger' import { processContactAction } from '../../Utils/sync-action-utils' describe('processContactAction', () => { const mockLogger: ILogger = { warn: jest.fn(), info: jest.fn(), debug: jest.fn(), error: jest.fn(), trace: jest.fn(), child: jest.fn(() => mockLogger), level: 'silent' } as unknown as ILogger beforeEach(() => { jest.clearAllMocks() }) describe('contacts.upsert', () => { it('emits with phoneNumber from id when id is PN user', () => { const action = { fullName: 'John Doe', lidJid: '123456789@lid', pnJid: null } const id = '5511999999999@s.whatsapp.net' const results = processContactAction(action, id) expect(results).toContainEqual({ event: 'contacts.upsert', data: [ { id: '5511999999999@s.whatsapp.net', name: 'John Doe', lid: '123456789@lid', phoneNumber: '5511999999999@s.whatsapp.net' } ] }) }) it('uses pnJid as phoneNumber fallback when id is LID user', () => { const action = { fullName: 'John Doe', lidJid: null, pnJid: '5511888888888@s.whatsapp.net' } const id = '123456789@lid' const results = processContactAction(action, id) expect(results).toContainEqual({ event: 'contacts.upsert', data: [ { id: '123456789@lid', name: 'John Doe', lid: undefined, phoneNumber: '5511888888888@s.whatsapp.net' } ] }) }) it('handles undefined fullName', () => { const action = { fullName: undefined, lidJid: '123456789@lid', pnJid: null } const id = '5511999999999@s.whatsapp.net' const results = processContactAction(action, id) const contactData = results.find(r => r.event === 'contacts.upsert')!.data expect(contactData[0]!.name).toBeUndefined() }) }) describe('lid-mapping.update', () => { it('emits when LID and PN are valid', () => { const action = { fullName: 'John Doe', lidJid: '123456789@lid', pnJid: null } const id = '5511999999999@s.whatsapp.net' const results = processContactAction(action, id) expect(results).toContainEqual({ event: 'lid-mapping.update', data: [{ lid: '123456789@lid', pn: '5511999999999@s.whatsapp.net' }] }) }) it('handles LID with device ID suffix', () => { const action = { fullName: 'Contact', lidJid: '173233882013816:99@lid', pnJid: null } const id = '5511999999999@s.whatsapp.net' const results = processContactAction(action, id) expect(results).toContainEqual({ event: 'lid-mapping.update', data: [{ lid: '173233882013816:99@lid', pn: '5511999999999@s.whatsapp.net' }] }) }) it('does NOT emit when lidJid is missing', () => { const action = { fullName: 'John Doe', lidJid: null, pnJid: null } const id = '5511999999999@s.whatsapp.net' const results = processContactAction(action, id) expect(results.find(r => r.event === 'lid-mapping.update')).toBeUndefined() }) it('does NOT emit when id is LID user (not PN)', () => { const action = { fullName: 'John Doe', lidJid: '123456789@lid', pnJid: null } const id = '987654321@lid' const results = processContactAction(action, id) expect(results.find(r => r.event === 'lid-mapping.update')).toBeUndefined() }) it('does NOT emit when lidJid is invalid format', () => { const action = { fullName: 'John Doe', lidJid: 'invalid-lid-format', pnJid: null } const id = '5511999999999@s.whatsapp.net' const results = processContactAction(action, id) expect(results.find(r => r.event === 'lid-mapping.update')).toBeUndefined() }) it('does NOT emit for group JIDs', () => { const action = { fullName: 'Group', lidJid: '123456789@lid', pnJid: null } const id = '123456789012345678@g.us' const results = processContactAction(action, id) expect(results.find(r => r.event === 'lid-mapping.update')).toBeUndefined() }) }) describe('missing id', () => { it('returns empty array and logs warning when id is undefined', () => { const action = { fullName: 'John Doe', lidJid: '123456789@lid', pnJid: null } const results = processContactAction(action, undefined, mockLogger) expect(results).toEqual([]) expect(mockLogger.warn).toHaveBeenCalledWith( { hasFullName: true, hasLidJid: true, hasPnJid: false }, 'contactAction sync: missing id in index' ) }) it('returns empty array when id is empty string', () => { const action = { fullName: 'John Doe', lidJid: '123456789@lid', pnJid: null } const results = processContactAction(action, '', mockLogger) expect(results).toEqual([]) }) }) describe('PN extraction from index[1] (pnJid is always null)', () => { it('extracts PN from id when pnJid is null', () => { // In real WhatsApp data, pnJid is ALWAYS null - PN comes from index[1] const action = { fullName: 'Test Contact', lidJid: '111222333@lid', pnJid: null } const id = '5599887766@s.whatsapp.net' const results = processContactAction(action, id) const contactData = results.find(r => r.event === 'contacts.upsert')!.data expect(contactData[0]!.phoneNumber).toBe('5599887766@s.whatsapp.net') expect(contactData[0]!.lid).toBe('111222333@lid') const mapping = results.find(r => r.event === 'lid-mapping.update')!.data expect(mapping).toEqual({ lid: '111222333@lid', pn: '5599887766@s.whatsapp.net' }) }) it('prefers id over pnJid when id is PN user', () => { const action = { fullName: 'Test', lidJid: '111222333@lid', pnJid: '1111111111@s.whatsapp.net' } const id = '9999999999@s.whatsapp.net' const results = processContactAction(action, id) const contactData = results.find(r => r.event === 'contacts.upsert')!.data expect(contactData[0]!.phoneNumber).toBe('9999999999@s.whatsapp.net') const mapping = results.find(r => r.event === 'lid-mapping.update')!.data expect(mapping.pn).toBe('9999999999@s.whatsapp.net') }) }) })