Skip to main content
Glama
billvendor-create.test.ts9.45 kB
/** * Tests for billvendor_create tool */ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { billvendorCreateTool } from '../../../src/tools/bill-vendor/billvendor-create.js'; import { createMockClientWrapper } from '../../mocks/client.js'; import { mockVendorCreateResponse, mockVendorValidationError, mockVendorDuplicateError, } from '../../mocks/responses/bill-vendor.js'; import { mockUnauthorizedError, mockRateLimitError, mockServerError, mockNetworkTimeoutError, } from '../../mocks/errors/freshbooks-errors.js'; describe('billvendor_create tool', () => { let mockClient: ReturnType<typeof createMockClientWrapper>; const validInput = { accountId: 'ABC123', vendorName: 'New Vendor LLC', }; beforeEach(() => { mockClient = createMockClientWrapper(); vi.clearAllMocks(); }); describe('successful operations', () => { it('should create a vendor with required fields', async () => { const mockResponse = mockVendorCreateResponse({ vendorName: 'New Vendor LLC', }); mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockResponse), }, }; return apiCall(client); }); const result = await billvendorCreateTool.execute(validInput, mockClient as any); expect(result.id).toBe(99999); expect(result.vendorName).toBe('New Vendor LLC'); }); it('should create a vendor with contact information', async () => { const mockResponse = mockVendorCreateResponse({ vendorName: 'New Vendor LLC', contactName: 'John Smith', email: 'john@newvendor.com', phone: '555-555-1234', }); mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockResponse), }, }; return apiCall(client); }); const result = await billvendorCreateTool.execute( { ...validInput, contactName: 'John Smith', email: 'john@newvendor.com', phone: '555-555-1234', }, mockClient as any ); expect(result.contactName).toBe('John Smith'); expect(result.email).toBe('john@newvendor.com'); expect(result.phone).toBe('555-555-1234'); }); it('should create a vendor with full address', async () => { const mockResponse = mockVendorCreateResponse({ address: '456 Business Ave', city: 'Toronto', province: 'ON', postalCode: 'M5V 2H1', country: 'Canada', }); mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockResponse), }, }; return apiCall(client); }); const result = await billvendorCreateTool.execute( { ...validInput, address: '456 Business Ave', city: 'Toronto', province: 'ON', postalCode: 'M5V 2H1', country: 'Canada', }, mockClient as any ); expect(result.address).toBe('456 Business Ave'); expect(result.city).toBe('Toronto'); expect(result.country).toBe('Canada'); }); it('should create a vendor with tax information', async () => { const mockResponse = mockVendorCreateResponse({ taxNumber: '98-7654321', is1099: true, }); mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockResponse), }, }; return apiCall(client); }); const result = await billvendorCreateTool.execute( { ...validInput, taxNumber: '98-7654321', is1099: true, }, mockClient as any ); expect(result.taxNumber).toBe('98-7654321'); expect(result.is1099).toBe(true); }); it('should create a vendor with different currency', async () => { const mockResponse = mockVendorCreateResponse({ currencyCode: 'EUR', }); mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockResponse), }, }; return apiCall(client); }); const result = await billvendorCreateTool.execute( { ...validInput, currencyCode: 'EUR' }, mockClient as any ); expect(result.currencyCode).toBe('EUR'); }); it('should create a vendor with note', async () => { const mockResponse = mockVendorCreateResponse({ note: 'Important supplier for office equipment', }); mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockResponse), }, }; return apiCall(client); }); const result = await billvendorCreateTool.execute( { ...validInput, note: 'Important supplier for office equipment' }, mockClient as any ); expect(result.note).toBe('Important supplier for office equipment'); }); }); describe('error handling', () => { it('should handle unauthorized error', async () => { mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockUnauthorizedError()), }, }; return apiCall(client); }); await expect( billvendorCreateTool.execute(validInput, mockClient as any) ).rejects.toThrow(); }); it('should handle rate limit error', async () => { mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockRateLimitError(60)), }, }; return apiCall(client); }); await expect( billvendorCreateTool.execute(validInput, mockClient as any) ).rejects.toThrow(); }); it('should handle server error', async () => { mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockServerError()), }, }; return apiCall(client); }); await expect( billvendorCreateTool.execute(validInput, mockClient as any) ).rejects.toThrow(); }); it('should handle network timeout', async () => { mockClient.executeWithRetry.mockRejectedValueOnce(mockNetworkTimeoutError()); await expect( billvendorCreateTool.execute(validInput, mockClient as any) ).rejects.toThrow(); }); it('should handle validation error', async () => { mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue( mockVendorValidationError('vendorName', 'Name is required') ), }, }; return apiCall(client); }); await expect( billvendorCreateTool.execute(validInput, mockClient as any) ).rejects.toThrow(); }); it('should handle duplicate vendor error', async () => { mockClient.executeWithRetry.mockImplementation(async (operation, apiCall) => { const client = { billVendors: { create: vi.fn().mockResolvedValue(mockVendorDuplicateError('New Vendor LLC')), }, }; return apiCall(client); }); await expect( billvendorCreateTool.execute(validInput, mockClient as any) ).rejects.toThrow(); }); }); describe('input validation', () => { it('should require accountId', async () => { const { accountId, ...inputWithoutAccount } = validInput; await expect( billvendorCreateTool.execute(inputWithoutAccount as any, mockClient as any) ).rejects.toThrow(); }); it('should require vendorName', async () => { const { vendorName, ...inputWithoutName } = validInput; await expect( billvendorCreateTool.execute(inputWithoutName as any, mockClient as any) ).rejects.toThrow(); }); it('should reject empty vendorName', async () => { await expect( billvendorCreateTool.execute( { ...validInput, vendorName: '' }, mockClient as any ) ).rejects.toThrow(); }); it('should reject invalid email format', async () => { await expect( billvendorCreateTool.execute( { ...validInput, email: 'invalid-email' }, mockClient as any ) ).rejects.toThrow(); }); it('should reject invalid website format', async () => { await expect( billvendorCreateTool.execute( { ...validInput, website: 'not-a-url' }, mockClient as any ) ).rejects.toThrow(); }); }); });

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/Good-Samaritan-Software-LLC/freshbooks-mcp'

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