UNPKG

@hashgraphonline/conversational-agent

Version:

Hashgraph Online conversational AI agent implementing HCS-10 communication, HCS-2 registries, and content inscription on Hedera. https://hol.org

134 lines (112 loc) 5.18 kB
import { describe, expect, it, beforeEach, jest } from '@jest/globals'; import './SwarmTool.mocks'; import { ReadFeedTool } from '../../tools/ReadFeedTool'; import { beeMock, contextMock, swarmConfigMock } from './SwarmTool.mocks'; import { getErrorMessage, getResponseWithStructuredContent } from '../../utils'; import { BAD_REQUEST_STATUS } from '../../constants'; import { HederaAgentKit } from 'hedera-agent-kit'; describe('ReadFeedTool', () => { let tool: ReadFeedTool; let hederaKitMock: HederaAgentKit; beforeEach(() => { jest.clearAllMocks(); hederaKitMock = {} as HederaAgentKit; tool = new ReadFeedTool({ hederaKit: hederaKitMock, config: { ...swarmConfigMock, beeFeedPK: 'a'.repeat(64) }, bee: beeMock, logger: contextMock.logger, }); }); it('should throw if memoryTopic is missing', async () => { await expect(tool['executeQuery']({ memoryTopic: '' } as any)) .rejects.toThrow('Missing required parameter: memoryTopic.'); expect(contextMock.logger.error).toHaveBeenCalledWith( 'Missing required parameter: memoryTopic.' ); }); it('should throw if feed private key is missing', async () => { tool.config.beeFeedPK = ''; await expect(tool['executeQuery']({ memoryTopic: 'my-topic' })) .rejects.toThrow('Feed private key not configured.'); expect(contextMock.logger.error).toHaveBeenCalledWith( 'Feed private key not configured.' ); }); it('should throw if owner is invalid', async () => { await expect(tool['executeQuery']({ memoryTopic: 'topic', owner: '0x123' })) .rejects.toThrow('Owner must be a valid Ethereum address.'); expect(contextMock.logger.error).toHaveBeenCalledWith( 'Owner must be a valid Ethereum address.' ); }); it('should hash non-hex topic', async () => { const topic = 'nonHexTopic'; const downloadMock = jest.fn().mockReturnValueOnce({ payload: { toUtf8: () => 'feed-data' }, }); const makeFeedReaderMock = jest.fn().mockReturnValue({ downloadPayload: downloadMock, }); (beeMock.makeFeedReader as unknown as jest.Mock).mockImplementation(makeFeedReaderMock); const result = await tool['executeQuery']({ memoryTopic: topic }); expect(result).toEqual(getResponseWithStructuredContent({ textData: 'feed-data' })); }); it('should remove 0x prefix from hex topic and owner', async () => { const topic = '0x' + 'a'.repeat(64); const owner = '0x' + 'b'.repeat(40); const downloadMock = jest.fn().mockReturnValueOnce({ payload: { toUtf8: () => 'feed-data' }, }); const makeFeedReaderMock = jest.fn().mockReturnValue({ downloadPayload: downloadMock, }); (beeMock.makeFeedReader as unknown as jest.Mock).mockImplementation(makeFeedReaderMock); const result = await tool['executeQuery']({ memoryTopic: topic, owner }); expect(makeFeedReaderMock).toHaveBeenCalled(); expect(result).toEqual(getResponseWithStructuredContent({ textData: 'feed-data' })); }); it('should use feed private key to derive owner if not provided', async () => { const topic = '0x' + 'a'.repeat(64); const downloadMock = jest.fn().mockReturnValueOnce({ payload: { toUtf8: () => 'feed-data' }, }); const makeFeedReaderMock = jest.fn().mockReturnValue({ downloadPayload: downloadMock, }); (beeMock.makeFeedReader as unknown as jest.Mock).mockImplementation(makeFeedReaderMock); const result = await tool['executeQuery']({ memoryTopic: topic }); expect(result).toEqual(getResponseWithStructuredContent({ textData: 'feed-data' })); }); it('should handle BAD_REQUEST_STATUS error from feed', async () => { const topic = '0x' + 'a'.repeat(64); getErrorMessage as jest.MockedFunction<typeof getErrorMessage>; (getErrorMessage as jest.Mock).mockReturnValue('Custom bad request message.'); const error = new Error('Custom bad request message.'); (error as any).status = BAD_REQUEST_STATUS; (beeMock.makeFeedReader as unknown as jest.Mock).mockImplementation(() => { throw error; }); await expect(tool['executeQuery']({ memoryTopic: topic })) .rejects.toThrow('Custom bad request message.'); expect(contextMock.logger.error).toHaveBeenCalledWith( 'Custom bad request message.', expect.anything() ); }); it('should handle generic error from feed', async () => { const topic = '0x' + 'a'.repeat(64); getErrorMessage as jest.MockedFunction<typeof getErrorMessage>; (getErrorMessage as jest.Mock).mockReturnValue('Custom bad request message.'); const error = new Error('Custom bad request message.'); (beeMock.makeFeedReader as unknown as jest.Mock).mockImplementation(() => { throw error; }); await expect(tool['executeQuery']({ memoryTopic: topic })) .rejects.toThrow('Reading feed failed.'); expect(contextMock.logger.error).toHaveBeenCalledWith( 'Reading feed failed.', expect.anything() ); }); });