Files
tower/apps/worker/src/core/approval.test.ts
T
2026-06-09 02:02:40 +05:30

103 lines
3.7 KiB
TypeScript

import { handleReaction } from './approval';
import { approveMessage } from './approve-message';
import { NormalizedReaction } from '@tower/types';
jest.mock('./approve-message');
function makeReaction(overrides: Partial<NormalizedReaction> = {}): 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();
});
});