Implement GET /events/{token} backend with timezone support
Domain: add timezone field to Event and CreateEventCommand. Ports: new GetEventUseCase inbound port. Service: implement getByEventToken, validate IANA timezone on create. Controller: map to GetEventResponse, compute expired flag via Clock. Persistence: timezone column in JPA entity and mapping. Tests: integration tests use DTOs + ObjectMapper instead of inline JSON, GET tests seed DB directly via JpaRepository for isolation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,22 @@
|
||||
package de.fete.adapter.in.web;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.fete.TestcontainersConfig;
|
||||
import de.fete.adapter.in.web.model.CreateEventRequest;
|
||||
import de.fete.adapter.in.web.model.CreateEventResponse;
|
||||
import de.fete.adapter.out.persistence.EventJpaEntity;
|
||||
import de.fete.adapter.out.persistence.EventJpaRepository;
|
||||
import java.time.LocalDate;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
@@ -23,63 +33,89 @@ class EventControllerIntegrationTest {
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
private EventJpaRepository jpaRepository;
|
||||
|
||||
// --- Create Event tests ---
|
||||
|
||||
@Test
|
||||
void createEventWithValidBody() throws Exception {
|
||||
String body =
|
||||
"""
|
||||
{
|
||||
"title": "Birthday Party",
|
||||
"description": "Come celebrate!",
|
||||
"dateTime": "2026-06-15T20:00:00+02:00",
|
||||
"location": "Berlin",
|
||||
"expiryDate": "%s"
|
||||
}
|
||||
""".formatted(LocalDate.now().plusDays(30));
|
||||
var request = new CreateEventRequest()
|
||||
.title("Birthday Party")
|
||||
.description("Come celebrate!")
|
||||
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
|
||||
.timezone("Europe/Berlin")
|
||||
.location("Berlin")
|
||||
.expiryDate(LocalDate.now().plusDays(30));
|
||||
|
||||
mockMvc.perform(post("/api/events")
|
||||
var result = mockMvc.perform(post("/api/events")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$.eventToken").isNotEmpty())
|
||||
.andExpect(jsonPath("$.organizerToken").isNotEmpty())
|
||||
.andExpect(jsonPath("$.title").value("Birthday Party"))
|
||||
.andExpect(jsonPath("$.timezone").value("Europe/Berlin"))
|
||||
.andExpect(jsonPath("$.dateTime").isNotEmpty())
|
||||
.andExpect(jsonPath("$.expiryDate").isNotEmpty());
|
||||
.andExpect(jsonPath("$.expiryDate").isNotEmpty())
|
||||
.andReturn();
|
||||
|
||||
var response = objectMapper.readValue(
|
||||
result.getResponse().getContentAsString(), CreateEventResponse.class);
|
||||
|
||||
EventJpaEntity persisted = jpaRepository
|
||||
.findByEventToken(response.getEventToken()).orElseThrow();
|
||||
assertThat(persisted.getTitle()).isEqualTo("Birthday Party");
|
||||
assertThat(persisted.getDescription()).isEqualTo("Come celebrate!");
|
||||
assertThat(persisted.getTimezone()).isEqualTo("Europe/Berlin");
|
||||
assertThat(persisted.getLocation()).isEqualTo("Berlin");
|
||||
assertThat(persisted.getExpiryDate()).isEqualTo(request.getExpiryDate());
|
||||
assertThat(persisted.getDateTime().toInstant())
|
||||
.isEqualTo(request.getDateTime().toInstant());
|
||||
assertThat(persisted.getOrganizerToken()).isNotNull();
|
||||
assertThat(persisted.getCreatedAt()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createEventWithOptionalFieldsNull() throws Exception {
|
||||
String body =
|
||||
"""
|
||||
{
|
||||
"title": "Minimal Event",
|
||||
"dateTime": "2026-06-15T20:00:00+02:00",
|
||||
"expiryDate": "%s"
|
||||
}
|
||||
""".formatted(LocalDate.now().plusDays(30));
|
||||
var request = new CreateEventRequest()
|
||||
.title("Minimal Event")
|
||||
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
|
||||
.timezone("UTC")
|
||||
.expiryDate(LocalDate.now().plusDays(30));
|
||||
|
||||
mockMvc.perform(post("/api/events")
|
||||
var result = mockMvc.perform(post("/api/events")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$.eventToken").isNotEmpty())
|
||||
.andExpect(jsonPath("$.organizerToken").isNotEmpty())
|
||||
.andExpect(jsonPath("$.title").value("Minimal Event"));
|
||||
.andExpect(jsonPath("$.title").value("Minimal Event"))
|
||||
.andReturn();
|
||||
|
||||
var response = objectMapper.readValue(
|
||||
result.getResponse().getContentAsString(), CreateEventResponse.class);
|
||||
|
||||
EventJpaEntity persisted = jpaRepository
|
||||
.findByEventToken(response.getEventToken()).orElseThrow();
|
||||
assertThat(persisted.getTitle()).isEqualTo("Minimal Event");
|
||||
assertThat(persisted.getDescription()).isNull();
|
||||
assertThat(persisted.getLocation()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createEventMissingTitleReturns400() throws Exception {
|
||||
String body =
|
||||
"""
|
||||
{
|
||||
"dateTime": "2026-06-15T20:00:00+02:00",
|
||||
"expiryDate": "%s"
|
||||
}
|
||||
""".formatted(LocalDate.now().plusDays(30));
|
||||
var request = new CreateEventRequest()
|
||||
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
|
||||
.timezone("Europe/Berlin")
|
||||
.expiryDate(LocalDate.now().plusDays(30));
|
||||
|
||||
mockMvc.perform(post("/api/events")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentTypeCompatibleWith("application/problem+json"))
|
||||
.andExpect(jsonPath("$.title").value("Validation Failed"))
|
||||
@@ -88,17 +124,14 @@ class EventControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
void createEventMissingDateTimeReturns400() throws Exception {
|
||||
String body =
|
||||
"""
|
||||
{
|
||||
"title": "No Date",
|
||||
"expiryDate": "%s"
|
||||
}
|
||||
""".formatted(LocalDate.now().plusDays(30));
|
||||
var request = new CreateEventRequest()
|
||||
.title("No Date")
|
||||
.timezone("Europe/Berlin")
|
||||
.expiryDate(LocalDate.now().plusDays(30));
|
||||
|
||||
mockMvc.perform(post("/api/events")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentTypeCompatibleWith("application/problem+json"))
|
||||
.andExpect(jsonPath("$.fieldErrors").isArray());
|
||||
@@ -106,17 +139,14 @@ class EventControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
void createEventMissingExpiryDateReturns400() throws Exception {
|
||||
String body =
|
||||
"""
|
||||
{
|
||||
"title": "No Expiry",
|
||||
"dateTime": "2026-06-15T20:00:00+02:00"
|
||||
}
|
||||
""";
|
||||
var request = new CreateEventRequest()
|
||||
.title("No Expiry")
|
||||
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
|
||||
.timezone("Europe/Berlin");
|
||||
|
||||
mockMvc.perform(post("/api/events")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentTypeCompatibleWith("application/problem+json"))
|
||||
.andExpect(jsonPath("$.fieldErrors").isArray());
|
||||
@@ -124,18 +154,15 @@ class EventControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
void createEventExpiryDateInPastReturns400() throws Exception {
|
||||
String body =
|
||||
"""
|
||||
{
|
||||
"title": "Past Expiry",
|
||||
"dateTime": "2026-06-15T20:00:00+02:00",
|
||||
"expiryDate": "2025-01-01"
|
||||
}
|
||||
""";
|
||||
var request = new CreateEventRequest()
|
||||
.title("Past Expiry")
|
||||
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
|
||||
.timezone("Europe/Berlin")
|
||||
.expiryDate(LocalDate.of(2025, 1, 1));
|
||||
|
||||
mockMvc.perform(post("/api/events")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentTypeCompatibleWith("application/problem+json"))
|
||||
.andExpect(jsonPath("$.type").value("urn:problem-type:expiry-date-in-past"));
|
||||
@@ -143,18 +170,15 @@ class EventControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
void createEventExpiryDateTodayReturns400() throws Exception {
|
||||
String body =
|
||||
"""
|
||||
{
|
||||
"title": "Today Expiry",
|
||||
"dateTime": "2026-06-15T20:00:00+02:00",
|
||||
"expiryDate": "%s"
|
||||
}
|
||||
""".formatted(LocalDate.now());
|
||||
var request = new CreateEventRequest()
|
||||
.title("Today Expiry")
|
||||
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
|
||||
.timezone("Europe/Berlin")
|
||||
.expiryDate(LocalDate.now());
|
||||
|
||||
mockMvc.perform(post("/api/events")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentTypeCompatibleWith("application/problem+json"))
|
||||
.andExpect(jsonPath("$.type").value("urn:problem-type:expiry-date-in-past"));
|
||||
@@ -162,19 +186,101 @@ class EventControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
void errorResponseContentTypeIsProblemJson() throws Exception {
|
||||
String body =
|
||||
"""
|
||||
{
|
||||
"title": "",
|
||||
"dateTime": "2026-06-15T20:00:00+02:00",
|
||||
"expiryDate": "%s"
|
||||
}
|
||||
""".formatted(LocalDate.now().plusDays(30));
|
||||
var request = new CreateEventRequest()
|
||||
.title("")
|
||||
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
|
||||
.timezone("Europe/Berlin")
|
||||
.expiryDate(LocalDate.now().plusDays(30));
|
||||
|
||||
mockMvc.perform(post("/api/events")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentTypeCompatibleWith("application/problem+json"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createEventWithInvalidTimezoneReturns400() throws Exception {
|
||||
var request = new CreateEventRequest()
|
||||
.title("Bad TZ")
|
||||
.dateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)))
|
||||
.timezone("Not/A/Zone")
|
||||
.expiryDate(LocalDate.now().plusDays(30));
|
||||
|
||||
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:invalid-timezone"));
|
||||
}
|
||||
|
||||
// --- GET /events/{token} tests ---
|
||||
|
||||
@Test
|
||||
void getEventReturnsFullResponse() throws Exception {
|
||||
EventJpaEntity entity = seedEvent(
|
||||
"Summer BBQ", "Bring drinks!", "Europe/Berlin",
|
||||
"Central Park", LocalDate.now().plusDays(30));
|
||||
|
||||
mockMvc.perform(get("/api/events/" + entity.getEventToken()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.eventToken").value(entity.getEventToken().toString()))
|
||||
.andExpect(jsonPath("$.title").value("Summer BBQ"))
|
||||
.andExpect(jsonPath("$.description").value("Bring drinks!"))
|
||||
.andExpect(jsonPath("$.timezone").value("Europe/Berlin"))
|
||||
.andExpect(jsonPath("$.location").value("Central Park"))
|
||||
.andExpect(jsonPath("$.attendeeCount").value(0))
|
||||
.andExpect(jsonPath("$.expired").value(false))
|
||||
.andExpect(jsonPath("$.dateTime").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getEventWithOptionalFieldsAbsent() throws Exception {
|
||||
EventJpaEntity entity = seedEvent(
|
||||
"Minimal", null, "UTC", null, LocalDate.now().plusDays(30));
|
||||
|
||||
mockMvc.perform(get("/api/events/" + entity.getEventToken()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.title").value("Minimal"))
|
||||
.andExpect(jsonPath("$.description").doesNotExist())
|
||||
.andExpect(jsonPath("$.location").doesNotExist())
|
||||
.andExpect(jsonPath("$.attendeeCount").value(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getEventNotFoundReturns404() throws Exception {
|
||||
mockMvc.perform(get("/api/events/" + UUID.randomUUID()))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(content().contentTypeCompatibleWith("application/problem+json"))
|
||||
.andExpect(jsonPath("$.type").value("urn:problem-type:event-not-found"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getExpiredEventReturnsExpiredTrue() throws Exception {
|
||||
EventJpaEntity entity = seedEvent(
|
||||
"Past Event", "It happened", "Europe/Berlin",
|
||||
"Old Venue", LocalDate.now().minusDays(1));
|
||||
|
||||
mockMvc.perform(get("/api/events/" + entity.getEventToken()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.title").value("Past Event"))
|
||||
.andExpect(jsonPath("$.expired").value(true));
|
||||
}
|
||||
|
||||
private EventJpaEntity seedEvent(
|
||||
String title, String description, String timezone,
|
||||
String location, LocalDate expiryDate) {
|
||||
var entity = new EventJpaEntity();
|
||||
entity.setEventToken(UUID.randomUUID());
|
||||
entity.setOrganizerToken(UUID.randomUUID());
|
||||
entity.setTitle(title);
|
||||
entity.setDescription(description);
|
||||
entity.setDateTime(OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)));
|
||||
entity.setTimezone(timezone);
|
||||
entity.setLocation(location);
|
||||
entity.setExpiryDate(expiryDate);
|
||||
entity.setCreatedAt(OffsetDateTime.now());
|
||||
return jpaRepository.save(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import de.fete.domain.model.Event;
|
||||
import de.fete.domain.port.out.EventRepository;
|
||||
import java.time.LocalDate;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
@@ -65,6 +66,7 @@ class EventPersistenceAdapterTest {
|
||||
event.setTitle("Full Event");
|
||||
event.setDescription("A detailed description");
|
||||
event.setDateTime(dateTime);
|
||||
event.setTimezone(ZoneId.of("Europe/Berlin"));
|
||||
event.setLocation("Berlin, Germany");
|
||||
event.setExpiryDate(expiryDate);
|
||||
event.setCreatedAt(createdAt);
|
||||
@@ -77,6 +79,7 @@ class EventPersistenceAdapterTest {
|
||||
assertThat(found.getTitle()).isEqualTo("Full Event");
|
||||
assertThat(found.getDescription()).isEqualTo("A detailed description");
|
||||
assertThat(found.getDateTime().toInstant()).isEqualTo(dateTime.toInstant());
|
||||
assertThat(found.getTimezone()).isEqualTo(ZoneId.of("Europe/Berlin"));
|
||||
assertThat(found.getLocation()).isEqualTo("Berlin, Germany");
|
||||
assertThat(found.getExpiryDate()).isEqualTo(expiryDate);
|
||||
assertThat(found.getCreatedAt().toInstant()).isEqualTo(createdAt.toInstant());
|
||||
@@ -89,6 +92,7 @@ class EventPersistenceAdapterTest {
|
||||
event.setTitle("Test Event");
|
||||
event.setDescription("Test description");
|
||||
event.setDateTime(OffsetDateTime.now().plusDays(7));
|
||||
event.setTimezone(ZoneId.of("Europe/Berlin"));
|
||||
event.setLocation("Somewhere");
|
||||
event.setExpiryDate(LocalDate.now().plusDays(30));
|
||||
event.setCreatedAt(OffsetDateTime.now());
|
||||
|
||||
@@ -16,6 +16,8 @@ import java.time.LocalDate;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -50,6 +52,7 @@ class EventServiceTest {
|
||||
"Birthday Party",
|
||||
"Come celebrate!",
|
||||
OffsetDateTime.of(2026, 6, 15, 20, 0, 0, 0, ZoneOffset.ofHours(2)),
|
||||
ZoneId.of("Europe/Berlin"),
|
||||
"Berlin",
|
||||
LocalDate.of(2026, 7, 15)
|
||||
);
|
||||
@@ -58,28 +61,13 @@ class EventServiceTest {
|
||||
|
||||
assertThat(result.getTitle()).isEqualTo("Birthday Party");
|
||||
assertThat(result.getDescription()).isEqualTo("Come celebrate!");
|
||||
assertThat(result.getTimezone()).isEqualTo(ZoneId.of("Europe/Berlin"));
|
||||
assertThat(result.getLocation()).isEqualTo("Berlin");
|
||||
assertThat(result.getEventToken()).isNotNull();
|
||||
assertThat(result.getOrganizerToken()).isNotNull();
|
||||
assertThat(result.getCreatedAt()).isEqualTo(OffsetDateTime.now(FIXED_CLOCK));
|
||||
}
|
||||
|
||||
@Test
|
||||
void eventTokenAndOrganizerTokenAreDifferent() {
|
||||
when(eventRepository.save(any(Event.class)))
|
||||
.thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
var command = new CreateEventCommand(
|
||||
"Test", null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), null,
|
||||
LocalDate.now(FIXED_CLOCK).plusDays(30)
|
||||
);
|
||||
|
||||
Event result = eventService.createEvent(command);
|
||||
|
||||
assertThat(result.getEventToken()).isNotEqualTo(result.getOrganizerToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
void repositorySaveCalledExactlyOnce() {
|
||||
when(eventRepository.save(any(Event.class)))
|
||||
@@ -87,7 +75,7 @@ class EventServiceTest {
|
||||
|
||||
var command = new CreateEventCommand(
|
||||
"Test", null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), ZONE, null,
|
||||
LocalDate.now(FIXED_CLOCK).plusDays(30)
|
||||
);
|
||||
|
||||
@@ -102,7 +90,7 @@ class EventServiceTest {
|
||||
void expiryDateTodayThrowsException() {
|
||||
var command = new CreateEventCommand(
|
||||
"Test", null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), ZONE, null,
|
||||
LocalDate.now(FIXED_CLOCK)
|
||||
);
|
||||
|
||||
@@ -114,7 +102,7 @@ class EventServiceTest {
|
||||
void expiryDateInPastThrowsException() {
|
||||
var command = new CreateEventCommand(
|
||||
"Test", null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), ZONE, null,
|
||||
LocalDate.now(FIXED_CLOCK).minusDays(5)
|
||||
);
|
||||
|
||||
@@ -129,7 +117,7 @@ class EventServiceTest {
|
||||
|
||||
var command = new CreateEventCommand(
|
||||
"Test", null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1), ZONE, null,
|
||||
LocalDate.now(FIXED_CLOCK).plusDays(1)
|
||||
);
|
||||
|
||||
@@ -137,4 +125,51 @@ class EventServiceTest {
|
||||
|
||||
assertThat(result.getExpiryDate()).isEqualTo(LocalDate.of(2026, 3, 6));
|
||||
}
|
||||
|
||||
// --- GetEventUseCase tests (T004) ---
|
||||
|
||||
@Test
|
||||
void getByEventTokenReturnsEvent() {
|
||||
UUID token = UUID.randomUUID();
|
||||
var event = new Event();
|
||||
event.setEventToken(token);
|
||||
event.setTitle("Found Event");
|
||||
when(eventRepository.findByEventToken(token))
|
||||
.thenReturn(Optional.of(event));
|
||||
|
||||
Optional<Event> result = eventService.getByEventToken(token);
|
||||
|
||||
assertThat(result).isPresent();
|
||||
assertThat(result.get().getTitle()).isEqualTo("Found Event");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByEventTokenReturnsEmptyForUnknownToken() {
|
||||
UUID token = UUID.randomUUID();
|
||||
when(eventRepository.findByEventToken(token))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
Optional<Event> result = eventService.getByEventToken(token);
|
||||
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
// --- Timezone validation tests (T006) ---
|
||||
|
||||
@Test
|
||||
void createEventWithValidTimezoneSucceeds() {
|
||||
when(eventRepository.save(any(Event.class)))
|
||||
.thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
var command = new CreateEventCommand(
|
||||
"Test", null,
|
||||
OffsetDateTime.now(FIXED_CLOCK).plusDays(1),
|
||||
ZoneId.of("America/New_York"), null,
|
||||
LocalDate.now(FIXED_CLOCK).plusDays(30)
|
||||
);
|
||||
|
||||
Event result = eventService.createEvent(command);
|
||||
|
||||
assertThat(result.getTimezone()).isEqualTo(ZoneId.of("America/New_York"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user