Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 1m17s
666 lines
22 KiB
TypeScript
666 lines
22 KiB
TypeScript
// src/routes/inventory.routes.test.ts
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import supertest from 'supertest';
|
|
import type { Request, Response, NextFunction } from 'express';
|
|
import { createMockUserProfile } from '../tests/utils/mockFactories';
|
|
import { createTestApp } from '../tests/utils/createTestApp';
|
|
import { NotFoundError } from '../services/db/errors.db';
|
|
import type { UserInventoryItem, ExpiringItemsResponse } from '../types/expiry';
|
|
|
|
// Mock the expiryService module
|
|
vi.mock('../services/expiryService.server', () => ({
|
|
getInventory: vi.fn(),
|
|
addInventoryItem: vi.fn(),
|
|
getInventoryItemById: vi.fn(),
|
|
updateInventoryItem: vi.fn(),
|
|
deleteInventoryItem: vi.fn(),
|
|
markItemConsumed: vi.fn(),
|
|
getExpiringItemsGrouped: vi.fn(),
|
|
getExpiringItems: vi.fn(),
|
|
getExpiredItems: vi.fn(),
|
|
getAlertSettings: vi.fn(),
|
|
updateAlertSettings: vi.fn(),
|
|
getRecipeSuggestionsForExpiringItems: vi.fn(),
|
|
}));
|
|
|
|
// Mock the logger to keep test output clean
|
|
vi.mock('../services/logger.server', async () => ({
|
|
logger: (await import('../tests/utils/mockLogger')).mockLogger,
|
|
}));
|
|
|
|
// Import the router and mocked service AFTER all mocks are defined.
|
|
import inventoryRouter from './inventory.routes';
|
|
import * as expiryService from '../services/expiryService.server';
|
|
|
|
const mockUser = createMockUserProfile({
|
|
user: { user_id: 'user-123', email: 'test@test.com' },
|
|
});
|
|
|
|
// Standardized mock for passport
|
|
vi.mock('../config/passport', () => ({
|
|
default: {
|
|
authenticate: vi.fn(() => (req: Request, res: Response, next: NextFunction) => {
|
|
req.user = mockUser;
|
|
next();
|
|
}),
|
|
initialize: () => (req: Request, res: Response, next: NextFunction) => next(),
|
|
},
|
|
}));
|
|
|
|
// Define a reusable matcher for the logger object.
|
|
const expectLogger = expect.objectContaining({
|
|
info: expect.any(Function),
|
|
error: expect.any(Function),
|
|
});
|
|
|
|
// Helper to create mock inventory item
|
|
function createMockInventoryItem(overrides: Partial<UserInventoryItem> = {}): UserInventoryItem {
|
|
return {
|
|
inventory_id: 1,
|
|
user_id: 'user-123',
|
|
product_id: null,
|
|
master_item_id: 100,
|
|
item_name: 'Milk',
|
|
quantity: 1,
|
|
unit: 'liters',
|
|
purchase_date: '2024-01-10',
|
|
expiry_date: '2024-02-10',
|
|
source: 'manual',
|
|
location: 'fridge',
|
|
notes: null,
|
|
is_consumed: false,
|
|
consumed_at: null,
|
|
expiry_source: 'manual',
|
|
receipt_item_id: null,
|
|
pantry_location_id: 1,
|
|
notification_sent_at: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
days_until_expiry: 10,
|
|
expiry_status: 'fresh',
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe('Inventory Routes (/api/inventory)', () => {
|
|
const mockUserProfile = createMockUserProfile({
|
|
user: { user_id: 'user-123', email: 'test@test.com' },
|
|
});
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
// Provide default mock implementations
|
|
vi.mocked(expiryService.getInventory).mockResolvedValue({ items: [], total: 0 });
|
|
vi.mocked(expiryService.getExpiringItems).mockResolvedValue([]);
|
|
vi.mocked(expiryService.getExpiredItems).mockResolvedValue([]);
|
|
vi.mocked(expiryService.getAlertSettings).mockResolvedValue([]);
|
|
});
|
|
|
|
const app = createTestApp({
|
|
router: inventoryRouter,
|
|
basePath: '/api/inventory',
|
|
authenticatedUser: mockUserProfile,
|
|
});
|
|
|
|
// ============================================================================
|
|
// INVENTORY ITEM ENDPOINTS
|
|
// ============================================================================
|
|
|
|
describe('GET /', () => {
|
|
it('should return paginated inventory items', async () => {
|
|
const mockItems = [createMockInventoryItem()];
|
|
vi.mocked(expiryService.getInventory).mockResolvedValue({
|
|
items: mockItems,
|
|
total: 1,
|
|
});
|
|
|
|
const response = await supertest(app).get('/api/inventory');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.data.items).toHaveLength(1);
|
|
expect(response.body.data.total).toBe(1);
|
|
});
|
|
|
|
it('should support filtering by location', async () => {
|
|
vi.mocked(expiryService.getInventory).mockResolvedValue({ items: [], total: 0 });
|
|
|
|
const response = await supertest(app).get('/api/inventory?location=fridge');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(expiryService.getInventory).toHaveBeenCalledWith(
|
|
expect.objectContaining({ location: 'fridge' }),
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should support filtering by expiring_within_days', async () => {
|
|
vi.mocked(expiryService.getInventory).mockResolvedValue({ items: [], total: 0 });
|
|
|
|
const response = await supertest(app).get('/api/inventory?expiring_within_days=7');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(expiryService.getInventory).toHaveBeenCalledWith(
|
|
expect.objectContaining({ expiring_within_days: 7 }),
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should support search filter', async () => {
|
|
vi.mocked(expiryService.getInventory).mockResolvedValue({ items: [], total: 0 });
|
|
|
|
const response = await supertest(app).get('/api/inventory?search=milk');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(expiryService.getInventory).toHaveBeenCalledWith(
|
|
expect.objectContaining({ search: 'milk' }),
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should support sorting', async () => {
|
|
vi.mocked(expiryService.getInventory).mockResolvedValue({ items: [], total: 0 });
|
|
|
|
const response = await supertest(app).get(
|
|
'/api/inventory?sort_by=expiry_date&sort_order=asc',
|
|
);
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(expiryService.getInventory).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
sort_by: 'expiry_date',
|
|
sort_order: 'asc',
|
|
}),
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should return 400 for invalid location', async () => {
|
|
const response = await supertest(app).get('/api/inventory?location=invalid');
|
|
|
|
expect(response.status).toBe(400);
|
|
});
|
|
|
|
it('should return 500 if service fails', async () => {
|
|
vi.mocked(expiryService.getInventory).mockRejectedValue(new Error('DB Error'));
|
|
|
|
const response = await supertest(app).get('/api/inventory');
|
|
|
|
expect(response.status).toBe(500);
|
|
});
|
|
});
|
|
|
|
describe('POST /', () => {
|
|
it('should add a new inventory item', async () => {
|
|
const mockItem = createMockInventoryItem();
|
|
vi.mocked(expiryService.addInventoryItem).mockResolvedValue(mockItem);
|
|
|
|
const response = await supertest(app).post('/api/inventory').send({
|
|
item_name: 'Milk',
|
|
source: 'manual',
|
|
quantity: 1,
|
|
location: 'fridge',
|
|
expiry_date: '2024-02-10',
|
|
});
|
|
|
|
expect(response.status).toBe(201);
|
|
expect(response.body.data.item_name).toBe('Milk');
|
|
expect(expiryService.addInventoryItem).toHaveBeenCalledWith(
|
|
mockUserProfile.user.user_id,
|
|
expect.objectContaining({
|
|
item_name: 'Milk',
|
|
source: 'manual',
|
|
}),
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should return 400 if item_name is missing', async () => {
|
|
const response = await supertest(app).post('/api/inventory').send({
|
|
source: 'manual',
|
|
});
|
|
|
|
expect(response.status).toBe(400);
|
|
// Zod returns a type error message when a required field is undefined
|
|
expect(response.body.error.details[0].message).toMatch(/expected string|required/i);
|
|
});
|
|
|
|
it('should return 400 for invalid source', async () => {
|
|
const response = await supertest(app).post('/api/inventory').send({
|
|
item_name: 'Milk',
|
|
source: 'invalid_source',
|
|
});
|
|
|
|
expect(response.status).toBe(400);
|
|
});
|
|
|
|
it('should return 400 for invalid expiry_date format', async () => {
|
|
const response = await supertest(app).post('/api/inventory').send({
|
|
item_name: 'Milk',
|
|
source: 'manual',
|
|
expiry_date: '01-10-2024',
|
|
});
|
|
|
|
expect(response.status).toBe(400);
|
|
expect(response.body.error.details[0].message).toMatch(/YYYY-MM-DD/);
|
|
});
|
|
|
|
it('should return 500 if service fails', async () => {
|
|
vi.mocked(expiryService.addInventoryItem).mockRejectedValue(new Error('DB Error'));
|
|
|
|
const response = await supertest(app).post('/api/inventory').send({
|
|
item_name: 'Milk',
|
|
source: 'manual',
|
|
});
|
|
|
|
expect(response.status).toBe(500);
|
|
});
|
|
});
|
|
|
|
describe('GET /:inventoryId', () => {
|
|
it('should return a specific inventory item', async () => {
|
|
const mockItem = createMockInventoryItem();
|
|
vi.mocked(expiryService.getInventoryItemById).mockResolvedValue(mockItem);
|
|
|
|
const response = await supertest(app).get('/api/inventory/1');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.data.inventory_id).toBe(1);
|
|
expect(expiryService.getInventoryItemById).toHaveBeenCalledWith(
|
|
1,
|
|
mockUserProfile.user.user_id,
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should return 404 when item not found', async () => {
|
|
vi.mocked(expiryService.getInventoryItemById).mockRejectedValue(
|
|
new NotFoundError('Item not found'),
|
|
);
|
|
|
|
const response = await supertest(app).get('/api/inventory/999');
|
|
|
|
expect(response.status).toBe(404);
|
|
});
|
|
|
|
it('should return 400 for invalid inventory ID', async () => {
|
|
const response = await supertest(app).get('/api/inventory/abc');
|
|
|
|
expect(response.status).toBe(400);
|
|
});
|
|
});
|
|
|
|
describe('PUT /:inventoryId', () => {
|
|
it('should update an inventory item', async () => {
|
|
const mockItem = createMockInventoryItem({ quantity: 2 });
|
|
vi.mocked(expiryService.updateInventoryItem).mockResolvedValue(mockItem);
|
|
|
|
const response = await supertest(app).put('/api/inventory/1').send({
|
|
quantity: 2,
|
|
});
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.data.quantity).toBe(2);
|
|
});
|
|
|
|
it('should update expiry_date', async () => {
|
|
const mockItem = createMockInventoryItem({ expiry_date: '2024-03-01' });
|
|
vi.mocked(expiryService.updateInventoryItem).mockResolvedValue(mockItem);
|
|
|
|
const response = await supertest(app).put('/api/inventory/1').send({
|
|
expiry_date: '2024-03-01',
|
|
});
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(expiryService.updateInventoryItem).toHaveBeenCalledWith(
|
|
1,
|
|
mockUserProfile.user.user_id,
|
|
expect.objectContaining({ expiry_date: '2024-03-01' }),
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should return 400 if no update fields provided', async () => {
|
|
const response = await supertest(app).put('/api/inventory/1').send({});
|
|
|
|
expect(response.status).toBe(400);
|
|
expect(response.body.error.details[0].message).toMatch(/At least one field/);
|
|
});
|
|
|
|
it('should return 404 when item not found', async () => {
|
|
vi.mocked(expiryService.updateInventoryItem).mockRejectedValue(
|
|
new NotFoundError('Item not found'),
|
|
);
|
|
|
|
const response = await supertest(app).put('/api/inventory/999').send({
|
|
quantity: 2,
|
|
});
|
|
|
|
expect(response.status).toBe(404);
|
|
});
|
|
});
|
|
|
|
describe('DELETE /:inventoryId', () => {
|
|
it('should delete an inventory item', async () => {
|
|
vi.mocked(expiryService.deleteInventoryItem).mockResolvedValue(undefined);
|
|
|
|
const response = await supertest(app).delete('/api/inventory/1');
|
|
|
|
expect(response.status).toBe(204);
|
|
expect(expiryService.deleteInventoryItem).toHaveBeenCalledWith(
|
|
1,
|
|
mockUserProfile.user.user_id,
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should return 404 when item not found', async () => {
|
|
vi.mocked(expiryService.deleteInventoryItem).mockRejectedValue(
|
|
new NotFoundError('Item not found'),
|
|
);
|
|
|
|
const response = await supertest(app).delete('/api/inventory/999');
|
|
|
|
expect(response.status).toBe(404);
|
|
});
|
|
});
|
|
|
|
describe('POST /:inventoryId/consume', () => {
|
|
it('should mark item as consumed', async () => {
|
|
vi.mocked(expiryService.markItemConsumed).mockResolvedValue(undefined);
|
|
|
|
const response = await supertest(app).post('/api/inventory/1/consume');
|
|
|
|
expect(response.status).toBe(204);
|
|
expect(expiryService.markItemConsumed).toHaveBeenCalledWith(
|
|
1,
|
|
mockUserProfile.user.user_id,
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should return 404 when item not found', async () => {
|
|
vi.mocked(expiryService.markItemConsumed).mockRejectedValue(
|
|
new NotFoundError('Item not found'),
|
|
);
|
|
|
|
const response = await supertest(app).post('/api/inventory/999/consume');
|
|
|
|
expect(response.status).toBe(404);
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// EXPIRING ITEMS ENDPOINTS
|
|
// ============================================================================
|
|
|
|
describe('GET /expiring/summary', () => {
|
|
it('should return expiring items grouped by urgency', async () => {
|
|
const mockSummary: ExpiringItemsResponse = {
|
|
expiring_today: [createMockInventoryItem({ days_until_expiry: 0 })],
|
|
expiring_this_week: [createMockInventoryItem({ days_until_expiry: 3 })],
|
|
expiring_this_month: [createMockInventoryItem({ days_until_expiry: 20 })],
|
|
already_expired: [createMockInventoryItem({ days_until_expiry: -5 })],
|
|
counts: {
|
|
today: 1,
|
|
this_week: 1,
|
|
this_month: 1,
|
|
expired: 1,
|
|
total: 4,
|
|
},
|
|
};
|
|
|
|
vi.mocked(expiryService.getExpiringItemsGrouped).mockResolvedValue(mockSummary);
|
|
|
|
const response = await supertest(app).get('/api/inventory/expiring/summary');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.data.counts.total).toBe(4);
|
|
});
|
|
|
|
it('should return 500 if service fails', async () => {
|
|
vi.mocked(expiryService.getExpiringItemsGrouped).mockRejectedValue(new Error('DB Error'));
|
|
|
|
const response = await supertest(app).get('/api/inventory/expiring/summary');
|
|
|
|
expect(response.status).toBe(500);
|
|
});
|
|
});
|
|
|
|
describe('GET /expiring', () => {
|
|
it('should return items expiring within default 7 days', async () => {
|
|
const mockItems = [createMockInventoryItem({ days_until_expiry: 5 })];
|
|
vi.mocked(expiryService.getExpiringItems).mockResolvedValue(mockItems);
|
|
|
|
const response = await supertest(app).get('/api/inventory/expiring');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.data.items).toHaveLength(1);
|
|
expect(expiryService.getExpiringItems).toHaveBeenCalledWith(
|
|
mockUserProfile.user.user_id,
|
|
7,
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should accept custom days parameter', async () => {
|
|
vi.mocked(expiryService.getExpiringItems).mockResolvedValue([]);
|
|
|
|
const response = await supertest(app).get('/api/inventory/expiring?days=14');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(expiryService.getExpiringItems).toHaveBeenCalledWith(
|
|
mockUserProfile.user.user_id,
|
|
14,
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should return 400 for invalid days parameter', async () => {
|
|
const response = await supertest(app).get('/api/inventory/expiring?days=100');
|
|
|
|
expect(response.status).toBe(400);
|
|
});
|
|
});
|
|
|
|
describe('GET /expired', () => {
|
|
it('should return already expired items', async () => {
|
|
const mockItems = [
|
|
createMockInventoryItem({ days_until_expiry: -3, expiry_status: 'expired' }),
|
|
];
|
|
vi.mocked(expiryService.getExpiredItems).mockResolvedValue(mockItems);
|
|
|
|
const response = await supertest(app).get('/api/inventory/expired');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.data.items).toHaveLength(1);
|
|
expect(expiryService.getExpiredItems).toHaveBeenCalledWith(
|
|
mockUserProfile.user.user_id,
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should return 500 if service fails', async () => {
|
|
vi.mocked(expiryService.getExpiredItems).mockRejectedValue(new Error('DB Error'));
|
|
|
|
const response = await supertest(app).get('/api/inventory/expired');
|
|
|
|
expect(response.status).toBe(500);
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// ALERT SETTINGS ENDPOINTS
|
|
// ============================================================================
|
|
|
|
describe('GET /alerts', () => {
|
|
it('should return user alert settings', async () => {
|
|
const mockSettings = [
|
|
{
|
|
expiry_alert_id: 1,
|
|
user_id: 'user-123',
|
|
alert_method: 'email' as const,
|
|
days_before_expiry: 3,
|
|
is_enabled: true,
|
|
last_alert_sent_at: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
},
|
|
];
|
|
|
|
vi.mocked(expiryService.getAlertSettings).mockResolvedValue(mockSettings);
|
|
|
|
const response = await supertest(app).get('/api/inventory/alerts');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.data).toHaveLength(1);
|
|
expect(response.body.data[0].alert_method).toBe('email');
|
|
});
|
|
|
|
it('should return 500 if service fails', async () => {
|
|
vi.mocked(expiryService.getAlertSettings).mockRejectedValue(new Error('DB Error'));
|
|
|
|
const response = await supertest(app).get('/api/inventory/alerts');
|
|
|
|
expect(response.status).toBe(500);
|
|
});
|
|
});
|
|
|
|
describe('PUT /alerts/:alertMethod', () => {
|
|
it('should update alert settings for email', async () => {
|
|
const mockSettings = {
|
|
expiry_alert_id: 1,
|
|
user_id: 'user-123',
|
|
alert_method: 'email' as const,
|
|
days_before_expiry: 5,
|
|
is_enabled: true,
|
|
last_alert_sent_at: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
vi.mocked(expiryService.updateAlertSettings).mockResolvedValue(mockSettings);
|
|
|
|
const response = await supertest(app).put('/api/inventory/alerts/email').send({
|
|
days_before_expiry: 5,
|
|
is_enabled: true,
|
|
});
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.data.days_before_expiry).toBe(5);
|
|
expect(expiryService.updateAlertSettings).toHaveBeenCalledWith(
|
|
mockUserProfile.user.user_id,
|
|
'email',
|
|
{ days_before_expiry: 5, is_enabled: true },
|
|
expectLogger,
|
|
);
|
|
});
|
|
|
|
it('should return 400 for invalid alert method', async () => {
|
|
const response = await supertest(app).put('/api/inventory/alerts/sms').send({
|
|
is_enabled: true,
|
|
});
|
|
|
|
expect(response.status).toBe(400);
|
|
});
|
|
|
|
it('should return 400 for invalid days_before_expiry', async () => {
|
|
const response = await supertest(app).put('/api/inventory/alerts/email').send({
|
|
days_before_expiry: 0,
|
|
});
|
|
|
|
expect(response.status).toBe(400);
|
|
});
|
|
|
|
it('should return 400 if days_before_expiry exceeds maximum', async () => {
|
|
const response = await supertest(app).put('/api/inventory/alerts/email').send({
|
|
days_before_expiry: 31,
|
|
});
|
|
|
|
expect(response.status).toBe(400);
|
|
});
|
|
|
|
it('should return 500 if service fails', async () => {
|
|
vi.mocked(expiryService.updateAlertSettings).mockRejectedValue(new Error('DB Error'));
|
|
|
|
const response = await supertest(app).put('/api/inventory/alerts/email').send({
|
|
is_enabled: false,
|
|
});
|
|
|
|
expect(response.status).toBe(500);
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// RECIPE SUGGESTIONS ENDPOINT
|
|
// ============================================================================
|
|
|
|
describe('GET /recipes/suggestions', () => {
|
|
it('should return recipe suggestions for expiring items', async () => {
|
|
const mockInventoryItem = createMockInventoryItem({ inventory_id: 1, item_name: 'Milk' });
|
|
const mockResult = {
|
|
recipes: [
|
|
{
|
|
recipe_id: 1,
|
|
recipe_name: 'Milk Smoothie',
|
|
description: 'A healthy smoothie',
|
|
prep_time_minutes: 5,
|
|
cook_time_minutes: 0,
|
|
servings: 2,
|
|
photo_url: null,
|
|
matching_items: [mockInventoryItem],
|
|
match_count: 1,
|
|
},
|
|
],
|
|
total: 1,
|
|
considered_items: [mockInventoryItem],
|
|
};
|
|
|
|
vi.mocked(expiryService.getRecipeSuggestionsForExpiringItems).mockResolvedValue(
|
|
mockResult as any,
|
|
);
|
|
|
|
const response = await supertest(app).get('/api/inventory/recipes/suggestions');
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.data.recipes).toHaveLength(1);
|
|
expect(response.body.data.total).toBe(1);
|
|
});
|
|
|
|
it('should accept days, limit, and offset parameters', async () => {
|
|
vi.mocked(expiryService.getRecipeSuggestionsForExpiringItems).mockResolvedValue({
|
|
recipes: [],
|
|
total: 0,
|
|
considered_items: [],
|
|
});
|
|
|
|
const response = await supertest(app).get(
|
|
'/api/inventory/recipes/suggestions?days=14&limit=5&offset=10',
|
|
);
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(expiryService.getRecipeSuggestionsForExpiringItems).toHaveBeenCalledWith(
|
|
mockUserProfile.user.user_id,
|
|
14,
|
|
expectLogger,
|
|
{ limit: 5, offset: 10 },
|
|
);
|
|
});
|
|
|
|
it('should return 400 for invalid days parameter', async () => {
|
|
const response = await supertest(app).get('/api/inventory/recipes/suggestions?days=100');
|
|
|
|
expect(response.status).toBe(400);
|
|
});
|
|
|
|
it('should return 500 if service fails', async () => {
|
|
vi.mocked(expiryService.getRecipeSuggestionsForExpiringItems).mockRejectedValue(
|
|
new Error('DB Error'),
|
|
);
|
|
|
|
const response = await supertest(app).get('/api/inventory/recipes/suggestions');
|
|
|
|
expect(response.status).toBe(500);
|
|
});
|
|
});
|
|
});
|