/** * API regression tests for the Accounts endpoint. * * Tests CRUD operations on /api/accounts. * Requires authentication — logs in first to get a Bearer token. */ import { test, expect } from '@playwright/test'; import { apiLogin, apiSwitchOrg, authHeaders } from '../fixtures/auth.fixture'; import { TEST_USERS, TEST_PREFIX } from '../fixtures/test-data'; const API_BASE = process.env.API_BASE_URL || 'http://localhost/api'; let accessToken: string; test.beforeAll(async ({ request }) => { // Login and switch to test org const tokens = await apiLogin(request, TEST_USERS.treasurer); if (tokens.organizations?.length > 0) { const orgId = (tokens.organizations[0] as any).id; try { const switched = await apiSwitchOrg(request, tokens.accessToken, orgId); accessToken = switched.accessToken; } catch { accessToken = tokens.accessToken; } } else { accessToken = tokens.accessToken; } }); test.describe('GET /api/accounts', () => { test('should return accounts list', async ({ request }) => { const response = await request.get(`${API_BASE}/accounts`, { headers: authHeaders(accessToken), }); expect(response.status()).toBe(200); const accounts = await response.json(); expect(Array.isArray(accounts)).toBe(true); }); test('should return 401 without auth', async ({ request }) => { const response = await request.get(`${API_BASE}/accounts`); expect(response.status()).toBe(401); }); test('should filter by fund type', async ({ request }) => { const response = await request.get(`${API_BASE}/accounts?fundType=operating`, { headers: authHeaders(accessToken), }); expect(response.status()).toBe(200); const accounts = await response.json(); expect(Array.isArray(accounts)).toBe(true); }); }); test.describe('Accounts CRUD', () => { let createdAccountId: string; test('should create a new account', async ({ request }) => { const response = await request.post(`${API_BASE}/accounts`, { headers: authHeaders(accessToken), data: { name: `${TEST_PREFIX}Operating Checking`, number: '1099', accountType: 'asset', fundType: 'operating', description: 'E2E test account — safe to delete', }, }); expect(response.status()).toBe(201); const account = await response.json(); expect(account).toHaveProperty('id'); expect(account.name).toBe(`${TEST_PREFIX}Operating Checking`); createdAccountId = account.id; }); test('should get the created account', async ({ request }) => { test.skip(!createdAccountId, 'No account was created'); const response = await request.get(`${API_BASE}/accounts/${createdAccountId}`, { headers: authHeaders(accessToken), }); expect(response.status()).toBe(200); const account = await response.json(); expect(account.id).toBe(createdAccountId); expect(account.name).toBe(`${TEST_PREFIX}Operating Checking`); }); test('should update the account', async ({ request }) => { test.skip(!createdAccountId, 'No account was created'); const response = await request.put(`${API_BASE}/accounts/${createdAccountId}`, { headers: authHeaders(accessToken), data: { name: `${TEST_PREFIX}Updated Checking`, description: 'Updated by E2E test', }, }); expect(response.status()).toBe(200); const account = await response.json(); expect(account.name).toBe(`${TEST_PREFIX}Updated Checking`); }); test('should appear in accounts list', async ({ request }) => { test.skip(!createdAccountId, 'No account was created'); const response = await request.get(`${API_BASE}/accounts`, { headers: authHeaders(accessToken), }); const accounts = await response.json(); const found = accounts.find((a: any) => a.id === createdAccountId); expect(found).toBeTruthy(); expect(found.name).toBe(`${TEST_PREFIX}Updated Checking`); }); }); test.describe('GET /api/accounts/trial-balance', () => { test('should return trial balance data', async ({ request }) => { const response = await request.get(`${API_BASE}/accounts/trial-balance`, { headers: authHeaders(accessToken), }); expect(response.status()).toBe(200); const data = await response.json(); // Trial balance returns an object or array with debit/credit totals expect(data).toBeDefined(); }); });