Files
flyer-crawler.projectium.com/src/services/db/shopping.db.test.ts
Torben Sorensen e39a7560ee
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 5m57s
home page errors in progress
2025-12-09 23:11:09 -08:00

508 lines
26 KiB
TypeScript

// src/services/db/shopping.db.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { mockPoolInstance } from '../../tests/setup/tests-setup-unit';
import { createMockShoppingList, createMockShoppingListItem } from '../../tests/utils/mockFactories';
// Un-mock the module we are testing to ensure we use the real implementation.
vi.unmock('./shopping.db');
import { ShoppingRepository } from './shopping.db';
import { ForeignKeyConstraintError, UniqueConstraintError } from './errors.db';
// Mock the logger to prevent console output during tests
vi.mock('../logger.server', () => ({
logger: {
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
debug: vi.fn(),
},
}));
describe('Shopping DB Service', () => {
let shoppingRepo: ShoppingRepository;
beforeEach(() => {
vi.clearAllMocks();
// Instantiate the repository with the mock pool for each test
shoppingRepo = new ShoppingRepository(mockPoolInstance as any);
});
describe('getShoppingLists', () => {
it('should execute the correct query and return shopping lists', async () => {
const mockLists = [createMockShoppingList({ user_id: 'user-1' })];
mockPoolInstance.query.mockResolvedValue({ rows: mockLists });
const result = await shoppingRepo.getShoppingLists('user-1');
expect(mockPoolInstance.query).toHaveBeenCalledWith(expect.stringContaining('FROM public.shopping_lists sl'), ['user-1']);
expect(result).toEqual(mockLists);
});
it('should return an empty array if a user has no shopping lists', async () => {
mockPoolInstance.query.mockResolvedValue({ rows: [] });
const result = await shoppingRepo.getShoppingLists('user-with-no-lists');
expect(mockPoolInstance.query).toHaveBeenCalledWith(expect.stringContaining('FROM public.shopping_lists sl'), ['user-with-no-lists']);
expect(result).toEqual([]);
});
it('should throw an error if the database query fails', async () => {
mockPoolInstance.query.mockRejectedValue(new Error('DB Connection Error'));
await expect(shoppingRepo.getShoppingLists('user-1')).rejects.toThrow('Failed to retrieve shopping lists.');
});
});
describe('getShoppingListById', () => {
it('should execute the correct query and return a single shopping list', async () => {
const mockList = createMockShoppingList({ shopping_list_id: 1, user_id: 'user-1' });
mockPoolInstance.query.mockResolvedValue({ rows: [mockList] });
const result = await shoppingRepo.getShoppingListById(1, 'user-1');
expect(mockPoolInstance.query).toHaveBeenCalledWith(
expect.stringContaining('WHERE sl.shopping_list_id = $1 AND sl.user_id = $2'),
[1, 'user-1']
);
expect(result).toEqual(mockList);
});
it('should return undefined if the shopping list is not found or not owned by the user', async () => {
mockPoolInstance.query.mockResolvedValue({ rows: [] });
const result = await shoppingRepo.getShoppingListById(999, 'user-1');
expect(result).toBeUndefined();
});
it('should throw an error if the database query fails', async () => {
const dbError = new Error('DB Connection Error');
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.getShoppingListById(1, 'user-1')).rejects.toThrow('Failed to retrieve shopping list.');
});
});
describe('createShoppingList', () => {
it('should insert a new shopping list and return it', async () => {
const mockList = createMockShoppingList({ name: 'New List' });
mockPoolInstance.query.mockResolvedValue({ rows: [mockList] });
const result = await shoppingRepo.createShoppingList('user-1', 'New List');
expect(mockPoolInstance.query).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO public.shopping_lists'), ['user-1', 'New List']);
expect(result).toEqual(mockList);
});
it('should throw ForeignKeyConstraintError if user does not exist', async () => {
const dbError = new Error('insert or update on table "shopping_lists" violates foreign key constraint "shopping_lists_user_id_fkey"');
(dbError as any).code = '23503';
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.createShoppingList('non-existent-user', 'Wont work')).rejects.toThrow('The specified user does not exist.');
});
it('should throw a generic error if the database query fails for other reasons', async () => {
const dbError = new Error('DB Connection Error');
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.createShoppingList('user-1', 'New List')).rejects.toThrow('Failed to create shopping list.');
});
});
describe('deleteShoppingList', () => {
it('should delete a shopping list if rowCount is 1', async () => {
mockPoolInstance.query.mockResolvedValue({ rowCount: 1, rows: [], command: 'DELETE' });
await expect(shoppingRepo.deleteShoppingList(1, 'user-1')).resolves.toBeUndefined();
expect(mockPoolInstance.query).toHaveBeenCalledWith('DELETE FROM public.shopping_lists WHERE shopping_list_id = $1 AND user_id = $2', [1, 'user-1']);
});
it('should throw an error if no rows are deleted (list not found or wrong user)', async () => {
mockPoolInstance.query.mockResolvedValue({ rowCount: 0, rows: [], command: 'DELETE' });
await expect(shoppingRepo.deleteShoppingList(999, 'user-1')).rejects.toThrow('Failed to delete shopping list.');
});
it('should throw a generic error if the database query fails', async () => {
const dbError = new Error('DB Connection Error');
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.deleteShoppingList(1, 'user-1')).rejects.toThrow('Failed to delete shopping list.');
});
});
describe('addShoppingListItem', () => {
it('should add a custom item to a shopping list', async () => {
const mockItem = createMockShoppingListItem({ custom_item_name: 'Custom Item' });
mockPoolInstance.query.mockResolvedValue({ rows: [mockItem] });
const result = await shoppingRepo.addShoppingListItem(1, { customItemName: 'Custom Item' });
expect(mockPoolInstance.query).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO public.shopping_list_items'), [1, null, 'Custom Item']);
expect(result).toEqual(mockItem);
});
it('should add a master item to a shopping list', async () => {
const mockItem = createMockShoppingListItem({ master_item_id: 123 });
mockPoolInstance.query.mockResolvedValue({ rows: [mockItem] });
const result = await shoppingRepo.addShoppingListItem(1, { masterItemId: 123 });
expect(mockPoolInstance.query).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO public.shopping_list_items'), [1, 123, null]);
expect(result).toEqual(mockItem);
});
it('should add an item with both masterItemId and customItemName', async () => {
const mockItem = createMockShoppingListItem({ master_item_id: 123, custom_item_name: 'Organic Apples' });
mockPoolInstance.query.mockResolvedValue({ rows: [mockItem] });
const result = await shoppingRepo.addShoppingListItem(1, { masterItemId: 123, customItemName: 'Organic Apples' });
expect(mockPoolInstance.query).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO public.shopping_list_items'), [1, 123, 'Organic Apples']);
expect(result).toEqual(mockItem);
});
it('should throw an error if both masterItemId and customItemName are missing', async () => {
await expect(shoppingRepo.addShoppingListItem(1, {})).rejects.toThrow('Either masterItemId or customItemName must be provided.');
});
it('should throw ForeignKeyConstraintError if list or master item does not exist', async () => {
const dbError = new Error('violates foreign key constraint');
(dbError as any).code = '23503';
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.addShoppingListItem(999, { masterItemId: 999 })).rejects.toThrow(ForeignKeyConstraintError);
});
it('should throw a generic error if the database query fails', async () => {
const dbError = new Error('DB Connection Error');
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.addShoppingListItem(1, { customItemName: 'Test' })).rejects.toThrow('Failed to add item to shopping list.');
});
});
describe('updateShoppingListItem', () => {
it('should update an item and return the updated record', async () => {
const mockItem = createMockShoppingListItem({ shopping_list_item_id: 1, is_purchased: true });
mockPoolInstance.query.mockResolvedValue({ rows: [mockItem], rowCount: 1 });
const result = await shoppingRepo.updateShoppingListItem(1, { is_purchased: true });
expect(mockPoolInstance.query).toHaveBeenCalledWith(
'UPDATE public.shopping_list_items SET is_purchased = $1 WHERE shopping_list_item_id = $2 RETURNING *',
[true, 1]
);
expect(result).toEqual(mockItem);
});
it('should update multiple fields at once', async () => {
const updates = { is_purchased: true, quantity: 5, notes: 'Get the green ones' };
const mockItem = createMockShoppingListItem({ shopping_list_item_id: 1, ...updates });
mockPoolInstance.query.mockResolvedValue({ rows: [mockItem], rowCount: 1 });
const result = await shoppingRepo.updateShoppingListItem(1, updates);
expect(mockPoolInstance.query).toHaveBeenCalledWith(
'UPDATE public.shopping_list_items SET quantity = $1, is_purchased = $2, notes = $3 WHERE shopping_list_item_id = $4 RETURNING *',
[updates.quantity, updates.is_purchased, updates.notes, 1]
);
expect(result).toEqual(mockItem);
});
it('should throw an error if the item to update is not found', async () => {
mockPoolInstance.query.mockResolvedValue({ rowCount: 0, rows: [], command: 'UPDATE' });
await expect(shoppingRepo.updateShoppingListItem(999, { quantity: 5 })).rejects.toThrow('Shopping list item not found.');
});
it('should throw an error if no valid fields are provided to update', async () => {
// The function should throw before even querying the database.
await expect(shoppingRepo.updateShoppingListItem(1, {})).rejects.toThrow('No valid fields to update.');
});
it('should throw a generic error if the database query fails', async () => {
const dbError = new Error('DB Connection Error');
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.updateShoppingListItem(1, { is_purchased: true })).rejects.toThrow('Failed to update shopping list item.');
});
});
describe('removeShoppingListItem', () => {
it('should delete an item if rowCount is 1', async () => {
mockPoolInstance.query.mockResolvedValue({ rowCount: 1, rows: [], command: 'DELETE' });
await expect(shoppingRepo.removeShoppingListItem(1)).resolves.toBeUndefined();
expect(mockPoolInstance.query).toHaveBeenCalledWith('DELETE FROM public.shopping_list_items WHERE shopping_list_item_id = $1', [1]);
});
it('should throw an error if no rows are deleted (item not found)', async () => {
mockPoolInstance.query.mockResolvedValue({ rowCount: 0, rows: [], command: 'DELETE' });
await expect(shoppingRepo.removeShoppingListItem(999)).rejects.toThrow('Shopping list item not found.');
});
it('should throw a generic error if the database query fails', async () => {
const dbError = new Error('DB Connection Error');
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.removeShoppingListItem(1)).rejects.toThrow('Failed to remove item from shopping list.');
});
});
describe('completeShoppingList', () => {
it('should call the complete_shopping_list database function', async () => {
mockPoolInstance.query.mockResolvedValue({ rows: [{ complete_shopping_list: 1 }] });
const result = await shoppingRepo.completeShoppingList(1, 'user-123', 5000);
expect(result).toBe(1);
expect(mockPoolInstance.query).toHaveBeenCalledWith('SELECT public.complete_shopping_list($1, $2, $3)', [1, 'user-123', 5000]);
});
it('should throw ForeignKeyConstraintError if the shopping list does not exist', async () => {
const dbError = new Error('violates foreign key constraint');
(dbError as any).code = '23503';
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.completeShoppingList(999, 'user-123')).rejects.toThrow('The specified shopping list does not exist.');
});
it('should throw a generic error if the database query fails', async () => {
const dbError = new Error('DB Function Error');
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.completeShoppingList(1, 'user-123')).rejects.toThrow('Failed to complete shopping list.');
});
});
describe('generateShoppingListForMenuPlan', () => {
it('should call the correct database function and return items', async () => {
const mockItems = [{ master_item_id: 1, item_name: 'Apples', quantity_needed: 2 }];
mockPoolInstance.query.mockResolvedValue({ rows: mockItems });
const result = await shoppingRepo.generateShoppingListForMenuPlan(1, 'user-1');
expect(mockPoolInstance.query).toHaveBeenCalledWith('SELECT * FROM public.generate_shopping_list_for_menu_plan($1, $2)', [1, 'user-1']);
expect(result).toEqual(mockItems);
});
it('should return an empty array if the menu plan generates no items', async () => {
mockPoolInstance.query.mockResolvedValue({ rows: [] });
const result = await shoppingRepo.generateShoppingListForMenuPlan(1, 'user-1');
expect(result).toEqual([]);
});
it('should throw an error if the database query fails', async () => {
mockPoolInstance.query.mockRejectedValue(new Error('DB Error'));
await expect(shoppingRepo.generateShoppingListForMenuPlan(1, 'user-1')).rejects.toThrow('Failed to generate shopping list for menu plan.');
});
});
describe('addMenuPlanToShoppingList', () => {
it('should call the correct database function and return added items', async () => {
const mockItems = [{ master_item_id: 1, item_name: 'Apples', quantity_needed: 2 }];
mockPoolInstance.query.mockResolvedValue({ rows: mockItems });
const result = await shoppingRepo.addMenuPlanToShoppingList(1, 10, 'user-1');
expect(mockPoolInstance.query).toHaveBeenCalledWith('SELECT * FROM public.add_menu_plan_to_shopping_list($1, $2, $3)', [1, 10, 'user-1']);
expect(result).toEqual(mockItems);
});
it('should return an empty array if no items are added from the menu plan', async () => {
mockPoolInstance.query.mockResolvedValue({ rows: [] });
const result = await shoppingRepo.addMenuPlanToShoppingList(1, 10, 'user-1');
expect(result).toEqual([]);
});
it('should throw an error if the database query fails', async () => {
mockPoolInstance.query.mockRejectedValue(new Error('DB Error'));
await expect(shoppingRepo.addMenuPlanToShoppingList(1, 10, 'user-1')).rejects.toThrow('Failed to add menu plan to shopping list.');
});
});
describe('getPantryLocations', () => {
it('should return a list of pantry locations for a user', async () => {
const mockLocations = [{ pantry_location_id: 1, name: 'Fridge', user_id: 'user-1' }];
mockPoolInstance.query.mockResolvedValue({ rows: mockLocations });
const result = await shoppingRepo.getPantryLocations('user-1');
expect(mockPoolInstance.query).toHaveBeenCalledWith('SELECT * FROM public.pantry_locations WHERE user_id = $1 ORDER BY name', ['user-1']);
expect(result).toEqual(mockLocations);
});
it('should return an empty array if user has no pantry locations', async () => {
mockPoolInstance.query.mockResolvedValue({ rows: [] });
const result = await shoppingRepo.getPantryLocations('user-1');
expect(result).toEqual([]);
});
it('should throw an error if the database query fails', async () => {
mockPoolInstance.query.mockRejectedValue(new Error('DB Error'));
await expect(shoppingRepo.getPantryLocations('user-1')).rejects.toThrow('Failed to get pantry locations.');
});
});
describe('createPantryLocation', () => {
it('should insert a new pantry location and return it', async () => {
const mockLocation = { pantry_location_id: 1, name: 'Freezer', user_id: 'user-1' };
mockPoolInstance.query.mockResolvedValue({ rows: [mockLocation] });
const result = await shoppingRepo.createPantryLocation('user-1', 'Freezer');
expect(mockPoolInstance.query).toHaveBeenCalledWith('INSERT INTO public.pantry_locations (user_id, name) VALUES ($1, $2) RETURNING *', ['user-1', 'Freezer']);
expect(result).toEqual(mockLocation);
});
it('should throw UniqueConstraintError on duplicate name', async () => {
const dbError = new Error('duplicate key value violates unique constraint');
(dbError as any).code = '23505';
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.createPantryLocation('user-1', 'Fridge')).rejects.toThrow(UniqueConstraintError);
});
it('should throw ForeignKeyConstraintError if user does not exist', async () => {
const dbError = new Error('violates foreign key constraint');
(dbError as any).code = '23503';
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.createPantryLocation('non-existent-user', 'Pantry')).rejects.toThrow(ForeignKeyConstraintError);
});
it('should throw a generic error if the database query fails', async () => {
mockPoolInstance.query.mockRejectedValue(new Error('DB Error'));
await expect(shoppingRepo.createPantryLocation('user-1', 'Pantry')).rejects.toThrow('Failed to create pantry location.');
});
});
describe('getShoppingTripHistory', () => {
it('should return a list of shopping trips for a user', async () => {
const mockTrips = [{ shopping_trip_id: 1, user_id: 'user-1', items: [] }];
mockPoolInstance.query.mockResolvedValue({ rows: mockTrips });
const result = await shoppingRepo.getShoppingTripHistory('user-1');
expect(mockPoolInstance.query).toHaveBeenCalledWith(expect.stringContaining('FROM public.shopping_trips st'), ['user-1']);
expect(result).toEqual(mockTrips);
});
it('should return an empty array if a user has no shopping trips', async () => {
mockPoolInstance.query.mockResolvedValue({ rows: [] });
const result = await shoppingRepo.getShoppingTripHistory('user-no-trips');
expect(result).toEqual([]);
});
it('should throw an error if the database query fails', async () => {
mockPoolInstance.query.mockRejectedValue(new Error('DB Error'));
await expect(shoppingRepo.getShoppingTripHistory('user-1')).rejects.toThrow('Failed to retrieve shopping trip history.');
});
});
describe('createReceipt', () => {
it('should insert a new receipt and return it', async () => {
const mockReceipt = { receipt_id: 1, user_id: 'user-1', receipt_image_url: 'url', status: 'pending' };
mockPoolInstance.query.mockResolvedValue({ rows: [mockReceipt] });
const result = await shoppingRepo.createReceipt('user-1', 'url');
expect(mockPoolInstance.query).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO public.receipts'), ['user-1', 'url']);
expect(result).toEqual(mockReceipt);
});
it('should throw ForeignKeyConstraintError if user does not exist', async () => {
const dbError = new Error('violates foreign key constraint');
(dbError as any).code = '23503';
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.createReceipt('non-existent-user', 'url')).rejects.toThrow(ForeignKeyConstraintError);
});
it('should throw a generic error if the database query fails', async () => {
mockPoolInstance.query.mockRejectedValue(new Error('DB Error'));
await expect(shoppingRepo.createReceipt('user-1', 'url')).rejects.toThrow('Failed to create receipt record.');
});
});
describe('findReceiptOwner', () => {
it('should return the user_id of the receipt owner', async () => {
const mockOwner = { user_id: 'owner-123' };
mockPoolInstance.query.mockResolvedValue({ rows: [mockOwner] });
const result = await shoppingRepo.findReceiptOwner(1);
expect(mockPoolInstance.query).toHaveBeenCalledWith('SELECT user_id FROM public.receipts WHERE receipt_id = $1', [1]);
expect(result).toEqual(mockOwner);
});
it('should return undefined if the receipt is not found', async () => {
mockPoolInstance.query.mockResolvedValue({ rows: [] });
const result = await shoppingRepo.findReceiptOwner(999);
expect(result).toBeUndefined();
});
it('should throw a generic error if the database query fails', async () => {
const dbError = new Error('DB Error');
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.findReceiptOwner(1)).rejects.toThrow('Failed to retrieve receipt owner from database.');
});
});
describe('processReceiptItems', () => {
it('should call the process_receipt_items database function with correct parameters', async () => {
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);
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"'),
]
);
expect(mockClient.query).toHaveBeenCalledWith('COMMIT');
expect(mockClient.release).toHaveBeenCalled();
});
it('should handle items with quantity but no price', async () => {
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: '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])]));
});
it('should update receipt status to "failed" on error', async () => {
const mockClient = { query: vi.fn(), release: vi.fn() };
vi.mocked(mockPoolInstance.connect).mockResolvedValue(mockClient as any);
const dbError = new Error('Function error');
mockClient.query
.mockResolvedValueOnce({ rows: [] }) // BEGIN
.mockRejectedValueOnce(dbError); // process_receipt_items fails
const items = [{ raw_item_description: 'Milk', price_paid_cents: 399 }];
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]);
});
// Note: The `processReceiptItems` method in shopping.db.ts has a potential bug where it calls `client.query('ROLLBACK')`
// but then calls `this.db.query(...)` to update the status. This should be `client.query(...)` to ensure
// the status update happens on the same transaction before rollback. I've left it as is to match the
// existing logic but it's something to be aware of.
});
describe('findDealsForReceipt', () => {
it('should call the find_deals_for_receipt_items database function', async () => {
const mockDeals = [{ receipt_item_id: 1, master_item_id: 10, item_name: 'Milk', price_paid_cents: 399, current_best_price_in_cents: 350, potential_savings_cents: 49, deal_store_name: 'Grocer', flyer_id: 101 }];
mockPoolInstance.query.mockResolvedValue({ rows: mockDeals });
const result = await shoppingRepo.findDealsForReceipt(1);
expect(mockPoolInstance.query).toHaveBeenCalledWith('SELECT * FROM public.find_deals_for_receipt_items($1)', [1]);
expect(result).toEqual(mockDeals);
});
it('should return an empty array if no deals are found', async () => {
mockPoolInstance.query.mockResolvedValue({ rows: [] });
const result = await shoppingRepo.findDealsForReceipt(1);
expect(result).toEqual([]);
});
it('should throw an error if the database query fails', async () => {
const dbError = new Error('DB Error');
mockPoolInstance.query.mockRejectedValue(dbError);
await expect(shoppingRepo.findDealsForReceipt(1)).rejects.toThrow('Failed to find deals for receipt.');
});
});
});