UNPKG

quickbooks-api

Version:

A modular TypeScript SDK for seamless integration with Intuit QuickBooks APIs. Provides robust authentication handling and future-ready foundation for accounting, payments, and commerce operations.

243 lines (200 loc) 8.11 kB
// Imports import { AuthProvider, Environment, ApiClient, AuthScopes, type BillOptions, QuickbooksError } from '../src/app'; import { describe, expect, test } from 'bun:test'; // Describe the Bill API describe('Live API: Bills', async () => { // Initialize the Auth Provider const authProvider = new AuthProvider( process.env.QB_CLIENT_ID!, process.env.QB_CLIENT_SECRET!, process.env.REDIRECT_URI!, [AuthScopes.Accounting], null, Environment.Sandbox, ); // Deserialize the Token await authProvider.deserializeToken(process.env.SERIALIZED_TOKEN!, process.env.SECRET_KEY!); // Setup the API Client const apiClient = new ApiClient(authProvider, Environment.Sandbox); // Test retrieving all bills test('should retrieve all bills', async () => { // Get all bills const searchResponse = await apiClient.bills.getAllBills(); // Test the Bills expect(searchResponse.results).toBeInstanceOf(Array); expect(searchResponse.results.length).toBeGreaterThan(0); // Test the Intuit TID expect(searchResponse.intuitTID).toBeDefined(); expect(typeof searchResponse.intuitTID).toBe('string'); }); // Test Checking for Next Page test('should check for next page', async () => { // Get all bills const searchResponse = await apiClient.bills.getAllBills(); // Test the Bills expect(searchResponse.hasNextPage).toBe(true); // Test the Intuit TID expect(searchResponse.intuitTID).toBeDefined(); expect(typeof searchResponse.intuitTID).toBe('string'); }); // Test retrieving a single bill test('should retrieve a single bill', async () => { // Get all bills const searchResponse = await apiClient.bills.getAllBills(); // Get the first bill const bill = searchResponse.results[0]; // Get the Bill by ID const billResponse = await apiClient.bills.getBillById(bill.Id); // Test the Bill Response Structure expect(billResponse).toBeDefined(); expect(billResponse).toHaveProperty('bill'); expect(billResponse).toHaveProperty('intuitTID'); expect(typeof billResponse.intuitTID).toBe('string'); // Test the Bill ID expect(billResponse.bill.Id).toBe(bill.Id); }); // Test retrieving limited bills test('should retrieve limited bills', async () => { // Setup the Bill Options const billOptions: BillOptions = { searchOptions: { maxResults: 10 } }; // Get all bills const searchResponse = await apiClient.bills.getAllBills(billOptions); // Test the Bills expect(searchResponse.results).toBeInstanceOf(Array); expect(searchResponse.results.length).toBeGreaterThan(0); expect(searchResponse.results.length).toBeLessThanOrEqual(10); }); // Test pagination test('should handle pagination', async () => { // Setup the Bill Options const billOptions1: BillOptions = { searchOptions: { maxResults: 10, page: 1 } }; const billOptions2: BillOptions = { searchOptions: { maxResults: 10, page: 2 } }; // Get all bills const searchResponse1 = await apiClient.bills.getAllBills(billOptions1); const searchResponse2 = await apiClient.bills.getAllBills(billOptions2); // Test the Bills expect(searchResponse1.results).toBeInstanceOf(Array); expect(searchResponse2.results).toBeInstanceOf(Array); expect(searchResponse1.results.length).toBeGreaterThan(0); expect(searchResponse2.results.length).toBeGreaterThan(0); expect(searchResponse1.results).not.toEqual(searchResponse2.results); }); // Test date range filtering test('should retrieve bills within date range', async () => { // Get the End Date const endDate = new Date(); // Get the Start Date const startDate = new Date(); startDate.setDate(endDate.getDate() - 730); // Get the Bills const searchResponse = await apiClient.bills.getBillsForDateRange(startDate, endDate); // Assert the Bills expect(searchResponse.results).toBeInstanceOf(Array); // Test the Intuit TID expect(searchResponse.intuitTID).toBeDefined(); expect(typeof searchResponse.intuitTID).toBe('string'); }); // Should handle all Search Options test('should handle all search options', async () => { // Setup the Bill Options const billOptions: BillOptions = { searchOptions: { maxResults: 10, page: 1, orderBy: { field: 'Id', direction: 'DESC' }, }, }; // Get all bills const searchResponse = await apiClient.bills.getAllBills(billOptions); // Test the Bills expect(searchResponse.results).toBeInstanceOf(Array); expect(searchResponse.results.length).toBeGreaterThan(0); // loop through the bills and test each id is less than the previous one for (let i = 0; i < searchResponse.results.length - 1; i++) { expect(Number(searchResponse.results[i].Id)).toBeGreaterThan(Number(searchResponse.results[i + 1].Id)); } }); // Test error handling for invalid ID test('should throw QuickbooksError for invalid bill ID', async () => { try { await apiClient.bills.getBillById('invalid'); expect(false).toBe(true); // Should not reach here } catch (error) { // Assert the Error is a QuickbooksError expect(error).toBeInstanceOf(QuickbooksError); expect(error).toBeInstanceOf(Error); // Assert the Error has the correct structure expect(error.message).toBeDefined(); expect(error.details).toBeDefined(); expect(error.details.statusCode).toBeDefined(); expect(typeof error.details.statusCode).toBe('number'); expect(error.details.intuitError).toBeDefined(); expect(Array.isArray(error.details.intuitError)).toBe(true); expect(error.details.intuitTID).toBeDefined(); expect(typeof error.details.intuitTID).toBe('string'); } }); // Test error handling for invalid raw query test('should throw QuickbooksError for invalid raw query', async () => { // Get the Query Builder const queryBuilder = await apiClient.bills.getQueryBuilder(); // Add an invalid ID filter that will cause an error queryBuilder.whereId('invalid-id-that-does-not-exist'); try { await apiClient.bills.rawBillQuery(queryBuilder); expect(false).toBe(true); // Should not reach here } catch (error) { // Assert the Error is a QuickbooksError expect(error).toBeInstanceOf(QuickbooksError); expect(error).toBeInstanceOf(Error); // Assert the Error has the correct structure expect(error.message).toBeDefined(); expect(error.details).toBeDefined(); expect(error.details.statusCode).toBeDefined(); expect(typeof error.details.statusCode).toBe('number'); expect(error.details.intuitError).toBeDefined(); expect(Array.isArray(error.details.intuitError)).toBe(true); expect(error.details.intuitTID).toBeDefined(); expect(typeof error.details.intuitTID).toBe('string'); } }); // Test Bill class methods describe('Bill Class Methods', () => { // Test downloading bill PDF // Note: Bills may not support PDF downloads in QuickBooks API test('should download bill PDF (if supported)', async () => { // Get all bills const searchResponse = await apiClient.bills.getAllBills({ searchOptions: { maxResults: 1 } }); // Check if we have at least one bill if (searchResponse.results.length === 0) { console.log('No bills found, skipping PDF download test'); return; } // Get the first bill const bill = searchResponse.results[0]; // Get the bill by ID to get class instance const billResponse = await apiClient.bills.getBillById(bill.Id); // Check if bill exists if (!billResponse.bill) { console.log('Bill not found, skipping PDF download test'); return; } // Try to download the PDF (Bills may not support PDF downloads) try { const pdf = await billResponse.bill.downloadPDF(); // Assert the PDF is a Blob expect(pdf).toBeInstanceOf(Blob); expect(pdf.type).toContain('application/pdf'); expect(pdf.size).toBeGreaterThan(0); } catch (error) { // Bills may not support PDF downloads - log and skip if (error instanceof QuickbooksError && error.details?.statusCode === 400) { console.log('Bill PDF download not supported (400 error), skipping test'); return; } // Re-throw if it's a different error throw error; } }); }); });