162 lines
5.3 KiB
TypeScript
162 lines
5.3 KiB
TypeScript
// src/services/db/conversion.db.test.ts
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { mockPoolInstance } from '../../tests/setup/tests-setup-unit';
|
|
import { getPool } from './connection.db';
|
|
import { conversionRepo } from './conversion.db';
|
|
import { NotFoundError } from './errors.db';
|
|
import type { UnitConversion } from '../../types';
|
|
|
|
// Un-mock the module we are testing
|
|
vi.unmock('./conversion.db');
|
|
|
|
// Mock dependencies
|
|
vi.mock('./connection.db', () => ({
|
|
getPool: vi.fn(),
|
|
}));
|
|
|
|
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('Conversion DB Service', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
mockPoolInstance.query.mockReset();
|
|
// Make getPool return our mock instance for each test
|
|
vi.mocked(getPool).mockReturnValue(mockPoolInstance as any);
|
|
});
|
|
|
|
describe('getConversions', () => {
|
|
it('should return all conversions if no filters are provided', async () => {
|
|
const mockConversions: UnitConversion[] = [
|
|
{
|
|
unit_conversion_id: 1,
|
|
master_item_id: 1,
|
|
from_unit: 'g',
|
|
to_unit: 'kg',
|
|
factor: 0.001,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
},
|
|
];
|
|
mockPoolInstance.query.mockResolvedValue({ rows: mockConversions });
|
|
|
|
const result = await conversionRepo.getConversions({}, mockLogger);
|
|
|
|
expect(mockPoolInstance.query).toHaveBeenCalledWith(
|
|
expect.stringContaining('SELECT * FROM public.unit_conversions'),
|
|
expect.any(Array),
|
|
);
|
|
// Check that WHERE clause is not present for master_item_id
|
|
expect(mockPoolInstance.query.mock.calls[0][0]).not.toContain('WHERE master_item_id');
|
|
expect(result).toEqual(mockConversions);
|
|
});
|
|
|
|
it('should filter by masterItemId', async () => {
|
|
mockPoolInstance.query.mockResolvedValue({ rows: [] });
|
|
|
|
await conversionRepo.getConversions({ masterItemId: 123 }, mockLogger);
|
|
|
|
expect(mockPoolInstance.query).toHaveBeenCalledWith(
|
|
expect.stringContaining('WHERE master_item_id = $1'),
|
|
[123],
|
|
);
|
|
});
|
|
|
|
it('should throw an error if the database query fails', async () => {
|
|
const dbError = new Error('DB Error');
|
|
mockPoolInstance.query.mockRejectedValue(dbError);
|
|
|
|
await expect(conversionRepo.getConversions({}, mockLogger)).rejects.toThrow(
|
|
'Failed to retrieve unit conversions.',
|
|
);
|
|
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
{ err: dbError, filters: {} },
|
|
'Database error in getConversions',
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('createConversion', () => {
|
|
const newConversion = {
|
|
master_item_id: 1,
|
|
from_unit: 'cup',
|
|
to_unit: 'ml',
|
|
factor: 236.588,
|
|
};
|
|
|
|
it('should insert a new conversion and return it', async () => {
|
|
const mockCreatedConversion: UnitConversion = {
|
|
unit_conversion_id: 1,
|
|
...newConversion,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
mockPoolInstance.query.mockResolvedValue({ rows: [mockCreatedConversion] });
|
|
|
|
const result = await conversionRepo.createConversion(newConversion, mockLogger);
|
|
|
|
expect(mockPoolInstance.query).toHaveBeenCalledWith(
|
|
expect.stringContaining('INSERT INTO public.unit_conversions'),
|
|
[1, 'cup', 'ml', 236.588],
|
|
);
|
|
expect(result).toEqual(mockCreatedConversion);
|
|
});
|
|
|
|
it('should throw an error if the database query fails', async () => {
|
|
const dbError = new Error('DB Error');
|
|
mockPoolInstance.query.mockRejectedValue(dbError);
|
|
|
|
await expect(conversionRepo.createConversion(newConversion, mockLogger)).rejects.toThrow(
|
|
'Failed to create unit conversion.',
|
|
);
|
|
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
{ err: dbError, conversionData: newConversion },
|
|
'Database error in createConversion',
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('deleteConversion', () => {
|
|
it('should delete a conversion if found', async () => {
|
|
mockPoolInstance.query.mockResolvedValue({ rowCount: 1 });
|
|
|
|
await conversionRepo.deleteConversion(1, mockLogger);
|
|
|
|
expect(mockPoolInstance.query).toHaveBeenCalledWith(
|
|
'DELETE FROM public.unit_conversions WHERE unit_conversion_id = $1',
|
|
[1],
|
|
);
|
|
});
|
|
|
|
it('should throw NotFoundError if conversion is not found', async () => {
|
|
mockPoolInstance.query.mockResolvedValue({ rowCount: 0 });
|
|
|
|
await expect(conversionRepo.deleteConversion(999, mockLogger)).rejects.toThrow(NotFoundError);
|
|
await expect(conversionRepo.deleteConversion(999, mockLogger)).rejects.toThrow(
|
|
'Unit conversion with ID 999 not found.',
|
|
);
|
|
});
|
|
|
|
it('should throw an error if the database query fails', async () => {
|
|
const dbError = new Error('DB Error');
|
|
mockPoolInstance.query.mockRejectedValue(dbError);
|
|
|
|
await expect(conversionRepo.deleteConversion(1, mockLogger)).rejects.toThrow(
|
|
'Failed to delete unit conversion.',
|
|
);
|
|
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
{ err: dbError, conversionId: 1 },
|
|
'Database error in deleteConversion',
|
|
);
|
|
});
|
|
});
|
|
});
|