Skip to main content
Glama
by calebl
ListBudgetsTool.test.ts7.4 kB
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest'; import * as ynab from 'ynab'; import * as ListBudgetsTool from '../tools/ListBudgetsTool'; vi.mock('ynab'); describe('ListBudgetsTool', () => { let mockApi: { budgets: { getBudgets: Mock; }; }; beforeEach(() => { vi.clearAllMocks(); mockApi = { budgets: { getBudgets: vi.fn(), }, }; (ynab.API as any).mockImplementation(() => mockApi); process.env.YNAB_API_TOKEN = 'test-token'; }); describe('execute', () => { const mockBudgetsData = [ { id: 'budget-1', name: 'My Personal Budget', last_modified_on: '2023-01-01T00:00:00Z', first_month: '2023-01-01', last_month: '2023-12-01', date_format: { format: 'MM/DD/YYYY', }, currency_format: { iso_code: 'USD', example_format: '123,456.78', decimal_digits: 2, decimal_separator: '.', symbol_first: true, group_separator: ',', currency_symbol: '$', display_symbol: true, }, }, { id: 'budget-2', name: 'Family Budget', last_modified_on: '2023-01-02T00:00:00Z', first_month: '2023-01-01', last_month: '2023-12-01', date_format: { format: 'DD/MM/YYYY', }, currency_format: { iso_code: 'EUR', example_format: '123.456,78', decimal_digits: 2, decimal_separator: ',', symbol_first: false, group_separator: '.', currency_symbol: '€', display_symbol: true, }, }, { id: 'budget-3', name: 'Business Budget', last_modified_on: '2023-01-03T00:00:00Z', first_month: '2023-01-01', last_month: '2023-12-01', date_format: { format: 'YYYY-MM-DD', }, currency_format: { iso_code: 'GBP', example_format: '£123,456.78', decimal_digits: 2, decimal_separator: '.', symbol_first: true, group_separator: ',', currency_symbol: '£', display_symbol: true, }, }, ]; it('should successfully list all budgets', async () => { mockApi.budgets.getBudgets.mockResolvedValue({ data: { budgets: mockBudgetsData }, }); const result = await ListBudgetsTool.execute({}, mockApi as any); expect(mockApi.budgets.getBudgets).toHaveBeenCalledWith(); const expectedResult = { content: [{ type: "text", text: JSON.stringify([ { id: 'budget-1', name: 'My Personal Budget' }, { id: 'budget-2', name: 'Family Budget' }, { id: 'budget-3', name: 'Business Budget' }, ], null, 2) }] }; expect(result).toEqual(expectedResult); }); it('should handle empty budget list', async () => { mockApi.budgets.getBudgets.mockResolvedValue({ data: { budgets: [] }, }); const result = await ListBudgetsTool.execute({}, mockApi as any); expect(mockApi.budgets.getBudgets).toHaveBeenCalledWith(); const expectedResult = { content: [{ type: "text", text: JSON.stringify([], null, 2) }] }; expect(result).toEqual(expectedResult); }); it('should handle single budget', async () => { const singleBudget = [mockBudgetsData[0]]; mockApi.budgets.getBudgets.mockResolvedValue({ data: { budgets: singleBudget }, }); const result = await ListBudgetsTool.execute({}, mockApi as any); const expectedResult = { content: [{ type: "text", text: JSON.stringify([ { id: 'budget-1', name: 'My Personal Budget' }, ], null, 2) }] }; expect(result).toEqual(expectedResult); }); it('should return error message when YNAB API token is not set', async () => { delete process.env.YNAB_API_TOKEN; const result = await ListBudgetsTool.execute({}, mockApi as any); const expectedResult = { content: [{ type: "text", text: "YNAB API Token is not set" }] }; expect(result).toEqual(expectedResult); expect(mockApi.budgets.getBudgets).not.toHaveBeenCalled(); }); it('should return error message when YNAB API token is empty string', async () => { process.env.YNAB_API_TOKEN = ''; const result = await ListBudgetsTool.execute({}, mockApi as any); const expectedResult = { content: [{ type: "text", text: "YNAB API Token is not set" }] }; expect(result).toEqual(expectedResult); expect(mockApi.budgets.getBudgets).not.toHaveBeenCalled(); }); it('should handle API error', async () => { const apiError = new Error('API Error: Unauthorized'); mockApi.budgets.getBudgets.mockRejectedValue(apiError); const result = await ListBudgetsTool.execute({}, mockApi as any); expect(result.content[0].text).toContain('Error listing budgets:'); }); it('should handle budgets with special characters in names', async () => { const specialBudgets = [ { id: 'budget-special-1', name: 'Budget with "Quotes" & Symbols!', last_modified_on: '2023-01-01T00:00:00Z', first_month: '2023-01-01', last_month: '2023-12-01', date_format: { format: 'MM/DD/YYYY' }, currency_format: { iso_code: 'USD', example_format: '123,456.78', decimal_digits: 2, decimal_separator: '.', symbol_first: true, group_separator: ',', currency_symbol: '$', display_symbol: true, }, }, { id: 'budget-special-2', name: 'émojis 🎯 & ünîcødé', last_modified_on: '2023-01-02T00:00:00Z', first_month: '2023-01-01', last_month: '2023-12-01', date_format: { format: 'DD/MM/YYYY' }, currency_format: { iso_code: 'EUR', example_format: '123.456,78', decimal_digits: 2, decimal_separator: ',', symbol_first: false, group_separator: '.', currency_symbol: '€', display_symbol: true, }, }, ]; mockApi.budgets.getBudgets.mockResolvedValue({ data: { budgets: specialBudgets }, }); const result = await ListBudgetsTool.execute({}, mockApi as any); const expectedResult = { content: [{ type: "text", text: JSON.stringify([ { id: 'budget-special-1', name: 'Budget with "Quotes" & Symbols!' }, { id: 'budget-special-2', name: 'émojis 🎯 & ünîcødé' }, ], null, 2) }] }; expect(result).toEqual(expectedResult); }); }); describe('tool configuration', () => { it('should have correct name and description', () => { expect(ListBudgetsTool.name).toBe('list_budgets'); expect(ListBudgetsTool.description).toBe('Lists all available budgets from YNAB API'); }); it('should have empty input schema', () => { expect(ListBudgetsTool.inputSchema).toEqual({}); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/calebl/ynab-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server