import { handleReaction } from './approval'; import { approveMessage } from './approve-message'; import { NormalizedReaction } from '@tower/types'; jest.mock('./approve-message'); function makeReaction(overrides: Partial = {}): NormalizedReaction { return { reactorJid: '919876543210@s.whatsapp.net', targetMsgId: 'TARGET_MSG_123', sourceGroupJid: '120363043312345678@g.us', emoji: '⭐', accountId: 'acc_1', ...overrides, }; } function makeMessage(overrides: object = {}) { return { id: 'msg_1', tenantId: 'tnt_1', status: 'PENDING', sourceGroup: { platformId: '120363043312345678@g.us' }, ...overrides, }; } function makePool(isAdmin: boolean) { return { get: jest.fn().mockReturnValue({ groupMetadata: jest.fn().mockResolvedValue({ participants: [ { id: '919876543210@s.whatsapp.net', admin: isAdmin ? 'admin' : undefined }, { id: 'other@s.whatsapp.net', admin: 'superadmin' }, ], }), }), }; } const mockPrisma = { message: { findUnique: jest.fn() }, tenantRule: { findMany: jest.fn() }, }; const mockForwardQueue = { add: jest.fn() }; const mockIndexQueue = { add: jest.fn() }; describe('handleReaction', () => { beforeEach(() => { jest.clearAllMocks(); mockPrisma.message.findUnique.mockResolvedValue(makeMessage()); (approveMessage as jest.Mock).mockResolvedValue({ forwardJobs: [], indexDoc: {} }); }); it('returns null when message not found', async () => { mockPrisma.message.findUnique.mockResolvedValue(null); expect(await handleReaction(makeReaction(), mockPrisma, makePool(true))).toBeNull(); }); it('returns null when message is not PENDING', async () => { mockPrisma.message.findUnique.mockResolvedValue(makeMessage({ status: 'APPROVED' })); expect(await handleReaction(makeReaction(), mockPrisma, makePool(true))).toBeNull(); }); it('returns null when no reaction rule matches', async () => { mockPrisma.tenantRule.findMany.mockResolvedValue([]); expect(await handleReaction(makeReaction(), mockPrisma, makePool(true))).toBeNull(); }); it('returns null when reactor is not a group admin', async () => { mockPrisma.tenantRule.findMany.mockResolvedValue([ { id: 'r1', matchType: 'REACTION_EMOJI', matchValue: '⭐', action: 'AUTO_APPROVE', priority: 0 }, ]); expect(await handleReaction(makeReaction(), mockPrisma, makePool(false))).toBeNull(); }); it('approves when reactor is admin and reaction rule matches', async () => { mockPrisma.tenantRule.findMany.mockResolvedValue([ { id: 'r1', matchType: 'REACTION_EMOJI', matchValue: '⭐', action: 'AUTO_APPROVE', priority: 0 }, ]); const result = await handleReaction(makeReaction(), mockPrisma, makePool(true)); expect(result).not.toBeNull(); expect(approveMessage).toHaveBeenCalledWith('msg_1', 'tnt_1', '919876543210@s.whatsapp.net', mockPrisma); }); it('returns null when socket not available', async () => { mockPrisma.tenantRule.findMany.mockResolvedValue([ { id: 'r1', matchType: 'REACTION_EMOJI', matchValue: '⭐', action: 'AUTO_APPROVE', priority: 0 }, ]); const pool = { get: jest.fn().mockReturnValue(undefined) }; expect(await handleReaction(makeReaction(), mockPrisma, pool)).toBeNull(); }); it('returns null when approveMessage returns null', async () => { mockPrisma.tenantRule.findMany.mockResolvedValue([ { id: 'r1', matchType: 'REACTION_EMOJI', matchValue: '⭐', action: 'AUTO_APPROVE', priority: 0 }, ]); (approveMessage as jest.Mock).mockResolvedValue(null); expect(await handleReaction(makeReaction(), mockPrisma, makePool(true))).toBeNull(); }); });