122 lines
3.4 KiB
TypeScript
122 lines
3.4 KiB
TypeScript
import { beforeEach, expect, mock, test } from 'bun:test';
|
|
|
|
import { Errors } from '@/lib/errors';
|
|
import { err, ok } from '@/lib/result';
|
|
|
|
const rescheduleAdminBookingMock = mock(async (_userId: string, _id: string, _input: unknown) =>
|
|
ok({})
|
|
);
|
|
|
|
mock.module(
|
|
'@/modules/admin-booking/features/reschedule-admin-booking/reschedule-admin-booking.business',
|
|
() => ({
|
|
__esModule: true,
|
|
rescheduleAdminBooking: rescheduleAdminBookingMock,
|
|
})
|
|
);
|
|
|
|
const { rescheduleAdminBookingHandler } = await import(
|
|
'@/modules/admin-booking/features/reschedule-admin-booking/reschedule-admin-booking.handler'
|
|
);
|
|
|
|
type HandlerContext = {
|
|
get: (key: 'user' | 'requestId') => { id: string } | undefined;
|
|
req: {
|
|
valid: (type: string) => Record<string, unknown>;
|
|
};
|
|
json: ReturnType<typeof mock>;
|
|
};
|
|
|
|
function createContext(input: { userId: string; body: unknown }) {
|
|
const json = mock((payload: unknown, init?: unknown) => ({
|
|
payload,
|
|
init,
|
|
}));
|
|
|
|
const c = {
|
|
get: (key: 'user' | 'requestId') => {
|
|
if (key === 'user') return { id: input.userId };
|
|
return undefined;
|
|
},
|
|
req: {
|
|
valid: (type: string) => {
|
|
if (type === 'param') return { id: 'booking-1' };
|
|
if (type === 'json') return input.body as Record<string, unknown>;
|
|
return {};
|
|
},
|
|
},
|
|
json,
|
|
} as unknown as HandlerContext;
|
|
|
|
return { c, json };
|
|
}
|
|
|
|
beforeEach(() => {
|
|
rescheduleAdminBookingMock.mockReset();
|
|
});
|
|
|
|
test('returns 200 with the updated booking', async () => {
|
|
const updatedBooking = {
|
|
id: 'booking-1',
|
|
bookingCode: 'ABC123',
|
|
complexId: 'complex-1',
|
|
complexName: 'Complejo Test',
|
|
courtId: 'court-2',
|
|
courtName: 'Cancha 2',
|
|
sport: { id: 'sport-1', name: 'Tenis', slug: 'tenis' },
|
|
date: '2026-07-15',
|
|
startTime: '14:00',
|
|
endTime: '15:00',
|
|
customerName: 'Juan Perez',
|
|
customerPhone: '1144444444',
|
|
customerEmail: 'juan@example.com',
|
|
price: 15000,
|
|
status: 'CONFIRMED',
|
|
recurringGroupId: null,
|
|
createdAt: '2026-07-14T00:00:00.000Z',
|
|
updatedAt: '2026-07-14T00:00:00.000Z',
|
|
} as const;
|
|
|
|
rescheduleAdminBookingMock.mockResolvedValue(ok(updatedBooking));
|
|
|
|
const { c, json } = createContext({
|
|
userId: 'user-1',
|
|
body: { courtId: 'court-2', startTime: '14:00' },
|
|
});
|
|
|
|
const response = await rescheduleAdminBookingHandler(c as never);
|
|
|
|
expect(rescheduleAdminBookingMock).toHaveBeenCalledWith('user-1', 'booking-1', {
|
|
courtId: 'court-2',
|
|
startTime: '14:00',
|
|
});
|
|
expect(json.mock.calls[0]?.[0]).toEqual(updatedBooking);
|
|
expect(json.mock.calls[0]?.[1]).toBe(200);
|
|
expect(response).toBeDefined();
|
|
});
|
|
|
|
test('maps AdminBookingServiceError to an error response', async () => {
|
|
rescheduleAdminBookingMock.mockResolvedValue(
|
|
err(Errors.conflict('Solo se pueden reprogramar reservas en estado confirmada.'))
|
|
);
|
|
|
|
const { c, json } = createContext({
|
|
userId: 'user-1',
|
|
body: { startTime: '14:00' },
|
|
});
|
|
|
|
const response = await rescheduleAdminBookingHandler(c as never);
|
|
|
|
expect(rescheduleAdminBookingMock).toHaveBeenCalledWith('user-1', 'booking-1', {
|
|
startTime: '14:00',
|
|
});
|
|
expect(json.mock.calls[0]?.[0]).toEqual({
|
|
type: 'https://api.myapp.dev/problems/conflict',
|
|
title: 'Conflict',
|
|
status: 409,
|
|
detail: 'Solo se pueden reprogramar reservas en estado confirmada.',
|
|
});
|
|
expect(json.mock.calls[0]?.[1]).toBe(409);
|
|
expect(response).toBeDefined();
|
|
});
|