Validate expiryDate is strictly after eventDate and harden rejection tests
All checks were successful
CI / backend-test (push) Successful in 59s
CI / frontend-test (push) Successful in 22s
CI / frontend-e2e (push) Successful in 56s
CI / build-and-publish (push) Has been skipped

Adds ExpiryDateBeforeEventException (400) when expiryDate <= eventDate,
asserts DB row count unchanged after every rejection in integration tests,
and replaces all hardcoded dates in EventServiceTest with TODAY-relative
expressions derived from the fixed Clock.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 13:22:10 +01:00
parent 4d6df8d16b
commit 90bfd12bf3
5 changed files with 171 additions and 23 deletions

View File

@@ -2,6 +2,7 @@ package de.fete.adapter.in.web;
import de.fete.application.service.EventExpiredException; import de.fete.application.service.EventExpiredException;
import de.fete.application.service.EventNotFoundException; import de.fete.application.service.EventNotFoundException;
import de.fete.application.service.ExpiryDateBeforeEventException;
import de.fete.application.service.ExpiryDateInPastException; import de.fete.application.service.ExpiryDateInPastException;
import de.fete.application.service.InvalidTimezoneException; import de.fete.application.service.InvalidTimezoneException;
import java.net.URI; import java.net.URI;
@@ -47,6 +48,19 @@ public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
return handleExceptionInternal(ex, problemDetail, headers, status, request); return handleExceptionInternal(ex, problemDetail, headers, status, request);
} }
/** Handles expiry date before event date. */
@ExceptionHandler(ExpiryDateBeforeEventException.class)
public ResponseEntity<ProblemDetail> handleExpiryDateBeforeEvent(
ExpiryDateBeforeEventException ex) {
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(
HttpStatus.BAD_REQUEST, ex.getMessage());
problemDetail.setTitle("Invalid Expiry Date");
problemDetail.setType(URI.create("urn:problem-type:expiry-date-before-event"));
return ResponseEntity.badRequest()
.contentType(MediaType.APPLICATION_PROBLEM_JSON)
.body(problemDetail);
}
/** Handles expiry date validation failures. */ /** Handles expiry date validation failures. */
@ExceptionHandler(ExpiryDateInPastException.class) @ExceptionHandler(ExpiryDateInPastException.class)
public ResponseEntity<ProblemDetail> handleExpiryDateInPast( public ResponseEntity<ProblemDetail> handleExpiryDateInPast(

View File

@@ -32,6 +32,10 @@ public class EventService implements CreateEventUseCase, GetEventUseCase {
throw new ExpiryDateInPastException(command.expiryDate()); throw new ExpiryDateInPastException(command.expiryDate());
} }
if (!command.expiryDate().isAfter(command.dateTime().toLocalDate())) {
throw new ExpiryDateBeforeEventException(command.expiryDate(), command.dateTime());
}
var event = new Event(); var event = new Event();
event.setEventToken(EventToken.generate()); event.setEventToken(EventToken.generate());
event.setOrganizerToken(OrganizerToken.generate()); event.setOrganizerToken(OrganizerToken.generate());

View File

@@ -0,0 +1,13 @@
package de.fete.application.service;
import java.time.LocalDate;
import java.time.OffsetDateTime;
/** Thrown when an event's expiry date is not after the event date. */
public class ExpiryDateBeforeEventException extends RuntimeException {
/** Creates a new exception for the given dates. */
public ExpiryDateBeforeEventException(LocalDate expiryDate, OffsetDateTime dateTime) {
super("Expiry date " + expiryDate + " must be after event date " + dateTime.toLocalDate());
}
}

View File

@@ -56,7 +56,7 @@ class EventControllerIntegrationTest {
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2))) .dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
.timezone("Europe/Berlin") .timezone("Europe/Berlin")
.location("Berlin") .location("Berlin")
.expiryDate(LocalDate.now().plusDays(30)); .expiryDate(LocalDate.of(2026, 6, 16));
var result = mockMvc.perform(post("/api/events") var result = mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
@@ -92,7 +92,7 @@ class EventControllerIntegrationTest {
.title("Minimal Event") .title("Minimal Event")
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2))) .dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
.timezone("UTC") .timezone("UTC")
.expiryDate(LocalDate.now().plusDays(30)); .expiryDate(LocalDate.of(2026, 6, 16));
var result = mockMvc.perform(post("/api/events") var result = mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
@@ -115,10 +115,12 @@ class EventControllerIntegrationTest {
@Test @Test
void createEventMissingTitleReturns400() throws Exception { void createEventMissingTitleReturns400() throws Exception {
long countBefore = jpaRepository.count();
var request = new CreateEventRequest() var request = new CreateEventRequest()
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2))) .dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
.timezone("Europe/Berlin") .timezone("Europe/Berlin")
.expiryDate(LocalDate.now().plusDays(30)); .expiryDate(LocalDate.of(2026, 6, 16));
mockMvc.perform(post("/api/events") mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
@@ -127,14 +129,18 @@ class EventControllerIntegrationTest {
.andExpect(content().contentTypeCompatibleWith("application/problem+json")) .andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.title").value("Validation Failed")) .andExpect(jsonPath("$.title").value("Validation Failed"))
.andExpect(jsonPath("$.fieldErrors").isArray()); .andExpect(jsonPath("$.fieldErrors").isArray());
assertThat(jpaRepository.count()).isEqualTo(countBefore);
} }
@Test @Test
void createEventMissingDateTimeReturns400() throws Exception { void createEventMissingDateTimeReturns400() throws Exception {
long countBefore = jpaRepository.count();
var request = new CreateEventRequest() var request = new CreateEventRequest()
.title("No Date") .title("No Date")
.timezone("Europe/Berlin") .timezone("Europe/Berlin")
.expiryDate(LocalDate.now().plusDays(30)); .expiryDate(LocalDate.of(2026, 6, 16));
mockMvc.perform(post("/api/events") mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
@@ -142,10 +148,14 @@ class EventControllerIntegrationTest {
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith("application/problem+json")) .andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.fieldErrors").isArray()); .andExpect(jsonPath("$.fieldErrors").isArray());
assertThat(jpaRepository.count()).isEqualTo(countBefore);
} }
@Test @Test
void createEventMissingExpiryDateReturns400() throws Exception { void createEventMissingExpiryDateReturns400() throws Exception {
long countBefore = jpaRepository.count();
var request = new CreateEventRequest() var request = new CreateEventRequest()
.title("No Expiry") .title("No Expiry")
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2))) .dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
@@ -157,10 +167,14 @@ class EventControllerIntegrationTest {
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith("application/problem+json")) .andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.fieldErrors").isArray()); .andExpect(jsonPath("$.fieldErrors").isArray());
assertThat(jpaRepository.count()).isEqualTo(countBefore);
} }
@Test @Test
void createEventExpiryDateInPastReturns400() throws Exception { void createEventExpiryDateInPastReturns400() throws Exception {
long countBefore = jpaRepository.count();
var request = new CreateEventRequest() var request = new CreateEventRequest()
.title("Past Expiry") .title("Past Expiry")
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2))) .dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
@@ -173,10 +187,14 @@ class EventControllerIntegrationTest {
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith("application/problem+json")) .andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.type").value("urn:problem-type:expiry-date-in-past")); .andExpect(jsonPath("$.type").value("urn:problem-type:expiry-date-in-past"));
assertThat(jpaRepository.count()).isEqualTo(countBefore);
} }
@Test @Test
void createEventExpiryDateTodayReturns400() throws Exception { void createEventExpiryDateTodayReturns400() throws Exception {
long countBefore = jpaRepository.count();
var request = new CreateEventRequest() var request = new CreateEventRequest()
.title("Today Expiry") .title("Today Expiry")
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2))) .dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
@@ -189,6 +207,48 @@ class EventControllerIntegrationTest {
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith("application/problem+json")) .andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.type").value("urn:problem-type:expiry-date-in-past")); .andExpect(jsonPath("$.type").value("urn:problem-type:expiry-date-in-past"));
assertThat(jpaRepository.count()).isEqualTo(countBefore);
}
@Test
void createEventExpiryDateBeforeEventDateReturns400() throws Exception {
long countBefore = jpaRepository.count();
var request = new CreateEventRequest()
.title("Bad Expiry")
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
.timezone("Europe/Berlin")
.expiryDate(LocalDate.of(2026, 6, 10));
mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.type").value("urn:problem-type:expiry-date-before-event"));
assertThat(jpaRepository.count()).isEqualTo(countBefore);
}
@Test
void createEventExpiryDateSameAsEventDateReturns400() throws Exception {
long countBefore = jpaRepository.count();
var request = new CreateEventRequest()
.title("Same Day Expiry")
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
.timezone("Europe/Berlin")
.expiryDate(LocalDate.of(2026, 6, 15));
mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.type").value("urn:problem-type:expiry-date-before-event"));
assertThat(jpaRepository.count()).isEqualTo(countBefore);
} }
@Test @Test
@@ -197,7 +257,7 @@ class EventControllerIntegrationTest {
.title("") .title("")
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2))) .dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
.timezone("Europe/Berlin") .timezone("Europe/Berlin")
.expiryDate(LocalDate.now().plusDays(30)); .expiryDate(LocalDate.of(2026, 6, 16));
mockMvc.perform(post("/api/events") mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
@@ -208,11 +268,13 @@ class EventControllerIntegrationTest {
@Test @Test
void createEventWithInvalidTimezoneReturns400() throws Exception { void createEventWithInvalidTimezoneReturns400() throws Exception {
long countBefore = jpaRepository.count();
var request = new CreateEventRequest() var request = new CreateEventRequest()
.title("Bad TZ") .title("Bad TZ")
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2))) .dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
.timezone("Not/A/Zone") .timezone("Not/A/Zone")
.expiryDate(LocalDate.now().plusDays(30)); .expiryDate(LocalDate.of(2026, 6, 16));
mockMvc.perform(post("/api/events") mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
@@ -220,6 +282,8 @@ class EventControllerIntegrationTest {
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith("application/problem+json")) .andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.type").value("urn:problem-type:invalid-timezone")); .andExpect(jsonPath("$.type").value("urn:problem-type:invalid-timezone"));
assertThat(jpaRepository.count()).isEqualTo(countBefore);
} }
// --- GET /events/{token} tests --- // --- GET /events/{token} tests ---
@@ -307,6 +371,7 @@ class EventControllerIntegrationTest {
EventJpaEntity event = seedEvent( EventJpaEntity event = seedEvent(
"RSVP Event", null, "Europe/Berlin", "RSVP Event", null, "Europe/Berlin",
null, LocalDate.now().plusDays(30)); null, LocalDate.now().plusDays(30));
long countBefore = rsvpJpaRepository.count();
var request = new CreateRsvpRequest().name(""); var request = new CreateRsvpRequest().name("");
@@ -315,6 +380,8 @@ class EventControllerIntegrationTest {
.content(objectMapper.writeValueAsString(request))) .content(objectMapper.writeValueAsString(request)))
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith("application/problem+json")); .andExpect(content().contentTypeCompatibleWith("application/problem+json"));
assertThat(rsvpJpaRepository.count()).isEqualTo(countBefore);
} }
@Test @Test
@@ -339,6 +406,8 @@ class EventControllerIntegrationTest {
@Test @Test
void createRsvpForUnknownEventReturns404() throws Exception { void createRsvpForUnknownEventReturns404() throws Exception {
long countBefore = rsvpJpaRepository.count();
var request = new CreateRsvpRequest().name("Ghost"); var request = new CreateRsvpRequest().name("Ghost");
mockMvc.perform(post("/api/events/" + UUID.randomUUID() + "/rsvps") mockMvc.perform(post("/api/events/" + UUID.randomUUID() + "/rsvps")
@@ -347,6 +416,8 @@ class EventControllerIntegrationTest {
.andExpect(status().isNotFound()) .andExpect(status().isNotFound())
.andExpect(content().contentTypeCompatibleWith("application/problem+json")) .andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.type").value("urn:problem-type:event-not-found")); .andExpect(jsonPath("$.type").value("urn:problem-type:event-not-found"));
assertThat(rsvpJpaRepository.count()).isEqualTo(countBefore);
} }
@Test @Test
@@ -354,6 +425,7 @@ class EventControllerIntegrationTest {
EventJpaEntity event = seedEvent( EventJpaEntity event = seedEvent(
"Expired Party", null, "Europe/Berlin", "Expired Party", null, "Europe/Berlin",
null, LocalDate.now().minusDays(1)); null, LocalDate.now().minusDays(1));
long countBefore = rsvpJpaRepository.count();
var request = new CreateRsvpRequest().name("Late Guest"); var request = new CreateRsvpRequest().name("Late Guest");
@@ -363,6 +435,8 @@ class EventControllerIntegrationTest {
.andExpect(status().isConflict()) .andExpect(status().isConflict())
.andExpect(content().contentTypeCompatibleWith("application/problem+json")) .andExpect(content().contentTypeCompatibleWith("application/problem+json"))
.andExpect(jsonPath("$.type").value("urn:problem-type:event-expired")); .andExpect(jsonPath("$.type").value("urn:problem-type:event-expired"));
assertThat(rsvpJpaRepository.count()).isEqualTo(countBefore);
} }
private EventJpaEntity seedEvent( private EventJpaEntity seedEvent(

View File

@@ -16,7 +16,6 @@ import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Optional; import java.util.Optional;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -32,6 +31,7 @@ class EventServiceTest {
private static final Instant FIXED_INSTANT = private static final Instant FIXED_INSTANT =
LocalDate.of(2026, 3, 5).atStartOfDay(ZONE).toInstant(); LocalDate.of(2026, 3, 5).atStartOfDay(ZONE).toInstant();
private static final Clock FIXED_CLOCK = Clock.fixed(FIXED_INSTANT, ZONE); private static final Clock FIXED_CLOCK = Clock.fixed(FIXED_INSTANT, ZONE);
private static final LocalDate TODAY = LocalDate.ofInstant(FIXED_INSTANT, ZONE);
@Mock @Mock
private EventRepository eventRepository; private EventRepository eventRepository;
@@ -51,21 +51,21 @@ class EventServiceTest {
var command = new CreateEventCommand( var command = new CreateEventCommand(
"Birthday Party", "Birthday Party",
"Come celebrate!", "Come celebrate!",
OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)), TODAY.plusDays(90).atStartOfDay(ZONE).toOffsetDateTime(),
ZoneId.of("Europe/Berlin"), ZONE,
"Berlin", "Berlin",
LocalDate.of(2026, 7, 15) TODAY.plusDays(120)
); );
Event result = eventService.createEvent(command); Event result = eventService.createEvent(command);
assertThat(result.getTitle()).isEqualTo("Birthday Party"); assertThat(result.getTitle()).isEqualTo("Birthday Party");
assertThat(result.getDescription()).isEqualTo("Come celebrate!"); assertThat(result.getDescription()).isEqualTo("Come celebrate!");
assertThat(result.getTimezone()).isEqualTo(ZoneId.of("Europe/Berlin")); assertThat(result.getTimezone()).isEqualTo(ZONE);
assertThat(result.getLocation()).isEqualTo("Berlin"); assertThat(result.getLocation()).isEqualTo("Berlin");
assertThat(result.getEventToken()).isNotNull(); assertThat(result.getEventToken()).isNotNull();
assertThat(result.getOrganizerToken()).isNotNull(); assertThat(result.getOrganizerToken()).isNotNull();
assertThat(result.getCreatedAt()).isEqualTo(OffsetDateTime.now(FIXED_CLOCK)); assertThat(result.getCreatedAt()).isEqualTo(OffsetDateTime.ofInstant(FIXED_INSTANT, ZONE));
} }
@Test @Test
@@ -75,8 +75,8 @@ class EventServiceTest {
var command = new CreateEventCommand( var command = new CreateEventCommand(
"Test", null, "Test", null,
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), ZONE, null, TODAY.plusDays(10).atStartOfDay(ZONE).toOffsetDateTime(), ZONE, null,
LocalDate.now(FIXED_CLOCK).plusDays(30) TODAY.plusDays(11)
); );
eventService.createEvent(command); eventService.createEvent(command);
@@ -90,8 +90,8 @@ class EventServiceTest {
void expiryDateTodayThrowsException() { void expiryDateTodayThrowsException() {
var command = new CreateEventCommand( var command = new CreateEventCommand(
"Test", null, "Test", null,
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), ZONE, null, TODAY.plusDays(10).atStartOfDay(ZONE).toOffsetDateTime(), ZONE, null,
LocalDate.now(FIXED_CLOCK) TODAY
); );
assertThatThrownBy(() -> eventService.createEvent(command)) assertThatThrownBy(() -> eventService.createEvent(command))
@@ -102,8 +102,8 @@ class EventServiceTest {
void expiryDateInPastThrowsException() { void expiryDateInPastThrowsException() {
var command = new CreateEventCommand( var command = new CreateEventCommand(
"Test", null, "Test", null,
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), ZONE, null, TODAY.plusDays(10).atStartOfDay(ZONE).toOffsetDateTime(), ZONE, null,
LocalDate.now(FIXED_CLOCK).minusDays(5) TODAY.minusDays(5)
); );
assertThatThrownBy(() -> eventService.createEvent(command)) assertThatThrownBy(() -> eventService.createEvent(command))
@@ -117,13 +117,56 @@ class EventServiceTest {
var command = new CreateEventCommand( var command = new CreateEventCommand(
"Test", null, "Test", null,
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), ZONE, null, TODAY.plusDays(1).atStartOfDay(ZONE).toOffsetDateTime(), ZONE, null,
LocalDate.now(FIXED_CLOCK).plusDays(1) TODAY.plusDays(2)
); );
Event result = eventService.createEvent(command); Event result = eventService.createEvent(command);
assertThat(result.getExpiryDate()).isEqualTo(LocalDate.of(2026, 3, 6)); assertThat(result.getExpiryDate()).isEqualTo(TODAY.plusDays(2));
}
@Test
void expiryDateSameAsEventDateThrowsException() {
var command = new CreateEventCommand(
"Test", null,
TODAY.plusDays(10).atStartOfDay(ZONE).toOffsetDateTime(),
ZONE, null,
TODAY.plusDays(10)
);
assertThatThrownBy(() -> eventService.createEvent(command))
.isInstanceOf(ExpiryDateBeforeEventException.class);
}
@Test
void expiryDateBeforeEventDateThrowsException() {
var command = new CreateEventCommand(
"Test", null,
TODAY.plusDays(10).atStartOfDay(ZONE).toOffsetDateTime(),
ZONE, null,
TODAY.plusDays(5)
);
assertThatThrownBy(() -> eventService.createEvent(command))
.isInstanceOf(ExpiryDateBeforeEventException.class);
}
@Test
void expiryDateDayAfterEventDateSucceeds() {
when(eventRepository.save(any(Event.class)))
.thenAnswer(invocation -> invocation.getArgument(0));
var command = new CreateEventCommand(
"Test", null,
TODAY.plusDays(10).atStartOfDay(ZONE).toOffsetDateTime(),
ZONE, null,
TODAY.plusDays(11)
);
Event result = eventService.createEvent(command);
assertThat(result.getExpiryDate()).isEqualTo(TODAY.plusDays(11));
} }
// --- GetEventUseCase tests (T004) --- // --- GetEventUseCase tests (T004) ---
@@ -163,9 +206,9 @@ class EventServiceTest {
var command = new CreateEventCommand( var command = new CreateEventCommand(
"Test", null, "Test", null,
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), TODAY.plusDays(10).atStartOfDay(ZONE).toOffsetDateTime(),
ZoneId.of("America/New_York"), null, ZoneId.of("America/New_York"), null,
LocalDate.now(FIXED_CLOCK).plusDays(30) TODAY.plusDays(11)
); );
Event result = eventService.createEvent(command); Event result = eventService.createEvent(command);