unit test fixin
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 8m50s

This commit is contained in:
2025-12-11 00:53:24 -08:00
parent 99d0dba296
commit 6aa72dd90b
28 changed files with 204 additions and 142 deletions

View File

@@ -72,10 +72,9 @@ describe('Budget DB Service', () => {
// Mock the sequence of queries within the transaction
mockClient.query
.mockResolvedValueOnce({ rows: [] }) // BEGIN
.mockResolvedValueOnce({ rows: [mockCreatedBudget] }) // INSERT...RETURNING
.mockResolvedValueOnce({ rows: [] }) // award_achievement
.mockResolvedValueOnce({ rows: [] }); // COMMIT
.mockResolvedValueOnce({ rows: [] }) // For BEGIN
.mockResolvedValueOnce({ rows: [mockCreatedBudget] }) // For the INSERT...RETURNING
.mockResolvedValueOnce({ rows: [] }); // For both award_achievement and COMMIT
const result = await budgetRepo.createBudget('user-123', budgetData);

View File

@@ -204,6 +204,7 @@ describe('Flyer DB Service', () => {
// Mock the sequence of calls within the transaction
mockClient.query
.mockResolvedValueOnce({ rows: [] }) // BEGIN
.mockResolvedValueOnce({ rows: [{ store_id: 1 }] }) // findOrCreateStore
.mockResolvedValueOnce({ rows: [mockFlyer] }) // insertFlyer
.mockResolvedValueOnce({ rows: mockItems }) // insertFlyerItems
.mockResolvedValueOnce({ rows: [] }); // COMMIT

View File

@@ -338,11 +338,10 @@ describe('Personalization DB Service', () => {
expect(mockQuery).toHaveBeenCalledWith('BEGIN');
expect(mockQuery).toHaveBeenCalledWith('DELETE FROM public.user_dietary_restrictions WHERE user_id = $1', ['user-123']);
// FIX: Make assertion robust for array parameters
expect(mockQuery).toHaveBeenNthCalledWith(3,
expect.stringContaining('INSERT INTO public.user_dietary_restrictions'),
['user-123', [1, 2]]
);
// The implementation uses unnest, so it's one call with an array parameter
expect(mockQuery).toHaveBeenCalledWith(
expect.stringContaining('INSERT INTO public.user_dietary_restrictions'),
['user-123', [1, 2]]);
expect(mockQuery).toHaveBeenCalledWith('COMMIT');
});

View File

@@ -196,7 +196,10 @@ describe('Recipe DB Service', () => {
const updates = { name: 'Updated Recipe', description: 'New desc' };
const result = await recipeRepo.updateRecipe(1, 'user-123', updates);
expect(mockQuery).toHaveBeenCalledWith(expect.stringContaining('UPDATE public.recipes'), ['Updated Recipe', 'New desc', 1, 'user-123']);
expect(mockQuery).toHaveBeenCalledWith(
expect.stringContaining('UPDATE public.recipes'),
['Updated Recipe', 'New desc', 1, 'user-123']
);
expect(result).toEqual(mockRecipe);
});

View File

@@ -423,7 +423,6 @@ describe('Shopping DB Service', () => {
const mockClient = { query: vi.fn(), release: vi.fn() };
vi.mocked(mockPoolInstance.connect).mockResolvedValue(mockClient as any);
mockClient.query.mockResolvedValue({ rows: [] });
const items = [{ raw_item_description: 'Milk', price_paid_cents: 399 }];
await shoppingRepo.processReceiptItems(1, items);
@@ -431,14 +430,7 @@ describe('Shopping DB Service', () => {
const expectedItemsWithQuantity = [{ raw_item_description: 'Milk', price_paid_cents: 399, quantity: 1 }];
expect(mockClient.query).toHaveBeenCalledWith('BEGIN');
expect(mockClient.query).toHaveBeenCalledWith(
'SELECT public.process_receipt_items($1, $2, $3)',
[
1,
// The order of keys in the stringified JSON is not guaranteed.
// Instead, we'll parse the JSON string from the mock call and check its contents.
expect.stringContaining('"raw_item_description":"Milk"'),
expect.stringContaining('"raw_item_description":"Milk"'),
]
'SELECT public.process_receipt_items($1, $2, $3)', [1, JSON.stringify(expectedItemsWithQuantity), JSON.stringify(expectedItemsWithQuantity)]
);
expect(mockClient.query).toHaveBeenCalledWith('COMMIT');
expect(mockClient.release).toHaveBeenCalled();
@@ -452,14 +444,7 @@ describe('Shopping DB Service', () => {
const items = [{ raw_item_description: 'Bag', price_paid_cents: 0 }];
await shoppingRepo.processReceiptItems(1, items);
const expectedItems = [{ raw_item_description: 'Bag', price_paid_cents: 0, quantity: 1 }];
const call = mockClient.query.mock.calls.find(c => c[0].includes('process_receipt_items'));
expect(call).toBeDefined();
const passedJson = JSON.parse(call![1]);
expect(mockClient.query).toHaveBeenCalledWith(
'SELECT public.process_receipt_items($1, $2, $3)',
[1, expect.any(String), expect.any(String)]
);
expect(passedJson).toEqual(expect.arrayContaining([expect.objectContaining(expectedItems[0])]));
expect(mockClient.query).toHaveBeenCalledWith('SELECT public.process_receipt_items($1, $2, $3)', [1, JSON.stringify(expectedItems), JSON.stringify(expectedItems)]);
});
it('should update receipt status to "failed" on error', async () => {
@@ -474,7 +459,7 @@ describe('Shopping DB Service', () => {
await expect(shoppingRepo.processReceiptItems(1, items)).rejects.toThrow('Failed to process and save receipt items.');
// Verify that the status was updated to 'failed' in the catch block
expect(mockPoolInstance.query).toHaveBeenCalledWith("UPDATE public.receipts SET status = 'failed' WHERE id = $1", [1]);
expect(mockPoolInstance.query).toHaveBeenCalledWith("UPDATE public.receipts SET status = 'failed' WHERE receipt_id = $1", [1]);
});
// Note: The `processReceiptItems` method in shopping.db.ts has a potential bug where it calls `client.query('ROLLBACK')`

View File

@@ -94,10 +94,9 @@ describe('User DB Service', () => {
// Mock the sequence of queries within the transaction
mockClient.query
.mockResolvedValueOnce({ rows: [] }) // BEGIN
.mockResolvedValueOnce({ rows: [] }) // set_config
.mockResolvedValueOnce({ rows: [mockUser] }) // INSERT user
.mockResolvedValueOnce({ rows: [mockProfile] }) // SELECT profile
.mockResolvedValueOnce({ rows: [] }); // COMMIT
.mockResolvedValueOnce({ rows: [] }) // COMMIT;
const result = await userRepo.createUser('new@example.com', 'hashedpass', { full_name: 'New User' });
@@ -113,13 +112,11 @@ describe('User DB Service', () => {
// Arrange: Mock the user insert query to fail after BEGIN and set_config
mockClient.query
.mockResolvedValueOnce({ rows: [] }) // BEGIN
.mockRejectedValueOnce(new Error('User insert failed')); // INSERT fails
// Act & Assert
// FIX: The repo now throws "Failed to create user in database." instead of the original error.
await expect(userRepo.createUser('fail@example.com', 'badpass', {})).rejects.toThrow('Failed to create user in database.');
expect(mockClient.query).toHaveBeenCalledWith('BEGIN');
await expect(userRepo.createUser('fail@example.com', 'badpass', {})).rejects.toThrow('User insert failed');
expect(mockClient.query).toHaveBeenCalledWith('BEGIN'); // This will be called inside the try block
// The createUser function now throws the original error, so we check for that.
expect(mockClient.query).toHaveBeenCalledWith('ROLLBACK');
expect(mockClient.release).toHaveBeenCalled();
@@ -132,13 +129,10 @@ describe('User DB Service', () => {
vi.mocked(mockPoolInstance.connect).mockResolvedValue(mockClient as any);
mockClient.query
.mockResolvedValueOnce({ rows: [] }) // BEGIN
.mockResolvedValueOnce({ rows: [] }) // set_config in trigger
.mockResolvedValueOnce({ rows: [mockUser] }) // INSERT user
.mockRejectedValueOnce(new Error('Profile fetch failed')); // SELECT profile fails
// FIX: The repo wraps the error, so expect the wrapped message or generic failure.
// Based on implementation: "Failed to create user in database."
await expect(userRepo.createUser('fail@example.com', 'pass', {})).rejects.toThrow('Failed to create user in database.');
await expect(userRepo.createUser('fail@example.com', 'pass', {})).rejects.toThrow('Profile fetch failed');
expect(mockClient.query).toHaveBeenCalledWith('ROLLBACK');
expect(mockClient.release).toHaveBeenCalled();
});
@@ -157,7 +151,6 @@ describe('User DB Service', () => {
// 4. ROLLBACK (success)
mockClient.query
.mockResolvedValueOnce({ rows: [] }) // BEGIN
.mockResolvedValueOnce({ rows: [] }) // set_config
.mockRejectedValueOnce(dbError) // INSERT fails
.mockResolvedValueOnce({ rows: [] }); // ROLLBACK