All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 32m3s
135 lines
4.9 KiB
TypeScript
135 lines
4.9 KiB
TypeScript
// src/services/db/address.db.test.ts
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { AddressRepository } from './address.db';
|
|
import type { Address } from '../../types';
|
|
import { UniqueConstraintError, NotFoundError } from './errors.db';
|
|
|
|
// Mock dependencies
|
|
vi.mock('../logger.server', () => ({
|
|
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() },
|
|
}));
|
|
import { logger as mockLogger } from '../logger.server';
|
|
|
|
describe('Address DB Service', () => {
|
|
let addressRepo: AddressRepository;
|
|
const mockDb = {
|
|
query: vi.fn(),
|
|
};
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
mockDb.query.mockReset();
|
|
addressRepo = new AddressRepository(mockDb);
|
|
});
|
|
|
|
describe('getAddressById', () => {
|
|
it('should return an address if found', async () => {
|
|
const mockAddress: Address = {
|
|
address_id: 1,
|
|
address_line_1: '123 Main St',
|
|
city: 'Anytown',
|
|
province_state: 'CA',
|
|
postal_code: '12345',
|
|
country: 'USA',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
mockDb.query.mockResolvedValue({ rows: [mockAddress], rowCount: 1 });
|
|
|
|
const result = await addressRepo.getAddressById(1, mockLogger);
|
|
|
|
expect(result).toEqual(mockAddress);
|
|
expect(mockDb.query).toHaveBeenCalledWith(
|
|
'SELECT * FROM public.addresses WHERE address_id = $1',
|
|
[1],
|
|
);
|
|
});
|
|
|
|
it('should throw NotFoundError if no address is found', async () => {
|
|
mockDb.query.mockResolvedValue({ rowCount: 0, rows: [] });
|
|
await expect(addressRepo.getAddressById(999, mockLogger)).rejects.toThrow(NotFoundError);
|
|
await expect(addressRepo.getAddressById(999, mockLogger)).rejects.toThrow(
|
|
'Address with ID 999 not found.',
|
|
);
|
|
});
|
|
|
|
it('should throw an error if the database query fails', async () => {
|
|
const dbError = new Error('DB Error');
|
|
mockDb.query.mockRejectedValue(dbError);
|
|
|
|
await expect(addressRepo.getAddressById(1, mockLogger)).rejects.toThrow(
|
|
'Failed to retrieve address.',
|
|
);
|
|
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
{ err: dbError, addressId: 1 },
|
|
'Database error in getAddressById',
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('upsertAddress', () => {
|
|
it('should INSERT a new address when no address_id is provided', async () => {
|
|
const newAddressData = { address_line_1: '456 New Ave', city: 'Newville' };
|
|
mockDb.query.mockResolvedValue({ rows: [{ address_id: 2 }] });
|
|
|
|
const result = await addressRepo.upsertAddress(newAddressData, mockLogger);
|
|
|
|
expect(result).toBe(2);
|
|
const [query, values] = mockDb.query.mock.calls[0];
|
|
expect(query).toContain('INSERT INTO public.addresses');
|
|
expect(query).toContain('ON CONFLICT (address_id) DO UPDATE');
|
|
expect(values).toEqual(['456 New Ave', 'Newville']);
|
|
});
|
|
|
|
it('should UPDATE an existing address when an address_id is provided', async () => {
|
|
const existingAddressData = { address_id: 1, address_line_1: '789 Old Rd', city: 'Oldtown' };
|
|
mockDb.query.mockResolvedValue({ rows: [{ address_id: 1 }] });
|
|
|
|
const result = await addressRepo.upsertAddress(existingAddressData, mockLogger);
|
|
|
|
expect(result).toBe(1);
|
|
const [query, values] = mockDb.query.mock.calls[0];
|
|
expect(query).toContain('INSERT INTO public.addresses');
|
|
expect(query).toContain('ON CONFLICT (address_id) DO UPDATE');
|
|
expect(values).toEqual([1, '789 Old Rd', 'Oldtown']);
|
|
});
|
|
|
|
it('should throw UniqueConstraintError on unique constraint violation', async () => {
|
|
const addressData = { address_line_1: '123 Duplicate St' };
|
|
const dbError = new Error('duplicate key value violates unique constraint');
|
|
(dbError as any).code = '23505';
|
|
mockDb.query.mockRejectedValue(dbError);
|
|
|
|
await expect(addressRepo.upsertAddress(addressData, mockLogger)).rejects.toThrow(
|
|
UniqueConstraintError,
|
|
);
|
|
await expect(addressRepo.upsertAddress(addressData, mockLogger)).rejects.toThrow(
|
|
'An identical address already exists.',
|
|
);
|
|
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
{
|
|
err: dbError,
|
|
address: addressData,
|
|
code: '23505',
|
|
constraint: undefined,
|
|
detail: undefined,
|
|
},
|
|
'Database error in upsertAddress',
|
|
);
|
|
});
|
|
|
|
it('should throw a generic error if the database query fails for other reasons', async () => {
|
|
const addressData = { address_line_1: '789 Failure Rd' };
|
|
const dbError = new Error('DB Connection Error');
|
|
mockDb.query.mockRejectedValue(dbError);
|
|
|
|
await expect(addressRepo.upsertAddress(addressData, mockLogger)).rejects.toThrow(
|
|
'Failed to upsert address.',
|
|
);
|
|
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
{ err: dbError, address: addressData },
|
|
'Database error in upsertAddress',
|
|
);
|
|
});
|
|
});
|
|
}); |