Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static uk.gov.justice.services.messaging.JsonObjects.createArrayBuilder;
import static uk.gov.justice.services.messaging.JsonObjects.createReader;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -606,6 +607,17 @@ private static LocalDate lastWorkingDayBeforeToday() {
return day;
}

// most recent Saturday strictly before today - with the following Sunday it forms a pure-weekend
// span that is always past, ordered, and within 6 months (endDate is at latest today, when today
// is Sunday), so only the no-sitting-day rule can reject it
private static LocalDate mostRecentSaturday() {
LocalDate day = LocalDate.now().minusDays(1);
while (day.getDayOfWeek() != java.time.DayOfWeek.SATURDAY) {
day = day.minusDays(1);
}
return day;
}

private static final UUID MOVE_COURT_ROOM_ID = randomUUID();

// startTime is an absolute UTC instant (e.g. 2026-07-02T10:00:00.000Z); the request carries no
Expand Down Expand Up @@ -674,6 +686,26 @@ public void shouldRejectMoveWhenEndDateBeforeStartDate() {
verify(sender, never()).send(any());
}

@Test
public void shouldRejectMoveWhenRangeContainsNoSittingDay() {
// Saturday..Sunday span: passes validateMoveDates (past, ordered, within 6 months) but
// expands to zero sitting days - courts do not sit at weekends.
final LocalDate saturday = mostRecentSaturday();
stubMovePayload(randomUUID(), randomUUID(), saturday, "10:00");
given(payload.containsKey("endTime")).willReturn(true);
given(payload.isNull("endTime")).willReturn(false);
given(payload.getString("endTime")).willReturn(saturday.plusDays(1) + "T10:00:00.000Z");

final MoveHearingToPastDateException thrown = assertThrows(MoveHearingToPastDateException.class,
() -> listingCommandApi.handleMoveHearingToPastDate(envelope));

assertThat(thrown.getHttpStatus(), is(422));
assertThat(thrown.getErrorCode(), is("INVALID_DATE_RANGE"));
// distinguishes the no-sitting-day INVALID_DATE_RANGE from the end-before-start one
assertThat(thrown.getResponseBody().getString("message"), containsString("sitting"));
verify(sender, never()).send(any());
}

@Test
public void shouldMoveMagistratesHearingToPastDateEnrichWithSlotDetailsAndSend() {
final UUID hearingId = randomUUID();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,16 @@ void shouldRejectMoveWith400WhenCourtRoomIdMissing() {
assertThat(response.getStatus(), is(400));
}

@Test
void shouldRejectMoveWith400WhenStartTimeMissing() {
final HearingsData hearingsData = hearingsDataWithAllocationDataAndJudiciary(MAGISTRATES_JURISDICTION);
final MoveHearingToPastDateSteps moveSteps = new MoveHearingToPastDateSteps(hearingsData);

final Response response = moveSteps.whenHearingIsMovedWithMissingStartTime();

assertThat(response.getStatus(), is(400));
}

@Test
void shouldMoveCrownHearingToPastDateListingSideOnlyWithoutCallingCourtScheduler() {
final MoveHearingToPastDateSteps moveSteps = givenAListedHearing(CROWN_JURISDICTION);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ public Response whenHearingIsMovedWithMissingCourtRoom(final LocalDate date) {
return postMove(hearingId, payload);
}

public Response whenHearingIsMovedWithMissingStartTime() {
// startTime omitted (schema-mandatory); both ids present so the 400 is unambiguously the
// missing startTime. No date parameter - the payload carries no instant at all.
final String payload = "{\"courtCentreId\":\"" + courtCentreId + "\",\"courtRoomId\":\"" + courtRoomId + "\"}";
return postMove(hearingId, payload);
}

/** A multi-day move over [startTime, endTime], scoped to a specific room. */
public Response whenHearingIsMovedToPastDateRange(final LocalDate startDate, final LocalDate endDate, final String courtRoomId) {
final String payload = "{\"courtCentreId\":\"" + courtCentreId
Expand Down
Loading