UNPKG

@chargetrip/mcp

Version:

Chargetrip MCP server

415 lines (348 loc) 14.4 kB
import { GraphQLError } from 'graphql'; import { FetchAndProcessUtil } from '../fetch-and-process'; import { GraphQLClient } from '../graphql-client'; jest.mock('../graphql-client'); describe('FetchAndProcessUtil', () => { let mockGraphQLClient: jest.Mocked<GraphQLClient>; beforeEach(() => { mockGraphQLClient = { query: jest.fn(), mutate: jest.fn(), subscription: jest.fn(), } as any; (GraphQLClient.getInstance as jest.Mock).mockReturnValue(mockGraphQLClient); }); afterEach(() => { jest.clearAllMocks(); }); describe('getList', () => { const mockQuery = 'query { list { id name } }'; const mockVariables = { filter: 'test' }; const mockMapFunction = (item: { id: string; name: string }) => `${item.id}: ${item.name}`; it('should return formatted list when data is successfully fetched', async () => { const mockData = { list: [ { id: '1', name: 'Item 1' }, { id: '2', name: 'Item 2' }, ], }; // @ts-ignore: Ignoring type errors for testing purposes mockGraphQLClient.query.mockResolvedValue({ data: mockData, error: null }); const result = await FetchAndProcessUtil.getList({ query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(4); expect(result.content[0]).toEqual({ type: 'text', text: 'Here is the response of the API for the list:', }); expect(result.content[1]).toEqual({ type: 'text', text: '1: Item 1\n2: Item 2' }); expect(result.content[2]).toEqual({ type: 'text', text: 'Here is the query that was used to fetch the list:', }); expect(result.content[3]).toEqual({ type: 'text', text: `Query: "${mockQuery}"\nVariables: "${JSON.stringify(mockVariables, null, 2)}"`, }); }); it('should handle GraphQL error from response', async () => { mockGraphQLClient.query.mockResolvedValue({ data: null, // @ts-ignore: Ignoring type errors for testing purposes error: { message: 'GraphQL error message' }, }); const result = await FetchAndProcessUtil.getList({ query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: 'GraphQL error occurred while fetching the list: GraphQL error message', }); }); it('should handle empty list', async () => { // @ts-ignore: Ignoring type errors for testing purposes mockGraphQLClient.query.mockResolvedValue({ data: { list: [] }, error: null }); const result = await FetchAndProcessUtil.getList({ query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: 'Unexpected error occurred while fetching the list: No data found or an error occurred while fetching the list.', }); }); it('should handle null data', async () => { // @ts-ignore: Ignoring type errors for testing purposes mockGraphQLClient.query.mockResolvedValue({ data: null, error: null }); const result = await FetchAndProcessUtil.getList({ query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: 'Unexpected error occurred while fetching the list: No data found or an error occurred while fetching the list.', }); }); it('should handle unexpected errors', async () => { mockGraphQLClient.query.mockRejectedValue(new Error('Network error')); const result = await FetchAndProcessUtil.getList({ query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: 'Unexpected error occurred while fetching the list: Network error', }); }); it('should handle non-Error exceptions', async () => { mockGraphQLClient.query.mockRejectedValue('String error'); const result = await FetchAndProcessUtil.getList({ query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: 'Unexpected error occurred while fetching the list: String error', }); }); }); describe('getItem', () => { const mockItemName = 'test-item'; const mockQuery = 'query { item { id name } }'; const mockVariables = { id: '1' }; const mockMapFunction = (item: { id: string; name: string }) => `${item.id}: ${item.name}`; it('should return formatted item when query is successful', async () => { const mockData = { item: { id: '1', name: 'Test Item' } }; // @ts-ignore: Ignoring type errors for testing purposes mockGraphQLClient.query.mockResolvedValue({ data: mockData, error: null }); const result = await FetchAndProcessUtil.getItem({ itemName: mockItemName, query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(4); expect(result.content[0]).toEqual({ type: 'text', text: `Here is the response of the API for the ${mockItemName}:`, }); expect(result.content[1]).toEqual({ type: 'text', text: '1: Test Item' }); expect(result.content[2]).toEqual({ type: 'text', text: `Here is the query that was used to fetch the ${mockItemName}:`, }); }); it('should use mutation when operationType is mutation', async () => { const mockData = { item: { id: '1', name: 'Test Item' } }; // @ts-ignore: Ignoring type errors for testing purposes mockGraphQLClient.mutate.mockResolvedValue({ data: mockData, error: null }); await FetchAndProcessUtil.getItem({ itemName: mockItemName, query: mockQuery, variables: mockVariables, operationType: 'mutation', mapFunction: mockMapFunction, }); expect(mockGraphQLClient.mutate).toHaveBeenCalledWith(mockQuery, mockVariables); expect(mockGraphQLClient.query).not.toHaveBeenCalled(); }); it('should use query when operationType is query', async () => { const mockData = { item: { id: '1', name: 'Test Item' } }; // @ts-ignore: Ignoring type errors for testing purposes mockGraphQLClient.query.mockResolvedValue({ data: mockData, error: null }); await FetchAndProcessUtil.getItem({ itemName: mockItemName, query: mockQuery, variables: mockVariables, operationType: 'query', mapFunction: mockMapFunction, }); expect(mockGraphQLClient.query).toHaveBeenCalledWith(mockQuery, mockVariables); expect(mockGraphQLClient.mutate).not.toHaveBeenCalled(); }); it('should handle GraphQL error from response', async () => { mockGraphQLClient.query.mockResolvedValue({ data: null, // @ts-ignore: Ignoring type errors for testing purposes error: { message: 'Item not found' }, }); const result = await FetchAndProcessUtil.getItem({ itemName: mockItemName, query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: `GraphQL error occurred while fetching the ${mockItemName}: Item not found`, }); }); it('should handle null item data', async () => { // @ts-ignore: Ignoring type errors for testing purposes mockGraphQLClient.query.mockResolvedValue({ data: { item: null }, error: null }); const result = await FetchAndProcessUtil.getItem({ itemName: mockItemName, query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: `Unexpected error occurred while fetching the ${mockItemName}: No data found or an error occurred while fetching the data.`, }); }); it('should handle unexpected errors', async () => { mockGraphQLClient.query.mockRejectedValue(new Error('Network error')); const result = await FetchAndProcessUtil.getItem({ itemName: mockItemName, query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: `Unexpected error occurred while fetching the ${mockItemName}: Network error`, }); }); it('should handle non-Error exceptions', async () => { mockGraphQLClient.query.mockRejectedValue('String error'); const result = await FetchAndProcessUtil.getItem({ itemName: mockItemName, query: mockQuery, variables: mockVariables, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: `Unexpected error occurred while fetching the ${mockItemName}: String error`, }); }); }); describe('getItemFromSubscription', () => { const mockItemName = 'subscription-item'; const mockQuery = 'subscription { item { id status } }'; const mockVariables = { id: '1' }; const mockMapFunction = (item: { id: string; status: string }) => `${item.id}: ${item.status}`; const mockSubscribeFunction = (item: { id: string; status: string }) => item.status === 'completed'; it('should return formatted item when subscription resolves', async () => { const mockData = { id: '1', status: 'completed' }; const mockUnsubscribe = jest.fn(); const mockSubscribe = jest.fn(callback => { setTimeout(() => callback({ data: mockData }), 0); return { unsubscribe: mockUnsubscribe }; }); // @ts-ignore: Ignoring type errors for testing purposes mockGraphQLClient.subscription.mockReturnValue({ subscribe: mockSubscribe }); const result = await FetchAndProcessUtil.getItemFromSubscription({ itemName: mockItemName, query: mockQuery, variables: mockVariables, subscribeFunction: mockSubscribeFunction, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(4); expect(result.content[0]).toEqual({ type: 'text', text: `Here is the response of the API for the ${mockItemName}:`, }); expect(result.content[1]).toEqual({ type: 'text', text: '1: completed' }); expect(mockUnsubscribe).toHaveBeenCalled(); }); it('should continue subscription until condition is met', async () => { const mockUnsubscribe = jest.fn(); let callCount = 0; const mockSubscribe = jest.fn(callback => { const interval = setInterval(() => { callCount++; const status = callCount < 3 ? 'processing' : 'completed'; callback({ data: { id: '1', status } }); if (status === 'completed') { clearInterval(interval); } }, 0); return { unsubscribe: mockUnsubscribe }; }); // @ts-ignore: Ignoring type errors for testing purposes mockGraphQLClient.subscription.mockReturnValue({ subscribe: mockSubscribe }); const result = await FetchAndProcessUtil.getItemFromSubscription({ itemName: mockItemName, query: mockQuery, variables: mockVariables, subscribeFunction: mockSubscribeFunction, mapFunction: mockMapFunction, }); expect(result.content[1]).toEqual({ type: 'text', text: '1: completed' }); expect(mockUnsubscribe).toHaveBeenCalled(); }); it('should handle GraphQL errors in subscription', async () => { mockGraphQLClient.subscription.mockImplementation(() => { throw new GraphQLError('Subscription error'); }); const result = await FetchAndProcessUtil.getItemFromSubscription({ itemName: mockItemName, query: mockQuery, variables: mockVariables, subscribeFunction: mockSubscribeFunction, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: 'GraphQL error occurred while waiting for the subscription-item: Subscription error', }); }); it('should handle unexpected errors in subscription', async () => { mockGraphQLClient.subscription.mockImplementation(() => { throw new Error('Network error'); }); const result = await FetchAndProcessUtil.getItemFromSubscription({ itemName: mockItemName, query: mockQuery, variables: mockVariables, subscribeFunction: mockSubscribeFunction, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: 'Unexpected error occurred while waiting for the subscription-item: Network error', }); }); it('should handle non-Error exceptions in subscription', async () => { mockGraphQLClient.subscription.mockImplementation(() => { throw 'String subscription error'; }); const result = await FetchAndProcessUtil.getItemFromSubscription({ itemName: mockItemName, query: mockQuery, variables: mockVariables, subscribeFunction: mockSubscribeFunction, mapFunction: mockMapFunction, }); expect(result.content).toHaveLength(1); expect(result.content[0]).toEqual({ type: 'text', text: 'Unexpected error occurred while waiting for the subscription-item: String subscription error', }); }); }); });