Refactor to vertical slice
This commit is contained in:
@@ -2,8 +2,8 @@ import { beforeEach, expect, test } from 'bun:test';
|
||||
|
||||
import { prismaMock, transactionMock, uuidV7Mock } from '../support/prisma.mock';
|
||||
|
||||
const { AdminBookingServiceError, rescheduleAdminBooking } = await import(
|
||||
'@/modules/admin-booking/services/admin-booking.service'
|
||||
const { rescheduleAdminBooking } = await import(
|
||||
'@/modules/admin-booking/features/reschedule-admin-booking/reschedule-admin-booking.business'
|
||||
);
|
||||
|
||||
function makeBooking(overrides?: Record<string, unknown>) {
|
||||
@@ -84,9 +84,11 @@ test('reschedules a booking changing both court and time', async () => {
|
||||
startTime: '14:00',
|
||||
});
|
||||
|
||||
expect(result.courtId).toBe('court-2');
|
||||
expect(result.startTime).toBe('14:00');
|
||||
expect(result.courtName).toBe('Cancha 2');
|
||||
expect(result.ok).toBe(true);
|
||||
if (!result.ok) return;
|
||||
expect(result.value.courtId).toBe('court-2');
|
||||
expect(result.value.startTime).toBe('14:00');
|
||||
expect(result.value.courtName).toBe('Cancha 2');
|
||||
expect(prismaMock.courtBookingLog.create).toHaveBeenCalledTimes(1);
|
||||
expect(prismaMock.courtBooking.update).toHaveBeenCalledWith({
|
||||
where: { id: 'booking-1' },
|
||||
@@ -137,8 +139,10 @@ test('reschedules a booking changing only the time', async () => {
|
||||
startTime: '15:00',
|
||||
});
|
||||
|
||||
expect(result.startTime).toBe('15:00');
|
||||
expect(result.courtId).toBe('court-1');
|
||||
expect(result.ok).toBe(true);
|
||||
if (!result.ok) return;
|
||||
expect(result.value.startTime).toBe('15:00');
|
||||
expect(result.value.courtId).toBe('court-1');
|
||||
expect(prismaMock.courtBookingLog.create).toHaveBeenCalledTimes(1);
|
||||
expect(prismaMock.courtBooking.update).toHaveBeenCalledWith({
|
||||
where: { id: 'booking-1' },
|
||||
@@ -153,15 +157,11 @@ test('reschedules a booking changing only the time', async () => {
|
||||
test('rejects when booking is not found', async () => {
|
||||
prismaMock.courtBooking.findFirst.mockResolvedValue(null as never);
|
||||
|
||||
let caught: unknown;
|
||||
try {
|
||||
await rescheduleAdminBooking('user-1', 'non-existent', { startTime: '14:00' });
|
||||
} catch (error) {
|
||||
caught = error;
|
||||
}
|
||||
const result = await rescheduleAdminBooking('user-1', 'non-existent', { startTime: '14:00' });
|
||||
|
||||
expect(caught).toBeInstanceOf(AdminBookingServiceError);
|
||||
expect((caught as InstanceType<typeof AdminBookingServiceError>).status).toBe(404);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error.type).toBe('not_found');
|
||||
expect(transactionMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -170,15 +170,11 @@ test('rejects when booking status is not CONFIRMED', async () => {
|
||||
makeBooking({ status: 'COMPLETED' }) as never
|
||||
);
|
||||
|
||||
let caught: unknown;
|
||||
try {
|
||||
await rescheduleAdminBooking('user-1', 'booking-1', { startTime: '14:00' });
|
||||
} catch (error) {
|
||||
caught = error;
|
||||
}
|
||||
const result = await rescheduleAdminBooking('user-1', 'booking-1', { startTime: '14:00' });
|
||||
|
||||
expect(caught).toBeInstanceOf(AdminBookingServiceError);
|
||||
expect((caught as InstanceType<typeof AdminBookingServiceError>).status).toBe(409);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error.type).toBe('conflict');
|
||||
expect(transactionMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -194,18 +190,14 @@ test('rejects when slot is not available in target court', async () => {
|
||||
}) as never
|
||||
);
|
||||
|
||||
let caught: unknown;
|
||||
try {
|
||||
await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'court-2',
|
||||
startTime: '14:00',
|
||||
});
|
||||
} catch (error) {
|
||||
caught = error;
|
||||
}
|
||||
const result = await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'court-2',
|
||||
startTime: '14:00',
|
||||
});
|
||||
|
||||
expect(caught).toBeInstanceOf(AdminBookingServiceError);
|
||||
expect((caught as InstanceType<typeof AdminBookingServiceError>).status).toBe(409);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error.type).toBe('conflict');
|
||||
});
|
||||
|
||||
test('rejects when target court has a different sport', async () => {
|
||||
@@ -216,18 +208,14 @@ test('rejects when target court has a different sport', async () => {
|
||||
}) as never
|
||||
);
|
||||
|
||||
let caught: unknown;
|
||||
try {
|
||||
await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'court-2',
|
||||
startTime: '14:00',
|
||||
});
|
||||
} catch (error) {
|
||||
caught = error;
|
||||
}
|
||||
const result = await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'court-2',
|
||||
startTime: '14:00',
|
||||
});
|
||||
|
||||
expect(caught).toBeInstanceOf(AdminBookingServiceError);
|
||||
expect((caught as InstanceType<typeof AdminBookingServiceError>).status).toBe(409);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error.type).toBe('conflict');
|
||||
expect(transactionMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -239,18 +227,14 @@ test('rejects when target court is under maintenance', async () => {
|
||||
}) as never
|
||||
);
|
||||
|
||||
let caught: unknown;
|
||||
try {
|
||||
await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'court-2',
|
||||
startTime: '14:00',
|
||||
});
|
||||
} catch (error) {
|
||||
caught = error;
|
||||
}
|
||||
const result = await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'court-2',
|
||||
startTime: '14:00',
|
||||
});
|
||||
|
||||
expect(caught).toBeInstanceOf(AdminBookingServiceError);
|
||||
expect((caught as InstanceType<typeof AdminBookingServiceError>).status).toBe(409);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error.type).toBe('conflict');
|
||||
});
|
||||
|
||||
test('rejects when there is an overlapping booking', async () => {
|
||||
@@ -266,33 +250,25 @@ test('rejects when there is an overlapping booking', async () => {
|
||||
}) as never
|
||||
);
|
||||
|
||||
let caught: unknown;
|
||||
try {
|
||||
await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'court-2',
|
||||
startTime: '14:00',
|
||||
});
|
||||
} catch (error) {
|
||||
caught = error;
|
||||
}
|
||||
const result = await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'court-2',
|
||||
startTime: '14:00',
|
||||
});
|
||||
|
||||
expect(caught).toBeInstanceOf(AdminBookingServiceError);
|
||||
expect((caught as InstanceType<typeof AdminBookingServiceError>).status).toBe(409);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error.type).toBe('conflict');
|
||||
expect(transactionMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('rejects when neither courtId nor startTime changes', async () => {
|
||||
prismaMock.courtBooking.findFirst.mockResolvedValue(makeBooking() as never);
|
||||
|
||||
let caught: unknown;
|
||||
try {
|
||||
await rescheduleAdminBooking('user-1', 'booking-1', {});
|
||||
} catch (error) {
|
||||
caught = error;
|
||||
}
|
||||
const result = await rescheduleAdminBooking('user-1', 'booking-1', {});
|
||||
|
||||
expect(caught).toBeInstanceOf(AdminBookingServiceError);
|
||||
expect((caught as InstanceType<typeof AdminBookingServiceError>).status).toBe(400);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error.type).toBe('validation');
|
||||
expect(transactionMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -301,17 +277,13 @@ test('rejects when target court does not belong to the same complex', async () =
|
||||
// Court belongs to a different complex
|
||||
prismaMock.court.findFirst.mockResolvedValue(null as never);
|
||||
|
||||
let caught: unknown;
|
||||
try {
|
||||
await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'other-complex-court',
|
||||
startTime: '14:00',
|
||||
});
|
||||
} catch (error) {
|
||||
caught = error;
|
||||
}
|
||||
const result = await rescheduleAdminBooking('user-1', 'booking-1', {
|
||||
courtId: 'other-complex-court',
|
||||
startTime: '14:00',
|
||||
});
|
||||
|
||||
expect(caught).toBeInstanceOf(AdminBookingServiceError);
|
||||
expect((caught as InstanceType<typeof AdminBookingServiceError>).status).toBe(404);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error.type).toBe('not_found');
|
||||
expect(transactionMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user