Skip to main content
Glama

QuickFile MCP Server

by marcusquinn
api.test.ts8.24 kB
/** * Integration tests for QuickFile API * * These tests make REAL API calls to QuickFile. * They use TestMode where supported to avoid affecting live data. * * Prerequisites: * - Valid credentials in ~/.config/.quickfile-mcp/credentials.json * - Network access to api.quickfile.co.uk * * Run with: npm run test:integration */ import { QuickFileApiClient, QuickFileApiError } from '../../src/api/client'; import { loadCredentials, validateCredentialsFormat } from '../../src/api/auth'; // Increase timeout for API calls jest.setTimeout(30000); describe('QuickFile API Integration Tests', () => { let client: QuickFileApiClient; beforeAll(() => { // Verify credentials exist and are valid format const credentials = loadCredentials(); if (!validateCredentialsFormat(credentials)) { throw new Error('Invalid credential format - check ~/.config/.quickfile-mcp/credentials.json'); } // Create client in test mode client = new QuickFileApiClient({ testMode: true }); }); describe('Connection & Authentication', () => { it('should load credentials successfully', () => { const credentials = loadCredentials(); expect(credentials.accountNumber).toBeDefined(); expect(credentials.apiKey).toBeDefined(); expect(credentials.applicationId).toBeDefined(); }); it('should have valid credential format', () => { const credentials = loadCredentials(); expect(validateCredentialsFormat(credentials)).toBe(true); }); it('should create API client', () => { expect(client).toBeInstanceOf(QuickFileApiClient); expect(client.getAccountNumber()).toBeDefined(); }); }); describe('System API', () => { it('should get account details', async () => { const response = await client.request< { AccountDetails: { AccountNumber: string; ReturnVariables: { Variable: string[] } } }, { AccountDetails: Record<string, unknown> } >('System_GetAccountDetails', { AccountDetails: { AccountNumber: client.getAccountNumber(), ReturnVariables: { Variable: ['CompanyName', 'BaseCurrency', 'VatRegNumber'], }, }, }); expect(response).toBeDefined(); expect(response.AccountDetails).toBeDefined(); }); }); describe('Client API', () => { it('should search clients', async () => { const response = await client.request< { SearchParameters: Record<string, unknown> }, { RecordsetCount: number; ReturnCount: number; Record: unknown[] } >('Client_Search', { SearchParameters: { ReturnCount: 5, Offset: 0, OrderResultsBy: 'CompanyName', OrderDirection: 'ASC', }, }); expect(response).toBeDefined(); expect(typeof response.RecordsetCount).toBe('number'); expect(typeof response.ReturnCount).toBe('number'); expect(Array.isArray(response.Record)).toBe(true); }); it('should handle client search with filters', async () => { const response = await client.request< { SearchParameters: Record<string, unknown> }, { RecordsetCount: number; Record: unknown[] } >('Client_Search', { SearchParameters: { ReturnCount: 10, Offset: 0, OrderResultsBy: 'CompanyName', // DateCreated may not be valid OrderDirection: 'DESC', }, }); expect(response).toBeDefined(); expect(response.RecordsetCount).toBeGreaterThanOrEqual(0); }); }); describe('Invoice API', () => { it('should search invoices', async () => { const response = await client.request< { SearchParameters: Record<string, unknown> }, { RecordsetCount?: number; Invoices?: { Invoice: unknown[] } } >('Invoice_Search', { SearchParameters: { InvoiceType: 'INVOICE', ReturnCount: 5, Offset: 0, OrderResultsBy: 'InvoiceNumber', OrderDirection: 'DESC', }, }); expect(response).toBeDefined(); // API may return RecordsetCount or embed count differently expect(response.Invoices !== undefined || response.RecordsetCount !== undefined).toBe(true); }); it('should search estimates', async () => { const response = await client.request< { SearchParameters: Record<string, unknown> }, { RecordsetCount?: number; Invoices?: { Invoice: unknown[] } } >('Invoice_Search', { SearchParameters: { InvoiceType: 'ESTIMATE', ReturnCount: 5, Offset: 0, OrderResultsBy: 'InvoiceNumber', OrderDirection: 'DESC', }, }); expect(response).toBeDefined(); }); }); describe('Purchase API', () => { it('should search purchases', async () => { const response = await client.request< { SearchParameters: Record<string, unknown> }, { RecordsetCount?: number; Purchases?: { Purchase: unknown[] } } >('Purchase_Search', { SearchParameters: { ReturnCount: 5, Offset: 0, OrderResultsBy: 'ReceiptDate', OrderDirection: 'DESC', }, }); expect(response).toBeDefined(); }); }); describe('Supplier API', () => { it('should search suppliers', async () => { const response = await client.request< { SearchParameters: Record<string, unknown> }, { RecordsetCount?: number; Suppliers?: { Supplier: unknown[] } } >('Supplier_Search', { SearchParameters: { ReturnCount: 5, Offset: 0, OrderResultsBy: 'CompanyName', OrderDirection: 'ASC', }, }); expect(response).toBeDefined(); }); }); describe('Bank API', () => { it('should get bank accounts', async () => { const response = await client.request< { SearchParameters: { OrderResultsBy: string; AccountTypes: { AccountType: string[] } } }, { BankAccounts?: { BankAccount: unknown[] } } >('Bank_GetAccounts', { SearchParameters: { OrderResultsBy: 'NominalCode', AccountTypes: { AccountType: ['CURRENT', 'PETTY', 'BUILDINGSOC', 'CREDITCARD'], }, }, }); expect(response).toBeDefined(); }); }); describe('Report API', () => { it('should get chart of accounts', async () => { const response = await client.request< Record<string, never>, { NominalCodes?: { NominalCode: unknown[] } } >('Report_ChartOfAccounts', {}); expect(response).toBeDefined(); }); it('should get profit and loss report', async () => { // Use last 30 days const endDate = new Date().toISOString().split('T')[0]; const startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]; const response = await client.request< { SearchParameters: { FromDate: string; ToDate: string } }, { Report?: Record<string, unknown> } >('Report_ProfitAndLoss', { SearchParameters: { FromDate: startDate, ToDate: endDate, }, }); expect(response).toBeDefined(); }); it('should get balance sheet report', async () => { const reportDate = new Date().toISOString().split('T')[0]; const response = await client.request< { SearchParameters: { ToDate: string } }, { Report?: Record<string, unknown> } >('Report_BalanceSheet', { SearchParameters: { ToDate: reportDate, }, }); expect(response).toBeDefined(); }); }); describe('Error Handling', () => { it('should handle invalid client ID gracefully', async () => { await expect( client.request<{ ClientID: number }, unknown>('Client_Get', { ClientID: 999999999, }) ).rejects.toThrow(QuickFileApiError); }); it('should handle invalid invoice ID gracefully', async () => { await expect( client.request<{ InvoiceID: number }, unknown>('Invoice_Get', { InvoiceID: 999999999, }) ).rejects.toThrow(QuickFileApiError); }); }); });

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/marcusquinn/quickfile-mcp'

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