@ideal-photography/shared
Version:
Shared MongoDB and utility logic for Ideal Photography PWAs: users, products, services, bookings, orders/cart, galleries, reviews, notifications, campaigns, settings, audit logs, minimart items/orders, and push notification subscriptions.
119 lines (102 loc) • 3.69 kB
JavaScript
import { jest } from '@jest/globals';
// Mock StockService
const mockReleaseReservation = jest.fn().mockResolvedValue(true);
jest.unstable_mockModule('../StockService.js', () => ({
StockService: { releaseReservation: mockReleaseReservation }
}));
// Mock data storage
const mockOrders = [];
const mockBookings = [];
// Mock mongoDB with proper connection state and replica set support
const mockMongoose = {
startSession: jest.fn(),
connection: {
readyState: 1,
db: {
serverConfig: {
isReplicaSet: false, // Set to false to skip transactions in tests
isMongos: false
}
}
}
};
// Mock session object
const fakeSession = {
withTransaction: jest.fn(async (fn) => await fn()),
endSession: jest.fn(),
};
// Always return fake session
mockMongoose.startSession.mockResolvedValue(fakeSession);
// Mock Order model - return mockOrders array directly (async iterable)
const mockOrderFind = jest.fn(() => {
const query = {
session: jest.fn(function () {
return Promise.resolve(mockOrders);
}),
exec: jest.fn(() => Promise.resolve(mockOrders))
};
// Make it awaitable
query.then = (resolve) => resolve(mockOrders);
return query;
});
// Mock Booking model - return mockBookings array directly (async iterable)
const mockBookingFind = jest.fn(() => {
const query = {
session: jest.fn(function () {
return Promise.resolve(mockBookings);
}),
exec: jest.fn(() => Promise.resolve(mockBookings))
};
// Make it awaitable
query.then = (resolve) => resolve(mockBookings);
return query;
});
jest.unstable_mockModule('../../mongoDB/index.js', () => ({
mongoose: mockMongoose,
models: {
Order: { find: mockOrderFind },
Booking: { find: mockBookingFind },
},
}));
// Now import after mocks
const { processExpirations } = await import('../RentalSessionManager.js');
describe('RentalSessionManager', () => {
beforeEach(() => {
mockOrders.length = 0;
mockBookings.length = 0;
jest.clearAllMocks();
});
it('should complete rental order and release stock', async () => {
const endDate = new Date(Date.now() - 60 * 60 * 1000);
const order = {
_id: 'order1',
status: 'in_progress',
items: [
{ productType: 'equipment_rental', rentalPeriod: { endDate } },
],
metadata: {},
save: jest.fn().mockResolvedValue(true),
};
mockOrders.push(order);
await processExpirations(new Date());
expect(order.status).toBe('completed');
expect(order.metadata.autoTransitioned).toBe(true);
expect(mockReleaseReservation).toHaveBeenCalledWith('order1', order.items);
expect(order.save).toHaveBeenCalled();
}, 10000); // Increase timeout to 10s
it('should mark booking completed', async () => {
const prefDate = new Date(Date.now() - 2 * 60 * 60 * 1000);
const booking = {
status: 'in_progress',
preferredDate: prefDate,
duration: 1,
metadata: {},
save: jest.fn().mockResolvedValue(true),
};
mockBookings.push(booking);
await processExpirations(new Date());
expect(booking.status).toBe('completed');
expect(booking.metadata.autoTransitioned).toBe(true);
expect(booking.save).toHaveBeenCalled();
}, 10000); // Increase timeout to 10s
});